#include "../tdkpin_collision_events.h" #include #include uint8_t g_current_player; static uint8_t g_stack[0x400]; static uint8_t g_object[0x0c00]; static uint8_t g_dgroup[0x5000]; static Win16FarPtr g_receiver; static uint16_t g_restore_ids[64]; static uint16_t g_refresh_ids[64]; static uint16_t g_sounds[32]; static int32_t g_scores[32]; static unsigned g_restore_calls; static unsigned g_refresh_calls; static unsigned g_sound_calls; static unsigned g_score_calls; static unsigned g_draw_score_calls; static unsigned g_composite_calls; static unsigned g_present_calls; static unsigned g_restore_background_calls; static unsigned g_get_dc_calls; static unsigned g_release_dc_calls; static unsigned g_random_calls; static uint16_t g_random_values[4]; static uint16_t g_last_sprite; static int32_t g_last_drawn_score; static Win16FarPtr record(uint16_t id) { return win16_dgroup_pointer((uint16_t)(0x095b + id * 0x53u)); } void tdkpin_restore_record_or_item_a(uint16_t caller_bp, uint16_t id) { assert(caller_bp == 0x0100 && g_restore_calls < 64); g_restore_ids[g_restore_calls++] = id; } void tdkpin_refresh_collision_record(uint16_t caller_bp, uint16_t id) { assert(caller_bp == 0x0100 && g_refresh_calls < 64); g_refresh_ids[g_refresh_calls++] = id; } void tdkpin_play_sound_if_not_tilted(uint16_t sound_number) { assert(g_sound_calls < 32); g_sounds[g_sound_calls++] = sound_number; } void tdkpin_add_score_from_caller_frame(uint16_t caller_bp, int32_t delta) { assert(caller_bp == 0x0100 && g_score_calls < 32); g_scores[g_score_calls++] = delta; } void tdkpin_draw_score_from_caller_frame( uint16_t caller_bp, uint16_t low, uint16_t high) { assert(caller_bp == 0x0100); g_last_drawn_score = (int32_t)((uint32_t)low | ((uint32_t)high << 16)); g_draw_score_calls++; } uint16_t borland_random_below(uint16_t upper_bound) { assert(upper_bound == 6 && g_random_calls < 4); return g_random_values[g_random_calls++]; } int32_t borland_multiply_i32(int32_t left, int32_t right) { return (int32_t)((uint32_t)left * (uint32_t)right); } HDC16 GetDC16(HWND16 window) { assert(window == 0x2222); g_get_dc_calls++; return 0x3333; } INT16 ReleaseDC16(HWND16 window, HDC16 dc) { assert(window == 0x2222 && dc == 0x3333); g_release_dc_calls++; return 1; } void tdkpin_composite_player_sprite(uint16_t sprite_index, HDC16 dc) { assert(dc == 0x3333); g_last_sprite = sprite_index; g_composite_calls++; } void tdkpin_restore_background_region_a( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 dc) { assert(height > 0 && width > 0 && dc == 0x3333); (void)y; (void)x; g_restore_background_calls++; } void tdkpin_present_background_region( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 dc) { assert(height > 0 && width > 0 && dc == 0x3333); (void)y; (void)x; g_present_calls++; } static void reset_counters(void) { memset(g_restore_ids, 0, sizeof(g_restore_ids)); memset(g_refresh_ids, 0, sizeof(g_refresh_ids)); memset(g_sounds, 0, sizeof(g_sounds)); memset(g_scores, 0, sizeof(g_scores)); g_restore_calls = 0; g_refresh_calls = 0; g_sound_calls = 0; g_score_calls = 0; g_draw_score_calls = 0; g_composite_calls = 0; g_present_calls = 0; g_restore_background_calls = 0; g_get_dc_calls = 0; g_release_dc_calls = 0; g_random_calls = 0; memset(g_random_values, 0, sizeof(g_random_values)); g_last_sprite = 0; g_last_drawn_score = 0; } static void prepare_fixture(void) { memset(g_stack, 0, sizeof(g_stack)); memset(g_object, 0, sizeof(g_object)); memset(g_dgroup, 0, sizeof(g_dgroup)); win16_reset_segment_bindings(); win16_bind_segment(0x7000, g_stack, sizeof(g_stack), true); win16_bind_segment(0x7100, g_object, sizeof(g_object), true); win16_bind_segment(0x7200, g_dgroup, sizeof(g_dgroup), true); win16_set_dgroup_selector(0x7200); win16_set_stack_state(0x7000, 0); g_receiver = win16_make_far_pointer(0x7100, 0); win16_write_stack_u16(0x0106, win16_far_offset(g_receiver)); win16_write_stack_u16(0x0108, win16_far_selector(g_receiver)); win16_write_u16(g_receiver, 4, 0x2222); g_current_player = 2; reset_counters(); } static void seed_bounds(uint16_t id, INT16 left, INT16 top) { win16_write_u16(record(id), 0x4b, (uint16_t)left); win16_write_u16(record(id), 0x4d, (uint16_t)top); win16_write_u16(record(id), 0x4f, (uint16_t)(left + 2)); win16_write_u16(record(id), 0x51, (uint16_t)(top + 3)); } static void test_tilt_and_combined_low_events(void) { prepare_fixture(); win16_write_u8(win16_dgroup_pointer(0x07c6), 1); tdkpin_handle_collision_events(0x0100, 0xffff, 129); assert(g_restore_calls == 0 && g_sound_calls == 0); prepare_fixture(); win16_write_u16(record(129), 0x43, 20); win16_write_u8(win16_far_add_offset(record(20), 0x34), 1); win16_write_u8(win16_far_add_offset(record(21), 0x34), 1); win16_write_u8(win16_far_add_offset(record(22), 0x34), 1); tdkpin_handle_collision_events( 0x0100, 0x0001u | 0x0002u | 0x2000u | 0x0400u, 129); assert(win16_read_u8(win16_far_add_offset( g_receiver, (uint16_t)(0x0467 + 2u * 20u + 15u))) == 1); assert(g_restore_calls == 1 && g_restore_ids[0] == 1015); assert(g_refresh_calls == 1 && g_refresh_ids[0] == 20); assert(win16_read_u8(win16_far_add_offset(record(20), 0x34)) == 0); assert(win16_read_u8(win16_far_add_offset(record(21), 0x34)) == 0); assert(win16_read_u8(win16_far_add_offset(record(22), 0x34)) == 0); assert(win16_read_u32(win16_dgroup_pointer(0x0855)) == 0); assert(win16_read_u8(win16_dgroup_pointer(0x07c7)) == 1); } static void test_sprite_award(void) { prepare_fixture(); win16_write_u16(win16_dgroup_pointer(0x09a8), 0, 2); g_random_values[0] = 1; g_random_values[1] = 2; tdkpin_handle_collision_events(0x0100, 0x0004, 0); assert(g_sound_calls == 1 && g_sounds[0] == 12); assert(win16_read_u8(win16_far_add_offset(record(149), 0x34)) == 1); assert(g_restore_ids[0] == 149 && g_random_calls == 2); assert(win16_read_u16(win16_dgroup_pointer(0x09a8)) == 3); assert(g_composite_calls == 1 && g_last_sprite == 3); assert(g_present_calls == 1 && g_get_dc_calls == 1); prepare_fixture(); win16_write_u16(win16_dgroup_pointer(0x399a), 0, 1); tdkpin_handle_collision_events(0x0100, 0x0004, 0); assert(win16_read_u16(win16_dgroup_pointer(0x09a8)) == 7); assert(g_random_calls == 0 && g_last_sprite == 7); } static void set_group_heads(uint16_t first, uint16_t groups, uint8_t active) { for (uint16_t group = 0; group < groups; group++) { win16_write_u8( win16_far_add_offset(record((uint16_t)(first + group * 3u)), 0x34), active); } } static void test_ready_bank(void) { prepare_fixture(); set_group_heads(90, 5, 0); win16_write_u8(win16_dgroup_pointer(0x0818), 6); tdkpin_handle_collision_events(0x0100, 0x0008, 0); assert(g_sound_calls == 2 && g_sounds[0] == 12 && g_sounds[1] == 17); assert(g_score_calls == 1 && g_scores[0] == 50000); assert(g_refresh_calls == 5); prepare_fixture(); set_group_heads(90, 5, 0); win16_write_u8(win16_dgroup_pointer(0x0818), 2); tdkpin_handle_collision_events(0x0100, 0x0008, 0); assert(win16_read_u8(win16_dgroup_pointer(0x0818)) == 3); assert(g_restore_calls == 1 && g_restore_ids[0] == 1002); assert(g_score_calls == 0 && g_refresh_calls == 5); } static void set_item_bank_count(uint16_t count) { for (uint16_t item = 1; item <= count; item++) { win16_write_u8(win16_far_add_offset( g_receiver, (uint16_t)(0x046c + 2u * 20u + item)), 1); } } static void test_item_bank_branches(void) { prepare_fixture(); set_group_heads(109, 4, 0); tdkpin_handle_collision_events(0x0100, 0x0010, 0); assert(g_restore_ids[0] == 1006 && g_scores[0] == 10000); assert(g_refresh_calls == 4); prepare_fixture(); set_group_heads(109, 4, 0); set_item_bank_count(8); seed_bounds(153, 1, 2); seed_bounds(6, 3, 4); seed_bounds(154, 5, 6); tdkpin_handle_collision_events(0x0100, 0x0010, 0); assert(g_restore_ids[0] == 1014 && g_scores[0] == 24464); assert(win16_read_u8(win16_far_add_offset(g_receiver, 0x0bdc)) == 1); assert(g_restore_background_calls == 3 && g_present_calls == 3); assert(g_get_dc_calls == 1 && g_release_dc_calls == 1); prepare_fixture(); set_group_heads(109, 4, 0); set_item_bank_count(9); win16_write_u8(win16_far_add_offset(g_receiver, 0x0bdc), 1); win16_write_u32(win16_dgroup_pointer(0x0996), 0, 10); win16_write_u8(win16_dgroup_pointer(0x09a3), 3); tdkpin_handle_collision_events(0x0100, 0x0010, 0); assert(win16_read_u32(win16_dgroup_pointer(0x0996)) == 100010u); assert(g_draw_score_calls == 1 && g_last_drawn_score == 300030); assert(g_sounds[1] == 7); } static void test_switch_and_timed_records(void) { static const uint16_t event_ids[3] = {150, 151, 152}; static const uint16_t related[3] = {153, 6, 154}; for (uint16_t index = 0; index < 3; index++) { prepare_fixture(); tdkpin_handle_collision_events(0x0100, 0x1000, event_ids[index]); assert(win16_read_u8(win16_far_add_offset( g_receiver, (uint16_t)(0x00f7 + index))) == 10); assert(g_restore_calls == 2); assert(g_restore_ids[0] == event_ids[index]); assert(g_restore_ids[1] == related[index]); assert(win16_read_u8(win16_far_add_offset( record(related[index]), 0x34)) == 1); } prepare_fixture(); win16_write_u8(win16_dgroup_pointer(0x0818), 3); tdkpin_handle_collision_events(0x0100, 0x0040, 51); assert(g_sounds[0] == 6 && g_restore_ids[0] == 51); assert(g_scores[0] == 2000); assert(win16_read_u8(win16_far_add_offset(g_receiver, 0x94)) == 5); prepare_fixture(); tdkpin_handle_collision_events(0x0100, 0x0040, 140); assert(win16_read_u8(win16_far_add_offset(g_receiver, 0x00ed)) == 20); assert(g_restore_ids[0] == 140 && g_sound_calls == 0); } int main(void) { test_tilt_and_combined_low_events(); test_sprite_award(); test_ready_bank(); test_item_bank_branches(); test_switch_and_timed_records(); return 0; }