BizHawk/BizHawk.Client.Common/cheats/NesGameGenieDecoder.cs

118 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
namespace BizHawk.Client.Common.cheats
{
public static class NesGameGenieDecoder
{
private static readonly Dictionary<char, int> GameGenieTable = new Dictionary<char, int>
{
['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 static IDecodeResult Decode(string code)
{
if (code == null)
{
throw new ArgumentNullException(nameof(code));
}
if (code.Length != 6 && code.Length != 8)
{
return new InvalidCheatCode("Game Genie codes need to be six or eight characters in length.");
}
var result = new DecodeResult { Size = WatchSize.Byte };
// 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|
result.Value = 0;
result.Address = 0x8000;
GameGenieTable.TryGetValue(code[0], out var x);
result.Value |= x & 0x07;
result.Value |= (x & 0x08) << 4;
GameGenieTable.TryGetValue(code[1], out x);
result.Value |= (x & 0x07) << 4;
result.Address |= (x & 0x08) << 4;
GameGenieTable.TryGetValue(code[2], out x);
result.Address |= (x & 0x07) << 4;
GameGenieTable.TryGetValue(code[3], out x);
result.Address |= (x & 0x07) << 12;
result.Address |= x & 0x08;
GameGenieTable.TryGetValue(code[4], out x);
result.Address |= x & 0x07;
result.Address |= (x & 0x08) << 8;
GameGenieTable.TryGetValue(code[5], out x);
result.Address |= (x & 0x07) << 8;
result.Value |= x & 0x08;
}
else
{
// 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|@|#|$|
result.Value = 0;
result.Address = 0x8000;
result.Compare = 0;
GameGenieTable.TryGetValue(code[0], out var x);
result.Value |= x & 0x07;
result.Value |= (x & 0x08) << 4;
GameGenieTable.TryGetValue(code[1], out x);
result.Value |= (x & 0x07) << 4;
result.Address |= (x & 0x08) << 4;
GameGenieTable.TryGetValue(code[2], out x);
result.Address |= (x & 0x07) << 4;
GameGenieTable.TryGetValue(code[3], out x);
result.Address |= (x & 0x07) << 12;
result.Address |= x & 0x08;
GameGenieTable.TryGetValue(code[4], out x);
result.Address |= x & 0x07;
result.Address |= (x & 0x08) << 8;
GameGenieTable.TryGetValue(code[5], out x);
result.Address |= (x & 0x07) << 8;
result.Compare |= x & 0x08;
GameGenieTable.TryGetValue(code[6], out x);
result.Compare |= x & 0x07;
result.Compare |= (x & 0x08) << 4;
GameGenieTable.TryGetValue(code[7], out x);
result.Compare |= (x & 0x07) << 4;
result.Value |= x & 0x08;
}
return result;
}
}
}