Difference between revisions of "IMG archive"

From GTAMods Wiki
Jump to navigation Jump to search
m
 
(71 intermediate revisions by 16 users not shown)
Line 1: Line 1:
= Introduction =
+
{{TocRight}}GTA's most commonly used [[archive file]]s are cd images, known by the extension <code>'''.img'''</code>. They have a very simple format and currently exist in multiple versions.
  
GTA's archive files are known by the extension '''.img''', have a very simple format, and currently exist in two versions. Archived files are stored in 2 KB blocks, unsorted, uncompressed and linear (no directory tree).
+
== Structure ==
  
= Structure =
+
The format reflects [http://en.wikipedia.org/wiki/Disk_sector sectors] of CD-ROMs, improving I/O speed on the storage media. Every file contained in the img archive must be sector aligned, where the size of each sector is '''2048 bytes'''.
 +
Thus values for offset and size have to be ''multiplied by 2048''. This means that even a file with only 123 byte content will take up 2 KiB in the archive.
  
== Version 1 - GTA3 &amp; VC ==
+
The format is divided between directory entries, which contains information about the actual files in the img archive, and the actual files, which are stored (usually) unsorted, uncompressed and linear (no directory tree).
  
Version 1 archives, used in GTA III and Vice City, are actually split up into two files: the content directory (.dir) and the actual archive (.img).  
+
Directory entries should be in the same order as the files are stored, and there should not be any empty block between files. This is because the game might read more than one file with a single system call. By not following this rule, the game might get unstable.
  
The directory is a list of files, each with name, offset and size of the file. The values for offset and size have to be ''multiplied by 2048'', since files are aligned to 2 KB boundaries. This means that even a file with only 123 byte content will take up 2 KB in the archive.
+
=== Version 1 - GTA III &amp; VC ===
  
First you have to find out the <strong>number of entries (n)</strong>.
+
In this version, the directory and the raw files are stored in separate files, the directory entries are stored in a <code>.dir</code> and the content pointed by the directory in the <code>.img</code> itself.  
Just divide the filesize of the .dir file by 32 and you will get it.
 
  
There is no Header, like in V2 (San Andreas) Files!
+
The directory archive (<code>.dir</code>) must have the same name as the <code>.img</code> archive, except for the extension.
 +
The directory archive is pretty simple, it contains no header, just the following structure repeated until the end of the file.
  
Entry: (repeated n times)<br>
+
==== Directory Entry ====
   4 byte - DWORD     - offset of file inside archive (in blocks)
+
Size of '''32 bytes'''
   4 byte - DWORD     - size of file (in blocks)
+
   4 byte - DWORD - Offset (in sectors)
  24 byte - CHAR[24] - name of file
+
   4 byte - DWORD - Size (in sectors)
 +
  24 byte - CHAR[24] - Name of the file (null terminated)
  
The .img file itself has no special structure or header, just all the files in 2 KB blocks.
+
The total number of entries can be found by dividing the size of the <code>.dir</code> file by 32.
  
== Version 2 - GTA SA ==
+
The <code>.img</code> file itself has no special structure or header, just all the files pointed by the directory.
  
Version 2 archives, introduced with GTA San Andreas, combine .dir and .img files into one .img file. The directory has the same format as in version 1, but is located at the beginning of the archive. Files are again aligned to 2 KB boundaries. File offsets are relative to the start of the whole archive, not to the end of the file list.
+
This format was also used in the PC version of ''Bully: Scholarship Edition''.
  
Header:<br>
+
==== Compression ====
  4 byte - CHAR[4- FourCC, always "VER2"
+
 
  4 byte - DWORD     - number of entries (n)<br>
+
The XBOX versions of GTA III and GTA Vice City use [http://www.oberhumer.com/opensource/lzo/lzonews.php lzo1x-999] compression on TXD and DFF files.
  Entry: (repeated n times)<br>
+
 
   4 byte - DWORD    - offset of file inside archive (in blocks)
+
===== TXD Archive Compression =====
   4 byte - DWORD    - size of file (in blocks)
+
 
  24 byte - CHAR[24] - name of file
+
The '''lzo compression stream''' uses a similar format as was used in the lzo library examples. It consists of a '''master header''' that is followed by a number of '''compression blocks'''. Each compression block can have an arbitrary size, but all of them together have to match the compression data size that is provided in the master header.
 +
 
 +
'''Master header:'''
 +
<source lang="c">
 +
4 byte - DWORD - magic number (0x67A3A1CE little endian)
 +
4 byte - DWORD - checksum
 +
4 byte - DWORD - size of entire compression data (pre-block-header + file data)
 +
</source>
 +
 
 +
To detect whether a stream '''is lzo compressed''', it is recommended to check if the magic number as well as its structure make sense. Just checking the magic number can be sufficient for RenderWare streams and other Rockstar related formats but is ill-advised in general practice.
 +
 
 +
Once detected you have to read the compressed data stream. This is done by first reading a '''per-block header'''.
 +
 
 +
'''Per-block header + compression data:'''
 +
<source lang="c">
 +
4 byte - DWORD - always 4 (?)
 +
4 byte - DWORD - suggested decompressed size
 +
4 byte - DWORD - size of compressed block
 +
 
 +
byte[n] - compressed block
 +
</source>
 +
 
 +
This header represents a ''compression unit''. This means that the data that follows this block has to be '''(de-)compressed using the lzo1x_decompress_safe routine of the lzo library'''. The resulting decompressed data is arbitarily bigger than its compressed counter-part, so '''please do not use a fixed-size output buffer'''.
 +
 
 +
For compressing data, you have to split the input data stream into chunks and compress each one individually. The Rockstar games compressor divided the data into a continuous row of 0x00020000 (131072) byte chunks. Doing that is '''recommended''' since working on smaller temporary memory buffers is memory friendly. It also means that, practically, each ''compression unit'' can only decompress to 131072 bytes in memory, allowing for architecture specific optimizations.
 +
 
 +
''Checksum calculation is currently undocumented (not required for decompression).''
 +
 
 +
=== Version 2 - GTA SA ===
 +
 
 +
Introduced with GTA San Andreas, combines the directory entries (<code>.dir</code>) and raw files (<code>.img</code>) into one <code>.img</code> file.
 +
The directory has the same format as in version 1, but is located at the beginning of the archive. File offsets are relative to the start of the whole archive, not to the end of the file list.
 +
 
 +
==== Header ====
 +
Size of '''8 bytes'''
 +
4 byte - CHAR[4] - "VER2"
 +
  4 byte - DWORD - Number Of Entries
 +
 
 +
Followed by the header, there are the directory entries, containing information about the files in the archive.
 +
 
 +
==== Directory Entry ====
 +
Size of '''32 bytes''' 
 +
  4 byte - DWORD - Offset (in sectors)
 +
   2 byte - WORD - Streaming Size (in sectors)
 +
   2 byte - WORD - Size in archive (in sectors) ''(always 0)''
 +
  24 byte - CHAR[24] - Name of the file (null terminated)
 +
 
 +
The streaming size is how many actual sectors the file takes in memory. If streaming size is 0, size will be used as streaming size. The stock img files never used streaming size (thus always 0), it's believed that this mechanism would be used for compression of files, but it never made it's way into production.
  
 
A major drawback of this format is the complicated extendability. If you have to add many files, it might happen that you run out of space for the directory, and have to move the first file(s) to the end.
 
A major drawback of this format is the complicated extendability. If you have to add many files, it might happen that you run out of space for the directory, and have to move the first file(s) to the end.
  
[[Category:Other Formats]][[Category:GTA 3]][[Category:GTA VC]][[Category:GTA SA]]
+
=== Version 3 - GTA IV ===
 +
 
 +
GTA IV introduced yet another <code>.img</code> file format. Not only the format is new, also there can be encrypted archive headers (see below). The internal IMG parser of the game works with 2 kb buffers, which means that the 2 kb bounds from earlier versions (sectors) are still present, yet optional.
 +
 
 +
==== IMG Header ====
 +
 
 +
The header of an unencrypted file always has a size of '''20 bytes'''.
 +
 
 +
4 byte - DWORD      - Identifier (0xA94E2A52 if the archive is not encrypted)
 +
4 byte - DWORD      - Version (always 3, if not the format would be differ)
 +
4 byte - DWORD      - Number of Items
 +
4 byte - DWORD      - Table Size (in bytes)
 +
2 byte - WORD      - Size of Table Items (needs to be always 0x10)
 +
2 byte - WORD      - Unknown
 +
 
 +
==== IMG Table ====
 +
 
 +
The table holds information about the items. Each item header has a size of '''16 bytes''' .
 +
 
 +
4 byte - DWORD      - Itemsize (in bytes)
 +
4 byte - DWORD      - Resource type
 +
4 byte - DWORD      - Offset (in sectors)
 +
2 byte - WORD      - Used Blocks
 +
2 byte - WORD      - Padding
 +
 
 +
Item Names' length will be calculate as :
 +
Table Size - (Number of Items * Item Size)
 +
Next that string will be split by '\x0'
 +
 
 +
A [[resource file|resource]] type is identified by the 4b DWORD value:
 +
* 0x01: Generic
 +
* 0x08: Texture archive
 +
* 0x20: Bounds
 +
* 0x6E: Model file
 +
* 0x24: xpfl
 +
 
 +
==== [[Cryptography|Encryption]] ====
 +
 
 +
The header and directory (table) of IMG archives can be encrypted. This is usually the case if the 4 byte identifier at the start of the file seems invalid. Decryption is done via 16 repetitions of [[Cryptography#AES|AES-128]] in ECB mode.
 +
 
 +
== Additional archives ==
 +
It is possible to add additional IMG archives to the current default ones. The following examples are lines that can be added anywhere in either the [[default.dat]] or [[gta.dat|gta*.dat]] files.
 +
 
 +
{|
 +
| {{Icon|3}} {{Icon|VC}} || <code>CDIMAGE MODELS\FOO.IMG</code>
 +
|-
 +
| style="text-align:center" | {{Icon|SA}} || <code>IMG MODELS\FOO.IMG</code>
 +
|}
 +
 
 +
Where FOO can be any name. The FOO.IMG (and FOO.DIR for GTA III and Vice City) must be created and placed within the <code>..\models</code> folder in these examples. This method is primarily used for [[San Andreas v2.0 Modding|modifying version 2 of San Andreas]], as well as for storing assets (models/textures/etc.) used in total conversions.
 +
 
 +
By default GTA San Andreas is able to load max of 8 archives (3 standard archives gta3.img, gta_int.img, player.img and 5 archives defined within default.dat or gta.dat). GTA VC is able to load max of 8 archives (one archive is hard-coded to be loaded - gta3.img) too. Using more than 8 archives crashes the game, although this can be fixed with {{U|fastman92}}'s IMG Limit Adjuster.
 +
 
 +
== Coding example ==
 +
 
 +
=== IMG v2 C++ library ===
 +
 
 +
==== Usage ====
 +
IMGArchive* newIMgArchive = new IMGArchive("archive.img");
 +
IMGArchiveFile* newFile = newIMgArchive->getFileByID(o);
 +
if (newFile != NULL)
 +
{
 +
//Do some operations
 +
cout << newFile->fileEntry->fileName << endl;
 +
//Can get all bytes for the file and write it out into the separate file
 +
}
 +
delete newFile;
 +
delete newIMgArchive;
 +
 
 +
{| class="collapsible collapsed wikitable"
 +
|-
 +
!IMGArchive.h
 +
|-
 +
|<syntaxhighlight lang="cpp">#ifndef IMGArchive_H
 +
#define IMGArchive_H
 +
 +
#include <iostream>
 +
#include <string>
 +
#include <vector>
 +
 +
typedef unsigned char                 uchar;
 +
typedef unsigned int                 uint;
 +
typedef unsigned short                 ushort;
 +
typedef unsigned long long                 uint64;
 +
 +
struct DirEntry
 +
{
 +
        uint offset;
 +
        ushort fSize;
 +
        ushort fSize2;
 +
        char fileName[24];
 +
};
 +
 +
struct IMGArchiveFile
 +
{
 +
        DirEntry* fileEntry;
 +
        uint64 actualFileOffset;
 +
        uint64 actualFileSize;
 +
        uchar* fileByteBuffer;
 +
};
 +
 +
class IMGArchive
 +
{
 +
public:
 +
        IMGArchive(std::string archiveFilePath);
 +
        ~IMGArchive();
 +
 +
        uint getFileCount();
 +
        IMGArchiveFile*         getFileByID(uint id);
 +
        IMGArchiveFile*         getFileByName(std::string fileName);
 +
        std::vector<DirEntry>                 getArchiveDirEntries();
 +
private:
 +
        void openArchive(std::string archiveFilePath);
 +
        FILE* imgArchiveFile_;
 +
        std::string archiveFilePath_;
 +
        std::vector<DirEntry>                 archiveFileEntries_;
 +
};
 +
#endif // IMGArchive_H</syntaxhighlight>
 +
|}
 +
 
 +
{| class="collapsible collapsed wikitable"
 +
!IMGarchive.cpp
 +
|-
 +
|<syntaxhighlight lang="cpp">
 +
#include "stdafx.h"
 +
#include "IMGArchive.h"
 +
 +
IMGArchive::IMGArchive(std::string archiveFilePath)
 +
{
 +
        imgArchiveFile_ = NULL;
 +
        archiveFilePath_ = archiveFilePath;
 +
        openArchive(archiveFilePath);
 +
}
 +
 +
IMGArchive::~IMGArchive()
 +
{
 +
        archiveFileEntries_.clear();
 +
}
 +
 +
void IMGArchive::openArchive(std::string archiveFilePath)
 +
{
 +
        fopen_s(&imgArchiveFile_, &archiveFilePath[0], "rb");
 +
        if (imgArchiveFile_ != NULL)
 +
        {
 +
                char ver[4];
 +
                fread(ver, 1, 4, imgArchiveFile_);
 +
                if (ver[0] == 'V' && ver[3] == '2')
 +
                {
 +
                        uint entryCount;
 +
                fread(&entryCount, sizeof(uint), 1, imgArchiveFile_);
 +
                for (int i = 0; i < entryCount; i++)
 +
                {
 +
                DirEntry newEntry;
 +
                fread(&newEntry, 1, 32, imgArchiveFile_);
 +
                archiveFileEntries_.push_back(newEntry);
 +
                }
 +
        }
 +
        fclose(imgArchiveFile_);
 +
        }
 +
}
 +
 +
uint IMGArchive::getFileCount()
 +
{
 +
        return archiveFileEntries_.size();
 +
}
 +
 +
std::vector<DirEntry> IMGArchive::getArchiveDirEntries()
 +
{
 +
        return archiveFileEntries_;
 +
}
 +
 +
IMGArchiveFile* IMGArchive::getFileByID(uint id)
 +
{
 +
        if (archiveFileEntries_.size() <= id || id < 0)
 +
        {
 +
                return NULL;
 +
        }
 +
        else
 +
        {
 +
                imgArchiveFile_ = NULL;
 +
                fopen_s(&imgArchiveFile_, &archiveFilePath_[0], "rb");
 +
                if (imgArchiveFile_ != NULL)
 +
                {
 +
                IMGArchiveFile* newArchiveFile = new IMGArchiveFile;
 +
                newArchiveFile->fileEntry = &archiveFileEntries_[id];
 +
                newArchiveFile->actualFileOffset = archiveFileEntries_[id].offset * 2048;
 +
                newArchiveFile->actualFileSize = archiveFileEntries_[id].fSize * 2048;
 +
                newArchiveFile->fileByteBuffer = new uchar[newArchiveFile->actualFileSize];
 +
                fseek(imgArchiveFile_, newArchiveFile->actualFileOffset, SEEK_SET);
 +
                fread(newArchiveFile->fileByteBuffer, 1, newArchiveFile->actualFileSize, imgArchiveFile_);
 +
                fclose(imgArchiveFile_);
 +
                return newArchiveFile;
 +
                }
 +
                return NULL;
 +
        }
 +
}
 +
 +
IMGArchiveFile* IMGArchive::getFileByName(std::string fileName)
 +
{
 +
        for (int i = 0; i < archiveFileEntries_.size(); i++)
 +
        {
 +
                if ((std::string)archiveFileEntries_[i].fileName == fileName)
 +
                {
 +
                imgArchiveFile_ = NULL;
 +
                fopen_s(&imgArchiveFile_, &archiveFilePath_[0], "rb");
 +
                if (imgArchiveFile_ != NULL)
 +
                {
 +
                IMGArchiveFile* newArchiveFile = new IMGArchiveFile;
 +
                newArchiveFile->fileEntry = &archiveFileEntries_[i];
 +
                newArchiveFile->actualFileOffset = archiveFileEntries_[i].offset * 2048;
 +
                newArchiveFile->actualFileSize = archiveFileEntries_[i].fSize * 2048;
 +
                newArchiveFile->fileByteBuffer = new uchar[newArchiveFile->actualFileSize];
 +
                fseek(imgArchiveFile_, newArchiveFile->actualFileOffset, SEEK_SET);
 +
                fread(newArchiveFile->fileByteBuffer, 1, newArchiveFile->actualFileSize, imgArchiveFile_);
 +
                fclose(imgArchiveFile_);
 +
                return newArchiveFile;
 +
                }
 +
                return NULL;
 +
                }
 +
        }
 +
        return NULL;
 +
}
 +
</syntaxhighlight>
 +
|}
 +
 
 +
== Tools ==
 +
{|
 +
| style="text-align:center" | {{Icon|trilogy}} || {{GTAG|27155|IMG Factory(Recommended)}} &ndash; by {{U|X-Seti}}
 +
|-
 +
| style="text-align:center" | {{Icon|3}} {{Icon|VC}} {{Icon|SA}} || {{GTAF|524409|fastman92 IMG Console(Recommended)}} &ndash; by {{U|fastman92}}
 +
|-
 +
| style="text-align:center" | {{Icon|3}} {{Icon|VC}} || [[ImgEd]] &ndash; by Dan Strandberg
 +
|-
 +
| style="text-align:center" | {{Icon|trilogy}} {{Icon|4}} || [http://www.x-squares.com/File/i/54/IMG-Manager.aspx IMG Manager] &ndash; by {{U|xmen}}
 +
|-
 +
| style="text-align:center" | {{Icon|SA}} || {{GTAG|1503|Spark}} &ndash; by {{U|aru}}
 +
|-
 +
| style="text-align:center" | {{Icon|trilogy}} || [[IMG Tool]] &ndash; by {{U|Spooky}}
 +
|-
 +
| style="text-align:center" | {{Icon|trilogy}} || [[G-IMG]] &ndash; by {{U|REspawn}}
 +
|-
 +
| style="text-align:center" | {{Icon|VC}} {{Icon|SA}} || {{GTAF|500814|IMG & Stream Limit Adjuster}} &ndash; by {{U|fastman92}}
 +
|-
 +
| style="text-align:center" | {{Icon|VC}} {{Icon|SA}} || {{GTAF|733982|Fastman92 Limit Adjuster}} &ndash; by {{U|fastman92}}
 +
<!--
 +
|-
 +
| style="text-align:center" | {{Icon|trilogy}} {{Icon|LCS}} {{Icon|VCS}} || [http://www.dustin.gzwn.net/YAIE.zip Yet Another IMG Editor] &ndash; by {{U|dustcrazy}}
 +
-->
 +
|-
 +
| style="text-align:center" | {{Icon|LCS}} {{Icon|VCS}} || {{GTAF|post|439980|1060569495|GTA Stories IMG Tool}} &ndash; by {{U|HackMan128}}
 +
|-
 +
| style="text-align:center" | {{Icon|4}} || [[SparkIV]] &ndash; by {{U|aru}}
 +
|-
 +
| style="text-align:center" | {{Icon|4}} || [[OpenIV]] &ndash; by {{U|GooD-NTS}}
 +
|-
 +
| style="text-align:center" | {{Icon|4}} || [[Shadow-Mapper]] &ndash; by {{U|Prince-Link}}
 +
|}
 +
 
 +
== Libraries ==
 +
====Version 2 only====
 +
* [http://www.x-squares.com/File/i/35/X-Archive-Dragon.aspx X Archive Dragon]
 +
 
 +
====Version 3 only====
 +
* [[X Archive Poison]]
 +
 
 +
{{N|IV|VCS|LCS|SA|VC|III}}
 +
 
 +
[[Category:File Formats]]

Latest revision as of 23:12, 12 January 2021

GTA's most commonly used archive files are cd images, known by the extension .img. They have a very simple format and currently exist in multiple versions.

Structure

The format reflects sectors of CD-ROMs, improving I/O speed on the storage media. Every file contained in the img archive must be sector aligned, where the size of each sector is 2048 bytes. Thus values for offset and size have to be multiplied by 2048. This means that even a file with only 123 byte content will take up 2 KiB in the archive.

The format is divided between directory entries, which contains information about the actual files in the img archive, and the actual files, which are stored (usually) unsorted, uncompressed and linear (no directory tree).

Directory entries should be in the same order as the files are stored, and there should not be any empty block between files. This is because the game might read more than one file with a single system call. By not following this rule, the game might get unstable.

Version 1 - GTA III & VC

In this version, the directory and the raw files are stored in separate files, the directory entries are stored in a .dir and the content pointed by the directory in the .img itself.

The directory archive (.dir) must have the same name as the .img archive, except for the extension. The directory archive is pretty simple, it contains no header, just the following structure repeated until the end of the file.

Directory Entry

Size of 32 bytes

 4 byte - DWORD 	- Offset (in sectors)
 4 byte - DWORD 	- Size (in sectors)
24 byte - CHAR[24]	- Name of the file (null terminated)

The total number of entries can be found by dividing the size of the .dir file by 32.

The .img file itself has no special structure or header, just all the files pointed by the directory.

This format was also used in the PC version of Bully: Scholarship Edition.

Compression

The XBOX versions of GTA III and GTA Vice City use lzo1x-999 compression on TXD and DFF files.

TXD Archive Compression

The lzo compression stream uses a similar format as was used in the lzo library examples. It consists of a master header that is followed by a number of compression blocks. Each compression block can have an arbitrary size, but all of them together have to match the compression data size that is provided in the master header.

Master header:

4 byte - DWORD - magic number (0x67A3A1CE little endian)
4 byte - DWORD - checksum
4 byte - DWORD - size of entire compression data (pre-block-header + file data)

To detect whether a stream is lzo compressed, it is recommended to check if the magic number as well as its structure make sense. Just checking the magic number can be sufficient for RenderWare streams and other Rockstar related formats but is ill-advised in general practice.

Once detected you have to read the compressed data stream. This is done by first reading a per-block header.

Per-block header + compression data:

4 byte - DWORD - always 4 (?)
4 byte - DWORD - suggested decompressed size
4 byte - DWORD - size of compressed block

byte[n] - compressed block

This header represents a compression unit. This means that the data that follows this block has to be (de-)compressed using the lzo1x_decompress_safe routine of the lzo library. The resulting decompressed data is arbitarily bigger than its compressed counter-part, so please do not use a fixed-size output buffer.

For compressing data, you have to split the input data stream into chunks and compress each one individually. The Rockstar games compressor divided the data into a continuous row of 0x00020000 (131072) byte chunks. Doing that is recommended since working on smaller temporary memory buffers is memory friendly. It also means that, practically, each compression unit can only decompress to 131072 bytes in memory, allowing for architecture specific optimizations.

Checksum calculation is currently undocumented (not required for decompression).

Version 2 - GTA SA

Introduced with GTA San Andreas, combines the directory entries (.dir) and raw files (.img) into one .img file. The directory has the same format as in version 1, but is located at the beginning of the archive. File offsets are relative to the start of the whole archive, not to the end of the file list.

Header

Size of 8 bytes

4 byte - CHAR[4]	- "VER2"
4 byte - DWORD		- Number Of Entries

Followed by the header, there are the directory entries, containing information about the files in the archive.

Directory Entry

Size of 32 bytes

 4 byte - DWORD 	- Offset (in sectors)
 2 byte - WORD		- Streaming Size (in sectors)
 2 byte - WORD		- Size in archive (in sectors) (always 0)
24 byte - CHAR[24]	- Name of the file (null terminated)

The streaming size is how many actual sectors the file takes in memory. If streaming size is 0, size will be used as streaming size. The stock img files never used streaming size (thus always 0), it's believed that this mechanism would be used for compression of files, but it never made it's way into production.

A major drawback of this format is the complicated extendability. If you have to add many files, it might happen that you run out of space for the directory, and have to move the first file(s) to the end.

Version 3 - GTA IV

GTA IV introduced yet another .img file format. Not only the format is new, also there can be encrypted archive headers (see below). The internal IMG parser of the game works with 2 kb buffers, which means that the 2 kb bounds from earlier versions (sectors) are still present, yet optional.

IMG Header

The header of an unencrypted file always has a size of 20 bytes.

4 byte - DWORD      - Identifier (0xA94E2A52 if the archive is not encrypted)
4 byte - DWORD      - Version (always 3, if not the format would be differ)
4 byte - DWORD      - Number of Items
4 byte - DWORD      - Table Size (in bytes)
2 byte - WORD       - Size of Table Items (needs to be always 0x10)
2 byte - WORD       - Unknown

IMG Table

The table holds information about the items. Each item header has a size of 16 bytes .

4 byte - DWORD      - Itemsize (in bytes)
4 byte - DWORD      - Resource type
4 byte - DWORD      - Offset (in sectors)
2 byte - WORD       - Used Blocks
2 byte - WORD       - Padding

Item Names' length will be calculate as :

Table Size - (Number of Items * Item Size)

Next that string will be split by '\x0'

A resource type is identified by the 4b DWORD value:

  • 0x01: Generic
  • 0x08: Texture archive
  • 0x20: Bounds
  • 0x6E: Model file
  • 0x24: xpfl

Encryption

The header and directory (table) of IMG archives can be encrypted. This is usually the case if the 4 byte identifier at the start of the file seems invalid. Decryption is done via 16 repetitions of AES-128 in ECB mode.

Additional archives

It is possible to add additional IMG archives to the current default ones. The following examples are lines that can be added anywhere in either the default.dat or gta*.dat files.

GTA III Vice City CDIMAGE MODELS\FOO.IMG
San Andreas IMG MODELS\FOO.IMG

Where FOO can be any name. The FOO.IMG (and FOO.DIR for GTA III and Vice City) must be created and placed within the ..\models folder in these examples. This method is primarily used for modifying version 2 of San Andreas, as well as for storing assets (models/textures/etc.) used in total conversions.

By default GTA San Andreas is able to load max of 8 archives (3 standard archives gta3.img, gta_int.img, player.img and 5 archives defined within default.dat or gta.dat). GTA VC is able to load max of 8 archives (one archive is hard-coded to be loaded - gta3.img) too. Using more than 8 archives crashes the game, although this can be fixed with fastman92's IMG Limit Adjuster.

Coding example

IMG v2 C++ library

Usage

IMGArchive* newIMgArchive = new IMGArchive("archive.img");
IMGArchiveFile* newFile = newIMgArchive->getFileByID(o);
if (newFile != NULL)
{
//Do some operations
cout << newFile->fileEntry->fileName << endl;
//Can get all bytes for the file and write it out into the separate file
}
delete newFile;
delete newIMgArchive;

Tools

GTA III Vice City San Andreas GTA Net GTAGarage: IMG Factory(Recommended) – by X-Seti
GTA III Vice City San Andreas GTA Net GTAForums: fastman92 IMG Console(Recommended) – by fastman92
GTA III Vice City ImgEd – by Dan Strandberg
GTA III Vice City San Andreas GTA IV IMG Manager – by xmen
San Andreas GTA Net GTAGarage: Spark – by aru
GTA III Vice City San Andreas IMG Tool – by Spooky
GTA III Vice City San Andreas G-IMG – by REspawn
Vice City San Andreas GTA Net GTAForums: IMG & Stream Limit Adjuster – by fastman92
Vice City San Andreas GTA Net GTAForums: Fastman92 Limit Adjuster – by fastman92
Liberty City Stories Vice City Stories Post.png GTAForums: GTA Stories IMG Tool – by HackMan128
GTA IV SparkIV – by aru
GTA IV OpenIV – by GooD-NTS
GTA IV Shadow-Mapper – by Prince-Link

Libraries

Version 2 only

Version 3 only