Replace the partial mechanics transcriptions with a separate, readable C11 reconstruction of the complete Win16 image while preserving the original raw Ghidra export as immutable evidence. Cover all ordinary and overlapping entry points, Borland runtime behavior, Win16 imports, segmented data, callbacks, resources, indirect control flow, physics, rendering, persistence, and startup/shutdown lifecycles. Add deterministic extraction and audit tooling plus address-linked ledgers for functions, imports, DGROUP ranges and objects, relocations, resources, and callbacks. The final gate records zero raw, partial, restored, unknown, blocked, or unclassified required units. Keep the semantic-fidelity boundary explicit: the portable C is not claimed to reproduce a byte-identical Borland NE build. Add strict focused harnesses for every reconstructed C unit, exact resource round-trip checks, and a 16-bit Borland Real48 reference probe. No Rust source or Cargo metadata is changed in this phase. Test Plan: - `bash original/tools/test_reconstructed_c.sh` -- passed - `bash original/tools/probe_real48_reference.sh` -- passed bit-for-bit - `python3 original/tools/audit_reconstruction.py --require-complete` -- passed - `git diff --cached --check` -- passed - `git diff HEAD -- '*.rs' Cargo.toml Cargo.lock` -- empty
201 lines
6.7 KiB
C
201 lines
6.7 KiB
C
#include "../tdkpin_application.h"
|
|
|
|
#include <assert.h>
|
|
|
|
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;
|
|
}
|