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
183 lines
6.0 KiB
C
183 lines
6.0 KiB
C
#include "../tdkpin_object_list.h"
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
static Win16FarPtr g_false_child;
|
|
static HWND16 g_iconic_window;
|
|
static unsigned g_get_text_calls;
|
|
static unsigned g_set_text_calls;
|
|
static Win16FarPtr g_prepare_proc;
|
|
static uint16_t g_prepare_argument;
|
|
static Win16FarPtr g_transfer_children[4];
|
|
static Win16FarPtr g_transfer_cursors[4];
|
|
static unsigned g_transfer_calls;
|
|
|
|
bool win16_call_object_bool_method(
|
|
Win16FarPtr procedure, Win16FarPtr object)
|
|
{
|
|
assert(procedure == win16_make_far_pointer(0x6100, 0x0200));
|
|
return object != g_false_child;
|
|
}
|
|
|
|
BOOL16 IsIconic16(HWND16 window)
|
|
{
|
|
return window == g_iconic_window;
|
|
}
|
|
|
|
INT16 GetWindowText16(HWND16 window, char *text, INT16 maximum)
|
|
{
|
|
assert(window == g_iconic_window && maximum == 81);
|
|
strcpy(text, "title");
|
|
g_get_text_calls++;
|
|
return 5;
|
|
}
|
|
|
|
BOOL16 SetWindowText16(HWND16 window, const char *text)
|
|
{
|
|
assert(window == g_iconic_window && strcmp(text, "title") == 0);
|
|
g_set_text_calls++;
|
|
return 1;
|
|
}
|
|
|
|
void borland_dispose_object(Win16FarPtr object)
|
|
{
|
|
(void)object;
|
|
}
|
|
|
|
bool win16_call_object_predicate(
|
|
Win16FarPtr procedure, Win16FarPtr child)
|
|
{
|
|
(void)procedure;
|
|
(void)child;
|
|
return false;
|
|
}
|
|
|
|
void win16_call_object_action(
|
|
Win16FarPtr procedure, Win16FarPtr child)
|
|
{
|
|
(void)procedure;
|
|
(void)child;
|
|
}
|
|
|
|
void win16_call_object_u16_method(
|
|
Win16FarPtr procedure, Win16FarPtr object, uint16_t argument)
|
|
{
|
|
(void)object;
|
|
g_prepare_proc = procedure;
|
|
g_prepare_argument = argument;
|
|
}
|
|
|
|
uint16_t win16_call_object_transfer_method(
|
|
Win16FarPtr procedure,
|
|
Win16FarPtr object,
|
|
uint16_t direction,
|
|
Win16FarPtr cursor)
|
|
{
|
|
assert(procedure == win16_make_far_pointer(0x6100, 0x0400));
|
|
assert(direction == 2);
|
|
g_transfer_children[g_transfer_calls] = object;
|
|
g_transfer_cursors[g_transfer_calls] = cursor;
|
|
return g_transfer_calls++ == 0 ? 3 : 5;
|
|
}
|
|
|
|
static void configure_child(
|
|
Win16FarPtr child, uint16_t group, uint8_t flags, HWND16 window)
|
|
{
|
|
win16_write_u16(child, 0, 0x0100);
|
|
win16_write_u16(child, 4, window);
|
|
win16_write_u8(win16_far_add_offset(child, 0x16), flags);
|
|
win16_write_u16(child, 0x17, group);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
static uint8_t dgroup[0x1000];
|
|
static uint8_t container_bytes[64];
|
|
static uint8_t a_bytes[64];
|
|
static uint8_t b_bytes[64];
|
|
static uint8_t c_bytes[64];
|
|
win16_reset_segment_bindings();
|
|
win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true);
|
|
win16_set_dgroup_selector(0x5000);
|
|
win16_bind_segment(0x7000, container_bytes, sizeof(container_bytes), true);
|
|
win16_bind_segment(0x7100, a_bytes, sizeof(a_bytes), true);
|
|
win16_bind_segment(0x7200, b_bytes, sizeof(b_bytes), true);
|
|
win16_bind_segment(0x7300, c_bytes, sizeof(c_bytes), true);
|
|
win16_write_u16(win16_dgroup_pointer(0x0120), 0, 0x0200);
|
|
win16_write_u16(win16_dgroup_pointer(0x0122), 0, 0x6100);
|
|
Win16FarPtr prepare_proc = win16_make_far_pointer(0x6100, 0x0300);
|
|
win16_write_u16(win16_dgroup_pointer(0x0144), 0,
|
|
win16_far_offset(prepare_proc));
|
|
win16_write_u16(win16_dgroup_pointer(0x0146), 0,
|
|
win16_far_selector(prepare_proc));
|
|
win16_write_u16(win16_dgroup_pointer(0x0140), 0, 0x0400);
|
|
win16_write_u16(win16_dgroup_pointer(0x0142), 0, 0x6100);
|
|
|
|
Win16FarPtr container = win16_make_far_pointer(0x7000, 2);
|
|
Win16FarPtr a = win16_make_far_pointer(0x7100, 2);
|
|
Win16FarPtr b = win16_make_far_pointer(0x7200, 2);
|
|
Win16FarPtr c = win16_make_far_pointer(0x7300, 2);
|
|
configure_child(a, 1, 4, 0x11);
|
|
configure_child(b, 2, 4, 0x22);
|
|
configure_child(c, 0, 4, 0x33);
|
|
object_windows_append_child(container, a);
|
|
object_windows_append_child(container, b);
|
|
object_windows_append_child(container, c);
|
|
|
|
assert(object_windows_child_group_matches(1, a));
|
|
assert(!object_windows_child_group_matches(-1, a));
|
|
assert(!object_windows_child_group_matches(2, a));
|
|
|
|
g_false_child = a;
|
|
assert(object_windows_try_child_activation(0, a));
|
|
g_false_child = 0;
|
|
g_iconic_window = 0x22;
|
|
g_get_text_calls = 0;
|
|
g_set_text_calls = 0;
|
|
assert(!object_windows_try_child_activation(0, b));
|
|
assert(g_get_text_calls == 1 && g_set_text_calls == 1);
|
|
assert(!object_windows_unindexed_child_matches(0, b));
|
|
|
|
g_false_child = a;
|
|
assert(object_windows_validate_child_groups(container));
|
|
g_false_child = c;
|
|
assert(!object_windows_validate_child_groups(container));
|
|
g_false_child = 0;
|
|
assert(object_windows_validate_child_groups(container));
|
|
|
|
static uint8_t empty_bytes[64];
|
|
win16_bind_segment(0x7400, empty_bytes, sizeof(empty_bytes), true);
|
|
assert(object_windows_validate_child_groups(
|
|
win16_make_far_pointer(0x7400, 2)));
|
|
Win16FarPtr empty = win16_make_far_pointer(0x7400, 2);
|
|
win16_write_u16(empty, 0, 0x0100);
|
|
g_prepare_proc = 0;
|
|
object_windows_prepare_window(empty);
|
|
assert(g_prepare_proc == prepare_proc && g_prepare_argument == 2);
|
|
g_false_child = c;
|
|
win16_write_u16(container, 2, 0);
|
|
g_prepare_proc = 0;
|
|
object_windows_prepare_window(container);
|
|
assert(win16_read_u16(win16_far_add_offset(container, 2)) == 0xfffc);
|
|
assert(g_prepare_proc == 0);
|
|
|
|
win16_write_u8(win16_far_add_offset(a, 0x16), 0x10);
|
|
win16_write_u8(win16_far_add_offset(b, 0x16), 0);
|
|
win16_write_u8(win16_far_add_offset(c, 0x16), 0x10);
|
|
win16_write_u16(container, 0x0e, 0x0100);
|
|
win16_write_u16(container, 0x10, 0x8000);
|
|
g_transfer_calls = 0;
|
|
object_windows_transfer_child_data(container, 2);
|
|
assert(g_transfer_calls == 2);
|
|
assert(g_transfer_children[0] == a && g_transfer_children[1] == c);
|
|
assert(g_transfer_cursors[0] == win16_make_far_pointer(0x8000, 0x0100));
|
|
assert(g_transfer_cursors[1] == win16_make_far_pointer(0x8000, 0x0103));
|
|
ObjectWindowsTransferContext context = {
|
|
win16_make_far_pointer(0x8000, 0xfffe), 2};
|
|
g_transfer_calls = 0;
|
|
object_windows_transfer_child_callback(&context, a);
|
|
assert(context.cursor == win16_make_far_pointer(0x8000, 1));
|
|
return 0;
|
|
}
|