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。也是沒給其他模式時的位置性引數。 |
--selftest | — | Run 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-ram | — | Force-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。 |
--region | ntsc|pal|dendy | Select region timing (default ntsc).選區域時序(預設 ntsc)。 |
--joypad | — | Attach 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-lower | — | Skip the S1.5 netlist-lowering pass (the mapped-checksum A/B gate).跳過 S1.5 netlist-lowering pass(mapped-checksum 的 A/B 閘)。 |
--fast-path | — | No-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-verdict | — | AccuracyCoin 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-verdict | — | B-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: 300000 → 0x794A43ABDF169ADA.benchmark 精確跑 N 個原始主 half-cycle。金:300000 → 0x794A43ABDF169ADA。 |
--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-footprint | — | Print 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-shims | — | Disable all test-mode shims (diagnostics).停用全部 test-mode shim(診斷)。 |
--no-alu-shim | — | A/B the ALU input-latch hold shim (ANC/ALR/ARR family).A/B:ALU 輸入 latch hold shim(ANC/ALR/ARR 家族)。 |
--no-dbl2007-shim | — | A/B the $2007 double-read merge shim.A/B:$2007 雙讀合併 shim。 |
--no-ppu-ale-read-feedback-shim | — | Expose 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-shim | — | Re-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-shim | — | Disable 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.cs 與 WireCore.System.cs 用 GetEnvironmentVariable 全域掃描 —— 沒有對應的 CLI 開關。A 組調 ALERead mux;B 組是 per-shim 關閉開關(有設 = 跳過該 shim);C 組是取證追蹤探針。
| Variable變數 | Value值 | What it does作用 |
|---|---|---|
| Group A — ALERead phase muxA 組 — ALERead 相位 mux | ||
ALEREAD_MUX | set (any)有設(任意) | Arm the ALERead $2007-access phase mux + node-split (cuts ppu.io_ab↔cpu.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_ab↔cpu.ab)。必須在 LoadSystem 前存在 —— 有設就是開。ALERead 測試必需;旗艦配方設 ALEREAD_MUX=1。這就是大家最常忘的那個。 |
MUX_HC | sw,rpS,rpE,fzS,fzE | Tune 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_GATE | vlo,vhi,hlo,hhi | Override 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_DBG | set有設 | 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_SHIM | set有設 | Skip the open-bus last-transferred-byte replay shim.跳過 open-bus 最後傳輸位元組重放 shim。 |
NO_DL_SHIM | set有設 | Skip the DL/idl φ2-transparency shim at $4016/$4017.跳過 $4016/$4017 的 DL/idl φ2 透明 shim。 |
NO_ABORT_SHIM | set有設 | Skip the deferred-$4015 DMC-DMA abort shim.跳過延遲 $4015 的 DMC-DMA 中止 shim。 |
NO_OAMEDGE_SHIM | set有設 | Skip the rendering-disable-edge OAM-write-suppression shim.跳過關渲染邊沿抑制 OAM 寫入的 shim。 |
NO_BGS_SHIM | set有設 | 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_DEBUG | 1 | Turn 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_DEBUG | 1 | LAE shim forensic output (read-loop, merged-value derivation).LAE shim 取證輸出(讀取環、合併值推導)。 |
ODMA_DEBUG | set有設 | OAM-DMA-PPU-bus shim forensic output.OAM-DMA-PPU-bus shim 取證輸出。 |
PB_DEBUG | set有設 | PPU ALE/read-feedback shim forensic output.PPU ALE/read-feedback shim 取證輸出。 |
PWD_DEBUG | 1 | $2001 write-delay shim forensic output.$2001 寫入延遲 shim 取證輸出。 |
OE_DEBUG | set有設 | OAM-blank-edge shim forensic output.OAM-blank-edge shim 取證輸出。 |
PC_WIN | lo,hi | A 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取證工具箱
| 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-system | — | Compose 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-work | — | Dump 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 掛牌跑(完整無人值守)
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
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.py 依 catalog.json 為每顆挑對旗標,以下是手動跑單顆的方式。與 --ac-verdict 不同,這些一律掛卡帶工作 RAM(test 模式自動設 ForceExtraRam —— blargg 協定住在 $6000)。
| Class類別 | How it judges怎麼判 | Extra flag額外旗標 | detection= |
|---|---|---|---|
| A | blargg $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-r | Same, 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 |
| B | Screen 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-verdict | screen |
| C | Screen 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 網表不動);--input 以 Button:秒[: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 —— 一次跑怎麼設界
--max-frames Nis the primary budget (simulated frames; default 900 ≈ 15 sim-seconds). Exhaust it and the verdict is timeout, exit code 3. A too-small budget looks exactly like a hang — get the true frame count from the AprNes oracle first (tools/estimate_frames.py), don't just raise it blindly.--max-frames N是主要預算(模擬幀;預設 900 ≈ 15 模擬秒)。耗盡即判 timeout、exit code 3。預算太小看起來就跟卡死一模一樣 —— 先用 AprNes oracle(tools/estimate_frames.py)拿真幀數,別盲目調高。--max-wait Nis a wall-clock safety cap in seconds (0 = off); it is secondary to--max-frames.--max-wait N是 wall-clock 安全上限(秒;0 = 關);次於--max-frames。- The batch runner adds two more guards on top: it caps each ROM at
min(maxFrames, 1.5×typicalFrames+5)(a hung/regressed test is killed at ~1.5× its known verdict frame) and a subprocess wall-guard ofmaxFrames×10+600s.批次 runner 再加兩道保險:每顆封頂min(maxFrames, 1.5×typicalFrames+5)(卡死/退化的測試約 1.5 倍就砍),另有子行程 wall-guardmaxFrames×10+600秒。
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-json 的 status 為準,別只看 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
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 模式會自動掛;只有你改過引擎才需懷疑這點。