using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace SabreTools.Helper
{
///
/// Contains all remappings of known import classes
///
public class Remapping
{
// Remapping classes represented by dictionaries (from, to)
public static Dictionary Good = new Dictionary();
public static Dictionary MAME = new Dictionary();
public static Dictionary MaybeIntro = new Dictionary();
public static Dictionary NoIntro = new Dictionary();
public static Dictionary NonGood = new Dictionary();
public static Dictionary Redump = new Dictionary();
public static Dictionary TOSEC = new Dictionary();
public static Dictionary TruRip = new Dictionary();
// Header skip classes represented by dictionaries (header, size)
public static Dictionary A7800 = new Dictionary();
public static Dictionary FDS = new Dictionary();
public static Dictionary Lynx = new Dictionary();
//public static Dictionary N64 = new Dictionary();
public static Dictionary NES = new Dictionary();
public static Dictionary PCE = new Dictionary();
public static Dictionary PSID = new Dictionary();
public static Dictionary SNES = new Dictionary();
public static Dictionary SPC = new Dictionary();
///
/// Create all remappings to be used by the program
///
public static void CreateRemappings()
{
// Create array of dictionary names
string[] remappings =
{
"Good", "MAME", "MaybeIntro", "NoIntro", "NonGood", "Redump", "TOSEC", "TruRip",
};
// Loop through and add all remappings
foreach (string remapping in remappings)
{
RemappingHelper(remapping);
}
}
///
/// Create a remapping from XML
///
/// Name of the mapping to be populated
private static void RemappingHelper(string mapping)
{
// Read in remapping from file
XmlDocument doc = new XmlDocument();
try
{
doc.LoadXml(File.ReadAllText("Mappings/" + mapping + ".xml"));
}
catch (XmlException ex)
{
Console.WriteLine(mapping + " remappings could not be loaded! " + ex.ToString());
return;
}
// Get the mappings parent node
XmlNode node = doc.FirstChild;
while (node.Name != "mappings")
{
node = node.NextSibling;
}
// If the node is empty, just return so it doesn't crash
if (!node.HasChildNodes)
{
return;
}
// Get the first mapping node
node = node.FirstChild;
while (node.NodeType != XmlNodeType.Element && node.Name != "mapping")
{
node = node.NextSibling;
}
// Now read in the mappings
while (node != null && node.Name == "mapping")
{
switch (mapping)
{
case "Good":
Good.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "MAME":
MAME.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "MaybeIntro":
MaybeIntro.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "NoIntro":
NoIntro.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "NonGood":
NonGood.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "Redump":
Redump.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "TOSEC":
TOSEC.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
case "TruRip":
TruRip.Add(node.Attributes["from"].Value, node.Attributes["to"].Value);
break;
}
// Get the next node and skip over anything that's not an element
node = node.NextSibling;
if (node == null)
{
break;
}
while (node.NodeType != XmlNodeType.Element && node.Name != "mapping")
{
node = node.NextSibling;
}
}
}
///
/// Create all header mappings to be used by the program
///
public static void CreateHeaderSkips()
{
// Create array of dictionary names
string[] skippers =
{
"a7800", "fds", "lynx", /* "n64", */ "nes", "pce", "psid", "snes", "spc",
};
// Loop through and add all remappings
foreach (string skipper in skippers)
{
SkipperHelper(skipper);
}
}
///
/// Create a remapping from XML
///
/// Name of the header skipper to be populated
private static void SkipperHelper(string skipper)
{
// Read in remapping from file
XmlDocument doc = new XmlDocument();
try
{
doc.LoadXml(File.ReadAllText("Skippers/" + skipper + ".xml"));
}
catch (XmlException ex)
{
Console.WriteLine(skipper + " header skippers could not be loaded! " + ex.ToString());
return;
}
// Get the detector parent node
XmlNode node = doc.FirstChild;
while (node.Name != "detector")
{
node = node.NextSibling;
}
// Get the first rule node
node = node.SelectSingleNode("rule");
// Now read in the rules
while (node != null && node.Name == "rule")
{
// Size is the offset for the actual game data
int size = (node.Attributes["start_offset"] != null ? Convert.ToInt32(node.Attributes["start_offset"].Value, 16) : 0);
// Each rule set can have more than one data rule. We can't really use multiples right now
if (node.SelectNodes("data") != null)
{
foreach (XmlNode child in node.SelectNodes("data"))
{
// Add an offset to the match if one exists
string header = (child.Attributes["offset"] != null && child.Attributes["offset"].Value != "0" ? "^.{" + (Convert.ToInt32(child.Attributes["offset"].Value, 16) * 2) + "}" : "^");
header += child.Attributes["value"].Value;
// Now add the header and value to the appropriate skipper dictionary
switch (skipper)
{
case "a7800":
A7800.Add(header, size);
break;
case "fds":
FDS.Add(header, size);
break;
case "lynx":
Lynx.Add(header, size);
break;
/*
case "n64":
N64.Add(header, size);
break;
*/
case "nes":
NES.Add(header, size);
break;
case "pce":
PCE.Add(header, size);
break;
case "psid":
PSID.Add(header, size);
break;
case "snes":
SNES.Add(header, size);
break;
case "spc":
SPC.Add(header, size);
break;
}
}
}
// Get the next node and skip over anything that's not an element
node = node.NextSibling;
if (node == null)
{
break;
}
while (node.NodeType != XmlNodeType.Element && node.Name != "rule")
{
node = node.NextSibling;
}
}
}
}
}