#!/usr/bin/env bash # verify-x68000-tilebank.sh - Tile-bank gate for the X68000: proves that # assetbake's x68000 encoder (plane-major, like the Amiga's, under its own # target byte) writes exactly the layout the X68000's native tile paste # (src/m68k/planarTile.h via src/x68000/x68kTile.h) reads, and that the # X68000 build refuses a bank baked for any other target. # # Boots Human68k headless under MAME with TILEBANK.X (examples/tilebank) and # the DATA/tilebank make/x68000.mk staged from the host gate's fixture on a # data disk in drive B. The program loads its own bake through # jlTileBankLoadToSurface and through jlTileBankLoad + jlTilePaste, checks # every pixel of both against the PNG, hashes both, tries every other # target's bake, logs one TILEBANK line and shows its verdict lamp. The Lua # below waits for the lamp in text VRAM, then presses a key so the program # exits -- Human68k only finalises joeylog.txt's directory entry when the # program's stdio closes it -- and stops MAME. The line, extracted from the # data disk, must say PASS with both hashes equal to the host gate's # (scripts/check-tilebank.sh, run here for the value) and every other target # refused, and the lamp must be the PASS colour. # # Text-plane geometry (see verify-x68000-input.sh): four 1bpp planes 0x20000 # apart at 0xE00000, 128 bytes per row, leftmost pixel in bit 7, the 320x200 # stage centred at (96, 156). The lamp is examples/tilebank's: 64x64 at stage # (128, 68), colour 1 for PASS and 2 for FAIL, with FILL_COLOR (9) either side # of it on its rows. # # Usage: scripts/verify-x68000-tilebank.sh # Env: TILEBANK_DATA_DIR stage this DATA/tilebank instead (negative controls) # Requires: MAME, the X68000 firmware and CG ROM, a host cc; # build/x68000/bin/TILEBANK.X and its DATA/tilebank (make x68000). set -uo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" source "$repo/scripts/lib/tileBankGate.sh" joeyNeed MAME mame joeyNeed X68K_DIR x68kFirmware joeyNeedFile "$X68K_DIR/roms/x68000/cgrom.dat" x68kCgrom source "$repo/scripts/lib/x68kDisk.sh" joeyNeedFile "$X68K_SYSTEM_DISK" x68kFirmware binDir=$repo/build/x68000/bin dataDir=$(tileBankData "$binDir") wall=600 # hard cap on MAME, whatever happens to this script frames=20000 # emulated frames before the Lua gives up on the lamp tileBankNeedBuild "$binDir/TILEBANK.X" "$dataDir" "make x68000" tileBankReference work=$(mktemp -d -t joeylib-x68-tilebank.XXXXXX) trap 'rm -rf "$work"' EXIT # The boot disk carries only Human68k and AUTOEXEC; the program, its DATA and # its log live on the data disk in B:, which AUTOEXEC makes current. x68kBootDisk "$work/boot.xdf" 'B:' 'B:\TILEBANK.X' || exit 1 x68kDataDisk "$work/data.xdf" || exit 1 x68kXdf add "$work/data.xdf" "$binDir/TILEBANK.X" TILEBANK.X > /dev/null || exit 1 x68kAddTree "$work/data.xdf" "$dataDir" DATA/TILEBANK || exit 1 cat > "$work/tilebank.lua" < jlShutdown -> stdio closes the log local LAMP_X, LAMP_Y, LAMP_W, LAMP_H = 128, 68, 64, 64 local PASS_COLOR, FAIL_COLOR, FILL_COLOR = 1, 2, 9 local MARGIN = 4 -- inside probes keep off the lamp's edge local BESIDE = 8 -- outside probes sit this far off it local frame = 0 local seen = 0 local lamp = 0 local exitAt = 0 local done = false local function stagePixel(px, py) local x = 96 + px local byteOff = (156 + py) * 128 + (x >> 3) local bit = 0x80 >> (x & 7) local v = 0 for plane = 0, 3 do if (mem:read_u8(0xE00000 + plane * 0x20000 + byteOff) & bit) ~= 0 then v = v | (1 << plane) end end return v end -- The lamp colour when the whole lamp shows one verdict colour with -- FILL_COLOR on its rows either side, else 0. local function lampColor() local left = LAMP_X + MARGIN local right = LAMP_X + LAMP_W - 1 - MARGIN local top = LAMP_Y + MARGIN local bottom = LAMP_Y + LAMP_H - 1 - MARGIN local midY = LAMP_Y + LAMP_H // 2 local c = stagePixel(left, top) if c ~= PASS_COLOR and c ~= FAIL_COLOR then return 0 end for _, p in ipairs({ {right, top}, {left, bottom}, {right, bottom}, {LAMP_X + LAMP_W // 2, midY} }) do if stagePixel(p[1], p[2]) ~= c then return 0 end end if stagePixel(LAMP_X - BESIDE, midY) ~= FILL_COLOR or stagePixel(LAMP_X + LAMP_W - 1 + BESIDE, midY) ~= FILL_COLOR then return 0 end return c end emu.register_frame_done(function() frame = frame + 1 if done then return end if exitAt == 0 then if frame % SAMPLE_EVERY == 0 then local c = lampColor() if c ~= 0 and c == lamp then seen = seen + 1 else seen = (c ~= 0) and 1 or 0 end lamp = c if seen >= LAMP_STABLE then io.write(string.format("TILEBANK-X68K lamp=%s f%d\n", (lamp == PASS_COLOR) and "PASS" or "FAIL", frame)) io.flush() exitAt = frame + EXIT_SETTLE end end else if frame % KEY_EVERY == 0 then nat:post(" ") end if frame >= exitAt then done = true manager.machine:exit() end end if frame > FRAMES then done = true io.write("TILEBANK-X68K no-lamp f"..frame.."\n") io.flush() manager.machine:exit() end end) LUA # From the work dir, so MAME's cfg/ and nvram/ never persist between runs. out=$(cd "$work" && timeout -s KILL "$wall" "$MAME" x68000 -bios ipl10 \ -rompath "$X68K_DIR/roms" -flop1 "$work/boot.xdf" -flop2 "$work/data.xdf" \ -video none -sound none -nothrottle \ -autoboot_script "$work/tilebank.lua" < /dev/null 2>&1 | grep '^TILEBANK-X68K') echo "${out:-TILEBANK-X68K: no report from the Lua (MAME died, or hit the ${wall}s cap)}" lampOk=1 if ! grep -q 'lamp=PASS' <<< "$out"; then lampOk=0 fi if ! x68kXdf extract "$work/data.xdf" joeylog.txt "$work/joeylog.txt" > /dev/null 2>&1; then echo "verify-x68000-tilebank: FAIL - no joeylog.txt on the data disk (the program never logged, or never exited)" >&2 exit 1 fi tileBankJudge "$work/joeylog.txt" || exit 1 if [ "$lampOk" -eq 0 ]; then echo "verify-x68000-tilebank: FAIL - the on-screen lamp did not show PASS" >&2 exit 1 fi