From 967e2760dff3208271850fd754ef7b6c61d2d346 Mon Sep 17 00:00:00 2001 From: ngrst183 Date: Sat, 25 Sep 2021 12:50:42 -0700 Subject: [PATCH] Add BiDirectionalDictionary for opcodes --- src/xdecode/BiDirectionalDictionary.cs | 71 +++++++++++++ src/xdecode/Opcode.cs | 135 ++++--------------------- src/xdecode/OpcodeDefinitions.cs | 52 ++++++++++ 3 files changed, 141 insertions(+), 117 deletions(-) create mode 100644 src/xdecode/BiDirectionalDictionary.cs create mode 100644 src/xdecode/OpcodeDefinitions.cs diff --git a/src/xdecode/BiDirectionalDictionary.cs b/src/xdecode/BiDirectionalDictionary.cs new file mode 100644 index 0000000..2d5c27d --- /dev/null +++ b/src/xdecode/BiDirectionalDictionary.cs @@ -0,0 +1,71 @@ +using System.Collections; +using System.Collections.Generic; + +namespace xdecode +{ + public class BiDirectionalDictionary : IEnumerable> + { + private readonly Dictionary _forward = new(); + private readonly Dictionary _reverse = new(); + + public Indexer Forward { get; } + public Indexer Reverse { get; } + + public BiDirectionalDictionary() + { + Forward = new Indexer(_forward); + Reverse = new Indexer(_reverse); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public IEnumerator> GetEnumerator() + { + return _forward.GetEnumerator(); + } + + public void Add(T1 t1, T2 t2) + { + _forward.Add(t1, t2); + _reverse.Add(t2, t1); + } + + public void Remove(T1 t1) + { + var revKey = Forward[t1]; + _forward.Remove(t1); + _reverse.Remove(revKey); + } + + public void Remove(T2 t2) + { + var forwardKey = Reverse[t2]; + _reverse.Remove(t2); + _forward.Remove(forwardKey); + } + + public class Indexer + { + private readonly Dictionary _dictionary; + + public T4 this[T3 index] + { + get => _dictionary[index]; + set => _dictionary[index] = value; + } + + public Indexer(Dictionary dictionary) + { + _dictionary = dictionary; + } + + public bool Contains(T3 key) + { + return _dictionary.ContainsKey(key); + } + } + } +} \ No newline at end of file diff --git a/src/xdecode/Opcode.cs b/src/xdecode/Opcode.cs index c7dac16..9700c13 100644 --- a/src/xdecode/Opcode.cs +++ b/src/xdecode/Opcode.cs @@ -1,12 +1,12 @@ -namespace xdecode +using System; + +namespace xdecode { public class Opcode { - public OpcodeType Type { get; private set; } - - public byte Value { get; private set; } + public OpcodeType Type { get; } - // TODO: bi-directional dictionary bindings for different opcode versions (assuming multiple values don't map to the same opcode per version) + public byte Value { get; } public bool IsValid => (int)Type >= 0x100 && (int)Type <= 0x10B; @@ -14,125 +14,26 @@ public Opcode(byte value, OpcodeVersion version = OpcodeVersion.Retail) { Value = value; - switch(version) + Type = version switch { - case OpcodeVersion.Retail: - Type = value switch - { - 0x02 => OpcodeType.MemRead, - 0x03 => OpcodeType.MemWrite, - 0x04 => OpcodeType.PciWrite, - 0x05 => OpcodeType.PciRead, - 0x06 => OpcodeType.AndOr, - 0x07 => OpcodeType.Chain, - 0x08 => OpcodeType.Jne, - 0x09 => OpcodeType.Jmp, - 0x10 => OpcodeType.AndOrEbp, - 0x11 => OpcodeType.IoWrite, - 0x12 => OpcodeType.IoRead, - 0xEE => OpcodeType.Exit, - _ => (OpcodeType)value - }; - break; - case OpcodeVersion.EarlyDebug: - Type = value switch - { - 0x9A => OpcodeType.MemRead, - 0x5B => OpcodeType.MemWrite, - 0xF9 => OpcodeType.PciWrite, - 0xF5 => OpcodeType.PciRead, - 0xED => OpcodeType.AndOr, - 0x68 => OpcodeType.Chain, - 0x04 => OpcodeType.Jne, - 0x25 => OpcodeType.Jmp, - 0x6C => OpcodeType.AndOrEbp, - 0x3C => OpcodeType.IoWrite, - 0xC8 => OpcodeType.IoRead, - 0xBF => OpcodeType.Exit, - _ => (OpcodeType)value - }; - break; - case OpcodeVersion.LateDebug: - Type = value switch - { - 0x09 => OpcodeType.MemRead, - 0x03 => OpcodeType.MemWrite, - 0x01 => OpcodeType.PciWrite, - 0x05 => OpcodeType.PciRead, - 0x06 => OpcodeType.AndOr, - 0xE1 => OpcodeType.Chain, - 0x04 => OpcodeType.Jne, - 0x07 => OpcodeType.Jmp, - 0x02 => OpcodeType.IoWrite, - 0x08 => OpcodeType.IoRead, - 0xEE => OpcodeType.Exit, - _ => (OpcodeType)value - }; - break; - } + OpcodeVersion.EarlyDebug => OpcodeDefinitions.EarlyDebugOpcodeDefinitions.Forward[value], + OpcodeVersion.LateDebug => OpcodeDefinitions.LateDebugOpcodeDefinitions.Forward[value], + OpcodeVersion.Retail => OpcodeDefinitions.RetailOpcodeDefinitions.Forward[value], + _ => throw new ArgumentOutOfRangeException(nameof(version), version, null) + }; } public Opcode(OpcodeType type, OpcodeVersion version = OpcodeVersion.Retail) { Type = type; - switch (version) + Value = version switch { - case OpcodeVersion.Retail: - Value = type switch - { - OpcodeType.MemRead => 0x02, - OpcodeType.MemWrite => 0x03, - OpcodeType.PciWrite => 0x04, - OpcodeType.PciRead => 0x05, - OpcodeType.AndOr => 0x06, - OpcodeType.Chain => 0x07, - OpcodeType.Jne => 0x08, - OpcodeType.Jmp => 0x09, - OpcodeType.AndOrEbp => 0x10, - OpcodeType.IoWrite => 0x11, - OpcodeType.IoRead => 0x12, - OpcodeType.Exit => 0xEE, - _ => (byte)type - }; - break; - case OpcodeVersion.EarlyDebug: - Value = type switch - { - OpcodeType.MemRead => 0x9A, - OpcodeType.MemWrite => 0x5B, - OpcodeType.PciWrite => 0xF9, - OpcodeType.PciRead => 0xF5, - OpcodeType.AndOr => 0xED, - OpcodeType.Chain => 0x68, - OpcodeType.Jne => 0x04, - OpcodeType.Jmp => 0x2, - OpcodeType.AndOrEbp => 0x6C, - OpcodeType.IoWrite => 0x3C, - OpcodeType.IoRead => 0xC8, - OpcodeType.Exit => 0xBF, - _ => (byte)type - }; - break; - case OpcodeVersion.LateDebug: - - Value = type switch - { - OpcodeType.MemRead => 0x09, - OpcodeType.MemWrite => 0x03, - OpcodeType.PciWrite => 0x01, - OpcodeType.PciRead => 0x05, - OpcodeType.AndOr => 0x06, - OpcodeType.Chain => 0xE1, - OpcodeType.Jne => 0x04, - OpcodeType.Jmp => 0x07, - OpcodeType.IoWrite => 0x02, - OpcodeType.IoRead => 0x08, - OpcodeType.Exit => 0xEE, - _ => (byte)type - }; - break; - } + OpcodeVersion.EarlyDebug => OpcodeDefinitions.EarlyDebugOpcodeDefinitions.Reverse[type], + OpcodeVersion.LateDebug => OpcodeDefinitions.LateDebugOpcodeDefinitions.Reverse[type], + OpcodeVersion.Retail => OpcodeDefinitions.RetailOpcodeDefinitions.Reverse[type], + _ => throw new ArgumentOutOfRangeException(nameof(version), version, null) + }; } public override string ToString() @@ -151,7 +52,7 @@ public override string ToString() OpcodeType.Jmp => "xc_jmp", OpcodeType.Chain => "xc_chain", OpcodeType.Exit => "xc_exit", - _ => string.Format("xc_nop_{0:X2}", (byte)Type) + _ => $"xc_nop_{(byte) Type:X2}" }; } } diff --git a/src/xdecode/OpcodeDefinitions.cs b/src/xdecode/OpcodeDefinitions.cs new file mode 100644 index 0000000..d53b41d --- /dev/null +++ b/src/xdecode/OpcodeDefinitions.cs @@ -0,0 +1,52 @@ +namespace xdecode +{ + public static class OpcodeDefinitions + { + public static readonly BiDirectionalDictionary EarlyDebugOpcodeDefinitions = new() + { + {0x9A, OpcodeType.MemRead}, + {0x5B, OpcodeType.MemWrite}, + {0xF9, OpcodeType.PciWrite}, + {0xF5, OpcodeType.PciRead}, + {0xED, OpcodeType.AndOr}, + {0x68, OpcodeType.Chain}, + {0x04, OpcodeType.Jne}, + {0x25, OpcodeType.Jmp}, + {0x6C, OpcodeType.AndOrEbp}, + {0x3C, OpcodeType.IoWrite}, + {0xC8, OpcodeType.IoRead}, + {0xBF, OpcodeType.Exit} + }; + + public static readonly BiDirectionalDictionary LateDebugOpcodeDefinitions = new() + { + {0x09, OpcodeType.MemRead}, + {0x03, OpcodeType.MemWrite}, + {0x01, OpcodeType.PciWrite}, + {0x05, OpcodeType.PciRead}, + {0x06, OpcodeType.AndOr}, + {0xE1, OpcodeType.Chain}, + {0x04, OpcodeType.Jne}, + {0x07, OpcodeType.Jmp}, + {0x02, OpcodeType.IoWrite}, + {0x08, OpcodeType.IoRead}, + {0xEE, OpcodeType.Exit} + }; + + public static readonly BiDirectionalDictionary RetailOpcodeDefinitions = new() + { + {0x02, OpcodeType.MemRead}, + {0x03, OpcodeType.MemWrite}, + {0x04, OpcodeType.PciWrite}, + {0x05, OpcodeType.PciRead}, + {0x06, OpcodeType.AndOr}, + {0x07, OpcodeType.Chain}, + {0x08, OpcodeType.Jne}, + {0x09, OpcodeType.Jmp}, + {0x10, OpcodeType.AndOrEbp}, + {0x11, OpcodeType.IoWrite}, + {0x12, OpcodeType.IoRead}, + {0xEE, OpcodeType.Exit} + }; + } +} \ No newline at end of file