Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BiDirectionalDictionary for opcodes #1

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/xdecode/BiDirectionalDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Collections;
using System.Collections.Generic;

namespace xdecode
{
public class BiDirectionalDictionary<T1, T2> : IEnumerable<KeyValuePair<T1, T2>>
{
private readonly Dictionary<T1, T2> _forward = new();
private readonly Dictionary<T2, T1> _reverse = new();

public Indexer<T1, T2> Forward { get; }
public Indexer<T2, T1> Reverse { get; }

public BiDirectionalDictionary()
{
Forward = new Indexer<T1, T2>(_forward);
Reverse = new Indexer<T2, T1>(_reverse);
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public IEnumerator<KeyValuePair<T1, T2>> 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<T3, T4>
{
private readonly Dictionary<T3, T4> _dictionary;

public T4 this[T3 index]
{
get => _dictionary[index];
set => _dictionary[index] = value;
}

public Indexer(Dictionary<T3, T4> dictionary)
{
_dictionary = dictionary;
}

public bool Contains(T3 key)
{
return _dictionary.ContainsKey(key);
}
}
}
}
135 changes: 18 additions & 117 deletions src/xdecode/Opcode.cs
Original file line number Diff line number Diff line change
@@ -1,138 +1,39 @@
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;

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()
Expand All @@ -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}"
};
}
}
Expand Down
52 changes: 52 additions & 0 deletions src/xdecode/OpcodeDefinitions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
namespace xdecode
{
public static class OpcodeDefinitions
{
public static readonly BiDirectionalDictionary<byte, OpcodeType> 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<byte, OpcodeType> 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<byte, OpcodeType> 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}
};
}
}