public static async Task <RomFs> Load(IBinaryDataAccessor data) { var header = new RomFsHeader(await data.ReadArrayAsync(0, 0x6B)); var romfs = new RomFs(data, header); await romfs.Initialize(); return(romfs); }
/// <summary> /// Builds a new ROM file system from the given directory /// </summary> /// <param name="directory">Directory from which to load the files</param> /// <param name="fileSystem">File system from which to load the files</param> /// <returns>A newly built ROM file system</returns> public static async Task <RomFs> Build(string directory, IFileSystem fileSystem, ProcessingProgressedToken?progressToken = null) { Stream?stream = null; string?tempFilename = null; try { // A memory stream is faster, but an internal limitation means it's unsuitable for files larger than 2GB // We'll fall back to a file stream if our raw data won't fit within 2GB minus 400 MB (for safety, since there's still metadata, hashes, and other partitions) if (fileSystem.GetDirectoryLength(directory) < (int.MaxValue - (400 * Math.Pow(1024, 2)))) { stream = new MemoryStream(); } else { // Do not use IFileSystem; this is for temporary storage since RAM isn't an option tempFilename = Path.GetTempFileName(); stream = File.Open(tempFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite); } RomFsBuilder.RomFsBuilder.BuildRomFS(directory, fileSystem, stream, progressToken); BinaryFile data; if (stream is FileStream) { // We want the BinaryFile class to own the file so it will dispose of it properly // So let's dispose our copy and let it re-open it however it sees fit // And instead of a BinaryFile, use a FileDeletingBinaryFile to delete the file on dispose stream.Dispose(); stream = null; if (string.IsNullOrEmpty(tempFilename)) { // The developer (probably me) made a mistake throw new Exception("Temporary file not found"); } data = new FileDeletingBinaryFile(tempFilename); } else if (stream is MemoryStream memoryStream) { try { // Faster but maybe more memory-intensive var memoryStreamArray = memoryStream.ToArray(); data = new BinaryFile(memoryStreamArray); } catch (OutOfMemoryException) { // Slower but more reliable data = new BinaryFile(memoryStream); } } else { // The developer (probably me) made a mistake throw new Exception("Unexpected type of stream in RomFs.Build"); } var header = new RomFsHeader(await data.ReadArrayAsync(0, 0x6B)); var romFs = new RomFs(data, header); await romFs.Initialize(); return(romFs); } finally { stream?.Dispose(); } }