S1 CLI reference

Every command-line flag and environment variable of the golden switch-level engine — verified against the source, not the changelog.

黃金開關級引擎的每一個命令列旗標與環境變數 —— 對原始碼驗證,不是對變更紀錄。

71 CLI flags · 16 environment variables. The authoritative parser is src/AprVisual.S1/Test/TestRunner.cs; shim and mux behavior live in Test/TestRunner.Test.cs and Sim/WireCore.System.cs. Run as dotnet run --project src/AprVisual.S1 -- <flags> or dotnet AprVisual.S1.dll <flags>.

71 個 CLI 旗標 · 16 個環境變數。權威解析器是 src/AprVisual.S1/Test/TestRunner.cs;shim 與 mux 行為在 Test/TestRunner.Test.csSim/WireCore.System.cs。執行方式:dotnet run --project src/AprVisual.S1 -- <flags>dotnet AprVisual.S1.dll <flags>

← AprVisual (S1) hub← AprVisual 主站(S1) S1a CLI reference →S1a CLI 參考 →
One engine, one parser. The S1a fork (src/AprVisual.S1A/) currently shares every one of these 71 flags and 16 env vars, and adds its own mechanism toggles on top (the M2 / M4 / M6X physics mechanisms + extra per-shim kill switches). If you are driving S1a, read this page for the shared surface and the S1a CLI reference for what it adds. 一個引擎,一個解析器。S1a 分支(src/AprVisual.S1A/)目前共用這 71 個旗標與 16 個環境變數的每一個,並在其上加自己的機制開關(M2 / M4 / M6X 物理機制 + 額外的 per-shim 關閉開關)。若你在操作 S1a,共用面看這頁,新增的看 S1a CLI 參考

1 · Entry points1 · 入口Mode selectors執行模式(擇一)

Pick exactly one. The first matching mode below wins; everything else on the line composes as options.

擇一。下方第一個命中的模式生效;同一行其餘參數當選項組合。

Flag旗標Argument引數What it does作用
--benchmark<rom>Throughput mode: run a fixed number of master half-cycles, print hc/s, simulated FPS, MIPS, and the NodeStates checksum (the golden-verification hash). The ROM path after the flag is optional.效能量測模式:跑固定數量的主 half-cycle,輸出 hc/s、模擬 FPS、MIPS,以及 NodeStates checksum(黃金驗證雜湊)。旗標後的 ROM 路徑可選。
--test<rom>Run one test ROM to a verdict (blargg $6000 protocol, AccuracyCoin completion block, screen text, or CRC) or until the frame budget runs out. The result is carried in the process exit code.跑單顆測試 ROM 到判定(blargg $6000 協定、AccuracyCoin 完成塊、畫面文字或 CRC),或跑到幀預算耗盡。結果由 process exit code 帶出。
--test-dir<dir>Batch-run every *.nes under a directory (recursive); prints an N/total passed summary and returns non-zero on any failure.批次跑目錄下每顆 *.nes(遞迴);印 N/total passed 總結,有任一失敗回傳非零。
--rom<rom>The headless build has no live window, so a bare ROM renders 3 frames to screenshot.png. Also the positional catch-all when no other mode is given.headless 版沒有即時視窗,純 ROM 會 render 3 幀到 screenshot.png。也是沒給其他模式時的位置性引數。
--selftestRun the built-in hand-wired inverter / NAND / pass-gate / callback / static-merge micro-circuits (no ROM needed).跑內建手工接線的 inverter / NAND / pass-gate / callback / static-merge 微電路(不需 ROM)。
--help -h /?Print usage and exit.印使用說明並結束。

2 · Simulation environment2 · 模擬環境How the chip is loaded and run晶片怎麼載入與跑

