From b3166094ca2470da4a427f64ed6d4ef3c6def269 Mon Sep 17 00:00:00 2001 From: hegyak Date: Mon, 16 Nov 2015 06:49:00 -0800 Subject: [PATCH] Added PSX and Saturn GameShark Code Support. --- BizHawk.Client.EmuHawk/tools/GameShark.cs | 625 ++++++++++++++-------- 1 file changed, 400 insertions(+), 225 deletions(-) diff --git a/BizHawk.Client.EmuHawk/tools/GameShark.cs b/BizHawk.Client.EmuHawk/tools/GameShark.cs index 044ca687a6..9a051cb7df 100644 --- a/BizHawk.Client.EmuHawk/tools/GameShark.cs +++ b/BizHawk.Client.EmuHawk/tools/GameShark.cs @@ -6,7 +6,7 @@ using System.Globalization; namespace BizHawk.Client.EmuHawk { - [ToolAttributes(released: true, supportedSystems: new[] { "GB", "N64" })] + [ToolAttributes(released: true, supportedSystems: new[] { "GB", "N64", "PSX", "SAT" })] public partial class GameShark : Form, IToolForm, IToolFormAutoConfig { //We are using Memory Domains, so we NEED this. @@ -47,247 +47,422 @@ namespace BizHawk.Client.EmuHawk } + //My Variables + string parseString = null; + string RAMAddress = null; + string RAMValue = null; + int byteSize = 0; + string testo = null; private void btnGo_Click(object sender, EventArgs e) { - string parseString = null; - string RAMAddress = null; - string RAMValue = null; - //What System are we running? + //Reset Variables + parseString = null; + RAMAddress = null; + RAMValue = null; + byteSize = 0; //We want Upper Case. - int byteSize = 0; txtCheat.Text = txtCheat.Text.ToUpper(); - string testo = txtCheat.Text.Remove(2, 11); + //This determies what kind of Code we have + testo = txtCheat.Text.Remove(2, 11); + //What System are we running? switch (Emulator.SystemId) { case "GB": - //This Check ONLY applies to GB/GBC codes. - if (txtCheat.Text.Length != 8) - { - MessageBox.Show("All GameShark Codes need to be Eight characters in Length", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - //Let's make sure we start with zero. We have a good length, and a good starting zero, we should be good. Hopefully. - switch (testo) - { - //Is this 00 or 01? - case "00": - case "01": - //Good. - break; - default: - //No. - MessageBox.Show("All GameShark Codes for GameBoy need to start with 00 or 01", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - //Sample Input for GB/GBC: - //010FF6C1 - //Becomes: - //Address C1F6 - //Value 0F - - parseString = txtCheat.Text.Remove(0, 2); - //Now we need to break it down a little more. - RAMValue = parseString.Remove(2, 4); - parseString = parseString.Remove(0, 2); - //The issue is Endian... Time to get ultra clever. And Regret it. - //First Half - RAMAddress = parseString.Remove(0, 2); - RAMAddress = RAMAddress + parseString.Remove(2, 2); - //We now have our values. - //This part, is annoying... - try - { - //A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works. - //System Bus Domain, The Address to Watch, Byte size (Byte), Hex Display, Description. Not Big Endian. - var watch = Watch.GenerateWatch(MemoryDomains["System Bus"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Byte, Watch.DisplayType.Hex, txtDescription.Text, false); - //Take Watch, Add our Value we want, and it should be active when addded? - Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); - //Clear old Inputs - txtCheat.Clear(); - txtDescription.Clear(); - } - //Someone broke the world? - catch (Exception ex) - { - MessageBox.Show("An Error occured: " + ex.GetType().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - break; + GB(); + break; case "N64": - //These codes, more or less work without Needing much work. - if (txtCheat.Text.Contains(" ") == false) - { - MessageBox.Show("All N64 GameShark Codes need to contain a space after the eighth character", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - if (txtCheat.Text.Length != 13) - { - MessageBox.Show("All N64 GameShark Codes need to be 13 characters in length.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - //We need to determine what kind of cheat this is. - //I need to determine if this is a Byte or Word. - switch (testo) - { - //80 and 81 are the most common, so let's not get all worried. - case "80": - //Byte - byteSize = 8; - break; - case "81": - //Word - byteSize = 16; - break; - //Case A0 and A1 means "Write to Uncached address. - case "A0": - //Byte - byteSize = 8; - break; - case "A1": - //Word - byteSize = 16; - break; - //Do we support the GameShark Button? No. But these cheats, can be toggled. Which "Counts" - // Consequences be damned! - case "88": - //Byte - byteSize = 8; - break; - case "89": - //Word - byteSize = 16; - break; - //These are compare Address X to Value Y, then apply Value B to Address A - //This is not supported, yet - //TODO: When BizHawk supports a compare RAM Address's value is true then apply a value to another address, make it a thing. - case "D0": - //Byte - case "D1": - //Word - case "D2": - //Byte - case "D3": - //Word - MessageBox.Show("The code you entered is not supported by BizHawk.", "Emulator Error", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - //These codes are for Disabling the Expansion Pak. that's a bad thing? Assuming bad codes, until told otherwise. - case "EE": - case "DD": - case "CC": - MessageBox.Show("The code you entered is for Disabling the Expansion Pak. This is not allowed by this tool.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - //Enable Code - //Not Necessary? Think so? - case "DE": - //Single Write ON-Boot code. - //Not Necessary? Think so? - case "F0": - case "F1": - case "2A": - MessageBox.Show("The code you entered is not needed by Bizhawk.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - //TODO: Make Patch Code (5000XXYY) work. - case "50": - //Word? - MessageBox.Show("The code you entered is not supported by this tool. Please Submit the Game's Name, Cheat/Code and Purpose to the BizHawk forums.", "Tool Error", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - //I hope this isn't a thing. - default: - MessageBox.Show("The GameShark code entered is not a recognized format.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - //Leave this Method, before someone gets hurt. - return; - //break; - } - //Big Endian is USED constantly here. The question is, how do we determine if it's one or two bytes? - //Now to get clever. - //Sample Input for N64: - //8133B21E 08FF - //Becomes: - //Address 33B21E - //Value 08FF - - //Note, 8XXXXXXX 00YY - //Is Byte, not Word - //Remove the 8X Octect - parseString = txtCheat.Text.Remove(0, 2); - //Get RAM Address - RAMAddress = parseString.Remove(6, 5); - //Get RAM Value - RAMValue = parseString.Remove(0, 7); - - try - { - //A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works. - //System Bus Domain, The Address to Watch, Byte size (Word), Hex Display, Description. Big Endian. - if (byteSize == 8) - { - //We have a Word (Double Byte) sized Value - var watch = Watch.GenerateWatch(MemoryDomains["RDRAM"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Word, Watch.DisplayType.Hex, txtDescription.Text, true); - //Take Watch, Add our Value we want, and it should be active when addded? - Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); - } - if (byteSize == 16) - { - //We have a Byte sized value - var watch = Watch.GenerateWatch(MemoryDomains["RDRAM"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Byte, Watch.DisplayType.Hex, txtDescription.Text, true); - //Take Watch, Add our Value we want, and it should be active when addded? - Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); - } - //Clear old Inputs - txtCheat.Clear(); - txtDescription.Clear(); - } - //Someone broke the world? - catch (Exception ex) - { - MessageBox.Show("An Error occured: " + ex.GetType().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + N64(); break; case "PSX": - //Not yet. - //These codes, more or less work without Needing much work. - if (txtCheat.Text.Contains(" ") == false) - { - MessageBox.Show("All PSX GameShark Cheats need to contain a space after the eighth character", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - if (txtCheat.Text.Length != 13) - { - MessageBox.Show("All PSX GameShark Cheats need to be 13 characters in length.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - //We need to determine what kind of cheat this is. - //I need to determine if this is a Byte or Word. - switch (testo) - { - //30 80 Cheats mean, "Write, don't care otherwise." - case "30": - byteSize = 8; - break; - case "80": - byteSize = 16; - break; - //When value hits YYYY, make the next cheat go off - case "E0": - //E0 byteSize = 8; - case "D0": - //D0 byteSize = 16; - MessageBox.Show("The code you entered is not supported by BizHawk.", "Emulator Error", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - //Something wrong with their input. - default: - MessageBox.Show("The GameShark code entered is not a recognized format.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - //Leave this Method, before someone gets hurt. - return; - } - - //MainRAM + PSX(); break; + case "SAT": + SAT(); + break; default: //This should NEVER happen break; } } + private void GB() + { + //This Check ONLY applies to GB/GBC codes. + if (txtCheat.Text.Length != 8) + { + MessageBox.Show("All GameShark Codes need to be Eight characters in Length", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + //Let's make sure we start with zero. We have a good length, and a good starting zero, we should be good. Hopefully. + switch (testo) + { + //Is this 00 or 01? + case "00": + case "01": + //Good. + break; + default: + //No. + MessageBox.Show("All GameShark Codes for GameBoy need to start with 00 or 01", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + //Sample Input for GB/GBC: + //010FF6C1 + //Becomes: + //Address C1F6 + //Value 0F + parseString = txtCheat.Text.Remove(0, 2); + //Now we need to break it down a little more. + RAMValue = parseString.Remove(2, 4); + parseString = parseString.Remove(0, 2); + //The issue is Endian... Time to get ultra clever. And Regret it. + //First Half + RAMAddress = parseString.Remove(0, 2); + RAMAddress = RAMAddress + parseString.Remove(2, 2); + //We now have our values. + //This part, is annoying... + try + { + //A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works. + //System Bus Domain, The Address to Watch, Byte size (Byte), Hex Display, Description. Not Big Endian. + var watch = Watch.GenerateWatch(MemoryDomains["System Bus"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Byte, Watch.DisplayType.Hex, txtDescription.Text, false); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + //Clear old Inputs + txtCheat.Clear(); + txtDescription.Clear(); + } + //Someone broke the world? + catch (Exception ex) + { + MessageBox.Show("An Error occured: " + ex.GetType().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + private void N64() + { //These codes, more or less work without Needing much work. + if (txtCheat.Text.Contains(" ") == false) + { + MessageBox.Show("All N64 GameShark Codes need to contain a space after the eighth character", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (txtCheat.Text.Length != 13) + { + MessageBox.Show("All N64 GameShark Codes need to be 13 characters in length.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + //We need to determine what kind of cheat this is. + //I need to determine if this is a Byte or Word. + switch (testo) + { + //80 and 81 are the most common, so let's not get all worried. + case "80": + //Byte + byteSize = 8; + break; + case "81": + //Word + byteSize = 16; + break; + //Case A0 and A1 means "Write to Uncached address. + case "A0": + //Byte + byteSize = 8; + break; + case "A1": + //Word + byteSize = 16; + break; + //Do we support the GameShark Button? No. But these cheats, can be toggled. Which "Counts" + // Consequences be damned! + case "88": + //Byte + byteSize = 8; + break; + case "89": + //Word + byteSize = 16; + break; + //These are compare Address X to Value Y, then apply Value B to Address A + //This is not supported, yet + //TODO: When BizHawk supports a compare RAM Address's value is true then apply a value to another address, make it a thing. + case "D0": + //Byte + case "D1": + //Word + case "D2": + //Byte + case "D3": + //Word + MessageBox.Show("The code you entered is not supported by BizHawk.", "Emulator Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + //These codes are for Disabling the Expansion Pak. that's a bad thing? Assuming bad codes, until told otherwise. + case "EE": + case "DD": + case "CC": + MessageBox.Show("The code you entered is for Disabling the Expansion Pak. This is not allowed by this tool.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + //Enable Code + //Not Necessary? Think so? + case "DE": + //Single Write ON-Boot code. + //Not Necessary? Think so? + case "F0": + case "F1": + case "2A": + case "3C": + case "FF": + MessageBox.Show("The code you entered is not needed by Bizhawk.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + //TODO: Make Patch Code (5000XXYY) work. + case "50": + //Word? + MessageBox.Show("The code you entered is not supported by this tool. Please Submit the Game's Name, Cheat/Code and Purpose to the BizHawk forums.", "Tool Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + //I hope this isn't a thing. + default: + MessageBox.Show("The GameShark code entered is not a recognized format.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + //Leave this Method, before someone gets hurt. + return; + //break; + } + //Big Endian is USED constantly here. The question is, how do we determine if it's one or two bytes? + //Now to get clever. + //Sample Input for N64: + //8133B21E 08FF + //Becomes: + //Address 33B21E + //Value 08FF + + //Note, 80XXXXXX 00YY + //Is Byte, not Word + //Remove the 80 Octect + parseString = txtCheat.Text.Remove(0, 2); + //Get RAM Address + RAMAddress = parseString.Remove(6, 5); + //Get RAM Value + RAMValue = parseString.Remove(0, 7); + + try + { + //A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works. + //System Bus Domain, The Address to Watch, Byte size (Word), Hex Display, Description. Big Endian. + if (byteSize == 8) + { + //We have a Byte sized value + var watch = Watch.GenerateWatch(MemoryDomains["RDRAM"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Word, Watch.DisplayType.Hex, txtDescription.Text, true); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + } + if (byteSize == 16) + { + //We have a Word (Double Byte) sized Value + var watch = Watch.GenerateWatch(MemoryDomains["RDRAM"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Byte, Watch.DisplayType.Hex, txtDescription.Text, true); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + } + //Clear old Inputs + txtCheat.Clear(); + txtDescription.Clear(); + } + //Someone broke the world? + catch (Exception ex) + { + MessageBox.Show("An Error occured: " + ex.GetType().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + private void PSX() + { + //These codes, more or less work without Needing much work. + if (txtCheat.Text.Contains(" ") == false) + { + MessageBox.Show("All PSX GameShark Cheats need to contain a space after the eighth character", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (txtCheat.Text.Length != 13) + { + MessageBox.Show("All PSX GameShark Cheats need to be 13 characters in length.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + //We need to determine what kind of cheat this is. + //I need to determine if this is a Byte or Word. + switch (testo) + { + //30 80 Cheats mean, "Write, don't care otherwise." + case "30": + byteSize = 8; + break; + case "80": + byteSize = 16; + break; + //When value hits YYYY, make the next cheat go off + case "E0": + //E0 byteSize = 8; + case "E1": + //E1 byteSize = 8; + case "E2": + //E2 byteSize = 8; + case "D0": + //D0 byteSize = 16; + case "D1": + //D1 byteSize = 16; + case "D2": + //D2 byteSize = 16; + case "D3": + //D3 byteSize = 16; + case "D4": + //D4 byteSize = 16; + case "D5": + //D5 byteSize = 16; + case "D6": + //D6 byteSize = 16; + + //Increment/Decrement Codes + case "10": + //10 byteSize = 16; + case "11": + //11 byteSize = 16; + case "20": + //20 byteSize = 8 + case "21": + //21 byteSize = 8 + MessageBox.Show("The code you entered is not supported by BizHawk.", "Emulator Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + case "C0": + case "C1": + //Slow-Mo + case "40": + MessageBox.Show("The code you entered is not needed by Bizhawk.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + case "C2": + case "50": + //Word? + MessageBox.Show("The code you entered is not supported by this tool. Please Submit the Game's Name, Cheat/Code and Purpose to the BizHawk forums.", "Tool Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + //Something wrong with their input. + default: + MessageBox.Show("The GameShark code entered is not a recognized format.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + //Leave this Method, before someone gets hurt. + return; + } + //Sample Input for PSX: + //800D10BA 0009 + //Address: 0D10BA + //Value: 0009 + //Remove first two octets + parseString = txtCheat.Text.Remove(0, 2); + //Get RAM Address + RAMAddress = parseString.Remove(6, 5); + //Get RAM Value + RAMValue = parseString.Remove(0, 7); + try + { + //A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works. + //System Bus Domain, The Address to Watch, Byte size (Word), Hex Display, Description. Big Endian. + + //My Consern is that Work RAM High may be incorrect? + if (byteSize == 8) + { + //We have a Byte sized value + var watch = Watch.GenerateWatch(MemoryDomains["MainRAM"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Word, Watch.DisplayType.Hex, txtDescription.Text, false); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + } + if (byteSize == 16) + { + //We have a Word (Double Byte) sized Value + var watch = Watch.GenerateWatch(MemoryDomains["MainRAM"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Byte, Watch.DisplayType.Hex, txtDescription.Text, false); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + } + //Clear old Inputs + txtCheat.Clear(); + txtDescription.Clear(); + } + //Someone broke the world? + catch (Exception ex) + { + MessageBox.Show("An Error occured: " + ex.GetType().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + } + private void SAT() + { + //Not yet. + if (txtCheat.Text.Contains(" ") == false) + { + MessageBox.Show("All Saturn GameShark Cheats need to contain a space after the eighth character", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (txtCheat.Text.Length != 13) + { + MessageBox.Show("All Saturn GameShark Cheats need to be 13 characters in length.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + //This is a special test. Only the first character really matters? 16 or 36? + testo = testo.Remove(1, 1); + switch (testo) + { + case "1": + byteSize = 16; + break; + case "3": + byteSize = 8; + break; + //0 writes once. + case "0": + //D is RAM Equal To Activator, do Next Value + case "D": + MessageBox.Show("The code you entered is not supported by BizHawk.", "Emulator Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + case "F": + MessageBox.Show("The code you entered is not needed by Bizhawk.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + default: + MessageBox.Show("The GameShark code entered is not a recognized format.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + //Leave this Method, before someone gets hurt. + return; + } + //Sample Input for Saturn: + //160949FC 0090 + //Address: 0949FC + //Value: 90 + //Note, 3XXXXXXX are Big Endian + //Remove first two octets + parseString = txtCheat.Text.Remove(0, 2); + //Get RAM Address + RAMAddress = parseString.Remove(6, 5); + //Get RAM Value + RAMValue = parseString.Remove(0, 7); + try + { + //A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works. + //System Bus Domain, The Address to Watch, Byte size (Word), Hex Display, Description. Big Endian. + + //My Consern is that Work RAM High may be incorrect? + if (byteSize == 8) + { + //We have a Byte sized value + var watch = Watch.GenerateWatch(MemoryDomains["Work Ram High"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Word, Watch.DisplayType.Hex, txtDescription.Text, true); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + } + if (byteSize == 16) + { + //We have a Word (Double Byte) sized Value + var watch = Watch.GenerateWatch(MemoryDomains["Work Ram High"], long.Parse(RAMAddress, NumberStyles.HexNumber), Watch.WatchSize.Byte, Watch.DisplayType.Hex, txtDescription.Text, true); + //Take Watch, Add our Value we want, and it should be active when addded? + Global.CheatList.Add(new Cheat(watch, int.Parse(RAMValue, NumberStyles.HexNumber))); + } + //Clear old Inputs + txtCheat.Clear(); + txtDescription.Clear(); + } + //Someone broke the world? + catch (Exception ex) + { + MessageBox.Show("An Error occured: " + ex.GetType().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } private void btnClear_Click(object sender, EventArgs e) { //Clear old Inputs