Files
tdkpin/original/C_RECONSTRUCTION_FINAL_AUDIT.md
T
ddidderr 7633ef9990 fix(attract): restore all remainder-driven cycles
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
2026-08-23 20:53:12 +02:00

6.9 KiB

TDKPIN.EXE C reconstruction final audit

Audit target:

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

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.