feat(core): add font set, quirks config, and save-state snapshot
This commit is contained in:
1 parent
434dcbae15
commit
87ac07c68e
3 files changed
+175
No files matched your search
@@ -0,0 +1,48 @@
|
|||||||
|
namespace Chip8.Core;
|
||||||
|
|
||||||
|
internal static class FontSet
|
||||||
|
{
|
||||||
|
public const int glyphBytes = 5;
|
||||||
|
|
||||||
|
public const int bigGlyphBytes = 10;
|
||||||
|
|
||||||
|
public static readonly byte[] glyphs =
|
||||||
|
{
|
||||||
|
0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
|
||||||
|
0x20, 0x60, 0x20, 0x20, 0x70, // 1
|
||||||
|
0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
|
||||||
|
0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
|
||||||
|
0x90, 0x90, 0xF0, 0x10, 0x10, // 4
|
||||||
|
0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
|
||||||
|
0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
|
||||||
|
0xF0, 0x10, 0x20, 0x40, 0x40, // 7
|
||||||
|
0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
|
||||||
|
0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
|
||||||
|
0xF0, 0x90, 0xF0, 0x90, 0x90, // A
|
||||||
|
0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
|
||||||
|
0xF0, 0x80, 0x80, 0x80, 0xF0, // C
|
||||||
|
0xE0, 0x90, 0x90, 0x90, 0xE0, // D
|
||||||
|
0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
|
||||||
|
0xF0, 0x80, 0xF0, 0x80, 0x80, // F
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] bigGlyphs =
|
||||||
|
{
|
||||||
|
0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C, // 0
|
||||||
|
0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, // 1
|
||||||
|
0x3E, 0x7F, 0xC3, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, // 2
|
||||||
|
0x3C, 0x7E, 0xC3, 0x03, 0x0E, 0x0E, 0x03, 0xC3, 0x7E, 0x3C, // 3
|
||||||
|
0x06, 0x0E, 0x1E, 0x36, 0x66, 0xC6, 0xFF, 0xFF, 0x06, 0x06, // 4
|
||||||
|
0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFE, 0x03, 0xC3, 0x7E, 0x3C, // 5
|
||||||
|
0x3E, 0x7C, 0xE0, 0xC0, 0xFC, 0xFE, 0xC3, 0xC3, 0x7E, 0x3C, // 6
|
||||||
|
0xFF, 0xFF, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x60, // 7
|
||||||
|
0x3C, 0x7E, 0xC3, 0xC3, 0x7E, 0x7E, 0xC3, 0xC3, 0x7E, 0x3C, // 8
|
||||||
|
0x3C, 0x7E, 0xC3, 0xC3, 0x7F, 0x3F, 0x03, 0x07, 0x7E, 0x7C, // 9
|
||||||
|
0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, // A
|
||||||
|
0xFC, 0xFE, 0xC3, 0xC3, 0xFE, 0xFE, 0xC3, 0xC3, 0xFE, 0xFC, // B
|
||||||
|
0x3C, 0x7E, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x7E, 0x3C, // C
|
||||||
|
0xFC, 0xFE, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFE, 0xFC, // D
|
||||||
|
0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFC, 0xC0, 0xC0, 0xFF, 0xFF, // E
|
||||||
|
0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFC, 0xC0, 0xC0, 0xC0, 0xC0, // F
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Chip8.Core;
|
||||||
|
|
||||||
|
public sealed class MachineSnapshot
|
||||||
|
{
|
||||||
|
public ushort pc { get; init; }
|
||||||
|
public ushort i { get; init; }
|
||||||
|
public byte sp { get; init; }
|
||||||
|
public byte delayTimer { get; init; }
|
||||||
|
public byte soundTimer { get; init; }
|
||||||
|
public int planeMask { get; init; }
|
||||||
|
public bool hires { get; init; }
|
||||||
|
public bool exited { get; init; }
|
||||||
|
public byte[] v { get; init; } = Array.Empty<byte>();
|
||||||
|
public ushort[] stack { get; init; } = Array.Empty<ushort>();
|
||||||
|
|
||||||
|
public static MachineSnapshot capture(Machine machine)
|
||||||
|
{
|
||||||
|
var stackFrames = new ushort[machine.sp];
|
||||||
|
Array.Copy(machine.stack, stackFrames, machine.sp);
|
||||||
|
return new MachineSnapshot
|
||||||
|
{
|
||||||
|
pc = machine.pc,
|
||||||
|
i = machine.i,
|
||||||
|
sp = machine.sp,
|
||||||
|
delayTimer = machine.delayTimer,
|
||||||
|
soundTimer = machine.soundTimer,
|
||||||
|
planeMask = machine.planeMask,
|
||||||
|
hires = machine.hires,
|
||||||
|
exited = machine.exited,
|
||||||
|
v = (byte[])machine.v.Clone(),
|
||||||
|
stack = stackFrames,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public string format()
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
builder.Append("PC=0x").Append(pc.ToString("X4", CultureInfo.InvariantCulture));
|
||||||
|
builder.Append(" I=0x").Append(i.ToString("X4", CultureInfo.InvariantCulture));
|
||||||
|
builder.Append(" SP=").Append(sp);
|
||||||
|
builder.Append(" DT=").Append(delayTimer);
|
||||||
|
builder.Append(" ST=").Append(soundTimer);
|
||||||
|
builder.Append(" plane=").Append(planeMask);
|
||||||
|
builder.Append(" hires=").Append(hires ? "1" : "0");
|
||||||
|
builder.Append('\n');
|
||||||
|
|
||||||
|
for (int register = 0; register < v.Length; register++)
|
||||||
|
{
|
||||||
|
builder.Append('V').Append(register.ToString("X1", CultureInfo.InvariantCulture));
|
||||||
|
builder.Append('=').Append(v[register].ToString("X2", CultureInfo.InvariantCulture));
|
||||||
|
builder.Append((register & 0x7) == 0x7 ? '\n' : ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append("stack=[");
|
||||||
|
for (int frame = 0; frame < stack.Length; frame++)
|
||||||
|
{
|
||||||
|
if (frame > 0)
|
||||||
|
{
|
||||||
|
builder.Append(' ');
|
||||||
|
}
|
||||||
|
builder.Append("0x").Append(stack[frame].ToString("X4", CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
builder.Append("]\n");
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
namespace Chip8.Core;
|
||||||
|
|
||||||
|
public sealed class Quirks
|
||||||
|
{
|
||||||
|
public bool shiftUsesVy { get; set; }
|
||||||
|
|
||||||
|
public bool jumpWithVx { get; set; }
|
||||||
|
|
||||||
|
public bool loadStoreIncrementsI { get; set; }
|
||||||
|
|
||||||
|
public bool resetVfOnLogic { get; set; }
|
||||||
|
|
||||||
|
public bool clipSprites { get; set; }
|
||||||
|
|
||||||
|
public bool addToIndexSetsCarry { get; set; }
|
||||||
|
|
||||||
|
public static Quirks cosmacVip() => new()
|
||||||
|
{
|
||||||
|
shiftUsesVy = true,
|
||||||
|
jumpWithVx = false,
|
||||||
|
loadStoreIncrementsI = true,
|
||||||
|
resetVfOnLogic = true,
|
||||||
|
clipSprites = true,
|
||||||
|
addToIndexSetsCarry = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Quirks modern() => new()
|
||||||
|
{
|
||||||
|
shiftUsesVy = false,
|
||||||
|
jumpWithVx = false,
|
||||||
|
loadStoreIncrementsI = false,
|
||||||
|
resetVfOnLogic = false,
|
||||||
|
clipSprites = true,
|
||||||
|
addToIndexSetsCarry = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Quirks superChip() => new()
|
||||||
|
{
|
||||||
|
shiftUsesVy = false,
|
||||||
|
jumpWithVx = true,
|
||||||
|
loadStoreIncrementsI = false,
|
||||||
|
resetVfOnLogic = false,
|
||||||
|
clipSprites = true,
|
||||||
|
addToIndexSetsCarry = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Quirks xoChip() => new()
|
||||||
|
{
|
||||||
|
shiftUsesVy = false,
|
||||||
|
jumpWithVx = false,
|
||||||
|
loadStoreIncrementsI = false,
|
||||||
|
resetVfOnLogic = false,
|
||||||
|
clipSprites = false,
|
||||||
|
addToIndexSetsCarry = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in new issue
Block a user