fix(physics): restore relative slingshot response
A full comparison against the 175-record ledger found stale guessed coordinates in both relative slingshot chains. Circles 56/58/71/73 and lines 57/59/72/74 were displaced by up to 70 pixels. The corrected record-57 geometry then exposed a second issue: readable C and Rust had collapsed two independent binary response projections into one. Transcribe the accumulated initializer coordinates exactly. Use the swapped-component projection only to sign the current tangential response `abs(normal_velocity) * response_tangent`, and use the standard dot product for `spin_delta * 0.02 * response_tangent`. Correct the readable C evidence and Rust together, extend live tracing with the six-byte spin field, and seal the stopped-Wine transition from `(75530,354765)/(3000,15)` to `(77369,356597)/(1839,1832)` with Real48 spin `-5.28` in both harnesses. Test Plan: - stopped Wine 11.15 record-57 injection/trace -- matched position, velocity, and spin - `cargo test --workspace --all-targets --all-features` -- 123 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 - `python3 -m py_compile original/tools/trace_original_state.py original/tools/inject_original_state.py` -- passed - `rumdl check --flavor commonmark RECONSTRUCTION.md CHANGELOG.md` -- passed - `git diff --cached --check` -- passed
This commit is contained in:
@@ -21,6 +21,7 @@ from trace_original_state import (
|
||||
PHYSICS_SUBSTEPS,
|
||||
PREVIOUS_BALL_X,
|
||||
PREVIOUS_BALL_Y,
|
||||
SPIN_REAL48,
|
||||
VELOCITY_X,
|
||||
VELOCITY_Y,
|
||||
ProcessMemory,
|
||||
@@ -139,7 +140,8 @@ def main() -> None:
|
||||
memory.write(object_base + BALL_SUSPENDED, bytes(1))
|
||||
print(
|
||||
f"TDKPIN pid={pid} data={data_base:#x} object={object_base:#x} "
|
||||
f"ball=({args.x:.3f},{args.y:.3f}) velocity=({args.vx:.3f},{args.vy:.3f})"
|
||||
f"ball=({args.x:.3f},{args.y:.3f}) velocity=({args.vx:.3f},{args.vy:.3f}) "
|
||||
f"spin={int.from_bytes(memory.read(object_base + SPIN_REAL48, 6), 'little'):#014x}"
|
||||
)
|
||||
finally:
|
||||
if resume_afterward:
|
||||
|
||||
@@ -39,6 +39,7 @@ GRAVITY_PER_SUBSTEP = 0x005A
|
||||
ACTIVE_BALL_COUNT = 0x0061
|
||||
VELOCITY_X = 0x0BAA
|
||||
VELOCITY_Y = 0x0BAE
|
||||
SPIN_REAL48 = 0x0BCE
|
||||
PREVIOUS_BALL_X = 0x0BBA
|
||||
PREVIOUS_BALL_Y = 0x0BBE
|
||||
OBJECT_BALL_X = 0x0BC2
|
||||
@@ -224,6 +225,7 @@ CSV_FIELDS = [
|
||||
"next_ball_y_milli",
|
||||
"velocity_x_milli_per_tick",
|
||||
"velocity_y_milli_per_tick",
|
||||
"spin_real48_bits",
|
||||
"previous_ball_x_milli",
|
||||
"previous_ball_y_milli",
|
||||
"object_ball_x_milli",
|
||||
@@ -257,6 +259,7 @@ def sample_state(data: bytes, obj: bytes) -> tuple[int, ...]:
|
||||
unpack_i32(data, NEXT_BALL_Y),
|
||||
unpack_i32(obj, VELOCITY_X),
|
||||
unpack_i32(obj, VELOCITY_Y),
|
||||
int.from_bytes(obj[SPIN_REAL48 : SPIN_REAL48 + 6], "little"),
|
||||
unpack_i32(obj, PREVIOUS_BALL_X),
|
||||
unpack_i32(obj, PREVIOUS_BALL_Y),
|
||||
unpack_i32(obj, OBJECT_BALL_X),
|
||||
|
||||
Reference in New Issue
Block a user