The same raw Div32 pattern used by the item animation appears in every nested idle phase: after division by 32, 40, or 16, the binary copies the remainder from CX:BX before the second division. Readable C and Rust used quotients for targets, word quads, the record strip, and the four-point chase, turning short repeating chases into slow one-shot progressions. Use `%32/2`, `%32/4`, `%40/4`, and `%16/4` for those cycles alongside the already corrected `%144/8` items. Preserve the first-cycle phase-zero delay, then repeat each incremental overlay state exactly. Add C and Rust coverage at phase activation, reversal, deactivation, and wrap boundaries. Test Plan: - raw instruction review at `1000:01b7-063b` -- all remainder transfers confirmed - `cargo test --workspace --all-targets --all-features` -- 125 passed - `cargo clippy --workspace --all-targets --all-features -- -D warnings` -- passed - `bash original/tools/test_reconstructed_c.sh` -- passed - `python3 original/tools/audit_reconstruction.py --require-complete` -- passed with zero incomplete or unclassified units - `cargo run -- --simulate attract --step 145 --screenshot /tmp/tdkpin-attract-remainder.png` -- passed; visually inspected at 640x460 - `rumdl check --flavor commonmark RECONSTRUCTION.md CHANGELOG.md` -- passed - `git diff --cached --check` -- passed
116 lines
6.9 KiB
Markdown
116 lines
6.9 KiB
Markdown
# TDKPIN.EXE C reconstruction final audit
|
|
|
|
Audit target:
|
|
|
|
```text
|
|
a9022f1894e3e6e21fc42e8f6c932f7c549ca77f63aaa0c488bb9d55d9d0174c TDKPIN.EXE
|
|
987a47580ba5c92fa071c989bdaeddf138e285d2b07106c5909a4acbc3e27088 TDKPIN_GHIDRA_RAW.c
|
|
```
|
|
|
|
The vendor source is unavailable. “Faithful C” therefore means an
|
|
address-traceable semantic reconstruction whose claims are closed by image
|
|
bytes, disassembly, relocation/reference data, typed Win16/Borland behavior,
|
|
and focused runtime evidence. It does not mean a byte-identical rebuild with
|
|
the original Borland compiler.
|
|
|
|
## Requirement audit
|
|
|
|
1. **Immutable evidence:** `TDKPIN_GHIDRA_RAW.c` retains its sealed hash.
|
|
Regenerated complete raw evidence is separate and never used as readable C.
|
|
2. **Executable bytes:** all 93,064 executable-segment bytes are classified.
|
|
93,062 have non-overlapping Ghidra code/data units. The remaining two are
|
|
individually explained in `UNEXPLAINED.tsv` as an overlapping-entry opcode
|
|
at `1020:0666` and an alignment NOP at `1020:0dea`; zero bytes are
|
|
unclassified.
|
|
3. **Functions:** 391 ordinary in-image functions and all six overlapping/shared
|
|
entries are `verified`. Every ordinary function row names its exact address,
|
|
readable C symbol, source module, disassembly evidence, and semantic result.
|
|
No row is raw, partial, restored, unknown, or blocked.
|
|
4. **Readable C:** the authoritative deliverable is the 63 strict-C11 units
|
|
under `reconstructed/`. Historical partial `TDKPIN_*_RESTORED.c` files are
|
|
explicitly marked superseded and are not completion artifacts.
|
|
5. **Imports and ABI:** all 292 NE import slots are verified. The 137 called
|
|
slots have reviewed Win16 prototypes and call-site effects; 155 duplicate,
|
|
data-only, or unused slots have explicit zero-CALL accounting. Segment/offset
|
|
far pointers, PASCAL stack cleanup, 16-bit widths/wrap, and intentionally
|
|
retained register bytes are represented in the C model.
|
|
6. **Runtime library:** every in-image Borland routine is reconstructed or
|
|
identified through its exact implementation role. Real48 conversion,
|
|
arithmetic, comparison, transcendental tables, rounding, overflow/error
|
|
behavior, heap, files, strings, objects, and startup/shutdown paths are
|
|
address-linked rather than silently omitted.
|
|
7. **Data:** all 19,770 DGROUP bytes are covered by 744 non-overlapping verified
|
|
ranges and 219 verified semantic objects. All 455 referenced DGROUP addresses
|
|
and all 18 code-embedded objects (282 bytes) are verified. The complete
|
|
175-record collision/rule table and all indirect dispatch/VMT/procedure
|
|
tables are represented.
|
|
8. **Callbacks and indirect control flow:** all six callback registrations are
|
|
verified with target, thunk/instance lifetime, and invocation behavior. All
|
|
301 NE entry points, 2,434 relocation sites, VMT dispatches, bound thunks,
|
|
function pointers, and shared/overlapping entries are inventoried.
|
|
9. **Resources:** all 63 NE resources round-trip byte-for-byte from the target
|
|
and have decoded derivatives where applicable. `RESOURCE_RECONSTRUCTION.tsv`
|
|
has 63 verified rows. The semantic C catalog in `tdkpin_resources.c` records
|
|
every type/ID, file offset, flags, allocated/meaningful size, dimensions or
|
|
sample rate, disposition, and role. Four Borland File Open/Save templates are
|
|
explicitly `linked-unused`; ICON 1 and VERSION 1 are Windows-resolved rather
|
|
than falsely assigned image-code callers. WAV 2022 is loaded/freed by the
|
|
generic loop but has no in-image playback selector.
|
|
10. **Companion timer:** `MMTIMER.DLL` is sealed as
|
|
`f1d9ac980c7bfba5dc53eaa9e7cb2c3cd9b82f879ee8962ad40bf863d641bb49`.
|
|
TDKPIN's sole ordinal-1 relocation/call, the DLL's timer callback, message
|
|
`0x0580`, returned timer ID, and `timeKillEvent` lifetime are mapped.
|
|
11. **Behavioral validation:** every reconstructed C unit is compiled with
|
|
strict warnings by `tools/test_reconstructed_c.sh`; 89 focused harness
|
|
units cover normal, boundary, error, ownership, ABI, rendering, persistence,
|
|
resource, physics, callback, and lifecycle paths. The resource verifier
|
|
proves all 63 raw hashes and derivatives. `probe_real48_reference.sh`
|
|
matches a real 16-bit Borland reference stream bit-for-bit. Documented
|
|
Wine 11.15 probes cover original startup/input, timer gravity/substeps,
|
|
claw terminals, moving flippers, collision types 1..4, target/rule effects,
|
|
multiball, and scoring. Static/host evidence is not mislabeled as Wine.
|
|
12. **Phase boundary:** no Rust source or Cargo manifest/lockfile was modified.
|
|
|
|
Post-audit evidence correction (2026-08-23): raw `1000:9b69` reads predicted
|
|
DGROUP coordinates `1028:07db/07df`, not current `07d3/07d7`. The readable
|
|
helper and its harness now reflect that distinction; the complete C test and
|
|
ledger gates below still pass. Raw `1000:c79c` also confirms that the response
|
|
reads fixed candidate slot 1 at `SS:...d8a2`; later nearer candidates are stored
|
|
in subsequent 0x34-byte slots but do not replace the applied record. A focused
|
|
two-candidate harness now seals that record-order behavior.
|
|
Raw `1000:531e` further corrects the Pascal-order BitBlt interpretation: the
|
|
DAT994 progress strip is drawn at `(202,328)` with height 13 and width
|
|
`(stage-1)*7`, rather than the impossible historical 328x202 read from a
|
|
237x13 bitmap. The focused loading-stage harness seals stages 1, 35, and 0.
|
|
Live one-substep rail/circle probes further correct the response transform.
|
|
The binary's standard dot-product tangent
|
|
`tv=(vx*normal_x + vy*normal_y)/length` drives
|
|
`spin_delta=tv*0.02*response_tangent`. The current tangential response opposes
|
|
the sign of `tv` with magnitude
|
|
`abs(normal_velocity)*response_tangent` (negative when `tv==0`) and is added to
|
|
retained `spin*0.4`. The documented horizontal drain
|
|
`(0,3015)->(-302,-1809)`, ordinary circle/bumper transitions, and stopped
|
|
Wine record-57 transition `(75530,354765)/(3000,15)` to
|
|
`(77369,356597)/(1839,1832)` with exact Real48 spin `-5.28`, plus record 72
|
|
`(235348,356825)/(-3000,15)` to `(233253,358494)/(-2095,1669)` with spin
|
|
`+5.46`, seal both paths and both relative slingshot chains.
|
|
Raw `1000:01b7-063b` further distinguishes the DOS divide outputs throughout
|
|
the idle animation: each nested phase copies the first division's remainder
|
|
from `CX:BX` before its second division. The readable C and focused timer
|
|
harness therefore use target `%32/2`, word-quad `%32/4`, record-strip `%40/4`,
|
|
four-point `%16/4`, and item `%144/8` cycles. This produces the repeating
|
|
animation rather than the previously inferred unbounded quotients.
|
|
|
|
## Reproducible gates
|
|
|
|
```sh
|
|
bash original/tools/test_reconstructed_c.sh
|
|
bash original/tools/probe_real48_reference.sh
|
|
python3 original/tools/audit_reconstruction.py --require-complete
|
|
git diff -- '*.rs' Cargo.toml Cargo.lock
|
|
```
|
|
|
|
The final ledger gate requires every function, import, data range/object,
|
|
resource, callback, and shared entry to be `verified`, plus zero unclassified
|
|
executable ranges. At this audit all required incomplete-status counts are zero.
|