20 KiB
Next Analysis Targets
Priority 0: Native playable acceptance and calibration
The QEMU/HVF Cocoa game path, loopback spike3-playfield/v1 bridge, safe
pause/restart synchronization, VPX 10.8.1 controller-plugin rebase, generated
hardware-contract mapping, clean-room dual-mode VPX table, private controller
profile, and native two-window launcher are implemented; see
native-playable-table.md and vpx-table-recreation.md. The default launcher
now builds and selects
emulation/vpx-rebuild/dist/PokemonPro_Rebuild.vpx. The deprecated
emulation/vpx/PokemonPro_Greybox.vpx is historical evidence that the clean
rebuild does not inspect or write; it is not a build input or runtime default.
The input transport blockers are now repaired and live-checked. The table uses
VPXActionKey(25..28); power-distribution command 0x15 carries active-low
Action/Start/door state; CPU-SPI 0-SW-23 is correctly aligned; and service
Back/Up/Down/Enter use CPU-SPI 0-SW-8/9/10/11. Immediate host-event ingestion
replaces the broken dependency on node-bus polling. The genuine display
accepted service Up/Down/Back, and the guest acknowledged the exact raw states.
The final clean table now passes the supervised native startup gate: the
2026-07-20 run reached Playable cabinet connected, returned 392 lamp updates,
7 LED frames, and 1 driver pulse, kept both captive optos stable, and delivered
QEMU-keyboard coin/Start edges. The launcher now allows 420 seconds because
normal game initialization can take about five minutes. The next blocking
integration target is a complete normal game and persistence check. If a fresh
image enters Guided Setup, complete Save & Exit through the repaired panel,
trace any subsequent invalid-machine decision, identify the minimum genuine
NVRAM or conagent-backed setup records, persist them across two reboots, and
prove the second boot reaches attract mode and accepts Start.
The clean table and geometry-free hardware contract pass their static
validators. emulation/vpx-rebuild/qa/runtime-smoke.log records a bounded VPX
10.8.1 CaptureAttract pass on 2026-07-20: it loaded the table and VBS,
compiled/started the script, rendered two frames, and closed with exit code 0.
The final smoke now matches the current distribution SHA-256
ddce5d48033ee3c6e67248910a73897293e8b9c36eee29df164160a93572a30e.
It is not interactive play or a substitute for the QEMU-connected acceptance
below.
After those blockers, continue acceptance and calibration:
- Complete and preserve a normal game plus a multiball sequence through the genuine rules on the final clean table, without dashboard ball-motion shortcuts.
- Exercise the shooter lane, both orbits, every ramp, both outlanes/returns, pops, QEMU-authoritative slings, Pokedex captive chain, Town VUK, right-ramp hold/Pikachu post, gates, spinner, targets, and Meowth movement with physical VPX balls. Treat contact injection as transport coverage, not shot proof.
- Capture exact-address RGB lamp behavior, ordered driver pulses, retained-ball ownership, disconnect fail-safe, and reconnect baselines in one integrated run of the final table.
- Record input-to-visible-flipper and bridge-output-to-mechanism p95/p99 from live native traces, plus rendered fps/1% low under simultaneous QEMU load.
- Preserve a full 60-minute inventory soak and explicit QEMU, bridge, and VPX restart logs before declaring the long-run acceptance row complete.
- Compare
emulation/vpx-rebuild/design/geometry.jsonwith a physical Pro machine: measure ramp Z/clearance, post and toy footprints, Pikachu post direction/stroke, Meowth crank travel, coil timing, pitch, and ball/rubber behavior. Replace estimated or simulation-tuned values only with recorded evidence. - Acquire a licensed stripped/bare-playfield scan to replace the official registered photograph, whose baked-in hardware and lighting remain visible beneath VPX geometry. Re-run visual and runtime QA after that asset change.
- Test QEMU D-Bus shared-memory scanout only after the two-window release is stable. Retain Cocoa rather than adopting a VNC/browser capture fallback if page-flip, 60 fps, or one-frame latency gates fail.
The current derived-data inventory and confidence boundaries are summarized in analysis-evidence-map.md. This page tracks only the work that remains or still needs stronger validation.
Priority 1: Main Game Binary
Status: first-pass static strings, dependency review, targeted Ghidra decompilation, topper serial-key recovery, a MicroPython emulator artifact, and a Docker/QEMU emulation scaffold are complete; see main-game-behavior.md, topper-serial-key-emulator.md, and docker-qemu-emulation.md.
Target:
/games/pokemon_pro/game
Why:
- It is the real machine application started by
game_monitor. - It interprets hardware state, controls gameplay, and likely talks to SPIKE node hardware.
- Exit codes are meaningful and documented in
game_monitor.
Suggested first passes:
- Extract strings with offsets. Done:
analysis/static-triage/game.strings. - Identify linked libraries with an AArch64-aware ELF parser. Done with
objdump -p; seeanalysis/static-triage/game.objdump-p.txt. - Load into Ghidra/IDA/rizin as AArch64 PIE. Done for targeted paths.
- Search for paths from the init scripts:
/connectivity,/data,/games,/dev,UPDATE_REQUESTED,UPDATE_COMPLETED, and node firmware filenames. - Search for exit-code constants matching the monitor script:
0through6, plus signal paths.
Follow-up passes:
- Exercise the new process-level lane documented in
process-level-emulation.md. Static validation resolves all 51 target runtime libraries and matchingGLIBC_2.39/GLIBCXX_3.4.32nodes; launcher/unit/syntax checks and the Apple Silicon ARM64 container build pass without executing the target. The initialpreparerun exposed a nested/games/spike3alias bug which is now fixed and regression-tested; the post-fix run was blocked by the local Codex Docker approval/usage gate. The next acceptance sequence isprepare,boot-display,spike-menu, thengame: execute the Mesa FBO smoke test, verify changing noVNC frames on port 6081, nonzero WAV capture, five-minute attract stability, one synthetic-ball Start/flipper/drain cycle from the dashboard, a qemu-user smoke run, and live GDB attachment. Record each failure from the timestampedemulation/work/runs/bundle rather than treating source completion as playability. - Continue from
emulation/: QEMU now boots the generated rootfs, exposes noVNC/dashboard, uses cached rootfs preparation, loadsvirtio_gpu, creates/dev/dri/card0plus/dev/dri/renderD128, and reachesboot-display,spike-menu, and/games/game. The generated rootfs includes a display probe,fbdevfallback interposer, Mesa surfaceless/pbuffer support, synthetic GLES/GBM/EGLImage fallbacks, GPIO sysfs stubs, framebuffer diagnostic renderer, and null ALSA default. Verified captures include nonblankemulation/work/boot-display-fbo-wrap.ppm,emulation/work/spike-menu-gpio-wrap.ppm,emulation/work/game-gl-limits.ppm,emulation/work/game-fbdev-real-egl.png, and the earlier diagnostic screen inemulation/work/game-diagnostic.png. The prior black-screen, missing-ALSA-default, boot-display framebuffer retry, SPIKE-menu GPIO 25 spam, Mesa loader dependency, and zero-varying shader blockers are cleared. The Docker/VNC softpipe path still encounters the target-created EGLImage/FBO issue and fallback color bands. The native macOS HVF/Cocoa path now has a verified complete 1920x1080 game-frame capture with the opt-in Debian Mesa 22.3.6 llvmpipe stack, although it uses about 5.3 host CPU cores and logs rejected page flips. Other current blockers are TAS/MAX amp register verify reads and bridge/netbridge startup failures (OpenOCD init failed,netbridge image CRC mismatch,failed to init bridge thread). The next display pass should measure llvmpipe frame pacing against softpipe and then investigate an Apple-GPU-backed VirtIO/translation path separately from the working CPU-rendered baseline. - Validate
analysis/topper-emulator/topper_emulator.pyon live hardware or a nodebus capture. - Recover the exact Magikarp topper
IDENTITY_BOARD_PART_IDexpected by command0xfe. - Confirm physical UART pins, baud, voltage level, and any netbridge timing/break behavior required for a MicroPython node.
Priority 2: image.bin / Radium Runtime Image
Status: first-pass static comparison, whole-rootfs audio search, targeted Ghidra xrefs for the sound path, main-game section 8 PCM table reversal, full main-game section 5 sound command-stream scan, generic section 5 opcode stream decode with payload-field summaries, native opcode length/handler table dumps, section 3 bitmap-record preview extraction, SPIKE menu section 8 PCM parse, SPIKE menu section 5 command-stream scan, Godot .gdc string decoding, full main-game WAV export, 54 SPIKE menu WAV exports, 25 Ghidra-confirmed native sound-name aliases, catalog-order offset candidate audit and preview page, 1,137 aligned Pokedex voice aliases, 1,705 draft ASR transcript labels, 169 low-confidence ASR review candidates, complete best-available named alias export, game-asset spoiler/unreleased-feature inventory, and wiki preview pages are complete; see package-image-firmware.md, audio-asset-search.md, radium-image-format.md, sound-export.md, sound-catalog-offset-candidates.md, sound-pokedex-voice.md, sound-spike-menu.md, sound-native-names.md, sound-native-sound-test.md, sound-asr-draft-labels.md, sound-asr-review-candidates.md, sound-best-named-export.md, asset-previews.md, radium-section3-bitmaps.md, and game-asset-spoilers-unreleased.md.
Targets:
/games/pokemon_pro/image.bin/games/pokemon_pro/spike3/spike_menu/image.bin
Why:
image.binis larger than the executable and is probably a resource pack, filesystem image, or application asset bundle used by the game.- The SPIKE menu explicitly copies its
image.binto tmpfs because updates may overwrite it while mmap-ed. main.pckhas already been extracted into workspace-localassets/; seegodot-and-radium-assets.md.
Suggested first passes:
- Run
file,binwalk, entropy analysis, and magic-number scans.file,binwalk, header dump, and first strings completed. - Search for embedded filenames, JSON, SQLite, compression headers, and Godot pack headers. First strings show Stern EULA text; no standard archive signature found by
binwalk. - Compare structure between game
image.binand spike-menuimage.bin. First 0xb0-byte header shape and early EULA structure are similar, with different size/table values. - Reverse the Radium/cereal mmap image table used by
/games/pokemon_pro/gamestrings such asFlash memory init mmap failed,/lcd/demand_loaded, and/lcd/auto_loaded. - Map the remaining Radium sound object IDs and section 8 chunk indices to higher-level script/gameplay names and call sites. Section 8 is decoded as headerless 16-bit PCM chunks, the parser resolves section 5 opcode
0x0bcommand-stream references for all chunks, and all chunks are exported as WAVs. A native Godot bridge table confirms names for 25 IDs; Ghidra xrefs to its registration helper are exhausted at those 25 direct calls. Catalog-order comparison now identifies two native anchor offsets,+69for EOB Pokedex FX and+78for attack-type FX, and writes 199 neighboring unpromoted candidate labels plus one sound-test-candidate disagreement toanalysis/radium-image/catalog_offset_candidate_labels.tsv. Of those candidates, 196 non-conflicting rows are now used as explicitly markedcatalog_offset_candidatebest-name aliases for sounds that previously had only structural object references. The Pokedex voice stream now maps objects409through1545to 1,137 semantic Pokemon voice labels. The current ASR pass adds 1,705 draft content labels for bounded voice-like clips, including 220 catalog-matchedSE_PK_VO_*inferred names across 90 catalog constants, plus 34 low-confidence ASR review aliases for rows that would otherwise remain structural. ASR labels and catalog-offset candidates still need native/script confirmation. - Maintain
analysis/all-sound-best-name-manifest.tsvas the complete named-export surface. It currently has 2,545 rows: 25 confirmed native names, 1,137 Pokedex voice alignments, 220 catalog-matched ASR aliases, 583 raw ASR draft aliases after stronger-name priority, 196 explicitly marked catalog-offset candidate aliases, 34 low-confidence ASR review aliases, 1 main-image duplicate hash match inheriting a confirmed native name, 295 main structural object fallbacks, 4 SPIKE menu exact-payload matches inheriting stronger main-image names, and 50 SPIKE menu structural fallbacks. The remaining 345 structural rows are also grouped for review insound-unresolved-review.mdby bank and duration/channel bucket. Four sound-test-adjacent native label rows are retained for audit, but are not promoted as confirmed best-name labels because their numeric field conflicts with ASR/Pokedex cross-checks. - Continue section 3 image-record recovery. Ghidra xrefs identify section 3 as a 1,477-entry qword pointer table; the current static exporter renders 1,449 raw indexed bitmap records and leaves 28 compact payload records undecoded in
analysis/radium-image/section3_bitmap_manifest.tsv. Next steps are recovering the compact subtype, confirming palette/alpha semantics, and correlating section 3 records with section 4 or runtime display callers. - Recover SPIKE menu object metadata and higher-level menu names in
/games/pokemon_pro/spike3/spike_menu/game. The current menu export resolves all 54 section 8 PCM chunks through 300 section 5 opcode0x0breferences, but only to local object IDs. - Continue decoding compiled GDScript bytecode beyond string recovery if broader script call-site reconstruction is needed. Current static
.gdcstring decoding recovers the 760-name sound catalog and 12 direct Pokedex EOB scene references, but not a general name-to-Radium-object map. - Assign semantics to the non-sound section 5 opcodes now summarized in
analysis/radium-image/command_opcode_payload_summary.tsv,analysis/radium-spike-menu-image/command_opcode_payload_summary.tsv,analysis/radium-image/opcode_handler_table.tsv, andanalysis/radium-spike-menu-image/opcode_handler_table.tsv. The current generic decode confirms clean0x00-terminated streams, observed opcodes, fixed payload sizes, common payload values, native handler-address table entries, and that opcode0x0bis the sound-reference command, but most non-0x0bopcode names still need confirmation from runtime consumers. - Validate the unreleased/deep-feature candidates from
game-asset-spoilers-unreleased.md: Team Rocket Multiball 3, Pikachu vs. Lucario / Story Wizard 2, Pikachu vs. Magikarp, Eevee Evolution Combos, and Cave/Mountain Top backgrounds. The current evidence is static strings, extracted assets, and candidate sound labels; reachability still needs code-path or runtime confirmation.
Priority 3: conagent
Status: first-pass reverse engineering complete in conagent-re.md; non-compilable C-like flow export is in conagent-pseudocode.c; host-side backend/machine emulator added under analysis/conagent-machine-emulator/ and documented in conagent-machine-emulator.md.
Target:
/games/pokemon_pro/conagent
Why:
- It is separately supervised and restarted forever.
- Name and
/connectivitypaths suggest Stern Insider Connected or connectivity agent behavior.
Suggested first passes:
- Strings and URL/domain extraction.
- Network syscall/import review.
- Trace references to
/connectivity/cache,/connectivity/files,/connectivity/update, and hostname handling.
Follow-up passes:
- Force Ghidra function creation for the stripped text region and rerun decompilation.
- Audit
ifup/ifdowncommand construction and interface-name validation. - Audit direct Game-to-Server endpoint validation.
- Audit file-transfer local path validation and update handoff.
- Recover enough of the
/usr/local/spike/agent.udsframed protocol to add a local game-process emulator mode.
Priority 4: Netbridge Debug Path
Status: first-pass strings, ELF program-header review, targeted Ghidra decompilation, host protocol recovery, power-distribution command 0x15 static recovery, a Python host-side emulator scaffold, Docker/QEMU optional serial wiring, and a Pico SDK firmware recreation are complete; see package-image-firmware.md, netbridge-re.md, and docker-qemu-emulation.md.
Targets:
/games/pokemon_pro/spike3/netbridge/netbridge.elf/games/pokemon_pro/spike3/netbridge/spike3-swd.cfg/games/pokemon_pro/spike3/netbridge/rp2040.cfg
Why:
netbridge.elfis not stripped and has debug info.- OpenOCD config maps SWD onto Raspberry Pi GPIOs 10 and 11.
- This may be the clearest path to understanding lower-level board communication and programming/debug pathways.
Findings:
netbridge.elfis a 32-bit ARM static executable with code mapped at0x10000000and RAM at0x20000000/0x20040000.- Strings include
uart_node.c,NODEBUS_Poll,NODEUART_Write,UART_NodeRxIrq, andWS2812_NodeSetLED. - Ghidra decompilation identifies the Pi-facing host UART as 2,000,000 baud STX/ETX/ESC framed messages on RP2040 GPIO 16/17, with
0x30returning firmware CRC0x357f5327and0x41carrying direct nodebus requests. - Static disassembly of
powerdist_ext.hexconfirms that command0x15returns GPIO P0_8/P0_9/P0_11 in bits 0/1/2 and emits an unsolicited sequence-0 report whenever a debounced cabinet input changes. The Python emulator now reproduces both the poll and asynchronous paths. analysis/netbridge-emulator/netbridge_emu.pyimplements the recovered host frame codec, core bridge commands, CRC response, PTY serving mode, and a stub node at address0x0a.analysis/netbridge-pico-firmware/implements the same recovered protocol as a Pico SDK firmware recreation with a portable host-core test.- Docker/QEMU now has an optional
SPIKE3_NETBRIDGE_EMU=1path that starts the Python emulator onemulation/work/netbridge.sock, attaches it as a second PL011 serial, maps guest/dev/ttyAMA5to the real serial, and lets the preload shim pass that path through.
Follow-up passes:
- Run the full Docker path with
SPIKE3_NETBRIDGE_EMU=1and verify whether the game bridge thread accepts the emulated/dev/ttyAMA5device. - Decide whether the OpenOCD programming path should be allowed, replaced with a success stub, or bypassed once CRC command
0x30is reachable. - Build a Pico UF2 after configuring
PICO_SDK_PATH, then bench-test it against a host serial harness before connecting it to target hardware. - Validate nodebus timing, break behavior, voltage level, and connector routing on live hardware or a logic-analyzer capture.
- Expand the node model beyond the Magikarp/topper-oriented commands once the game requests additional playfield nodes.
Priority 5: Node Firmware
Status: first-pass Intel HEX range parsing is complete for top-level node firmware, and the power-distribution 0x15 input path has been disassembled; see package-image-firmware.md and netbridge-re.md.
Targets:
- All
*-LPC*.hexfiles under/games/pokemon_pro. /games/pokemon_pro/spike3/powerdist/powerdist_ext.hex(input-report path complete; other commands remain open).
Why:
- These likely define behavior for distributed playfield nodes: coils, LEDs, LCD, magnet sensors, HDMI, TMC drivers, power distribution.
- Firmware names expose node families and MCU types.
Suggested first passes:
- Parse Intel HEX metadata and address ranges. Done for 17 top-level HEX files in
analysis/static-triage/node-firmware-ranges.md. - Group by MCU family. Initial grouping by filename identifies LPC1112, LPC1113, LPC1124, LPC1313, and LPC812 families.
- Disassemble with the correct Cortex-M profile per chip.
- Correlate firmware names with harnesses, playfield devices, and game binary strings.
Priority 6: Update Format
Status: first-pass .sidx strings/header review complete; see package-image-firmware.md.
Targets:
/games/spk/index/pokemon_pro-0_83_0.sidx- Any available
.spkupdate packages outside this rootfs.
Why:
/etc/init.d/updateandupdate_monitormake.spkthe software update format.- The index file may describe package contents, hashes, versions, or install paths.
Suggested first passes:
- Inspect
.sidxwithfile, strings, hexdump, and structured parsers. Done withfile,xxd, andstrings; 686 package paths were identified. - Compare with any
.spkavailable from machine update media or connectivity cache.