apps/termtris/tests/harness.lua is now the one copy of the debugger-assisted
loader harness: COFF parse/poke, .bss prefill, descriptor, create_process
entry, LOADER_END result polling, snapshot and exit. The six tests are
configuration plus hooks — input sequences, the app's result cells, and the
app-specific result line. tests/*.sh and verify.sh are untouched.
harness.lua returns a table with H.config{...}, H.key(...), H.message(...), H.sequence(...), H.on_frame(fn), H.result_dump(fn), H.on_done(fn) and H.run(). The exit is still the fixed LOADER_END frame;
no early-completion path was imported, because these tests read loader_frame<LOADER_END>.png (3200/3300/3400).
Removed per #7: LOADER_MODE / LOADER_A8_DESC / RETURN_STUB / RETURN_SP, the marker / xhello result branches and base_contains_marker polling, the LOADER_TRACE / ld1.tr path (no tests/*.sh used it, so it was dropped rather than renamed), the empty status
block, and the unused key_p.
One DIAG format for all six, a superset of both old ones:
Every configured value is identical to the baseline. The only DIAG changes are
the superset: the loops line now also appears for play/smoke/fmt/render/ input (with -1 for cells those tests do not configure), and the tick line
gains quit= for play_keys (play.sh parses DIAG: tick= and both play_keys.sh and verify.sh parse DIAG: loops=, so both still work).
Log diff, old vs new
diff -u of each test log, with the worktree path normalised and MAME's
wall-clock Average speed line removed — the -/+ path lines below are only
the two different checkouts:
=== play_move
-LOADER: payload <TREE>/dwt/loader/build/loader.bin (1220 B) -> bit 01880000
+LOADER: payload <TREE>/dwt/loader/build/loader.bin (1220 B) -> bit 01880000
-LOADER: COFF <TREE>/apps/termtris/build/termtris.coff (15186 B) -> bit 01900000
+LOADER: COFF <TREE>/apps/termtris/build/termtris.coff (15186 B) -> bit 01900000
-DIAG: tick=887
+DIAG: tick=887 quit=0
-LOADER: snapshot <TREE>/apps/termtris/evidence/loader_frame3200.png ok=true
+LOADER: snapshot <TREE>/apps/termtris/evidence/loader_frame3200.png ok=true
The other logs differ the same way: only the DIAG: lines and the checkout
path in the LOADER: payload/COFF/snapshot lines.
Evidence
The five committed PNGs are byte-identical to what both the old and the new run
produce (old tree, new tree, and git show HEAD:):
2183 → 486 (−78%). The plan's "around 380" was an estimate: the actual is
higher because the harness keeps the full loader diagnostics the six copies
carried (payload/COFF/section header lines, poke read-backs, .bss prefill,
placement check, result block) so the log lines stay identical, and every test
keeps a short comment header. There is now one copy of the machinery.
rg is not installed in this environment, so the grep used the same pattern
with grep -rnE.
The .sh files are untouched (diffed against upstream/master at push time, 0b3db19; this branch was rebased onto it):
MAME was not rebuilt (--skip-mame was used, as the plan allows).
Each run used a private HOME (/tmp/opencode/t5-old-home, /tmp/opencode/t5-new-home, /tmp/opencode/t5-oldplay-home) so nvram/cfg
were not shared with other threads.
Closes #6, #7.
## What changed
`apps/termtris/tests/harness.lua` is now the one copy of the debugger-assisted
loader harness: COFF parse/poke, `.bss` prefill, descriptor, `create_process`
entry, `LOADER_END` result polling, snapshot and exit. The six tests are
configuration plus hooks — input sequences, the app's result cells, and the
app-specific result line. `tests/*.sh` and `verify.sh` are untouched.
`harness.lua` returns a table with `H.config{...}`, `H.key(...)`,
`H.message(...)`, `H.sequence(...)`, `H.on_frame(fn)`, `H.result_dump(fn)`,
`H.on_done(fn)` and `H.run()`. The exit is still the fixed `LOADER_END` frame;
no early-completion path was imported, because these tests read
`loader_frame<LOADER_END>.png` (3200/3300/3400).
Removed per #7: `LOADER_MODE` / `LOADER_A8_DESC` / `RETURN_STUB` /
`RETURN_SP`, the `marker` / `xhello` result branches and
`base_contains_marker` polling, the `LOADER_TRACE` / `ld1.tr` path (no
`tests/*.sh` used it, so it was dropped rather than renamed), the empty status
block, and the unused `key_p`.
One DIAG format for all six, a superset of both old ones:
DIAG: loops=%d events=%d last=%d focus=%08X rev=%d quit=%d
DIAG: tick=%d quit=%d
Unconfigured cells print `-1`. `play.sh` still finds `DIAG: tick=` and
`play_keys.sh` / `verify.sh` still find `DIAG: loops=`.
## Baseline (unmodified tests, separate worktree)
```
$ git worktree add /tmp/opencode/t5-baseline-wt 772311b
$ HOME=/tmp/opencode/t5-old-home apps/termtris/verify.sh --skip-mame
== smoke PASS
== fmt PASS
== render PASS
== input PASS
== play PASS
== play_keys PASS
== play acceptance
move DIAG: loops=650 events=18 last=3 focus=00400001 rev=0 quit=0
panels DIAG: loops=648 events=12 last=3 focus=00400001 rev=0 quit=0
quit DIAG: loops=555 events=10 last=3 focus=00400001 rev=0 quit=1
verify: PASS
```
Old `play.lua`'s own DIAG line (pre-refactor script run against the same
`termtris.coff`, same env as `play.sh`):
```
$ git show 772311b:apps/termtris/tests/play.lua > /tmp/opencode/t5-old-play.lua
$ HOME=/tmp/opencode/t5-oldplay-home VT1200_SKIP_LEVEL1=1 LOADER_SNAP=1 \
DIAG_TICK=0x01a08980 DIAG_QUIT=0x01a08960 LOADER_AT=2500 LOADER_END=3300 \
LOADER_BIN=$PWD/dwt/loader/build/loader.bin \
LOADER_COFF=$PWD/apps/termtris/build/termtris.coff \
LOADER_OUT=/tmp/opencode/t5-oldplay-ev \
$M vt1200 -rompath harness/mame/roms -video none -sound none -nothrottle \
-skip_gameinfo -debug -debugger none \
-autoboot_script /tmp/opencode/t5-old-play.lua -autoboot_delay 0
$ grep -a -E 'DIAG:|LOADER: result' /tmp/opencode/t5-old-play.log
LOADER: result status=0 (OK) entry=018A0000 text=018A0000/84576 bits data=018B4A60/4816 bits bss=01A00000/125984 bits relocs=0 pcb=003FEE50 nscns=4 len=15186
DIAG: tick=887 quit=0
```
Old `play_keys.lua` quit mode (same method, `PLAY_MODE=quit`,
`LOADER_END=3200`):
```
$ grep -a 'DIAG:' /tmp/opencode/t5-old-play_keys.log
DIAG: loops=555 events=10 last=3 focus=00400001 rev=0 quit=1
DIAG: tick=887
```
`smoke`, `fmt`, `render` and `input` printed no DIAG line at all.
## After
```
$ HOME=/tmp/opencode/t5-new-home apps/termtris/verify.sh --skip-mame
== smoke PASS
== fmt PASS
== render PASS
== input PASS
== play PASS
== play_keys PASS
== play acceptance
move DIAG: loops=650 events=18 last=3 focus=00400001 rev=0 quit=0
panels DIAG: loops=648 events=12 last=3 focus=00400001 rev=0 quit=0
quit DIAG: loops=555 events=10 last=3 focus=00400001 rev=0 quit=1
== ROM checksum (after the suite)
ok: b46a3e442ccb86134d2356bd70d22fd2
verify: PASS
```
Per-test DIAG, from the final run's logs:
```
$ grep -a 'DIAG:' apps/termtris/build/play.log
DIAG: loops=-1 events=-1 last=-1 focus=-1 rev=-1 quit=0
DIAG: tick=887 quit=0
$ grep -a 'DIAG:' apps/termtris/build/play_move.log
DIAG: loops=650 events=18 last=3 focus=00400001 rev=0 quit=0
DIAG: tick=887 quit=0
$ grep -a 'DIAG:' apps/termtris/build/play_panels.log
DIAG: loops=648 events=12 last=3 focus=00400001 rev=0 quit=0
DIAG: tick=887 quit=0
$ grep -a 'DIAG:' apps/termtris/build/play_quit.log
DIAG: loops=555 events=10 last=3 focus=00400001 rev=0 quit=1
DIAG: tick=887 quit=1
$ for f in smoke fmt render input; do grep -a 'DIAG:' apps/termtris/build/$f.log; done
DIAG: loops=-1 events=-1 last=-1 focus=-1 rev=-1 quit=-1
DIAG: tick=-1 quit=-1
DIAG: loops=-1 events=-1 last=-1 focus=-1 rev=-1 quit=-1
DIAG: tick=-1 quit=-1
DIAG: loops=-1 events=-1 last=-1 focus=-1 rev=-1 quit=-1
DIAG: tick=-1 quit=-1
DIAG: loops=-1 events=-1 last=-1 focus=-1 rev=-1 quit=-1
DIAG: tick=-1 quit=-1
```
Every configured value is identical to the baseline. The only DIAG changes are
the superset: the loops line now also appears for `play`/`smoke`/`fmt`/`render`/
`input` (with `-1` for cells those tests do not configure), and the tick line
gains `quit=` for `play_keys` (`play.sh` parses `DIAG: tick=` and both
`play_keys.sh` and `verify.sh` parse `DIAG: loops=`, so both still work).
## Log diff, old vs new
`diff -u` of each test log, with the worktree path normalised and MAME's
wall-clock `Average speed` line removed — the `-`/`+` path lines below are only
the two different checkouts:
```
=== play_move
-LOADER: payload <TREE>/dwt/loader/build/loader.bin (1220 B) -> bit 01880000
+LOADER: payload <TREE>/dwt/loader/build/loader.bin (1220 B) -> bit 01880000
-LOADER: COFF <TREE>/apps/termtris/build/termtris.coff (15186 B) -> bit 01900000
+LOADER: COFF <TREE>/apps/termtris/build/termtris.coff (15186 B) -> bit 01900000
-DIAG: tick=887
+DIAG: tick=887 quit=0
-LOADER: snapshot <TREE>/apps/termtris/evidence/loader_frame3200.png ok=true
+LOADER: snapshot <TREE>/apps/termtris/evidence/loader_frame3200.png ok=true
```
The other logs differ the same way: only the `DIAG:` lines and the checkout
path in the `LOADER:` payload/COFF/snapshot lines.
## Evidence
The five committed PNGs are byte-identical to what both the old and the new run
produce (old tree, new tree, and `git show HEAD:`):
```
render_frame3400.png b06a240e20a9d63b1a29e5af62fcd558
termtris_frame3300.png 7164d01bd0b6d27bf88c9904692c31e5
termtris_move_3200.png 7f60c07676146e5c70a1a16b639d4fde
termtris_panels_3200.png 3f9fe2687ee6916ce0e270dcc37daf1d
termtris_quit_3200.png 5cd103b73aa683e1e1a563e38e470f19
```
## Counts and dead paths
```
$ wc -l apps/termtris/tests/*.lua # before (772311b)
354 fmt.lua 387 input.lua 350 play.lua 390 play_keys.lua
347 render.lua 355 smoke.lua
2183 total
$ wc -l apps/termtris/tests/*.lua # after
24 fmt.lua
354 harness.lua
30 input.lua
8 play.lua
34 play_keys.lua
17 render.lua
19 smoke.lua
486 total
$ grep -rnE 'LOADER_MODE|LOADER_A8_DESC|RETURN_STUB|RETURN_SP|xhello|ld1\.tr' apps/termtris/tests/
$ echo $?
1
```
2183 → 486 (−78%). The plan's "around 380" was an estimate: the actual is
higher because the harness keeps the full loader diagnostics the six copies
carried (payload/COFF/section header lines, poke read-backs, `.bss` prefill,
placement check, result block) so the log lines stay identical, and every test
keeps a short comment header. There is now one copy of the machinery.
`rg` is not installed in this environment, so the grep used the same pattern
with `grep -rnE`.
The `.sh` files are untouched (diffed against `upstream/master` at push time,
`0b3db19`; this branch was rebased onto it):
```
$ git diff --name-only 0b3db19..HEAD | grep '\.sh$'
$ echo $?
1
$ git diff --stat 0b3db19..HEAD
apps/termtris/tests/fmt.lua | 350 +------------------------------
apps/termtris/tests/harness.lua | 354 +++++++++++++++++++++++++++++++
apps/termtris/tests/input.lua | 411 +++---------------------------------
apps/termtris/tests/play.lua | 354 +-------------------------------
apps/termtris/tests/play_keys.lua | 424 +++-----------------------------------
apps/termtris/tests/render.lua | 354 ++-----------------------------
apps/termtris/tests/smoke.lua | 364 ++-----------------------------
7 files changed, 457 insertions(+), 2154 deletions(-)
```
## ROM
```
$ md5sum vt1200_v22.bin
b46a3e442ccb86134d2356bd70d22fd2 vt1200_v22.bin
```
## Not done
- MAME was not rebuilt (`--skip-mame` was used, as the plan allows).
- Each run used a private `HOME` (`/tmp/opencode/t5-old-home`,
`/tmp/opencode/t5-new-home`, `/tmp/opencode/t5-oldplay-home`) so nvram/cfg
were not shared with other threads.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #6, #7.
What changed
apps/termtris/tests/harness.luais now the one copy of the debugger-assistedloader harness: COFF parse/poke,
.bssprefill, descriptor,create_processentry,
LOADER_ENDresult polling, snapshot and exit. The six tests areconfiguration plus hooks — input sequences, the app's result cells, and the
app-specific result line.
tests/*.shandverify.share untouched.harness.luareturns a table withH.config{...},H.key(...),H.message(...),H.sequence(...),H.on_frame(fn),H.result_dump(fn),H.on_done(fn)andH.run(). The exit is still the fixedLOADER_ENDframe;no early-completion path was imported, because these tests read
loader_frame<LOADER_END>.png(3200/3300/3400).Removed per #7:
LOADER_MODE/LOADER_A8_DESC/RETURN_STUB/RETURN_SP, themarker/xhelloresult branches andbase_contains_markerpolling, theLOADER_TRACE/ld1.trpath (notests/*.shused it, so it was dropped rather than renamed), the empty statusblock, and the unused
key_p.One DIAG format for all six, a superset of both old ones:
Unconfigured cells print
-1.play.shstill findsDIAG: tick=andplay_keys.sh/verify.shstill findDIAG: loops=.Baseline (unmodified tests, separate worktree)
Old
play.lua's own DIAG line (pre-refactor script run against the sametermtris.coff, same env asplay.sh):Old
play_keys.luaquit mode (same method,PLAY_MODE=quit,LOADER_END=3200):smoke,fmt,renderandinputprinted no DIAG line at all.After
Per-test DIAG, from the final run's logs:
Every configured value is identical to the baseline. The only DIAG changes are
the superset: the loops line now also appears for
play/smoke/fmt/render/input(with-1for cells those tests do not configure), and the tick linegains
quit=forplay_keys(play.shparsesDIAG: tick=and bothplay_keys.shandverify.shparseDIAG: loops=, so both still work).Log diff, old vs new
diff -uof each test log, with the worktree path normalised and MAME'swall-clock
Average speedline removed — the-/+path lines below are onlythe two different checkouts:
The other logs differ the same way: only the
DIAG:lines and the checkoutpath in the
LOADER:payload/COFF/snapshot lines.Evidence
The five committed PNGs are byte-identical to what both the old and the new run
produce (old tree, new tree, and
git show HEAD:):Counts and dead paths
2183 → 486 (−78%). The plan's "around 380" was an estimate: the actual is
higher because the harness keeps the full loader diagnostics the six copies
carried (payload/COFF/section header lines, poke read-backs,
.bssprefill,placement check, result block) so the log lines stay identical, and every test
keeps a short comment header. There is now one copy of the machinery.
rgis not installed in this environment, so the grep used the same patternwith
grep -rnE.The
.shfiles are untouched (diffed againstupstream/masterat push time,0b3db19; this branch was rebased onto it):ROM
Not done
--skip-mamewas used, as the plan allows).HOME(/tmp/opencode/t5-old-home,/tmp/opencode/t5-new-home,/tmp/opencode/t5-oldplay-home) so nvram/cfgwere not shared with other threads.