Flag旗標Argument引數What it does作用
--system-def-dir<dir>Directory of the .js system-module definitions (default data/system-def). The golden recipe points this at AprVisualBenchMark/data/system-def..js 系統模組定義的目錄(預設 data/system-def)。黃金配方指向 AprVisualBenchMark/data/system-def
--extra-ramForce-map cart extra-RAM ($6000-$7FFF). Required for the golden checksum. Note: --ac-verdict auto-disables it, because AccuracyCoin measures the open bus in that region.強制掛載 cart extra-RAM($6000-$7FFF)。金 checksum 必帶。注意:--ac-verdict 會自動停用它,因為 AccuracyCoin 量的是該區 open bus。
--regionntsc|pal|dendySelect region timing (default ntsc).選區域時序(預設 ntsc)。
--joypadAttach the behavioral joypad + u7/u8 tie-rewire (per-test). Needed for controller / exec-space ROMs. OFF by default — the module swap + 6 tie rewires are a load-time graph change that re-rolls the power-on alignment lottery.掛上行為層手把 + u7/u8 tie-rewire(per-test)。手把 / 執行空間類 ROM 需要。預設關 —— 模組置換 + 6 條 tie rewire 是載入期圖變更,會重擲開機對齊彩票。
--reset-hold-extra<K>Hold reset K extra half-cycles (a CPU/PPU power-on phase-alignment experiment). The flagship AccuracyCoin recipe uses K=1.reset 多按住 K 個 half-cycle(CPU/PPU 開機相位對齊實驗)。旗艦 AccuracyCoin 配方用 K=1
--pin[N]Pin the hot thread, raise to High priority, disable EcoQoS — cuts bench variance (Windows). No arg = auto-pick the quietest P-core; N = force logical core N. Opt-in, bit-exact, does not touch clock frequency.把熱執行緒釘核、拉 High priority、關 EcoQoS —— 降 bench variance(Windows)。無引數 = 自動挑最安靜的 P-core;N = 強制邏輯核 N。opt-in、bit-exact、碰頻率。
--no-lowerSkip the S1.5 netlist-lowering pass (the mapped-checksum A/B gate).跳過 S1.5 netlist-lowering pass(mapped-checksum 的 A/B 閘)。
--fast-pathNo-op — the fast-path is always on in S1; accepted for compatibility.無作用 —— fast-path 在 S1 恆開;保留相容性。

3 · Verdict detection3 · 測試判定How a test-ROM result is read測試 ROM 結果怎麼判

Flag旗標Argument引數What it does作用
--ac-verdictAccuracyCoin unattended verdict: read the completion block in CPU RAM $07F0 (magic DE B0 61 + passed/total/skipped). Auto-disables extra-RAM. Includes storm detection (PC parked in $06xx for 120 frames → judge from the results table = an epilogue frame-IRQ storm) and dumps the $0400-$04FF results table at exit.AccuracyCoin 無人值守判定:讀 CPU RAM $07F0 完成塊(magic DE B0 61 + passed/total/skipped)。自動停用 extra-RAM。含風暴偵測(PC 停 $06xx 達 120 幀 → 由結果表判 = epilogue frame-IRQ storm),並在結束時傾印 $0400-$04FF 結果表。
--screen-verdictB-class: per-frame nametable scan for a terminal Passed/Failed marker (or old-blargg $0X code); requires 2 consecutive identical frames.B 類:逐幀掃 nametable 找 terminal Passed/Failed 標記(或舊 blargg $0X 碼);需連續 2 幀相同。
--pass-marker<txt>Custom terminal PASS text for ROMs that never print "Passed" (e.g. read_joy3 tallies).為不印 "Passed" 的 ROM 自訂 terminal PASS 字串(如 read_joy3 計數)。
--expected-crc<A,B,…>C-class: comma-separated accept set for an isolated on-screen 8-hex CRC (dmc_dma visual tests); 2-frame confirm.C 類:畫面上孤立 8-hex CRC 的逗號分隔接受集(dmc_dma 視覺測試);2 幀確認。
--max-wait<sec>Wall-clock safety cap in seconds (0 = disabled). --max-frames is the primary limit.wall-clock 安全上限(秒;0 = 停用)。--max-frames 才是主要限制。
--max-frames<N>Simulation-frame budget — the primary limit (default 900 ≈ 15 sim-seconds). A too-small budget looks like a hang; get a frame baseline from AprNes first.模擬幀預算 —— 主要限制(預設 900 ≈ 15 模擬秒)。預算太小看起來像卡死;先用 AprNes 拿幀數基準。
--input"<spec>"Scripted controller input, AprNes-compatible Button:sec[:holdSec] (e.g. A:2,Start:6.5). 60.0988 fps; default hold 10 frames.腳本化手把輸入,AprNes 相容 Button:秒[:holdSec](如 A:2,Start:6.5)。60.0988 fps;預設 hold 10 幀。
--test-json<path>Write a structured per-test result record (schema aprvisual-testrom/1; consumed by tools/testrom/build_report.py).寫結構化的每測結果記錄(schema aprvisual-testrom/1;由 tools/testrom/build_report.py 消化)。
--test-screenshot<path>Save the final frame as a PNG for the report page.把最終幀存成 PNG 給報告頁用。
--shot-delay<N>Run N extra frames after the verdict before the screenshot (cosmetic — some ROMs keep rendering disabled until after they publish the verdict bytes).判定後多跑 N 幀再截圖(裝飾用 —— 有些 ROM 在公布判定位元組前一直關渲染)。

