#include "../tdkpin_multimedia.h" #include "../tdkpin_borland_files.h" #include "../tdkpin_borland_records.h" #include #include #include #include Win16FarPtr g_multimedia_procedures[11]; HINSTANCE16 g_multimedia_module; uint8_t g_multimedia_initialized; uint8_t g_multimedia_pending; uint16_t g_multimedia_version; uint8_t g_multimedia_auto_subclassed; uint8_t g_multimedia_argument_2; uint8_t g_multimedia_argument_1; uint8_t g_multimedia_legacy_windows; char g_multimedia_library_path[21]; uint16_t g_multimedia_system_directory_length; uint16_t g_multimedia_windows_version; HINSTANCE16 g_win16_previous_instance; HINSTANCE16 g_win16_instance; uint16_t g_win16_show_command; _Atomic uint16_t g_borland_io_result; uint8_t g_borland_file_mode; static const char *g_system_directory = "SYS"; static uint16_t g_get_version_result; static uint16_t g_open_results[4]; static unsigned g_open_result_count; static unsigned g_open_result_index; static unsigned g_assign_calls; static unsigned g_close_calls; static unsigned g_require_calls; static uint8_t g_assigned_length; static uint8_t g_assigned_last; UINT16 GetSystemDirectoryFar16(Win16FarPtr buffer, UINT16 size) { assert(size == 200); size_t length = strlen(g_system_directory); for (size_t index = 0; index <= length; index++) { win16_write_u8( win16_far_add_offset(buffer, (uint16_t)index), (uint8_t)g_system_directory[index]); } return (UINT16)length; } uint32_t GetVersion16(void) { return 0xbeef0000u | g_get_version_result; } void borland_assign_file_short(Win16FarPtr name, Win16FarPtr record) { (void)record; g_assign_calls++; g_assigned_length = win16_read_u8(name); g_assigned_last = win16_read_u8( win16_far_add_offset(name, g_assigned_length)); } void borland_open_generic_file(uint16_t record_size, Win16FarPtr record) { (void)record; assert(record_size == 1); assert(g_open_result_index < g_open_result_count); atomic_store( &g_borland_io_result, g_open_results[g_open_result_index++]); } uint16_t borland_take_io_result(void) { return atomic_exchange(&g_borland_io_result, 0); } void borland_close_generic_file(Win16FarPtr record) { (void)record; g_close_calls++; } void borland_require_io_success(void) { assert(atomic_load(&g_borland_io_result) == 0); g_require_calls++; } static void reset_probe_results(void) { g_open_result_count = 0; g_open_result_index = 0; g_assign_calls = 0; g_close_calls = 0; g_require_calls = 0; atomic_store(&g_borland_io_result, 0); } static void expect_short( Win16FarPtr string, const char *expected) { size_t length = strlen(expected); assert(win16_read_u8(string) == length); for (size_t index = 0; index < length; index++) { assert(win16_read_u8(win16_far_add_offset( string, (uint16_t)(index + 1))) == (uint8_t)expected[index]); } } static void expect_c_string( Win16FarPtr string, const char *expected) { size_t length = strlen(expected); for (size_t index = 0; index <= length; index++) { assert(win16_read_u8(win16_far_add_offset( string, (uint16_t)index)) == (uint8_t)expected[index]); } } static void reset_unit_state(uint8_t *dgroup) { memset(dgroup + 0x4750, 0xcc, 0x3d); memcpy(dgroup + 0x0522, "CTL3D.DLL", 10); memcpy(dgroup + 0x052c, "CTL3DV2.DLL", 12); for (unsigned index = 0; index < 11; index++) { g_multimedia_procedures[index] = win16_make_far_pointer(0x8888, (uint16_t)index); } g_multimedia_module = 0x7777; g_multimedia_initialized = 1; g_multimedia_pending = 1; g_multimedia_auto_subclassed = 1; g_multimedia_argument_1 = 9; g_multimedia_argument_2 = 8; } int main(void) { static uint8_t dgroup[0x6000]; static uint8_t code[0x600]; uint8_t stack_anchor = 0; uintptr_t stack_base = (uintptr_t)&stack_anchor - 0x8000; win16_reset_segment_bindings(); win16_bind_segment(0x7000, dgroup, sizeof(dgroup), true); win16_set_dgroup_selector(0x7000); win16_bind_ne_segment(3, 0x6000, code, sizeof(code), false); win16_bind_segment(0x7200, (void *)stack_base, 0x10000, true); code[0x0470] = 1; code[0x0471] = '\\'; Win16FarPtr short_name = win16_make_far_pointer(0x7000, 0x600); win16_write_u8(short_name, 3); win16_write_u8(win16_far_add_offset(short_name, 1), 'A'); win16_write_u8(win16_far_add_offset(short_name, 2), 'B'); win16_write_u8(win16_far_add_offset(short_name, 3), 'C'); reset_probe_results(); g_open_result_count = 1; g_open_results[0] = 2; assert(!multimedia_short_file_exists(short_name)); assert(g_assign_calls == 1 && g_assigned_length == 3 && g_assigned_last == 'C'); assert(g_close_calls == 0 && g_require_calls == 0); reset_probe_results(); g_open_result_count = 1; g_open_results[0] = 0; assert(multimedia_short_file_exists(short_name)); assert(g_close_calls == 1 && g_require_calls == 1); reset_probe_results(); reset_unit_state(dgroup); g_system_directory = "SYS"; g_open_result_count = 1; g_open_results[0] = 0; /* CTL3DV2 exists. */ g_get_version_result = 0x0003; multimedia_initialize_runtime_unit(); assert(g_open_result_index == 1); expect_short( win16_make_far_pointer(0x7000, 0x486d), "SYS\\CTL3D.DLL"); expect_short( win16_make_far_pointer(0x7000, 0x496d), "SYS\\CTL3DV2.DLL"); expect_c_string( win16_make_far_pointer(0x7000, 0x478d), "CTL3DV2.DLL"); assert(g_multimedia_system_directory_length == 3); assert(g_multimedia_windows_version == 0x0003); assert(g_multimedia_legacy_windows == 1); for (unsigned index = 0; index < 11; index++) { assert(g_multimedia_procedures[index] == 0); } assert(g_multimedia_auto_subclassed == 0); assert(g_multimedia_argument_2 == 0 && g_multimedia_argument_1 == 1); assert(g_multimedia_module == 0 && g_multimedia_pending == 0 && g_multimedia_initialized == 0); reset_probe_results(); reset_unit_state(dgroup); g_open_result_count = 2; g_open_results[0] = 2; /* V2 absent. */ g_open_results[1] = 0; /* Classic present. */ g_get_version_result = 0x0a03; multimedia_initialize_runtime_unit(); assert(g_open_result_index == 2); expect_c_string( win16_make_far_pointer(0x7000, 0x478d), "CTL3D.DLL"); assert(g_multimedia_legacy_windows == 0); reset_probe_results(); reset_unit_state(dgroup); g_open_result_count = 2; g_open_results[0] = 2; g_open_results[1] = 3; g_get_version_result = 0x0004; multimedia_initialize_runtime_unit(); expect_c_string( win16_make_far_pointer(0x7000, 0x478d), "CTL3DV2.DLL"); assert(g_multimedia_legacy_windows == 0); reset_probe_results(); reset_unit_state(dgroup); memcpy(dgroup + 0x478d, "KEEP", 5); g_system_directory = ""; g_get_version_result = 0x0004; multimedia_initialize_runtime_unit(); assert(g_open_result_index == 0); expect_c_string( win16_make_far_pointer(0x7000, 0x478d), "KEEP"); return 0; }