redesign nes decoder to simpler design
This commit is contained in:
parent
addb861f50
commit
3cdd36699f
|
@ -0,0 +1,51 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common.cheats
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a decoded cheat value
|
||||
/// </summary>
|
||||
public interface IDecodeResult
|
||||
{
|
||||
int Address { get; }
|
||||
int Value { get; }
|
||||
int? Compare { get; }
|
||||
WatchSize Size { get; }
|
||||
bool IsValid { get; }
|
||||
}
|
||||
|
||||
public class DecodeResult : IDecodeResult
|
||||
{
|
||||
public int Address { get; internal set; }
|
||||
public int Value { get; internal set; }
|
||||
public int? Compare { get; internal set; }
|
||||
public WatchSize Size { get; internal set; }
|
||||
public bool IsValid => true;
|
||||
}
|
||||
|
||||
public class InvalidResult : IDecodeResult
|
||||
{
|
||||
public int Address => int.MaxValue;
|
||||
public int Value => int.MaxValue;
|
||||
public int? Compare => null;
|
||||
public WatchSize Size => WatchSize.Separator;
|
||||
public bool IsValid => false;
|
||||
}
|
||||
|
||||
public static class DecodeResultExtensions
|
||||
{
|
||||
public static Cheat ToCheat(this IDecodeResult result, MemoryDomain domain, string description)
|
||||
{
|
||||
var watch = Watch.GenerateWatch(
|
||||
domain,
|
||||
result.Address,
|
||||
result.Size,
|
||||
DisplayType.Hex,
|
||||
domain.EndianType == MemoryDomain.Endian.Big,
|
||||
description);
|
||||
return result.Compare.HasValue
|
||||
? new Cheat(watch, result.Value, result.Compare.Value, true, Cheat.CompareType.Equal)
|
||||
: new Cheat(watch, result.Value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.Common.cheats
|
||||
{
|
||||
public class NesGameGenieDecoder
|
||||
public static class NesGameGenieDecoder
|
||||
{
|
||||
private readonly string _code;
|
||||
|
||||
private readonly Dictionary<char, int> _gameGenieTable = new Dictionary<char, int>
|
||||
private static readonly Dictionary<char, int> GameGenieTable = new Dictionary<char, int>
|
||||
{
|
||||
['A'] = 0, // 0000
|
||||
['P'] = 1, // 0001
|
||||
|
@ -26,90 +25,93 @@ namespace BizHawk.Client.Common.cheats
|
|||
['N'] = 15 // 1111
|
||||
};
|
||||
|
||||
public NesGameGenieDecoder(string code)
|
||||
public static IDecodeResult Decode(string code)
|
||||
{
|
||||
_code = code;
|
||||
Decode();
|
||||
}
|
||||
if (code == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(code));
|
||||
}
|
||||
|
||||
public int Address { get; private set; }
|
||||
public int Value { get; private set; }
|
||||
public int? Compare { get; private set; }
|
||||
if (code.Length != 6 && code.Length != 8)
|
||||
{
|
||||
return new InvalidResult();
|
||||
}
|
||||
|
||||
public void Decode()
|
||||
{
|
||||
var result = new DecodeResult { Size = WatchSize.Byte };
|
||||
// char 3 bit 3 denotes the code length.
|
||||
if (_code.Length == 6)
|
||||
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;
|
||||
result.Value = 0;
|
||||
result.Address = 0x8000;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[0], out var x);
|
||||
Value |= x & 0x07;
|
||||
Value |= (x & 0x08) << 4;
|
||||
GameGenieTable.TryGetValue(code[0], out var x);
|
||||
result.Value |= x & 0x07;
|
||||
result.Value |= (x & 0x08) << 4;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[1], out x);
|
||||
Value |= (x & 0x07) << 4;
|
||||
Address |= (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);
|
||||
Address |= (x & 0x07) << 4;
|
||||
GameGenieTable.TryGetValue(code[2], out x);
|
||||
result.Address |= (x & 0x07) << 4;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[3], out x);
|
||||
Address |= (x & 0x07) << 12;
|
||||
Address |= x & 0x08;
|
||||
GameGenieTable.TryGetValue(code[3], out x);
|
||||
result.Address |= (x & 0x07) << 12;
|
||||
result.Address |= x & 0x08;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[4], out x);
|
||||
Address |= x & 0x07;
|
||||
Address |= (x & 0x08) << 8;
|
||||
GameGenieTable.TryGetValue(code[4], out x);
|
||||
result.Address |= x & 0x07;
|
||||
result.Address |= (x & 0x08) << 8;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[5], out x);
|
||||
Address |= (x & 0x07) << 8;
|
||||
Value |= x & 0x08;
|
||||
GameGenieTable.TryGetValue(code[5], out x);
|
||||
result.Address |= (x & 0x07) << 8;
|
||||
result.Value |= x & 0x08;
|
||||
}
|
||||
else if (_code.Length == 8)
|
||||
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|@|#|$|
|
||||
Value = 0;
|
||||
Address = 0x8000;
|
||||
Compare = 0;
|
||||
result.Value = 0;
|
||||
result.Address = 0x8000;
|
||||
result.Compare = 0;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[0], out var x);
|
||||
Value |= x & 0x07;
|
||||
Value |= (x & 0x08) << 4;
|
||||
GameGenieTable.TryGetValue(code[0], out var x);
|
||||
result.Value |= x & 0x07;
|
||||
result.Value |= (x & 0x08) << 4;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[1], out x);
|
||||
Value |= (x & 0x07) << 4;
|
||||
Address |= (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);
|
||||
Address |= (x & 0x07) << 4;
|
||||
GameGenieTable.TryGetValue(code[2], out x);
|
||||
result.Address |= (x & 0x07) << 4;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[3], out x);
|
||||
Address |= (x & 0x07) << 12;
|
||||
Address |= x & 0x08;
|
||||
GameGenieTable.TryGetValue(code[3], out x);
|
||||
result.Address |= (x & 0x07) << 12;
|
||||
result.Address |= x & 0x08;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[4], out x);
|
||||
Address |= x & 0x07;
|
||||
Address |= (x & 0x08) << 8;
|
||||
GameGenieTable.TryGetValue(code[4], out x);
|
||||
result.Address |= x & 0x07;
|
||||
result.Address |= (x & 0x08) << 8;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[5], out x);
|
||||
Address |= (x & 0x07) << 8;
|
||||
Compare |= x & 0x08;
|
||||
GameGenieTable.TryGetValue(code[5], out x);
|
||||
result.Address |= (x & 0x07) << 8;
|
||||
result.Compare |= x & 0x08;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[6], out x);
|
||||
Compare |= x & 0x07;
|
||||
Compare |= (x & 0x08) << 4;
|
||||
GameGenieTable.TryGetValue(code[6], out x);
|
||||
result.Compare |= x & 0x07;
|
||||
result.Compare |= (x & 0x08) << 4;
|
||||
|
||||
_gameGenieTable.TryGetValue(_code[7], out x);
|
||||
Compare |= (x & 0x07) << 4;
|
||||
Value |= x & 0x08;
|
||||
GameGenieTable.TryGetValue(code[7], out x);
|
||||
result.Compare |= (x & 0x07) << 4;
|
||||
result.Value |= x & 0x08;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,19 +45,11 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (NESAvailable && MemoryDomains != null)
|
||||
{
|
||||
var decoder = new NesGameGenieDecoder(code);
|
||||
var watch = Watch.GenerateWatch(
|
||||
MemoryDomains["System Bus"],
|
||||
decoder.Address,
|
||||
WatchSize.Byte,
|
||||
DisplayType.Hex,
|
||||
false,
|
||||
code);
|
||||
|
||||
Global.CheatList.Add(new Cheat(
|
||||
watch,
|
||||
decoder.Value,
|
||||
decoder.Compare));
|
||||
var result = NesGameGenieDecoder.Decode(code);
|
||||
if (result.IsValid)
|
||||
{
|
||||
Global.CheatList.Add(result.ToCheat(MemoryDomains.SystemBus, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +119,12 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (NESAvailable)
|
||||
{
|
||||
var decoder = new NesGameGenieDecoder(code);
|
||||
Global.CheatList.RemoveRange(
|
||||
Global.CheatList.Where(c => c.Address == decoder.Address));
|
||||
var decoder = NesGameGenieDecoder.Decode(code);
|
||||
if (decoder.IsValid)
|
||||
{
|
||||
Global.CheatList.RemoveRange(
|
||||
Global.CheatList.Where(c => c.Address == decoder.Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -277,21 +277,23 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.CheatList.Add(new Cheat(watch, decoder.Value));
|
||||
}
|
||||
|
||||
private void Nes(string cheat)
|
||||
private void Nes(string code)
|
||||
{
|
||||
if (cheat.Length != 6 && cheat.Length != 8)
|
||||
if (code.Length != 6 && code.Length != 8)
|
||||
{
|
||||
InputError("Game Genie codes need to be six or eight characters in length.");
|
||||
}
|
||||
|
||||
var description = Description(cheat);
|
||||
var decoder = new NesGameGenieDecoder(cheat);
|
||||
|
||||
var watch = Watch.GenerateWatch(MemoryDomains["System Bus"], decoder.Address, WatchSize.Byte, Common.DisplayType.Hex, false, description);
|
||||
Global.CheatList.Add(
|
||||
decoder.Compare.HasValue
|
||||
? new Cheat(watch, decoder.Value, decoder.Compare.Value, true, Cheat.CompareType.Equal)
|
||||
: new Cheat(watch, decoder.Value));
|
||||
var description = Description(code);
|
||||
var result = NesGameGenieDecoder.Decode(code);
|
||||
if (result.IsValid)
|
||||
{
|
||||
Global.CheatList.Add(result.ToCheat(MemoryDomains.SystemBus, description));
|
||||
}
|
||||
else
|
||||
{
|
||||
InputError("Invalid Game Genie code");
|
||||
}
|
||||
}
|
||||
|
||||
private void Psx(string cheat)
|
||||
|
|
Loading…
Reference in New Issue