4 · Snapshot / resume · 5 · progress4 · 快照/續跑 · 5 · 進度Windowed regression & long-run telemetry窗口回歸與長跑遙測

Flag旗標Argument引數What it does作用
--snapshot-frames<N>Full engine-state snapshot every N frames (0 = off). ~380 KB each; a v2 state_fNNNNNN.sav carries live shim state + a CRC-32.每 N 幀存完整引擎狀態(0 = 關)。每顆 ~380 KB;v2 state_fNNNNNN.sav 含 live shim 狀態 + CRC-32。
--snapshot-dir<dir>Where the snapshot .sav files land.snapshot .sav 檔輸出目錄。
--resume<sav>Restore a snapshot after LoadSystem and continue from its frame+1. A fingerprint check (node/transistor counts, ROM CRC, shim flags) refuses a mismatch — you cannot resume a joyON snapshot into a joyOFF build.LoadSystem 後還原快照,從它的 frame+1 續跑。指紋校驗(節點/電晶體數、ROM CRC、shim 旗標)不符即拒 —— joyON 快照不能 resume 進 joyOFF 版。
--progress-frames<N>Every N frames, checkpoint a screenshot (latest.png) + append a JSON status line to progress.jsonl (frame, sim-sec, hc, wall, CPU PC/AB/DB, AC stage). 0 = off.每 N 幀 checkpoint 一張截圖(latest.png)+ 對 progress.jsonl 追加一行 JSON 狀態(frame、sim 秒、hc、wall、CPU PC/AB/DB、AC stage)。0 = 關。
--progress-dir<dir>Where those checkpoints land (cleared of stale files at start, so the data describes exactly one run).checkpoint 輸出目錄(啟動時清舊檔,確保資料只描述一次 run)。

6 · Benchmark / perf6 · 效能量測Throughput knobs & profiling dumps吞吐旋鈕與剖析傾印

Flag旗標Argument引數What it does作用
--bench-hc<N>Benchmark exactly N raw master half-cycles. Golden: 3000000x794A43ABDF169ADA.benchmark 精確跑 N 個原始主 half-cycle。金:3000000x794A43ABDF169ADA
--log-dir<dir>Benchmark JSON log output directory (default log).benchmark JSON log 輸出目錄(預設 log)。
--dump-states<path>After the bench run, dump per-node states for A/B per-node diffing.bench 跑完後傾印全節點狀態,做 A/B 逐節點 diff。
--array-footprintPrint the hot unmanaged-array base+size at bench setup (for IBS/SPE data-address bucketing).bench 設定時印熱 unmanaged 陣列的 base+size(供 IBS/SPE 資料位址分桶)。
--payload-hist<path>NodeInfo inline-payload size distribution (the 16-byte-pack study).NodeInfo inline-payload 大小分佈(16-byte-pack 研究)。
--fc-taint-stats<path>same-state-prune eligibility: FC-free vs FC-tainted channel components (diagnostic only).same-state-prune 適格性:FC-free vs FC-tainted channel 元件(僅診斷)。

7 · Shim toggles & environment variables7 · Shim 開關與環境變數The analog-race patch surface類比賽跑補丁面

Shims are small, honest, test-mode-only overrides that supply behavior the binary switch-level model structurally cannot express. The benchmark path never loads them. Each has an A/B kill switch — some as a CLI flag, some as an environment variable.

Shim 是小而誠實、只在 test 模式的覆蓋,補上二值開關級模型結構上表達不了的行為。benchmark 路徑一律不載。每個都有 A/B 關閉開關 —— 有的是 CLI 旗標,有的是環境變數。

CLI shim flagsCLI shim 旗標

