From f7138e6514f4d2fa3321f32626702fdfb0ca0192 Mon Sep 17 00:00:00 2001 From: adelikat Date: Sat, 2 Nov 2013 01:48:35 +0000 Subject: [PATCH] move NES game genie encoding/decoding logic into specialized classes in client.common and refactor the dialog and lua functions accordingly --- .../BizHawk.Client.Common.csproj | 1 + .../NESGameGenieEncoderDecoder.cs | 175 ++++++++++++++++++ .../tools/Lua/Libraries/EmuLuaLibrary.NES.cs | 48 ++--- BizHawk.MultiClient/tools/NES/NESGameGenie.cs | 126 ++----------- 4 files changed, 207 insertions(+), 143 deletions(-) create mode 100644 BizHawk.Client.Common/NESGameGenieEncoderDecoder.cs diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj index 017b278f66..d05fbdf908 100644 --- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj +++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj @@ -124,6 +124,7 @@ + diff --git a/BizHawk.Client.Common/NESGameGenieEncoderDecoder.cs b/BizHawk.Client.Common/NESGameGenieEncoderDecoder.cs new file mode 100644 index 0000000000..338396f4a2 --- /dev/null +++ b/BizHawk.Client.Common/NESGameGenieEncoderDecoder.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.Client.Common +{ + public class NESGameGenieDecoder + { + public int Address { get; private set; } + public int Value { get; private set; } + public int? Compare { get; private set; } + + private readonly string _code = String.Empty; + + public NESGameGenieDecoder(string code) + { + _code = code; + Decode(); + } + + private readonly Dictionary GameGenieTable = new Dictionary + { + { 'A', 0 }, //0000 + { 'P', 1 }, //0001 + { 'Z', 2 }, //0010 + { 'L', 3 }, //0011 + { 'G', 4 }, //0100 + { 'I', 5 }, //0101 + { 'T', 6 }, //0110 + { 'Y', 7 }, //0111 + { 'E', 8 }, //1000 + { 'O', 9 }, //1001 + { 'X', 10}, //1010 + { 'U', 11}, //1011 + { 'K', 12}, //1100 + { 'S', 13}, //1101 + { 'V', 14}, //1110 + { 'N', 15}, //1111 + }; + + public void Decode() + { + //char 3 bit 3 denotes the code length. + if (_code.Length == 6) + { + //Char # | 1 | 2 | 3 | 4 | 5 | 6 | + //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| + //maps to|1|6|7|8|H|2|3|4|-|I|J|K|L|A|B|C|D|M|N|O|5|E|F|G| + Value = 0; + Address = 0x8000; + int x; + + GameGenieTable.TryGetValue(_code[0], out x); + Value |= (x & 0x07); + Value |= (x & 0x08) << 4; + + GameGenieTable.TryGetValue(_code[1], out x); + Value |= (x & 0x07) << 4; + Address |= (x & 0x08) << 4; + + GameGenieTable.TryGetValue(_code[2], out x); + Address |= (x & 0x07) << 4; + + GameGenieTable.TryGetValue(_code[3], out x); + Address |= (x & 0x07) << 12; + Address |= (x & 0x08); + + GameGenieTable.TryGetValue(_code[4], out x); + Address |= (x & 0x07); + Address |= (x & 0x08) << 8; + + GameGenieTable.TryGetValue(_code[5], out x); + Address |= (x & 0x07) << 8; + Value |= (x & 0x08); + } + else if (_code.Length == 8) + { + //Char # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + //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|1|6|7|8|H|2|3|4|-|I|J|K|L|A|B|C|D|M|N|O|%|E|F|G|!|^|&|*|5|@|#|$| + Value = 0; + Address = 0x8000; + Compare = 0; + int x; + + GameGenieTable.TryGetValue(_code[0], out x); + Value |= (x & 0x07); + Value |= (x & 0x08) << 4; + + GameGenieTable.TryGetValue(_code[1], out x); + Value |= (x & 0x07) << 4; + Address |= (x & 0x08) << 4; + + GameGenieTable.TryGetValue(_code[2], out x); + Address |= (x & 0x07) << 4; + + GameGenieTable.TryGetValue(_code[3], out x); + Address |= (x & 0x07) << 12; + Address |= (x & 0x08); + + GameGenieTable.TryGetValue(_code[4], out x); + Address |= (x & 0x07); + Address |= (x & 0x08) << 8; + + GameGenieTable.TryGetValue(_code[5], out x); + Address |= (x & 0x07) << 8; + Compare |= (x & 0x08); + + GameGenieTable.TryGetValue(_code[6], out x); + Compare |= (x & 0x07); + Compare |= (x & 0x08) << 4; + + GameGenieTable.TryGetValue(_code[7], out x); + Compare |= (x & 0x07) << 4; + Value |= (x & 0x08); + } + } + } + + public class NESGameGenieEncoder + { + private readonly char[] letters = { 'A', 'P', 'Z', 'L', 'G', 'I', 'T', 'Y', 'E', 'O', 'X', 'U', 'K', 'S', 'V', 'N' }; + + private int _address; + private int _value; + private int? _compare; + + public string GameGenieCode { get; private set; } + + public NESGameGenieEncoder(int address, int value, int? compare) + { + _address = address; + if (_address >= 0x8000) + { + _address -= 0x8000; + } + _value = value; + _compare = compare; + + GameGenieCode = String.Empty; + } + + public string Encode() + { + byte[] num = { 0, 0, 0, 0, 0, 0, 0, 0 }; + num[0] = (byte)((_value & 7) + ((_value >> 4) & 8)); + num[1] = (byte)(((_value >> 4) & 7) + ((_address >> 4) & 8)); + num[2] = (byte)(((_address >> 4) & 7)); + num[3] = (byte)((_address >> 12) + (_address & 8)); + num[4] = (byte)((_address & 7) + ((_address >> 8) & 8)); + num[5] = (byte)(((_address >> 8) & 7)); + + if (_compare.HasValue) + { + num[2] += 8; + num[5] += (byte)(_compare & 8); + num[6] = (byte)((_compare & 7) + ((_compare >> 4) & 8)); + num[7] = (byte)(((_compare >> 4) & 7) + (_value & 8)); + for (int i = 0; i < 8; i++) + { + GameGenieCode += letters[num[i]]; + } + } + else + { + num[5] += (byte)(_value & 8); + for (int i = 0; i < 6; i++) + { + GameGenieCode += letters[num[i]]; + } + } + + return GameGenieCode; + } + } +} diff --git a/BizHawk.MultiClient/tools/Lua/Libraries/EmuLuaLibrary.NES.cs b/BizHawk.MultiClient/tools/Lua/Libraries/EmuLuaLibrary.NES.cs index 1b9d766d3f..b1dcdadb41 100644 --- a/BizHawk.MultiClient/tools/Lua/Libraries/EmuLuaLibrary.NES.cs +++ b/BizHawk.MultiClient/tools/Lua/Libraries/EmuLuaLibrary.NES.cs @@ -25,7 +25,7 @@ namespace BizHawk.MultiClient "setclipleftandright", "setdispbackground", "setdispsprites", - "setscanlines", + "setscanlines" }; } } @@ -34,26 +34,20 @@ namespace BizHawk.MultiClient { if (Global.Emulator is NES) { - NESGameGenie gg = new NESGameGenie(); - gg.DecodeGameGenieCode(code); - if (gg.Address.HasValue && gg.Value.HasValue) - { - Watch watch = Watch.GenerateWatch( - Global.Emulator.MemoryDomains[1], - gg.Address.Value, - Watch.WatchSize.Byte, - Watch.DisplayType.Hex, - code, - false - ); - - Global.CheatList.Add(new Cheat( - watch, - gg.Value.Value, - gg.Compare - )); - } - + var decoder = new NESGameGenieDecoder(code); + Watch watch = Watch.GenerateWatch( + Global.Emulator.MemoryDomains[1], + decoder.Address, + Watch.WatchSize.Byte, + Watch.DisplayType.Hex, + code, + false + ); + Global.CheatList.Add(new Cheat( + watch, + decoder.Value, + decoder.Compare + )); ToolHelpers.UpdateCheatRelatedTools(); } } @@ -106,14 +100,10 @@ namespace BizHawk.MultiClient { if (Global.Emulator is NES) { - NESGameGenie gg = new NESGameGenie(); - gg.DecodeGameGenieCode(code); - if (gg.Address.HasValue && gg.Value.HasValue) - { - var cheats = Global.CheatList.Where(x => x.Address == gg.Address); - Global.CheatList.RemoveRange(cheats); - } - + var decoder = new NESGameGenieDecoder(code); + Global.CheatList.RemoveRange( + Global.CheatList.Where(x => x.Address == decoder.Address) + ); ToolHelpers.UpdateCheatRelatedTools(); } } diff --git a/BizHawk.MultiClient/tools/NES/NESGameGenie.cs b/BizHawk.MultiClient/tools/NES/NESGameGenie.cs index d2d727ff82..f95ce3eaf9 100644 --- a/BizHawk.MultiClient/tools/NES/NESGameGenie.cs +++ b/BizHawk.MultiClient/tools/NES/NESGameGenie.cs @@ -5,15 +5,14 @@ using System.Windows.Forms; using System.Globalization; using BizHawk.Client.Common; -using BizHawk.Emulation.Consoles.Nintendo; namespace BizHawk.MultiClient { public partial class NESGameGenie : Form { - private int? _address = null; - private int? _value = null; - private int? _compare = null; + private int? _address; + private int? _value; + private int? _compare; private readonly Dictionary GameGenieTable = new Dictionary { { 'A', 0 }, //0000 @@ -63,83 +62,12 @@ namespace BizHawk.MultiClient public void DecodeGameGenieCode(string code) { - //char 3 bit 3 denotes the code length. - if (code.Length == 6) - { - //Char # | 1 | 2 | 3 | 4 | 5 | 6 | - //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| - //maps to|1|6|7|8|H|2|3|4|-|I|J|K|L|A|B|C|D|M|N|O|5|E|F|G| - _value = 0; - _address = 0x8000; - int x; - GameGenieTable.TryGetValue(code[0], out x); - _value |= (x & 0x07); - _value |= (x & 0x08) << 4; - - GameGenieTable.TryGetValue(code[1], out x); - _value |= (x & 0x07) << 4; - _address |= (x & 0x08) << 4; - - GameGenieTable.TryGetValue(code[2], out x); - _address |= (x & 0x07) << 4; - - GameGenieTable.TryGetValue(code[3], out x); - _address |= (x & 0x07) << 12; - _address |= (x & 0x08); - - GameGenieTable.TryGetValue(code[4], out x); - _address |= (x & 0x07); - _address |= (x & 0x08) << 8; - - GameGenieTable.TryGetValue(code[5], out x); - _address |= (x & 0x07) << 8; - _value |= (x & 0x08); - - SetProperties(); - } - else if (code.Length == 8) - { - //Char # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | - //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|1|6|7|8|H|2|3|4|-|I|J|K|L|A|B|C|D|M|N|O|%|E|F|G|!|^|&|*|5|@|#|$| - _value = 0; - _address = 0x8000; - _compare = 0; - int x; - - GameGenieTable.TryGetValue(code[0], out x); - _value |= (x & 0x07); - _value |= (x & 0x08) << 4; - - GameGenieTable.TryGetValue(code[1], out x); - _value |= (x & 0x07) << 4; - _address |= (x & 0x08) << 4; - - GameGenieTable.TryGetValue(code[2], out x); - _address |= (x & 0x07) << 4; - - GameGenieTable.TryGetValue(code[3], out x); - _address |= (x & 0x07) << 12; - _address |= (x & 0x08); - - GameGenieTable.TryGetValue(code[4], out x); - _address |= (x & 0x07); - _address |= (x & 0x08) << 8; - - GameGenieTable.TryGetValue(code[5], out x); - _address |= (x & 0x07) << 8; - _compare |= (x & 0x08); - - GameGenieTable.TryGetValue(code[6], out x); - _compare |= (x & 0x07); - _compare |= (x & 0x08) << 4; - - GameGenieTable.TryGetValue(code[7], out x); - _compare |= (x & 0x07) << 4; - _value |= (x & 0x08); - SetProperties(); - } + var decoder = new NESGameGenieDecoder(code); + _address = decoder.Address; + _value = decoder.Value; + _compare = decoder.Compare; + SetProperties(); } private void SetProperties() @@ -196,36 +124,7 @@ namespace BizHawk.MultiClient _address = AddressBox.ToRawInt(); _value = ValueBox.ToRawInt(); _compare = CompareBox.ToRawInt(); - - char[] letters = { 'A', 'P', 'Z', 'L', 'G', 'I', 'T', 'Y', 'E', 'O', 'X', 'U', 'K', 'S', 'V', 'N' }; - if (_address >= 0x8000) - _address -= 0x8000; - GameGenieCode.Text = String.Empty; - byte[] num = { 0, 0, 0, 0, 0, 0, 0, 0 }; - num[0] = (byte)((_value & 7) + ((_value >> 4) & 8)); - num[1] = (byte)(((_value >> 4) & 7) + ((_address >> 4) & 8)); - num[2] = (byte)(((_address >> 4) & 7)); - num[3] = (byte)((_address >> 12) + (_address & 8)); - num[4] = (byte)((_address & 7) + ((_address >> 8) & 8)); - num[5] = (byte)(((_address >> 8) & 7)); - - if (_compare < 0 || CompareBox.Text.Length == 0) - { - num[5] += (byte)(_value & 8); - for (int x = 0; x < 6; x++) - GameGenieCode.Text += letters[num[x]]; - } - else - { - num[2] += 8; - num[5] += (byte)(_compare & 8); - num[6] = (byte)((_compare & 7) + ((_compare >> 4) & 8)); - num[7] = (byte)(((_compare >> 4) & 7) + (_value & 8)); - for (int i = 0; i < 8; i++) - { - GameGenieCode.Text += letters[num[i]]; - } - } + GameGenieCode.Text = new NESGameGenieEncoder(_address.Value, _value.Value, _compare).Encode(); } private void AddCheatClick() @@ -249,10 +148,10 @@ namespace BizHawk.MultiClient Global.CheatList.Add(new Cheat( watch, ValueBox.ToRawInt(), - compare, - enabled: true)); + compare + )); - GlobalWinF.MainForm.Cheats_UpdateValues(); + ToolHelpers.UpdateCheatRelatedTools(); } } @@ -378,7 +277,6 @@ namespace BizHawk.MultiClient { if (Encoding.Checked && AddressBox.Text.Length > 0) { - int _address = int.Parse(AddressBox.Text, NumberStyles.HexNumber); if (!String.IsNullOrEmpty(ValueBox.Text)) { EncodeGameGenie();