diff --git a/SabreTools.Skippers/Enums.cs b/SabreTools.Skippers/Enums.cs
index 8535aa6f..ab4ae5d6 100644
--- a/SabreTools.Skippers/Enums.cs
+++ b/SabreTools.Skippers/Enums.cs
@@ -12,18 +12,6 @@
WordByteswap,
}
- ///
- /// Determines the type of test to be done
- ///
- public enum HeaderSkipTest
- {
- Data = 0,
- Or,
- Xor,
- And,
- File,
- }
-
///
/// Determines the operator to be used in a file test
///
diff --git a/SabreTools.Skippers/SkipperFile.cs b/SabreTools.Skippers/SkipperFile.cs
index 44fca1e3..4fc07528 100644
--- a/SabreTools.Skippers/SkipperFile.cs
+++ b/SabreTools.Skippers/SkipperFile.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Schema;
+using System.Xml.Serialization;
namespace SabreTools.Skippers
{
@@ -20,26 +21,31 @@ namespace SabreTools.Skippers
///
/// Skipper name
///
+ [XmlElement("name")]
public string Name { get; set; } = string.Empty;
///
/// Author names
///
+ [XmlElement("author")]
public string Author { get; set; } = string.Empty;
///
/// File version
///
+ [XmlElement("version")]
public string Version { get; set; } = string.Empty;
///
/// Set of all rules in the skipper
///
+ [XmlArray("rule")]
public List Rules { get; set; } = new List();
///
/// Filename the skipper lives in
///
+ [XmlIgnore]
public string SourceFile { get; set; } = string.Empty;
#endregion
@@ -129,7 +135,7 @@ namespace SabreTools.Skippers
SkipperRule rule = ParseRule(xtr);
if (rule != null)
Rules.Add(rule);
-
+
xtr.Read();
break;
@@ -227,7 +233,7 @@ namespace SabreTools.Skippers
subreader.Read();
break;
-
+
default:
subreader.Read();
break;
@@ -256,41 +262,27 @@ namespace SabreTools.Skippers
try
{
// Get the test type
- SkipperTest test = new SkipperTest
+ SkipperTest test = xtr.Name.ToLowerInvariant() switch
{
- Offset = 0,
- Value = new byte[0],
- Result = true,
- Mask = new byte[0],
- Size = 0,
- Operator = HeaderSkipTestFileOperator.Equal,
+ "and" => new AndSkipperTest(),
+ "data" => new DataSkipperTest(),
+ "file" => new FileSkipperTest(),
+ "or" => new OrSkipperTest(),
+ "xor" => new XorSkipperTest(),
+ _ => null,
};
- switch (xtr.Name.ToLowerInvariant())
- {
- case "data":
- test.Type = HeaderSkipTest.Data;
- break;
+ // If we had an invalid test type
+ if (test == null)
+ return null;
- case "or":
- test.Type = HeaderSkipTest.Or;
- break;
-
- case "xor":
- test.Type = HeaderSkipTest.Xor;
- break;
-
- case "and":
- test.Type = HeaderSkipTest.And;
- break;
-
- case "file":
- test.Type = HeaderSkipTest.File;
- break;
-
- default:
- return null;
- }
+ // Set the default values
+ test.Offset = 0;
+ test.Value = Array.Empty();
+ test.Result = true;
+ test.Mask = Array.Empty();
+ test.Size = 0;
+ test.Operator = HeaderSkipTestFileOperator.Equal;
// Now populate all the parts that we can
if (xtr.GetAttribute("offset") != null)
diff --git a/SabreTools.Skippers/SkipperFiles/Atari7800.cs b/SabreTools.Skippers/SkipperFiles/Atari7800.cs
index bd3f4005..9f196194 100644
--- a/SabreTools.Skippers/SkipperFiles/Atari7800.cs
+++ b/SabreTools.Skippers/SkipperFiles/Atari7800.cs
@@ -11,17 +11,15 @@ namespace SabreTools.Skippers.SkipperFiles
public Atari7800()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x01,
Value = new byte[] { 0x41, 0x54, 0x41, 0x52, 0x49, 0x37, 0x38, 0x30, 0x30 },
Result = true,
};
- var rule2Test1 = new SkipperTest
+ var rule2Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x64,
Value = new byte[] { 0x41, 0x43, 0x54, 0x55, 0x41, 0x4C, 0x20, 0x43, 0x41, 0x52, 0x54, 0x20, 0x44, 0x41, 0x54, 0x41, 0x20, 0x53, 0x54, 0x41, 0x52, 0x54, 0x53, 0x20, 0x48, 0x45, 0x52, 0x45 },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/AtariLynx.cs b/SabreTools.Skippers/SkipperFiles/AtariLynx.cs
index 44b424a3..8399e9b6 100644
--- a/SabreTools.Skippers/SkipperFiles/AtariLynx.cs
+++ b/SabreTools.Skippers/SkipperFiles/AtariLynx.cs
@@ -11,17 +11,15 @@ namespace SabreTools.Skippers.SkipperFiles
public AtariLynx()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x4C, 0x59, 0x4E, 0x58 },
Result = true,
};
- var rule2Test1 = new SkipperTest
+ var rule2Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x06,
Value = new byte[] { 0x42, 0x53, 0x39 },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/CommodorePSID.cs b/SabreTools.Skippers/SkipperFiles/CommodorePSID.cs
index 2ddf741d..46ac4740 100644
--- a/SabreTools.Skippers/SkipperFiles/CommodorePSID.cs
+++ b/SabreTools.Skippers/SkipperFiles/CommodorePSID.cs
@@ -11,41 +11,36 @@ namespace SabreTools.Skippers.SkipperFiles
public CommodorePSID()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x50, 0x53, 0x49, 0x44, 0x00, 0x01, 0x00, 0x76 },
Result = true,
};
- var rule2Test1 = new SkipperTest
+ var rule2Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x50, 0x53, 0x49, 0x44, 0x00, 0x03, 0x00, 0x7c },
Result = true,
};
- var rule3Test1 = new SkipperTest
+ var rule3Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x50, 0x53, 0x49, 0x44, 0x00, 0x02, 0x00, 0x7c },
Result = true,
};
- var rule4Test1 = new SkipperTest
+ var rule4Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x50, 0x53, 0x49, 0x44, 0x00, 0x01, 0x00, 0x7c },
Result = true,
};
- var rule5Test1 = new SkipperTest
+ var rule5Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x52, 0x53, 0x49, 0x44, 0x00, 0x02, 0x00, 0x7c },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/NECPCEngine.cs b/SabreTools.Skippers/SkipperFiles/NECPCEngine.cs
index acfc72e4..a4e973fe 100644
--- a/SabreTools.Skippers/SkipperFiles/NECPCEngine.cs
+++ b/SabreTools.Skippers/SkipperFiles/NECPCEngine.cs
@@ -11,9 +11,8 @@ namespace SabreTools.Skippers.SkipperFiles
public NECPCEngine()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0x02 },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/Nintendo64.cs b/SabreTools.Skippers/SkipperFiles/Nintendo64.cs
index 2df5b23b..2178d9e3 100644
--- a/SabreTools.Skippers/SkipperFiles/Nintendo64.cs
+++ b/SabreTools.Skippers/SkipperFiles/Nintendo64.cs
@@ -11,25 +11,22 @@ namespace SabreTools.Skippers.SkipperFiles
public Nintendo64()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x80, 0x37, 0x12, 0x40 },
Result = true,
};
- var rule2Test1 = new SkipperTest
+ var rule2Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x37, 0x80, 0x40, 0x12 },
Result = true,
};
- var rule3Test1 = new SkipperTest
+ var rule3Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x40, 0x12, 0x37, 0x80 },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/NintendoEntertainmentSystem.cs b/SabreTools.Skippers/SkipperFiles/NintendoEntertainmentSystem.cs
index edb024fb..04ce1ebe 100644
--- a/SabreTools.Skippers/SkipperFiles/NintendoEntertainmentSystem.cs
+++ b/SabreTools.Skippers/SkipperFiles/NintendoEntertainmentSystem.cs
@@ -11,9 +11,8 @@ namespace SabreTools.Skippers.SkipperFiles
public NintendoEntertainmentSystem()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x4E, 0x45, 0x53, 0x1A },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/NintendoFamicomDiskSystem.cs b/SabreTools.Skippers/SkipperFiles/NintendoFamicomDiskSystem.cs
index ce25cd98..9708441c 100644
--- a/SabreTools.Skippers/SkipperFiles/NintendoFamicomDiskSystem.cs
+++ b/SabreTools.Skippers/SkipperFiles/NintendoFamicomDiskSystem.cs
@@ -11,33 +11,29 @@ namespace SabreTools.Skippers.SkipperFiles
public NintendoFamicomDiskSystem()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x46, 0x44, 0x53, 0x1A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Result = true,
};
- var rule2Test1 = new SkipperTest
+ var rule2Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x46, 0x44, 0x53, 0x1A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Result = true,
};
- var rule3Test1 = new SkipperTest
+ var rule3Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x46, 0x44, 0x53, 0x1A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Result = true,
};
- var rule4Test1 = new SkipperTest
+ var rule4Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x46, 0x44, 0x53, 0x1A, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/SuperFamicomSPC.cs b/SabreTools.Skippers/SkipperFiles/SuperFamicomSPC.cs
index f693d0d8..ffd677f3 100644
--- a/SabreTools.Skippers/SkipperFiles/SuperFamicomSPC.cs
+++ b/SabreTools.Skippers/SkipperFiles/SuperFamicomSPC.cs
@@ -11,9 +11,8 @@ namespace SabreTools.Skippers.SkipperFiles
public SuperFamicomSPC()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x00,
Value = new byte[] { 0x53, 0x4E, 0x45, 0x53, 0x2D, 0x53, 0x50, 0x43 },
Result = true,
diff --git a/SabreTools.Skippers/SkipperFiles/SuperNintendoEntertainmentSystem.cs b/SabreTools.Skippers/SkipperFiles/SuperNintendoEntertainmentSystem.cs
index e28d54f3..24ea94ce 100644
--- a/SabreTools.Skippers/SkipperFiles/SuperNintendoEntertainmentSystem.cs
+++ b/SabreTools.Skippers/SkipperFiles/SuperNintendoEntertainmentSystem.cs
@@ -11,25 +11,22 @@ namespace SabreTools.Skippers.SkipperFiles
public SuperNintendoEntertainmentSystem()
{
// Create tests
- var rule1Test1 = new SkipperTest
+ var rule1Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x16,
Value = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Result = true,
};
- var rule2Test1 = new SkipperTest
+ var rule2Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x16,
Value = new byte[] { 0xAA, 0xBB, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
Result = true,
};
- var rule3Test1 = new SkipperTest
+ var rule3Test1 = new DataSkipperTest
{
- Type = HeaderSkipTest.Data,
Offset = 0x16,
Value = new byte[] { 0x53, 0x55, 0x50, 0x45, 0x52, 0x55, 0x46, 0x4F },
Result = true,
diff --git a/SabreTools.Skippers/SkipperRule.cs b/SabreTools.Skippers/SkipperRule.cs
index a845d686..0187e1be 100644
--- a/SabreTools.Skippers/SkipperRule.cs
+++ b/SabreTools.Skippers/SkipperRule.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Xml.Serialization;
using SabreTools.Logging;
@@ -13,26 +14,36 @@ namespace SabreTools.Skippers
///
/// Starting offset for applying rule
///
+ [XmlAttribute("start_offset")]
public long? StartOffset { get; set; } // null is EOF
///
/// Ending offset for applying rule
///
+ [XmlAttribute("end_offset")]
public long? EndOffset { get; set; } // null if EOF
///
/// Byte manipulation operation
///
+ [XmlAttribute("operation")]
public HeaderSkipOperation Operation { get; set; }
///
/// List of matching tests in a rule
///
+ [XmlArray]
+ [XmlArrayItem("data")]
+ [XmlArrayItem("or")]
+ [XmlArrayItem("xor")]
+ [XmlArrayItem("and")]
+ [XmlArrayItem("file")]
public List Tests { get; set; }
///
/// Filename the skipper rule lives in
///
+ [XmlIgnore]
public string SourceFile { get; set; }
#endregion
diff --git a/SabreTools.Skippers/SkipperTest.cs b/SabreTools.Skippers/SkipperTest.cs
index b6510fa9..25fa472e 100644
--- a/SabreTools.Skippers/SkipperTest.cs
+++ b/SabreTools.Skippers/SkipperTest.cs
@@ -1,49 +1,52 @@
using System;
using System.IO;
+using System.Xml;
+using System.Xml.Serialization;
namespace SabreTools.Skippers
{
///
/// Individual test that applies to a SkipperRule
///
- public class SkipperTest
+ public abstract class SkipperTest
{
#region Fields
- ///
- /// Type of test to be run
- ///
- public HeaderSkipTest Type { get; set; }
-
///
/// File offset to run the test
///
/// null is EOF
+ [XmlAttribute("offset")]
public long? Offset { get; set; }
///
/// Static value to be checked at the offset
///
+ [XmlAttribute("value")]
public byte[] Value { get; set; }
///
/// Determines whether a pass or failure is expected
///
+ [XmlAttribute("result")]
public bool Result { get; set; }
///
/// Byte mask to be applied to the tested bytes
///
+ [XmlAttribute("mask")]
public byte[] Mask { get; set; }
///
/// Expected size of the input byte array, used with the Operator
///
+ [XmlAttribute("size")]
public long? Size { get; set; } // null is PO2, "power of 2" filesize
///
/// Expected range value for the input byte array size, used with Size
///
+ [XmlAttribute("operator")]
public HeaderSkipTestFileOperator Operator { get; set; }
#endregion
@@ -53,27 +56,50 @@ namespace SabreTools.Skippers
///
/// Stream to check rule against
/// The Stream is assumed to be in the proper position for a given test
- public bool Passes(Stream input)
- {
- return Type switch
- {
- HeaderSkipTest.And => CheckAnd(input),
- HeaderSkipTest.Data => CheckData(input),
- HeaderSkipTest.File => CheckFile(input),
- HeaderSkipTest.Or => CheckOr(input),
- HeaderSkipTest.Xor => CheckXor(input),
- _ => true,
- };
- }
+ public abstract bool Passes(Stream input);
#region Checking Helpers
///
- /// Run an And test against an input stream
+ /// Seek an input stream based on the test value
///
- /// Stream to check rule against
- /// True if the stream passed, false otherwise
- private bool CheckAnd(Stream input)
+ /// Stream to seek
+ /// True if the stream could seek, false on error
+ protected bool Seek(Stream input)
+ {
+ try
+ {
+ // Null offset means EOF
+ if (Offset == null)
+ input.Seek(0, SeekOrigin.End);
+
+ // Positive offset means from beginning
+ else if (Offset >= 0 && Offset <= input.Length)
+ input.Seek(Offset.Value, SeekOrigin.Begin);
+
+ // Negative offset means from end
+ else if (Offset < 0 && Math.Abs(Offset.Value) <= input.Length)
+ input.Seek(Offset.Value, SeekOrigin.End);
+
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ #endregion
+ }
+
+ ///
+ /// Skipper test using AND
+ ///
+ [XmlRoot("and")]
+ public class AndSkipperTest : SkipperTest
+ {
+ ///
+ public override bool Passes(Stream input)
{
// First seek to the correct position
Seek(input);
@@ -109,13 +135,16 @@ namespace SabreTools.Skippers
// Return if the expected and actual results match
return result == Result;
}
+ }
- ///
- /// Run a Data test against an input stream
- ///
- /// Stream to check rule against
- /// True if the stream passed, false otherwise
- private bool CheckData(Stream input)
+ ///
+ /// Skipper test using DATA
+ ///
+ [XmlRoot("data")]
+ public class DataSkipperTest : SkipperTest
+ {
+ ///
+ public override bool Passes(Stream input)
{
// First seek to the correct position
if (!Seek(input))
@@ -143,13 +172,16 @@ namespace SabreTools.Skippers
// Return if the expected and actual results match
return result == Result;
}
+ }
- ///
- /// Run a File test against an input stream
- ///
- /// Stream to check rule against
- /// True if the stream passed, false otherwise
- private bool CheckFile(Stream input)
+ ///
+ /// Skipper test using FILE
+ ///
+ [XmlRoot("file")]
+ public class FileSkipperTest : SkipperTest
+ {
+ ///
+ public override bool Passes(Stream input)
{
// First get the file size from stream
long size = input.Length;
@@ -177,13 +209,16 @@ namespace SabreTools.Skippers
// Return if the expected and actual results match
return result == Result;
}
+ }
- ///
- /// Run an Or test against an input stream
- ///
- /// Stream to check rule against
- /// True if the stream passed, false otherwise
- private bool CheckOr(Stream input)
+ ///
+ /// Skipper test using OR
+ ///
+ [XmlRoot("or")]
+ public class OrSkipperTest : SkipperTest
+ {
+ ///
+ public override bool Passes(Stream input)
{
// First seek to the correct position
Seek(input);
@@ -219,13 +254,16 @@ namespace SabreTools.Skippers
// Return if the expected and actual results match
return result == Result;
}
+ }
- ///
- /// Run an Xor test against an input stream
- ///
- /// Stream to check rule against
- /// True if the stream passed, false otherwise
- private bool CheckXor(Stream input)
+ ///
+ /// Skipper test using XOR
+ ///
+ [XmlRoot("xor")]
+ public class XorSkipperTest : SkipperTest
+ {
+ ///
+ public override bool Passes(Stream input)
{
// First seek to the correct position
Seek(input);
@@ -261,36 +299,5 @@ namespace SabreTools.Skippers
// Return if the expected and actual results match
return result == Result;
}
-
- ///
- /// Seek an input stream based on the test value
- ///
- /// Stream to seek
- /// True if the stream could seek, false on error
- private bool Seek(Stream input)
- {
- try
- {
- // Null offset means EOF
- if (Offset == null)
- input.Seek(0, SeekOrigin.End);
-
- // Positive offset means from beginning
- else if (Offset >= 0 && Offset <= input.Length)
- input.Seek(Offset.Value, SeekOrigin.Begin);
-
- // Negative offset means from end
- else if (Offset < 0 && Math.Abs(Offset.Value) <= input.Length)
- input.Seek(Offset.Value, SeekOrigin.End);
-
- return true;
- }
- catch
- {
- return false;
- }
- }
-
- #endregion
}
}
\ No newline at end of file