Flag旗標Argument引數What it does作用
--no-shimsDisable all test-mode shims (diagnostics).停用全部 test-mode shim(診斷)。
--no-alu-shimA/B the ALU input-latch hold shim (ANC/ALR/ARR family).A/B:ALU 輸入 latch hold shim(ANC/ALR/ARR 家族)。
--no-dbl2007-shimA/B the $2007 double-read merge shim.A/B:$2007 雙讀合併 shim。
--no-ppu-ale-read-feedback-shimExpose the raw CHR ALE+/RD binary analog-feedback loop (a P4 feedback guard; A/B).暴露原始 CHR ALE+/RD 二值類比回授環(P4 回授 guard;A/B)。
--oam-dma-ppu-bus-shimRe-affirm the $4014-from-PPU-I/O-bus OAM write-data hold — already ON by default.重申 $4014-自-PPU-I/O-bus 的 OAM 寫資料 hold —— 預設本來就開。
--no-oam-dma-ppu-bus-shimDisable that OAM-DMA-PPU-bus shim.停用該 OAM-DMA-PPU-bus shim。
--ppu-write-delay<N>$2001 write-effect delay in hc (even_odd family; default 16; narrow window vpos261/hpos338-339; 0 = off).$2001 寫入生效延遲 N hc(even_odd 家族;預設 16;窄窗 vpos261/hpos338-339;0 = 關)。
--ppu-write-delay-global<N>dot-339 sprite-counter-reset delay in hc on visible lines (StaleSprite Test3; default 24; 0 = off).可見掃描線上 dot-339 精靈計數器重置延遲 N hc(StaleSprite Test3;預設 24;0 = 關)。
--callback-drain-limit<N>Non-convergence guard: if one callback drain exceeds N dispatches, fail with callback/node evidence instead of hanging (the AC recipe uses 2000).非收斂 guard:單次 callback 排水超過 N 次 dispatch 就帶 callback/node 證據失敗,而非卡死(AC 配方用 2000)。

Environment variables (16)環境變數(16 個)

Env vars are scanned globally with GetEnvironmentVariable in TestRunner.Test.cs and WireCore.System.cs — there is no CLI switch for these. Group A tunes the ALERead mux; Group B are per-shim kill switches (set = skip that shim); Group C are forensic trace probes.

環境變數在 TestRunner.Test.csWireCore.System.csGetEnvironmentVariable 全域掃描 —— 沒有對應的 CLI 開關。A 組調 ALERead mux;B 組是 per-shim 關閉開關(有設 = 跳過該 shim);C 組是取證追蹤探針。

