
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
991 lines
23 KiB
C++
991 lines
23 KiB
C++
#ifndef _INCLUDED_IFF_HPP_
|
|
#define _INCLUDED_IFF_HPP_
|
|
|
|
#if defined(_WIN32) || defined(WIN32) || defined(WINDOWS) || defined(_WINDOWS)
|
|
#define _IFF_WIN_TARGET
|
|
#include <windows.h>
|
|
#else // ! WIN32 && ! _WIN32 && ! WINDOWS && ! _WINDOWS
|
|
#include <stdio.h>
|
|
#include <conio.h>
|
|
#endif // ! WIN32 && ! _WIN32 && ! WINDOWS && ! _WINDOWS
|
|
|
|
#include "media.hpp"
|
|
|
|
namespace IFF
|
|
{
|
|
/*************************/
|
|
/* Class Hierarchy: */
|
|
/* */
|
|
/* + Unknown */
|
|
/* + SerializableObj */
|
|
/* + GenericFile */
|
|
/* + File */
|
|
/* + Chunk */
|
|
/* + Composite */
|
|
/* + Form */
|
|
/* + Cat */
|
|
/* + List */
|
|
/* + Prop */
|
|
/* + MiscChunk */
|
|
/* + <user chunks> */
|
|
/* + Arvhive */
|
|
/* + ArchvIn */
|
|
/* + ArchvOut(*) */
|
|
/* + DataBlock */
|
|
/* + DataNode */
|
|
/* + SerialData */
|
|
/* + ArchvOut(*) */
|
|
/* + ChildNode */
|
|
/* + DeviceHandle */
|
|
/*************************/
|
|
|
|
#ifdef _IFF_WIN_TARGET
|
|
inline void DisplayMessage(TCHAR const * pszTitle,TCHAR const * pszText)
|
|
{
|
|
::MessageBox(NULL,pszText,pszTitle,MB_OK|MB_ICONEXCLAMATION|MB_SETFOREGROUND);
|
|
}
|
|
#else
|
|
inline void DisplayMessage(char const * pszTitle,char const * pszText)
|
|
{
|
|
::printf("%s\n%s\n",pszTitle,pszText);
|
|
while (::kbhit())
|
|
::getch();
|
|
while (!::kbhit() || '\r' != ::getch())
|
|
;
|
|
}
|
|
#endif
|
|
|
|
// forward refs
|
|
//class Unknown;
|
|
//class SerializableObj;
|
|
//class GenericFile;
|
|
//class File;
|
|
//class Chunk;
|
|
class Composite;
|
|
//class Form;
|
|
//class Cat;
|
|
//class List;
|
|
//class Prop;
|
|
//class MiscChunk;
|
|
//class Archive;
|
|
//class ArchvIn;
|
|
//class ArchvOut;
|
|
//class DataBlock;
|
|
//class DataNode;
|
|
//class SerialData;
|
|
class ChildNode;
|
|
//class DeviceHandle;
|
|
|
|
/*****************************/
|
|
/* Original File: iffObj.hpp */
|
|
/*****************************/
|
|
|
|
class Unknown
|
|
{
|
|
public:
|
|
unsigned AddRef() { return ++m_nRefCnt; }
|
|
unsigned Release() { if (0==(--m_nRefCnt)) { delete this; return 0;} else return m_nRefCnt; }
|
|
protected:
|
|
virtual ~Unknown() {
|
|
#ifndef NDEBUG
|
|
DbForget(this);
|
|
#endif
|
|
}
|
|
Unknown() : m_nRefCnt(1) {
|
|
#ifndef NDEBUG
|
|
DbRemember(this);
|
|
#endif
|
|
}
|
|
Unknown(Unknown const &) : m_nRefCnt(1) {
|
|
#ifndef NDEBUG
|
|
DbRemember(this);
|
|
#endif
|
|
}
|
|
private:
|
|
unsigned m_nRefCnt;
|
|
|
|
#ifndef NDEBUG
|
|
friend void DbRemember(Unknown * pObj);
|
|
friend void DbForget(Unknown * pObj);
|
|
friend class AllocList;
|
|
#endif
|
|
};
|
|
|
|
/*******************************/
|
|
/* Original File: iffTypes.hpp */
|
|
/*******************************/
|
|
|
|
// deal with any silly bastard who's put #define BYTE ... in a header, etc.
|
|
#ifdef BYTE
|
|
#undef BYTE
|
|
#pragma message("BYTE was defined - undefining")
|
|
#endif
|
|
typedef signed char BYTE;
|
|
typedef unsigned char UBYTE;
|
|
|
|
typedef signed short INT16;
|
|
typedef unsigned short UINT16;
|
|
|
|
typedef signed INT32;
|
|
typedef unsigned UINT32;
|
|
|
|
typedef signed __int64 INT64;
|
|
typedef unsigned __int64 UINT64;
|
|
|
|
struct RGBTriple
|
|
{
|
|
UBYTE r;
|
|
UBYTE g;
|
|
UBYTE b;
|
|
};
|
|
|
|
union ID
|
|
{
|
|
UINT32 m_nID;
|
|
char m_sID[4];
|
|
|
|
inline ID(){}
|
|
inline ID(char const * pszID) { m_nID = *reinterpret_cast<UINT32 const *>(pszID); }
|
|
inline ID(UINT32 nID) : m_nID(nID) {}
|
|
inline operator UINT32 () const { return m_nID; }
|
|
inline operator char const * () const { return &m_sID[0]; }
|
|
inline bool operator == (ID const & rId) const { return !m_nID || !rId.m_nID || m_nID == rId.m_nID; }
|
|
inline bool operator != (ID const & rId) const { return ! operator == (rId); }
|
|
inline bool operator ! () const { return !m_nID; }
|
|
};
|
|
|
|
ID const ID_ANY(0U);
|
|
|
|
#ifndef IFF_READ_ONLY
|
|
|
|
/*******************************/
|
|
/* Original File: iffSData.hpp */
|
|
/*******************************/
|
|
|
|
class DataBlock : public Unknown
|
|
{
|
|
public:
|
|
virtual ~DataBlock();
|
|
DataBlock() : m_pBlock(new UBYTE [128]), m_nMaxSize(128), m_nCurSize(0) {}
|
|
|
|
unsigned GetDataSize() const;
|
|
UBYTE const * GetDataPtr() const;
|
|
|
|
bool WriteToFile(::MediaMedium * pMedium) const;
|
|
|
|
void Append(UBYTE byte);
|
|
void Append(void const * pData, unsigned nSize);
|
|
|
|
private:
|
|
void Expand(unsigned nMinSize);
|
|
|
|
UBYTE * m_pBlock;
|
|
unsigned m_nMaxSize;
|
|
unsigned m_nCurSize;
|
|
};
|
|
|
|
inline unsigned DataBlock::GetDataSize() const
|
|
{
|
|
return m_nCurSize;
|
|
}
|
|
|
|
inline UBYTE const * DataBlock::GetDataPtr() const
|
|
{
|
|
return m_pBlock;
|
|
}
|
|
|
|
inline void DataBlock::Append(UBYTE byte)
|
|
{
|
|
if (m_nCurSize >= m_nMaxSize)
|
|
Expand(m_nCurSize+1);
|
|
|
|
m_pBlock[m_nCurSize++] = byte;
|
|
}
|
|
|
|
inline void DataBlock::Append(void const * pData, unsigned nSize)
|
|
{
|
|
if (m_nCurSize+nSize > m_nMaxSize)
|
|
Expand(m_nCurSize+nSize+32);
|
|
|
|
memcpy(&m_pBlock[m_nCurSize],pData,nSize);
|
|
|
|
m_nCurSize += nSize;
|
|
}
|
|
|
|
class DataNode : public Unknown
|
|
{
|
|
public:
|
|
DataNode(DataNode * pNext, DataBlock * pData, DataNode * pPrev)
|
|
: m_pNext(pNext)
|
|
, m_pData(pData)
|
|
, m_pPrev(pPrev)
|
|
{
|
|
if (pNext) pNext->AddRef();
|
|
if (pData) pData->AddRef();
|
|
if (pPrev) pPrev->AddRef();
|
|
}
|
|
virtual ~DataNode();
|
|
|
|
unsigned GetDataSize() const;
|
|
|
|
bool WriteToFile(::MediaMedium * pMedium) const;
|
|
|
|
private:
|
|
DataNode * m_pNext;
|
|
DataBlock * m_pData;
|
|
DataNode * m_pPrev;
|
|
};
|
|
|
|
class SerialData : public Unknown
|
|
{
|
|
public:
|
|
virtual ~SerialData();
|
|
SerialData() : m_pPrev(NULL), m_pData(new DataBlock) {};
|
|
|
|
void Clear();
|
|
|
|
unsigned GetDataSize() const;
|
|
|
|
bool WriteToFile(::MediaMedium * pMedium) const;
|
|
|
|
void Append(UBYTE byte);
|
|
void Append(void const * pData, unsigned nSize);
|
|
|
|
void Append(SerialData * pData);
|
|
|
|
private:
|
|
DataBlock * m_pData;
|
|
DataNode * m_pPrev;
|
|
};
|
|
|
|
inline void SerialData::Append(UBYTE byte)
|
|
{
|
|
m_pData->Append(byte);
|
|
}
|
|
|
|
inline void SerialData::Append(void const * pData, unsigned nSize)
|
|
{
|
|
m_pData->Append(pData,nSize);
|
|
}
|
|
|
|
inline void SerialData::Append(SerialData * pIns)
|
|
{
|
|
DataNode * pNewNode = new DataNode(pIns->m_pPrev,m_pData,m_pPrev);
|
|
|
|
m_pData->Release();
|
|
m_pData = pIns->m_pData;
|
|
pIns->m_pData->AddRef();
|
|
|
|
if (m_pPrev)
|
|
m_pPrev->Release();
|
|
m_pPrev = pNewNode;
|
|
}
|
|
|
|
/*******************************/
|
|
/* Original File: iffArchv.hpp */
|
|
/*******************************/
|
|
|
|
class Archive : public Unknown
|
|
{
|
|
public:
|
|
// constructor - construct with true iff the archive is for loading data
|
|
Archive(bool bIsLoading) : m_bIsLoading(bIsLoading), m_bError(false) {}
|
|
|
|
// to determine easily whenever necessary if the archive is loading data
|
|
bool const m_bIsLoading;
|
|
bool m_bError;
|
|
|
|
// returns either the size in bytes of the data so far written to a storing archive
|
|
// or the number of bytes remaining to be read from a loading archive, could be negative
|
|
// if too many bytes were read
|
|
virtual signed GetSize() const = 0;
|
|
|
|
// if the archive is loading, nSize bytes are sectioned off to be read from a sub-archive
|
|
// or if the archive is storing, nSize is ignored and data written to the sub-archive
|
|
// will be stored when the sub-archive is closed
|
|
virtual Archive * OpenSubArchive(unsigned nSize = 0) = 0;
|
|
|
|
// commits data written temporarily to a sub-archive (if storing)
|
|
// and advances the archive to the next byte after the sub-archive's data
|
|
virtual void CloseSubArchive(Archive * pSub) = 0;
|
|
|
|
virtual void Open(::MediaMedium * pMedium) = 0;
|
|
virtual void Close() = 0;
|
|
|
|
virtual void Transfer(RGBTriple &) = 0;
|
|
virtual void Transfer(BYTE &) = 0;
|
|
virtual void Transfer(UBYTE &) = 0;
|
|
virtual void Transfer(INT16 &) = 0;
|
|
virtual void Transfer(UINT16 &) = 0;
|
|
virtual void Transfer(INT32 &) = 0;
|
|
virtual void Transfer(UINT32 &) = 0;
|
|
virtual void Transfer(INT64 &) = 0;
|
|
virtual void Transfer(UINT64 &) = 0;
|
|
virtual void Transfer(ID &) = 0;
|
|
|
|
virtual void TransferBlock(void * pData,unsigned nSize) = 0;
|
|
};
|
|
|
|
/*******************************/
|
|
/* Original File: iffArchO.hpp */
|
|
/*******************************/
|
|
|
|
class ArchvOut : public Archive, public SerialData
|
|
{
|
|
public:
|
|
ArchvOut() : Archive(false), m_pMedium(NULL) {}
|
|
~ArchvOut();
|
|
|
|
signed GetSize() const;
|
|
|
|
Archive * OpenSubArchive(unsigned nSize = 0);
|
|
|
|
void CloseSubArchive(Archive * pSub);
|
|
|
|
void Open(::MediaMedium * pMedium);
|
|
void Close();
|
|
|
|
void Transfer(RGBTriple &);
|
|
void Transfer(BYTE &);
|
|
void Transfer(UBYTE &);
|
|
void Transfer(INT16 &);
|
|
void Transfer(UINT16 &);
|
|
void Transfer(INT32 &);
|
|
void Transfer(UINT32 &);
|
|
void Transfer(INT64 &);
|
|
void Transfer(UINT64 &);
|
|
void Transfer(ID &);
|
|
|
|
void TransferBlock(void * pData,unsigned nSize);
|
|
|
|
private:
|
|
::MediaMedium * m_pMedium;
|
|
};
|
|
|
|
inline signed ArchvOut::GetSize() const
|
|
{
|
|
return GetDataSize();
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(RGBTriple & n)
|
|
{
|
|
Append(n.r);
|
|
Append(n.g);
|
|
Append(n.b);
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(BYTE & n)
|
|
{
|
|
Append(n);
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(UBYTE & n)
|
|
{
|
|
Append(n);
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(INT16 & n)
|
|
{
|
|
Append(static_cast<BYTE>(n >> 8));
|
|
Append(static_cast<BYTE>(n));
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(UINT16 & n)
|
|
{
|
|
Append(static_cast<UBYTE>(n >> 8));
|
|
Append(static_cast<UBYTE>(n));
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(INT32 & n)
|
|
{
|
|
Append(static_cast<BYTE>(n >> 24));
|
|
Append(static_cast<BYTE>(n >> 16));
|
|
Append(static_cast<BYTE>(n >> 8));
|
|
Append(static_cast<BYTE>(n));
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(UINT32 & n)
|
|
{
|
|
Append(static_cast<UBYTE>(n >> 24));
|
|
Append(static_cast<UBYTE>(n >> 16));
|
|
Append(static_cast<UBYTE>(n >> 8));
|
|
Append(static_cast<UBYTE>(n));
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(INT64 & n)
|
|
{
|
|
Append(static_cast<BYTE>(n >> 56));
|
|
Append(static_cast<BYTE>(n >> 48));
|
|
Append(static_cast<BYTE>(n >> 40));
|
|
Append(static_cast<BYTE>(n >> 32));
|
|
Append(static_cast<BYTE>(n >> 24));
|
|
Append(static_cast<BYTE>(n >> 16));
|
|
Append(static_cast<BYTE>(n >> 8));
|
|
Append(static_cast<BYTE>(n));
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(UINT64 & n)
|
|
{
|
|
Append(static_cast<UBYTE>(n >> 56));
|
|
Append(static_cast<UBYTE>(n >> 48));
|
|
Append(static_cast<UBYTE>(n >> 40));
|
|
Append(static_cast<UBYTE>(n >> 32));
|
|
Append(static_cast<UBYTE>(n >> 24));
|
|
Append(static_cast<UBYTE>(n >> 16));
|
|
Append(static_cast<UBYTE>(n >> 8));
|
|
Append(static_cast<UBYTE>(n));
|
|
}
|
|
|
|
inline void ArchvOut::Transfer(ID & n)
|
|
{
|
|
Append(&n,4);
|
|
}
|
|
|
|
inline void ArchvOut::TransferBlock(void * pData,unsigned nSize)
|
|
{
|
|
Append(pData,nSize);
|
|
}
|
|
|
|
#endif // ! IFF_READ_ONLY
|
|
|
|
/*******************************/
|
|
/* Original File: iffArchI.hpp */
|
|
/*******************************/
|
|
|
|
#ifdef IFF_READ_ONLY
|
|
#define _IFF_ARCHI_BASE Unknown
|
|
#define _IFF_ARCHI_GENR ArchvIn
|
|
#define _IFF_ARCHI_FLAG m_bIsLoading
|
|
#define _IFF_ARCHI_INIT ,m_bError(false)
|
|
#else // ! IFF_READ_ONLY
|
|
#define _IFF_ARCHI_BASE Archive
|
|
#define _IFF_ARCHI_GENR Archive
|
|
#define _IFF_ARCHI_FLAG Archive
|
|
#define _IFF_ARCHI_INIT
|
|
#endif // ! IFF_READ_ONLY
|
|
|
|
class ArchvIn : public _IFF_ARCHI_BASE
|
|
{
|
|
public:
|
|
ArchvIn() : _IFF_ARCHI_FLAG(true), m_pMedium(NULL) _IFF_ARCHI_INIT {}
|
|
~ArchvIn();
|
|
|
|
#ifdef IFF_READ_ONLY
|
|
bool const m_bIsLoading;
|
|
bool m_bError;
|
|
#endif // IFF_READ_ONLY
|
|
|
|
signed GetSize() const;
|
|
|
|
_IFF_ARCHI_GENR * OpenSubArchive(unsigned nSize = 0);
|
|
|
|
void CloseSubArchive(_IFF_ARCHI_GENR * pSub);
|
|
|
|
void Open(::MediaMedium * pMedium);
|
|
void Close();
|
|
|
|
void Transfer(RGBTriple &);
|
|
void Transfer(BYTE &);
|
|
void Transfer(UBYTE &);
|
|
void Transfer(INT16 &);
|
|
void Transfer(UINT16 &);
|
|
void Transfer(INT32 &);
|
|
void Transfer(UINT32 &);
|
|
void Transfer(INT64 &);
|
|
void Transfer(UINT64 &);
|
|
void Transfer(ID &);
|
|
|
|
void TransferBlock(void * pData,unsigned nSize);
|
|
|
|
private:
|
|
ArchvIn(ArchvIn * pParent, unsigned nSize);
|
|
|
|
::MediaMedium * m_pMedium;
|
|
signed m_nBytesRemaining;
|
|
unsigned m_nEndPos;
|
|
};
|
|
|
|
#ifdef IFF_READ_ONLY
|
|
typedef ArchvIn Archive;
|
|
#endif // IFF_READ_ONLY
|
|
|
|
inline signed ArchvIn::GetSize() const
|
|
{
|
|
return m_nBytesRemaining;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(RGBTriple & n)
|
|
{
|
|
m_nBytesRemaining -= 3;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
::MediaRead(m_pMedium, &n.r);
|
|
::MediaRead(m_pMedium, &n.g);
|
|
::MediaRead(m_pMedium, &n.b);
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(UBYTE & n)
|
|
{
|
|
m_nBytesRemaining -= 1;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
::MediaRead(m_pMedium, &n);
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(BYTE & n)
|
|
{
|
|
m_nBytesRemaining -= 1;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
::MediaRead(m_pMedium, &n);
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(UINT16 & n)
|
|
{
|
|
m_nBytesRemaining -= 2;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
UBYTE byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n = byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(INT16 & n)
|
|
{
|
|
m_nBytesRemaining -= 2;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
BYTE byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n = byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(UINT32 & n)
|
|
{
|
|
m_nBytesRemaining -= 4;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
UBYTE byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n = byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(INT32 & n)
|
|
{
|
|
m_nBytesRemaining -= 4;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
BYTE byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n = byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(UINT64 & n)
|
|
{
|
|
m_nBytesRemaining -= 8;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
UBYTE byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n = byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(INT64 & n)
|
|
{
|
|
m_nBytesRemaining -= 8;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
BYTE byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n = byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
::MediaRead(m_pMedium, &byte);
|
|
n <<= 8;
|
|
n |= byte;
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::Transfer(ID & n)
|
|
{
|
|
m_nBytesRemaining -= 4;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
// cast pointer to pointer to 4 byte data type to force 4 byte 'fast' read
|
|
::MediaRead(m_pMedium, reinterpret_cast<UINT32 *>(&n.m_sID[0]));
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
inline void ArchvIn::TransferBlock(void * pData,unsigned nSize)
|
|
{
|
|
m_nBytesRemaining -= nSize;
|
|
if (m_nBytesRemaining >= 0)
|
|
{
|
|
m_pMedium->ReadBlock(pData,nSize);
|
|
if (m_pMedium->m_fError) m_bError = true;
|
|
}
|
|
else m_bError = true;
|
|
}
|
|
|
|
/*******************************/
|
|
/* Original File: iffSrlOb.hpp */
|
|
/*******************************/
|
|
|
|
class SerializableObj : public Unknown
|
|
{
|
|
public:
|
|
virtual void Serialize(Archive * pArchv) = 0;
|
|
};
|
|
|
|
/*******************************/
|
|
/* Original File: iffChunk.hpp */
|
|
/*******************************/
|
|
|
|
class Chunk : public SerializableObj
|
|
{
|
|
public:
|
|
ID m_idCk;
|
|
|
|
Chunk * GetProperty(ID idProp) const;
|
|
|
|
virtual bool IsUnknown() const { return false; }
|
|
|
|
void Write(Archive * pArchv);
|
|
static Chunk * Load(ID idParent, Archive * pArchv, ID idChunk = ID_ANY, bool bKnown = true);
|
|
|
|
static Chunk * DynCreate(ID idParent, ID idChunk);
|
|
static void Register(ID idParent, ID idChunk, Chunk * (* pfnCreate) () );
|
|
|
|
Composite const * GetParent() const { return m_pParent; }
|
|
|
|
protected:
|
|
Chunk() : m_pParent(NULL) {}
|
|
|
|
private:
|
|
Composite const * m_pParent; // mot reference counted
|
|
ChildNode const * m_pNode; // not reference counted either
|
|
|
|
friend class Composite;
|
|
};
|
|
|
|
#define IFF_IMPLEMENT_DYNCREATE(idParent,idChunk,tokenClassName) _IFF_IMPLEMENT_DYNCREATE_LINE_EX(idParent,idChunk,tokenClassName,__LINE__)
|
|
#define _IFF_IMPLEMENT_DYNCREATE_LINE_EX(idParent,idChunk,tokenClassName,nLine) _IFF_IMPLEMENT_DYNCREATE_LINE(idParent,idChunk,tokenClassName,nLine)
|
|
|
|
#define _IFF_IMPLEMENT_DYNCREATE_LINE(idParent,idChunk,tokenClassName,nLine) \
|
|
static IFF::Chunk * CreateClassObject ## tokenClassName ##_## nLine () { \
|
|
IFF::Chunk * pChunk = new IFF::tokenClassName; \
|
|
pChunk->m_idCk = idChunk; \
|
|
return pChunk; \
|
|
} \
|
|
class RegisterChunkClass ## tokenClassName ##_## nLine { \
|
|
public: RegisterChunkClass ## tokenClassName ##_## nLine () { \
|
|
IFF::Chunk::Register(idParent , idChunk , CreateClassObject ## tokenClassName ##_## nLine); \
|
|
} \
|
|
} rcc ## tokenClassName ##_## nLine;
|
|
|
|
/*******************************/
|
|
/* Original File: iffBlock.hpp */
|
|
/*******************************/
|
|
|
|
class ChildNode : public Unknown
|
|
{
|
|
public:
|
|
Chunk * GetChunk() const { return m_pChunk; }
|
|
private:
|
|
ChildNode * m_pNext;
|
|
ChildNode * m_pPrev;
|
|
Chunk * m_pChunk;
|
|
|
|
friend class Composite;
|
|
};
|
|
|
|
class Composite : public Chunk
|
|
{
|
|
public:
|
|
ID m_idData;
|
|
|
|
Composite() : m_pFirst(NULL), m_pLast(NULL) {}
|
|
virtual ~Composite();
|
|
|
|
ChildNode * GetFirstChild() const { return m_pFirst; }
|
|
ChildNode * GetFirstChild(ID idMatch) const;
|
|
ChildNode * GetLastChild() const { return m_pLast; }
|
|
ChildNode * GetLastChild(ID idMatch) const;
|
|
static ChildNode * GetNextChild(ChildNode const * pNode) { return pNode->m_pNext; }
|
|
static ChildNode * GetNextChild(ChildNode const * pNode, ID idMatch);
|
|
static ChildNode * GetPrevChild(ChildNode const * pNode) { return pNode->m_pPrev; }
|
|
static ChildNode * GetPrevChild(ChildNode const * pNode, ID idMatch);
|
|
|
|
Chunk * GetProperty(ChildNode const * pNode, ID idProp) const;
|
|
|
|
void DeleteChild(ChildNode * pNode);
|
|
void DeleteAllChildren();
|
|
|
|
ChildNode * InsertChildFirst(Chunk * pChunk);
|
|
ChildNode * InsertChildLast(Chunk * pChunk);
|
|
ChildNode * InsertChildAfter(ChildNode * pNode, Chunk * pChunk);
|
|
ChildNode * InsertChildBefore(ChildNode * pNode, Chunk * pChunk);
|
|
|
|
// pfnCallback should return true to continue the enumeration, false to finish
|
|
virtual bool EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const;
|
|
|
|
protected:
|
|
virtual void Serialize(Archive * pArchv);
|
|
|
|
virtual Chunk * LoadChunk(Archive * pArchv) const;
|
|
virtual bool IsValidChildID(ID id) const;
|
|
|
|
private:
|
|
ChildNode * m_pFirst;
|
|
ChildNode * m_pLast;
|
|
};
|
|
|
|
class Form : public Composite
|
|
{
|
|
public:
|
|
Form() { m_idCk = "FORM"; }
|
|
protected:
|
|
virtual bool IsValidChildID(ID id) const;
|
|
};
|
|
|
|
class Cat : public Composite
|
|
{
|
|
public:
|
|
Cat() { m_idCk = "CAT "; }
|
|
virtual bool EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const;
|
|
protected:
|
|
virtual bool IsValidChildID(ID id) const;
|
|
};
|
|
|
|
class List : public Composite
|
|
{
|
|
public:
|
|
List() { m_idCk = "LIST"; }
|
|
virtual bool EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const;
|
|
protected:
|
|
virtual bool IsValidChildID(ID id) const;
|
|
};
|
|
|
|
class Prop : public Composite
|
|
{
|
|
public:
|
|
Prop() { m_idCk = "PROP"; }
|
|
protected:
|
|
virtual bool IsValidChildID(ID id) const;
|
|
};
|
|
|
|
/*******************************/
|
|
/* Original File: iffMscCk.hpp */
|
|
/*******************************/
|
|
|
|
class MiscChunk : public Chunk
|
|
{
|
|
public:
|
|
MiscChunk(ID id)
|
|
#ifndef IFF_READ_ONLY
|
|
: m_pData(NULL)
|
|
#endif // ! IFF_READ_ONLY
|
|
{
|
|
m_idCk = id;
|
|
}
|
|
|
|
virtual bool IsUnknown() const { return true; }
|
|
|
|
protected:
|
|
virtual void Serialize(Archive * pArchv);
|
|
#ifndef IFF_READ_ONLY
|
|
virtual ~MiscChunk();
|
|
#endif // ! IFF_READ_ONLY
|
|
|
|
private:
|
|
#ifndef IFF_READ_ONLY
|
|
BYTE * m_pData;
|
|
unsigned m_nSize;
|
|
#endif // ! IFF_READ_ONLY
|
|
};
|
|
|
|
/******************************/
|
|
/* Original File: iffFile.hpp */
|
|
/******************************/
|
|
|
|
class GenericFile : public SerializableObj
|
|
{
|
|
public:
|
|
#ifndef IFF_READ_ONLY
|
|
GenericFile() : m_pszFileName(NULL) {}
|
|
virtual ~GenericFile() { if (m_pszFileName) delete[] m_pszFileName; }
|
|
#endif
|
|
|
|
bool Load(TCHAR const * pszFileName);
|
|
bool Load(::MediaMedium * pMedium);
|
|
|
|
#ifndef IFF_READ_ONLY
|
|
bool Write(TCHAR const * pszFileName = NULL);
|
|
bool Write(::MediaMedium * pMedium);
|
|
#endif // ! IFF_READ_ONLY
|
|
|
|
private:
|
|
#ifndef IFF_READ_ONLY
|
|
TCHAR * m_pszFileName;
|
|
#endif // ! IFF_READ_ONLY
|
|
};
|
|
|
|
class File : public GenericFile
|
|
{
|
|
public:
|
|
virtual ~File();
|
|
File() : m_pContents(NULL) {}
|
|
|
|
Composite * GetContents() const;
|
|
void SetContents(Composite * pContents);
|
|
|
|
protected:
|
|
virtual void Serialize(Archive * pArchv);
|
|
|
|
private:
|
|
ID m_idType;
|
|
Composite * m_pContents;
|
|
};
|
|
|
|
inline Composite * File::GetContents() const
|
|
{
|
|
return m_pContents;
|
|
}
|
|
|
|
inline void File::SetContents(Composite * pContents)
|
|
{
|
|
if (m_pContents) m_pContents->Release();
|
|
if (pContents)
|
|
{
|
|
pContents->AddRef();
|
|
m_idType = pContents->m_idCk;
|
|
}
|
|
m_pContents = pContents;
|
|
}
|
|
|
|
// Have a static object of this in each file:
|
|
// It will detect if some files are compiled with
|
|
// IFF_READ_ONLY defined differently to each other
|
|
static class ConsistencyCheck
|
|
{
|
|
public: inline ConsistencyCheck()
|
|
{
|
|
#ifdef IFF_READ_ONLY
|
|
static bool bReadOnly = true;
|
|
if (!bReadOnly)
|
|
#else
|
|
static bool bReadOnly = false;
|
|
if (bReadOnly)
|
|
#endif
|
|
{
|
|
DisplayMessage
|
|
(
|
|
#ifdef NDEBUG
|
|
TEXT("Error"),
|
|
TEXT("IFF_READ_ONLY definition not consistent")
|
|
#else
|
|
TEXT("IFF Compile Option Error"),
|
|
TEXT("Some files which #include \"iff.hpp\"\n")
|
|
TEXT("have the macro IFF_READ_ONLY defined\n")
|
|
TEXT("and some don't.\n\n")
|
|
TEXT("Please ensure this is consistent and recompile.")
|
|
#endif
|
|
);
|
|
exit(-45);
|
|
}
|
|
}
|
|
}
|
|
consistencyCheck;
|
|
|
|
} // namespace IFF
|
|
|
|
#endif // ! _INCLUDED_IFF_HPP_
|