The reconstructed tree now produces a runnable binary with the authentic 1995 toolchain (BC4.52 / tlink32 / DPMI32): - BTL4.CPP main TU reconstructed from the 4.11 Ghidra decomp (FUN_0040109c) + the 4.10 binary's own string pool + surviving RPL4TOOL.CPP house style; probe_main.cpp scaffold retired (BTL4.NOTES.md documents every decoded call) - L4NET.CPP staged: L4NetworkManager ctor/dtor + 10 vtable-pulled virtuals (standalone-benign ones no-op, network ones Fail loudly) + NetNub client globals (Net_Common_Ptr=NULL routes L4File to its plain-DOS path) - build410.sh: libs now built in the AUTHENTIC makefile member order (MUNGA.MAK / mungal4.mak / BT.MAK / BTL4.MAK). Order is load-bearing: tlink emits static-init records in module pull order, and alphabetical order booted into a null-vptr crash (IcomManager::ClassDerivations constructing before parent NetworkClient::ClassDerivations). Also fixed stage_link to the proven 32-bit lib set (SOSDBXC+SOSMBXC, no WATTCPLG) - BOXTREE.HPP MemoryBlock unify, BTL4GRND notify stubs, remaining engine backfills (audio/gauge/resource/stream TUs) that closed the deep ledger Smoke test (DOSBox-X + 32RTM, copy of the pod BT tree, our exe swapped in): BattleTech v4.10 BTL4Application::BTL4Application l4net.cpp(22): L4NetworkManager -- l4net.cpp not yet reconstructed Static init, main, -egg parse, BTL4.RES load (version 1.0.6 check passes), ApplicationManager and the BTL4Application ctor chain all execute real reconstructed code; boot halts at the first staged Fail() as designed. Next brick: the real l4net.cpp body. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
451 lines
10 KiB
C++
451 lines
10 KiB
C++
# if !defined(MUNGA_HPP)
|
|
# include <munga.hpp>
|
|
# endif
|
|
# if !defined(CSTR_HPP)
|
|
# include <cstr.hpp>
|
|
# endif
|
|
# if !defined(MEMSTRM_HPP)
|
|
# include <memstrm.hpp>
|
|
# endif
|
|
|
|
//namespace Munga
|
|
//{
|
|
rString StringRepresentation::operator+=(char chr)
|
|
{
|
|
Check(this);
|
|
size_t len = strlen(&firstByte);
|
|
*(&firstByte + len++) = chr;
|
|
*(&firstByte + len) = '\0';
|
|
return *this;
|
|
}
|
|
|
|
#if defined(USE_SIGNATURE)
|
|
int Is_Signature_Bad(const StringRepresentation *)
|
|
{
|
|
return False;
|
|
}
|
|
#endif
|
|
|
|
MemoryStream& MemoryStream_Read(MemoryStream *stream, StringRepresentation *str)
|
|
{
|
|
Check(stream);
|
|
Check(str);
|
|
|
|
pString ptr = *str;
|
|
for (*stream >> ptr[(size_t)0]; ptr[(size_t)0]; ++ptr)
|
|
*stream >> ptr[(size_t)0];
|
|
return *stream;
|
|
}
|
|
|
|
MemoryStream& MemoryStream_Write(MemoryStream *stream, const StringRepresentation &str)
|
|
{
|
|
Check(stream);
|
|
Check(&str);
|
|
|
|
return stream->WriteBytes((const char*)str, str.GetLength() + 1);
|
|
}
|
|
|
|
#define DELETE_FILL_CHAR ('0')
|
|
|
|
size_t CStringRepresentation::allocationIncrement = 8;
|
|
|
|
inline size_t CStringRepresentation::CalculateSize(size_t needed)
|
|
{
|
|
Verify(!Small_Enough(allocationIncrement));
|
|
size_t x = ((needed + allocationIncrement) / allocationIncrement) * allocationIncrement;
|
|
return x;
|
|
}
|
|
|
|
CStringRepresentation::CStringRepresentation()
|
|
{
|
|
stringLength = 0;
|
|
stringSize = 0;
|
|
stringText = NULL;
|
|
referenceCount = 0;
|
|
}
|
|
|
|
CStringRepresentation::CStringRepresentation(const CStringRepresentation &str)
|
|
{
|
|
Check(&str);
|
|
stringLength = str.stringLength;
|
|
stringSize = str.stringSize;
|
|
|
|
if (str.stringText == NULL)
|
|
stringText = NULL;
|
|
else
|
|
{
|
|
stringText = new char[stringSize];
|
|
Register_Pointer(stringText);
|
|
Mem_Copy(stringText, str.stringText, stringLength + 1, stringSize);
|
|
}
|
|
referenceCount = 0;
|
|
}
|
|
|
|
CStringRepresentation::CStringRepresentation(const char *cstr)
|
|
{
|
|
if ((cstr == NULL) || (cstr[0] == '\x00'))
|
|
{
|
|
stringLength = 0;
|
|
stringSize = 0;
|
|
stringText = NULL;
|
|
}
|
|
else
|
|
{
|
|
stringLength = strlen(cstr);
|
|
stringSize = CalculateSize(stringLength);
|
|
|
|
stringText = new char[stringSize];
|
|
Register_Pointer(stringText);
|
|
Mem_Copy(stringText, cstr, stringLength + 1, stringSize);
|
|
}
|
|
referenceCount = 0;
|
|
}
|
|
|
|
CStringRepresentation::~CStringRepresentation()
|
|
{
|
|
if (stringText != NULL)
|
|
{
|
|
#if DEBUG_LEVEL>0
|
|
memset(stringText, DELETE_FILL_CHAR, stringSize);
|
|
#endif
|
|
Unregister_Pointer(stringText);
|
|
delete[] stringText;
|
|
}
|
|
}
|
|
|
|
Logical CStringRepresentation::TestInstance() const
|
|
{
|
|
if (stringText == NULL)
|
|
{
|
|
Verify(stringSize == 0);
|
|
Verify(stringLength == 0);
|
|
}
|
|
else
|
|
{
|
|
Verify(stringSize > 0);
|
|
Verify(stringLength == strlen(stringText));
|
|
}
|
|
return True;
|
|
}
|
|
|
|
CStringRepresentation CStringRepresentation::operator = (const CStringRepresentation &str)
|
|
{
|
|
Check(this);
|
|
|
|
if (this == &str)
|
|
return *this;
|
|
|
|
if (stringText != NULL)
|
|
{
|
|
#if DEBUG_LEVEL>0
|
|
memset(stringText, DELETE_FILL_CHAR, stringSize);
|
|
#endif
|
|
Unregister_Pointer(stringText);
|
|
delete[] stringText;
|
|
}
|
|
|
|
Check(&str);
|
|
stringLength = str.stringLength;
|
|
stringSize = str.stringSize;
|
|
|
|
if (stringSize == 0)
|
|
stringText = NULL;
|
|
else
|
|
{
|
|
stringText = new char[stringSize];
|
|
Register_Pointer(stringText);
|
|
Mem_Copy(stringText, str.stringText, stringLength + 1, stringSize);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
CStringRepresentation CStringRepresentation::operator = (const char *cstr)
|
|
{
|
|
Check(this);
|
|
|
|
if (stringText != NULL)
|
|
{
|
|
#if DEBUG_LEVEL>0
|
|
memset(stringText, DELETE_FILL_CHAR, stringSize);
|
|
#endif
|
|
Unregister_Pointer(stringText);
|
|
delete[] stringText;
|
|
}
|
|
|
|
if ((cstr == NULL) || (cstr[0] == '\x00'))
|
|
{
|
|
stringLength = 0;
|
|
stringSize = 0;
|
|
stringText = NULL;
|
|
}
|
|
else
|
|
{
|
|
stringLength = strlen(cstr);
|
|
stringSize = CalculateSize(stringLength);
|
|
|
|
stringText = new char[stringSize];
|
|
Register_Pointer(stringText);
|
|
Mem_Copy(stringText, cstr, stringLength + 1, stringSize);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
CStringRepresentation operator + (const CStringRepresentation &str1, const CStringRepresentation &str2)
|
|
{
|
|
Check(&str1);
|
|
Check(&str2);
|
|
|
|
CStringRepresentation temp;
|
|
|
|
unsigned long totalLen = str1.stringLength + str2.stringLength;
|
|
|
|
if (totalLen == 0)
|
|
return temp;
|
|
|
|
temp.stringLength = 0;
|
|
temp.stringSize = CStringRepresentation::CalculateSize((size_t)totalLen);
|
|
temp.stringText = new char[temp.stringSize];
|
|
Register_Pointer(temp.stringText);
|
|
|
|
Verify(temp.stringSize >= 1);
|
|
temp.stringText[0] = '\000';
|
|
|
|
if (str1.stringText != NULL)
|
|
{
|
|
Mem_Copy(temp.stringText, str1.stringText, str1.stringLength, temp.stringSize);
|
|
temp.stringLength = str1.stringLength;
|
|
}
|
|
|
|
if (str2.stringText != NULL)
|
|
{
|
|
Verify(temp.stringLength < temp.stringSize);
|
|
Mem_Copy(&temp.stringText[temp.stringLength], str2.stringText, str2.stringLength + 1, temp.stringSize - temp.stringLength);
|
|
temp.stringLength += str2.stringLength;
|
|
}
|
|
|
|
Check(&temp);
|
|
return temp;
|
|
}
|
|
|
|
CStringRepresentation operator + (const CStringRepresentation &str, char ch)
|
|
{
|
|
Check(&str);
|
|
|
|
CStringRepresentation temp;
|
|
|
|
if (str.stringText == NULL)
|
|
{
|
|
temp.stringLength = 1;
|
|
temp.stringSize = CStringRepresentation::allocationIncrement;
|
|
temp.stringText = new char [temp.stringSize];
|
|
Register_Pointer(temp.stringText);
|
|
|
|
Verify(temp.stringSize >= 2);
|
|
temp.stringText[0] = ch;
|
|
temp.stringText[1] = '\000';
|
|
}
|
|
else
|
|
{
|
|
Verify(str.stringLength != UINT_MAX);
|
|
|
|
temp.stringLength = str.stringLength + 1;
|
|
|
|
if (temp.stringLength == str.stringSize)
|
|
temp.stringSize = str.stringSize + CStringRepresentation::allocationIncrement;
|
|
else
|
|
temp.stringSize = str.stringSize;
|
|
|
|
temp.stringText = new char[temp.stringSize];
|
|
Register_Pointer(temp.stringText);
|
|
Mem_Copy(temp.stringText, str.stringText, str.stringLength, temp.stringSize);
|
|
|
|
Verify(str.stringLength < temp.stringSize);
|
|
Verify(temp.stringLength < temp.stringSize);
|
|
temp.stringText[str.stringLength] = ch;
|
|
temp.stringText[temp.stringLength] = '\000';
|
|
}
|
|
|
|
Check(&temp);
|
|
return temp;
|
|
}
|
|
|
|
int CStringRepresentation::Compare(const CStringRepresentation &str) const
|
|
{
|
|
Check(this);
|
|
Check(&str);
|
|
|
|
// handle special cases where one string is empty
|
|
if (stringText == NULL)
|
|
{
|
|
if (str.stringText == NULL)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
}
|
|
if (str.stringText == NULL)
|
|
return 1;
|
|
|
|
return strcmp(stringText, str.stringText);
|
|
}
|
|
|
|
CStringRepresentation CStringRepresentation::GetNthToken(size_t nth_token, char *delimiters) const
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
// Which delimters to use
|
|
//
|
|
char *delimter_string = " \t,";
|
|
|
|
if (delimiters != NULL)
|
|
delimter_string = delimiters;
|
|
Check_Pointer(delimter_string);
|
|
|
|
//
|
|
// Make temporary
|
|
//
|
|
CStringRepresentation temp(*this);
|
|
|
|
if (temp.stringText == NULL)
|
|
return temp;
|
|
|
|
//
|
|
// Parse string with strtok
|
|
//
|
|
size_t i;
|
|
char *ptr;
|
|
|
|
Check_Pointer(temp.stringText);
|
|
ptr = strtok(temp.stringText, delimter_string);
|
|
for (i = 0; i < nth_token; i++)
|
|
if ((ptr = strtok(NULL, delimter_string)) == NULL)
|
|
break;
|
|
|
|
if (ptr == NULL)
|
|
{
|
|
CStringRepresentation null_return;
|
|
return null_return;
|
|
}
|
|
CStringRepresentation token_return(ptr);
|
|
return token_return;
|
|
}
|
|
|
|
#if 0
|
|
void CStringRepresentation::ToUpper()
|
|
{
|
|
Check(this);
|
|
if (stringText != NULL)
|
|
strupr(stringText);
|
|
}
|
|
|
|
void CStringRepresentation::ToLower()
|
|
{
|
|
Check(this);
|
|
if (stringText != NULL)
|
|
strlwr(stringText);
|
|
}
|
|
#endif
|
|
|
|
MemoryStream& MemoryStream_Read(MemoryStream *stream, CStringRepresentation *str)
|
|
{
|
|
Check(stream);
|
|
Check(str);
|
|
|
|
size_t string_length;
|
|
char *ptr;
|
|
|
|
MemoryStream_Read(stream, &string_length);
|
|
ptr = new char[string_length + 1];
|
|
Register_Pointer(ptr);
|
|
stream->ReadBytes(ptr, string_length + 1);
|
|
|
|
*str = ptr;
|
|
|
|
Unregister_Pointer(ptr);
|
|
delete[] ptr;
|
|
|
|
Check(str);
|
|
return *stream;
|
|
}
|
|
|
|
MemoryStream& MemoryStream_Write(MemoryStream *stream, const CStringRepresentation &str)
|
|
{
|
|
Check(stream);
|
|
Check(&str);
|
|
|
|
MemoryStream_Write(stream, &str.stringLength);
|
|
return stream->WriteBytes(str.stringText, str.stringLength + 1);
|
|
}
|
|
|
|
void Convert_From_Ascii(const char *str, CStringRepresentation *value)
|
|
{
|
|
#if 0
|
|
Check_Pointer(str);
|
|
Check(value);
|
|
*value = str;
|
|
#else
|
|
if (str == NULL)
|
|
Fail("Convert_From_Ascii - str == NULL");
|
|
if (value == NULL)
|
|
Fail("Convert_From_Ascii - value == NULL");
|
|
*value = str;
|
|
#endif
|
|
}
|
|
|
|
CString CString::operator = (const CString &str)
|
|
{
|
|
Check(this);
|
|
Check(&str);
|
|
|
|
if (this == &str)
|
|
return *this;
|
|
|
|
Check(representation);
|
|
representation->DecrementReferenceCount();
|
|
representation = str.representation;
|
|
representation->IncrementReferenceCount();
|
|
return *this;
|
|
}
|
|
|
|
CString CString::operator = (const char *cstr)
|
|
{
|
|
Check(representation);
|
|
representation->DecrementReferenceCount();
|
|
representation = new CStringRepresentation(cstr);
|
|
Register_Object(representation);
|
|
representation->IncrementReferenceCount();
|
|
return *this;
|
|
}
|
|
|
|
MemoryStream& MemoryStream_Read(MemoryStream *stream, CString *str)
|
|
{
|
|
Check(str);
|
|
Check(str->representation);
|
|
str->representation->DecrementReferenceCount();
|
|
str->representation = new CStringRepresentation;
|
|
Register_Object(str->representation);
|
|
str->representation->IncrementReferenceCount();
|
|
Verify(str->representation->referenceCount == 1);
|
|
return MemoryStream_Read(stream, str->representation);
|
|
}
|
|
|
|
void Convert_From_Ascii(const char *str, CString *value)
|
|
{
|
|
Check(value);
|
|
Check(value->representation);
|
|
value->representation->DecrementReferenceCount();
|
|
value->representation = new CStringRepresentation;
|
|
Register_Object(value->representation);
|
|
value->representation->IncrementReferenceCount();
|
|
Verify(value->representation->referenceCount == 1);
|
|
Convert_From_Ascii(str, value->representation);
|
|
}
|
|
//}
|
|
|
|
#if defined(TEST_CLASS)
|
|
#include "cstr.tcp"
|
|
#endif
|
|
|