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
216 lines
6.4 KiB
C
216 lines
6.4 KiB
C
#include "../tdkpin_application.h"
|
|
|
|
#include <assert.h>
|
|
#include <setjmp.h>
|
|
#include <stdio.h>
|
|
#include <string.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;
|
|
Win16FarPtr g_object_windows_message_hook;
|
|
Win16FarPtr g_win16_message_box;
|
|
|
|
static bool g_reserve_unallocated;
|
|
static unsigned g_ensure_calls;
|
|
static Win16FarPtr g_disposed;
|
|
static uint16_t g_error;
|
|
static Win16FarPtr g_validator_result;
|
|
static bool g_create_result;
|
|
static int16_t g_execute_result;
|
|
static Win16FarPtr g_validate_proc;
|
|
static Win16FarPtr g_error_proc;
|
|
static Win16FarPtr g_create_proc;
|
|
static Win16FarPtr g_execute_proc;
|
|
static INT16 g_message_box_response;
|
|
static char g_message_text[32];
|
|
static uint16_t g_exit_status;
|
|
static jmp_buf g_exit_jump;
|
|
|
|
bool borland_heap_reserve_is_unallocated(void)
|
|
{
|
|
return g_reserve_unallocated;
|
|
}
|
|
|
|
void borland_ensure_heap_reserve(void)
|
|
{
|
|
g_ensure_calls++;
|
|
}
|
|
|
|
void borland_dispose_object(Win16FarPtr object)
|
|
{
|
|
g_disposed = object;
|
|
}
|
|
|
|
void win16_call_object_u16_method(
|
|
Win16FarPtr procedure, Win16FarPtr object, uint16_t argument)
|
|
{
|
|
(void)object;
|
|
assert(procedure == g_error_proc);
|
|
g_error = argument;
|
|
}
|
|
|
|
Win16FarPtr win16_call_application_window_method(
|
|
Win16FarPtr procedure, Win16FarPtr application, Win16FarPtr window)
|
|
{
|
|
(void)application;
|
|
(void)window;
|
|
assert(procedure == g_validate_proc);
|
|
return g_validator_result;
|
|
}
|
|
|
|
bool win16_call_object_bool_method(
|
|
Win16FarPtr procedure, Win16FarPtr object)
|
|
{
|
|
(void)object;
|
|
assert(procedure == g_create_proc);
|
|
return g_create_result;
|
|
}
|
|
|
|
int16_t win16_call_object_int_method(
|
|
Win16FarPtr procedure, Win16FarPtr object)
|
|
{
|
|
(void)object;
|
|
assert(procedure == g_execute_proc);
|
|
return g_execute_result;
|
|
}
|
|
|
|
INT16 wvsprintf16(
|
|
char *output, const char *format, const uint16_t *arguments)
|
|
{
|
|
assert(strcmp(format, "Error code = %d. Continue?") == 0);
|
|
return (INT16)snprintf(
|
|
output, 32, format, (int16_t)arguments[0]);
|
|
}
|
|
|
|
INT16 win16_call_message_box(
|
|
Win16FarPtr procedure,
|
|
HWND16 owner,
|
|
const char *text,
|
|
const char *caption,
|
|
UINT16 type)
|
|
{
|
|
assert(procedure == g_win16_message_box);
|
|
assert(owner == 0 && type == 0x14);
|
|
assert(strcmp(caption, "Application Error") == 0);
|
|
strcpy(g_message_text, text);
|
|
return g_message_box_response;
|
|
}
|
|
|
|
_Noreturn void borland_runtime_exit(uint16_t status)
|
|
{
|
|
g_exit_status = status;
|
|
longjmp(g_exit_jump, 1);
|
|
}
|
|
|
|
static void write_far(uint16_t offset, Win16FarPtr pointer)
|
|
{
|
|
win16_write_u16(
|
|
win16_dgroup_pointer(offset), 0, win16_far_offset(pointer));
|
|
win16_write_u16(
|
|
win16_dgroup_pointer((uint16_t)(offset + 2)),
|
|
0,
|
|
win16_far_selector(pointer));
|
|
}
|
|
|
|
static void reset_state(void)
|
|
{
|
|
g_reserve_unallocated = false;
|
|
g_ensure_calls = 0;
|
|
g_disposed = 0;
|
|
g_error = 0;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
static uint8_t dgroup[0x1000];
|
|
static uint8_t application_bytes[64];
|
|
static uint8_t window_bytes[64];
|
|
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);
|
|
|
|
Win16FarPtr application = win16_make_far_pointer(0x7000, 2);
|
|
Win16FarPtr window = win16_make_far_pointer(0x7100, 2);
|
|
uint16_t app_vmt = 0x0100;
|
|
uint16_t window_vmt = 0x0200;
|
|
win16_write_u16(application, 0, app_vmt);
|
|
win16_write_u16(window, 0, window_vmt);
|
|
g_validate_proc = win16_make_far_pointer(0x6000, 0x1000);
|
|
g_error_proc = win16_make_far_pointer(0x6000, 0x2000);
|
|
g_create_proc = win16_make_far_pointer(0x6100, 0x3000);
|
|
g_execute_proc = win16_make_far_pointer(0x6100, 0x4000);
|
|
g_win16_message_box = win16_make_far_pointer(0x6200, 0x5000);
|
|
write_far(app_vmt + 0x3c, g_validate_proc);
|
|
write_far(app_vmt + 0x40, g_error_proc);
|
|
write_far(window_vmt + 0x20, g_create_proc);
|
|
write_far(window_vmt + 0x4c, g_execute_proc);
|
|
|
|
reset_state();
|
|
assert(object_windows_application_validate_window(application, 0) == 0);
|
|
win16_write_u16(window, 2, 0);
|
|
assert(object_windows_application_validate_window(application, window) ==
|
|
window);
|
|
|
|
reset_state();
|
|
win16_write_u16(window, 2, 5);
|
|
assert(object_windows_application_validate_window(application, window) == 0);
|
|
assert(g_error == 5 && g_disposed == window && g_ensure_calls == 0);
|
|
|
|
reset_state();
|
|
g_reserve_unallocated = true;
|
|
win16_write_u16(window, 2, 0);
|
|
assert(object_windows_application_validate_window(application, window) == 0);
|
|
assert(g_error == 0xfffe && g_disposed == window && g_ensure_calls == 1);
|
|
|
|
reset_state();
|
|
g_validator_result = window;
|
|
g_create_result = true;
|
|
assert(object_windows_application_make_window(application, window) == window);
|
|
assert(g_disposed == 0);
|
|
reset_state();
|
|
g_validator_result = window;
|
|
g_create_result = false;
|
|
win16_write_u16(window, 2, 7);
|
|
assert(object_windows_application_make_window(application, window) == 0);
|
|
assert(g_error == 7 && g_disposed == window);
|
|
reset_state();
|
|
g_validator_result = 0;
|
|
assert(object_windows_application_make_window(application, window) == 0);
|
|
assert(g_disposed == 0);
|
|
|
|
reset_state();
|
|
g_validator_result = window;
|
|
g_execute_result = 4;
|
|
assert(object_windows_application_exec_dialog(application, window) == 4);
|
|
assert(g_disposed == window && g_error == 0);
|
|
reset_state();
|
|
g_validator_result = window;
|
|
g_execute_result = -1;
|
|
assert(object_windows_application_exec_dialog(application, window) == 2);
|
|
assert(g_error == 0xffff && g_disposed == window);
|
|
reset_state();
|
|
g_validator_result = 0;
|
|
assert(object_windows_application_exec_dialog(application, window) == 2);
|
|
assert(g_disposed == 0);
|
|
|
|
g_message_box_response = 6;
|
|
object_windows_application_error(application, 123);
|
|
assert(strcmp(g_message_text, "Error code = 123. Continue?") == 0);
|
|
g_message_box_response = 7;
|
|
if (setjmp(g_exit_jump) == 0) {
|
|
object_windows_application_error(application, 0x8123);
|
|
assert(false);
|
|
}
|
|
assert(g_exit_status == 0x8123);
|
|
assert(strcmp(g_message_text, "Error code = -32477. Continue?") == 0);
|
|
return 0;
|
|
}
|