Variable變數ValueWhat it does作用
Group A — ALERead phase muxA 組 — ALERead 相位 mux
ALEREAD_MUXset (any)有設(任意)Arm the ALERead $2007-access phase mux + node-split (cuts ppu.io_abcpu.ab). MUST be present before LoadSystem — presence alone is the switch. Required for the ALERead test; the flagship recipe sets ALEREAD_MUX=1. This is the one everyone forgets.武裝 ALERead $2007 存取相位 mux + node-split(切開 ppu.io_abcpu.ab)。必須在 LoadSystem 前存在 —— 有設就是開。ALERead 測試必需;旗艦配方設 ALEREAD_MUX=1。這就是大家最常忘的那個。
MUX_HCsw,rpS,rpE,fzS,fzETune the five mux window edges (swallow-end, replay-start, replay-end, freeze-start, freeze-end). Default 13,13,25,44,52 — the only calibration verified to PASS in-suite (the code default already matches).調 mux 五個窗邊(swallow-end、replay-start、replay-end、freeze-start、freeze-end)。預設 13,13,25,44,52 —— 唯一驗證套內 PASS 的校準(code 預設已同)。
MUX_GATEvlo,vhi,hlo,hhiOverride the mux detection gate (vpos lo/hi, hpos lo/hi). Default 3,3,220,226 — kept tight so only the boing2k7 stunt read triggers it.覆蓋 mux 偵測閘(vpos lo/hi、hpos lo/hi)。預設 3,3,220,226 —— 保持很緊,只有 boing2k7 特技讀取會觸發。
MUX_DBGset有設Print [mux] arm/detect/replay/freeze trace lines (also switched on by OB_DEBUG).[mux] arm/detect/replay/freeze 追蹤行(OB_DEBUG 也會開)。
Group B — per-shim kill switches (set = skip)B 組 — per-shim 關閉開關(有設 = 跳過)
NO_OB_SHIMset有設Skip the open-bus last-transferred-byte replay shim.跳過 open-bus 最後傳輸位元組重放 shim。
NO_DL_SHIMset有設Skip the DL/idl φ2-transparency shim at $4016/$4017.跳過 $4016/$4017 的 DL/idl φ2 透明 shim。
NO_ABORT_SHIMset有設Skip the deferred-$4015 DMC-DMA abort shim.跳過延遲 $4015 的 DMC-DMA 中止 shim。
NO_OAMEDGE_SHIMset有設Skip the rendering-disable-edge OAM-write-suppression shim.跳過關渲染邊沿抑制 OAM 寫入的 shim。
NO_BGS_SHIMset有設Skip the BG-serial reload-delay shim ($2001-enable at the dot%8==7 shifter-load boundary; M6 family).跳過 BG 序列 reload 延遲 shim($2001 致能在 dot%8==7 移位器載入邊界;M6 家族)。
Group C — forensic debug probesC 組 — 取證除錯探針
OB_DEBUG1Turn on the test-only forensic probe group ([ob]/[obshim]/[dl]/[dma]/[pcm]/[a5]/[fin]/[ae]…; some carry hardcoded time windows — TEMP diagnostics). Also enables the mux trace.開 test-only 取證探針群([ob]/[obshim]/[dl]/[dma]/[pcm]/[a5]/[fin]/[ae]…;部分帶硬編時間窗 —— TEMP 診斷)。也會開 mux 追蹤。
LAE_DEBUG1LAE shim forensic output (read-loop, merged-value derivation).LAE shim 取證輸出(讀取環、合併值推導)。
ODMA_DEBUGset有設OAM-DMA-PPU-bus shim forensic output.OAM-DMA-PPU-bus shim 取證輸出。
PB_DEBUGset有設PPU ALE/read-feedback shim forensic output.PPU ALE/read-feedback shim 取證輸出。
PWD_DEBUG1$2001 write-delay shim forensic output.$2001 寫入延遲 shim 取證輸出。
OE_DEBUGset有設OAM-blank-edge shim forensic output.OAM-blank-edge shim 取證輸出。
PC_WINlo,hiA lo,hi time-window (in hc) that scopes the forensic probes; default = the original IDR-forensics window 13750000,15090000.一個 lo,hi 時間窗(以 hc 計),把取證探針的輸出限定在該範圍;預設 = 原始 IDR-forensics 窗 13750000,15090000

8 · Diagnostic probes8 · 診斷探針The forensic toolbox取證工具箱

