Add an atomic live-state injector for the traceable Wine process. It updates all recovered global and object copies of ball position and velocity while the process is stopped, clears pending impulses, and re-enables normal collision processing before resuming the unmodified executable. This makes individual walls, circles, gates, and mechanisms reachable without relying on random gameplay. Document the first controlled claw probe, including its original terminal-18 animation, exact release state, and three-substep gravity behavior. Test Plan: - `ruff check original/tools/trace_original_state.py original/tools/inject_original_state.py` -- passed - controlled `(289,94)` injection and one-second live claw trace -- passed - terminal-18 release matched `(325000,92000)` and `(0,1000)` -- passed - `shellcheck original/tools/run_traceable_original.sh` -- passed - `git diff --cached --check` -- passed
6.0 KiB
Mechanics reconstruction progress
This ledger scopes the current reverse-engineering pass to the claw and
flippers. The preserved executable is the authority; TDKPIN_GHIDRA_RAW.c
remains immutable raw evidence, while TDKPIN_MECHANICS_RESTORED.c carries
reviewed names and control flow.
Target: TDKPIN.EXE SHA-256
a9022f1894e3e6e21fc42e8f6c932f7c549ca77f63aaa0c488bb9d55d9d0174c.
Function inventory
| Address | Raw name | Restored role | Status |
|---|---|---|---|
1000:638e |
FUN_1000_638e |
key-release flag updates | reviewed |
1000:6bf8 |
FUN_1000_6bf8 |
key-press flag updates | reviewed |
1000:7ed9 |
FUN_1000_7ed9 |
flipper collision movement and sound | reviewed; inner fixed-point geometry still raw |
1000:8b0d |
FUN_1000_8b0d |
flipper bitmap/collider movement | reviewed; inner fixed-point geometry still raw |
1000:99f0 |
FUN_1000_99f0 |
binary flipper transition state machine | restored |
1000:c79c |
FUN_1000_c79c |
collision dispatch, including claw object 0x59 |
claw branch restored |
1000:eab1 |
exported ordinal 10 | timer tick, claw release and return | claw branch restored |
1008:0002 |
FUN_1008_0002 |
sound-enabled dispatch | restored |
1008:0e08 |
FUN_1008_0e08 |
claw background restore and sprite slicing | restored |
Inventory coverage is 9/9 functions inspected for this mechanism pass. This is not a claim that all instructions in the two large physics functions have been renamed.
Proven behavior now available to the Rust port
- Left Control (scan
0x1d) and keypad Enter (scan0x1c) set input flags; the timer changes each flipper position only between 0 and 1. - Every flipper movement edge, including return, invokes sound number 21, Win16 WAVE resource 2021.
- Claw collision object
0x59suspends the ball, zeros its live motion, disables collision records 12 through 20, and selects terminal frame 1, 6, 7, or 18. - The claw advances exactly one frame per timer tick to its terminal, releases the ball, then advances one frame per tick back to frame 10 before clearing the overlay and restoring collision records 12 through 20.
- Resource 900 is sliced into 100x74 frames, nine columns by four rows. The
destination is
(238,47); closing rows begin at source y=0 and opening rows at source y=148. - Claw capture/contact uses sound 2015; release uses sound 2016.
- The release-coordinate projection is
(raw + 500) / 1000for rendering; decoded physics centers are(258,78),(270,94),(275,97), and(325,92)for the four selectable terminal frames. - The speed scalar is 3800 millipixels per tick. Its Borland Real48 direction constants are decoded for all release cases in the readable C companion.
Explicit pending evidence
- Differentially verify the recovered 10/20/30/40/50 ms timer choices against live original captures; the Rust port intentionally uses the default 30 ms claw cadence independently of render rate.
- Transcribe the full fixed-point flipper impulse calculation, then compare it with the Rust floating-point collision response.
- Force each chosen claw terminal in the live original and compare its complete frame/trajectory sequence with the deterministic Rust trace. A controlled collision probe has covered terminal 18; terminals 1, 6, and 7 remain.
Those items are intentionally not counted as semantic parity. The readable C file preserves their raw constants and labels the unresolved conversion so a later implementation cannot silently turn an estimate into claimed evidence.
Runtime comparison on 2026-08-22
Wine 11.15 (staging) ran the preserved 16-bit NE executable from this tree.
Keypad + was sent to the real window and produced the one-player started
state. Down was then held for 1.1 seconds and released; captures confirmed that
the original plunger advances while held and launches only on release.
The Rust validation mode captured the corresponding started and half-charge states plus closing and release frames for claw terminal 6. That original live session did not reach the claw; the controlled tracing described below later captured an original terminal-18 sequence.
Live fixed-point tracing
Wine's remote debugger changes the Win16 exception path and is not suitable for
continuous gameplay traces. On Linux, tools/run_traceable_original.sh starts
the unmodified executable with a same-user ptrace opt-in. While it is waiting at
the launcher, tools/trace_original_state.py locates the live DGROUP and game
object by recovered binary/state signatures and records their fixed-point state:
original/tools/run_traceable_original.sh
original/tools/trace_original_state.py --duration 5 --output /tmp/launch.csv
The sampler records original millipixel positions, predicted positions,
velocities, flipper inputs and states, and claw animation state whenever any of
them changes. It neither patches TDKPIN.EXE nor pauses Wine. The tracing helper
is Linux-only development infrastructure; it is not part of the Rust replica.
tools/inject_original_state.py briefly stops the opted-in process and updates
all recovered copies of the ball position and velocity atomically. This permits
repeatable probes at individual walls, circles, gates, and mechanism triggers:
original/tools/inject_original_state.py --x 289 --y 94 --vx 0 --vy 0
The executable image remains unchanged; only the current disposable Wine
process is modified. Run the injector while the ball is waiting in the launcher
so it can identify the live game object, or supply the previously reported
--object-base during a sequence of probes.
A probe at (289,94) captured the original terminal-18 path. The collision
suspended the ball while frames advanced from 10 through 18 at the configured
30 ms cadence. Release assigned (325000,92000) and (0,1000) millipixels,
then cleared suspension during the same timer callback. The three default
physics substeps each added 15 millipixels of vertical velocity, confirming the
observed total gravity increment of 45 per timer tick.