J Sync 7/21/26

This commit is contained in:
MrARM
2026-07-21 10:45:59 -05:00
parent 32751448c6
commit 8c6547acbd
8 changed files with 451 additions and 302 deletions

View File

@@ -8,6 +8,7 @@ Target artifacts:
- `/games/pokemon_pro/spike3/netbridge/spike3-swd.cfg`
- `/games/pokemon_pro/spike3/netbridge/rp2040.cfg`
- `/games/pokemon_pro/spike3/netbridge/version.txt`
- `/games/pokemon_pro/spike3/powerdist/powerdist_ext.hex`
Generated artifacts:
@@ -160,6 +161,35 @@ CRC32(0, &__logical_binary_start, 0x12a40)
For this ELF, `__logical_binary_start` maps to file offset `0x1100`. A Python `binascii.crc32` over `games/pokemon_pro/spike3/netbridge/netbridge.elf[0x1100:0x1100+0x12a40]` gives `0x357f5327`.
## Power-Distribution Cabinet Inputs
Confirmed static facts:
- SHA-256 of `/games/pokemon_pro/spike3/powerdist/powerdist_ext.hex` is `f8eb96998a32ff86008663f7f07f2df76c32a9c86200f690c215dc36917391a9`; it is a 32,799-byte Intel HEX file whose decoded address range starts at `0x3800`.
- In `netbridge.elf`, `HOST_Update` at `0x10001210` calls `POWERDIST_IsSpike3`. For a SPIKE 3 controller, commands `0x10..0x1f` are passed to `POWERDIST_SendCmd` at `0x100020b4`; the legacy non-SPIKE-3 command `0x15` fallback is the unrelated one-byte `0xff` response.
- `POWERDIST_Update` at `0x10002174` parses controller frames and forwards their original command, sequence, and payload to the Pi with `HOSTUART_SendMessage`. These frames are not restricted to replies to a Pi request.
- Disassembling the decoded power-distribution image as Thumb code at `0x3800` shows command `0x15` dispatch at `0x427c`. It calls `0x475c` and returns exactly one payload byte.
- Function `0x46b4` composes that byte from raw GPIO P0_8, P0_9, and P0_11 as bits 0, 1, and 2. The installed cabinet map assigns Action to bit 0 and Start to bit 1; bit 2 is the coin-door power interlock state.
- Most importantly, the controller's input-change path at `0x407a` calls the frame sender at `0x3f9c` with command `0x15`, sequence `0`, a one-byte payload, and length `1`. A separate command handler at `0x428a` provides the same state for explicit polls.
The last point explains the VPX failure introduced while adding the first
power-distribution model. The emulator answered explicit `0x15` polls but did
not reproduce the controller's unsolicited change report, so a Start edge
could exist inside the emulator without ever reaching game code. The repaired
UART service queues every changed Start/Action state as command `0x15`,
sequence `0`, and drains those frames independently of incoming host traffic.
An integration test uses a socket pair to prove that a Start transition emits
`15 00 01` at the decoded protocol level without first sending a poll.
Reproduction commands used for the static controller pass:
```sh
arm-none-eabi-objcopy -I ihex -O binary \
games/pokemon_pro/spike3/powerdist/powerdist_ext.hex /tmp/powerdist_ext.bin
arm-none-eabi-objdump -D -b binary -m arm -M force-thumb \
--adjust-vma=0x3800 /tmp/powerdist_ext.bin
```
## Nodebus Layer
`NODE_Init` configures a mixed PIO/hardware-UART nodebus:
@@ -220,6 +250,8 @@ It currently provides:
- Firmware CRC response `0x357f5327`.
- PTY, serial-device, and Unix-socket serving modes for QEMU or host-side serial plumbing.
- Existing-node stub at address `0x0a` with Magikarp/topper-oriented commands `0xf2`, `0xfc`, `0xfd`, `0xfe`, and `0xff`.
- Power-distribution command `0x15` polling plus unsolicited sequence-0
Start/Action change reports matching the installed controller firmware.
Run:
@@ -243,8 +275,8 @@ Verification performed:
```text
python3 -m unittest discover -s analysis/netbridge-emulator
....
Ran 4 tests in 0.000s
...................................................................
Ran 67 tests
OK
python3 -m py_compile analysis/netbridge-emulator/netbridge_emu.py analysis/netbridge-emulator/test_netbridge_emu.py