Files
verstack/docs/decoder-evidence.md

4.0 KiB

Decoder evidence

Firmware, extracted assets, and local validation receipts remain excluded from Git. The reference wiki is /home/jordan/pokemon-triage-wiki; it is read-only input. Reference counts must be tied to matching content hashes, not game names alone.

Indexed DMD bitmap grammar

plugins/dmd_bitmap.py implements a bounded decoder selected by structural pointer tables and per-record encoding bytes. media_extract.py revision 4 preserves the encoded record, exact decoded indices, and a PNG with an explicitly approximate palette. Palette selection and application compositing are not established by the index decoder.

The grammar was recovered from named functions in the Game of Thrones 1.37 Pro ARM executable, SHA-256 637acf6d6ff171def2c6e75437534ece8ea4017959eccd616829ccd621f97828:

Address Routine
0008bb24 image_alloc_and_decompress_column_whitespace
0008bc70 image_alloc_and_decompress_row_whitespace
0008bd84 image_alloc_and_decompress_row_16
0008be58 image_get_keyframe_and_decompress_column_delta
0008bf64 image_get_keyframe_and_decompress_row_delta

These addresses document the evidence; production decoding does not hardcode them. The dispatch table at executable file offset 0x2849a4 has four pointers per encoding. Records contain little-endian identity, flags, width, and height followed by an encoding byte: <IIHHB. Payload starts at byte 13. Treating byte 12 as a pixel, as the earlier approximate extraction did, shifts raw frames.

Encoding Interpretation
0 Raw eight-bit indices
1 / 7 Column / row whitespace packets
3 / 9 Column / row deltas against a preceding cached keyframe
12 Row four-bit indices, low nibble first

Whitespace tokens use the upper six bits as a count and the lower two bits for literal, zero fill, index-15 fill, or repeated next-byte fill. Delta tokens below 128 copy literal indices; tokens at least 128 skip 256-token existing indices. A zero token terminates either packet stream. Bounds, complete frame coverage, matching keyframe dimensions, and known encoding are required. Unsupported or truncated records produce coverage failures rather than invented pixels.

scripts/validate_dmd_native.py runs the named ARM routines under Unicorn, hooks allocation and copying, and compares their output with the Python decoder. It does not execute firmware as a host process. Local receipts establish:

  • Pokémon image SHA-256 2f1a958c1f859c339c716e53cc9ee752412373c486ea2a1bfd116eefce4617a3: all 28 compact records match those firmware routines pixel for pixel (data/validation/dmd-real/native-receipt.json). This is a cross-build grammar check using the GOT executable, not execution of Pokémon's own decoder.
  • GOT image SHA-256 b52720c75d5650b61005694cc61fd941d4ab5c054166f9a4eff2c71faf454d92: all 17,159 records parse; 34 representative compressed records match the native routines, covering every compressed encoding present (got-native-receipt.json, got-summary.json in the same directory).

The GOT counts are 4,071 raw, 4,231 row whitespace, 2,361 column whitespace, 18 row delta, 2 column delta, and 6,476 four-bit records. These checks establish index reconstruction for the cited inputs, not full coverage of every SPIKE build.

Other family evidence

SPIKE2 audio uses the pinned upstream source and executable-specific emulation profiles recorded in docs/toolchain.lock.json. The Aerosmith main image produced 1,522 WAVs with no failed main-image sounds in data/validation/spike2-real/audio/spike2-audio-evidence.json. Its menu executable has no validated codec profile and remains a visible failure.

PCM sample rates come from structural metadata or matching executable ALSA call evidence; they must not be guessed from a game label. Godot entries retain their source ranges and validate supplied checksums. FFmpeg previews retain inspection and full-decode readback evidence. Intel HEX records retain address and entry-point metadata; the pinned upstream node4-* limitation remains explicit.