From 99458b9d0b7b05695811adee0a8adfc95025faf0 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 27 Aug 2026 13:30:28 +0200 Subject: [PATCH] chore(cli): scaffold CLI project with option parsing --- src/Chip8.Cli/Chip8.Cli.csproj | 22 +++++++ src/Chip8.Cli/Options.cs | 116 +++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/Chip8.Cli/Chip8.Cli.csproj create mode 100644 src/Chip8.Cli/Options.cs diff --git a/src/Chip8.Cli/Chip8.Cli.csproj b/src/Chip8.Cli/Chip8.Cli.csproj new file mode 100644 index 0000000..926193e --- /dev/null +++ b/src/Chip8.Cli/Chip8.Cli.csproj @@ -0,0 +1,22 @@ + + + + Exe + net6.0 + disable + enable + Chip8.Cli + Chip8.Cli + 10 + true + + + + + + + + + + + diff --git a/src/Chip8.Cli/Options.cs b/src/Chip8.Cli/Options.cs new file mode 100644 index 0000000..ca380e1 --- /dev/null +++ b/src/Chip8.Cli/Options.cs @@ -0,0 +1,116 @@ +using System; +using Chip8.Core; + +namespace Chip8.Cli; + +sealed class Options +{ + public string romPath = ""; + public bool headless; + public int cycles = 2000; + public int scale = 14; + public int instructionsPerFrame = 11; + public int? seed; + public string quirksProfile = "auto"; + public string platformName = "chip8"; + public string paletteName = "octo"; + public int maxFrames; + public string? screenshotPath; + public string? dumpPpmPath; + public string? dumpWavPath; + + public Platform buildPlatform() => platformName.ToLowerInvariant() switch + { + "superchip" or "schip" => Platform.SuperChip, + "xochip" or "xo" => Platform.XoChip, + _ => Platform.Chip8, + }; + + public Quirks? buildQuirks() => quirksProfile.ToLowerInvariant() switch + { + "auto" => null, + "cosmac" => Quirks.cosmacVip(), + "superchip" => Quirks.superChip(), + "xochip" => Quirks.xoChip(), + _ => Quirks.modern(), + }; + + public Palette buildPalette() => Palette.byName(paletteName); + + public static Options parse(string[] args) + { + var options = new Options(); + int index = 0; + + while (index < args.Length) + { + string token = args[index]; + switch (token) + { + case "--headless": + options.headless = true; + index++; + break; + case "--cycles": + options.cycles = int.Parse(args[++index]); + index++; + break; + case "--scale": + options.scale = int.Parse(args[++index]); + index++; + break; + case "--ipf": + options.instructionsPerFrame = int.Parse(args[++index]); + index++; + break; + case "--seed": + options.seed = int.Parse(args[++index]); + index++; + break; + case "--quirks": + options.quirksProfile = args[++index]; + index++; + break; + case "--platform": + options.platformName = args[++index]; + index++; + break; + case "--palette": + options.paletteName = args[++index]; + index++; + break; + case "--frames": + options.maxFrames = int.Parse(args[++index]); + index++; + break; + case "--shot": + options.screenshotPath = args[++index]; + index++; + break; + case "--ppm": + options.dumpPpmPath = args[++index]; + index++; + break; + case "--wav": + options.dumpWavPath = args[++index]; + index++; + break; + default: + if (token.StartsWith("--")) + { + throw new ArgumentException($"Unknown option: {token}"); + } + options.romPath = token; + index++; + break; + } + } + + if (options.romPath.Length == 0) + { + throw new ArgumentException("No ROM path given."); + } + + return options; + } +}