Files
tdkpin/original/reconstructed/tests/test_bound_thunks.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

98 lines
3.2 KiB
C

#include "../tdkpin_object_windows.h"
#include <assert.h>
#include <string.h>
uint16_t g_object_windows_thunk_code_selector;
Win16FarPtr g_object_windows_free_thunk;
Win16FarPtr g_object_windows_dispatch_proc;
static uint8_t g_pool[0x100];
static HGLOBAL16 g_allocation = 0x1234;
static unsigned g_allocations;
static unsigned g_alias_allocations;
static unsigned g_alias_frees;
static unsigned g_presto_calls;
HGLOBAL16 GlobalAlloc16(UINT16 flags, uint32_t bytes)
{
assert(flags == 0 && bytes == sizeof(g_pool));
g_allocations++;
return g_allocation;
}
Win16FarPtr GlobalLock16(HGLOBAL16 allocation)
{
assert(allocation == g_allocation);
return win16_make_far_pointer(0x8000, 0);
}
uint16_t AllocCStoDSAlias16(uint16_t code_selector)
{
assert(code_selector == 0x8000);
g_alias_allocations++;
return 0x8100;
}
uint16_t FreeSelector16(uint16_t selector)
{
assert(selector == 0x8100);
g_alias_frees++;
return 0;
}
uint16_t PrestoChangoSelector16(
uint16_t source_selector, uint16_t destination_selector)
{
assert(source_selector == 0x8000 && destination_selector == 0x8000);
g_presto_calls++;
return 0x8000;
}
int main(void)
{
static uint8_t dgroup[0x1000];
win16_reset_segment_bindings();
win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true);
win16_set_dgroup_selector(0x5000);
win16_bind_segment(0x8000, g_pool, sizeof(g_pool), true);
win16_bind_segment(0x8100, g_pool, sizeof(g_pool), true);
const uint8_t template_bytes[5] = {0x5b, 0x2e, 0xc4, 0x1f, 0xea};
memcpy(&dgroup[0x0686], template_bytes, sizeof(template_bytes));
g_object_windows_dispatch_proc =
win16_make_far_pointer(0x6000, 0x1234);
Win16FarPtr first_object = win16_make_far_pointer(0x7000, 0x0020);
Win16FarPtr first = object_windows_allocate_bound_thunk(first_object);
assert(first == win16_make_far_pointer(0x8000, 0x00f9));
assert(g_allocations == 1 && g_presto_calls == 1);
assert(win16_read_u16(win16_make_far_pointer(0x8000, 0)) == 0);
for (uint16_t index = 0; index < sizeof(template_bytes); index++) {
assert(win16_read_u8(
win16_make_far_pointer(0x8000, (uint16_t)(2 + index))) ==
template_bytes[index]);
}
assert(win16_read_far_pointer(
win16_make_far_pointer(0x8000, 7), 0) ==
g_object_windows_dispatch_proc);
assert(win16_read_u8(first) == 0xe8);
assert(win16_read_u16(win16_far_add_offset(first, 1)) == 0xff06);
assert(win16_read_far_pointer(first, 3) == first_object);
assert(g_object_windows_free_thunk ==
win16_make_far_pointer(0x8000, 0x00f2));
Win16FarPtr second_object = win16_make_far_pointer(0x7000, 0x0040);
Win16FarPtr second = object_windows_allocate_bound_thunk(second_object);
assert(second == win16_make_far_pointer(0x8000, 0x00f2));
assert(win16_read_far_pointer(second, 3) == second_object);
assert(g_allocations == 1);
object_windows_release_bound_thunk(first);
assert(g_object_windows_free_thunk == first);
assert(win16_read_far_pointer(first, 3) ==
win16_make_far_pointer(0x8000, 0x00eb));
assert(object_windows_allocate_bound_thunk(first_object) == first);
assert(g_alias_allocations == 4 && g_alias_frees == 4);
return 0;
}