Files
tdkpin/original/reconstructed/tests/test_message_dispatch.c
T
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

170 lines
6.1 KiB
C

#include "../tdkpin_object_windows.h"
#include <assert.h>
Win16FarPtr g_object_windows_creating_object;
uint16_t g_object_windows_thunk_code_selector;
Win16FarPtr g_object_windows_free_thunk;
Win16FarPtr g_object_windows_dispatch_proc;
Win16FarPtr g_object_windows_message_hook;
static Win16FarPtr g_expected_handler;
static Win16FarPtr g_expected_object;
static unsigned g_handler_calls;
static unsigned g_hook_calls;
static ObjectWindowsMessage g_hook_message;
static Win16FarPtr g_event_pointer;
void win16_call_object_message_handler(
Win16FarPtr procedure,
Win16FarPtr object,
ObjectWindowsMessage *message)
{
assert(procedure == g_expected_handler);
assert(object == g_expected_object);
assert(message->window == 0x77);
assert(message->wparam == 0x3344);
assert(message->lparam == (LPARAM16)0x89abcdefu);
message->result = (LRESULT16)0x12345678u;
g_handler_calls++;
}
void win16_call_object_message_hook(
Win16FarPtr procedure,
Win16FarPtr object,
Win16FarPtr handler,
HWND16 window,
UINT16 message,
WPARAM16 wparam,
LPARAM16 lparam)
{
assert(procedure == g_object_windows_message_hook);
assert(object == g_expected_object && handler == g_expected_handler);
g_hook_message = (ObjectWindowsMessage){
window, message, wparam, lparam, 0};
g_hook_calls++;
}
void win16_call_object_event_handler(
Win16FarPtr procedure, Win16FarPtr object, Win16FarPtr event)
{
assert(procedure == g_expected_handler);
assert(object == g_expected_object);
g_event_pointer = event;
}
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));
}
int main(void)
{
static uint8_t dgroup[0x1000];
static uint8_t object_bytes[64];
static uint8_t event_bytes[32];
win16_reset_segment_bindings();
win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true);
win16_set_dgroup_selector(0x5000);
win16_bind_segment(
0x7000, object_bytes, sizeof(object_bytes), true);
win16_bind_segment(
0x7100, event_bytes, sizeof(event_bytes), true);
const uint16_t vmt = 0x0100;
const uint16_t derived_table = 0x0200;
const uint16_t parent_table = 0x0300;
Win16FarPtr fallback = win16_make_far_pointer(0x6100, 0x1111);
Win16FarPtr derived = win16_make_far_pointer(0x6200, 0x2222);
Win16FarPtr parent = win16_make_far_pointer(0x6300, 0x3333);
write_far((uint16_t)(vmt + 0x0c), fallback);
win16_write_u16(
win16_dgroup_pointer((uint16_t)(vmt + 4)), 0, derived_table);
win16_write_u16(win16_dgroup_pointer(derived_table), 0, parent_table);
win16_write_u16(win16_dgroup_pointer(derived_table + 2), 0, 0xffff);
win16_write_u16(win16_dgroup_pointer(derived_table + 4), 0, 0xffff);
win16_write_u16(win16_dgroup_pointer(derived_table + 6), 0, 1);
win16_write_u16(win16_dgroup_pointer(derived_table + 8), 0, 0x0100);
write_far((uint16_t)(derived_table + 10), derived);
win16_write_u16(win16_dgroup_pointer(parent_table), 0, 0);
win16_write_u16(win16_dgroup_pointer(parent_table + 2), 0, 0xffff);
win16_write_u16(win16_dgroup_pointer(parent_table + 4), 0, 0xffff);
win16_write_u16(win16_dgroup_pointer(parent_table + 6), 0, 1);
win16_write_u16(win16_dgroup_pointer(parent_table + 8), 0, 0x0200);
write_far((uint16_t)(parent_table + 10), parent);
assert(object_windows_resolve_message_handler(vmt, 0x0100, 0x0c) ==
win16_dgroup_pointer(derived_table + 10));
assert(object_windows_resolve_message_handler(vmt, 0x0200, 0x0c) ==
win16_dgroup_pointer(parent_table + 10));
assert(win16_read_u16(win16_dgroup_pointer(derived_table + 2)) ==
0x0200);
assert(win16_read_u16(win16_dgroup_pointer(derived_table + 4)) ==
parent_table + 10);
/* Cache lookup still works after the table contents become unusable. */
win16_write_u16(win16_dgroup_pointer(derived_table + 6), 0, 0xffff);
assert(object_windows_resolve_message_handler(vmt, 0x0200, 0x0c) ==
win16_dgroup_pointer(parent_table + 10));
win16_write_u16(win16_dgroup_pointer(derived_table + 6), 0, 1);
assert(object_windows_resolve_message_handler(vmt, 0x0999, 0x0c) ==
win16_dgroup_pointer(vmt + 0x0c));
Win16FarPtr object = win16_make_far_pointer(0x7000, 4);
win16_write_u16(object, 0, vmt);
g_expected_object = object;
g_object_windows_message_hook =
win16_make_far_pointer(0x6400, 0x4444);
g_expected_handler = parent;
g_handler_calls = 0;
g_hook_calls = 0;
LRESULT16 result = object_dispatch_window_or_dialog_proc(
object,
0x77,
0x0200,
0x3344,
(LPARAM16)0x89abcdefu);
assert(result == (LRESULT16)0x12345678u);
assert(win16_read_u16(win16_far_add_offset(object, 4)) == 0x77);
assert(g_handler_calls == 1 && g_hook_calls == 1);
assert(g_hook_message.message == 0x0200);
assert(g_hook_message.lparam == (LPARAM16)0x89abcdefu);
g_object_windows_message_hook = win16_make_far_pointer(0, 0x9999);
g_expected_handler = fallback;
g_hook_calls = 0;
(void)object_dispatch_window_or_dialog_proc(
object,
0x77,
0xffff,
0x3344,
(LPARAM16)0x89abcdefu);
assert(g_hook_calls == 0);
Win16FarPtr event = win16_make_far_pointer(0x7100, 2);
win16_write_u16(event, 0, 0x77);
win16_write_u16(event, 2, 0x0100);
win16_write_u16(event, 4, 0x3344);
win16_write_u16(event, 6, 0xcdef);
win16_write_u16(event, 8, 0x89ab);
g_object_windows_message_hook =
win16_make_far_pointer(0x6400, 0x4444);
g_expected_handler = derived;
g_hook_calls = 0;
g_event_pointer = 0;
object_windows_dispatch_event(0x0c, 0x0100, event, object);
assert(g_event_pointer == event);
assert(g_hook_calls == 1);
assert(g_hook_message.window == 0x77);
assert(g_hook_message.message == 0x0100);
assert(g_hook_message.wparam == 0x3344);
assert(g_hook_message.lparam == (LPARAM16)0x89abcdefu);
return 0;
}