Changes

Jump to navigation Jump to search
2,253 bytes added ,  00:37, 30 July 2019
m
→‎Header versions 6+: Updated a comment
Line 20: Line 20:  
  {
 
  {
 
     uint128 headerMD5;
 
     uint128 headerMD5;
     uint32 metaDataOffset;
+
     uint32 gbxHeadersStart; // offset to metadata section
     uint32 dataOffset;
+
     uint32 dataStart;
 
     if version >= 2:
 
     if version >= 2:
 
     {
 
     {
         uint32 metaDataUncompressedSize;
+
         uint32 gbxHeadersSize;
         uint32 metaDataCompressedSize;
+
         uint32 gbxHeadersComprSize;
 
     }
 
     }
 
     if version >= 3:
 
     if version >= 3:
Line 46: Line 46:  
         uint32 compressedSize;
 
         uint32 compressedSize;
 
         uint32 offset;
 
         uint32 offset;
         uint32[[Class IDs | classID]]; // indicates the type of the file
+
         uint32 [[Class IDs|classID]]; // indicates the type of the file
 
         uint64 flags;
 
         uint64 flags;
 
     }
 
     }
Line 79: Line 79:  
There is one special exception with .gbx files. If the specific class ID is 0x07031000 (Control::CControlText), 0x07001000 (Control::CControlBase) is used as input instead.
 
There is one special exception with .gbx files. If the specific class ID is 0x07031000 (Control::CControlText), 0x07001000 (Control::CControlBase) is used as input instead.
   −
===Header versions 6-8===
+
===Header versions 6+===
  byte magic[8]: "NadeoPak"
+
  byte magic[8];  // "NadeoPak"
  uint32 version (6, 7, 8)
