fix(physics): restore standard tangent sign response
The left relative slingshot probe proved the spin projection, but its geometry did not distinguish the sign rule. A stopped-Wine probe on symmetric record 72 did: the binary uses the standard dot-product tangent for both spin and the opposing direction of the current tangential response. The earlier swapped-component interpretation happened to agree for vertical walls and a centered circle but selected the wrong sign on the right slingshot. Use `tv=(vx*nx+vy*ny)/length`, update spin with `tv*0.02*response_tangent`, and apply `-sign(tv)*abs(normal_velocity)*response_tangent`, retaining the binary's negative direction when tv is zero. Seal record 72's exact position, velocity, and `+5.46` Real48 spin in C and Rust. Keep the two-minute autoplay assertion focused on actual launch, press/release, target, bumper, and finite-state activity after the corrected trajectory. Test Plan: - stopped Wine 11.15 record-72 injection/trace -- matched position, velocity, and spin - `cargo test --workspace --all-targets --all-features` -- 124 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 - `rumdl check --flavor commonmark RECONSTRUCTION.md CHANGELOG.md` -- passed - `git diff --cached --check` -- passed
This commit is contained in:
@@ -518,6 +518,51 @@ static void test_live_relative_record_57_transition(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void test_live_relative_record_72_transition(void)
|
||||
{
|
||||
prepare_fixture();
|
||||
set_ball(238348, 356810, -3000, 0);
|
||||
win16_write_u32(g_window, 0x5a, 15);
|
||||
win16_write_u32(g_window, 0x56, 3800);
|
||||
TdkpinCollisionRecord segment = base_record(2);
|
||||
segment.bounds_min_x_milli = 209000;
|
||||
segment.bounds_min_y_milli = 339000;
|
||||
segment.bounds_max_x_milli = 266000;
|
||||
segment.bounds_max_y_milli = 371000;
|
||||
segment.point1_x_milli = 261000;
|
||||
segment.point1_y_milli = 344000;
|
||||
segment.point2_x_milli = 214000;
|
||||
segment.point2_y_milli = 366000;
|
||||
segment.response_normal =
|
||||
(BorlandReal48){{0x80,0x00,0x00,0x00,0x00,0x00}};
|
||||
segment.response_tangent =
|
||||
(BorlandReal48){{0x7d,0xcd,0xcc,0xcc,0xcc,0x4c}};
|
||||
segment.layer_mask = 2;
|
||||
write_record(72, &segment);
|
||||
|
||||
tdkpin_simulate_ball_and_dispatch_collision(0x0300);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_dgroup_pointer(0x07d3)) == 235348);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_dgroup_pointer(0x07d7)) == 356825);
|
||||
tdkpin_simulate_ball_and_dispatch_collision(0x0300);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_dgroup_pointer(0x07d3)) == 233253);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_dgroup_pointer(0x07d7)) == 358494);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_far_add_offset(g_window, 0x0baa)) == -2095);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_far_add_offset(g_window, 0x0bae)) == 1669);
|
||||
static const uint8_t expected_spin[6] = {
|
||||
0x83, 0x86, 0xeb, 0x51, 0xb8, 0x2e};
|
||||
for (uint16_t index = 0; index < 6; index++) {
|
||||
assert(win16_read_u8(win16_far_add_offset(
|
||||
g_window, (uint16_t)(0x0bce + index))) ==
|
||||
expected_spin[index]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_free_integration_and_speed_clamp();
|
||||
@@ -526,5 +571,6 @@ int main(void)
|
||||
test_capture_boundary_and_claw();
|
||||
test_out_of_bounds_and_zero_substeps_multiball();
|
||||
test_live_relative_record_57_transition();
|
||||
test_live_relative_record_72_transition();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user