feat: arm the switch-edge logger — add switch sites, values and buttons to the KK LE port

The v3 runtime's edge logger could never arm: the port had no switch_edge /
switch_drain sites, no switch_records/switch_count data and no switch_*
record-layout values, and switches_arm() skips a port without switch lines.

Located in the King Kong LE 0.97 ELF with the decryptor's
portswitch.switch_source() (generation-B framework): switch_edge 0x0055fa04,
switch_drain 0x005606e4, switch_records 0x008ecc78, switch_count 0x0093437c;
record layout 384/32/24/8/26/28 as on the other generation-B builds. Added
LOCKDOWN/START/flipper button switch lines on bits the game's shot dispatch
never sends, so the logger arms and the buttons become named shots.

Deployed to the machine and verified in play: the boot log arms the drain
(switch_edge 0x0055fa04, drain 0x005606e4..0x00560864) and /dump/switch.log
logged ~6000 in-game edges, both edges of all four flipper buttons, named.

Also fixes the runtime's mangled GAMELOG comment (broke the build) and the
switch_names.inc entry count in the README.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-10-12 17:10:05 -04:00
co-authored by Claude Code
parent abc881f913
commit 18ab285e22
3 changed files with 34 additions and 12 deletions
+8 -10
View File
@@ -18,11 +18,14 @@ why, and the game runs stock.
| Shots (`SHOT`): every named shot dispatched while a ball is up | **deployed on the machine, verified in play** | | Shots (`SHOT`): every named shot dispatched while a ball is up | **deployed on the machine, verified in play** |
| Stock modes (`gamelog: MODE START/END`): the game's own 22 modes with score delta | **deployed on the machine, verified in play** (`mode_score` is approximate) | | Stock modes (`gamelog: MODE START/END`): the game's own 22 modes with score delta | **deployed on the machine, verified in play** (`mode_score` is approximate) |
| Award screens (`AWARD id=…`): every award the game shows, extra-ball tracking | **deployed on the machine, verified in play** — except the extra-ball award id is not yet confirmed (below) | | Award screens (`AWARD id=…`): every award the game shows, extra-ball tracking | **deployed on the machine, verified in play** — except the extra-ball award id is not yet confirmed (below) |
| Switch/button log (`/dump/switch.log`, `SW` lines with generated names) | **implemented in this tree, NOT yet deployed or verified** — the deployed `mode.so` (built 2026-10-12 10:46) predates it | | Switch/button log (`/dump/switch.log`, `SW` lines with generated names) | **deployed on the machine, verified in play** (flippers on both edges; sites located with `portswitch.switch_source` and added to the port) |
The machine currently runs the v2 build (events, shots, modes, awards). The The machine currently runs the v3 build (events, shots, modes, awards, switch
switch logger (v3) is in this tree and needs a rebuild + redeploy before it can log). The v3 work needed more than a rebuild: the port had no `switch_edge` /
be relied on. `switch_drain` sites or `switch_*` values, so the runtime's edge logger could
never arm. They were located in the King Kong LE 0.97 ELF with the decryptor's
`pinball_decryptor.plugins.stern.portswitch.switch_source()` (generation-B
framework) and added to `ports/king_kong_le-0.97.port`.
## Files ## Files
@@ -30,7 +33,7 @@ be relied on.
|---|---| |---|---|
| `gamelog.c` | the logger: a passive PAD mode. It never `pm_begin()s`, never blocks, allocates nothing — it only watches and writes `[GAMELOG]` lines | | `gamelog.c` | the logger: a passive PAD mode. It never `pm_begin()s`, never blocks, allocates nothing — it only watches and writes `[GAMELOG]` lines |
| `pad_mode_runtime.c` | the PAD Modes SDK runtime, **patched**: (a) a GAMELOG section — passive stock-mode and award watching, exporting `gl_award_seq()` / `gl_last_award_id()` to modes; (b) the per-edge switch logger to `/dump/switch.log`; (c) the Insider Connected gate made passive. Our exact changes vs upstream: `docs/runtime-patch.diff` | | `pad_mode_runtime.c` | the PAD Modes SDK runtime, **patched**: (a) a GAMELOG section — passive stock-mode and award watching, exporting `gl_award_seq()` / `gl_last_award_id()` to modes; (b) the per-edge switch logger to `/dump/switch.log`; (c) the Insider Connected gate made passive. Our exact changes vs upstream: `docs/runtime-patch.diff` |
| `switch_names.inc` | King Kong LE 0.97 switch id → name table (103 entries), `#include`d by the runtime's switch logger. Generated from the game's own data (method: `swnames.py` in the decryptor repo); fix names here if any are wrong | | `switch_names.inc` | King Kong LE 0.97 switch id → name table (104 entries, ids 1–104), `#include`d by the runtime's switch logger. Generated from the game's own data (method: `swnames.py` in the decryptor repo); fix names here if any are wrong |
| `pad_mode.h`, `pad_stock.h` | unmodified SDK headers (needed by the build) | | `pad_mode.h`, `pad_stock.h` | unmodified SDK headers (needed by the build) |
| `build_mode.sh` | unmodified SDK build script: compiles the runtime + your mode into one `-nostdlib` shared object and refuses banned libc calls | | `build_mode.sh` | unmodified SDK build script: compiles the runtime + your mode into one `-nostdlib` shared object and refuses banned libc calls |
| `event_probe.c`, `event_read.py` | the event-bus measurement instrument and its log reader — how bus event ids are identified for another game (MODE_SDK.md, "Measuring events on another game") | | `event_probe.c`, `event_read.py` | the event-bus measurement instrument and its log reader — how bus event ids are identified for another game (MODE_SDK.md, "Measuring events on another game") |
@@ -169,11 +172,6 @@ The ids you name that way become the `event` lines of a port (the six in
## Unfinished work / known issues ## Unfinished work / known issues
- **The switch logger is not on the machine yet.** The deployed `mode.so` is the
2026-10-12 10:46 build (events/shots/modes/awards). The `/dump/switch.log`
feature (runtime patch + `switch_names.inc`) was written later the same day:
it needs a rebuild, a redeploy, and verification that the log appears and the
names are right.
- **The extra-ball award id is unconfirmed.** Default 13 is a static guess from - **The extra-ball award id is unconfirmed.** Default 13 is a static guess from
the game's object-name tables; every award id is logged, so earn an extra the game's object-name tables; every award id is logged, so earn an extra
ball, read the `AWARD` line, and pin it down (or override it in the port). ball, read the `AWARD` line, and pin it down (or override it in the port).
+2 -2
View File
@@ -7915,12 +7915,12 @@ static void stock_tick(void); /* item 160 */
static void magnet_tick(void); /* PAD-381 */ static void magnet_tick(void); /* PAD-381 */
static void scoop_tick(void); /* PAD-381 */ static void scoop_tick(void); /* PAD-381 */
/* ---- GAMELOG: passive stock-mode and award watching*/
#ifndef O_WRONLY #ifndef O_WRONLY
#define O_WRONLY 1 #define O_WRONLY 1
#define O_CREAT 0100 #define O_CREAT 0100
#define O_APPEND 02000 #define O_APPEND 02000
#endif for the gameplay logger. #endif
/* ---- GAMELOG: passive stock-mode and award watching for the gameplay logger.
* Added on top of the stock runtime (2026-10-12): logs the game's own modes * Added on top of the stock runtime (2026-10-12): logs the game's own modes
* (Island Scenes and the rest of the port's block_* set) starting and ending - * (Island Scenes and the rest of the port's block_* set) starting and ending -
* with the player's score at each edge, so the mode's score total is the * with the player's score at each edge, so the mode's score total is the
+24
View File
@@ -149,6 +149,11 @@ site event_cancel 0x0051f2ac 0xe92d40f8 0xe30b6c88
site switch_hit 0x0057ba64 0xe2503000 0x012fff1e site switch_hit 0x0057ba64 0xe2503000 0x012fff1e
# switch_hit2: located (strict) [The Beatles 1.29] # switch_hit2: located (strict) [The Beatles 1.29]
site switch_hit2 0x0057bb04 0xe92d4010 0xe2504000 site switch_hit2 0x0057bb04 0xe92d4010 0xe2504000
# switch_edge: the framework's per-switch call in its switch drain (generation B: r0 = the switch
# id, called for every edge after the new level is stored) [portswitch.switch_source on this build]
site switch_edge 0x0055fa04 0xe304337c 0xe3403093
# switch_drain: the drain itself, never hooked: an edge counts only when switch_edge is called from it
site switch_drain 0x005606e4 0xe92d4ff0 0xe30e9c70
# ---- globals: data <name> <address> ---- # ---- globals: data <name> <address> ----
# cur_player: derived from 2 places, e.g. 0x338790+0x60 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool Pro 1.16, TMNT Pro 1.59] # cur_player: derived from 2 places, e.g. 0x338790+0x60 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool Pro 1.16, TMNT Pro 1.59]
@@ -157,6 +162,10 @@ data cur_player 0x00819088
data scores 0x008ec3a0 data scores 0x008ec3a0
# mode_mask: derived from 2 places, e.g. 0x1c420+0xf8 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool LE 1.14, Deadpool Pro 1.16, TMNT Pro 1.59] # mode_mask: derived from 2 places, e.g. 0x1c420+0xf8 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool LE 1.14, Deadpool Pro 1.16, TMNT Pro 1.59]
data mode_mask 0x008b87fe data mode_mask 0x008b87fe
# switch_records: the switch drain's per-switch records [portswitch.switch_source on this build]
data switch_records 0x008ecc78
# switch_count: [portswitch.switch_source on this build]
data switch_count 0x0093437c
# event_head: derived from 2 places, e.g. 0x52d08+0x30 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool LE 1.14, Deadpool Pro 1.16, TMNT Pro 1.59] # event_head: derived from 2 places, e.g. 0x52d08+0x30 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool LE 1.14, Deadpool Pro 1.16, TMNT Pro 1.59]
data event_head 0x008ebc88 data event_head 0x008ebc88
# event_current: derived from 2 places, e.g. 0x4bc4c+0x4 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool LE 1.14, Deadpool Pro 1.16, TMNT Pro 1.59] # event_current: derived from 2 places, e.g. 0x4bc4c+0x4 [Godzilla Premium/LE 1.16, Godzilla Pro 1.15, The Beatles 1.29, Jaws LE 1.02, Deadpool LE 1.14, Deadpool Pro 1.16, TMNT Pro 1.59]
@@ -211,6 +220,13 @@ scene video_bank 60ed7e5036b8ce09d35a3e101ea6fc1380b37d97
scene attract 394c4a037fb26e12f536c42b2677bfed831f5c98 scene attract 394c4a037fb26e12f536c42b2677bfed831f5c98
# ---- values: COPIED from the references (framework offsets), unverified; the switch_* and ball_end_event values read from this build's own framework code ---- # ---- values: COPIED from the references (framework offsets), unverified; the switch_* and ball_end_event values read from this build's own framework code ----
# switch_*: the switch record's layout, read off this build's own drain by portswitch.switch_source
value switch_drain_size 384
value switch_record_size 32
value switch_level_at 24
value switch_desc_via 8
value switch_flags_at 26
value switch_polarity_at 28
value mode_mask_busy 0x210 value mode_mask_busy 0x210
value surface_playing 2 value surface_playing 2
value clip_layer 0 value clip_layer 0
@@ -851,3 +867,11 @@ text wizard_film_2 KING KONG spelled
data wizard_obj_3 0x008a7738 # cmode_trex_boss_battle, a multiball data wizard_obj_3 0x008a7738 # cmode_trex_boss_battle, a multiball
text wizard_name_3 T-Rex Boss Battle text wizard_name_3 T-Rex Boss Battle
text wizard_film_3 KING KONG spelled again text wizard_film_3 KING KONG spelled again
# ---- switches: the buttons, on bits the game's shot dispatch never sends (MODE_SDK.md, Buttons).
# The switch drain's edge logger (site switch_edge) arms only when the port has switch lines; these
# four also become named shots for the modes. Every edge of every switch lands in /dump/switch.log.
switch 34 0x1000000000000000 LOCKDOWN BUTTON
switch 36 0x2000000000000000 START BUTTON
switch 62 0x4000000000000000 RIGHT FLIPPER BUTTON
switch 63 0x8000000000000000 LEFT FLIPPER BUTTON