diff --git a/.gitignore b/.gitignore index a67add3f..7e6382fc 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ /SabreTools.Data/obj/ /SabreTools.Library/bin/ /SabreTools.Library/obj/ +/SabreTools.Skippers/bin/ +/SabreTools.Skippers/obj/ /SabreTools.userprefs diff --git a/SabreTools.Library/IO/FileExtensions.cs b/SabreTools.Library/IO/FileExtensions.cs index 52c3c355..41af4627 100644 --- a/SabreTools.Library/IO/FileExtensions.cs +++ b/SabreTools.Library/IO/FileExtensions.cs @@ -9,7 +9,7 @@ using SabreTools.Data; using SabreTools.Library.DatFiles; using SabreTools.Library.FileTypes; using SabreTools.Library.Logging; -using SabreTools.Library.Skippers; +using SabreTools.Library.Tools; namespace SabreTools.Library.IO { @@ -370,7 +370,7 @@ namespace SabreTools.Library.IO // Try to match the supplied header skipper if (header != null) { - SkipperRule rule = Transform.GetMatchingRule(input, Path.GetFileNameWithoutExtension(header)); + var rule = Transform.GetMatchingRule(input, Path.GetFileNameWithoutExtension(header)); // If there's a match, transform the stream before getting info if (rule.Tests != null && rule.Tests.Count != 0) diff --git a/SabreTools.Library/Skippers/Transform.cs b/SabreTools.Library/IO/Transform.cs similarity index 98% rename from SabreTools.Library/Skippers/Transform.cs rename to SabreTools.Library/IO/Transform.cs index c98ff3d2..8115cdcc 100644 --- a/SabreTools.Library/Skippers/Transform.cs +++ b/SabreTools.Library/IO/Transform.cs @@ -4,11 +4,11 @@ using System.IO; using SabreTools.Data; using SabreTools.Library.DatFiles; using SabreTools.Library.FileTypes; -using SabreTools.Library.IO; using SabreTools.Library.Logging; +using SabreTools.Library.Skippers; using SabreTools.Library.Tools; -namespace SabreTools.Library.Skippers +namespace SabreTools.Library.IO { /// /// Class for wrapping general file transformations @@ -32,6 +32,11 @@ namespace SabreTools.Library.Skippers /// private static List List; + /// + /// Local paths + /// + private static string LocalPath = Path.Combine(Globals.ExeDir, "Skippers") + Path.DirectorySeparatorChar; + #region Logging /// @@ -41,11 +46,6 @@ namespace SabreTools.Library.Skippers #endregion - /// - /// Local paths - /// - public static string LocalPath = Path.Combine(Globals.ExeDir, "Skippers") + Path.DirectorySeparatorChar; - /// /// Initialize static fields /// diff --git a/SabreTools.Library/SabreTools.Library.csproj b/SabreTools.Library/SabreTools.Library.csproj index f8617ca5..d27e5b52 100644 --- a/SabreTools.Library/SabreTools.Library.csproj +++ b/SabreTools.Library/SabreTools.Library.csproj @@ -13,48 +13,7 @@ - - - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - + diff --git a/SabreTools.Library/Skippers/Enums.cs b/SabreTools.Skippers/Enums.cs similarity index 100% rename from SabreTools.Library/Skippers/Enums.cs rename to SabreTools.Skippers/Enums.cs diff --git a/SabreTools.Skippers/SabreTools.Skippers.csproj b/SabreTools.Skippers/SabreTools.Skippers.csproj new file mode 100644 index 00000000..752c6fee --- /dev/null +++ b/SabreTools.Skippers/SabreTools.Skippers.csproj @@ -0,0 +1,56 @@ + + + + net48;netcoreapp3.1;net5.0 + win10-x64;win7-x86 + Debug;Release + AnyCPU;x64 + + + + NET_FRAMEWORK + + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + diff --git a/SabreTools.Library/Skippers/SkipperFile.cs b/SabreTools.Skippers/SkipperFile.cs similarity index 90% rename from SabreTools.Library/Skippers/SkipperFile.cs rename to SabreTools.Skippers/SkipperFile.cs index b2eb5af8..7ffff087 100644 --- a/SabreTools.Library/Skippers/SkipperFile.cs +++ b/SabreTools.Skippers/SkipperFile.cs @@ -4,10 +4,14 @@ using System.Globalization; using System.IO; using System.Xml; -using SabreTools.Library.IO; - namespace SabreTools.Library.Skippers { + /// + /// It is well worth considering just moving the XML files to code, similar to how RV does it + /// if only because nobody really has any skippers outside of this. It would also make the + /// output directory cleaner and less prone to user error in case something didn't get copied + /// correctly. The contents of these files should still be added to the wiki, in that case. + /// public class SkipperFile { #region Fields @@ -55,7 +59,7 @@ namespace SabreTools.Library.Skippers Rules = new List(); SourceFile = Path.GetFileNameWithoutExtension(filename); - XmlReader xtr = filename.GetXmlTextReader(); + XmlReader xtr = GetXmlTextReader(filename); bool valid = Parse(xtr); // If we somehow have an invalid file, zero out the fields @@ -406,5 +410,34 @@ namespace SabreTools.Library.Skippers } #endregion + + // TODO: Remove this region once IO namespace is separated out properly + #region TEMPORARY - REMOVEME + + /// + /// Get the XmlTextReader associated with a file, if possible + /// + /// Name of the file to be parsed + /// The XmlTextReader representing the (possibly converted) file, null otherwise + private static XmlReader GetXmlTextReader(string filename) + { + // Check if file exists + if (!File.Exists(filename)) + return null; + + XmlReader xtr = XmlReader.Create(filename, new XmlReaderSettings + { + CheckCharacters = false, + DtdProcessing = DtdProcessing.Ignore, + IgnoreComments = true, + IgnoreWhitespace = true, + ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None, + ValidationType = ValidationType.None, + }); + + return xtr; + } + + #endregion } } diff --git a/SabreTools.Library/Skippers/SkipperRule.cs b/SabreTools.Skippers/SkipperRule.cs similarity index 62% rename from SabreTools.Library/Skippers/SkipperRule.cs rename to SabreTools.Skippers/SkipperRule.cs index 4a2897cf..2fa0b79b 100644 --- a/SabreTools.Library/Skippers/SkipperRule.cs +++ b/SabreTools.Skippers/SkipperRule.cs @@ -2,9 +2,6 @@ using System.Collections.Generic; using System.IO; -using SabreTools.Library.IO; -using SabreTools.Library.Logging; - namespace SabreTools.Library.Skippers { public class SkipperRule @@ -43,7 +40,7 @@ namespace SabreTools.Library.Skippers /// /// Logging object /// - private readonly Logger logger; + //private readonly Logger logger; // TODO: Re-enable all logging once Logging namespace separated out #endregion @@ -54,7 +51,7 @@ namespace SabreTools.Library.Skippers /// public SkipperRule() { - logger = new Logger(this); + //logger = new Logger(this); } #endregion @@ -87,20 +84,20 @@ namespace SabreTools.Library.Skippers // If the input file doesn't exist, fail if (!File.Exists(input)) { - logger.Error($"I'm sorry but '{input}' doesn't exist!"); + //logger.Error($"I'm sorry but '{input}' doesn't exist!"); return false; } // Create the output directory if it doesn't already - DirectoryExtensions.Ensure(Path.GetDirectoryName(output)); + Ensure(Path.GetDirectoryName(output)); - logger.User($"Attempting to apply rule to '{input}'"); - bool success = TransformStream(FileExtensions.TryOpenRead(input), FileExtensions.TryCreate(output)); + //logger.User($"Attempting to apply rule to '{input}'"); + bool success = TransformStream(TryOpenRead(input), TryCreate(output)); // If the output file has size 0, delete it if (new FileInfo(output).Length == 0) { - FileExtensions.TryDelete(output); + TryDelete(output); success = false; } @@ -125,7 +122,7 @@ namespace SabreTools.Library.Skippers || (Operation > HeaderSkipOperation.Byteswap && (extsize % 4) != 0) || (Operation > HeaderSkipOperation.Bitswap && (StartOffset == null || StartOffset % 2 == 0))) { - logger.Error("The stream did not have the correct size to be transformed!"); + //logger.Error("The stream did not have the correct size to be transformed!"); return false; } @@ -134,7 +131,7 @@ namespace SabreTools.Library.Skippers BinaryReader br = null; try { - logger.User("Applying found rule to input stream"); + //logger.User("Applying found rule to input stream"); bw = new BinaryWriter(output); br = new BinaryReader(input); @@ -222,7 +219,7 @@ namespace SabreTools.Library.Skippers } catch (Exception ex) { - logger.Error(ex); + //logger.Error(ex); return false; } finally @@ -238,5 +235,113 @@ namespace SabreTools.Library.Skippers return success; } + + // TODO: Remove this region once IO namespace is separated out properly + #region TEMPORARY - REMOVEME + + /// + /// Ensure the output directory is a proper format and can be created + /// + /// Directory to check + /// True if the directory should be created, false otherwise (default) + /// True if this is a temp directory, false otherwise + /// Full path to the directory + public static string Ensure(string dir, bool create = false, bool temp = false) + { + // If the output directory is invalid + if (string.IsNullOrWhiteSpace(dir)) + { + if (temp) + dir = Path.GetTempPath(); + else + dir = Environment.CurrentDirectory; + } + + // Get the full path for the output directory + dir = Path.GetFullPath(dir); + + // If we're creating the output folder, do so + if (create) + Directory.CreateDirectory(dir); + + return dir; + } + + /// + /// Try to create a file for write, optionally throwing the error + /// + /// Name of the file to create + /// True if the error that is thrown should be thrown back to the caller, false otherwise + /// An opened stream representing the file on success, null otherwise + public static FileStream TryCreate(string file, bool throwOnError = false) + { + // Now wrap opening the file + try + { + return File.Open(file, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); + } + catch (Exception ex) + { + if (throwOnError) + throw ex; + else + return null; + } + } + + /// + /// Try to safely delete a file, optionally throwing the error + /// + /// Name of the file to delete + /// True if the error that is thrown should be thrown back to the caller, false otherwise + /// True if the file didn't exist or could be deleted, false otherwise + public static bool TryDelete(string file, bool throwOnError = false) + { + // Check if the file exists first + if (!File.Exists(file)) + return true; + + // Now wrap deleting the file + try + { + File.Delete(file); + return true; + } + catch (Exception ex) + { + if (throwOnError) + throw ex; + else + return false; + } + } + + /// + /// Try to open a file for read, optionally throwing the error + /// + /// Name of the file to open + /// True if the error that is thrown should be thrown back to the caller, false otherwise + /// An opened stream representing the file on success, null otherwise + public static FileStream TryOpenRead(string file, bool throwOnError = false) + { + // Check if the file exists first + if (!File.Exists(file)) + return null; + + // Now wrap opening the file + try + { + return File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + } + catch (Exception ex) + { + if (throwOnError) + throw ex; + else + return null; + } + } + + #endregion } } diff --git a/SabreTools.Library/Skippers/SkipperTest.cs b/SabreTools.Skippers/SkipperTest.cs similarity index 100% rename from SabreTools.Library/Skippers/SkipperTest.cs rename to SabreTools.Skippers/SkipperTest.cs diff --git a/SabreTools.Library/Skippers/a7800.xml b/SabreTools.Skippers/a7800.xml similarity index 100% rename from SabreTools.Library/Skippers/a7800.xml rename to SabreTools.Skippers/a7800.xml diff --git a/SabreTools.Library/Skippers/fds.xml b/SabreTools.Skippers/fds.xml similarity index 100% rename from SabreTools.Library/Skippers/fds.xml rename to SabreTools.Skippers/fds.xml diff --git a/SabreTools.Library/Skippers/lynx.xml b/SabreTools.Skippers/lynx.xml similarity index 100% rename from SabreTools.Library/Skippers/lynx.xml rename to SabreTools.Skippers/lynx.xml diff --git a/SabreTools.Library/Skippers/n64.xml b/SabreTools.Skippers/n64.xml similarity index 100% rename from SabreTools.Library/Skippers/n64.xml rename to SabreTools.Skippers/n64.xml diff --git a/SabreTools.Library/Skippers/nes.xml b/SabreTools.Skippers/nes.xml similarity index 100% rename from SabreTools.Library/Skippers/nes.xml rename to SabreTools.Skippers/nes.xml diff --git a/SabreTools.Library/Skippers/pce.xml b/SabreTools.Skippers/pce.xml similarity index 100% rename from SabreTools.Library/Skippers/pce.xml rename to SabreTools.Skippers/pce.xml diff --git a/SabreTools.Library/Skippers/psid.xml b/SabreTools.Skippers/psid.xml similarity index 100% rename from SabreTools.Library/Skippers/psid.xml rename to SabreTools.Skippers/psid.xml diff --git a/SabreTools.Library/Skippers/snes.xml b/SabreTools.Skippers/snes.xml similarity index 100% rename from SabreTools.Library/Skippers/snes.xml rename to SabreTools.Skippers/snes.xml diff --git a/SabreTools.Library/Skippers/spc.xml b/SabreTools.Skippers/spc.xml similarity index 100% rename from SabreTools.Library/Skippers/spc.xml rename to SabreTools.Skippers/spc.xml diff --git a/SabreTools.sln b/SabreTools.sln index 0df32d4a..85719aaa 100644 --- a/SabreTools.sln +++ b/SabreTools.sln @@ -16,7 +16,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.MD = README.MD EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Data", "SabreTools.Data\SabreTools.Data.csproj", "{66E2FB10-77C0-4589-9DCD-3CA48702C18A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SabreTools.Data", "SabreTools.Data\SabreTools.Data.csproj", "{66E2FB10-77C0-4589-9DCD-3CA48702C18A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Skippers", "SabreTools.Skippers\SabreTools.Skippers.csproj", "{D8665F27-75E6-4E3F-9F0A-286433831C69}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -58,6 +60,14 @@ Global {66E2FB10-77C0-4589-9DCD-3CA48702C18A}.Release|Any CPU.Build.0 = Release|Any CPU {66E2FB10-77C0-4589-9DCD-3CA48702C18A}.Release|x64.ActiveCfg = Release|Any CPU {66E2FB10-77C0-4589-9DCD-3CA48702C18A}.Release|x64.Build.0 = Release|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Debug|x64.ActiveCfg = Debug|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Debug|x64.Build.0 = Debug|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Release|Any CPU.Build.0 = Release|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Release|x64.ActiveCfg = Release|Any CPU + {D8665F27-75E6-4E3F-9F0A-286433831C69}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SabreTools/Features/Extract.cs b/SabreTools/Features/Extract.cs index a25c716c..bebafe55 100644 --- a/SabreTools/Features/Extract.cs +++ b/SabreTools/Features/Extract.cs @@ -2,7 +2,7 @@ using SabreTools.Library.Help; using SabreTools.Library.IO; -using SabreTools.Library.Skippers; +using SabreTools.Library.Tools; namespace SabreTools.Features { diff --git a/SabreTools/Features/Restore.cs b/SabreTools/Features/Restore.cs index 8c4e3542..d06feef2 100644 --- a/SabreTools/Features/Restore.cs +++ b/SabreTools/Features/Restore.cs @@ -2,7 +2,6 @@ using SabreTools.Library.Help; using SabreTools.Library.IO; -using SabreTools.Library.Skippers; namespace SabreTools.Features {