fix(flippers): match original moving-hit geometry
The clone's moving-flipper gate used the cross-product operands in the opposite order, mirroring and narrowing the hit wedge. Right-flipper release also used record 81's first endpoint even though the original reads its second endpoint. Correct both geometry paths, retain the recovered swept tip bounds, and add live-binary boundary vectors plus a dense transition regression. Test Plan: - `cargo test --workspace --all-targets --all-features` -- passed (134 tests) - `cargo clippy --workspace --all-targets --all-features -- -D warnings` -- passed - `cargo build --profile production` -- passed - `LSAN_OPTIONS=detect_leaks=0 ASAN_OPTIONS=detect_leaks=0 bash original/tools/test_reconstructed_c.sh` -- passed - `python3 original/tools/audit_reconstruction.py --require-complete` -- passed - `git diff --cached --check` -- passed
This commit is contained in:
@@ -158,10 +158,10 @@ static FlipperCollisionGeometry load_flipper_geometry(
|
||||
geometry.unused_positive_point_x = record_i32(
|
||||
81, offsetof(TdkpinCollisionRecord, point1_x_milli));
|
||||
geometry.positive_edge_x = subtract_wrap_i32(
|
||||
record_i32(81, offsetof(TdkpinCollisionRecord, point1_x_milli)),
|
||||
record_i32(81, offsetof(TdkpinCollisionRecord, point2_x_milli)),
|
||||
20000);
|
||||
geometry.positive_edge_y = record_i32(
|
||||
81, offsetof(TdkpinCollisionRecord, point1_y_milli));
|
||||
81, offsetof(TdkpinCollisionRecord, point2_y_milli));
|
||||
geometry.response_record = delta == 1 ? 81 : 83;
|
||||
} else {
|
||||
geometry = (FlipperCollisionGeometry){
|
||||
@@ -202,8 +202,8 @@ static int32_t cross_product_for_edge(
|
||||
int32_t edge_from_pivot_x = divide_by_thousand(
|
||||
subtract_wrap_i32(edge_x, pivot_x));
|
||||
return subtract_wrap_i32(
|
||||
borland_multiply_i32(edge_from_ball_y, edge_from_pivot_x),
|
||||
borland_multiply_i32(edge_from_ball_x, edge_from_pivot_y));
|
||||
borland_multiply_i32(edge_from_ball_x, edge_from_pivot_y),
|
||||
borland_multiply_i32(edge_from_ball_y, edge_from_pivot_x));
|
||||
}
|
||||
|
||||
static int32_t radial_distance_milli(
|
||||
|
||||
@@ -185,11 +185,25 @@ static void test_right_positive_contact(void)
|
||||
win16_far_add_offset(g_receiver, 0x0baa)) == -737);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_far_add_offset(g_receiver, 0x0bae)) == 2263);
|
||||
assert(g_move_x == -8549 && g_move_y == 26250);
|
||||
assert(g_move_x == -5578 && g_move_y == 17127);
|
||||
assert(g_sound_count == 1 && g_sounds[0] == 21);
|
||||
assert(g_move_calls == 1);
|
||||
}
|
||||
|
||||
static void test_live_binary_cross_product_order(void)
|
||||
{
|
||||
prepare_fixture();
|
||||
win16_write_u32(g_receiver, 0x56, 3800);
|
||||
set_ball(100000, 370000, 1000, 2000);
|
||||
tdkpin_move_flipper_collision_geometry(0x0300, -1, 1, 0);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_far_add_offset(g_receiver, 0x0baa)) == -189);
|
||||
assert((int32_t)win16_read_u32(
|
||||
win16_far_add_offset(g_receiver, 0x0bae)) == 960);
|
||||
assert(g_move_x == 0 && g_move_y == 0);
|
||||
assert(g_move_calls == 1);
|
||||
}
|
||||
|
||||
static void test_left_positive_contact(void)
|
||||
{
|
||||
prepare_fixture();
|
||||
@@ -230,8 +244,12 @@ static void test_vertical_edge_fallbacks(void)
|
||||
prepare_fixture();
|
||||
write_i32(
|
||||
81,
|
||||
offsetof(TdkpinCollisionRecord, point1_x_milli),
|
||||
offsetof(TdkpinCollisionRecord, point2_x_milli),
|
||||
240000);
|
||||
write_i32(
|
||||
81,
|
||||
offsetof(TdkpinCollisionRecord, point2_y_milli),
|
||||
411000);
|
||||
set_ball(197000, 455000, -1000, 2000);
|
||||
tdkpin_move_flipper_collision_geometry(0x0300, 1, 2, 0);
|
||||
assert(g_move_calls == 1 && g_move_y == 1000);
|
||||
@@ -270,6 +288,7 @@ int main(void)
|
||||
{
|
||||
test_left_negative_contact();
|
||||
test_right_positive_contact();
|
||||
test_live_binary_cross_product_order();
|
||||
test_left_positive_contact();
|
||||
test_right_negative_contact();
|
||||
test_vertical_edge_fallbacks();
|
||||
|
||||
Reference in New Issue
Block a user