#include "../tdkpin_gameplay_helpers.h" #include #include int32_t g_ball_x_milli; int32_t g_ball_y_milli; uint8_t g_borland_cpu_level = 2; _Noreturn void borland_runtime_error(uint16_t code) { (void)code; __builtin_trap(); } _Noreturn void win16_integer_divide_fault(void) { __builtin_trap(); } 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_create_dc_calls; static unsigned g_select_calls; static unsigned g_blit_calls; static unsigned g_delete_dc_calls; static INT16 g_dest_x; static INT16 g_dest_y; static INT16 g_source_x; static INT16 g_source_y; static INT16 g_width; static INT16 g_capture_height; static INT16 g_present_height; BOOL16 GetClientRect16(HWND16 window, Win16FarPtr rectangle) { assert(window == 0x2222); assert(rectangle == win16_make_far_pointer(0x7000, 0x00e6)); return 1; } HDC16 GetDC16(HWND16 window) { assert(window == 0x2222); return 0x3333; } HDC16 CreateCompatibleDC16(HDC16 dc) { assert(dc == 0x3333 && g_create_dc_calls < 3); return (HDC16)(0x4001 + g_create_dc_calls++); } HBITMAP16 CreateCompatibleBitmap16(HDC16 dc, INT16 width, INT16 height) { assert(dc == 0x3333 && width == 100 && height == 100); return 0x5000; } HGDIOBJ16 SelectObject16(HDC16 dc, HGDIOBJ16 object) { switch (g_select_calls++) { case 0: assert(dc == 0x4001 && object == 0x6000); return 0x7001; case 1: assert(dc == 0x4002 && object == 0x5000); return 0x7002; case 2: assert(dc == 0x4001 && object == 0x6100); return 0x6000; case 3: assert(dc == 0x4001 && object == 0x6200); return 0x6100; case 4: assert(dc == 0x4001 && object == 0x7001); return 0x6200; case 5: assert(dc == 0x4002 && object == 0x7002); return 0x5000; default: assert(g_select_calls == 7); assert(dc == 0x4003 && object == 0x7003); return 0; } } 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) { switch (g_blit_calls++) { case 0: assert(destination == 0x4002 && destination_x == 0); assert(destination_y == 0 && width == g_width); assert(height == g_capture_height && source == 0x4001); assert(source_x == g_dest_x && source_y == g_dest_y); assert(raster_operation == 0x00cc0020u); break; case 1: assert(destination == 0x4002 && destination_x == g_source_x); assert(destination_y == g_source_y && width == 19 && height == 19); assert(source == 0x4001 && source_x == 0 && source_y == 0); assert(raster_operation == 0x008800c6u); break; case 2: assert(destination == 0x4002 && destination_x == g_source_x); assert(destination_y == g_source_y && width == 19 && height == 19); assert(source == 0x4001 && source_x == 0 && source_y == 0); assert(raster_operation == 0x00ee0086u); break; default: assert(g_blit_calls == 4); assert(destination == 0x3333 && destination_x == g_dest_x); assert(destination_y == g_dest_y && width == g_width); assert(height == g_present_height && source == 0x4002); assert(source_x == 0 && source_y == 0); assert(raster_operation == 0x00cc0020u); break; } return 1; } BOOL16 DeleteObject16(HGDIOBJ16 object) { assert(object == 0x5000); return 1; } BOOL16 DeleteDC16(HDC16 dc) { assert(dc == (HDC16)(0x4001 + g_delete_dc_calls)); g_delete_dc_calls++; return 1; } INT16 ReleaseDC16(HWND16 window, HDC16 dc) { assert(window == 0x2222 && dc == 0x3333); return 1; } 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_stack_u16(0x00fa, 0x7003); win16_write_u16(g_receiver, 4, 0x2222); win16_write_u16(g_receiver, 0x52, 0x6200); win16_write_u16(g_receiver, 0x54, 0x6100); win16_write_u16(win16_dgroup_pointer(0x085b), 0, 0x6000); g_create_dc_calls = 0; g_select_calls = 0; g_blit_calls = 0; g_delete_dc_calls = 0; } static void run_case( int32_t current_x, int32_t current_y, int32_t previous_x, int32_t previous_y, INT16 expected_dest_x, INT16 expected_dest_y, INT16 expected_source_x, INT16 expected_source_y, INT16 expected_width, INT16 expected_capture_height, INT16 expected_present_height, int32_t expected_delta_x, int32_t expected_delta_y) { prepare_fixture(); g_ball_x_milli = current_x; g_ball_y_milli = current_y; win16_write_u32(g_receiver, 0x0bc2, (uint32_t)previous_x); win16_write_u32(g_receiver, 0x0bc6, (uint32_t)previous_y); g_dest_x = expected_dest_x; g_dest_y = expected_dest_y; g_source_x = expected_source_x; g_source_y = expected_source_y; g_width = expected_width; g_capture_height = expected_capture_height; g_present_height = expected_present_height; tdkpin_render_ball_swept_region(0x0100); assert((int32_t)win16_read_u32( win16_far_add_offset(g_receiver, 0x0bb2)) == expected_delta_x); assert((int32_t)win16_read_u32( win16_far_add_offset(g_receiver, 0x0bb6)) == expected_delta_y); assert(g_create_dc_calls == 3 && g_select_calls == 7); assert(g_blit_calls == 4 && g_delete_dc_calls == 3); } int main(void) { run_case( 120000, 430000, 100000, 440000, 91, 421, 21, 1, 39, 29, 22, 20, -10); run_case( 80000, 400000, 100000, 380000, 71, 371, 1, 21, 39, 39, 39, -20, 20); prepare_fixture(); g_ball_x_milli = 100000; g_ball_y_milli = 400000; g_dest_x = 91; g_dest_y = 381; g_source_x = 21; g_source_y = 1; g_width = 39; g_capture_height = 29; g_present_height = 29; tdkpin_move_ball_and_render(0x0100, 20000, -10000); assert(g_ball_x_milli == 120000 && g_ball_y_milli == 390000); assert(win16_read_u32(win16_far_add_offset(g_receiver, 0x0bc2)) == 100000u); assert(win16_read_u32(win16_far_add_offset(g_receiver, 0x0bc6)) == 400000u); assert((int32_t)win16_read_u32( win16_far_add_offset(g_receiver, 0x0bb2)) == 20); assert((int32_t)win16_read_u32( win16_far_add_offset(g_receiver, 0x0bb6)) == -10); return 0; }