+
  uint32 version;
 
  if (version >= 6)
 
  if (version >= 6)
 
  {
 
  {
  uint256   ContentsChecksum; // Checksum Sha256 of the pack contents starting at next byte
+
    uint256 ContentsChecksum;   // Checksum Sha256 of the pack contents starting at next byte
  uint32    DecryptFlags;
+
     struct SHeaderFlagsUncrypt
  if (version >= 7)
  −
  {
  −
     struct SAuthorInfo
   
     {
 
     {
      uint32 version;
+
        uint32 IsHeaderPrivate    : 1;
      string Login;
+
        uint32 UseDefaultHeaderKey : 1;
      string Nick;
+
        uint32 IsDataPrivate      : 1;
      string Zone;
+
        uint32 IsImpostor          : 1;
      string ExtraInfo;
+
        uint32 __Unused__          : 28;
     }
+
     };
    string  Comment;
+
     if (version >= 15)
    uint128  unused;
+
        uint32 HeaderMaxSize;   // 0x4000 = Small (16 KB), 0x100000 = Big (1 MB), 0x1000000 = Huge (16 MB)
    if (version >= 8)
+
     if (version >= 7)
    {
  −
      string CreationBuildInfo;
  −
      string AuthorUrl;
  −
     }
  −
  }
  −
}
  −
 
  −
===Header versions 9+===
  −
byte magic[8]: "NadeoPak"
  −
uint32 version (9 or higher)
  −
if (version >= 6)
  −
{
  −
  uint256 ContentsChecksum;  // Checksum Sha256 of the pack contents starting at next byte
  −
  uint32  DecryptFlags;
  −
  if (version >= 15)
  −
    uint32 HeaderMaxSize; // 0x4000 = small (16 KB), 0x100000 = big (1 MB), 0x1000000 = huge (16 MB)
  −
  if (version >= 9)
  −
  {
  −
    struct SAuthorInfo
  −
    {
  −
      uint32 version;
  −
      string Login;
  −
      string Nick;
  −
      string Zone;
  −
      string ExtraInfo;
  −
    }
  −
    string      ManialinkUrl;
  −
    if (version >= 13)
  −
      string    DownloadUrl;
  −
    uint64      CreationDate;
  −
    string      Comment;
  −
     if (version >= 12)
   
     {
 
     {
      string   Xml;
+
        struct SAuthorInfo
      string   TitleID;
+
        {
 +
            uint32 Version;
 +
            string Login;
 +
            string Nick;
 +
            string Zone;
 +
            string ExtraInfo;
 +
        };
 +
        if (version < 9)
 +
        {
 +
            string  Comment;
 +
            uint128 unused;
 +
        }
 +
        if (version == 8)
 +
        {
 +
            string CreationBuildInfo;
 +
            string AuthorUrl;
 +
        }
 +
        if (version >= 9)
 +
        {
 +
            string ManialinkUrl;
 +
            if (version >= 13)
 +
                string DownloadUrl;
 +
            uint64 CreationDate;  // Win32 FILETIME structure
 +
            string Comment;
 +
            if (version >= 12)
 +
            {
 +
                string Xml;
 +
                string TitleID;
 +
            }
 +
            string UsageSubDir;  // to known the kind of pack it is
 +
            string CreationBuildInfo;
 +
            uint128 unused;
 +
            if (version >= 10)
 +
            {
 +
                uint32 NbIncludedPacks;
 +
                struct SIncludedPacksHeaders
 +
                {
 +
                    uint256    ContentsChecksum; // Sha256
 +
                    string      Name;
 +
                    SAuthorInfo AuthorInfo;
 +
                    string      InfoManialinkUrl;
 +
                    uint64      CreationDate;
 +
                    string      Name;
 +
                    if (version >= 11)
 +
                        uint32 IncludeDepth;
 +
                } IncludedPacks[];
 +
            }
 +
        }
 
     }
 
     }
     string      UsageSubDir; // to known the kind of pack it is
+
     Blowfish encrypted: // Unencrypted if neither SHeaderFlagsUncrypt.IsHeaderPrivate nor SHeaderFlagsUncrypt.UseDefaultHeaderKey are set
    string      CreationBuildInfo;
  −
    uint128    unused;
  −
    if (version >= 10)
   
     {
 
     {
      uint32  NbIncludedPacks;
+
        uint128 Checksum;
      struct SIncludedPacksHeaders
+
        uint32 GbxHeadersStart; // Offset to the metadata section
      {
+
        if version < 15:
         uint256    ContentsChecksum; // Sha256
+
            uint32 DataStart;     // If version >= 15: DataStart = HeaderMaxSize
         string      Name;
+
        if version >= 2:
         SAuthorInfo AuthorInfo;
+
        {
         string     InfoManialinkUrl;
+
            uint32 GbxHeadersSize;
         uint64      CreationDate;
+
            uint32 GbxHeadersComprSize;
         string     Name;
+
        }
        if (version >= 11)
+
        if version >= 14:
          uint32    IncludeDepth;
+
            uint128 unused;
        } IncludedPacks[];
+
         if version >= 16:
 +
            uint32 FileSize;
 +
         if version >= 3:
 +
            uint128 unused;
 +
         if version == 6:
 +
            SAuthorInfo;
 +
         uint32 Flags;
 +
        uint32 NumFolders;
 +
        FolderDesc Folders[NumFolders]
 +
        {
 +
            int32 FolderIndexParent;
 +
            string FolderName;
 +
         }
 +
        uint32 NumFiles;
 +
         FileDesc Files[NumFiles]
 +
        {
 +
            int32 FolderIndex;
 +
            string FileName;
 +
            uint32 unknown;
 +
            uint32 UncompressedSize;
 +
            uint32 CompressedSize;
 +
            uint32 Offset;
 +
            uint32 [[Class IDs|classID]];
 +
            if version >= 17:
 +
                uint32 Size;
 +
            if version >= 14:
 +
                uint128 Checksum;
 +
            struct SFileDescFlags
 +
            {
 +
                uint32 IsHashed          : 1;
 +
                uint32 PublishFid        : 1;
 +
                uint32 Compression      : 4;
 +
                uint32 IsSeekable        : 1;
 +
                uint32 _Unknown_        : 1;
 +
                uint32 __Unused1__      : 24;
 +
                uint32 DontUseDummyWrite : 1;
 +
                uint32 OpaqueUserData   : 16;
 +
                uint32 PublicFile        : 1;
 +
                uint32 ForceNoCrypt      : 1;
 +
                uint32 __Unused2__      : 13;
 +
            };
 +
        }
 
     }
 
     }
  }
   
  }
 
  }
    
===Data===
 
===Data===
The content of each file starts at Header.dataOffset + FileDesc.offset in the .pak file. First, an 8-byte plaintext IV is read. Then, FileDesc.compressedSize bytes are read and decrypted using Blowfish in CBC mode, using the same key that was used to decrypt the header. If FileDesc.flags & 0x7C is not zero, the file is compressed and should be decompressed using zlib deflate after decryption (it will end up at FileDesc.uncompressedSize bytes).
+
The content of each file starts at Header.dataStart + FileDesc.offset in the .pak file. From version 15, the data block starts at HeaderMaxSize. First, an 8-byte plaintext IV is read. Then, FileDesc.compressedSize bytes are read and decrypted using Blowfish in CBC mode, using the same key that was used to decrypt the header. If FileDesc.flags & 0x7C is not zero, the file is compressed and should be decompressed using zlib deflate after decryption (it will end up at FileDesc.uncompressedSize bytes).
    
The type of the file can be found from the extension in the name, or, if this is not available (many file names are actually just hashes), from the [[Class IDs|class ID]].
 
The type of the file can be found from the extension in the name, or, if this is not available (many file names are actually just hashes), from the [[Class IDs|class ID]].

Navigation menu