Changes

Jump to navigation Jump to search
10,752 bytes added ,  00:21, 1 July 2017
Added basic data types
Line 1: Line 1:  
This page details the technical '''inner workings of ManiaPlanet''' (and the original TrackMania). It describes the game's classes, data structures and functions, and is as such geared towards reverse engineers and programmers.
 
This page details the technical '''inner workings of ManiaPlanet''' (and the original TrackMania). It describes the game's classes, data structures and functions, and is as such geared towards reverse engineers and programmers.
   −
This documentation goes together well with [[#Tools|TM2Unlimiter]].
+
== Basic data types ==
 +
Nadeo uses its own primitive data types in its game engine. Since they can't be reversed, they are not used on this page and are listed here only for the sake of completeness.
 +
 
 +
typedef int Integer;
 +
typedef unsigned int Bool;
 +
typedef unsigned char Nat8;
 +
typedef unsigned short Nat16;
 +
typedef unsigned int Natural, Nat32;
 +
typedef unsigned __int64 Nat64;
 +
typedef float Real, Real32;
    
== Basic data structures ==
 
== Basic data structures ==
Line 83: Line 92:  
* If bits 30 and 31 are set, the Id is empty (null). Typically ''value'' is -1 in this case.
 
* If bits 30 and 31 are set, the Id is empty (null). Typically ''value'' is -1 in this case.
   −
<div class="mw-collapsible mw-collapsed">
   
Ids are managed by the class CMwId:
 
Ids are managed by the class CMwId:
<div class="mw-collapsible-content">
   
  class CMwId
 
  class CMwId
 
  {
 
  {
 
  public:
 
  public:
     __thiscall CMwId(void);  // Initializes the ID with the value -1 (Unassigned)
+
     CMwId(void);  // Initializes the ID with the value -1 (Unassigned).
     __thiscall CMwId(class CMwId const &);  // Initializes the id with the ID of the passed class
+
     CMwId(CMwId const &);  // Initializes the id with the ID of the passed class.
     __thiscall ~CMwId(void);
+
     ~CMwId(void);
 
   
 
   
     static class CMwId * Unassigned;  // Points to the first entry in the table (Unassigned)
+
     static CMwId * Unassigned;  // Points to the first entry in the table (Unassigned).
     static void __cdecl StaticInit(void);  // Called from CGbxApp::Init. Creates the name table. Creates a first ID with the value -1 (Unassigned) and adds it to the table.
+
     static void StaticInit(void);  // Called from CGbxApp::Init. Creates the name table. Creates a first ID with the value -1 (Unassigned) and adds it to the table.
     static void __cdecl StaticRelease(void);  // Called from CGbxApp::Destroy. Releases the name table.
+
     static void StaticRelease(void);  // Called from CGbxApp::Destroy. Releases the name table.
 
   
 
   
     static class CMwId __cdecl CreateFromLocalIndex(unsigned long); // Calls CMwId::CMwId and sets the ID to the passed index.
+
     static CMwId CreateFromLocalIndex(unsigned long);   // Calls CMwId::CMwId and sets the ID to the passed index.
     static class CMwId __cdecl CreateFromTypeAndIndex(unsigned long); // Calls CMwId::CMwId and sets the ID to the passed index.
+
     static CMwId CreateFromTypeAndIndex(unsigned long); // Calls CMwId::CMwId and sets the ID to the passed index.
     static class CMwId __cdecl CreateFromLocalName(char const *); // Calls CMwId::CMwId and adds the passed name to the name table using SetLocalName (bit 30 of the ID is set).
+
     static CMwId CreateFromLocalName(char const *);     // Calls CMwId::CMwId and adds the passed name to the name table using SetLocalName (bit 30 of the ID is set).
     static class CMwId __cdecl CreateFromUUIdName(char const *); // Calls CMwId::CMwId and adds the passed name to the name table using AddName (bit 31 of the ID is set).
+
     static CMwId CreateFromUUIdName(char const *);     // Calls CMwId::CMwId and adds the passed name to the name table using AddName (bit 31 of the ID is set).
 
   
 
   
     void __thiscall SetLocalName(char const *);  // Sets the ID to -1 if the name is "Unassigned"; otherwise, adds the name to the table using AddName and sets bit 30 of the ID.
+
     void SetLocalName(char const *);  // Sets the ID to -1 if the name is "Unassigned"; otherwise, adds the name to the table using AddName and sets bit 30 of the ID.
     void __thiscall SetLocalName(class CFastStringInt const &);  // Calls CFastStringInt::GetUtf8 and than SetLocalName.
+
     void SetLocalName(CFastStringInt const &);  // Calls CFastStringInt::GetUtf8 and then SetLocalName.
 
   
 
   
     char const * __thiscall GetString(void)const;  // Gets the string to the ID if bit 30 or 31 is set; otherwise, NULL is returned.
+
     char const * GetString(void)const;  // Gets the string of the ID if bit 30 or 31 is set; otherwise, NULL is returned.
 
   
 
   
     void __thiscall GetName(class CFastString &)const;  // Returns either the name of the ID using GetString, "Unassigned" if the ID is -1 or "Id<number>" if ID represents a number.
+
     void GetName(CFastString &)const;  // Returns either the name of the ID using GetString, "Unassigned" if the ID is -1 or "Id<number>" if ID represents a number.
     void __thiscall GetName(class CFastStringInt &)const;
+
     void GetName(CFastStringInt &)const;
     class CFastString const __thiscall GetName(void)const;
+
     class CFastString const GetName(void)const;
 
   
 
   
     void __thiscall Archive(class CClassicArchive &);  // Serializes the ID. See "[[GBX#Primitives|lookbackstring]]" on the [[GBX]] page for some details.
+
     void Archive(CClassicArchive &);  // Serializes the ID. See "[[GBX#Primitives|lookbackstring]]" on the [[GBX]] page for some details.
 
   
 
   
 
  private:
 
  private:
     static struct SMwIdInternal * s_NameTable;  // Points to the name table
+
     static SMwIdInternal * s_NameTable;  // Points to the name table.
     static unsigned long __cdecl AddName(char const *);  // Adds the name to the name table
+
     static unsigned long AddName(char const *);  // Adds the name to the name table.
     static void __cdecl DeleteArchiveUserData(class CClassicArchive *);
+
     static void DeleteArchiveUserData(CClassicArchive *);
 
  };
 
  };
</div>
  −
</div>
      
===Identifier===
 
===Identifier===
 
Stores three Ids that together describe an object. Typically, this is the name of the object, the [[collection ID]], and the author name.
 
Stores three Ids that together describe an object. Typically, this is the name of the object, the [[collection ID]], and the author name.
    +
struct Ident
 +
{
 +
    Id id;          // Name. Could be the name of a map, name of a block, path of a file etc.
 +
    Id collection;  // Environment. In ManiaPlanet, 0xC = Canyon and 0xCA = Storm.
 +
    Id author;      // Author name (typically "Nadeo")
 +
};
 +
 +
Identifiers are managed by the class SGameCtnIdentifier:
 
  struct SGameCtnIdentifier
 
  struct SGameCtnIdentifier
 
  {
 
  {
     MwId uid;         // Name. Could be the name of a map, name of a block, path of a file etc.
+
public:
     MwId collection;  // Environment. In ManiaPlanet, 0xC = Canyon and 0xCA = Storm.
+
     SGameCtnIdentifier(void); // Calls CMwId::CMwId for all three IDs of the Ident.
     MwId author;      // Author name (typically "Nadeo")
+
     SGameCtnIdentifier(SGameCtnIdentifier const &);  // Calls CMwId::CMwId(class CMwId const &) for all three IDs of the Ident.
 +
    ~SGameCtnIdentifier(void);
 +
 +
    int operator==(SGameCtnIdentifier const &)const;  // Compares the first two IDs of the Ident.
 +
     static int sCompareCollectionAndId(SGameCtnIdentifier const *, SGameCtnIdentifier const *); // Compares the names of the first two IDs of the Ident using CMwId::GetName.
 +
 +
     void Archive(CClassicArchive &);  // Serializes the Ident. See "[[GBX#Primitives|meta]]" on the [[GBX]] page for details.
 
  };
 
  };
  −
Identifiers are managed by the class SGameCtnIdentifier.
      
===Delegate===
 
===Delegate===
Line 147: Line 164:  
  struct Color
 
  struct Color
 
  {
 
  {
     int r;
+
     float r;
     int g;
+
     float g;
     int b;
+
     float b;
 
  };
 
  };
   Line 235: Line 252:  
  {
 
  {
 
  public:
 
  public:
     virtual m0();
+
     CMwNod(void);
     virtual ~CMwNod();
+
    CMwNod(CMwNod const &);
     virtual CMwClassInfo* GetClassInfo();     // Gets information about the object's class
+
     virtual ~CMwNod(void);
     virtual int GetClassID();
+
     virtual CMwClassInfo const * MwGetClassInfo(void)const; // Gets information about the object's class
     virtual bool Is(int classID);   // Returns true if the object's class is equal to or derives from
+
     virtual unsigned long GetMwClassId(void)const;
                                    // the specified class
+
     virtual bool MwIsKindOf(unsigned long classID)const;   // Returns true if the object's class is equal to or derives from the specified class
     virtual SGameCtnIdentifier* GetIdentifier();     // Returns meta information about the object, like name and author
+
     virtual CMwId const * MwGetId(void)const;               // Returns meta information about the object, like name and author
     virtual void SetUID(char* psz); // Sets the name of the object (affects GetIdentifier())
+
     virtual void SetIdName(char const * psz);               // Sets the name of the object (affects MwGetId())
     virtual void m1C();
+
     virtual void MwIsKilled(CMwNod *);
     virtual void m20();
+
     virtual void MwIsUnreferenced(CMwNod *);
     virtual void GetPropertyIndirect(CMwStack* pStack, void** ppValue);   // Gets the value of a property
+
     virtual unsigned long VirtualParam_Get(CMwStack * pStack, CMwValueStd * ppValue); // Gets the value of a property
     virtual void CallMethodIndirect(CMwStack* pStack, void* pValue);     // Calls a method or sets a property
+
     virtual unsigned long VirtualParam_Set(CMwStack * pStack, void * pValue);         // Calls a method or sets a property
     virtual void m2C();
+
     virtual unsigned long VirtualParam_Add(CMwStack * pStack, void * pValue);
     virtual void m30();
+
     virtual unsigned long VirtualParam_Sub(CMwStack * pStack, void * pValue);
     virtual void ReadWriteChunks(CClassicArchive* pArchive);             // (De)serializes the nod from a stream
+
     virtual CMwNod * Archive(CClassicArchive & pArchive);                   // (De)serializes the [[GBX#Reading_the_body|nod]] from a stream
     virtual void ReadWriteChunk(CClassicArchive* pArchive, int chunkID);  // (De)serializes a single chunk from a stream
+
     virtual void Chunk(CClassicArchive & pArchive, unsigned long chunkID);  // (De)serializes a single chunk from a stream
     virtual void m3C();
+
     virtual unsigned long GetChunkInfo(unsigned long chunkID)const;         // Gets chunk-specific flags, e.g. if it is skippable
    virtual int GetChunkLoadFlags(int chunkID);       // Gets chunk-specific flags, e.g. if it is skippable
+
     virtual unsigned long GetUidChunkFromIndex(unsigned long index)const;   // Used during serialization: which chunk to write next
     virtual int GetChunkIDByIndex(int index);         // Used during serialization: which chunk to write next
+
     virtual unsigned long GetChunkCount(void)const; // Used during serialization: how many chunks to write
     virtual int GetNumChunks();                       // Used during serialization: how many chunks to write
+
     virtual void OnNodLoaded(void);                 // Called after the last chunk has been read/written
     virtual void OnFinishReadWriteChunks();           // Called after the last chunk has been read/written
+
     virtual void CreateDefaultData(void);
     virtual void m50();
+
     virtual void OnPackAvailable(CSystemFid *, CSystemFid *);
     virtual void m54();
+
     virtual void ApplyFidParameters(CSystemFidParameters const *, CSystemFidParameters *, CFastBuffer<SManuallyLoadedFid> &);
     virtual void m58();
+
     virtual int OnCrashDump(CFastString &);
     virtual void m5C();
+
     virtual void CopyFrom(CMwNod *);
     virtual void m60();
+
     virtual void HeaderChunk(CClassicArchive & pArchive, unsigned long & pHeaderChunkID, bool & pbLight); // Writes a header chunk to a stream
     virtual void WriteHeaderChunk(CClassicArchive* pArchive, int* pHeaderChunkID, bool* pbLight);
+
     virtual unsigned long GetUidHeaderChunkFromIndex(unsigned long index)const; // Used during serialization: which header chunk to write next
                                                      // Writes a header chunk to a stream
+
     virtual unsigned long GetHeaderChunkCount(void)const;                       // Used during serialization: how many header chunks to write
     virtual int GetHeaderChunkIDByIndex(int index);   // Used during serialization: which header chunk to write next
+
    virtual unsigned long GetUidMessageFromIndex(unsigned long index)const;
     virtual int GetNumHeaderChunks();                 // Used during serialization: how many header chunks to write
+
    virtual unsigned long GetMessageCount(void)const;
 +
    virtual void MwReceiveMessage(unsigned long const &, CMwNod *, unsigned long *);
 +
 +
    unsigned long Param_Get(CMwStack * pStack, CMwValueStd * ppValue);
 +
    unsigned long Param_Set(CMwStack * pStack, void * pValue);
 +
    unsigned long Param_Add(CMwStack * pStack, void * pValue);
 +
    unsigned long Param_Sub(CMwStack * pStack, void * pValue);
 +
    unsigned long Param_Check(CMwStack * pStack);
 +
    unsigned long Param_Set(CFastString const &, CFastStringInt const &);
 +
 +
    unsigned long MwAddRef(void);      // Increments countRef
 +
    unsigned long MwRelease(void);    // Decrements countRef. If zero, the object and all dependants are destroyed.
 +
 +
    void MwAddDependant(CMwNod *)const;
 +
    void MwAddReceiver(CMwNod *);
 +
    void MwSubDependant(CMwNod *)const;
 +
    void MwSubDependantSafe(CMwNod *)const;
 +
    void MwFinalSubDependant(CMwNod *)const;
 +
    void DependantSendMwIsKilled(void);
 
   
 
   
 
  private:
 
  private:
     int refcount;               // Reference count. If this reaches zero, the object is destroyed.
+
     int countRef;                     // Reference count. If this reaches zero, the object is destroyed.
     CSystemFid* pFid;           // File which the object originates from (if it was deserialized; NULL otherwise)
+
     CSystemFid* pFid;                 // File which the object originates from (if it was deserialized; NULL otherwise)
     FastBuffer<CMwNod*>* pList;  // Optional list of child objects
+
     FastBuffer<CMwNod*>* pDependants;  // Optional list of child objects
 
     int unknown;
 
     int unknown;
 
  };
 
  };
 
   
 
   
GetPropertyIndirect() and CallMethodIndirect() should not be used directly. These only exist for handling calculated properties (where the value doesn't come directly from a field in the class but is calculated). Instead, use the nonvirtual wrapper methods GetProperty() and CallMethod() which handle both field properties and calculated properties.
+
VirtualParam_Get() and VirtualParam_Set() should not be used directly. These only exist for handling calculated properties (where the value doesn't come directly from a field in the class but is calculated). Instead, use the nonvirtual wrapper methods Param_Get() and Param_Set() which handle both field properties and calculated properties.
    
===Runtime class inspection===
 
===Runtime class inspection===
Line 447: Line 482:  
Performing late binding in ManiaPlanet requires three objects:
 
Performing late binding in ManiaPlanet requires three objects:
 
* A CMwNod: the object on which you want to perform the action.
 
* A CMwNod: the object on which you want to perform the action.
* A CMwMemberInfo: the object that describes the member you want to access. This can be retrieved by getting the CMwNod's CMwClassInfo (pNod->GetClassInfo()) and looping over the class's members until you find the one with the name you are looking for.
+
* A CMwMemberInfo: the object that describes the member you want to access. This can be retrieved by getting the CMwNod's CMwClassInfo (pNod->MwGetClassInfo()) and looping over the class's members until you find the one with the name you are looking for.
 
* A CMwStack: wraps the CMwMemberInfo. In addition, when calling a method, this contains any method arguments.
 
* A CMwStack: wraps the CMwMemberInfo. In addition, when calling a method, this contains any method arguments.
   Line 464: Line 499:  
  List < class CPlugSolid* >& CFuncClouds::GetSolidFids () const
 
  List < class CPlugSolid* >& CFuncClouds::GetSolidFids () const
 
  {
 
  {
     static CMwMemberInfo* pMemberInfo = GetClassInfo ()->GetMemberInfo ( "SolidFids" );
+
     static CMwMemberInfo* pMemberInfo = MwGetClassInfo ()->GetMemberInfo ( "SolidFids" );
 
     struct
 
     struct
 
     {
 
     {
Line 485: Line 520:  
  void CFuncClouds::SetSolidFids ( List < class CPlugSolid* >& value )
 
  void CFuncClouds::SetSolidFids ( List < class CPlugSolid* >& value )
 
  {
 
  {
     static CMwMemberInfo* pMemberInfo = GetClassInfo ()->GetMemberInfo ( "SolidFids" );
+
     static CMwMemberInfo* pMemberInfo = MwGetClassInfo ()->GetMemberInfo ( "SolidFids" );
 
     CMwStack stack;
 
     CMwStack stack;
 
     stack.Push ( pMemberInfo );
 
     stack.Push ( pMemberInfo );
Line 502: Line 537:  
  uint CGameCtnEditorPluginScriptHandler::CanPlaceBlock ( class CGameCtnBlockInfo* pBlockModel, int3 coord, uint dir )
 
  uint CGameCtnEditorPluginScriptHandler::CanPlaceBlock ( class CGameCtnBlockInfo* pBlockModel, int3 coord, uint dir )
 
  {
 
  {
     static CMwMemberInfo* pMemberInfo = GetClassInfo ()->GetMemberInfo ( "CanPlaceBlock" );
+
     static CMwMemberInfo* pMemberInfo = MwGetClassInfo ()->GetMemberInfo ( "CanPlaceBlock" );
 
     uint uiVariantIndex;
 
     uint uiVariantIndex;
 
     CMwStack stack;
 
     CMwStack stack;
Line 525: Line 560:  
         ITEM_OBJECT    = 0x10000002,  // CMwNod*
 
         ITEM_OBJECT    = 0x10000002,  // CMwNod*
 
         ITEM_ENUM      = 0x10000003,
 
         ITEM_ENUM      = 0x10000003,
         ITEM_ISO4      = 0x10000004,   // Iso4*
+
         ITEM_ISO4      = 0x10000004,
 
         ITEM_VEC2      = 0x10000005,
 
         ITEM_VEC2      = 0x10000005,
 
         ITEM_VEC3      = 0x10000006,
 
         ITEM_VEC3      = 0x10000006,
Line 554: Line 589:  
Every CMwNod can be read from and written to a file. Typically this is a [[GBX|.gbx]] file, but it's also possible to "deserialize" a .png file into a CPlugFilePng instance. Serializing and deserializing is easy to do with the following methods:
 
Every CMwNod can be read from and written to a file. Typically this is a [[GBX|.gbx]] file, but it's also possible to "deserialize" a .png file into a CPlugFilePng instance. Serializing and deserializing is easy to do with the following methods:
   −
  void CreateNodFromFid(CMwNod** ppResultNod, CSystemFid* pFid, int flags = 7);
+
  int CSystemArchiveNod::LoadFromFid(CMwNod** ppResultNod, CSystemFid* pFid, enum EArchive = 7);
  void ReadNodFromFile(StringInt* pwstrFilePath, CMwNod** ppResultNod, CSystemFids* pFolder, int flags);
+
  int CSystemArchiveNod::LoadFileFrom(CFastStringInt* pwstrFilePath, CMwNod** ppResultNod, CSystemFids* pFolder, enum EArchive);
  void WriteNodToFile(StringInt* pwstrFilePath, CMwNod* pNod, CSystemFids* pFolder, int flags);
+
  int CSystemArchiveNod::SaveFile(CFastStringInt* pwstrFilePath, CMwNod* pNod, CSystemFids* pFolder, enum EArchive, int);
    
== I/O ==
 
== I/O ==
Line 655: Line 690:  
  class CSystemFid : public CMwNod          // Base class for files
 
  class CSystemFid : public CMwNod          // Base class for files
 
  {
 
  {
 +
public:
 +
    int ArchiveHeaderUserData(CClassicArchive *);        // Reads or writes header user data
 +
    void BuildHeaderUserData(CSystemArchiveNod const &);  // Prepares the header chunk data for writing
 +
 +
private:
 +
    int HeaderUserDataCreateFromArchive(CClassicArchive *, unsigned long size);  // Reads the header chunk data
 +
 
  private:
 
  private:
 
     int unknown0;
 
     int unknown0;
Line 712: Line 754:     
===Loading files===
 
===Loading files===
Loading a file in ManiaPlanet is quite easy: you get the CSystemFid's pLoader and call its GetBuffer() method, which returns a stream object ready for reading (see Streams section). Once you're done reading, call the loader's FreeBuffer() method to release the stream.
+
Loading a file in ManiaPlanet is quite easy: you get the CSystemFid's pLoader and call its OpenBuffer() method, which returns a stream object ready for reading (see Streams section). Once you're done reading, call the loader's CloseBuffer() method to release the stream.
    
  class CLoader
 
  class CLoader
 
  {
 
  {
 
  public:
 
  public:
     virtual CClassicBuffer* GetBuffer(CSystemFid* pFid, int mode, CClassicBuffer* pInnerBuffer = NULL);  // mode: 1 = read, 2 = write
+
     virtual CClassicBuffer * OpenBuffer(CSystemFid const * pFid, enum EMode, int)const;  // EMode: 1 = read, 2 = write
     virtual void FreeBuffer(CSystemFid* pFid, CClassicBuffer* pBuffer);
+
     virtual void CloseBuffer(CSystemFid const * pFid, CClassicBuffer * pBuffer)const;
 
  };
 
  };
   Line 730: Line 772:  
  {
 
  {
 
  public:
 
  public:
     virtual ~CClassicBuffer();
+
    CClassicBuffer(void);
     virtual int ReadBytes(void* pTargetBuffer, int length);
+
     virtual ~CClassicBuffer(void);
     virtual int WriteBytes(void* pData, int length);
+
     virtual int IsStoringSecured(void)const;
     virtual void Close();
+
     virtual int IsSeekable(void)const;
     virtual void m10()
+
     virtual void SetCurOffset(unsigned long);
     virtual int GetPosition();
+
     virtual CFastStringInt const * GetFileName(void);
     virtual int GetSize();
+
     virtual bool IsMemoryMapped();
+
     int ReadAll(void * data, unsigned long size);       // Reads the specified number of bytes
     virtual void SetPosition(int position);
+
     int WriteAll(void const * data, unsigned long size); // Writes the specified number of bytes
     virtual void m24();
+
     virtual void Seek(int offset);   // SetPosition(GetPosition() + offset);
+
     CClassicBufferMemory * CreateUncompressedBlock(void);
     virtual int GetCapacity();
+
     void AddCompressedBlock(CClassicBufferMemory const &);
 +
 +
     unsigned long Skip(unsigned long);
 +
     int IsEqualBuffer(CClassicBuffer &);
 +
    int CopyFrom(CClassicBuffer *);
 +
 +
     static int s_IsBufferExceptions;
 
   
 
   
 
  private:
 
  private:
     int mode;               // 1 = reading, 2 = writing
+
     enum EMode;             // 1 = reading, 2 = writing
     bool bInitializing;     // If set to true, writing to the CClassicBuffer will
+
     bool bDummyWrite;       // If set to true, writing to the CClassicBuffer will
 
                               // not actually write to the underlying stream.
 
                               // not actually write to the underlying stream.
 
                               // Instead, the data provided for writing will be used
 
                               // Instead, the data provided for writing will be used
Line 767: Line 815:  
  class CClassicBufferMemory : public CClassicBuffer
 
  class CClassicBufferMemory : public CClassicBuffer
 
  {
 
  {
 +
public:
 +
    CClassicBufferMemory(void);
 +
    virtual ~CClassicBufferMemory(void);
 +
    virtual unsigned long Read(void * pTargetBuffer, unsigned long length);
 +
    virtual unsigned long Write(void const * pData, unsigned long length);
 +
    virtual int Close(void);
 +
    virtual unsigned long m10(); // Stub that returns 0
 +
    virtual unsigned long GetCurOffset(void)const;
 +
    virtual unsigned long GetActualSize(void)const;
 +
    virtual bool IsSeekable(void)const;
 +
    virtual void SetCurOffset(unsigned long position);
 +
    virtual unsigned long m24(); // Stub that returns 0
 +
    virtual void AdvanceOffset(unsigned long offset); // SetCurOffset(GetCurOffset() + offset);
 +
    virtual unsigned long GetAllocatedSize(void)const;
 +
 +
    void PreAlloc(unsigned long);
 +
    void Attach(void *, unsigned long);
 +
    void CopyAndDetachBufferMemory(CClassicBufferMemory &);
 +
    void Reset(void);
 +
    void Empty(void);
 +
    void EmptyAndFreeMemory(void);
 +
    int IsEqualBuffer(CClassicBufferMemory const &)const;
 +
    unsigned long WriteVoid(unsigned long);
 +
    unsigned long WriteCopy(CClassicBuffer *, unsigned long);
 +
 
  private:
 
  private:
 
     void* pData;
 
     void* pData;
Line 772: Line 845:  
     int position;
 
     int position;
 
     int capacity;
 
     int capacity;
     int capacityIncrement;   // Step size by which to increase capacity when the buffer gets full
+
     int capacityIncrement; // Step size by which to increase capacity when the buffer gets full
 
  };
 
  };
   Line 857: Line 930:  
  {
 
  {
 
  public:
 
  public:
     virtual ~CClassicArchive();
+
    CClassicArchive(void);
     virtual ReadWriteNodRef(CMwNod** ppNod);   // Reads or writes a reference to an object.
+
     virtual ~CClassicArchive(void);
                                                // If this is the first time the object is encountered,
+
     virtual void DoNodPtr(CMwNod * &);
                                                // it is (de)serialized at this point.
+
    virtual void DoFid(CSystemFidFile * &);
     virtual ReadWriteNodRefNoCreate(CMwNod** ppNod);   // Reads or writes a reference to an object.
+
    virtual void DoFolder(CSystemFidsFolder * &, int, CSystemFidsFolder *);
                                                        // The object is expected to be already known
+
    virtual int GetArchivingFileName(CFastStringInt &)const;
                                                        // (no deserialization happens).
+
 +
    void AttachBuffer(CClassicBuffer *);
 +
    CClassicBuffer * DetachBuffer(int);
 +
 +
    void ReadData(void *, unsigned long);
 +
    void ReadBool(bool *, unsigned long);
 +
    void ReadMask(unsigned long *, unsigned long);
 +
    void ReadNat8(unsigned char *, unsigned long, int);
 +
    void ReadNat16(unsigned short *, unsigned long, int);
 +
    void ReadNat32(unsigned long *, unsigned long, int);
 +
    void ReadNatural(unsigned long *, unsigned long, int);
 +
    void ReadNat64(unsigned __int64 *, unsigned long, int);
 +
    void ReadInteger(int *, unsigned long, int);
 +
    void ReadReal(float *, unsigned long);
 +
    void ReadString(CFastString *, unsigned long);
 +
    void ReadString(CFastStringInt *, unsigned long);
 +
 +
    void WriteData(void const *, unsigned long);
 +
    void WriteBool(bool const *, unsigned long);
 +
    void WriteMask(unsigned long const *, unsigned long);
 +
    void WriteNat8(unsigned char const *, unsigned long, int);
 +
    void WriteNat16(unsigned short const *, unsigned long, int);
 +
    void WriteNat32(unsigned long const *, unsigned long, int);
 +
    void WriteNatural(unsigned long const *, unsigned long, int);
 +
    void WriteNat64(unsigned __int64 const *, unsigned long, int);
 +
    void WriteInteger(int const *, unsigned long, int);
 +
    void WriteReal(float const *, unsigned long);
 +
    void WriteString(CFastString const *, unsigned long);
 +
    void WriteString(CFastStringInt const *, unsigned long);
 +
 +
    void DoMarker(char const *);  // Reads or writes markup, like <Thumbnail.jpg> or </Thumbnail.jpg>
 +
    void DoData(void *, unsigned long count);  // Reads or writes the specified number of bytes
 +
    void DoBool(bool *, unsigned long count);  // Reads or writes a truth value
 +
    void DoMask(unsigned long *, unsigned long count);  // Reads or writes a hex value (typically a class ID)
 +
    void DoNat8(unsigned char *, unsigned long count, int isHex);
 +
    void DoNat16(unsigned short *, unsigned long count, int isHex);
 +
    void DoNat32(unsigned long *, unsigned long count, int isHex);
 +
    void DoNatural(unsigned long *, unsigned long count, int isHex);
 +
    void DoNat64(unsigned __int64 *, unsigned long count, int isHex);
 +
    void DoNat128(struct SNat128 *, unsigned long count);
 +
    void DoInteger(int *, unsigned long count, int isHex);
 +
    void DoReal(float *, unsigned long count);
 +
    void DoString(CFastString *, unsigned long count);
 +
    void DoString(CFastStringInt *, unsigned long count);
 +
     void DoStringI18nComment(CFastStringInt *, char const *);
 +
 +
    void SkipData(unsigned long); // Writes the specified number of zeros, or calls CClassicBuffer::Skip() while reading
 +
 +
    static void (__cdecl* s_ThrowCorruptedArchive)(void);
 +
    static int s_AllowUnprintableStrings;
 +
 +
protected:
 +
    int ReadLine(void);   // Reads data from a .gbx file in text format
 +
    void WriteLine(void);  // Writes data to a .gbx file in text format
 +
 +
    static void (__cdecl* s_DeleteMwIdUserDataCallBack)(CClassicArchive *);
 
   
 
   
 
  private:
 
  private:
Line 869: Line 997:  
     bool bWriting;
 
     bool bWriting;
 
     bool bTextMode;        // Whether to read/write in readable ASCII text or in binary
 
     bool bTextMode;        // Whether to read/write in readable ASCII text or in binary
     bool bUnknown;
+
     bool bBucr3IsR;
 
     void* pStringIndices;  // Pointer to cache of known string IDs
 
     void* pStringIndices;  // Pointer to cache of known string IDs
 
  };
 
  };
  −
For details on ReadWriteNodRef, see the definition of "noderef" on the [[GBX#Primitives|GBX page]].
      
====CSystemArchiveNod====
 
====CSystemArchiveNod====
Line 880: Line 1,006:  
  class CSystemArchiveNod : public CClassicArchive
 
  class CSystemArchiveNod : public CClassicArchive
 
  {
 
  {
 +
public:
 +
    CSystemArchiveNod(void);
 +
    virtual ~CSystemArchiveNod(void);
 +
    virtual void DoNodPtr(CMwNod * &); // Reads or writes a reference to an object. If this is the first time the object is encountered, it is (de)serialized at this point.
 +
    virtual void DoFid(CSystemFidFile * &);
 +
    virtual void DoFolder(CSystemFidsFolder * &, int, CSystemFidsFolder *);
 +
    virtual int GetArchivingFileName(CFastStringInt &)const;
 +
 +
    void DoDecode(unsigned long);
 +
    int DoFindNod(CMwNod * &, CSystemFid *);
 +
    int DoIsFileSame(CSystemFid *, CClassicBufferMemory &)
 +
    void DoFormatFromFid(void);
 +
    int AddInternalRef(CMwNod *, unsigned long &, char const *);
 +
    int InsertExternalLocations(CSystemFids *, CFastBuffer<CSystemFids *> *);
 +
    int ExtractExternalLocations(CFastBuffer<CSystemFids *> * &, CSystemFidsDrive *);
 +
    int LoadCurrentHeader(enum EVersion);  // Reads the file header of a .gbx file
 +
    int DoLoadHeader(void);      // Reads the magic 'GBX' and version of a .gbx file, and then calls LoadCurrentHeader()
 +
    int DoSaveHeader(void);      // Writes the header of a .gbx file
 +
    int DoLoadRef(void);        // Reads the reference table of a .gbx file
 +
    int DoSaveRef(void);        // Writes the reference table of a .gbx file
 +
    int DoLoadAllRef(void);      // Reads the header and the reference table of a .gbx file
 +
    int DoLoadBody(CMwNod * &);  // Reads the body of a .gbx file
 +
    int DoSaveBody(void);        // Writes the body of a .gbx file
 +
    int DoLoadAll(CMwNod * &);  // Reads the header, the reference table and the body of a .gbx file
 +
    int DoSaveAll(void);        // Writes the header, the reference table and the body of a .gbx file
 +
    int DoSaveBodyMemory(CMwNod *);
 +
    int DoSave(CMwNod *, unsigned long, enum EArchive, int);
 +
    int DoLoadResource(unsigned long, CMwNod * &);
 +
    int DoFidLoadFile(CMwNod * &);
 +
    int DoFidSaveFile(CMwNod *);
 +
    int DoFidSaveFileSafe(CMwNod *, unsigned long);
 +
    int DoFidLoadRefs(enum EArchive, CClassicBuffer *);
 +
    int DoFidLoadMemory(CMwNod * &);
 +
    int DoFidSaveMemory(CMwNod *);
 +
    int DoLoadFile(CFastStringInt const &, CMwNod * &, CSystemFids *, enum EArchive);
 +
    int DoSaveFile(CFastStringInt const &, CMwNod *, CSystemFids *, unsigned long, enum EArchive, int);
 +
    int DoLoadFromFid(CMwNod * &);
 +
    int DoLoadMemory(CClassicBufferMemory *, CMwNod * &);
 +
    int DoSaveMemory(CClassicBufferMemory *, CMwNod *, unsigned long);
 +
    int DoLoadMemoryTemp(CClassicBufferMemory *, CMwNod * &);
 +
    int DoSaveMemoryTemp(CClassicBufferMemory *, CMwNod *, unsigned long, int);
 +
 +
    static void DoFolder(CClassicArchive &, CSystemFidsFolder * &, CSystemFidsFolder *);
 +
    static int SaveFile(CFastStringInt const &, CMwNod *, CSystemFids *, unsigned long, enum EArchive, int);
 +
    static int LoadFromFid(CMwNod * &, CSystemFid *, enum EArchive);
 +
    static int SaveToFid(CSystemFid *, CMwNod *, unsigned long, int);
 +
    static int LoadFileFrom(CFastStringInt const &, CMwNod * &, CSystemFids *, enum EArchive);
 +
    static int LoadFileToMemory(CSystemFid *, CClassicBufferMemory *)
 +
    static int SaveMemoryToFile(CSystemFid *, CClassicBufferMemory *);
 +
    static int SaveMemory(CClassicBufferMemory *, CMwNod *, unsigned long);
 +
    static int LoadMemoryTemp(CClassicBufferMemory *, CMwNod * &);
 +
    static int SaveMemoryTemp(CClassicBufferMemory *, CMwNod *, unsigned long, int);
 +
    static int LoadResource(unsigned long, CMwNod * &);
 +
    static int Save(CMwNod *, unsigned long, int);
 +
    static int Compare(CMwNod *, CMwNod *, int &);
 +
    static int Duplicate(CMwNod * &, int);
 +
    static void ComputeCrcNat32(CMwNod *, unsigned long &);
 +
    static void ComputeCrcString(CMwNod *, CFastString &);
 +
 +
private:
 +
    void ParametrizedFinalization(CMwNod *);
 +
    void ParametrizedFindOrAddFid(CSystemFid *, CMwNod *);
 +
 
  private:
 
  private:
 
     word version;                                      // .gbx file version
 
     word version;                                      // .gbx file version
Line 886: Line 1,075:  
     FastArray<CSystemFids*> externalFolders;          // References to other folders
 
     FastArray<CSystemFids*> externalFolders;          // References to other folders
 
     FastBuffer<ExternalNodEntry> externalNodEntries;  // References to other files
 
     FastBuffer<ExternalNodEntry> externalNodEntries;  // References to other files
     FastBuffer<NodEntry> nodEntries;                  // List of objects, both in the current .gbx file
+
     FastBuffer<NodEntry> nodEntries;                  // List of objects, both in the current .gbx file
 
                                                         // and from external files
 
                                                         // and from external files
 
     FastBuffer<CSystemFids*> folders;
 
     FastBuffer<CSystemFids*> folders;
Line 898: Line 1,087:  
           int nodIndex;          // Index in nodEntries of where the external object will be placed
 
           int nodIndex;          // Index in nodEntries of where the external object will be placed
 
           int folderIndex;      // Index in externalFolders to the folder containing the .gbx file
 
           int folderIndex;      // Index in externalFolders to the folder containing the .gbx file
           bool bUseFid;          // If false, the file pFid will be deserialized and nodEntries is
+
           bool bUseFid;          // If false, the file pFid will be deserialized and nodEntries is
 
                                 // populated with the resulting object.
 
                                 // populated with the resulting object.
                                 // If true, nodEntries is populated with pFid itself.
+
                                 // If true, nodEntries is populated with pFid itself.
 
     };
 
     };
 
   
 
   
Line 910: Line 1,099:  
     };
 
     };
 
  };
 
  };
 +
 +
For details on DoNodPtr, see the definition of "noderef" on the [[GBX#Primitives|GBX page]].
    
A .gbx file contains a serialized main object instance whose type is indicated by classID. This main object can reference other objects, which may be contained in the same .gbx file or in other files.
 
A .gbx file contains a serialized main object instance whose type is indicated by classID. This main object can reference other objects, which may be contained in the same .gbx file or in other files.
   −
All objects, both from the current .gbx file and from external files, are stored in the nodEntries list. The main object of the .gbx file is always at index 0. Every time a subobject is read from the .gbx file, or an external file is referenced, the nodEntries index is specified where the object should be stored. The process of reading .gbx files is explained in detail on the [[GBX|GBX page]].
+
All objects, both from the current .gbx file and from external files, are stored in the nodEntries list. The main object of the .gbx file is always at index 0. Every time a subobject is read from the .gbx file, or an external file is referenced, the nodEntries index is specified where the object should be stored.
 +
 
 +
The process for reading a complete *.gbx file looks like this:
 +
LoadFileFrom -> DoLoadFile -> DoFidLoadFile -> DoLoadAll -> { DoLoadHeader { -> LoadCurrentHeader } -> DoLoadRef -> DoLoadBody }
 +
Reading the file header and body is explained in detail on the [[GBX|GBX page]].
    
== Tools ==
 
== Tools ==

Navigation menu