Files
BT412/engine/MUNGA/MEMSTRM.H
T
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

141 lines
5.8 KiB
C++

#pragma once
#include <iostream>
#include "style.h"
//##########################################################################
//####################### MemoryStream ###############################
//##########################################################################
class MemoryStream
{
friend MemoryStream& MemoryStream_Write(MemoryStream *stream, const MemoryStream *input_stream);
public:
MemoryStream(void *stream_start, size_t stream_size, size_t initial_offset=0);
size_t GetIndex() const { return currentPosition - streamStart; }
size_t GetSize() const { return streamSize; }
size_t GetBytesUsed() const { return currentPosition - streamStart; }
void Rewind() { SetPointer(0U); }
bool TestInstance() const;
virtual void* GetPointer() const { return currentPosition; }
virtual size_t GetBytesRemaining() const { return streamSize - GetBytesUsed(); }
virtual void SetPointer(void *new_pointer) { currentPosition = (char*)new_pointer; }
virtual void SetPointer(size_t index) { currentPosition = streamStart + index; }
virtual bool AllocateBytes(size_t count) { return GetBytesRemaining() <= count; }
virtual MemoryStream& RewindPointer(size_t count) { currentPosition -= count; return *this; }
virtual MemoryStream& AdvancePointer(size_t count) { currentPosition += count; return *this; }
virtual MemoryStream& ReadBytes(void *ptr, size_t number_of_bytes);
virtual MemoryStream& WriteBytes(const void *ptr, size_t number_of_bytes);
void operator= (void *new_pointer) { SetPointer(new_pointer); }
void operator= (size_t index) { SetPointer(index); }
MemoryStream& operator+= (size_t count) { return AdvancePointer(count); }
MemoryStream& operator-= (size_t count) { return RewindPointer(count); }
protected:
char *streamStart, *currentPosition;
size_t streamSize;
};
//--------------------------------------------------------------------------
// Extraction operators
//
template <class T> inline MemoryStream& operator>>(MemoryStream &stream, T &output)
{ return MemoryStream_Read(&stream, &output); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, char *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned char *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, short *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned short *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, int *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned int *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, long *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned long *output)
{ return stream->ReadBytes(output, sizeof(*output)); }
//--------------------------------------------------------------------------
// Insertion operators
//
template <class T> inline MemoryStream& operator<<(MemoryStream &stream, const T &input)
{ return MemoryStream_Write(&stream, &input); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const char *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned char *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const short *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned short *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const int *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned int *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const long *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned long *input)
{ return stream->WriteBytes(input, sizeof(*input)); }
MemoryStream& MemoryStream_Write(MemoryStream* stream, std::istream *input);
MemoryStream& MemoryStream_Write(MemoryStream* stream, const MemoryStream* input_stream);
#define MEM_STRM_WRITE_ENTRY(stream, name_list, type, name)\
{\
type name;\
const char* data = (const char*)(name_list)->FindData(#name);\
if (!data)\
{\
DEBUG_STREAM << "DYN_MEM_STRM_WRITE_ENTRY - #name == " << std::flush;\
DEBUG_STREAM << #name << "\n" << std::flush;\
Fail("DYN_MEM_STRM_WRITE_ENTRY - (name_list)->FindData(#name) == NULL");\
}\
Check_Pointer(data);\
Convert_From_Ascii(data, &name);\
stream << name;\
}
//##########################################################################
//################### DynamicMemoryStream ############################
//##########################################################################
class DynamicMemoryStream : public MemoryStream
{
public:
DynamicMemoryStream(size_t stream_size = 0);
DynamicMemoryStream(void *stream_start, size_t stream_size, size_t initial_offset = 0);
~DynamicMemoryStream();
bool TestInstance() const { return ((size_t)(currentPosition - streamStart) <= streamSize && streamLength <= streamSize); }
size_t GetBytesRemaining() const { return streamSize - GetBytesUsed(); }
bool AllocateBytes(size_t count);
MemoryStream& WriteBytes(const void *ptr, size_t number_of_bytes);
private:
size_t streamLength;
bool ownsStream;
};