Replace each invented centerline capsule with the original pair of moving line records and moving tip circle. Use the exact asymmetric raised coordinates read from live objects 66-68 and 81-83, while preserving their recovered type-1 and type-2 fixed-point response coefficients in normal object traversal. Remove the last generic segment overlap solver. Edge-time ball transfer remains separate because the original applies it after physics while moving the records. Test Plan: - `cargo test --all-targets` -- 43 passed - `cargo clippy --all-targets -- -D warnings` -- passed - live left and right key-edge record dumps matched the Rust coordinates - `git diff --cached --check` -- passed
142 lines
7.6 KiB
Markdown
142 lines
7.6 KiB
Markdown
# 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 (scan `0x1c`) 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 `0x59` suspends 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) / 1000` for 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:
|
|
|
|
```sh
|
|
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` updates all recovered copies of the ball
|
|
position and velocity between the original 30 ms callbacks. This permits
|
|
repeatable probes at individual walls, circles, gates, and mechanism triggers:
|
|
|
|
```sh
|
|
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` to both the injector and tracer during a sequence of active
|
|
probes. `--substeps 1` isolates one collision integration step; omitting it
|
|
retains the original configured detail level. `--stop-process` is available for
|
|
single probes, but repeated whole-process stops can strand Wine while a Win16
|
|
mutex is held and therefore are not the default.
|
|
|
|
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.
|
|
|
|
A one-substep probe against the vertical shooter walls recovered the type-2
|
|
response arithmetic. For unit tangent `t` from the registered start to end and
|
|
left normal `n`, an incoming contact with `vn = dot(v,n)` and `vt = dot(v,t)`
|
|
uses `vn' = -0.6 * vn` and `vt' = vt + 0.1 * vn` for the ordinary rail
|
|
coefficients stored in its two Real48 fields. The new position is the previous
|
|
position plus this response velocity; the original does not separate a circle
|
|
from the line with a modern capsule solver.
|
|
|
|
Fresh one-substep probes recovered type-1 response in the radial basis. With
|
|
outward normal `n`, clockwise tangent `t`, entering speed `vn < 0`, and tangent
|
|
speed `vt`, ordinary object 155 produced `vn' = -0.6 * vn` and
|
|
`vt' = vt - 0.1 * vn`. Bumper 51 additionally added `0.4 * 3800` along `n`.
|
|
The exact captured transitions were `(0,-940) -> (94,564)` and
|
|
`(0,-1970) -> (197,3096)` millipixels per substep.
|
|
|
|
Live key edges recovered all moving flipper geometry. The raised left records
|
|
are line 66 `(98,382)->(131,369)`, circle 67 `(133,377)`, and line 68
|
|
`(137,384)->(116,405)`. The raised right records are line 81
|
|
`(197,405)->(171,378)`, circle 82 `(181,376)`, and line 83
|
|
`(183,368)->(217,383)`. Resting records retain their registration-table
|
|
coordinates. Edge-time position and velocity transfer remains a separate
|
|
arithmetic restoration task.
|