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

219 lines
7.0 KiB
C

/* Borland 32-bit shift and Turbo Pascal ShortString helpers from Code5. */
#include "tdkpin_shortstrings.h"
uint32_t borland_shift_right_u32(uint32_t value, uint16_t count)
{
return value >> (count & 0x1f);
}
uint32_t borland_shift_left_u32(uint32_t value, uint16_t count)
{
return value << (count & 0x1f);
}
void borland_short_assign(Win16FarPtr destination, Win16FarPtr source)
{
uint8_t length = win16_read_u8(source);
win16_write_u8(destination, length);
for (uint16_t index = 1; index <= length; index++) {
win16_write_u8(
win16_far_add_offset(destination, index),
win16_read_u8(win16_far_add_offset(source, index)));
}
}
void borland_short_assign_truncated(
Win16FarPtr destination, Win16FarPtr source, uint8_t maximum_length)
{
uint8_t length = win16_read_u8(source);
if (length > maximum_length) {
length = maximum_length;
}
win16_write_u8(destination, length);
for (uint16_t index = 1; index <= length; index++) {
win16_write_u8(
win16_far_add_offset(destination, index),
win16_read_u8(win16_far_add_offset(source, index)));
}
}
void borland_short_substring(
Win16FarPtr destination,
Win16FarPtr source,
int16_t index,
int16_t count)
{
if (index < 1) {
index = 1;
}
uint16_t source_length = win16_read_u8(source);
uint16_t available = 0;
if ((uint16_t)index <= source_length) {
available = (uint16_t)(source_length - (uint16_t)index + 1);
}
uint16_t requested = count < 0 ? 0 : (uint16_t)count;
uint8_t copied = (uint8_t)(available < requested ? available : requested);
win16_write_u8(destination, copied);
for (uint16_t offset = 0; offset < copied; offset++) {
win16_write_u8(
win16_far_add_offset(destination, (uint16_t)(offset + 1)),
win16_read_u8(win16_far_add_offset(
source, (uint16_t)((uint16_t)index + offset))));
}
}
void borland_short_concat(Win16FarPtr destination, Win16FarPtr source)
{
uint8_t destination_length = win16_read_u8(destination);
uint8_t source_length = win16_read_u8(source);
uint16_t sum = (uint16_t)destination_length + source_length;
uint8_t copied = source_length;
if (sum > 0xff) {
copied = (uint8_t)~destination_length;
win16_write_u8(destination, 0xff);
} else {
win16_write_u8(destination, (uint8_t)sum);
}
for (uint16_t index = 1; index <= copied; index++) {
win16_write_u8(
win16_far_add_offset(
destination, (uint16_t)(destination_length + index)),
win16_read_u8(win16_far_add_offset(source, index)));
}
}
uint16_t borland_short_position(Win16FarPtr pattern, Win16FarPtr text)
{
uint8_t pattern_length = win16_read_u8(pattern);
uint8_t text_length = win16_read_u8(text);
if (pattern_length == 0 || pattern_length > text_length) {
return 0;
}
uint16_t last = (uint16_t)(text_length - pattern_length + 1);
for (uint16_t position = 1; position <= last; position++) {
bool equal = true;
for (uint16_t index = 1; index <= pattern_length; index++) {
if (win16_read_u8(win16_far_add_offset(pattern, index)) !=
win16_read_u8(win16_far_add_offset(
text, (uint16_t)(position + index - 1)))) {
equal = false;
break;
}
}
if (equal) {
return position;
}
}
return 0;
}
/* Materialize the original FLAGS-only comparison as a signed C result. */
int16_t borland_short_compare(Win16FarPtr left, Win16FarPtr right)
{
uint8_t left_length = win16_read_u8(left);
uint8_t right_length = win16_read_u8(right);
uint8_t common = left_length < right_length ? left_length : right_length;
for (uint16_t index = 1; index <= common; index++) {
uint8_t left_byte = win16_read_u8(win16_far_add_offset(left, index));
uint8_t right_byte = win16_read_u8(win16_far_add_offset(right, index));
if (left_byte != right_byte) {
return (int16_t)left_byte - right_byte;
}
}
return (int16_t)left_length - right_length;
}
void borland_character_to_short(Win16FarPtr destination, uint8_t character)
{
win16_write_u8(destination, 1);
win16_write_u8(win16_far_add_offset(destination, 1), character);
}
void borland_bytes_to_short(
Win16FarPtr destination, Win16FarPtr source, uint16_t count)
{
win16_write_u8(destination, (uint8_t)count);
for (uint16_t index = 0; index < count; index++) {
win16_write_u8(
win16_far_add_offset(destination, (uint16_t)(index + 1)),
win16_read_u8(win16_far_add_offset(source, index)));
}
}
static uint8_t copy_short_slice(
uint8_t *output,
uint8_t output_length,
Win16FarPtr source,
uint16_t first,
uint16_t count,
uint8_t maximum)
{
uint8_t source_length = win16_read_u8(source);
if (first < 1) {
first = 1;
}
uint16_t available = first <= source_length
? (uint16_t)(source_length - first + 1)
: 0;
uint16_t copied = available < count ? available : count;
if (copied > (uint16_t)(maximum - output_length)) {
copied = (uint16_t)(maximum - output_length);
}
for (uint16_t offset = 0; offset < copied; offset++) {
output[output_length++] = win16_read_u8(win16_far_add_offset(
source, (uint16_t)(first + offset)));
}
return output_length;
}
/* 1020:0b1b — Insert(insertion,destination,index) with destination max length. */
void borland_short_insert(
Win16FarPtr destination,
Win16FarPtr insertion,
int16_t index,
uint8_t maximum_length)
{
if (index < 1) {
index = 1;
}
uint8_t result[255];
uint8_t length = 0;
length = copy_short_slice(
result, length, destination, 1, (uint16_t)(index - 1), maximum_length);
length = copy_short_slice(
result, length, insertion, 1, 255, maximum_length);
length = copy_short_slice(
result, length, destination, (uint16_t)index, 255, maximum_length);
win16_write_u8(destination, length);
for (uint16_t offset = 0; offset < length; offset++) {
win16_write_u8(
win16_far_add_offset(destination, (uint16_t)(offset + 1)),
result[offset]);
}
}
/* 1020:0b7a — Delete(string,index,count); invalid ranges leave it unchanged. */
void borland_short_delete(Win16FarPtr string, int16_t index, int16_t count)
{
if (index <= 0 || count <= 0 || count >= 256) {
return;
}
if (index > 255) {
index = 255;
}
uint8_t result[255];
uint8_t length = 0;
length = copy_short_slice(
result, length, string, 1, (uint16_t)(index - 1), 255);
length = copy_short_slice(
result, length, string, (uint16_t)(index + count), 255, 255);
win16_write_u8(string, length);
for (uint16_t offset = 0; offset < length; offset++) {
win16_write_u8(
win16_far_add_offset(string, (uint16_t)(offset + 1)), result[offset]);
}
}