Files
pokemon_pinball_wiki/next-analysis-targets.md

200 lines
18 KiB
Markdown

# 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
manifest mapping, dual-mode VPX table, private controller profile, and native
two-window launcher are implemented; see `native-playable-table.md`. The
standalone table remains available.
The current native stop point is not yet validation-only. Resolve these two
blocking integration defects first:
- Replace the undefined VPX `Service1Key` through `Service4Key` variables with
the pinned host's supported `VPXActionKey(25)` through `VPXActionKey(28)`
expressions and exercise every mapped input in native VPX.
- Implement power-distribution command `0x15` for active-low Action, Start, and
cabinet-door inputs; correct the CPU-SPI `0-SW-23` raw-byte alignment; then
identify and complete the genuine factory/pre-play setup flow.
After those blockers, continue acceptance and calibration:
- Complete and preserve a normal three-ball game plus a multiball sequence
through the genuine game rules, without dashboard ball-motion shortcuts.
- Run the configurable native shot suite across shooter lane, both orbits,
every ramp, both outlanes/returns, pops, QEMU-authoritative slings, captive
ball, Town VUK, Poké Ball hold, gates/posts, and Meowth movement; tune only
the transitions that fail.
- 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.
- Replace `photo_estimate`, `comparable_part`, and `playability_tuned` ramp Z,
coil, restitution, and friction values when direct measurements or
slow-motion reference footage become available.
- 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`; see `analysis/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: `0` through `6`, 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 matching `GLIBC_2.39`/`GLIBCXX_3.4.32` nodes; launcher/unit/syntax checks and the Apple Silicon ARM64 container build pass without executing the target. The initial `prepare` run exposed a nested `/games/spike3` alias 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 is `prepare`, `boot-display`, `spike-menu`, then `game`: 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 timestamped `emulation/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, loads `virtio_gpu`, creates `/dev/dri/card0` plus `/dev/dri/renderD128`, and reaches `boot-display`, `spike-menu`, and `/games/game`. The generated rootfs includes a display probe, `fbdev` fallback interposer, Mesa surfaceless/pbuffer support, synthetic GLES/GBM/EGLImage fallbacks, GPIO sysfs stubs, framebuffer diagnostic renderer, and null ALSA default. Verified captures include nonblank `emulation/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 in `emulation/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.py` on live hardware or a nodebus capture.
- Recover the exact Magikarp topper `IDENTITY_BOARD_PART_ID` expected by command `0xfe`.
- 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.bin` is 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.bin` to tmpfs because updates may overwrite it while mmap-ed.
- `main.pck` has already been extracted into workspace-local `assets/`; see `godot-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.bin` and spike-menu `image.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/game` strings such as `Flash 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 `0x0b` command-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, `+69` for EOB Pokedex FX and `+78` for attack-type FX, and writes 199 neighboring unpromoted candidate labels plus one sound-test-candidate disagreement to `analysis/radium-image/catalog_offset_candidate_labels.tsv`. Of those candidates, 196 non-conflicting rows are now used as explicitly marked `catalog_offset_candidate` best-name aliases for sounds that previously had only structural object references. The Pokedex voice stream now maps objects `409` through `1545` to 1,137 semantic Pokemon voice labels. The current ASR pass adds 1,705 draft content labels for bounded voice-like clips, including 220 catalog-matched `SE_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.tsv` as 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 in `sound-unresolved-review.md` by 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 opcode `0x0b` references, but only to local object IDs.
- Continue decoding compiled GDScript bytecode beyond string recovery if broader script call-site reconstruction is needed. Current static `.gdc` string 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`, and `analysis/radium-spike-menu-image/opcode_handler_table.tsv`. The current generic decode confirms clean `0x00`-terminated streams, observed opcodes, fixed payload sizes, common payload values, native handler-address table entries, and that opcode `0x0b` is the sound-reference command, but most non-`0x0b` opcode 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 `/connectivity` paths 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`/`ifdown` command 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.uds` framed 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, 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.elf` is 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.elf` is a 32-bit ARM static executable with code mapped at `0x10000000` and RAM at `0x20000000`/`0x20040000`.
- Strings include `uart_node.c`, `NODEBUS_Poll`, `NODEUART_Write`, `UART_NodeRxIrq`, and `WS2812_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 `0x30` returning firmware CRC `0x357f5327` and `0x41` carrying direct nodebus requests.
- `analysis/netbridge-emulator/netbridge_emu.py` implements the recovered host frame codec, core bridge commands, CRC response, PTY serving mode, and a stub node at address `0x0a`.
- `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=1` path that starts the Python emulator on `emulation/work/netbridge.sock`, attaches it as a second PL011 serial, maps guest `/dev/ttyAMA5` to the real serial, and lets the preload shim pass that path through.
Follow-up passes:
- Run the full Docker path with `SPIKE3_NETBRIDGE_EMU=1` and verify whether the game bridge thread accepts the emulated `/dev/ttyAMA5` device.
- Decide whether the OpenOCD programming path should be allowed, replaced with a success stub, or bypassed once CRC command `0x30` is 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 complete for top-level node firmware; see `package-image-firmware.md`.
Targets:
- All `*-LPC*.hex` files under `/games/pokemon_pro`.
- `/games/pokemon_pro/spike3/powerdist/powerdist_ext.hex`.
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 `.spk` update packages outside this rootfs.
Why:
- `/etc/init.d/update` and `update_monitor` make `.spk` the software update format.
- The index file may describe package contents, hashes, versions, or install paths.
Suggested first passes:
- Inspect `.sidx` with `file`, strings, hexdump, and structured parsers. Done with `file`, `xxd`, and `strings`; 686 package paths were identified.
- Compare with any `.spk` available from machine update media or connectivity cache.