diff --git a/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs b/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs index b0f2ca300a..08098a0a9e 100644 --- a/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs +++ b/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs @@ -3,33 +3,30 @@ using System.Globalization; namespace BizHawk.Client.Common.cheats { - public class SnesActionReplayDecoder + public static class SnesActionReplayDecoder { - private readonly string _code; - - public SnesActionReplayDecoder(string code) - { - _code = code; - Decode(); - } - - public int Address { get; private set; } - public int Value { get; private set; } - public int ByteSize => 2; - // Sample Code: // 7E18A428 // Address: 7E18A4 // Value: 28 - public void Decode() + public static IDecodeResult Decode(string code) { - if (_code.Length != 8) + if (code == null) { - throw new InvalidOperationException("Pro Action Replay Codes need to be eight characters in length."); + throw new ArgumentNullException(nameof(code)); } - Address = int.Parse(_code.Remove(6, 2), NumberStyles.HexNumber); - Value = int.Parse(_code.Remove(0, 6), NumberStyles.HexNumber); + if (code.Length != 8) + { + return new InvalidCheatCode("Pro Action Replay Codes must to be eight characters."); + } + + return new DecodeResult + { + Size = WatchSize.Word, + Address = int.Parse(code.Remove(6, 2), NumberStyles.HexNumber), + Value = int.Parse(code.Remove(0, 6), NumberStyles.HexNumber) + }; } } } diff --git a/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs b/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs index aa07c11d8e..e3829eb69f 100644 --- a/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs +++ b/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs @@ -1,16 +1,15 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace BizHawk.Client.Common.cheats { - public class SnesGameGenieDecoder + public static class SnesGameGenieDecoder { - private readonly string _code; - // including transposition // Code: D F 4 7 0 9 1 5 6 B C 8 A 2 3 E // Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F // This only applies to the SNES - private readonly Dictionary _snesGameGenieTable = new Dictionary + private static readonly Dictionary SNESGameGenieTable = new Dictionary { ['D'] = 0, // 0000 ['F'] = 1, // 0001 @@ -30,17 +29,18 @@ namespace BizHawk.Client.Common.cheats ['E'] = 15 // 1111 }; - public SnesGameGenieDecoder(string code) + public static IDecodeResult Decode(string code) { - _code = code?.Replace("-", "") ?? ""; - Decode(); - } + if (code == null) + { + throw new ArgumentNullException(nameof(code)); + } - public int Address { get; private set; } - public int Value { get; private set; } + if (!code.Contains("-") && code.Length != 9) + { + return new InvalidCheatCode("Game genie codes must be 9 characters with a format of xxyy-yyyy"); + } - public void Decode() - { // Code: D F 4 7 0 9 1 5 6 B C 8 A 2 3 E // Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F // XXYY-YYYY, where XX is the value, and YY-YYYY is the address. @@ -48,61 +48,65 @@ namespace BizHawk.Client.Common.cheats // Bit # |3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0| // maps to| Value |i|j|k|l|q|r|s|t|o|p|a|b|c|d|u|v|w|x|e|f|g|h|m|n| // order | Value |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x| + var result = new DecodeResult { Size = WatchSize.Byte }; + int x; - // Getting Value - if (_code.Length > 0) + // Value + if (code.Length > 0) { - _snesGameGenieTable.TryGetValue(_code[0], out x); - Value = x << 4; + SNESGameGenieTable.TryGetValue(code[0], out x); + result.Value = x << 4; } - if (_code.Length > 1) + if (code.Length > 1) { - _snesGameGenieTable.TryGetValue(_code[1], out x); - Value |= x; + SNESGameGenieTable.TryGetValue(code[1], out x); + result.Value |= x; } // Address - if (_code.Length > 2) + if (code.Length > 2) { - _snesGameGenieTable.TryGetValue(_code[2], out x); - Address = x << 12; + SNESGameGenieTable.TryGetValue(code[2], out x); + result.Address = x << 12; } - if (_code.Length > 3) + if (code.Length > 3) { - _snesGameGenieTable.TryGetValue(_code[3], out x); - Address |= x << 4; + SNESGameGenieTable.TryGetValue(code[3], out x); + result.Address |= x << 4; } - if (_code.Length > 4) + if (code.Length > 4) { - _snesGameGenieTable.TryGetValue(_code[4], out x); - Address |= (x & 0xC) << 6; - Address |= (x & 0x3) << 22; + SNESGameGenieTable.TryGetValue(code[4], out x); + result.Address |= (x & 0xC) << 6; + result.Address |= (x & 0x3) << 22; } - if (_code.Length > 5) + if (code.Length > 5) { - _snesGameGenieTable.TryGetValue(_code[5], out x); - Address |= (x & 0xC) << 18; - Address |= (x & 0x3) << 2; + SNESGameGenieTable.TryGetValue(code[5], out x); + result.Address |= (x & 0xC) << 18; + result.Address |= (x & 0x3) << 2; } - if (_code.Length > 6) + if (code.Length > 6) { - _snesGameGenieTable.TryGetValue(_code[6], out x); - Address |= (x & 0xC) >> 2; - Address |= (x & 0x3) << 18; + SNESGameGenieTable.TryGetValue(code[6], out x); + result.Address |= (x & 0xC) >> 2; + result.Address |= (x & 0x3) << 18; } - if (_code.Length > 7) + if (code.Length > 7) { - _snesGameGenieTable.TryGetValue(_code[7], out x); - Address |= (x & 0xC) << 14; - Address |= (x & 0x3) << 10; + SNESGameGenieTable.TryGetValue(code[7], out x); + result.Address |= (x & 0xC) << 14; + result.Address |= (x & 0x3) << 10; } + + return result; } } } diff --git a/BizHawk.Client.EmuHawk/tools/GameShark.cs b/BizHawk.Client.EmuHawk/tools/GameShark.cs index 479df98d67..f86f75e9bc 100644 --- a/BizHawk.Client.EmuHawk/tools/GameShark.cs +++ b/BizHawk.Client.EmuHawk/tools/GameShark.cs @@ -349,29 +349,37 @@ namespace BizHawk.Client.EmuHawk InputError($"Unknown code type: {code}"); } - private void Snes(string cheat) + private void Snes(string code) { - if (cheat.Contains("-") && cheat.Length == 9) + if (code.Contains("-") && code.Length == 9) { MessageBox.Show("Game genie codes are not currently supported for SNES", "SNES Game Genie not supported", MessageBoxButtons.OK, MessageBoxIcon.Error); - ////var decoder = new SnesGameGenieDecoder(_singleCheat); - ////var watch = Watch.GenerateWatch(MemoryDomains["CARTROM"], decoder.Address, WatchSize.Byte, Common.DisplayType.Hex, false, txtDescription.Text); - ////Global.CheatList.Add(new Cheat(watch, decoder.Value)); + //var result = SnesGameGenieDecoder.Decode(code); + //if (result.IsValid) + //{ + // var description = Description(code); + // Global.CheatList.Add(result.ToCheat(MemoryDomains.SystemBus, description)); + //} + //else + //{ + // InputError(result.Error); + //} } - else if (cheat.Length == 8) + else if (code.Length == 8) { - var decoder = new SnesActionReplayDecoder(cheat); - var watch = Watch.GenerateWatch(MemoryDomains["System Bus"], decoder.Address, WatchSize.Word, Common.DisplayType.Hex, false, txtDescription.Text); - Global.CheatList.Add(new Cheat(watch, decoder.Value)); - } - else if (cheat.Contains("-") && cheat.Length != 9) - { - InputError("Game Genie Codes need to be nine characters in length."); - } - else if (cheat.Length != 9 && cheat.Length != 8) - { - InputError("Pro Action Replay Codes need to be eight characters in length."); + var result = GbGameSharkDecoder.Decode(code); + if (result.IsValid) + { + var description = Description(code); + Global.CheatList.Add(result.ToCheat(MemoryDomains.SystemBus, description)); + } + else + { + InputError(result.Error); + } } + + InputError($"Unknown code type: {code}"); } private void BtnClear_Click(object sender, EventArgs e) diff --git a/BizHawk.sln.DotSettings b/BizHawk.sln.DotSettings index 4f65d99bfc..a42094aa21 100644 --- a/BizHawk.sln.DotSettings +++ b/BizHawk.sln.DotSettings @@ -546,6 +546,7 @@ True True True + True True True True