Three probe rules (hard-won): (1) trust a PC sample only when two consecutive half-cycles agree — mid-instruction the PC register half-updates. (2) "budget exhausted" ≠ "hang" — get a frame baseline from AprNes first. (3) sample a bus transaction's value on its last half-cycle — the first half still carries the operand byte. 探針三鐵律(戰役學費):(1) PC 取樣要連續兩拍同值才可信 —— 指令執行中 PC 暫存器會半更新。(2)「預算耗盡」≠「卡死」—— 先用 AprNes 拿幀數基準。(3) 匯流排交易的值取樣「最後一個」半週期 —— 首半的 db 還是運算元位元組。
Flag旗標Argument引數What it does作用
--dump-node<name> / @<id>Dissect one node: its pull-up, the transistors it gates, and its channel-end transistors. @id uses the raw engine id. Note: this mode does not register raw-id aliases (cpu.#nnnn) — those resolve only in test mode.解剖單節點:pull-up、被它 gate 的電晶體、channel 端電晶體。@id 用引擎原始 id。注意:此模式掛 raw-id 別名(cpu.#nnnn)—— 別名只在 test 模式可解析。
--dump-module<name>Parse <system-def-dir>/<name>.js and print a summary.解析 <system-def-dir>/<name>.js 並印摘要。
--dump-systemCompose the full nes-001 + cart netlist and print counts + probes.組出完整 nes-001 + cart 網表並印計數 + 探針。
--names<id1,id2,…>Engine id → name (a LoadSystem that keeps the name map).引擎 id → 名稱(保留名稱映射的 LoadSystem)。
--watch<names>Comma list of node names, printed per frame (pairs with --micro; works after a --resume too).節點名逗號清單,每幀印(配 --micro;--resume 後也可用)。
--micro<path>Run N frames (see --micro-frames), dump work RAM $0200-$07FF.跑 N 幀(見 --micro-frames),傾印工作 RAM $0200-$07FF
--micro-frames<N>--micro frame count (default 3).--micro 幀數(預設 3)。
--trace<path>Classic trace-column output.傳統 trace 欄位輸出。
--cycles<N>--trace cycle count (default 64).--trace 週期數(預設 64)。
--bus-trace<path>DMC bus microscope ($4013/$4015 + RDY-stall cycles).DMC 匯流排顯微鏡($4013/$4015 + RDY-stall 週期)。
--op-probe<path> <hexaddr>hc-log the datapath buses when AB hits the given address.AB 命中指定位址時做 hc 級 datapath 匯流排記錄。
--rdy-probe<path>Per-frame cpu.rdy transition counts (DMC-DMA study).每幀 cpu.rdy 轉換計數(DMC-DMA 研究)。
--phase-probe<path>Per-hc CPU/PPU clock-phase dump (phase-alignment experiment).每 hc CPU/PPU 時鐘相位傾印(相位對齊實驗)。
--probe2002<path>Trace bus/PPU signals at the next $2002 read after vblank.追蹤 vblank 後下一個 $2002 讀取的匯流排/PPU 訊號。
--probe-vbl<path>Trace the 2C02 vbl-flag latch through the $2002 read path.追蹤 2C02 vbl 旗標 latch 經 $2002 讀取路徑。
--probe-2001<path>Trace a $2001 write → bkg_enable → rendering chain + the dot-339 skip window.追蹤 $2001 寫 → bkg_enable → rendering 鏈 + dot-339 skip 窗。
--probe-dma<path>Trace the OAM-DMA address bus + open bus (read_buffer #67).追蹤 OAM-DMA 位址匯流排 + open bus(read_buffer #67)。
--ppu-memory-trace<lo> <hi>Trace CHR/VRAM callbacks while the CPU PC is in this inclusive hex range.CPU PC 在此 hex 範圍(含端點)內時追蹤 CHR/VRAM callback。
--ppu-memory-trace-x<hex>Restrict the PPU memory trace to one CPU X value.把 PPU memory trace 限定到單一 CPU X 值。
--ac-dump-workDump AccuracyCoin work/results RAM $0500-$06FF at verdict (oracle comparison).判定時傾印 AccuracyCoin 工作/結果 RAM $0500-$06FF(oracle 比對)。

9 · Screen output9 · 畫面輸出Framebuffer dumpsframebuffer 傾印

Flag旗標Argument引數What it does作用
--screenshot<rom>Run N frames, dump the framebuffer to a PNG.跑 N 幀後把 framebuffer 傾印成 PNG。
--frames<N>Frame count for --screenshot / --ppu-dump (default 3).--screenshot / --ppu-dump 的幀數(預設 3)。
--out<path>Output PNG path for --screenshot (default screenshot.png).--screenshot 的輸出 PNG 路徑(預設 screenshot.png)。
--frame-dump<rom>Per-frame PNG dump with progress + timing.逐幀 PNG 傾印(含進度 + 計時)。
--frame-count<N>Number of frames for --frame-dump (default 50).--frame-dump 的幀數(預設 50)。
--out-dir<dir>Output directory for --frame-dump (default frames).--frame-dump 的輸出目錄(預設 frames)。
--ppu-dump<rom>Run N frames, then dump palette RAM / VRAM nametable / rendering state / pclk1 samples.跑 N 幀後傾印 palette RAM / VRAM nametable / rendering 狀態 / pclk1 取樣。

10 · Common recipes10 · 常用配方Copy-paste command lines可貼上的指令列

Golden checksum (run after ANY WireCore hot-path change)黃金驗證(任何 WireCore 熱路徑改動後必跑)

dotnet AprVisual.S1.dll --benchmark AprVisualBenchMark/roms/full_palette.nes --bench-hc 300000 \
  --extra-ram --system-def-dir AprVisualBenchMark/data/system-def
# checksum MUST be 0x794A43ABDF169ADA

AccuracyCoin flagship run (the full unattended sweep)AccuracyCoin 掛牌跑(完整無人值守)

The ALEREAD_MUX env is load-bearing and the thing everyone forgets. Without it the ALERead test fails; the calibration MUX_HC=13,13,25,44,52 is the only one verified to PASS in-suite (it equals the code default, so it is belt-and-suspenders). And the flagship must carry --max-frames 12000 — the default 900 stops the run long before completion. ALEREAD_MUX 環境變數是關鍵、也是大家最常忘的。沒有它 ALERead 測試就掛;校準 MUX_HC=13,13,25,44,52 是唯一驗證套內 PASS 的(它等於 code 預設,屬保險起見)。旗艦必帶 --max-frames 12000 —— 預設 900 會在跑完前就停。
ALEREAD_MUX=1 MUX_HC=13,13,25,44,52 \
dotnet AprVisual.S1.dll --test AprAccuracyCoinUnattended/AccuracyCoin.nes --ac-verdict --joypad \
  --callback-drain-limit 2000 --reset-hold-extra 1 --pin 2 \
  --system-def-dir AprVisualBenchMark/data/system-def --max-frames 12000 \
  --snapshot-frames 10 --snapshot-dir out/snaps --progress-frames 600 --progress-dir out/prog
# joyON ≈ 8-15 h; the numbers count only once the run finishes (ReportAC policy)

PowerShell: set the env vars first — $env:ALEREAD_MUX=1; $env:MUX_HC="13,13,25,44,52"; dotnet …PowerShell:先設環境變數 —— $env:ALEREAD_MUX=1; $env:MUX_HC="13,13,25,44,52"; dotnet …

Single isolated AccuracyCoin ROM (reproduce / verify one test)單顆孤立 AccuracyCoin ROM(重現 / 驗證一顆)

ALEREAD_MUX=1 \
dotnet AprVisual.S1.dll --test AprAccuracyCoinUnattended/AccuracyCoin_<Test>.nes --ac-verdict \
  --callback-drain-limit 2000 --reset-hold-extra 1 --pin 2 \
  --system-def-dir AprVisualBenchMark/data/system-def --max-frames 70 [--joypad]

Shim A/B isolation (suspected shim side-effect)Shim A/B 隔離(疑似 shim 副作用)

# turn every env-gated shim off, then re-enable one at a time to find the culprit:
NO_OB_SHIM=1 NO_DL_SHIM=1 NO_ABORT_SHIM=1 NO_OAMEDGE_SHIM=1 NO_BGS_SHIM=1 \
  dotnet AprVisual.S1.dll --test ...
# netlist-level shims use the --no-* CLI flags; --no-shims kills everything at once
One-runner rule: run only one simulation instance at a time (co-scheduled instances starve each other's cores); do not build during a benchmark (the DLL is locked). 單 runner 鐵律:同一時間只跑一個模擬實例(同時跑會互相餓死核心);benchmark 期間不 build(DLL 鎖)。

11 · The 147-ROM test battery11 · 147 測試 ROM 實戰Four verdict paths, a controller, and a budget四種判定、手把、與預算

The nes-test-roms battery (blargg's suites & friends — 147 NROM/CNROM NTSC ROMs) is judged once per simulated frame, headless. Each ROM belongs to one of four verdict classes; the batch runner tools/testrom/run_tests.py picks the right flags per-ROM from catalog.json, but this is how to drive any single one by hand. Unlike --ac-verdict, these all keep cart work-RAM mounted (test mode auto-sets ForceExtraRam — blargg's protocol lives at $6000).nes-test-roms 電池(blargg 系列 + 友軍 —— 147 顆 NROM/CNROM NTSC ROM),逐幀無畫面判定。每顆屬於四種判定類別之一;批次 runner tools/testrom/run_tests.pycatalog.json 為每顆挑對旗標,以下是手動跑單顆的方式。與 --ac-verdict 不同,這些一律掛卡帶工作 RAM(test 模式自動設 ForceExtraRam —— blargg 協定住在 $6000)。

Class類別How it judges怎麼判Extra flag額外旗標detection=
Ablargg $6000 protocol: reads a status byte at $6000 each frame (signature DE B0 61 at $6001-3); status <$80 = done, code 0 = pass. Most ROMs.blargg $6000 協定:每幀讀 $6000 狀態位元組($6001-3 簽名 DE B0 61);狀態 <$80 = 完成、碼 0 = 通過。多數 ROM。none (default)無(預設)6000
A-rSame, but the ROM asks for a soft reset (status $81): the engine pulses the console reset line and continues, up to 10 times.同上,但 ROM 要求軟重設(狀態 $81):引擎拉主機重設線後續跑,最多 10 次。none (automatic)無(自動)6000+reset
BScreen text: decode nametable 0 (tile = ASCII) each frame for a terminal Passed/Failed; 2-frame confirm.畫面文字:逐幀解 nametable 0(tile=ASCII)找 terminal Passed/Failed;連 2 幀確認。--screen-verdictscreen
CScreen CRC: find an isolated on-screen 8-hex CRC, match it against an accept set; 2-frame confirm.畫面 CRC:找畫面上孤立的 8-hex CRC,比對接受集;連 2 幀確認。--expected-crc <A,B,…>crc

Class A / A-r — the $6000 protocol (most ROMs)A / A-r 類 —— $6000 協定(多數 ROM)

dotnet AprVisual.S1.dll --test tools/testrom/roms/instr_test-v5/rom_singles/03-immediate.nes \
  --reset-hold-extra 1 --system-def-dir AprVisualBenchMark/data/system-def --max-frames 300
# exit 0 = PASS.  A-r (soft-reset) ROMs need no extra flag — the reset is automatic.

Class B — screen text (--screen-verdict)B 類 —— 畫面文字(--screen-verdict)

dotnet AprVisual.S1.dll --test tools/testrom/roms/other/palette_ram.nes --screen-verdict \
  --reset-hold-extra 1 --system-def-dir AprVisualBenchMark/data/system-def --max-frames 200
# for ROMs that print a custom tally instead of "Passed", add e.g. --pass-marker "Conflicts:"

Class C — screen CRC (--expected-crc)C 類 —— 畫面 CRC(--expected-crc)

dotnet AprVisual.S1.dll --test tools/testrom/roms/dmc_dma_during_read4/double_2007_read.nes \
  --expected-crc 3D8B4C6A,7F2E10A9 --reset-hold-extra 1 \
  --system-def-dir AprVisualBenchMark/data/system-def --max-frames 200
# PASS iff the on-screen CRC is in the comma-separated accept set (case-insensitive).

Controller simulation (--joypad + --input)手把模擬(--joypad + --input)

--joypad attaches a behavioral controller that drives the board's real CD4021 shift-register path through the LS368 buffer (the 2A03/2C02 netlists stay untouched); --input scripts button presses as Button:sec[:holdSec] at 60.0988 fps.--joypad 掛上行為層手把,驅動板上真實的 CD4021 移位暫存器路徑、經 LS368 緩衝(2A03/2C02 網表不動);--inputButton:秒[:holdSec](60.0988 fps)腳本化按鍵。

dotnet AprVisual.S1.dll --test tools/testrom/roms/read_joy3/test_buttons.nes --joypad \
  --input "A:2,B:2.5,Select:3,Start:3.5,Up:4,Down:4.5,Left:5,Right:5.5" --pass-marker "Errors:" \
  --reset-hold-extra 1 --system-def-dir AprVisualBenchMark/data/system-def --max-frames 500
# --joypad is a load-time graph change (u7/u8 tie-rewire) → scope it per-ROM, never globally.

Budget & timeout — how a run is bounded預算與 timeout —— 一次跑怎麼設界

Exit codes & the batch sweepExit code 與批次全跑

Exit code: 0 = pass · 1–125 = fail (the ROM's fail code) · 2 = load error · 3 = timeout. Judge from the --test-json status field, not the exit code alone. To run the whole battery (build → canary → 7-lane parallel sweep → report):Exit code:0 = 通過 · 1–125 = 失敗(ROM 的失敗碼)· 2 = 載入錯 · 3 = timeout。判定以 --test-jsonstatus 為準,別只看 exit code。跑整組電池(build → canary → 7 lane 平行 → 報告):

python tools/testrom/run_tests.py               # full 147 sweep, resume-aware (~6.2 h, 7 cores)
python tools/testrom/run_tests.py --filter apu  # only ROMs whose suite/name contains "apu"
python tools/testrom/run_tests.py --rerun       # ignore existing results, redo everything
dotnet AprVisual.S1.dll --test-dir tools/testrom/roms/instr_test-v5/  # or a raw directory batch
The detection=none trap. If a class-A ROM reports detection=none / "budget exhausted, no $6000 signature", the engine never saw the blargg signature — almost always the $6000 work RAM wasn't mounted, not a frame-budget problem (raising --max-frames just runs the failure longer). Test mode mounts it automatically; only suspect this if you modified the engine. detection=none 陷阱。若某 A 類 ROM 報 detection=none /「budget exhausted, no $6000 signature」,代表引擎沒看到 blargg 簽名 —— 幾乎都是 $6000 工作 RAM 沒掛,不是幀預算問題(調高 --max-frames 只會讓錯誤跑更久)。test 模式會自動掛;只有你改過引擎才需懷疑這點。