#include "../tdkpin_mechanism_render.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 unsigned g_select_calls; static unsigned g_blit_calls; static unsigned g_refresh_calls; static unsigned g_sound_calls; static unsigned g_delete_dc_calls; static int32_t g_state; HDC16 GetDC16(HWND16 window) { assert(window == 0x2222); return 0x3333; } HDC16 CreateCompatibleDC16(HDC16 dc) { static unsigned calls; assert(dc == 0x3333); HDC16 result = (HDC16)(0x4001 + calls); calls = (calls + 1u) % 2u; return result; } HBITMAP16 CreateCompatibleBitmap16(HDC16 dc, INT16 width, INT16 height) { assert(dc == 0x3333 && width == 91 && height == 90); return 0x5000; } HGDIOBJ16 SelectObject16(HDC16 dc, HGDIOBJ16 object) { unsigned call = g_select_calls++; if (call == 0) { assert(dc == 0x4001 && object == 0x6000); return 0x7001; } if (call == 1) { assert(dc == 0x4002 && object == 0x5000); return 0x7002; } if (g_state >= 6 && call == 2) { assert(dc == 0x4001 && object == 0x6001); return 0x6000; } if (g_state >= 6 && call == 3) { assert(dc == 0x4001 && object == 0x6000); return 0x6001; } unsigned cleanup_base = g_state >= 6 ? 4u : 2u; if (call == cleanup_base) { assert(dc == 0x4001 && object == 0x7001); return 0x6000; } assert(call == cleanup_base + 1u); assert(dc == 0x4002 && object == 0x7002); return 0x5000; } static const INT16 state_one_positions[5][2] = { {9, 41}, {23, 11}, {56, 14}, {63, 47}, {35, 63}}; static const INT16 state_six_positions[5][2] = { {8, 35}, {26, 8}, {59, 18}, {59, 50}, {27, 61}}; BOOL16 BitBlt16( HDC16 destination, INT16 destination_x, INT16 destination_y, INT16 width, INT16 height, HDC16 source, INT16 source_x, INT16 source_y, uint32_t raster_operation) { unsigned call = g_blit_calls++; if (call == 0) { assert(destination == 0x4002 && destination_x == 0); assert(destination_y == 0 && width == 91 && height == 90); assert(source == 0x4001); assert(source_x == (g_state < 6 ? 0 : 79)); assert(source_y == (g_state < 6 ? 0 : 33)); assert(raster_operation == 0x00cc0020u); return 1; } if (call <= 10) { unsigned target = (call - 1u) / 2u; const INT16 (*positions)[2] = g_state == 1 ? state_one_positions : state_six_positions; assert(destination == 0x4002); assert(destination_x == positions[target][0]); assert(destination_y == positions[target][1]); assert(width == 17 && height == 17 && source == 0x4001); assert(source_x == 455); if ((call & 1u) != 0) { assert(source_y == 17 && raster_operation == 0x008800c6u); } else { assert(source_y == 0 && raster_operation == 0x00ee0086u); } return 1; } assert(call == 11); assert(destination == 0x3333 && destination_x == 79); assert(destination_y == 33 && width == 91 && height == 90); assert(source == 0x4002 && source_x == 0 && source_y == 0); assert(raster_operation == 0x00cc0020u); return 1; } BOOL16 DeleteObject16(HGDIOBJ16 object) { assert(object == 0x5000); return 1; } BOOL16 DeleteDC16(HDC16 dc) { assert(dc == (g_delete_dc_calls == 0 ? 0x4002 : 0x4001)); g_delete_dc_calls++; return 1; } INT16 ReleaseDC16(HWND16 window, HDC16 dc) { assert(window == 0x2222 && dc == 0x3333); return 1; } void tdkpin_refresh_player_item(uint16_t caller_bp, uint16_t item) { assert(caller_bp == 0x0100 && item == 15 + g_refresh_calls); g_refresh_calls++; } void tdkpin_play_sound_if_not_tilted(uint16_t sound_number) { assert(sound_number == 11); g_sound_calls++; } static void prepare_fixture(int32_t state) { 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); win16_write_u16(win16_dgroup_pointer(0x0859), 0, 0x6000); win16_write_u16(win16_dgroup_pointer(0x085d), 0, 0x6001); win16_write_u32(win16_dgroup_pointer(0x0855), 0, (uint32_t)state); static const uint16_t words[5] = { 0x3371, 0x33c4, 0x3417, 0x346a, 0x34bd}; for (uint16_t index = 0; index < 5; index++) { win16_write_u16( win16_dgroup_pointer(words[index]), 0, (uint16_t)(index + 1)); } g_current_player = 2; for (uint16_t index = 0; index < 5; index++) { win16_write_u8( win16_far_add_offset( g_receiver, (uint16_t)(0x0476 + 2u * 0x14u + index)), (uint8_t)(0xa0 + index)); } g_state = state; g_select_calls = 0; g_blit_calls = 0; g_refresh_calls = 0; g_sound_calls = 0; g_delete_dc_calls = 0; } static void test_state_one(void) { prepare_fixture(1); tdkpin_rotate_and_draw_targets(0x0100); assert(g_blit_calls == 12 && g_select_calls == 4); assert(g_sound_calls == 1 && g_refresh_calls == 0); } static void test_state_six_rotation(void) { prepare_fixture(6); tdkpin_rotate_and_draw_targets(0x0100); assert(g_blit_calls == 12 && g_select_calls == 6); assert(g_sound_calls == 0 && g_refresh_calls == 5); static const uint16_t words[5] = { 0x3371, 0x33c4, 0x3417, 0x346a, 0x34bd}; static const uint16_t expected_words[5] = {2, 3, 4, 5, 1}; for (uint16_t index = 0; index < 5; index++) { assert(win16_read_u16(win16_dgroup_pointer(words[index])) == expected_words[index]); assert(win16_read_u8(win16_far_add_offset( g_receiver, (uint16_t)(0x0476 + 2u * 0x14u + index))) == (uint8_t)(0xa0 + (index + 1u) % 5u)); } } int main(void) { test_state_one(); test_state_six_rotation(); return 0; }