chore(replay): scaffold project with machine builder and frame types

This commit is contained in:
dualfroz committed 2026-08-26 11:14:48 +02:00
1 parent f7f26720cb
commit 247e896815
5 files changed
+124

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Chip8.Replay</RootNamespace>
<AssemblyName>Chip8.Replay</AssemblyName>
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Chip8.Core\Chip8.Core.csproj" />
</ItemGroup>
</Project>
+31
View File
@@ -0,0 +1,31 @@
using Chip8.Core;
namespace Chip8.Replay;
public static class MachineBuilder
{
public static Machine fromMovie(InputMovie movie)
{
return new Machine(QuirksCodec.clone(movie.quirks), movie.randomSeed, movie.platform);
}
public static Machine fromMovie(InputMovie movie, byte[] rom)
{
var machine = fromMovie(movie);
machine.loadRom(rom);
return machine;
}
public static InputMovie headerFor(Machine machine, byte[] rom, string romName, int instructionsPerFrame, int? randomSeed)
{
var movie = new InputMovie
{
platform = machine.platform,
quirks = QuirksCodec.clone(machine.quirks),
randomSeed = randomSeed,
instructionsPerFrame = instructionsPerFrame,
};
movie.setRom(rom, romName);
return movie;
}
}
+32
View File
@@ -0,0 +1,32 @@
using System;
namespace Chip8.Replay;
public readonly struct MovieFrame : IEquatable<MovieFrame>
{
public int index { get; }
public KeyMask keys { get; }
public MovieFrame(int index, KeyMask keys)
{
if (index < 0)
{
throw new ArgumentOutOfRangeException(nameof(index), "movie frame index cannot be negative");
}
this.index = index;
this.keys = keys;
}
public MovieFrame(int index, ushort keyBits)
: this(index, new KeyMask(keyBits))
{
}
public bool Equals(MovieFrame other) => index == other.index && keys == other.keys;
public override bool Equals(object? obj) => obj is MovieFrame other && Equals(other);
public override int GetHashCode() => (index * 397) ^ keys.bits;
public override string ToString() => "frame " + index + " " + keys.toKeyList();
}
+28
View File
@@ -0,0 +1,28 @@
using System;
using System.Globalization;
namespace Chip8.Replay;
public static class RomHash
{
const ulong fnvOffsetBasis = 14695981039346656037UL;
const ulong fnvPrime = 1099511628211UL;
public static ulong compute(byte[] rom)
{
ulong hash = fnvOffsetBasis;
foreach (byte value in rom)
{
hash ^= value;
hash *= fnvPrime;
}
return hash;
}
public static string toHex(byte[] rom) => format(compute(rom));
public static string format(ulong hash) => hash.ToString("X16", CultureInfo.InvariantCulture);
public static ulong parse(string hex) =>
ulong.Parse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
+17
View File
@@ -0,0 +1,17 @@
namespace Chip8.Replay;
public sealed class TimelineSnapshot
{
public int frameIndex { get; }
public byte[] state { get; }
public TimelineSnapshot(int frameIndex, byte[] state)
{
this.frameIndex = frameIndex;
this.state = state;
}
public int stateSize => state.Length;
public override string ToString() => "snapshot frame=" + frameIndex + " bytes=" + state.Length;
}