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

188 lines
5.5 KiB
C

/* DOS/Win16 path and environment helpers used by CTL3D discovery. */
#include "tdkpin_multimedia.h"
#include "tdkpin_strings.h"
/*
* 1008:2608 -- copy at most 79 ANSI bytes to a stack ASCIIZ buffer, translate
* it in-place to OEM, then issue DOS AX=4300h. The helper's original register
* interface preserves CX for the returned attributes; the typed bridge makes
* carry and that CX value explicit.
*/
Win16DosFileAttributesResult borland_dos_get_file_attributes_ansi(
Win16FarPtr name)
{
uint8_t oem_name[80];
uint16_t copied = 0;
while (copied < 79) {
uint8_t byte = win16_read_u8(win16_far_add_offset(name, copied));
if (byte == 0) {
break;
}
oem_name[copied++] = byte;
}
oem_name[copied] = 0;
Win16FarPtr local = win16_stack_pointer(oem_name);
(void)AnsiToOem16(local, local);
return win16_dos_get_file_attributes(local);
}
static uint16_t append_c_string(
Win16FarPtr output,
uint16_t cursor,
uint16_t *remaining,
Win16FarPtr source)
{
uint16_t source_index = 0;
while (*remaining != 0) {
uint8_t byte = win16_read_u8(
win16_far_add_offset(source, source_index++));
if (byte == 0) {
break;
}
win16_write_u8(win16_far_add_offset(output, cursor++), byte);
(*remaining)--;
}
win16_write_u8(win16_far_add_offset(output, cursor), 0);
return cursor;
}
/*
* 1008:2643 -- search for file_name first as given, then under each semicolon-
* separated directory. Result capacity is exactly 79 characters plus NUL.
* DOS volume labels/directories (attribute bits 08/10) do not count as files.
*/
Win16FarPtr multimedia_search_file(
Win16FarPtr search_path,
Win16FarPtr file_name,
Win16FarPtr result)
{
uint16_t search_index = 0;
uint16_t remaining = 79;
uint16_t cursor = append_c_string(result, 0, &remaining, file_name);
for (;;) {
Win16DosFileAttributesResult attributes =
borland_dos_get_file_attributes_ansi(result);
if (!attributes.carry && (attributes.attributes & 0x18u) == 0) {
return result;
}
remaining = 79;
cursor = 0;
uint8_t character = win16_read_u8(
win16_far_add_offset(search_path, search_index));
uint8_t last_copied = 0;
if (character == 0) {
win16_write_u8(result, 0);
return result;
}
for (;;) {
search_index++;
if (character == ';') {
break;
}
if (remaining != 0) {
last_copied = character;
win16_write_u8(
win16_far_add_offset(result, cursor++), character);
remaining--;
}
character = win16_read_u8(
win16_far_add_offset(search_path, search_index));
if (character == 0) {
break;
}
}
if (remaining != 0 && last_copied != ':' && last_copied != '\\') {
win16_write_u8(win16_far_add_offset(result, cursor++), '\\');
remaining--;
}
cursor = append_c_string(
result, cursor, &remaining, file_name);
}
}
/*
* 1008:26b0 -- Borland-style path splitter. Optional outputs receive the
* directory/drive prefix (max 67), basename (max 8), and extension (max 4).
* Return bits are 8 wildcard, 4 prefix, 2 basename, and 1 extension.
*/
uint16_t multimedia_split_path(
Win16FarPtr extension,
Win16FarPtr file_name,
Win16FarPtr directory,
Win16FarPtr input)
{
Win16FarPtr base = borland_far_strrchr(input, '\\');
if (base == 0) {
base = borland_far_strrchr(input, ':');
}
if (base == 0) {
base = input;
} else {
base = win16_far_add_offset(base, 1);
}
Win16FarPtr dot = borland_far_strchr(base, '.');
if (dot == 0) {
dot = borland_far_strend(base);
}
uint16_t prefix_length = (uint16_t)(
win16_far_offset(base) - win16_far_offset(input));
if (prefix_length > 0x43) {
prefix_length = 0x43;
}
uint16_t name_length = (uint16_t)(
win16_far_offset(dot) - win16_far_offset(base));
if (name_length > 8) {
name_length = 8;
}
uint16_t flags = 0;
if (borland_far_strchr(base, '?') != 0 ||
borland_far_strchr(base, '*') != 0) {
flags |= 8;
}
if (prefix_length != 0) {
flags |= 4;
}
if (name_length != 0) {
flags |= 2;
}
if (win16_read_u8(dot) != 0) {
flags |= 1;
}
if (directory != 0) {
(void)borland_far_strncpy(directory, input, prefix_length);
}
if (file_name != 0) {
(void)borland_far_strncpy(file_name, base, name_length);
}
if (extension != 0) {
(void)borland_far_strncpy(extension, dot, 4);
}
return flags;
}
/* 1008:2819 -- case-insensitive NAME= lookup in the DOS environment block. */
Win16FarPtr multimedia_environment_value(Win16FarPtr name)
{
uint16_t name_length = borland_far_strlen(name);
Win16FarPtr variable = GetDOSEnvironment16();
while (win16_read_u8(variable) != 0) {
if (borland_far_strnicmp(name, variable, name_length) == 0 &&
win16_read_u8(win16_far_add_offset(variable, name_length)) == '=') {
return win16_far_add_offset(variable, (uint16_t)(name_length + 1));
}
variable = win16_far_add_offset(
variable, (uint16_t)(borland_far_strlen(variable) + 1));
}
return 0;
}