feat(replay): add key mask input encoding
This commit is contained in:
1 parent
247e896815
commit
fe85a30407
1 file changed
+143
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Chip8.Replay;
|
||||
|
||||
public readonly struct KeyMask : IEquatable<KeyMask>
|
||||
{
|
||||
public const int keyCount = 16;
|
||||
public const ushort fullMask = 0xFFFF;
|
||||
|
||||
public ushort bits { get; }
|
||||
|
||||
public KeyMask(ushort bits)
|
||||
{
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
public static KeyMask empty => new KeyMask(0);
|
||||
|
||||
public bool isEmpty => bits == 0;
|
||||
|
||||
public int pressedCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
for (int key = 0; key < keyCount; key++)
|
||||
{
|
||||
if ((bits & (1 << key)) != 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isPressed(int key) => (bits & (1 << (key & 0xF))) != 0;
|
||||
|
||||
public KeyMask withPressed(int key) => new KeyMask((ushort)(bits | (1 << (key & 0xF))));
|
||||
|
||||
public KeyMask withReleased(int key) => new KeyMask((ushort)(bits & ~(1 << (key & 0xF))));
|
||||
|
||||
public KeyMask with(int key, bool pressed) => pressed ? withPressed(key) : withReleased(key);
|
||||
|
||||
public KeyMask union(KeyMask other) => new KeyMask((ushort)(bits | other.bits));
|
||||
|
||||
public KeyMask intersect(KeyMask other) => new KeyMask((ushort)(bits & other.bits));
|
||||
|
||||
public static KeyMask fromKeys(params int[] keys)
|
||||
{
|
||||
ushort acc = 0;
|
||||
foreach (int key in keys)
|
||||
{
|
||||
acc |= (ushort)(1 << (key & 0xF));
|
||||
}
|
||||
return new KeyMask(acc);
|
||||
}
|
||||
|
||||
public static KeyMask fromKeypad(bool[] keypad)
|
||||
{
|
||||
ushort acc = 0;
|
||||
for (int key = 0; key < keyCount && key < keypad.Length; key++)
|
||||
{
|
||||
if (keypad[key])
|
||||
{
|
||||
acc |= (ushort)(1 << key);
|
||||
}
|
||||
}
|
||||
return new KeyMask(acc);
|
||||
}
|
||||
|
||||
public void applyTo(bool[] keypad)
|
||||
{
|
||||
for (int key = 0; key < keyCount && key < keypad.Length; key++)
|
||||
{
|
||||
keypad[key] = (bits & (1 << key)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string toHex() => bits.ToString("X4", System.Globalization.CultureInfo.InvariantCulture);
|
||||
|
||||
public string toKeyList()
|
||||
{
|
||||
if (bits == 0)
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
for (int key = 0; key < keyCount; key++)
|
||||
{
|
||||
if ((bits & (1 << key)) != 0)
|
||||
{
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
builder.Append(',');
|
||||
}
|
||||
builder.Append(key.ToString("X1", System.Globalization.CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public static KeyMask parseHex(string text)
|
||||
{
|
||||
ushort value = ushort.Parse(text, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture);
|
||||
return new KeyMask(value);
|
||||
}
|
||||
|
||||
public static KeyMask parseKeyList(string text)
|
||||
{
|
||||
if (text == "-" || text.Length == 0)
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
|
||||
ushort acc = 0;
|
||||
foreach (string chunk in text.Split(','))
|
||||
{
|
||||
string trimmed = chunk.Trim();
|
||||
if (trimmed.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int key = Convert.ToInt32(trimmed, 16);
|
||||
acc |= (ushort)(1 << (key & 0xF));
|
||||
}
|
||||
return new KeyMask(acc);
|
||||
}
|
||||
|
||||
public bool Equals(KeyMask other) => bits == other.bits;
|
||||
|
||||
public override bool Equals(object? obj) => obj is KeyMask other && Equals(other);
|
||||
|
||||
public override int GetHashCode() => bits;
|
||||
|
||||
public override string ToString() => "KeyMask(" + toKeyList() + ")";
|
||||
|
||||
public static bool operator ==(KeyMask left, KeyMask right) => left.bits == right.bits;
|
||||
|
||||
public static bool operator !=(KeyMask left, KeyMask right) => left.bits != right.bits;
|
||||
}
|
||||
Reference in new issue
Block a user