This article deals with the format of a save game file for the PC version of GTA 3.
Location
By default, the game places its save game files into the folder "GTA3 User Files" which is located in the current user's Documents folder. The location of this folder varies depending upon the version of Windows installed.
The save files themselves are named in the format GTA3sfX.b where X represents the in-game slot number. There are 8 slots available in the game (1-8).
Format Details
- Save files are ALWAYS 0x3145C (201820) bytes long.
- Byte order is little endian. For example, the number 3452 (0x0D7C) is represented as as 0x7C 0x0D.
- File is divided into 20 blocks, followed by padding and then ending with a 4-byte checksum
Data Blocks
There is a DWORD value preceding any block of data which is equal to the size of the block.
Block 1: Miscellaneous
Game "meta-information" giving the overall state of things. Also includes 'TheScripts' sub-block.
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size
|
0x0004 |
wchar_t[24] |
save name (long names are truncated on the save/load screen)
|
0x0034 |
word |
SYSTEMTIME wYear
|
0x0036 |
word |
SYSTEMTIME wMonth
|
0x0038 |
word |
SYSTEMTIME wDayOfWeek
|
0x003A |
word |
SYSTEMTIME wDay
|
0x003C |
word |
SYSTEMTIME wHour
|
0x003E |
word |
SYSTEMTIME wMinute
|
0x0040 |
word |
SYSTEMTIME wSecond
|
0x0042 |
word |
SYSTEMTIME wMilliseconds
|
0x0044 |
dword |
unknown
|
0x0048 |
enum |
current island (1=Portland; 2=Staunton; 3=Shoreside Vale)
|
0x004C |
float[3] |
camera coordinates (x,y,z)
|
0x0058 |
dword |
length (ms) of in-game minute
|
0x005C |
dword |
weather timer
|
0x0060 |
byte |
game hour
|
0x0061 |
byte[3] |
(align)
|
0x0064 |
byte |
game minute
|
0x0065 |
byte[3] |
(align)
|
0x0068 |
word |
(unknown) current pad
|
0x006A |
byte[2] |
(align)
|
0x006C |
dword |
global timer
|
0x0070 |
float |
game speed
|
0x0074 |
float |
(unknown) frame delta time
|
0x0078 |
float |
(unknown) tick time (time of an iteration of the major game loop)
|
0x007C |
dword |
number of the frames processed from the beginning of the game
|
0x0080 |
float |
(unknown)
|
0x0084 |
float |
(unknown)
|
0x0088 |
float |
(unknown)
|
0x008C |
word |
(unknown)
|
0x008E |
byte[2] |
(align)
|
0x0090 |
word |
(unknown)
|
0x0092 |
byte[2] |
(align)
|
0x0094 |
word |
(unknown)
|
0x0096 |
byte[2] |
(align)
|
0x0098 |
float |
(unknown)
|
0x009C |
dword |
(unknown)
|
0x00A0 |
dword |
(unknown)
|
0x00A4 |
dword |
(unknown)
|
0x00A8 |
dword |
(unknown)
|
0x00AC |
dword |
(unknown)
|
0x00B0 |
dword |
(unknown)
|
0x00B4 |
dword |
(unknown)
|
0x00B8 |
float |
(unknown)
|
0x00BC |
float |
(unknown)
|
0x00C0 |
TheScripts |
various scripts information
|
TheScripts
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size
|
0x0004 |
char[4] |
'SCR\0' signature
|
0x0008 |
ScriptData |
data dumped from the main.scm
|
ScriptData
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size
|
0x0004 |
dword |
script global variables amount (n)
|
0x0008 |
dword[n] |
script global variables dump
|
0x0000 |
ScriptInfo |
various info from scripts
|
0x03CC |
dword |
threads amount (n2)
|
0x03D0 |
CRunningScript[n2] |
script threads dump
|
ScriptInfo
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size (always 0x3C8)
|
0x0004 |
dword |
$onmission var offset
|
0x0008 |
ContactInfo[16] |
contacts info
|
0x0088 |
Unknown[4] |
(unknown)
|
0x0188 |
dword |
(unknown)
|
0x018C |
StaticReplacement[25] |
static replacements
|
0x031C |
InvisibleObject[20] |
invisible objects
|
0x03BC |
byte |
(unknown) unused, always 1
|
0x03BD |
byte[3] |
(align)
|
0x03C0 |
dword |
size of the MAIN section in the main.scm
|
0x03C4 |
dword |
biggest mission size
|
0x03C8 |
word |
missions count
|
0x03CA |
byte[2] |
(align)
|
ContactInfo
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
mission_flag (opcode 0181)
|
0x0004 |
dword |
base_brief (opcode 0182)
|
StaticReplacement
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
type
|
0x0004 |
dword |
building handle
|
0x0008 |
dword |
new model
|
0x000C |
dword |
old model
|
InvisibleObject
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
type
|
0x0004 |
dword |
handle
|
CRunningScript
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
CRunningScript * |
next script
|
0x0004 |
CRunningScript * |
prev script
|
0x0008 |
char[8] |
name
|
0x0010 |
dword |
current_ip
|
0x0014 |
dword[4] |
return_stack
|
0x0024 |
dword |
|
0x0028 |
dword |
|
0x002C |
word |
stack_counter
|
0x002E |
word |
|
0x0030 |
dword[16] |
locals
|
0x0070 |
dword |
timerA
|
0x0074 |
dword |
timerB
|
0x0078 |
byte |
|
0x0079 |
byte |
|
0x007A |
byte |
|
0x007B |
byte |
|
0x007C |
dword |
wake time
|
0x0080 |
word |
|
0x0082 |
byte |
|
0x0083 |
byte |
|
0x0084 |
byte |
|
0x0085 |
byte |
|
0x0086 |
byte |
|
0x0087 |
byte |
|
Block 2: Player peds
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size
|
0x0004 |
PlayerPeds |
player peds information
|
PlayerPeds
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size
|
0x0004 |
dword |
players count (n)
|
0x0008 |
PlayerPed[n] |
player peds array
|
PlayerPed
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
unknown
|
0x0004 |
word |
unknown
|
0x0006 |
dword |
(unknown) ped reference
|
0x000A |
CPed |
CPed dump (0x5F0 bytes)
|
0x05FA |
dword |
max wanted level
|
0x05FE |
dword |
max chaos level
|
0x0602 |
char[24] |
model name
|
Block 3: Garages
Block 4: Vehicles pool
Block 5: Objects pool
Block 6: Path find
Block 7: Cranes
Block 8: Pickups
Block 9: Phone info
Block 10: Restarts
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size (constant 0x128)
|
0x0004 |
RestartBlock |
restart block
|
RestartBlock
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size (constant 0x124)
|
0x0004 |
char[4] |
'RST\0' signature
|
0x0008 |
RestartData |
restart data
|
RestartData
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
dword |
block size
|
0x0004 |
RestartPoint[8] |
restart point after wasted
|
0x0084 |
RestartPoint[8] |
restart point after busted
|
0x0104 |
word |
wasted restart points count
|
0x0106 |
word |
busted restart points count
|
0x0108 |
byte |
override next restart flag (opcodes 016E, 0255)
|
0x0109 |
byte[3] |
(align)
|
0x010C |
RestartPoint |
overriden restart point (opcodes 016E, 0255)
|
0x011C |
byte |
fade in after next death flag (opcode 040F)
|
0x011D |
byte |
fade in after next arrest flag (opcode 040E)
|
0x011E |
byte |
override hospital level flag (opcode 041F)
|
0x011F |
byte |
override police level flag (opcode 0420)
|
RestartPoint
OFFSET
|
TYPE
|
DESCRIPTION
|
0x0000 |
float[3] |
x,y,z coordinates
|
0x000C |
float |
z_angle
|
Block 11: Radar
Block 12: Zones
Block 13: Gangs
Block 14: Car Generators
Block 15: Particle objects
Block 16: Audio script objects
Block 17: Player info
Block 18: Stats
Block 19: Streaming
Block 20: Ped types
Padding
Following the last data block is a variable amount of padding. Since every save file is exactly 0x3145C bytes in length this padding is necessary to fill the space between the data blocks which start the file and the checksum value which ends it. There could be up to 4 padding blocks, each one is up to 55,000 bytes in length.
Checksum
The final four bytes of a save file are an unsigned integer checksum value. This checksum is simply the sum of all the preceding 0x3145C bytes. If the checksum value does not match the calculated sum of those bytes, the game will consider the save file to be "corrupted" and refuse to load it. Thus, any time you make any changes to a save file you must remember to update the checksum when you are finished.
See also
External links