From 52c15d4732c9908f6eb00fc7a513e0cb737030b7 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 18 Aug 2020 23:39:13 -0700 Subject: [PATCH] Replace RVX with Depth --- RombaSharp/Features/Build.cs | 4 +- SabreTools.Library/DatFiles/DatFile.cs | 103 +--- SabreTools.Library/DatFiles/DatHeader.cs | 14 +- SabreTools.Library/DatFiles/Missfile.cs | 2 +- SabreTools.Library/FileTypes/BaseArchive.cs | 8 +- SabreTools.Library/FileTypes/Folder.cs | 10 +- SabreTools.Library/FileTypes/GZipArchive.cs | 38 +- SabreTools.Library/FileTypes/LRZipArchive.cs | 9 +- SabreTools.Library/FileTypes/LZ4Archive.cs | 9 +- SabreTools.Library/FileTypes/RarArchive.cs | 550 +++++++++--------- .../FileTypes/SevenZipArchive.cs | 8 +- SabreTools.Library/FileTypes/TapeArchive.cs | 8 +- SabreTools.Library/FileTypes/XZArchive.cs | 39 +- SabreTools.Library/FileTypes/ZPAQArchive.cs | 8 +- SabreTools.Library/FileTypes/ZipArchive.cs | 8 +- SabreTools.Library/FileTypes/ZstdArchive.cs | 8 +- SabreTools.Library/IO/PathExtensions.cs | 25 +- SabreTools.Library/README.1ST | 35 +- SabreTools/Features/BaseFeature.cs | 66 +-- SabreTools/Features/DatFromDir.cs | 2 +- SabreTools/Features/Sort.cs | 42 +- SabreTools/Features/Update.cs | 2 +- SabreTools/Features/Verify.cs | 21 +- 23 files changed, 473 insertions(+), 546 deletions(-) diff --git a/RombaSharp/Features/Build.cs b/RombaSharp/Features/Build.cs index 9bf0b3ad..832df2f6 100644 --- a/RombaSharp/Features/Build.cs +++ b/RombaSharp/Features/Build.cs @@ -62,8 +62,8 @@ structure according to the original DAT master directory tree structure."; // Now scan all of those depots and rebuild datFile.RebuildDepot( onlineDepots, - romroot: false, - rvx: false, + indepth: 4, + outdepth: 4, outDir: outputFolder, outputFormat: (copy ? OutputFormat.TorrentGzipRomba : OutputFormat.TorrentZip), updateDat: false); diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs index 489a13a9..234f3d45 100644 --- a/SabreTools.Library/DatFiles/DatFile.cs +++ b/SabreTools.Library/DatFiles/DatFile.cs @@ -2103,7 +2103,7 @@ namespace SabreTools.Library.DatFiles }); // Now find all folders that are empty, if we are supposed to - if (Header.Romba == null && addBlanks) + if (!Header.Romba && addBlanks) { List empties = DirectoryExtensions.ListEmpty(basePath); Parallel.ForEach(empties, Globals.ParallelOptions, dir => @@ -2177,8 +2177,8 @@ namespace SabreTools.Library.DatFiles bool addDate, bool copyFiles) { - // Special case for if we are in Romba or RVX mode (all names are supposed to be SHA-1 hashes) - if (Header.Romba != null) + // Special case for if we are in Romba mode (all names are supposed to be SHA-1 hashes) + if (Header.Romba) { GZipArchive gzarc = new GZipArchive(item); BaseFile baseFile = gzarc.GetTorrentGZFileInfo(); @@ -2400,8 +2400,8 @@ namespace SabreTools.Library.DatFiles /// Process the DAT and find all matches in input files and folders assuming they're a depot /// /// List of input files/folders to check - /// True to build from 2-deep, false to default to 4-deep - /// True to only go to 2-deep, false to default to 4-deep + /// Positive value representing depth of input depot + /// Positive value representing depth of output depot /// Output directory to use to build to /// True if the date from the DAT should be used if available, false otherwise /// True if input files should be deleted, false otherwise @@ -2411,8 +2411,8 @@ namespace SabreTools.Library.DatFiles /// True if rebuilding was a success, false otherwise public bool RebuildDepot( List inputs, - bool romroot = false, - bool rvx = false, + int indepth = 4, + int outdepth = 4, string outDir = null, bool date = false, bool delete = false, @@ -2521,7 +2521,7 @@ namespace SabreTools.Library.DatFiles Globals.Logger.User($"Checking hash '{hash}'"); // Get the extension path for the hash - string subpath = PathExtensions.GetRombaPath(hash, romroot); + string subpath = PathExtensions.GetRombaPath(hash, indepth); // Find the first depot that includes the hash string foundpath = null; @@ -2553,9 +2553,9 @@ namespace SabreTools.Library.DatFiles // Otherwise, we rebuild that file to all locations that we need to bool usedInternally; if (Items[hash][0].ItemType == ItemType.Disk) - usedInternally = RebuildIndividualFile(new Disk(fileinfo), foundpath, outDir, rvx, date, inverse, outputFormat, updateDat, false /* isZip */); + usedInternally = RebuildIndividualFile(new Disk(fileinfo), foundpath, outDir, outdepth, date, inverse, outputFormat, updateDat, false /* isZip */); else - usedInternally = RebuildIndividualFile(new Rom(fileinfo), foundpath, outDir, rvx, date, inverse, outputFormat, updateDat, false /* isZip */); + usedInternally = RebuildIndividualFile(new Rom(fileinfo), foundpath, outDir, outdepth, date, inverse, outputFormat, updateDat, false /* isZip */); // If we are supposed to delete the depot file, do so if (delete && usedInternally) @@ -2584,7 +2584,7 @@ namespace SabreTools.Library.DatFiles /// /// List of input files/folders to check /// Output directory to use to build to - /// True to only go to 2-deep, false to default to 4-deep + /// Positive value representing depth of output depot /// True to enable external scanning of archives, false otherwise /// True if the date from the DAT should be used if available, false otherwise /// True if input files should be deleted, false otherwise @@ -2596,7 +2596,7 @@ namespace SabreTools.Library.DatFiles public bool RebuildGeneric( List inputs, string outDir = null, - bool rvx = false, + int outdepth = 4, bool quickScan = false, bool date = false, bool delete = false, @@ -2684,7 +2684,7 @@ namespace SabreTools.Library.DatFiles if (File.Exists(input)) { Globals.Logger.User($"Checking file: {input}"); - RebuildGenericHelper(input, outDir, rvx, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); + RebuildGenericHelper(input, outDir, outdepth, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); } // If the input is a directory @@ -2694,7 +2694,7 @@ namespace SabreTools.Library.DatFiles foreach (string file in Directory.EnumerateFiles(input, "*", SearchOption.AllDirectories)) { Globals.Logger.User($"Checking file: {file}"); - RebuildGenericHelper(file, outDir, rvx, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); + RebuildGenericHelper(file, outDir, outdepth, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); } } } @@ -2721,7 +2721,7 @@ namespace SabreTools.Library.DatFiles /// /// Name of the file to process /// Output directory to use to build to - /// True to only go to 2-deep, false to default to 4-deep + /// Positive value representing depth of output depot /// True to enable external scanning of archives, false otherwise /// True if the date from the DAT should be used if available, false otherwise /// True if input files should be deleted, false otherwise @@ -2732,7 +2732,7 @@ namespace SabreTools.Library.DatFiles private void RebuildGenericHelper( string file, string outDir, - bool rvx, + int outdepth, bool quickScan, bool date, bool delete, @@ -2760,7 +2760,7 @@ namespace SabreTools.Library.DatFiles else if (externalFileInfo.Type == FileType.None) externalDatItem = new Rom(externalFileInfo); - usedExternally = RebuildIndividualFile(externalDatItem, file, outDir, rvx, date, inverse, outputFormat, updateDat, null /* isZip */); + usedExternally = RebuildIndividualFile(externalDatItem, file, outDir, outdepth, date, inverse, outputFormat, updateDat, null /* isZip */); // Scan the file internally @@ -2793,7 +2793,7 @@ namespace SabreTools.Library.DatFiles else if (internalFileInfo.Type == FileType.None) internalDatItem = new Rom(internalFileInfo); - usedExternally = RebuildIndividualFile(internalDatItem, file, outDir, rvx, date, inverse, outputFormat, updateDat, null /* isZip */); + usedExternally = RebuildIndividualFile(internalDatItem, file, outDir, outdepth, date, inverse, outputFormat, updateDat, null /* isZip */); } // Otherwise, loop through the entries and try to match else @@ -2801,7 +2801,7 @@ namespace SabreTools.Library.DatFiles foreach (BaseFile entry in entries) { DatItem internalDatItem = DatItem.Create(entry); - usedInternally |= RebuildIndividualFile(internalDatItem, file, outDir, rvx, date, inverse, outputFormat, updateDat, !isTorrentGzip /* isZip */); + usedInternally |= RebuildIndividualFile(internalDatItem, file, outDir, outdepth, date, inverse, outputFormat, updateDat, !isTorrentGzip /* isZip */); } } @@ -2816,7 +2816,7 @@ namespace SabreTools.Library.DatFiles /// Information for the current file to rebuild from /// Name of the file to process /// Output directory to use to build to - /// True to only go to 2-deep, false to default to 4-deep + /// Positive value representing depth of output depot /// True if the date from the DAT should be used if available, false otherwise /// True if the DAT should be used as a filter instead of a template, false otherwise /// Output format that files should be written to @@ -2827,7 +2827,7 @@ namespace SabreTools.Library.DatFiles DatItem datItem, string file, string outDir, - bool rvx, + int outdepth, bool date, bool inverse, OutputFormat outputFormat, @@ -2869,7 +2869,7 @@ namespace SabreTools.Library.DatFiles // Get the proper output path if (outputFormat == OutputFormat.TorrentGzipRomba) - outDir = Path.Combine(outDir, PathExtensions.GetRombaPath(sha1, rvx)); + outDir = Path.Combine(outDir, PathExtensions.GetRombaPath(sha1, outdepth)); else outDir = Path.Combine(outDir, sha1 + ".gz"); @@ -2897,7 +2897,7 @@ namespace SabreTools.Library.DatFiles // Get the proper output path if (outputFormat == OutputFormat.TorrentXZRomba) - outDir = Path.Combine(outDir, PathExtensions.GetRombaPath(sha1, rvx)); + outDir = Path.Combine(outDir, PathExtensions.GetRombaPath(sha1, outdepth)); else outDir = Path.Combine(outDir, sha1 + ".xz"); @@ -2969,13 +2969,8 @@ namespace SabreTools.Library.DatFiles // Get the output archive, if possible Folder outputArchive = Folder.Create(outputFormat); - // Get the romba value - bool? romba = null; - if (outputFormat == OutputFormat.TorrentGzipRomba || outputFormat == OutputFormat.TorrentXZRomba) - romba = rvx; - // Now rebuild to the output file - outputArchive.Write(fileStream, outDir, (Rom)item, date: date, romba: romba); + outputArchive.Write(fileStream, outDir, (Rom)item, date: date, depth: outdepth); } // Close the input stream @@ -3041,14 +3036,9 @@ namespace SabreTools.Library.DatFiles // Get the output archive, if possible Folder outputArchive = Folder.Create(outputFormat); - // Get the romba value - bool? romba = null; - if (outputFormat == OutputFormat.TorrentGzipRomba || outputFormat == OutputFormat.TorrentXZRomba) - romba = rvx; - // Now rebuild to the output file - eitherSuccess |= outputArchive.Write(transformStream, outDir, (Rom)item, date: date, romba: romba); - eitherSuccess |= outputArchive.Write(fileStream, outDir, (Rom)datItem, date: date, romba: romba); + eitherSuccess |= outputArchive.Write(transformStream, outDir, (Rom)item, date: date, depth: outdepth); + eitherSuccess |= outputArchive.Write(fileStream, outDir, (Rom)datItem, date: date, depth: outdepth); // Now add the success of either rebuild rebuilt &= eitherSuccess; @@ -3071,10 +3061,10 @@ namespace SabreTools.Library.DatFiles /// Process the DAT and verify from the depots /// /// List of input directories to compare against - /// True to only go to 2-deep, false to default to 4-deep + /// Positive value representing depot depth, defaults to 4 /// Optional param for output directory /// True if verification was a success, false otherwise - public bool VerifyDepot(List inputs, bool rvx = false, string outDir = null) + public bool VerifyDepot(List inputs, int depth = 4, string outDir = null) { bool success = true; @@ -3110,7 +3100,7 @@ namespace SabreTools.Library.DatFiles Globals.Logger.User($"Checking hash '{hash}'"); // Get the extension path for the hash - string subpath = PathExtensions.GetRombaPath(hash, rvx); + string subpath = PathExtensions.GetRombaPath(hash, depth); // Find the first depot that includes the hash string foundpath = null; @@ -3792,7 +3782,7 @@ namespace SabreTools.Library.DatFiles string post = CreatePrefixPostfix(item, false); // If we're in Romba mode, take care of that instead - if (Header.Romba == true) + if (Header.Romba) { if (item.ItemType == ItemType.Rom) { @@ -3801,7 +3791,7 @@ namespace SabreTools.Library.DatFiles // We can only write out if there's a SHA-1 if (!string.IsNullOrWhiteSpace(romItem.SHA1)) { - name = PathExtensions.GetRombaPath(romItem.SHA1, Header.Romba == false).Replace('\\', '/'); + name = PathExtensions.GetRombaPath(romItem.SHA1, Header.RombaDepth).Replace('\\', '/'); item.Name = $"{pre}{name}{post}"; } } @@ -3812,36 +3802,7 @@ namespace SabreTools.Library.DatFiles // We can only write out if there's a SHA-1 if (!string.IsNullOrWhiteSpace(diskItem.SHA1)) { - name = PathExtensions.GetRombaPath(diskItem.SHA1, Header.Romba == false).Replace('\\', '/'); - item.Name = pre + name + post; - } - } - - return; - } - - // If we're in RVX mode, take care of that instead - if (Header.Romba == false) - { - if (item.ItemType == ItemType.Rom) - { - Rom romItem = item as Rom; - - // We can only write out if there's a SHA-1 - if (!string.IsNullOrWhiteSpace(romItem.SHA1)) - { - name = PathExtensions.GetRombaPath(romItem.SHA1, Header.Romba == false).Replace('\\', '/'); - item.Name = $"{pre}{name}{post}"; - } - } - else if (item.ItemType == ItemType.Disk) - { - Disk diskItem = item as Disk; - - // We can only write out if there's a SHA-1 - if (!string.IsNullOrWhiteSpace(diskItem.SHA1)) - { - name = PathExtensions.GetRombaPath(diskItem.SHA1, Header.Romba == false).Replace('\\', '/'); + name = PathExtensions.GetRombaPath(diskItem.SHA1, Header.RombaDepth).Replace('\\', '/'); item.Name = pre + name + post; } } diff --git a/SabreTools.Library/DatFiles/DatHeader.cs b/SabreTools.Library/DatFiles/DatHeader.cs index 3fbc658f..fb4a73d8 100644 --- a/SabreTools.Library/DatFiles/DatHeader.cs +++ b/SabreTools.Library/DatFiles/DatHeader.cs @@ -211,11 +211,16 @@ namespace SabreTools.Library.DatFiles public bool RemoveExtension { get; set; } /// - /// Romba or RVX output mode + /// Romba output mode /// - /// Null means neither, false means RVX, true means Romba [JsonIgnore] - public bool? Romba { get; set; } = null; + public bool Romba { get; set; } + + /// + /// Romba depth + /// + [JsonIgnore] + public int RombaDepth { get; set; } = 4; /// /// Output the machine name @@ -290,6 +295,7 @@ namespace SabreTools.Library.DatFiles RemoveExtension = this.RemoveExtension, GameName = this.GameName, Romba = this.Romba, + RombaDepth = this.RombaDepth, }; } @@ -353,6 +359,7 @@ namespace SabreTools.Library.DatFiles RemoveExtension = this.RemoveExtension, GameName = this.GameName, Romba = this.Romba, + RombaDepth = this.RombaDepth, }; } @@ -439,6 +446,7 @@ namespace SabreTools.Library.DatFiles this.RemoveExtension = datHeader.RemoveExtension; this.Romba = datHeader.Romba; + this.RombaDepth = datHeader.RombaDepth; this.GameName = datHeader.GameName; this.Quotes = datHeader.Quotes; this.UseRomName = datHeader.UseRomName; diff --git a/SabreTools.Library/DatFiles/Missfile.cs b/SabreTools.Library/DatFiles/Missfile.cs index caf01617..18d576c5 100644 --- a/SabreTools.Library/DatFiles/Missfile.cs +++ b/SabreTools.Library/DatFiles/Missfile.cs @@ -136,7 +136,7 @@ namespace SabreTools.Library.DatFiles ProcessItemName(datItem, false, forceRomName: false); // Romba mode automatically uses item name - if (Header.Romba != null || Header.UseRomName) + if (Header.Romba || Header.UseRomName) { sw.Write($"{datItem.GetField(Field.Name, Header.ExcludeFields)}\n"); } diff --git a/SabreTools.Library/FileTypes/BaseArchive.cs b/SabreTools.Library/FileTypes/BaseArchive.cs index b5a47b05..3661fa9d 100644 --- a/SabreTools.Library/FileTypes/BaseArchive.cs +++ b/SabreTools.Library/FileTypes/BaseArchive.cs @@ -176,9 +176,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override abstract bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null); + public override abstract bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4); /// /// Write an input stream to an archive @@ -187,9 +187,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override abstract bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null); + public override abstract bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4); /// /// Write a set of input files to an archive (assuming the same output archive name) diff --git a/SabreTools.Library/FileTypes/Folder.cs b/SabreTools.Library/FileTypes/Folder.cs index c61575ca..485eaca2 100644 --- a/SabreTools.Library/FileTypes/Folder.cs +++ b/SabreTools.Library/FileTypes/Folder.cs @@ -293,13 +293,13 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public virtual bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public virtual bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { FileStream fs = FileExtensions.TryOpenRead(inputFile); - return Write(fs, outDir, rom, date, romba); + return Write(fs, outDir, rom, date, depth); } /// @@ -309,10 +309,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public virtual bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public virtual bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { bool success = false; diff --git a/SabreTools.Library/FileTypes/GZipArchive.cs b/SabreTools.Library/FileTypes/GZipArchive.cs index bc54af15..0f3995d8 100644 --- a/SabreTools.Library/FileTypes/GZipArchive.cs +++ b/SabreTools.Library/FileTypes/GZipArchive.cs @@ -411,10 +411,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(string inputFile, string outDir, Rom rom = null, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom = null, bool date = false, int depth = 4) { // Check that the input file exists if (!File.Exists(inputFile)) @@ -426,7 +426,7 @@ namespace SabreTools.Library.FileTypes inputFile = Path.GetFullPath(inputFile); // Get the file stream for the file and write out - return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date, romba); + return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date, depth); } /// @@ -436,10 +436,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(Stream inputStream, string outDir, Rom rom = null, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom = null, bool date = false, int depth = 4) { bool success = false; @@ -457,31 +457,11 @@ namespace SabreTools.Library.FileTypes rom = new Rom(inputStream.GetInfo(keepReadOpen: true)); // Get the output file name - string outfile; + string outfile = Path.Combine(outDir, PathExtensions.GetRombaPath(rom.SHA1, depth)); // TODO: When updating to SHA-256, this needs to update to SHA256 - // If we have a Romba output, add the depot path - if (romba == true) - { - outfile = Path.Combine(outDir, PathExtensions.GetRombaPath(rom.SHA1, false)); // TODO: When updating to SHA-256, this needs to update to SHA256 - - // Check to see if the folder needs to be created - if (!Directory.Exists(Path.GetDirectoryName(outfile))) - Directory.CreateDirectory(Path.GetDirectoryName(outfile)); - } - // If we have an RVX output, add the RomRoot path - else if (romba == false) - { - outfile = Path.Combine(outDir, PathExtensions.GetRombaPath(rom.SHA1, true)); // TODO: When updating to SHA-256, this needs to update to SHA256 - - // Check to see if the folder needs to be created - if (!Directory.Exists(Path.GetDirectoryName(outfile))) - Directory.CreateDirectory(Path.GetDirectoryName(outfile)); - } - // Otherwise, we're just rebuilding to the main directory - else - { - outfile = Path.Combine(outDir, rom.SHA1 + ".gz"); // TODO: When updating to SHA-256, this needs to update to SHA256 - } + // Check to see if the folder needs to be created + if (!Directory.Exists(Path.GetDirectoryName(outfile))) + Directory.CreateDirectory(Path.GetDirectoryName(outfile)); // If the output file exists, don't try to write again if (!File.Exists(outfile)) diff --git a/SabreTools.Library/FileTypes/LRZipArchive.cs b/SabreTools.Library/FileTypes/LRZipArchive.cs index 0b9d6f40..48b6ae2c 100644 --- a/SabreTools.Library/FileTypes/LRZipArchive.cs +++ b/SabreTools.Library/FileTypes/LRZipArchive.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; -using SabreTools.Library.Data; using SabreTools.Library.DatFiles; using SabreTools.Library.DatItems; @@ -117,10 +116,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } @@ -132,10 +131,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } diff --git a/SabreTools.Library/FileTypes/LZ4Archive.cs b/SabreTools.Library/FileTypes/LZ4Archive.cs index d10bfe38..099ca6b6 100644 --- a/SabreTools.Library/FileTypes/LZ4Archive.cs +++ b/SabreTools.Library/FileTypes/LZ4Archive.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; -using SabreTools.Library.Data; using SabreTools.Library.DatFiles; using SabreTools.Library.DatItems; @@ -117,10 +116,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } @@ -132,10 +131,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } diff --git a/SabreTools.Library/FileTypes/RarArchive.cs b/SabreTools.Library/FileTypes/RarArchive.cs index c2a3567c..1c33dc15 100644 --- a/SabreTools.Library/FileTypes/RarArchive.cs +++ b/SabreTools.Library/FileTypes/RarArchive.cs @@ -13,313 +13,313 @@ using SharpCompress.Readers; namespace SabreTools.Library.FileTypes { - /// - /// Represents a TorrentRAR archive for reading and writing - /// - public class RarArchive : BaseArchive - { - #region Constructors + /// + /// Represents a TorrentRAR archive for reading and writing + /// + public class RarArchive : BaseArchive + { + #region Constructors - /// - /// Create a new TorrentRARArchive with no base file - /// - public RarArchive() - : base() - { - this.Type = FileType.RarArchive; - } + /// + /// Create a new TorrentRARArchive with no base file + /// + public RarArchive() + : base() + { + this.Type = FileType.RarArchive; + } - /// - /// Create a new TorrentRARArchive from the given file - /// - /// Name of the file to use as an archive - /// True for opening file as read, false for opening file as write - /// True if hashes for this file should be calculated, false otherwise (default) - public RarArchive(string filename, bool getHashes = false) - : base(filename, getHashes) - { - this.Type = FileType.RarArchive; - } + /// + /// Create a new TorrentRARArchive from the given file + /// + /// Name of the file to use as an archive + /// True for opening file as read, false for opening file as write + /// True if hashes for this file should be calculated, false otherwise (default) + public RarArchive(string filename, bool getHashes = false) + : base(filename, getHashes) + { + this.Type = FileType.RarArchive; + } - #endregion + #endregion - #region Extraction + #region Extraction - /// - /// Attempt to extract a file as an archive - /// - /// Output directory for archive extraction - /// True if the extraction was a success, false otherwise - public override bool CopyAll(string outDir) - { - bool encounteredErrors = true; + /// + /// Attempt to extract a file as an archive + /// + /// Output directory for archive extraction + /// True if the extraction was a success, false otherwise + public override bool CopyAll(string outDir) + { + bool encounteredErrors = true; - try - { - // Create the temp directory - Directory.CreateDirectory(outDir); + try + { + // Create the temp directory + Directory.CreateDirectory(outDir); - // Extract all files to the temp directory - SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename); - foreach (RarArchiveEntry entry in ra.Entries) - { - entry.WriteToDirectory(outDir, new SharpCompress.Common.ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); - } - encounteredErrors = false; - ra.Dispose(); - } - catch (EndOfStreamException) - { - // Catch this but don't count it as an error because SharpCompress is unsafe - } - catch (InvalidOperationException) - { - encounteredErrors = true; - } - catch (Exception ex) - { - Globals.Logger.Error(ex.ToString()); - encounteredErrors = true; - } + // Extract all files to the temp directory + SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename); + foreach (RarArchiveEntry entry in ra.Entries) + { + entry.WriteToDirectory(outDir, new SharpCompress.Common.ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); + } + encounteredErrors = false; + ra.Dispose(); + } + catch (EndOfStreamException) + { + // Catch this but don't count it as an error because SharpCompress is unsafe + } + catch (InvalidOperationException) + { + encounteredErrors = true; + } + catch (Exception ex) + { + Globals.Logger.Error(ex.ToString()); + encounteredErrors = true; + } - return encounteredErrors; - } + return encounteredErrors; + } - /// - /// Attempt to extract a file from an archive - /// - /// Name of the entry to be extracted - /// Output directory for archive extraction - /// Name of the extracted file, null on error - public override string CopyToFile(string entryName, string outDir) - { - // Try to extract a stream using the given information - (MemoryStream ms, string realEntry) = CopyToStream(entryName); + /// + /// Attempt to extract a file from an archive + /// + /// Name of the entry to be extracted + /// Output directory for archive extraction + /// Name of the extracted file, null on error + public override string CopyToFile(string entryName, string outDir) + { + // Try to extract a stream using the given information + (MemoryStream ms, string realEntry) = CopyToStream(entryName); - // If the memory stream and the entry name are both non-null, we write to file - if (ms != null && realEntry != null) - { - realEntry = Path.Combine(outDir, realEntry); + // If the memory stream and the entry name are both non-null, we write to file + if (ms != null && realEntry != null) + { + realEntry = Path.Combine(outDir, realEntry); - // Create the output subfolder now - Directory.CreateDirectory(Path.GetDirectoryName(realEntry)); + // Create the output subfolder now + Directory.CreateDirectory(Path.GetDirectoryName(realEntry)); - // Now open and write the file if possible - FileStream fs = FileExtensions.TryCreate(realEntry); - if (fs != null) - { - ms.Seek(0, SeekOrigin.Begin); - byte[] zbuffer = new byte[_bufferSize]; - int zlen; - while ((zlen = ms.Read(zbuffer, 0, _bufferSize)) > 0) - { - fs.Write(zbuffer, 0, zlen); - fs.Flush(); - } + // Now open and write the file if possible + FileStream fs = FileExtensions.TryCreate(realEntry); + if (fs != null) + { + ms.Seek(0, SeekOrigin.Begin); + byte[] zbuffer = new byte[_bufferSize]; + int zlen; + while ((zlen = ms.Read(zbuffer, 0, _bufferSize)) > 0) + { + fs.Write(zbuffer, 0, zlen); + fs.Flush(); + } - ms?.Dispose(); - fs?.Dispose(); - } - else - { - ms?.Dispose(); - fs?.Dispose(); - realEntry = null; - } - } + ms?.Dispose(); + fs?.Dispose(); + } + else + { + ms?.Dispose(); + fs?.Dispose(); + realEntry = null; + } + } - return realEntry; - } + return realEntry; + } - /// - /// Attempt to extract a stream from an archive - /// - /// Name of the entry to be extracted - /// Output representing the entry name that was found - /// MemoryStream representing the entry, null on error - public override (MemoryStream, string) CopyToStream(string entryName) - { - MemoryStream ms = new MemoryStream(); - string realEntry = null; + /// + /// Attempt to extract a stream from an archive + /// + /// Name of the entry to be extracted + /// Output representing the entry name that was found + /// MemoryStream representing the entry, null on error + public override (MemoryStream, string) CopyToStream(string entryName) + { + MemoryStream ms = new MemoryStream(); + string realEntry = null; - try - { - SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false, }); - foreach (RarArchiveEntry entry in ra.Entries) - { - if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName)) - { - // Write the file out - realEntry = entry.Key; - entry.WriteTo(ms); - } - } - ra.Dispose(); - } - catch (Exception ex) - { - Globals.Logger.Error(ex.ToString()); - ms = null; - realEntry = null; - } + try + { + SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false, }); + foreach (RarArchiveEntry entry in ra.Entries) + { + if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName)) + { + // Write the file out + realEntry = entry.Key; + entry.WriteTo(ms); + } + } + ra.Dispose(); + } + catch (Exception ex) + { + Globals.Logger.Error(ex.ToString()); + ms = null; + realEntry = null; + } - return (ms, realEntry); - } + return (ms, realEntry); + } - #endregion + #endregion - #region Information + #region Information - /// - /// Generate a list of DatItem objects from the header values in an archive - /// - /// Hash representing the hashes that should be skipped - /// True if entry dates should be included, false otherwise (default) - /// List of DatItem objects representing the found data - /// TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually - public override List GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) - { - List found = new List(); - string gamename = Path.GetFileNameWithoutExtension(this.Filename); + /// + /// Generate a list of DatItem objects from the header values in an archive + /// + /// Hash representing the hashes that should be skipped + /// True if entry dates should be included, false otherwise (default) + /// List of DatItem objects representing the found data + /// TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually + public override List GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) + { + List found = new List(); + string gamename = Path.GetFileNameWithoutExtension(this.Filename); - try - { - SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(FileExtensions.TryOpenRead(this.Filename)); - foreach (RarArchiveEntry entry in ra.Entries.Where(e => e != null && !e.IsDirectory)) - { - // If secure hashes are disabled, do a quickscan - if (omitFromScan == Hash.SecureHashes) - { - found.Add(new BaseFile - { - Filename = entry.Key, - Size = entry.Size, - CRC = BitConverter.GetBytes(entry.Crc), - Date = (date && entry.LastModifiedTime != null ? entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss") : null), + try + { + SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(FileExtensions.TryOpenRead(this.Filename)); + foreach (RarArchiveEntry entry in ra.Entries.Where(e => e != null && !e.IsDirectory)) + { + // If secure hashes are disabled, do a quickscan + if (omitFromScan == Hash.SecureHashes) + { + found.Add(new BaseFile + { + Filename = entry.Key, + Size = entry.Size, + CRC = BitConverter.GetBytes(entry.Crc), + Date = (date && entry.LastModifiedTime != null ? entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss") : null), - Parent = gamename, - }); - } - // Otherwise, use the stream directly - else - { - Stream entryStream = entry.OpenEntryStream(); - BaseFile rarEntryRom = entryStream.GetInfo(entry.Size, omitFromScan); - rarEntryRom.Filename = entry.Key; - rarEntryRom.Parent = gamename; - rarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss"); - found.Add(rarEntryRom); - entryStream.Dispose(); - } - } + Parent = gamename, + }); + } + // Otherwise, use the stream directly + else + { + Stream entryStream = entry.OpenEntryStream(); + BaseFile rarEntryRom = entryStream.GetInfo(entry.Size, omitFromScan); + rarEntryRom.Filename = entry.Key; + rarEntryRom.Parent = gamename; + rarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss"); + found.Add(rarEntryRom); + entryStream.Dispose(); + } + } - // Dispose of the archive - ra.Dispose(); - } - catch (Exception ex) - { - Globals.Logger.Error(ex.ToString()); - return null; - } + // Dispose of the archive + ra.Dispose(); + } + catch (Exception ex) + { + Globals.Logger.Error(ex.ToString()); + return null; + } - return found; - } + return found; + } - /// - /// Generate a list of empty folders in an archive - /// - /// Input file to get data from - /// List of empty folders in the archive - public override List GetEmptyFolders() - { - List empties = new List(); + /// + /// Generate a list of empty folders in an archive + /// + /// Input file to get data from + /// List of empty folders in the archive + public override List GetEmptyFolders() + { + List empties = new List(); - try - { - SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false }); - List rarEntries = ra.Entries.OrderBy(e => e.Key, new NaturalSort.NaturalReversedComparer()).ToList(); - string lastRarEntry = null; - foreach (RarArchiveEntry entry in rarEntries) - { - if (entry != null) - { - // If the current is a superset of last, we skip it - if (lastRarEntry != null && lastRarEntry.StartsWith(entry.Key)) - { - // No-op - } - // If the entry is a directory, we add it - else if (entry.IsDirectory) - { - empties.Add(entry.Key); - lastRarEntry = entry.Key; - } - } - } - } - catch (Exception ex) - { - Globals.Logger.Error(ex.ToString()); - } + try + { + SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false }); + List rarEntries = ra.Entries.OrderBy(e => e.Key, new NaturalSort.NaturalReversedComparer()).ToList(); + string lastRarEntry = null; + foreach (RarArchiveEntry entry in rarEntries) + { + if (entry != null) + { + // If the current is a superset of last, we skip it + if (lastRarEntry != null && lastRarEntry.StartsWith(entry.Key)) + { + // No-op + } + // If the entry is a directory, we add it + else if (entry.IsDirectory) + { + empties.Add(entry.Key); + lastRarEntry = entry.Key; + } + } + } + } + catch (Exception ex) + { + Globals.Logger.Error(ex.ToString()); + } - return empties; - } + return empties; + } - /// - /// Check whether the input file is a standardized format - /// - public override bool IsTorrent() - { - throw new NotImplementedException(); - } + /// + /// Check whether the input file is a standardized format + /// + public override bool IsTorrent() + { + throw new NotImplementedException(); + } - #endregion + #endregion - #region Writing + #region Writing - /// - /// Write an input file to a torrentrar archive - /// - /// Input filename to be moved - /// Output directory to build to - /// DatItem representing the new information - /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise - /// True if the archive was written properly, false otherwise - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) - { - // Get the file stream for the file and write out - return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date, romba); - } + /// + /// Write an input file to a torrentrar archive + /// + /// Input filename to be moved + /// Output directory to build to + /// DatItem representing the new information + /// True if the date from the DAT should be used if available, false otherwise (default) + /// Positive value for depth of the output depot, defaults to 4 + /// True if the archive was written properly, false otherwise + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) + { + // Get the file stream for the file and write out + return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date, depth); + } - /// - /// Write an input stream to a torrentrar archive - /// - /// Input stream to be moved - /// Output directory to build to - /// DatItem representing the new information - /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise - /// True if the archive was written properly, false otherwise - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) - { - throw new NotImplementedException(); - } + /// + /// Write an input stream to a torrentrar archive + /// + /// Input stream to be moved + /// Output directory to build to + /// DatItem representing the new information + /// True if the date from the DAT should be used if available, false otherwise (default) + /// Positive value for depth of the output depot, defaults to 4 + /// True if the archive was written properly, false otherwise + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) + { + throw new NotImplementedException(); + } - /// - /// Write a set of input files to a torrentrar archive (assuming the same output archive name) - /// - /// Input files to be moved - /// Output directory to build to - /// DatItem representing the new information - /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false otherwise - /// True if the archive was written properly, false otherwise - public override bool Write(List inputFiles, string outDir, List roms, bool date = false, bool romba = false) - { - throw new NotImplementedException(); - } + /// + /// Write a set of input files to a torrentrar archive (assuming the same output archive name) + /// + /// Input files to be moved + /// Output directory to build to + /// DatItem representing the new information + /// True if the date from the DAT should be used if available, false otherwise (default) + /// True if files should be output in Romba depot folders, false otherwise + /// True if the archive was written properly, false otherwise + public override bool Write(List inputFiles, string outDir, List roms, bool date = false, bool romba = false) + { + throw new NotImplementedException(); + } - #endregion - } + #endregion + } } diff --git a/SabreTools.Library/FileTypes/SevenZipArchive.cs b/SabreTools.Library/FileTypes/SevenZipArchive.cs index 35db0084..5070a244 100644 --- a/SabreTools.Library/FileTypes/SevenZipArchive.cs +++ b/SabreTools.Library/FileTypes/SevenZipArchive.cs @@ -414,9 +414,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { // Get the file stream for the file and write out return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date: date); @@ -429,9 +429,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { bool success = false; string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}"); diff --git a/SabreTools.Library/FileTypes/TapeArchive.cs b/SabreTools.Library/FileTypes/TapeArchive.cs index 4bc827df..8c0dbc84 100644 --- a/SabreTools.Library/FileTypes/TapeArchive.cs +++ b/SabreTools.Library/FileTypes/TapeArchive.cs @@ -289,9 +289,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { // Get the file stream for the file and write out return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date: date); @@ -304,9 +304,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { bool success = false; string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}"); diff --git a/SabreTools.Library/FileTypes/XZArchive.cs b/SabreTools.Library/FileTypes/XZArchive.cs index 2778363d..ee33efba 100644 --- a/SabreTools.Library/FileTypes/XZArchive.cs +++ b/SabreTools.Library/FileTypes/XZArchive.cs @@ -312,10 +312,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { // Check that the input file exists if (!File.Exists(inputFile)) @@ -327,7 +327,7 @@ namespace SabreTools.Library.FileTypes inputFile = Path.GetFullPath(inputFile); // Get the file stream for the file and write out - return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date, romba); + return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date, depth); } /// @@ -337,9 +337,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { bool success = false; @@ -357,31 +357,12 @@ namespace SabreTools.Library.FileTypes rom = new Rom(inputStream.GetInfo(keepReadOpen: true)); // Get the output file name - string outfile; + string outfile = Path.Combine(outDir, PathExtensions.GetRombaPath(rom.SHA1, depth)); // TODO: When updating to SHA-256, this needs to update to SHA256 + outfile = outfile.Replace(".gz", ".xz"); - // If we have a Romba output, add the depot path - if (romba == true) - { - outfile = Path.Combine(outDir, PathExtensions.GetRombaPath(rom.SHA1, false)); // TODO: When updating to SHA-256, this needs to update to SHA256 - - // Check to see if the folder needs to be created - if (!Directory.Exists(Path.GetDirectoryName(outfile))) - Directory.CreateDirectory(Path.GetDirectoryName(outfile)); - } - // If we have an RVX output, add the RomRoot path - else if (romba == false) - { - outfile = Path.Combine(outDir, PathExtensions.GetRombaPath(rom.SHA1, true)); // TODO: When updating to SHA-256, this needs to update to SHA256 - - // Check to see if the folder needs to be created - if (!Directory.Exists(Path.GetDirectoryName(outfile))) - Directory.CreateDirectory(Path.GetDirectoryName(outfile)); - } - // Otherwise, we're just rebuilding to the main directory - else - { - outfile = Path.Combine(outDir, rom.SHA1 + ".xz"); // TODO: When updating to SHA-256, this needs to update to SHA256 - } + // Check to see if the folder needs to be created + if (!Directory.Exists(Path.GetDirectoryName(outfile))) + Directory.CreateDirectory(Path.GetDirectoryName(outfile)); // If the output file exists, don't try to write again if (!File.Exists(outfile)) diff --git a/SabreTools.Library/FileTypes/ZPAQArchive.cs b/SabreTools.Library/FileTypes/ZPAQArchive.cs index d790b9cb..dac91832 100644 --- a/SabreTools.Library/FileTypes/ZPAQArchive.cs +++ b/SabreTools.Library/FileTypes/ZPAQArchive.cs @@ -116,10 +116,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } @@ -131,10 +131,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } diff --git a/SabreTools.Library/FileTypes/ZipArchive.cs b/SabreTools.Library/FileTypes/ZipArchive.cs index db16d71c..dfaaa365 100644 --- a/SabreTools.Library/FileTypes/ZipArchive.cs +++ b/SabreTools.Library/FileTypes/ZipArchive.cs @@ -419,9 +419,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { // Get the file stream for the file and write out return Write(FileExtensions.TryOpenRead(inputFile), outDir, rom, date: date); @@ -434,9 +434,9 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the archive was written properly, false otherwise - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { bool success = false; string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}"); diff --git a/SabreTools.Library/FileTypes/ZstdArchive.cs b/SabreTools.Library/FileTypes/ZstdArchive.cs index 03f0ed35..03954e5a 100644 --- a/SabreTools.Library/FileTypes/ZstdArchive.cs +++ b/SabreTools.Library/FileTypes/ZstdArchive.cs @@ -117,10 +117,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } @@ -132,10 +132,10 @@ namespace SabreTools.Library.FileTypes /// Output directory to build to /// DatItem representing the new information /// True if the date from the DAT should be used if available, false otherwise (default) - /// True if files should be output in Romba depot folders, false for RVX RomRoot folders, null otherwise + /// Positive value for depth of the output depot, defaults to 4 /// True if the write was a success, false otherwise /// This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code. - public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool? romba = null) + public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, int depth = 4) { throw new NotImplementedException(); } diff --git a/SabreTools.Library/IO/PathExtensions.cs b/SabreTools.Library/IO/PathExtensions.cs index ed2c8d72..a1a68c31 100644 --- a/SabreTools.Library/IO/PathExtensions.cs +++ b/SabreTools.Library/IO/PathExtensions.cs @@ -37,21 +37,30 @@ namespace SabreTools.Library.IO /// Get a proper romba sub path /// /// SHA-1 hash to get the path for - /// True to only go to 2-deep, false to default to 4-deep + /// Positive value representing the depth of the depot /// Subfolder path for the given hash - public static string GetRombaPath(string hash, bool rvx) + public static string GetRombaPath(string hash, int depth) { // If the hash isn't the right size, then we return null if (hash.Length != Constants.SHA1Length) // TODO: When updating to SHA-256, this needs to update to Constants.SHA256Length return null; - // RVX uses a 2-deep RomRoot - if (rvx) - return Path.Combine(hash.Substring(0, 2), hash.Substring(2, 2), hash + ".gz"); + // Cap the depth between 0 and 20, for now + if (depth < 0) + depth = 0; + else if (depth > Constants.SHA1ZeroBytes.Length) + depth = Constants.SHA1ZeroBytes.Length; - // Romba uses a 4-deep Depot - else - return Path.Combine(hash.Substring(0, 2), hash.Substring(2, 2), hash.Substring(4, 2), hash.Substring(6, 2), hash + ".gz"); + // Loop through and generate the subdirectory + string path = string.Empty; + for (int i = 0; i < depth; i++) + { + path += hash.Substring(i * 2, 2) + Path.DirectorySeparatorChar; + } + + // Now append the filename + path += hash + $"{hash}.gz"; + return path; } /// diff --git a/SabreTools.Library/README.1ST b/SabreTools.Library/README.1ST index e961ebf2..c8724bca 100644 --- a/SabreTools.Library/README.1ST +++ b/SabreTools.Library/README.1ST @@ -248,10 +248,9 @@ Options: output for physical files. Where appropriate, Romba depot files will be created as well. - -rvx, --romvaultx Treat like an RVX RomRoot (requires SHA-1) - This flag allows reading and writing of DATs and output files to and - from a RVX-style RomRoot. This also implies TorrentGZ input and - output for physical files. + --depr, --romba-depth Set depth of depot for outputs + Optionally, set the depth of output depots. Defaults to 4 deep + otherwise. -ska, --skip-archives Skip all archives Skip any files that are treated like archives @@ -629,10 +628,9 @@ Options: If this flag is used, all input directories will be assumed to be romba-style depots. - -rr, --romroot Assume directories are RVX RomRoots - Normally, input directories will be treated with no special format. - If this flag is used, all input directories will be assumed to be - RVX-style RomRoots. + --depd, --depot-depth Set depth of depot for inputs + Optionally, set the depth of input depots. Defaults to 4 deep + otherwise. -del, --delete Delete fully rebuilt input files Optionally, the input files, once processed and fully matched, can be @@ -694,10 +692,9 @@ Options: and output for physical files. Where appropriate, Romba depot files will be created as well. - -rvx, --romvaultx Treat like an RVX RomRoot (requires SHA-1) - This flag allows reading and writing of DATs and output files to - and from a RVX-style RomRoot. This also implies TorrentGZ input - and output for physical files. + --depr, --romba-depth Set depth of depot for outputs + Optionally, set the depth of output depots. Defaults to 4 deep + otherwise. -tzip, --torrent-zip Enable Torrent Zip output Instead of outputting files to folder, files will be rebuilt to @@ -1006,10 +1003,9 @@ Options: and output for physical files. Where appropriate, Romba depot files will be created as well. - -rvx, --romvaultx Treat like an RVX RomRoot (requires SHA-1) - This flag allows reading and writing of DATs and output files to - and from a RVX-style RomRoot. This also implies TorrentGZ input - and output for physical files. + --depr, --romba-depth Set depth of depot for outputs + Optionally, set the depth of output depots. Defaults to 4 deep + otherwise. -dpc, --deprecated Output 'game' instead of 'machine' By default, Logiqx XML DATs output with the more modern "machine" @@ -1537,10 +1533,9 @@ Options: If this flag is used, all input directories will be assumed to be romba-style depots. - -rr, --romroot Assume directories are RVX RomRoots - Normally, input directories will be treated with no special format. - If this flag is used, all input directories will be assumed to be - RVX-style RomRoots. + --depd, --depot-depth Set depth of depot for inputs + Optionally, set the depth of input depots. Defaults to 4 deep + otherwise. -t=, --temp= Set the temporary directory to use Optionally, a temp folder can be supplied in the case the default diff --git a/SabreTools/Features/BaseFeature.cs b/SabreTools/Features/BaseFeature.cs index 8fce91f9..d79c2310 100644 --- a/SabreTools/Features/BaseFeature.cs +++ b/SabreTools/Features/BaseFeature.cs @@ -794,20 +794,6 @@ namespace SabreTools.Features } } - internal const string RomRootValue = "romroot"; - internal static Feature RomRootFlag - { - get - { - return new Feature( - RomRootValue, - new List() { "-rr", "--romroot" }, - "Assume directories are RVX RomRoots", - FeatureType.Flag, - longDescription: "Normally, input directories will be treated with no special format. If this flag is used, all input directories will be assumed to be RVX-style RomRoots."); - } - } - internal const string RomsValue = "roms"; internal static Feature RomsFlag { @@ -836,20 +822,6 @@ namespace SabreTools.Features } } - internal const string RVXValue = "rvx"; - internal static Feature RVXFlag - { - get - { - return new Feature( - RVXValue, - new List() { "-rvx", "--romvaultx" }, - "Treat like an RVX RomRoot (requires SHA-1)", - FeatureType.Flag, - longDescription: "This flag allows reading and writing of DATs and output files to and from a RVX-style RomRoot. This also implies TorrentGZ input and output for physical files."); - } - } - internal const string SceneDateStripValue = "scene-date-strip"; internal static Feature SceneDateStripFlag { @@ -1248,6 +1220,34 @@ namespace SabreTools.Features #region Int32 features + internal const string DepotDepthInt32Value = "depot-depth"; + internal static Feature DepotDepthInt32Input + { + get + { + return new Feature( + DepotDepthInt32Value, + new List() { "-depd", "--depot-depth" }, + "Set depth of depot for inputs", + FeatureType.Int32, + longDescription: "Optionally, set the depth of input depots. Defaults to 4 deep otherwise."); + } + } + + internal const string RombaDepthInt32Value = "romba-depth"; + internal static Feature RombaDepthInt32Input + { + get + { + return new Feature( + RombaDepthInt32Value, + new List() { "-depr", "--romba-depth" }, + "Set depth of depot for outputs", + FeatureType.Int32, + longDescription: "Optionally, set the depth of output depots. Defaults to 4 deep otherwise."); + } + } + internal const string ThreadsInt32Value = "threads"; internal static Feature ThreadsInt32Input { @@ -2661,6 +2661,8 @@ Some special strings that can be used: RegionList = GetList(features, RegionListValue), RemoveExtension = GetBoolean(features, RemoveExtensionsValue), ReplaceExtension = GetString(features, ReplaceExtensionStringValue), + Romba = GetBoolean(features, RombaValue), + RombaDepth = GetInt32(features, RombaDepthInt32Value), RootDir = GetString(features, RootStringValue), SceneDateStrip = GetBoolean(features, SceneDateStripValue), Type = GetBoolean(features, SuperdatValue) ? "SuperDAT" : null, @@ -2669,11 +2671,9 @@ Some special strings that can be used: Version = GetString(features, VersionStringValue), }; - // Romba overrides RVX for flags - if (GetBoolean(features, RombaValue)) - datHeader.Romba = true; - else if (GetBoolean(features, RVXValue)) - datHeader.Romba = false; + // Set a reasonable default for the Romba depth + if (datHeader.RombaDepth == Int32.MinValue) + datHeader.RombaDepth = 4; bool deprecated = GetBoolean(features, DeprecatedValue); foreach (string ot in GetList(features, OutputTypeListValue)) diff --git a/SabreTools/Features/DatFromDir.cs b/SabreTools/Features/DatFromDir.cs index 69857f55..c4093439 100644 --- a/SabreTools/Features/DatFromDir.cs +++ b/SabreTools/Features/DatFromDir.cs @@ -35,7 +35,7 @@ namespace SabreTools.Features AddFeature(OutputTypeListInput); this[OutputTypeListInput].AddFeature(DeprecatedFlag); AddFeature(RombaFlag); - AddFeature(RVXFlag); + this[RombaFlag].AddFeature(RombaDepthInt32Input); AddFeature(SkipArchivesFlag); AddFeature(SkipFilesFlag); AddHeaderFeatures(); diff --git a/SabreTools/Features/Sort.cs b/SabreTools/Features/Sort.cs index 157a8ec0..ee8c3676 100644 --- a/SabreTools/Features/Sort.cs +++ b/SabreTools/Features/Sort.cs @@ -25,7 +25,7 @@ namespace SabreTools.Features AddFeature(DatListInput); AddFeature(OutputDirStringInput); AddFeature(DepotFlag); - AddFeature(RomRootFlag); + this[DepotFlag].AddFeature(DepotDepthInt32Input); AddFeature(DeleteFlag); AddFeature(InverseFlag); AddFeature(QuickFlag); @@ -38,7 +38,7 @@ namespace SabreTools.Features AddFeature(TarFlag); AddFeature(TorrentGzipFlag); this[TorrentGzipFlag].AddFeature(RombaFlag); - this[TorrentGzipFlag].AddFeature(RVXFlag); + this[TorrentGzipFlag][RombaFlag].AddFeature(RombaDepthInt32Input); //AddFeature(SharedInputs.TorrentLrzipFlag); //AddFeature(SharedInputs.TorrentLz4Flag); //AddFeature(SharedInputs.TorrentRarFlag); @@ -62,31 +62,27 @@ namespace SabreTools.Features TreatAsFiles asFiles = GetTreatAsFiles(features); bool date = GetBoolean(features, AddDateValue); bool delete = GetBoolean(features, DeleteValue); + bool depot = GetBoolean(features, DepotValue); bool inverse = GetBoolean(features, InverseValue); bool quickScan = GetBoolean(features, QuickValue); + bool romba = GetBoolean(features, RombaValue); bool updateDat = GetBoolean(features, UpdateDatValue); var outputFormat = GetOutputFormat(features); - // Romba overrides RVX for flags - bool? romba = null; - if (GetBoolean(features, RombaValue)) - romba = true; - else if (GetBoolean(features, RVXValue)) - romba = false; - - // Depot overrides RomRoot for flags - bool? depot = null; - if (GetBoolean(features, DepotValue)) - depot = true; - else if (GetBoolean(features, RomRootValue)) - depot = false; + // Get optional depths + int depotDepth = 4; + if (features.ContainsKey(DepotDepthInt32Value)) + depotDepth = GetInt32(features, DepotDepthInt32Value); + int rombaDepth = 4; + if (features.ContainsKey(RombaDepthInt32Value)) + rombaDepth = GetInt32(features, RombaDepthInt32Value); // If we have TorrentGzip output and the romba flag, update - if (romba != null && outputFormat == OutputFormat.TorrentGzip) + if (romba && outputFormat == OutputFormat.TorrentGzip) outputFormat = OutputFormat.TorrentGzipRomba; // If we hae TorrentXZ output and the romba flag, update - if (romba != null && outputFormat == OutputFormat.TorrentXZ) + if (romba && outputFormat == OutputFormat.TorrentXZ) outputFormat = OutputFormat.TorrentXZRomba; // Get a list of files from the input datfiles @@ -106,10 +102,10 @@ namespace SabreTools.Features datdata.Header.HeaderSkipper = Header.HeaderSkipper; // If we have the depot flag, respect it - if (depot != null) - datdata.RebuildDepot(Inputs, depot == false, romba == false, Path.Combine(OutputDir, datdata.Header.FileName), date, delete, inverse, outputFormat, updateDat); + if (depot) + datdata.RebuildDepot(Inputs, depotDepth, rombaDepth, Path.Combine(OutputDir, datdata.Header.FileName), date, delete, inverse, outputFormat, updateDat); else - datdata.RebuildGeneric(Inputs, Path.Combine(OutputDir, datdata.Header.FileName), romba == false, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); + datdata.RebuildGeneric(Inputs, Path.Combine(OutputDir, datdata.Header.FileName), rombaDepth, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); } } @@ -132,10 +128,10 @@ namespace SabreTools.Features watch.Stop(); // If we have the depot flag, respect it - if (depot != null) - datdata.RebuildDepot(Inputs, depot == false, romba == false, OutputDir, date, delete, inverse, outputFormat, updateDat); + if (depot) + datdata.RebuildDepot(Inputs, depotDepth, rombaDepth, OutputDir, date, delete, inverse, outputFormat, updateDat); else - datdata.RebuildGeneric(Inputs, OutputDir, romba == false, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); + datdata.RebuildGeneric(Inputs, OutputDir, rombaDepth, quickScan, date, delete, inverse, outputFormat, updateDat, asFiles); } } } diff --git a/SabreTools/Features/Update.cs b/SabreTools/Features/Update.cs index adbcc347..cfc1ecb3 100644 --- a/SabreTools/Features/Update.cs +++ b/SabreTools/Features/Update.cs @@ -32,7 +32,7 @@ namespace SabreTools.Features this[OutputTypeListInput].AddFeature(ReplaceExtensionStringInput); this[OutputTypeListInput].AddFeature(RemoveExtensionsFlag); this[OutputTypeListInput].AddFeature(RombaFlag); - this[OutputTypeListInput].AddFeature(RVXFlag); + this[OutputTypeListInput][RombaFlag].AddFeature(RombaDepthInt32Input); this[OutputTypeListInput].AddFeature(DeprecatedFlag); AddHeaderFeatures(); diff --git a/SabreTools/Features/Verify.cs b/SabreTools/Features/Verify.cs index 3c853b7b..fa32d5fd 100644 --- a/SabreTools/Features/Verify.cs +++ b/SabreTools/Features/Verify.cs @@ -22,7 +22,7 @@ namespace SabreTools.Features AddFeature(DatListInput); AddFeature(DepotFlag); - AddFeature(RomRootFlag); + this[DepotFlag].AddFeature(DepotDepthInt32Input); AddFeature(TempStringInput); AddFeature(OutputDirStringInput); AddFeature(HashOnlyFlag); @@ -44,15 +44,14 @@ namespace SabreTools.Features // Get feature flags TreatAsFiles asFiles = GetTreatAsFiles(features); + bool depot = GetBoolean(features, DepotValue); bool hashOnly = GetBoolean(features, HashOnlyValue); bool quickScan = GetBoolean(features, QuickValue); - // Depot overrides RomRoot for flags - bool? depot = null; - if (GetBoolean(features, DepotValue)) - depot = true; - else if (GetBoolean(features, RomRootValue)) - depot = false; + // Get optional depth + int depotDepth = 4; + if (features.ContainsKey(DepotDepthInt32Value)) + depotDepth = GetInt32(features, DepotDepthInt32Value); // If we are in individual mode, process each DAT on their own if (GetBoolean(features, IndividualValue)) @@ -68,8 +67,8 @@ namespace SabreTools.Features datdata.Header.HeaderSkipper = Header.HeaderSkipper; // If we have the depot flag, respect it - if (depot != null) - datdata.VerifyDepot(Inputs, depot == false, OutputDir); + if (depot) + datdata.VerifyDepot(Inputs, depotDepth, OutputDir); else datdata.VerifyGeneric(Inputs, OutputDir, hashOnly, quickScan, asFiles, Filter); } @@ -94,8 +93,8 @@ namespace SabreTools.Features watch.Stop(); // If we have the depot flag, respect it - if (depot != null) - datdata.VerifyDepot(Inputs, depot == false, OutputDir); + if (depot) + datdata.VerifyDepot(Inputs, depotDepth, OutputDir); else datdata.VerifyGeneric(Inputs, OutputDir, hashOnly, quickScan, asFiles, Filter); }