Changes

Jump to navigation Jump to search
10,182 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.
 +
 +
== 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 81: 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 then SetLocalName.
+
     void SetLocalName(CFastStringInt const &);  // Calls CFastStringInt::GetUtf8 and then SetLocalName.
 
   
 
   
     char const * __thiscall GetString(void)const;  // Gets the string of 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===
Line 129: Line 136:  
  };
 
  };
   −
<div class="mw-collapsible mw-collapsed">
   
Identifiers are managed by the class SGameCtnIdentifier:
 
Identifiers are managed by the class SGameCtnIdentifier:
<div class="mw-collapsible-content">
   
  struct SGameCtnIdentifier
 
  struct SGameCtnIdentifier
 
  {
 
  {
 
  public:
 
  public:
     __thiscall SGameCtnIdentifier(void);  // Calls CMwId::CMwId for all three IDs of the Ident.
+
     SGameCtnIdentifier(void);  // Calls CMwId::CMwId for all three IDs of the Ident.
     __thiscall SGameCtnIdentifier(struct SGameCtnIdentifier const &);  // Calls CMwId::CMwId(class CMwId const &) for all three IDs of the Ident.
+
     SGameCtnIdentifier(SGameCtnIdentifier const &);  // Calls CMwId::CMwId(class CMwId const &) for all three IDs of the Ident.
     __thiscall ~SGameCtnIdentifier(void);
+
     ~SGameCtnIdentifier(void);
 
   
 
   
     int __thiscall operator==(struct SGameCtnIdentifier const &)const;  // Compares the first two IDs of the Ident.
+
     int operator==(SGameCtnIdentifier const &)const;  // Compares the first two IDs of the Ident.
     static int __cdecl sCompareCollectionAndId(struct SGameCtnIdentifier const *, struct SGameCtnIdentifier const *);  // Compares the names of the first two IDs of the Ident using CMwId::GetName.
+
     static int sCompareCollectionAndId(SGameCtnIdentifier const *, SGameCtnIdentifier const *);  // Compares the names of the first two IDs of the Ident using CMwId::GetName.
 
   
 
   
     void __thiscall Archive(class CClassicArchive &);  // Serializes the Ident. See "[[GBX#Primitives|meta]]" on the [[GBX]] page for details.
+
     void Archive(CClassicArchive &);  // Serializes the Ident. See "[[GBX#Primitives|meta]]" on the [[GBX]] page for details.
 
  };
 
  };
</div>
  −
</div>
      
===Delegate===
 
