#include "../tdkpin_player_state.h" #include #include uint8_t g_player_count; 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 unsigned g_collision_calls; static unsigned g_restore_record_calls; static unsigned g_zero_score_calls; static unsigned g_add_score_calls; static unsigned g_marker_calls; static unsigned g_item_calls; static unsigned g_restore_a_calls; static unsigned g_restore_b_calls; static unsigned g_present_calls; static unsigned g_sprite_calls; static unsigned g_get_dc_calls; static unsigned g_release_dc_calls; static uint16_t g_last_sprite; static int32_t g_last_shown_score; static int32_t g_added_delta[4]; static uint8_t g_add_player[4]; void tdkpin_refresh_collision_record(uint16_t caller_bp, uint16_t id) { assert(caller_bp == 0x0100); assert(id == g_collision_calls + 1); g_collision_calls++; } void tdkpin_restore_record_b(uint16_t caller_bp, uint16_t id) { assert(caller_bp == 0x0100); assert(id == 1001 + g_restore_record_calls); g_restore_record_calls++; } void tdkpin_draw_score_from_caller_frame( uint16_t caller_bp, uint16_t low, uint16_t high) { assert(caller_bp == 0x0100); int32_t value = (int32_t)((uint32_t)low | ((uint32_t)high << 16)); if (value == 0 && g_zero_score_calls == 0) { g_zero_score_calls++; } else { g_last_shown_score = value; } } void tdkpin_add_score_from_caller_frame(uint16_t caller_bp, int32_t delta) { assert(caller_bp == 0x0100 && g_add_score_calls < 4); g_added_delta[g_add_score_calls] = delta; g_add_player[g_add_score_calls] = g_current_player; g_add_score_calls++; } void tdkpin_refresh_player_progress_markers(uint16_t caller_bp) { assert(caller_bp == 0x0100); assert(g_current_player == g_marker_calls + 1); g_marker_calls++; } void tdkpin_refresh_player_item(uint16_t caller_bp, uint16_t item) { assert(caller_bp == 0x0100 && g_current_player == 1); assert(item == g_item_calls + 1); g_item_calls++; } 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; } static void check_geometry( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 dc) { assert(dc == 0x3333); bool panel = height == 31 && width == 139 && x == 472; bool marker = height == 11 && width == 11 && x == 372; bool score_area = height == 123 && width == 42 && y == 79 && x == 55; assert(panel || marker || score_area); if (panel || marker) { uint16_t base = panel ? 276 : 280; assert(y >= (INT16)base && ((uint16_t)(y - base) % 44u) == 0); } } void tdkpin_restore_background_region_a( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 dc) { check_geometry(height, width, y, x, dc); assert(height != 123); g_restore_a_calls++; } void tdkpin_restore_background_region_b( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 dc) { check_geometry(height, width, y, x, dc); assert(height == 11); g_restore_b_calls++; } void tdkpin_present_background_region( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 dc) { check_geometry(height, width, y, x, dc); g_present_calls++; } void tdkpin_composite_player_sprite(uint16_t sprite_index, HDC16 dc) { assert(dc == 0x3333); g_last_sprite = sprite_index; g_sprite_calls++; } int32_t borland_multiply_i32(int32_t left, int32_t right) { return (int32_t)((uint32_t)left * (uint32_t)right); } static void prepare_fixture(void) { memset(g_stack, 0, sizeof(g_stack)); memset(g_object, 0xa5, sizeof(g_object)); memset(g_dgroup, 0xcc, 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_collision_calls = 0; g_restore_record_calls = 0; g_zero_score_calls = 0; g_add_score_calls = 0; g_marker_calls = 0; g_item_calls = 0; g_restore_a_calls = 0; g_restore_b_calls = 0; g_present_calls = 0; g_sprite_calls = 0; g_get_dc_calls = 0; g_release_dc_calls = 0; g_last_sprite = 0; g_last_shown_score = 0; memset(g_added_delta, 0, sizeof(g_added_delta)); memset(g_add_player, 0, sizeof(g_add_player)); } static void test_initialize_player_state(void) { prepare_fixture(); g_player_count = 2; g_current_player = 4; for (uint16_t id = 1; id <= 175; id++) { win16_write_u16( win16_dgroup_pointer((uint16_t)( 0x095b + id * 0x53u + 0x43u)), 0, (uint16_t)(0x1000 + id)); } tdkpin_initialize_player_state(0x0100); assert(g_collision_calls == 175 && g_restore_record_calls == 5); assert(g_zero_score_calls == 1); for (uint16_t player = 1; player <= 4; player++) { for (uint16_t id = 1; id <= 175; id++) { assert(win16_read_u16(win16_far_add_offset( g_receiver, (uint16_t)(0x036c + player * 0x015eu + id * 2u))) == (uint16_t)(0x1000 + id)); } } assert(g_add_score_calls == 2 && g_marker_calls == 2); assert(g_add_player[0] == 1 && g_add_player[1] == 2); assert(g_added_delta[0] == 0 && g_added_delta[1] == 0); for (uint16_t player = 1; player <= 2; player++) { assert(win16_read_u32(win16_dgroup_pointer( (uint16_t)(0x097e + player * 4u))) == 0); assert(win16_read_u32(win16_dgroup_pointer( (uint16_t)(0x098e + player * 4u))) == 0); assert(win16_read_u8(win16_dgroup_pointer( (uint16_t)(0x09a1 + player))) == 1); assert(win16_read_u16(win16_dgroup_pointer( (uint16_t)(0x09a4 + player * 2u))) == 0); assert(win16_read_u8(win16_dgroup_pointer( (uint16_t)(0x0816 + player))) == 1); assert(win16_read_u16(win16_dgroup_pointer( (uint16_t)(0x081f + player * 2u))) == (player == 1 ? 2 : 3)); assert(win16_read_u32(win16_dgroup_pointer( (uint16_t)(0x0835 + player * 4u))) == 1); assert(win16_read_u8(win16_dgroup_pointer( (uint16_t)(0x081a + player))) == 1); for (uint16_t item = 1; item <= 20; item++) { assert(win16_read_u8(win16_far_add_offset( g_receiver, (uint16_t)(0x0467 + player * 0x14u + item))) == 0); } } assert(g_current_player == 1 && g_item_calls == 20); assert(win16_read_u8(win16_dgroup_pointer(0x07d2)) == 0); assert(win16_read_u8(win16_dgroup_pointer(0x0874)) == 0); } static void test_redraw_all_players(void) { prepare_fixture(); g_player_count = 3; g_current_player = 2; win16_write_u32(win16_dgroup_pointer(0x0996), 0, 10); win16_write_u8(win16_dgroup_pointer(0x09a3), 3); win16_write_u16(win16_dgroup_pointer(0x09a8), 0, 5); tdkpin_redraw_all_players(0x0100); assert(g_add_score_calls == 3); assert(g_add_player[0] == 1 && g_added_delta[0] == -1); assert(g_add_player[1] == 2 && g_added_delta[1] == 0); assert(g_add_player[2] == 3 && g_added_delta[2] == -1); assert(g_last_shown_score == 30); assert(g_sprite_calls == 1 && g_last_sprite == 5); assert(g_restore_a_calls == 4 && g_restore_b_calls == 2); assert(g_present_calls == 7); assert(g_current_player == 2); assert(g_get_dc_calls == 1 && g_release_dc_calls == 1); } static void set_effect(uint16_t effect) { win16_write_u16( win16_dgroup_pointer((uint16_t)(0x09a4 + g_current_player * 2u)), 0, effect); } static void test_player_sprite_effects(void) { static const uint32_t additions[5] = { 10000u, 20000u, 50000u, 100000u, 200000u}; for (uint16_t effect = 1; effect <= 5; effect++) { prepare_fixture(); g_current_player = 2; set_effect(effect); win16_write_u32(win16_dgroup_pointer(0x0996), 0, 0xfffffff0u); win16_write_u8(win16_dgroup_pointer(0x09a3), 3); tdkpin_apply_player_sprite_effect(0x0100, 0); uint32_t expected = 0xfffffff0u + additions[effect - 1u]; assert(win16_read_u32(win16_dgroup_pointer(0x0996)) == expected); assert((uint32_t)g_last_shown_score == expected * 3u); assert(g_add_score_calls == 0); } prepare_fixture(); g_current_player = 2; set_effect(6); win16_write_u32(win16_dgroup_pointer(0x0996), 0, 12345); win16_write_u8(win16_dgroup_pointer(0x09a3), 4); tdkpin_apply_player_sprite_effect(0x0100, 0); assert(g_add_score_calls == 1 && g_added_delta[0] == 49380); assert(win16_read_u32(win16_dgroup_pointer(0x0996)) == 0); assert(g_last_shown_score == 0); prepare_fixture(); g_current_player = 2; set_effect(7); win16_write_u16(win16_dgroup_pointer(0x399a), 0, 55); win16_write_u8(win16_dgroup_pointer(0x0874), 0); win16_write_u8(win16_far_add_offset(g_receiver, 0x0be0), 0); tdkpin_apply_player_sprite_effect(0x0100, 55); assert(win16_read_u8(win16_dgroup_pointer(0x0874)) == 0); assert(win16_read_u8(win16_far_add_offset(g_receiver, 0x0be0)) == 0); tdkpin_apply_player_sprite_effect(0x0100, -1); assert(win16_read_u8(win16_dgroup_pointer(0x0874)) == 1); assert(win16_read_u8(win16_far_add_offset(g_receiver, 0x0be0)) == 1); } int main(void) { test_initialize_player_state(); test_redraw_all_players(); test_player_sprite_effects(); return 0; }