Files
ddidderr 8b99e9607c feat(reconstruction): complete binary-backed C recovery
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
2026-08-23 16:41:17 +02:00

275 lines
8.6 KiB
C

#include "../tdkpin_application.h"
#include <assert.h>
#include <string.h>
Win16FarPtr g_object_windows_application;
HINSTANCE16 g_win16_previous_instance;
HINSTANCE16 g_win16_instance;
Win16FarPtr g_object_windows_dispatch_proc;
uint16_t g_object_windows_thunk_code_selector;
Win16FarPtr g_object_windows_free_thunk;
Win16FarPtr g_object_windows_message_hook;
static MSG16 g_messages[4];
static unsigned g_message_index;
static unsigned g_message_count;
static unsigned g_empty_before_messages;
static unsigned g_wait_calls;
static unsigned g_translate_calls;
static unsigned g_dispatch_calls;
static bool g_idle_result;
static bool g_main_filter_result;
static Win16FarPtr g_filter_order[4];
static unsigned g_filter_calls;
static Win16FarPtr g_true_filter;
static BOOL16 g_dialog_result;
static HWND16 g_dialog_window;
static INT16 g_accelerator_result;
static HWND16 g_accelerator_window;
static HACCEL16 g_accelerator;
static BOOL16 g_mdi_result;
static HWND16 g_mdi_window;
static Win16FarPtr g_client_object;
static Win16FarPtr g_client_getter;
static Win16FarPtr g_bool_procedure;
static Win16FarPtr g_void_method;
static Win16FarPtr g_error_method;
static uint16_t g_error_argument;
BOOL16 PeekMessage16(
MSG16 *message,
HWND16 window,
UINT16 minimum_message,
UINT16 maximum_message,
UINT16 remove_message)
{
assert(window == 0 && minimum_message == 0 && maximum_message == 0);
assert(remove_message == 1);
if (g_empty_before_messages != 0) {
g_empty_before_messages--;
return 0;
}
assert(g_message_index < g_message_count);
*message = g_messages[g_message_index++];
return 1;
}
BOOL16 WaitMessage16(void)
{
g_wait_calls++;
return 1;
}
BOOL16 TranslateMessage16(const MSG16 *message)
{
assert(message->message != 0x12);
g_translate_calls++;
return 1;
}
LRESULT16 DispatchMessage16(const MSG16 *message)
{
assert(message->message != 0x12);
g_dispatch_calls++;
return 0;
}
BOOL16 IsDialogMessage16(HWND16 dialog, MSG16 *message)
{
(void)message;
g_dialog_window = dialog;
return g_dialog_result;
}
INT16 TranslateAccelerator16(
HWND16 window, HACCEL16 accelerator, MSG16 *message)
{
(void)message;
g_accelerator_window = window;
g_accelerator = accelerator;
return g_accelerator_result;
}
BOOL16 TranslateMDISysAccel16(HWND16 client, MSG16 *message)
{
(void)message;
g_mdi_window = client;
return g_mdi_result;
}
bool win16_call_object_bool_method(
Win16FarPtr procedure, Win16FarPtr object)
{
(void)procedure;
(void)object;
g_bool_procedure = procedure;
return g_idle_result;
}
bool win16_call_application_message_filter(
Win16FarPtr procedure, Win16FarPtr application, MSG16 *message)
{
(void)application;
(void)message;
g_filter_order[g_filter_calls++] = procedure;
if (g_filter_calls == 1 && g_main_filter_result) {
return true;
}
return procedure == g_true_filter;
}
Win16FarPtr win16_call_object_far_method(
Win16FarPtr procedure, Win16FarPtr object)
{
assert(procedure == g_client_getter);
(void)object;
return g_client_object;
}
void win16_call_object_method(
Win16FarPtr procedure, Win16FarPtr object)
{
(void)object;
g_void_method = procedure;
}
void win16_call_object_u16_method(
Win16FarPtr procedure, Win16FarPtr object, uint16_t argument)
{
(void)object;
g_error_method = procedure;
g_error_argument = argument;
}
static void write_far(uint16_t selector, uint16_t offset, Win16FarPtr value)
{
Win16FarPtr base = win16_make_far_pointer(selector, offset);
win16_write_u16(base, 0, win16_far_offset(value));
win16_write_u16(base, 2, win16_far_selector(value));
}
int main(void)
{
static uint8_t dgroup[0x1000];
static uint8_t application_bytes[64];
static uint8_t window_bytes[64];
static uint8_t dialog_bytes[32];
static uint8_t client_bytes[32];
win16_reset_segment_bindings();
win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true);
win16_set_dgroup_selector(0x5000);
win16_bind_segment(
0x7000, application_bytes, sizeof(application_bytes), true);
win16_bind_segment(0x7100, window_bytes, sizeof(window_bytes), true);
win16_bind_segment(0x7200, dialog_bytes, sizeof(dialog_bytes), true);
win16_bind_segment(0x7300, client_bytes, sizeof(client_bytes), true);
Win16FarPtr application = win16_make_far_pointer(0x7000, 2);
Win16FarPtr main_window = win16_make_far_pointer(0x7100, 2);
Win16FarPtr dialog = win16_make_far_pointer(0x7200, 2);
g_client_object = win16_make_far_pointer(0x7300, 2);
const uint16_t app_vmt = 0x0100;
const uint16_t window_vmt = 0x0200;
win16_write_u16(application, 0, app_vmt);
win16_write_u16(main_window, 0, window_vmt);
write_far(0x7000, 10, main_window);
write_far(0x7000, 16, dialog);
win16_write_u16(main_window, 4, 0x1111);
win16_write_u16(dialog, 4, 0x2222);
win16_write_u16(g_client_object, 4, 0x3333);
Win16FarPtr idle_proc = win16_make_far_pointer(0x6000, 0x1000);
Win16FarPtr main_filter = win16_make_far_pointer(0x6000, 0x2000);
Win16FarPtr run_proc = win16_make_far_pointer(0x6000, 0x2100);
Win16FarPtr error_proc = win16_make_far_pointer(0x6000, 0x2200);
Win16FarPtr filters[3] = {
win16_make_far_pointer(0x6000, 0x3000),
win16_make_far_pointer(0x6000, 0x4000),
win16_make_far_pointer(0x6000, 0x5000),
};
write_far(0x5000, app_vmt + 0x0c, idle_proc);
write_far(0x5000, app_vmt + 0x24, main_filter);
write_far(0x5000, app_vmt + 0x20, run_proc);
write_far(0x5000, app_vmt + 0x40, error_proc);
write_far(0x5000, app_vmt + 0x28, filters[0]);
write_far(0x5000, app_vmt + 0x30, filters[1]);
write_far(0x5000, app_vmt + 0x2c, filters[2]);
g_client_getter = win16_make_far_pointer(0x6100, 0x6000);
Win16FarPtr can_close = win16_make_far_pointer(0x6100, 0x7000);
write_far(0x5000, window_vmt + 0x30, g_client_getter);
write_far(0x5000, window_vmt + 0x3c, can_close);
memset(g_messages, 0, sizeof(g_messages));
g_messages[0].message = 0x0100;
g_messages[1].message = 0x0012;
g_messages[1].wparam = 0x55aa;
g_message_count = 2;
g_message_index = 0;
g_empty_before_messages = 1;
g_wait_calls = 0;
g_translate_calls = 0;
g_dispatch_calls = 0;
g_filter_calls = 0;
g_idle_result = false;
g_main_filter_result = false;
g_true_filter = 0;
object_windows_application_message_loop(application);
assert(g_wait_calls == 1);
assert(g_translate_calls == 1 && g_dispatch_calls == 1);
assert(g_filter_calls == 1 && g_filter_order[0] == main_filter);
assert(win16_read_u16(win16_far_add_offset(application, 2)) == 0x55aa);
MSG16 message = {0};
g_filter_calls = 0;
g_true_filter = filters[1];
assert(object_windows_application_preprocess_message(
application, &message));
assert(g_filter_calls == 2);
assert(g_filter_order[0] == filters[0] &&
g_filter_order[1] == filters[1]);
g_filter_calls = 0;
g_true_filter = 0;
assert(!object_windows_application_preprocess_message(
application, &message));
assert(g_filter_calls == 3);
g_dialog_result = 1;
assert(object_windows_application_process_dialog_message(
application, &message) == 0xff01);
assert(g_dialog_window == 0x2222);
g_dialog_result = 0;
assert(object_windows_application_process_dialog_message(
application, &message) == 0);
win16_write_u16(application, 0x0c, 0x4444);
g_accelerator_result = 1;
assert(object_windows_application_process_accelerator(
application, &message));
assert(g_accelerator_window == 0x1111 && g_accelerator == 0x4444);
g_mdi_result = 1;
assert(object_windows_application_process_mdi_accelerator(
application, &message));
assert(g_mdi_window == 0x3333);
g_client_object = 0;
assert(!object_windows_application_process_mdi_accelerator(
application, &message));
assert(object_windows_window_get_mdi_client_default(main_window) == 0);
win16_write_u16(application, 2, 0);
g_void_method = 0;
object_windows_application_run(application);
assert(g_void_method == run_proc);
win16_write_u16(application, 2, 0xfffb);
g_error_method = 0;
object_windows_application_run(application);
assert(g_error_method == error_proc && g_error_argument == 0xfffb);
g_idle_result = true;
assert(object_windows_application_can_close(application));
assert(g_bool_procedure == can_close);
g_idle_result = false;
assert(!object_windows_application_can_close(application));
return 0;
}