===Delegate===
Line 161: Line 164:  
  struct Color
 
  struct Color
 
  {
 
  {
     int r;
+
     float r;
     int g;
+
     float g;
     int b;
+
     float b;
 
  };
 
  };
   Line 249: Line 252:  
  {
 
  {
 
  public:
 
  public:
     CMwNod();
+
     CMwNod(void);
     virtual ~CMwNod();
+
    CMwNod(CMwNod const &);
     virtual CMwClassInfo* MwGetClassInfo(); // Gets information about the object's class
+
     virtual ~CMwNod(void);
     virtual int GetMwClassId();
+
     virtual CMwClassInfo const * MwGetClassInfo(void)const; // Gets information about the object's class
     virtual bool MwIsKindOf(int classID);   // Returns true if the object's class is equal to or derives from the specified class
+
     virtual unsigned long GetMwClassId(void)const;
     virtual CMwId* MwGetId();              // Returns meta information about the object, like name and author
+
     virtual bool MwIsKindOf(unsigned long classID)const;   // Returns true if the object's class is equal to or derives from the specified class
     virtual void SetIdName(char* psz);     // Sets the name of the object (affects MwGetId())
+
     virtual CMwId const * MwGetId(void)const;              // Returns meta information about the object, like name and author
     virtual void m1C();
+
     virtual void SetIdName(char const * psz);               // Sets the name of the object (affects MwGetId())
     virtual void MwIsUnreferenced(CMwNod*);
+
     virtual void MwIsKilled(CMwNod *);
     virtual void VirtualParam_Get(CMwStack* pStack, CMwValueStd* ppValue); // Gets the value of a property
+
     virtual void MwIsUnreferenced(CMwNod *);
     virtual void VirtualParam_Set(CMwStack* pStack, void* pValue);        // Calls a method or sets a property
+
     virtual unsigned long VirtualParam_Get(CMwStack * pStack, CMwValueStd * ppValue); // Gets the value of a property
     virtual void VirtualParam_Add(CMwStack* pStack, void* pValue);
+
     virtual unsigned long VirtualParam_Set(CMwStack * pStack, void * pValue);        // Calls a method or sets a property
     virtual void VirtualParam_Sub(CMwStack* pStack, void* pValue);
+
     virtual unsigned long VirtualParam_Add(CMwStack * pStack, void * pValue);
     virtual void Archive(CClassicArchive* pArchive);                       // (De)serializes the [[GBX#Reading_the_body|nod]] from a stream
+
     virtual unsigned long VirtualParam_Sub(CMwStack * pStack, void * pValue);
     virtual void Chunk(CClassicArchive* pArchive, int chunkID);           // (De)serializes a single chunk from a stream
+
     virtual CMwNod * Archive(CClassicArchive & pArchive);                   // (De)serializes the [[GBX#Reading_the_body|nod]] from a stream
     virtual void m3C();
+
     virtual void Chunk(CClassicArchive & pArchive, unsigned long chunkID); // (De)serializes a single chunk from a stream
    virtual int GetChunkInfo(int chunkID);        // Gets chunk-specific flags, e.g. if it is skippable
+
     virtual unsigned long GetChunkInfo(unsigned long chunkID)const;        // Gets chunk-specific flags, e.g. if it is skippable
     virtual int GetUidMessageFromIndex(int index); // Used during serialization: which chunk to write next
+
     virtual unsigned long GetUidChunkFromIndex(unsigned long index)const;   // Used during serialization: which chunk to write next
     virtual int GetHeaderChunkCount();             // Used during serialization: how many chunks to write
+
     virtual unsigned long GetChunkCount(void)const; // Used during serialization: how many chunks to write
     virtual void OnNodLoaded();                   // Called after the last chunk has been read/written
+
     virtual void OnNodLoaded(void);                 // Called after the last chunk has been read/written
     virtual void m50();
+
     virtual void CreateDefaultData(void);
     virtual void m54();
+
     virtual void OnPackAvailable(CSystemFid *, CSystemFid *);
     virtual void m58();
+
     virtual void ApplyFidParameters(CSystemFidParameters const *, CSystemFidParameters *, CFastBuffer<SManuallyLoadedFid> &);
     virtual void OnCrashDump(CFastString*);
+
     virtual int OnCrashDump(CFastString &);
     virtual void m60();
+
     virtual void CopyFrom(CMwNod *);
     virtual void HeaderChunk(CClassicArchive* pArchive, int* pHeaderChunkID, bool* pbLight); // Writes a header chunk to a stream
+
     virtual void HeaderChunk(CClassicArchive & pArchive, unsigned long & pHeaderChunkID, bool & pbLight); // Writes a header chunk to a stream
 +
    virtual unsigned long GetUidHeaderChunkFromIndex(unsigned long index)const; // Used during serialization: which header chunk to write next
 +
    virtual unsigned long GetHeaderChunkCount(void)const;                      // Used during serialization: how many header chunks to write
 +
    virtual unsigned long GetUidMessageFromIndex(unsigned long index)const;
 +
    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;
 
  };
 
  };
 
   
 
   
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 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 564: 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 665: 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 727: Line 759:  
  {
 
  {
 
  public:
 
  public:
     virtual CClassicBuffer* OpenBuffer(CSystemFid* pFid, enum EMode, int);  // EMode: 1 = read, 2 = write
+
     virtual CClassicBuffer * OpenBuffer(CSystemFid const * pFid, enum EMode, int)const;  // EMode: 1 = read, 2 = write
     virtual void CloseBuffer(CSystemFid* pFid, CClassicBuffer* pBuffer);
+
     virtual void CloseBuffer(CSystemFid const * pFid, CClassicBuffer * pBuffer)const;
 
  };
 
  };
   Line 740: 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 777: 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 782: 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 867: 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 879: 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 890: 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 896: 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 908: 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 920: 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