using System; using System.Collections.Generic; namespace BizHawk.Client.Common.cheats { public static class SnesGameGenieDecoder { // 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 static readonly Dictionary SNESGameGenieTable = new Dictionary { ['D'] = 0, // 0000 ['F'] = 1, // 0001 ['4'] = 2, // 0010 ['7'] = 3, // 0011 ['0'] = 4, // 0100 ['9'] = 5, // 0101 ['1'] = 6, // 0110 ['5'] = 7, // 0111 ['6'] = 8, // 1000 ['B'] = 9, // 1001 ['C'] = 10, // 1010 ['8'] = 11, // 1011 ['A'] = 12, // 1100 ['2'] = 13, // 1101 ['3'] = 14, // 1110 ['E'] = 15 // 1111 }; public static IDecodeResult Decode(string code) { if (code == null) { throw new ArgumentNullException(nameof(code)); } if (!code.Contains("-") && code.Length != 9) { return new InvalidCheatCode("Game genie codes must be 9 characters with a format of xxyy-yyyy"); } // 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. // Char # | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | // 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; // Value if (code.Length > 0) { SNESGameGenieTable.TryGetValue(code[0], out x); result.Value = x << 4; } if (code.Length > 1) { SNESGameGenieTable.TryGetValue(code[1], out x); result.Value |= x; } // Address if (code.Length > 2) { SNESGameGenieTable.TryGetValue(code[2], out x); result.Address = x << 12; } if (code.Length > 3) { SNESGameGenieTable.TryGetValue(code[3], out x); result.Address |= x << 4; } if (code.Length > 4) { SNESGameGenieTable.TryGetValue(code[4], out x); result.Address |= (x & 0xC) << 6; result.Address |= (x & 0x3) << 22; } if (code.Length > 5) { SNESGameGenieTable.TryGetValue(code[5], out x); result.Address |= (x & 0xC) << 18; result.Address |= (x & 0x3) << 2; } if (code.Length > 6) { SNESGameGenieTable.TryGetValue(code[6], out x); result.Address |= (x & 0xC) >> 2; result.Address |= (x & 0x3) << 18; } if (code.Length > 7) { SNESGameGenieTable.TryGetValue(code[7], out x); result.Address |= (x & 0xC) << 14; result.Address |= (x & 0x3) << 10; } return result; } } }