test(tiles): multi-datagram delta case and stricter block diff

This commit is contained in:
opencode.energia.arti.ee committed 2026-10-31 02:41:04 +00:00
1 parent 8f8454461d
commit b331b90c39
2 files changed
+89 -11

No files matched your search

+6 -4
View File
@@ -63,8 +63,10 @@
# memory and compares them itself: the assertion is a relation between two
# screens, not a rendering to re-derive, and it is why the first negative
# control's valid first entry matters (a decoder that painted as it decoded
# would have painted it). Evidence: $LOGDIR/vram-delta-*.bin and
# delta-status.txt.
# would have painted it). A last delta changes all 1,280 tiles (3,842 payload
# bytes: three datagrams), which is the only case where the count, the position
# list and the value list straddle a fragment boundary; every tile is compared
# with its new entry. Evidence: $LOGDIR/vram-delta-*.bin and delta-status.txt.
#
# The run uses VT1200_SKIP_LEVEL1=1: the payload's heap is only initialised in
# the OS phase. In the diagnostics menu the free counter (0x1E8BA0) and the
@@ -132,8 +134,8 @@ fi
if [ "$MODE" = "delta" ]; then
rm -f "$LOGDIR/vram-delta-before.bin" "$LOGDIR/vram-delta-after.bin" \
"$LOGDIR/vram-delta-reject.bin" "$LOGDIR/vram-delta-recover.bin" \
"$LOGDIR/dict-delta.bin" "$LOGDIR/indices-delta.bin" \
"$LOGDIR/delta-status.txt"
"$LOGDIR/vram-delta-large.bin" "$LOGDIR/dict-delta.bin" \
"$LOGDIR/indices-delta.bin" "$LOGDIR/delta-status.txt"
fi
# Absolute: the Lua runs with MAME's cwd, so a relative default only resolves
# when the caller happens to be at the repo root.
+83 -7
View File
@@ -178,10 +178,10 @@ elseif MODE == "tiles" and not os.getenv("VID_END") then
-- exits, so this is only the catastrophic-stall backstop.
DEFAULT_END = AT + 26 * tonumber(os.getenv("VID_TILE_WAIT") or "300") + 120
elseif MODE == "delta" and not os.getenv("VID_END") then
-- Same shape as tiles mode plus the keyframe and the three deltas: one
-- ring wait, 23 dictionary chunks and five frames, each bounded by
-- VID_DELTA_WAIT.
DEFAULT_END = AT + 30 * tonumber(os.getenv("VID_DELTA_WAIT") or "300") + 120
-- Same shape as tiles mode plus the keyframe and the five deltas: one
-- ring wait, 23 dictionary chunks and six frames, each bounded by
-- VID_DELTA_WAIT; the first timeout dumps and exits.
DEFAULT_END = AT + 34 * tonumber(os.getenv("VID_DELTA_WAIT") or "300") + 120
end
local STOP_AT = tonumber(os.getenv("VID_END") or tostring(DEFAULT_END))
local ORIGIN = tonumber(os.getenv("VID_ORIGIN") or "0x018C0000")
@@ -629,8 +629,9 @@ local STREAM_FILES = { "stream-status.bin", "stream-status.txt" }
local TILE_FILES = { "vram-tiles.bin", "dict-tiles.bin", "indices-tiles.bin",
"tiles-status.txt" }
local DELTA_FILES = { "vram-delta-before.bin", "vram-delta-after.bin",
"vram-delta-reject.bin", "vram-delta-recover.bin", "dict-delta.bin",
"indices-delta.bin", "delta-status.txt" }
"vram-delta-reject.bin", "vram-delta-recover.bin",
"vram-delta-large.bin", "dict-delta.bin", "indices-delta.bin",
"delta-status.txt" }
local function clear_dump_files()
if MODE == "dict" then
@@ -1998,7 +1999,12 @@ end)()
-- entries claimed, one carried). Same assertions -- the list may not run
-- past the frame;
-- 6. recover: one more valid delta at a different tile, so the refusals left
-- no latch behind; the assertions are the same shape as step 3.
-- no latch behind; the assertions are the same shape as step 3;
-- 7. large delta: all 1,280 tiles changed. 2 + 3*1,280 = 3,842 payload bytes
-- = THREE datagrams, so the count, the position list and the value list
-- each straddle a fragment boundary -- the path a one-tile delta cannot
-- reach, and the one that would break silently if the fragment walk were
-- off by a byte. Every tile is compared with its new entry.
--
-- The active area is screen rows 0..1023, bytes 0..159 of each 256-byte row.
-- Bytes 160..255 are outside every tile and belong to the resident OS, exactly
@@ -2084,6 +2090,7 @@ local delta_prev = nil -- the screen after the previous accepted frame
local delta_after = nil
local delta_reject = nil
local delta_recover = nil
local delta_large = nil
local delta_last_len = 0
local function delta_chunk_frame(off, body)
@@ -2280,6 +2287,9 @@ local function delta_dump(timed_out)
if delta_recover then
ok = write_file(DUMP_DIR .. "/vram-delta-recover.bin", delta_recover) and ok
end
if delta_large then
ok = write_file(DUMP_DIR .. "/vram-delta-large.bin", delta_large) and ok
end
local lines = {
string.format("RX_OK=%d", prog:read_u32(RX_OK)),
string.format("RX_BAD=%d", prog:read_u32(RX_BAD)),
@@ -2574,6 +2584,72 @@ local function delta_step()
delta_check(okv, string.format(
"the block is dictionary entry %d (first bad byte %d)",
(tile_index(RECOVER) + 2) & 0xFF, first))
delta_prev = delta_recover
-- Large delta: every tile, a new entry for each. 1,280 entries is a
-- 2 + 3*1,280 = 3,842-byte payload, delivered as THREE datagrams, so
-- the count, the position list and the value list all straddle a
-- fragment boundary -- the one path a one-tile delta never reaches.
local positions, values = {}, {}
for i = 0, TILES_PER_FRAME - 1 do
positions[i + 1] = i
values[i + 1] = (tile_index(i) + 1) & 0xFF
end
f, n = delta_send(positions, values, 0x0095)
if n <= DRAW_CHUNK then
delta_check(false, string.format(
"the large delta is more than one datagram (%d bytes)", n))
delta_dump(true)
return true
end
if not delta_take(f, n) then
delta_check(false, "the ring accepted the large delta")
delta_dump(true)
return true
end
delta_phase = 7
delta_phase_at = frames
return false
end
if delta_phase == 7 then
local bad
if not delta_settled() then
if frames >= delta_phase_at + DELTA_WAIT then
delta_check(false, string.format(
"the payload consumed the large delta (RX_OK=%d TILES_DROP=%d)",
prog:read_u32(RX_OK), prog:read_u32(TILES_DROP)))
delta_dump(true)
return true
end
return false
end
delta_check(delta_last == 3, string.format(
"the large delta arrived as 3 datagrams (%d)", delta_last))
delta_check(prog:read_u32(RX_OK) == 4,
string.format("the large delta reached the screen (RX_OK=%d)",
prog:read_u32(RX_OK)))
delta_check(prog:read_u32(TILES_DROP) == 2,
string.format("the large delta was not dropped (TILES_DROP=%d)",
prog:read_u32(TILES_DROP)))
delta_check(prog:read_u32(RX_LAST_LEN) == 2 + 3 * TILES_PER_FRAME,
string.format("RX_LAST_LEN is the large delta's payload_len (%d, expected %d)",
prog:read_u32(RX_LAST_LEN), 2 + 3 * TILES_PER_FRAME))
delta_large = read_vram()
bad = 0
first = -1
for i = 0, TILES_PER_FRAME - 1 do
okv = block_equals(delta_large, i % TILE_COLS, i // TILE_COLS,
(tile_index(i) + 1) & 0xFF)
if not okv then
bad = bad + 1
if first < 0 then
first = i
end
end
end
delta_check(bad == 0, string.format(
"all %d tiles of the large delta match their new entry (%d wrong, first tile %d)",
TILES_PER_FRAME, bad, first))
delta_check(prog:read_u32(DICT_READY) == 1
and prog:read_u32(DICT_BYTES) == TILE_DICT_SIZE
and prog:read_u32(DICT_BAD) == 0,