Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-10-10 10:17:00 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-10-10 10:17:00 +0300
commitc69fe813667edb0c3161c00ec3adfddaced2e375 (patch)
tree7ae9e32130722cb5927cbdc52de9480a95cde51f /GameGenie
parentd54bdf45f08e0772eb53de7ea2e18b69924804b2 (diff)
Added GameGenie for SNES but it glitchy and commented out
Diffstat (limited to 'GameGenie')
-rw-r--r--GameGenie/GameGenieDataBase.cs255
-rw-r--r--GameGenie/GameGenieFormatException.cs17
-rw-r--r--GameGenie/GameGenieNotFoundException.cs17
-rw-r--r--GameGenie/GameGeniePatcherNes.cs103
-rw-r--r--GameGenie/GameGeniePatcherSnes.cs72
5 files changed, 464 insertions, 0 deletions
diff --git a/GameGenie/GameGenieDataBase.cs b/GameGenie/GameGenieDataBase.cs
new file mode 100644
index 00000000..7531807b
--- /dev/null
+++ b/GameGenie/GameGenieDataBase.cs
@@ -0,0 +1,255 @@
+using com.clusterrr.Famicom;
+using com.clusterrr.hakchi_gui.Properties;
+using System.Collections.Generic;
+using System.IO;
+using System.Windows.Forms;
+using System.Xml;
+
+namespace com.clusterrr.hakchi_gui
+{
+ class GameGenieCode
+ {
+ public delegate void ChangedEvent(GameGenieCode e);
+ public event ChangedEvent Changed;
+
+ private string FCode = "";
+ private string FDescription = "";
+ private string FOldCode;
+ private string FOldDescription;
+
+ public string Code
+ {
+ get { return FCode; }
+ set
+ {
+ if (FCode != value)
+ {
+ FOldCode = FCode;
+ FCode = value;
+ if ((FOldCode != "") && (Changed != null))
+ Changed(this);
+ }
+ }
+ }
+ public string Description
+ {
+ get { return FDescription; }
+ set
+ {
+ if (FDescription != value)
+ {
+ FOldDescription = FDescription;
+ FDescription = value;
+ if ((FOldDescription != "") && (Changed != null))
+ Changed(this);
+ }
+ }
+ }
+ public string OldCode { get { return FOldCode; } }
+ public string OldDescription { get { return FOldDescription; } }
+
+ public override string ToString()
+ {
+ return Description;
+ }
+
+ public GameGenieCode(string ACode, string ADescription)
+ {
+ Code = ACode;
+ Description = ADescription;
+ }
+ }
+
+ class GameGenieDataBase
+ {
+ private XmlDocument FXml = new XmlDocument();
+ private XmlNode FGameNode = null;
+ private List<GameGenieCode> FGameCodes = null;
+ private string originalDatabasePath = Path.Combine(Path.Combine(Program.BaseDirectoryInternal, "data"), "GameGenieDB.xml");
+ private string userDatabasePath = Path.Combine(Path.Combine(Program.BaseDirectoryExternal, ConfigIni.ConfigDir), "GameGenieDB.xml");
+ private NesMiniApplication FGame = null;
+ private bool FModified = false;
+
+ private XmlNode GameNode
+ {
+ get
+ {
+ if (FGameNode == null)
+ {
+ FGameNode = FXml.SelectSingleNode(string.Format("/database/game[@code='{0}']", FGame.Code));
+
+ if (FGameNode == null)
+ {
+ string lGamesDir = Path.Combine(Program.BaseDirectoryExternal, "games");
+ NesFile lGame = new NesFile(Path.Combine(Path.Combine(lGamesDir, FGame.Code), FGame.Code + ".nes"));
+ XmlAttribute lXmlAttribute;
+
+ FGameNode = FXml.CreateElement("game");
+ FXml.DocumentElement.AppendChild(FGameNode);
+
+ lXmlAttribute = FXml.CreateAttribute("code");
+ lXmlAttribute.Value = FGame.Code;
+ FGameNode.Attributes.Append(lXmlAttribute);
+
+ lXmlAttribute = FXml.CreateAttribute("name");
+ lXmlAttribute.Value = FGame.Name;
+ FGameNode.Attributes.Append(lXmlAttribute);
+
+ lXmlAttribute = FXml.CreateAttribute("crc");
+ lXmlAttribute.Value = lGame.CRC32.ToString("X");
+ FGameNode.Attributes.Append(lXmlAttribute);
+ }
+ }
+ return FGameNode;
+ }
+ }
+
+ public List<GameGenieCode> GameCodes
+ {
+ get
+ {
+ if (FGameCodes == null)
+ {
+ FGameCodes = new List<GameGenieCode>();
+ XmlNodeList lCodes = FXml.SelectNodes(string.Format("/database/game[@code='{0}']//gamegenie", FGame.Code));
+ foreach (XmlNode lCurNode in lCodes)
+ {
+ GameGenieCode lCurCode = new GameGenieCode(lCurNode.Attributes.GetNamedItem("code").Value, lCurNode.Attributes.GetNamedItem("description").Value);
+ FGameCodes.Add(lCurCode);
+ }
+ }
+ return FGameCodes;
+ }
+ }
+
+ public bool Modified
+ {
+ get
+ {
+ return FModified;
+ }
+
+ }
+
+ public GameGenieDataBase(NesMiniApplication AGame)
+ {
+ //DataBasePath = Path.Combine(Path.Combine(Program.BaseDirectoryInternal, "data"), "GameGenieDB.xml");
+ FGame = AGame;
+ //FDBName = DataBasePath;
+ if (File.Exists(userDatabasePath))
+ FXml.Load(userDatabasePath);
+ else if (File.Exists(originalDatabasePath))
+ FXml.Load(originalDatabasePath);
+ else
+ FXml.AppendChild(FXml.CreateElement("database"));
+ }
+
+ public void AddCode(GameGenieCode ACode)
+ {
+ FModified = true;
+
+ XmlNode lCodeNode = FXml.CreateElement("gamegenie");
+ GameNode.AppendChild(lCodeNode);
+
+ XmlAttribute lAttribute;
+
+ lAttribute = FXml.CreateAttribute("code");
+ lAttribute.Value = ACode.Code.ToUpper().Trim();
+ lCodeNode.Attributes.Append(lAttribute);
+
+ lAttribute = FXml.CreateAttribute("description");
+ lAttribute.Value = ACode.Description;
+ lCodeNode.Attributes.Append(lAttribute);
+
+ if (FGameCodes == null)
+ FGameCodes = new List<GameGenieCode>();
+
+ FGameCodes.Add(ACode);
+ }
+
+ public void ModifyCode(GameGenieCode ACode)
+ {
+ XmlNode lCurCode = GameNode.SelectSingleNode(string.Format("gamegenie[@code='{0}']", ACode.OldCode.ToUpper().Trim()));
+ if (lCurCode != null)
+ {
+ lCurCode.Attributes.GetNamedItem("code").Value = ACode.Code.ToUpper().Trim();
+ lCurCode.Attributes.GetNamedItem("description").Value = ACode.Description;
+ FModified = true;
+ }
+ }
+
+ public void DeleteCode(GameGenieCode ACode)
+ {
+ XmlNode lCurCode = GameNode.SelectSingleNode(string.Format("gamegenie[@code='{0}']", ACode.Code.ToUpper().Trim()));
+ if (lCurCode != null)
+ lCurCode.ParentNode.RemoveChild(lCurCode);
+ FGameCodes.Remove(ACode);
+ FModified = true;
+ }
+
+ public void ImportCodes(string AFileName, bool AQuiet = false)
+ {
+ if (File.Exists(AFileName))
+ {
+ XmlDocument lXml = new XmlDocument();
+ XmlNodeList lCodes = null;
+ XmlNode lCodeNode = null;
+ XmlAttribute lAttribute = null;
+
+ lXml.Load(AFileName);
+ lCodes = lXml.SelectNodes("//genie/..");
+
+ FModified = true;
+
+ XmlNode lDeleteNode = GameNode.FirstChild;
+ while (lDeleteNode != null)
+ {
+ GameNode.RemoveChild(GameNode.FirstChild);
+ lDeleteNode = GameNode.FirstChild;
+ }
+ GameCodes.Clear();
+
+ string lGameFileName = Path.Combine(Path.Combine(Path.Combine(Program.BaseDirectoryExternal, "games"), FGame.Code), FGame.Code + ".nes");
+ foreach (XmlNode lCurCode in lCodes)
+ {
+ NesFile lGame = new NesFile(lGameFileName);
+ try
+ {
+ lGame.PRG = GameGeniePatcherNes.Patch(lGame.PRG, lCurCode["genie"].InnerText);
+
+ lCodeNode = FXml.CreateElement("gamegenie");
+ GameNode.AppendChild(lCodeNode);
+
+ lAttribute = FXml.CreateAttribute("code");
+ lAttribute.Value = lCurCode["genie"].InnerText.ToUpper().Trim();
+ lCodeNode.Attributes.Append(lAttribute);
+
+ lAttribute = FXml.CreateAttribute("description");
+ lAttribute.Value = lCurCode["description"].InnerText;
+ lCodeNode.Attributes.Append(lAttribute);
+
+ GameCodes.Add(new GameGenieCode(lCurCode["genie"].InnerText.ToUpper().Trim(), lCurCode["description"].InnerText));
+ }
+ catch (GameGenieFormatException)
+ {
+ if (!AQuiet)
+ MessageBox.Show(string.Format(Resources.GameGenieFormatError, lCurCode["genie"].InnerText, FGame.Name), Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ catch (GameGenieNotFoundException)
+ {
+ if (!AQuiet)
+ MessageBox.Show(string.Format(Resources.GameGenieNotFound, lCurCode["genie"].InnerText, FGame.Name), Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+ }
+
+ public void Save()
+ {
+ if (GameCodes.Count == 0)
+ GameNode.ParentNode.RemoveChild(GameNode);
+ Directory.CreateDirectory(Path.GetDirectoryName(userDatabasePath));
+ FXml.Save(userDatabasePath);
+ }
+ }
+}
diff --git a/GameGenie/GameGenieFormatException.cs b/GameGenie/GameGenieFormatException.cs
new file mode 100644
index 00000000..baec65b9
--- /dev/null
+++ b/GameGenie/GameGenieFormatException.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace com.clusterrr.hakchi_gui
+{
+ public class GameGenieFormatException : Exception
+ {
+ public readonly string Code;
+ public GameGenieFormatException(string code)
+ : base(string.Format("Invalid code \"{0}\"", code))
+ {
+ Code = code;
+ }
+ }
+}
diff --git a/GameGenie/GameGenieNotFoundException.cs b/GameGenie/GameGenieNotFoundException.cs
new file mode 100644
index 00000000..8a879c58
--- /dev/null
+++ b/GameGenie/GameGenieNotFoundException.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace com.clusterrr.hakchi_gui
+{
+ public class GameGenieNotFoundException : Exception
+ {
+ public readonly string Code;
+ public GameGenieNotFoundException(string code)
+ : base(string.Format("Invalid code \"{0}\"", code))
+ {
+ Code = code;
+ }
+ }
+}
diff --git a/GameGenie/GameGeniePatcherNes.cs b/GameGenie/GameGeniePatcherNes.cs
new file mode 100644
index 00000000..4fa9dba5
--- /dev/null
+++ b/GameGenie/GameGeniePatcherNes.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace com.clusterrr.hakchi_gui
+{
+ public static class GameGeniePatcherNes
+ {
+ public static byte[] Patch(byte[] data, string code)
+ {
+ code = code.ToUpper().Trim();
+ if (string.IsNullOrEmpty(code)) return data;
+ var result = (byte[])data.Clone();
+
+ var binaryCode = new StringBuilder(code);
+ foreach (var l in letterValues.Keys)
+ binaryCode.Replace(l.ToString(), letterValues[l]);
+
+ byte value, compare;
+ UInt16 address;
+
+ if (binaryCode.Length == 24)
+ {
+ if (binaryCode[8] != '0') throw new GameGenieFormatException(code);
+
+ try
+ {
+ value = Convert.ToByte(new string(new char[] { binaryCode[0], binaryCode[5], binaryCode[6], binaryCode[7], binaryCode[20], binaryCode[1], binaryCode[2], binaryCode[3] }), 2);
+ address = Convert.ToUInt16(new string(new char[] { binaryCode[13], binaryCode[14], binaryCode[15], binaryCode[16], binaryCode[21], binaryCode[22], binaryCode[23], binaryCode[4], binaryCode[9], binaryCode[10], binaryCode[11], binaryCode[12], binaryCode[17], binaryCode[18], binaryCode[19] }), 2);
+ }
+ catch
+ {
+ throw new GameGenieFormatException(code);
+ }
+
+ if (result.Length <= 0x8000)
+ {
+ result[address % result.Length] = value;
+ }
+ else
+ {
+ int pos = address % 0x2000;
+ while (pos < result.Length)
+ {
+ result[pos] = value;
+ pos += 0x2000;
+ }
+ }
+ }
+ else if (binaryCode.Length == 32)
+ {
+ if (binaryCode[8] != '1') throw new GameGenieFormatException(code);
+
+ try
+ {
+ value = Convert.ToByte(new string(new char[] { binaryCode[0], binaryCode[5], binaryCode[6], binaryCode[7], binaryCode[28], binaryCode[1], binaryCode[2], binaryCode[3] }), 2);
+ address = Convert.ToUInt16(new string(new char[] { binaryCode[13], binaryCode[14], binaryCode[15], binaryCode[16], binaryCode[21], binaryCode[22], binaryCode[23], binaryCode[4], binaryCode[9], binaryCode[10], binaryCode[11], binaryCode[12], binaryCode[17], binaryCode[18], binaryCode[19] }), 2);
+ compare = Convert.ToByte(new string(new char[] { binaryCode[24], binaryCode[29], binaryCode[30], binaryCode[31], binaryCode[20], binaryCode[25], binaryCode[26], binaryCode[27] }), 2);
+ }
+ catch
+ {
+ throw new GameGenieFormatException(code);
+ }
+
+ bool replaced = false;
+ int pos = address % 0x2000;
+ while (pos < result.Length)
+ {
+ if (result[pos] == compare)
+ {
+ result[pos] = value;
+ replaced = true;
+ }
+ pos += 0x2000;
+ }
+ if (!replaced) throw new GameGenieNotFoundException(code);
+ }
+ else throw new GameGenieFormatException(code);
+
+ return result;
+ }
+
+ static Dictionary<char, string> letterValues = new Dictionary<char, string>()
+ {
+ { 'A', "0000" },
+ { 'P', "0001" },
+ { 'Z', "0010" },
+ { 'L', "0011" },
+ { 'G', "0100" },
+ { 'I', "0101" },
+ { 'T', "0110" },
+ { 'Y', "0111" },
+ { 'E', "1000" },
+ { 'O', "1001" },
+ { 'X', "1010" },
+ { 'U', "1011" },
+ { 'K', "1100" },
+ { 'S', "1101" },
+ { 'V', "1110" },
+ { 'N', "1111" }
+ };
+ }
+}
diff --git a/GameGenie/GameGeniePatcherSnes.cs b/GameGenie/GameGeniePatcherSnes.cs
new file mode 100644
index 00000000..85f7c1af
--- /dev/null
+++ b/GameGenie/GameGeniePatcherSnes.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace com.clusterrr.hakchi_gui
+{
+ public static class GameGeniePatcherSnes
+ {
+ public static byte[] Patch(byte[] data, string code)
+ {
+ code = code.ToUpper().Trim();
+ if (string.IsNullOrEmpty(code)) return data;
+ if (code.Length != 9 || code[4] != '-')
+ throw new GameGenieFormatException(code);
+ code = Regex.Replace(code, "[^0-9A-F]", "");
+ if (code.Length != 8)
+ throw new GameGenieFormatException(code);
+
+ byte value = Convert.ToByte(code.Substring(0, 2), 16);
+ code = code.Substring(2);
+
+ var binaryCode = new StringBuilder();
+ foreach (char c in code)
+ binaryCode.Append(letterValues[c]);
+ var decoded = new StringBuilder(new string(' ', binaryCode.Length));
+ for (int i = 0; i < binaryCode.Length; i++)
+ {
+ var c = codeSeq[i];
+ var pos = clearSeq.IndexOf(c);
+ decoded[pos] = binaryCode[i];
+ }
+
+ SnesGame.SnesRomType romType;
+ string gameTitle;
+ SnesGame.GetCorrectHeader(data, out romType, out gameTitle);
+
+ UInt32 address = (Convert.ToUInt32(decoded.ToString(), 2)) & 0x3FFFFF;
+ if (romType == SnesGame.SnesRomType.LoRom)
+ address = address & 0x3FFFF;
+
+ var result = (byte[])data.Clone();
+ if (address >= result.Length)
+ throw new GameGenieFormatException(code);
+ result[address] = value;
+ return result;
+ }
+
+ static Dictionary<char, string> letterValues = new Dictionary<char, string>()
+ {
+ { 'D', "0000" },
+ { 'F', "0001" },
+ { '4', "0010" },
+ { '7', "0011" },
+ { '0', "0100" },
+ { '9', "0101" },
+ { '1', "0110" },
+ { '5', "0111" },
+ { '6', "1000" },
+ { 'B', "1001" },
+ { 'C', "1010" },
+ { '8', "1011" },
+ { 'A', "1100" },
+ { '2', "1101" },
+ { '3', "1110" },
+ { 'E', "1111" }
+ };
+
+ const string codeSeq = "ijklqrstopabcduvwxefghmn";
+ const string clearSeq = "abcdefghijklmnopqrstuvwx";
+ }
+}