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

218 lines
5.5 KiB
C

#include "../tdkpin_program_entry.h"
#include "../tdkpin_application.h"
#include <assert.h>
#include <setjmp.h>
uint32_t g_tdkpin_windows_version;
Win16FarPtr g_win16_message_box;
static jmp_buf g_exit_jump;
static uint16_t g_exit_status;
static uint32_t g_version_result;
static unsigned g_order[16];
static unsigned g_order_count;
static unsigned g_message_calls;
static unsigned g_construct_calls;
static unsigned g_run_calls;
static unsigned g_destruct_calls;
enum CallOrder {
CALL_INIT_TASK = 1,
CALL_BORLAND_STARTUP,
CALL_STACK,
CALL_TPWINCRT,
CALL_MULTIMEDIA,
CALL_UNIT_91,
CALL_UNIT_86,
CALL_UNIT_72,
CALL_GET_VERSION,
CALL_MESSAGE_BOX,
CALL_CONSTRUCT,
CALL_RUN,
CALL_DESTRUCT,
CALL_EXIT,
};
static void record_call(unsigned call)
{
assert(g_order_count < sizeof(g_order) / sizeof(*g_order));
g_order[g_order_count++] = call;
}
BorlandWin16StartupRegisters InitTask16(void)
{
record_call(CALL_INIT_TASK);
return (BorlandWin16StartupRegisters){
.loader_ax = 1,
.command_line = win16_make_far_pointer(0x4444, 0x0100),
.show_command = 7,
.previous_instance = 0,
.instance = 0x2222,
};
}
void borland_initialize_win16_runtime(
const BorlandWin16StartupRegisters *registers)
{
assert(registers->loader_ax == 1 && registers->instance == 0x2222);
assert(registers->command_line ==
win16_make_far_pointer(0x4444, 0x0100));
record_call(CALL_BORLAND_STARTUP);
}
void tdkpin_initialize_stack_guard(void)
{
record_call(CALL_STACK);
}
void tpwincrt_initialize_runtime_unit(void)
{
record_call(CALL_TPWINCRT);
}
void multimedia_initialize_runtime_unit(void)
{
record_call(CALL_MULTIMEDIA);
}
void tdkpin_initialize_unit_ordinal_91(void)
{
record_call(CALL_UNIT_91);
}
void tdkpin_initialize_unit_ordinal_86(void)
{
record_call(CALL_UNIT_86);
}
void tdkpin_initialize_unit_ordinal_72(void)
{
record_call(CALL_UNIT_72);
}
uint32_t GetVersion16(void)
{
record_call(CALL_GET_VERSION);
return g_version_result;
}
INT16 win16_call_message_box_far(
Win16FarPtr procedure,
HWND16 owner,
Win16FarPtr text,
Win16FarPtr caption,
UINT16 type)
{
assert(procedure == g_win16_message_box);
assert(owner == 0);
assert(text == win16_dgroup_pointer(0x0396));
assert(caption == win16_dgroup_pointer(0x03c8));
assert(type == 0x10);
g_message_calls++;
record_call(CALL_MESSAGE_BOX);
return 1;
}
Win16FarPtr object_windows_application_construct(
Win16FarPtr object, uint16_t vmt, Win16FarPtr name)
{
assert(object == win16_dgroup_pointer(0x0748));
assert(vmt == 0x0024);
assert(name == win16_dgroup_pointer(0x03e1));
win16_write_u16(object, 0, vmt);
g_construct_calls++;
record_call(CALL_CONSTRUCT);
return object;
}
void win16_call_object_method(
Win16FarPtr procedure, Win16FarPtr object)
{
assert(procedure == win16_make_far_pointer(0x6000, 0x1111));
assert(object == win16_dgroup_pointer(0x0748));
g_run_calls++;
record_call(CALL_RUN);
}
void win16_call_object_destructor(
Win16FarPtr procedure, Win16FarPtr object, uint16_t dispose_mode)
{
assert(procedure == win16_make_far_pointer(0x6000, 0x2222));
assert(object == win16_dgroup_pointer(0x0748));
assert(dispose_mode == 0);
g_destruct_calls++;
record_call(CALL_DESTRUCT);
}
_Noreturn void borland_runtime_exit(uint16_t status)
{
g_exit_status = status;
record_call(CALL_EXIT);
longjmp(g_exit_jump, 1);
}
static void write_far(
Win16FarPtr base, uint16_t offset, Win16FarPtr value)
{
win16_write_u16(base, offset, win16_far_offset(value));
win16_write_u16(
base, (uint16_t)(offset + 2), win16_far_selector(value));
}
static void run_case(uint32_t version, bool supported)
{
g_version_result = version;
g_order_count = 0;
g_message_calls = 0;
g_construct_calls = 0;
g_run_calls = 0;
g_destruct_calls = 0;
if (setjmp(g_exit_jump) == 0) {
tdkpin_ne_program_entry();
assert(false);
}
assert(g_exit_status == 0);
assert(g_tdkpin_windows_version == version);
for (unsigned index = 0; index < 9; index++) {
assert(g_order[index] == index + 1);
}
if (supported) {
assert(g_message_calls == 0);
assert(g_construct_calls == 1 && g_run_calls == 1 &&
g_destruct_calls == 1);
assert(g_order_count == 13);
assert(g_order[9] == CALL_CONSTRUCT);
assert(g_order[10] == CALL_RUN);
assert(g_order[11] == CALL_DESTRUCT);
assert(g_order[12] == CALL_EXIT);
} else {
assert(g_message_calls == 1);
assert(g_construct_calls == 0 && g_run_calls == 0 &&
g_destruct_calls == 0);
assert(g_order_count == 11);
assert(g_order[9] == CALL_MESSAGE_BOX);
assert(g_order[10] == CALL_EXIT);
}
}
int main(void)
{
static uint8_t dgroup[0x800];
win16_reset_segment_bindings();
win16_bind_segment(0x7000, dgroup, sizeof(dgroup), true);
win16_set_dgroup_selector(0x7000);
g_win16_message_box = win16_make_far_pointer(0x5000, 0x0100);
Win16FarPtr vmt = win16_dgroup_pointer(0x0024);
write_far(vmt, 0x1c, win16_make_far_pointer(0x6000, 0x1111));
write_far(vmt, 0x08, win16_make_far_pointer(0x6000, 0x2222));
run_case(0xabcd6302u, false); /* major 2 */
run_case(0xabcd0903u, false); /* Windows 3.9 */
run_case(0xabcd0a03u, true); /* Windows 3.10 */
run_case(0xabcd0004u, true); /* Windows 4.x */
return 0;
}