#include "../tdkpin_application.h" #include Win16FarPtr g_object_windows_application; HINSTANCE16 g_win16_previous_instance; HINSTANCE16 g_win16_instance; uint16_t g_win16_show_command; Win16FarPtr g_object_windows_dispatch_proc; uint16_t g_object_windows_thunk_code_selector; Win16FarPtr g_object_windows_free_thunk; static Win16FarPtr g_make_source; static HINSTANCE16 g_make_instance; static Win16FarPtr g_freed_proc; static Win16FarPtr g_first_method; static Win16FarPtr g_second_method; static unsigned g_method_calls; static bool g_first_sets_error; static unsigned g_heap_reserve_initializations; static Win16FarPtr g_freed_object; static uint16_t g_freed_size; static Win16FarPtr g_setup_method; static Win16FarPtr g_create_main_method; static Win16FarPtr g_created_main_window; static HWND16 g_shown_window; static INT16 g_show_command; BorlandAllocationAttempt borland_try_get_mem(uint16_t bytes) { (void)bytes; return (BorlandAllocationAttempt){0, true}; } bool borland_try_free_mem(Win16FarPtr object, uint16_t bytes) { g_freed_object = object; g_freed_size = bytes; return false; } _Noreturn void borland_runtime_error(uint16_t code) { (void)code; assert(false); __builtin_unreachable(); } Win16FarPtr MakeProcInstance16( Win16FarPtr procedure, HINSTANCE16 instance) { g_make_source = procedure; g_make_instance = instance; return win16_make_far_pointer(0x6200, 0x2222); } void FreeProcInstance16(Win16FarPtr procedure) { g_freed_proc = procedure; } void borland_initialize_heap_reserve(void) { g_heap_reserve_initializations++; } void win16_call_object_method( Win16FarPtr procedure, Win16FarPtr object) { g_method_calls++; if (procedure == g_setup_method) { return; } if (procedure == g_first_method) { if (g_first_sets_error) { win16_write_u16(object, 2, 5); } return; } assert(procedure == g_second_method); } Win16FarPtr win16_call_object_far_method( Win16FarPtr procedure, Win16FarPtr object) { (void)object; assert(procedure == g_create_main_method); return g_created_main_window; } BOOL16 ShowWindow16(HWND16 window, INT16 command) { g_shown_window = window; g_show_command = command; return 1; } static void reset_calls(void) { g_method_calls = 0; g_first_sets_error = false; g_heap_reserve_initializations = 0; g_freed_proc = 0; g_freed_object = 0; } int main(void) { static uint8_t dgroup[0x1000]; static uint8_t code[0x200]; static uint8_t object_bytes[64]; static uint8_t main_window_bytes[32]; win16_reset_segment_bindings(); win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true); win16_set_dgroup_selector(0x5000); win16_bind_ne_segment(4, 0x6000, code, sizeof(code), false); win16_bind_segment( 0x7000, object_bytes, sizeof(object_bytes), true); win16_bind_segment( 0x7100, main_window_bytes, sizeof(main_window_bytes), true); uint16_t vmt = 0x0200; win16_write_u16(win16_dgroup_pointer(vmt), 0, 18); g_first_method = win16_make_far_pointer(0x6100, 0x1000); g_second_method = win16_make_far_pointer(0x6100, 0x2000); g_setup_method = win16_make_far_pointer(0x6100, 0x3000); g_create_main_method = win16_make_far_pointer(0x6100, 0x4000); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x10)), 0, win16_far_offset(g_first_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x12)), 0, win16_far_selector(g_first_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x14)), 0, win16_far_offset(g_second_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x16)), 0, win16_far_selector(g_second_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x18)), 0, win16_far_offset(g_setup_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x1a)), 0, win16_far_selector(g_setup_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x34)), 0, win16_far_offset(g_create_main_method)); win16_write_u16(win16_dgroup_pointer((uint16_t)(vmt + 0x36)), 0, win16_far_selector(g_create_main_method)); Win16FarPtr object = win16_make_far_pointer(0x7000, 4); Win16FarPtr name = win16_make_far_pointer(0x5000, 0x0300); g_win16_instance = 0x1111; g_win16_previous_instance = 0; reset_calls(); assert(object_windows_application_construct(object, vmt, name) == object); assert(win16_read_u16(object) == vmt); assert(win16_read_far_pointer(object, 4) == name); assert(g_object_windows_application == object); assert(g_make_source == win16_make_far_pointer(0x6000, 0x0133)); assert(g_make_instance == 0x1111); assert(g_object_windows_dispatch_proc == win16_make_far_pointer(0x6200, 0x2222)); assert(g_heap_reserve_initializations == 1 && g_method_calls == 2); assert(!object_windows_application_idle_default(object)); object_windows_application_init_application_default(object); Win16FarPtr dialog = win16_make_far_pointer(0x7200, 0x3456); object_windows_application_set_active_dialog(object, dialog); assert(win16_read_far_pointer(object, 0x0e) == dialog); g_created_main_window = win16_make_far_pointer(0x7100, 2); win16_write_u16(g_created_main_window, 4, 0x0088); g_win16_show_command = 7; g_shown_window = 0; object_windows_application_initialize(object); assert(win16_read_far_pointer(object, 8) == g_created_main_window); assert(g_shown_window == 0x0088 && g_show_command == 7); g_created_main_window = 0; win16_write_u16(object, 2, 0); object_windows_application_initialize(object); assert(win16_read_far_pointer(object, 8) == 0); assert(win16_read_u16(win16_far_add_offset(object, 2)) == 0xfffb); g_shown_window = 0; object_windows_show(win16_make_far_pointer(0x7100, 10), 3); assert(g_shown_window == 0); reset_calls(); g_win16_previous_instance = 9; assert(object_windows_application_construct(object, vmt, name) == object); assert(g_method_calls == 1); /* With InitApplication skipped, the first observed call is InitInstance. */ assert(g_second_method != g_first_method); reset_calls(); g_win16_previous_instance = 0; g_first_sets_error = true; (void)object_windows_application_construct(object, vmt, name); assert(g_method_calls == 1); assert(win16_read_u16(win16_far_add_offset(object, 2)) == 5); win16_write_u16(object, 0, vmt); object_windows_application_destruct(object, 1); assert(g_freed_proc == g_object_windows_dispatch_proc); assert(g_freed_object == object && g_freed_size == 18); return 0; }