Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
568 lines
14 KiB
C++
568 lines
14 KiB
C++
//===========================================================================//
|
|
// File: memstrm.hpp //
|
|
// Project: MUNGA Brick: Resource Manager //
|
|
// Contents: Implementation Details of resource management //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#pragma once
|
|
|
|
#include "Stuff.hpp"
|
|
|
|
namespace Stuff {class MemoryStream;}
|
|
|
|
namespace MemoryStreamIO
|
|
{
|
|
Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream *stream,
|
|
const Stuff::MemoryStream *input_stream
|
|
);
|
|
}
|
|
|
|
namespace Stuff {
|
|
|
|
class MemoryStream;
|
|
class DynamicMemoryStream;
|
|
|
|
//##########################################################################
|
|
//####################### MemoryStream ###############################
|
|
//##########################################################################
|
|
|
|
const int End_Of_Stream=-1;
|
|
|
|
const int Empty_Bit_Buffer=-20;
|
|
|
|
|
|
class MemoryStream :
|
|
public RegisteredClass
|
|
{
|
|
friend MemoryStream& MemoryStreamIO::Write(
|
|
MemoryStream *stream,
|
|
const MemoryStream *input_stream
|
|
);
|
|
|
|
public:
|
|
static void InitializeClass();
|
|
static void TerminateClass();
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and testing
|
|
//
|
|
public:
|
|
MemoryStream(
|
|
void *stream_start,
|
|
DWORD stream_size,
|
|
DWORD initial_offset=0
|
|
);
|
|
virtual ~MemoryStream();
|
|
|
|
void TestInstance() const;
|
|
|
|
static bool TestClass();
|
|
|
|
protected:
|
|
MemoryStream(
|
|
ClassData *data,
|
|
void *stream_start,
|
|
DWORD stream_size,
|
|
DWORD initial_offset=0
|
|
);
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Class Data Support
|
|
//
|
|
public:
|
|
static ClassData *DefaultData;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Accessors
|
|
//
|
|
public:
|
|
virtual void* GetPointer() const
|
|
{Check_Object(this); return currentPosition;}
|
|
BYTE* GetStreamStart() const
|
|
{Check_Object(this); return streamStart; }
|
|
DWORD GetIndex() const
|
|
{Check_Object(this); return currentPosition - streamStart;}
|
|
DWORD GetSize() const
|
|
{Check_Object(this); return streamSize;}
|
|
|
|
DWORD GetBufferBytesUsed()
|
|
{Check_Object(this); return highWaterByte - streamStart;}
|
|
|
|
|
|
DWORD GetBytesUsed() const
|
|
{Check_Object(this); return currentPosition - streamStart;}
|
|
virtual DWORD GetBytesRemaining() const
|
|
{Check_Object(this); return streamSize - GetBytesUsed();}
|
|
|
|
|
|
void AdvanceToDwordBoundary()
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
if((int)currentPosition & 0x3)
|
|
{
|
|
AdvancePointer(4-(int)currentPosition & 0x3);
|
|
}
|
|
|
|
Check_Object(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Assignment methods
|
|
//
|
|
public:
|
|
virtual void SetPointer(void *new_pointer)
|
|
{
|
|
Check_Pointer(this);
|
|
currentPosition = Cast_Pointer(BYTE*, new_pointer);
|
|
|
|
if (currentPosition > highWaterByte)
|
|
highWaterByte = currentPosition;
|
|
|
|
Check_Object(this);
|
|
}
|
|
void operator=(void *new_pointer)
|
|
{SetPointer(new_pointer);}
|
|
|
|
virtual void SetPointer(DWORD index)
|
|
{
|
|
Check_Pointer(this);
|
|
currentPosition = streamStart + index;
|
|
|
|
if (currentPosition > highWaterByte)
|
|
highWaterByte = currentPosition;
|
|
|
|
Check_Object(this);
|
|
}
|
|
void operator=(DWORD index)
|
|
{SetPointer(index);}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Stream methods
|
|
//
|
|
public:
|
|
void Rewind()
|
|
{SetPointer((DWORD) 0U);currentBit = Empty_Bit_Buffer;}
|
|
|
|
virtual bool AllocateBytes(DWORD count)
|
|
{return GetBytesRemaining() <= count;}
|
|
virtual MemoryStream& AdvancePointer(DWORD count)
|
|
{
|
|
Check_Object(this);
|
|
currentPosition += count;
|
|
|
|
if (currentPosition > highWaterByte)
|
|
highWaterByte = currentPosition;
|
|
|
|
Verify(currentPosition >= streamStart);
|
|
Verify(currentPosition <= streamStart + streamSize);
|
|
|
|
Check_Object(this);
|
|
return *this;
|
|
}
|
|
MemoryStream& operator+=(DWORD count)
|
|
{return AdvancePointer(count);}
|
|
|
|
virtual MemoryStream& RewindPointer(DWORD count)
|
|
{
|
|
Check_Object(this);
|
|
currentPosition -= count;
|
|
|
|
if (currentPosition > highWaterByte)
|
|
highWaterByte = currentPosition;
|
|
|
|
Verify(currentPosition >= streamStart);
|
|
Verify(currentPosition <= streamStart + streamSize);
|
|
|
|
Check_Object(this);
|
|
return *this;
|
|
}
|
|
MemoryStream& operator-=(DWORD count)
|
|
{return RewindPointer(count);}
|
|
|
|
virtual MemoryStream& ReadBytes(
|
|
void *ptr,
|
|
DWORD number_of_bytes
|
|
);
|
|
virtual MemoryStream& WriteBytes(
|
|
const void *ptr,
|
|
DWORD number_of_bytes
|
|
);
|
|
|
|
MemoryStream& ReadSwappedBytes(
|
|
void *ptr,
|
|
DWORD number_of_bytes
|
|
);
|
|
MemoryStream& WriteSwappedBytes(
|
|
const void *ptr,
|
|
DWORD number_of_bytes
|
|
);
|
|
|
|
virtual int ReadChar();
|
|
|
|
virtual bool ReadLine(
|
|
char *buffer,
|
|
int size_of_buffer,
|
|
char continuator = '\0'
|
|
);
|
|
|
|
MString ReadString(
|
|
DWORD size_of_buffer = 512,
|
|
char continuator = '\0'
|
|
);
|
|
|
|
void WriteLine(char *buffer);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Bit operators
|
|
//
|
|
// WARNING - DO NOT MIX AND MATCH WITH BYTE METHODS!!!!!
|
|
//
|
|
|
|
private:
|
|
int currentBit;
|
|
|
|
BYTE workingBitBuffer;
|
|
|
|
MemoryStream& ReadUnsafeBits(void *ptr, DWORD number_of_bits);
|
|
|
|
public:
|
|
int GetCurrentBitCount()
|
|
{
|
|
Check_Object(this);
|
|
int current_bit = GetBytesUsed() * 8;
|
|
if (currentBit != Empty_Bit_Buffer)
|
|
{
|
|
current_bit -= (8-currentBit);
|
|
}
|
|
|
|
return current_bit;
|
|
}
|
|
|
|
MemoryStream& ReadBit(bool &bit_value);
|
|
MemoryStream& WriteBit(const bool &bit_value);
|
|
|
|
MemoryStream& ReadBits(__int64 *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits <= 64);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
MemoryStream& ReadBits(int *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits <= 32);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
MemoryStream& ReadBits(BYTE *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits <= 8);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
|
|
MemoryStream& ReadBits(WORD *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits <= 16);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
MemoryStream& ReadBits(DWORD *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits <= 32);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
MemoryStream& ReadBits(float *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits == 32);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0.0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
|
|
MemoryStream& ReadBits(double *ptr, DWORD number_of_bits)
|
|
{
|
|
Verify(number_of_bits == 64);
|
|
Check_Object(this); Check_Pointer(ptr);
|
|
*ptr = 0.0; return ReadUnsafeBits(ptr, number_of_bits);
|
|
}
|
|
|
|
MemoryStream& WriteBits(const void *ptr, DWORD number_of_bits);
|
|
|
|
MemoryStream& ReadBitsToScaledInt(int &number, int min, int max, DWORD number_of_bits);
|
|
MemoryStream& WriteScaledIntToBits(const int &number, int min, int max, DWORD number_of_bits);
|
|
|
|
MemoryStream& ReadBitsToScaledFloat(float &number, float min, float max, DWORD number_of_bits);
|
|
MemoryStream& WriteScaledFloatToBits(const float &number, float min, float max, DWORD number_of_bits);
|
|
|
|
|
|
void WriteByteAlign();
|
|
|
|
void ReadByteAlign();
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Protected data
|
|
//
|
|
protected:
|
|
BYTE
|
|
*streamStart,
|
|
*currentPosition,
|
|
*highWaterByte;
|
|
DWORD streamSize;
|
|
};
|
|
|
|
template <class T> inline MemoryStream& Read_Swapped(
|
|
MemoryStream *stream,
|
|
T data
|
|
)
|
|
{
|
|
return stream->ReadSwappedBytes(data, sizeof(*data));
|
|
}
|
|
|
|
template <class T> inline MemoryStream& Write_Swapped(
|
|
MemoryStream *stream,
|
|
const T data
|
|
)
|
|
{
|
|
return stream->WriteSwappedBytes(&data, sizeof(data));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Extraction operators
|
|
//
|
|
template <class T> inline MemoryStream& operator>>(
|
|
MemoryStream &stream,
|
|
T &output
|
|
)
|
|
{return MemoryStreamIO::Read(&stream, &output);}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Insertion operators
|
|
//
|
|
template <class T> inline MemoryStream& operator<<(
|
|
MemoryStream &stream,
|
|
const T &input
|
|
)
|
|
{return MemoryStreamIO::Write(&stream, &input);}
|
|
|
|
inline MemoryStream& operator<<(
|
|
MemoryStream& stream,
|
|
const char* input
|
|
)
|
|
{
|
|
Check_Pointer(input);
|
|
|
|
if (strlen(input) == 0)
|
|
return stream;
|
|
|
|
return stream.WriteBytes(input, strlen(input));
|
|
}
|
|
|
|
//##########################################################################
|
|
//################### DynamicMemoryStream ############################
|
|
//##########################################################################
|
|
|
|
class DynamicMemoryStream:
|
|
public MemoryStream
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction, destruction, and testing
|
|
//
|
|
public:
|
|
DynamicMemoryStream(DWORD stream_size=0);
|
|
DynamicMemoryStream(
|
|
void *stream_start,
|
|
DWORD stream_size,
|
|
DWORD initial_offset=0
|
|
);
|
|
DynamicMemoryStream(const DynamicMemoryStream& otherStream);
|
|
~DynamicMemoryStream();
|
|
|
|
void TestInstance() const
|
|
{
|
|
Verify((DWORD)(currentPosition - streamStart) <= streamSize);
|
|
Verify(streamSize <= bufferSize);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Accessors
|
|
//
|
|
public:
|
|
DWORD GetBufferSize()
|
|
{
|
|
Check_Object(this);
|
|
return bufferSize;
|
|
}
|
|
|
|
void SetSize(DWORD stream_length)
|
|
{
|
|
Check_Object(this);
|
|
Verify(stream_length <= bufferSize);
|
|
streamSize = stream_length;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Stream methods
|
|
//
|
|
public:
|
|
MemoryStream& WriteBytes(
|
|
const void *ptr,
|
|
DWORD number_of_bytes
|
|
);
|
|
|
|
bool AllocateBytes(DWORD count);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Private data
|
|
//
|
|
private:
|
|
DWORD bufferSize;
|
|
bool ownsStream;
|
|
};
|
|
|
|
}
|
|
|
|
namespace MemoryStreamIO {
|
|
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
char *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
BYTE *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
short *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
WORD *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
int *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
bool *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
unsigned *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
long *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
DWORD *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
|
|
inline Stuff::MemoryStream& Read(
|
|
Stuff::MemoryStream* stream,
|
|
double *output
|
|
)
|
|
{return stream->ReadBytes(output, sizeof(*output));}
|
|
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const char *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const BYTE *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const short *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const WORD *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const int *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const bool *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const unsigned *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const long *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const DWORD *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const double *input
|
|
)
|
|
{return stream->WriteBytes(input, sizeof(*input));}
|
|
|
|
inline Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const char* const* input
|
|
)
|
|
{
|
|
Check_Pointer(*input);
|
|
return stream->WriteBytes(*input, strlen(*input));
|
|
}
|
|
|
|
Stuff::MemoryStream& Write(
|
|
Stuff::MemoryStream* stream,
|
|
const Stuff::MemoryStream* input_stream
|
|
);
|
|
|
|
}
|