Saves (GTA SA)
Contents
- 1 Introduction
- 2 Location and Format Overview
- 3 Format Details
- 3.1 Data Blocks
- 3.1.1 Block 0: Miscellaneous
- 3.1.2 Block 1: Script
- 3.1.3 Block 2: Objects
- 3.1.4 Block 3: Garages
- 3.1.5 Block 4: (Unknown)
- 3.1.6 Block 5: Disabled Pathnode Cubes
- 3.1.7 Block 6: Pickups
- 3.1.8 Block 7: (Unknown)
- 3.1.9 Block 8: Restart Locations
- 3.1.10 Block 9: Radar Blips
- 3.1.11 Block 10: Zones
- 3.1.12 Block 11: Gang weapons
- 3.1.13 Block 12: Car Generators
- 3.1.14 Block 13: (Unknown)
- 3.1.15 Block 14: (Unknown)
- 3.1.16 Block 15: (Unknown)
- 3.1.17 Block 16: Player Stats
- 3.1.18 Block 17: (Unknown)
- 3.1.19 Block 18: (Unknown)
- 3.1.20 Block 19: (Unknown)
- 3.1.21 Block 20: (Unknown)
- 3.1.22 Block 21: (Unknown)
- 3.1.23 Block 22: (Unknown)
- 3.1.24 Block 23: (Unknown)
- 3.1.25 Block 24: (Unknown)
- 3.1.26 Block 25: ENEX Connections
- 3.1.27 Block 26: (Unknown)
- 3.1.28 Block 27: (Unknown)
- 3.2 Padding
- 3.3 Checksum
- 3.1 Data Blocks
Introduction
This article deals with the format of a saved game file for Grand Theft Auto: San Andreas (GTASA). It is specifically geared towards the PC version(s) but much of it may be applicable to console versions too.
Location and Format Overview
By default, GTASA places its saved game files into the folder "GTA San Andreas 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. Some typical locations for a user with an account named "Fred" would be:
- C:\My Documents\GTA San Andreas User Files -- Windows 98 Example
- C:\Documents and Settings\Fred\My Documents\GTA San Andreas User Files -- Windows XP Example
- C:\Users\Fred\Documents\GTA San Andreas User Files -- Windows Vista Example
Obviously those locations can vary based upon different Windows configurations or installation options. Note also that the executable can be modified to use a different file location through the use of a hex editor and special registry key in a process outlined at GTAForums
The save files themselves are named in the format GTASAsfX.b where X represents the in-game slot number. So, the game saved in slot 1 will be stored in the save file GTASAsf1.b and the game saved in slot 5 will be stored in the save file GTASAsf5.b. There are 8 slots available in the game (1-8). GTASA save files are always 0x31800 bytes long (202,752 in decimal) and are not compressed or encoded in any way.
Format Details
A GTASA save file consists of 28 "blocks" of data followed by some duplicated data for padding and then ending with a checksum value. Each of these elements is described below.
Data Blocks
Each data block consists of the 5 characters BLOCK followed by a variable amount of data; in general, each block has its own unique internal format. The format descriptions in this article only deal with those internal block formats which follow the initial BLOCK identifier and all offsets start at the byte following the BLOCK identifier for the given block.
Block 0: Miscellaneous
Game "meta-information" giving the overall state of things. This block has a constant length of 0x138 bytes
OFFSET TYPE DESCRIPTION 0x0000 dword Version ID String (Checksum of a string describing the time of compilation. See note 1 below) 0x0004 char[100] Save Name String (Long names are truncated on the save/load screen. See note 2 below) 0x0068 byte Current Missionpack 0x0069 byte[7] (Unknown) 0x0070 float[3] Camera Coordinates (x,y,z) 0x007C dword Length (ms) of in-game minute 0x0080 dword Weather Timer 0x0084 byte[2] (Unknown) 0x0086 byte Game Hour 0x0087 byte Game Minute 0x0088 byte[12] (Unknown) 0x0094 dword Global Timer 0x0098 float Game Speed 0x009C byte[32] (Unknown) 0x00BC dword Current Camera View 0x00C0 byte[36] (Unknown) 0x00E4 dword Max Wanted Level 0x00E8 dword Possible Police Aggression Level 0x00EC byte[50] (Unknown) 0x011E word SYSTEMTIME year 0x0120 word SYSTEMTIME month 0x0122 word SYSTEMTIME wkday 0x0124 word SYSTEMTIME day 0x0126 word SYSTEMTIME hour 0x0128 word SYSTEMTIME min 0x012A word SYSTEMTIME sec 0x012C word SYSTEMTIME ms 0x012E byte[10] (Unknown)
Notes:
- Version 2.0 of GTASA will not load a save file if the Version ID String does not match its own Version ID String. Thus if a game was played on a version 1.x exe using the exact same set of mission scripts as a version 2.0 installation, the version 2.0 game will refuse to load the save unless this ID is changed. Version 1.x exes make no Version ID String check and will attempt to load any non-corrupted save. Some known Version ID String values (listed as consecutive bytes):
- 0x75 0x81 0xDA 0x35 -- Version 1.00 Unmodified EXE
- 0x83 0xE5 0xF3 0x65 -- Version 1.00 Modified EXE
- 0x58 0xBE 0x6E 0x9A -- Version 1.01 Unmodified EXE
- 0x5E 0x76 0x45 0x93 -- Version 1.01 Modified EXE
- 0xF6 0x8D 0x14 0xFD -- Version 2.00 Unmodified EXE
- While the save name can be changed here to pretty much anything, that name will not persist the next time the game is saved, even if no missions were completed during the play session. This is because each time the game is saved this name string is reset based upon the GXT entry for the Last Mission Passed key stored in Block 15.
Block 1: Script
Information pertaining to the Mission Scripts in use when the game was saved. Includes all global variables and information about running threads including thread pointers and local variables. A minor size difference between the MAIN section of the version 1 and version 2 scripts is the primary cause of incompatibility between version 1 and version 2 saves because it forces the other threads to be at slightly different memory locations. One can adjust the thread pointers in this block and (if converting from 1 to 2) the Version ID String from block 0 to convert a save between the two versions; this applies to either completely unmodded or identically-modded installations of v1 and v2.
As the first section in this block can vary in size, offsets given are from the current section.
OFFSET TYPE DESCRIPTION 0x0000 dword Size of Global Variable space 0x0004 dword[] Global Variable Space -- every var is 4 bytes; the types can vary ... 0x0000 byte[2306] (Unknown) -- Info related to various opcodes ... 0x0000 dword Number of Running Threads 0x0004 Thread[] Thread structures -- each is 0x106 bytes in size; see details below
Thread Structure: 0x00 word Index/Handle 0x02 byte[224] Thread Memory Dump -- see details below 0xE2 byte[36] Relative Addresses -- see details below
Thread Memory Dump: 0x00 dword Next Pointer 0x04 dword Previous Pointer 0x08 char[8] Thread Name 0X10 dword Absolute Base Address 0x14 dword Absolute IP 0x18 dword[8] Absolute Return Stack 0x38 word Stack Pointer 0x3C dword[32] Local Variables 0xBC dword[2] Local Timers 0xC4 byte (Unknown) 0xC5 byte 'if' statement result 0xC6 byte (Unknown) 0xC7 byte Is External Script 0xC8 byte[4] (Unknown) 0xCC dword Wakeup Time 0xD0 word 'if' paramter 0xD2 byte 'not' flag 0xD3 byte 'wb_check' flag 0xD4 byte[4] (Unknown) 0xD8 dword New script IP -- 0 if absolute IP has been calculated from this 0xdc byte Is Mission 0xdd byte[3] (Unknown)
Relative Addresses: (Necessary here because the absolute addresses used in-game depend on memory layout) 0x00 dword Relative IP 0x04 dword[8] Relative Return Stack
Block 2: Objects
Mission-script placed objects such as doors, etc.
OFFSET TYPE DESCRIPTION 0x0000 byte[552] (Unknown) 0x0228 dword Number of Objects 0x022C Object[] Object structures -- each is 0x3C bytes in size; see details below
Object Structure: 0x00 byte[4] (Unknown) 0x04 dword (Unknown) Possibly Model 0x08 byte[4] (Unknown) 0x0C float[3] Coordinates (x,y,z) 0x18 byte[36] (Unknown)
Block 3: Garages
Information defining all garages (including bomb shops, pay & sprays, etc.) and also describing the cars stored in safehouse garages. This block can vary in size although in the unmodified game it will always be 0x23C7 bytes because there are 50 garages defined. The 80 saved vehicles (4 each in 20 garages) is a fixed number and probably cannot be exceeded. Also, the arrangement of the Garage Car structures in the save is non-intuitive: they follow the pattern Garage 1/Car 1, Garage 2/Car 1, ... Garage 20/Car 1, Garage 1/Car 2, Garage 2/Car 2 ...
OFFSET TYPE DESCRIPTION 0x0000 dword Number of Garages 0x0004 byte[35] (Unknown) 0x0027 GrgCar[20][4] Garage Car structures -- each is 0x40 bytes in size; see details below 0x1427 Garage[] Garage structures -- each is 0x50 bytes in size; see details below
Garage Car Structure (GrgCar): 0x00 float[3] Coordinates (x,y,z) 0x0c byte[52] (Unknown)
Garage Structure: 0x00 byte Garage Type 0x01 byte[3] (Unknown) 0x04 float[3] Coordinates (x,y,z) Possibly Lower Left Front 0x10 float[4] Rotation (Quaternion Rx, Ry, Rz, Rw) 0x20 float Top Z Coordinate 0x24 float Width 0x28 float Depth 0x2c float (Unknown) X 0x30 float (Unknown) X 0x34 float (Unknown) Y 0x38 float (Unknown) Y 0x3c float (Unknown) 0x40 float (Unknown) 0x44 char[8] Garage Name 0x4c word (Unknown) Possibly Original Type
Block 4: (Unknown)
Unknown data. Block can vary in size depending on number of entries; number of entries may be zero.
OFFSET TYPE DESCRIPTION 0x0000 dword Number of Entries 0x0004 byte[7] (Unknown) 0x000b Blk4Entry[] Entry structures -- each is 0x10 bytes in size; details unknown
Block 5: Disabled Pathnode Cubes
0 dword count 4 entries Entry structure: 0 float[6] x1,x2,y1,y2,z1,z2 18 byte[4] bools that somehow indicate which pathtypes are enabled 1c end
Block 6: Pickups
0 Pickup[620] pickups 4d80 word 4d82 byte 4d83 dword[20] 4dd3 end
Pickup structure: 8 dword ammo 10 word[3] x,y,z, all multiplied by 8 18 word model 1c byte type 20 end
Block 7: (Unknown)
(Usually empty)
Block 8: Restart Locations
---- wasted: 0 word count 2 restart structures ---- busted: 0 word count 2 restart structures ---- unknown things: 0 some bytes, floats, and dwords 37 end Restart structure: 0 float[3] coords c float heading 10 dword island 14 end
Block 9: Radar Blips
0 Blip[175] blips
Blip structure: 8 float[3] coords 28 end
Block 10: Zones
4 word count for first array 6 word count for second array 8 word count for third array a end ---- the three arrays: See structure descriptions below. First = info.zon, third = map.zon. ---- unknown: 68 end
First and third array structure: 0 char[8] zone name 8 char[8] zone group name 10 word[6] x1,y1,z1,x2,y2,z2 (rounded to ints) 1c word id 1e byte type 1f byte island 20 end Second array structure: 11 end
Block 11: Gang weapons
0 byte unused 4 dword weaponID A 8 dword weaponID B 12 dword weaponID C end
Notes:
- Blocks count 10
- Data can be changed by opcode 0237
Block 12: Car Generators
0 dword count 6 car generators ---- numberplates: 0 dword num entries used 4 Numplate[15] number plates f4 end
Car generator structure: 0 word handle (0..499) 2 word model 4 byte[2] colors 6 word[3] x,y,z, all multiplied by 8 c byte heading/360*256 d byte alarm chance e byte locked chance f byte flags: bit 1 = belongs to player 12 word monetary value 16 dword timer 1c word cars to generate 22 end Numplate structure: 0 dword car generator handle 4 char[8] numberplate string 10 end
Block 13: (Unknown)
(Usually Empty)
Block 14: (Unknown)
(Usually Empty)
Block 15: (Unknown)
0 dword size of block (always 28h) 4 some dwords, floats and bytes from the player structure 2c end
Block 16: Player Stats
0 float[82] float stats (numbered 0..81 in scm) 148 dword[223] int stats (numbered 120..342 in scm) 4c4 dword[32] 544 char[8] last mission passed (gxt key) 54c byte[56] 584 dword[100] 714 byte[128] 794 end
Block 17: (Unknown)
0 dword entries used 4 byte[32][210] entries 1a44 end
Block 18: (Unknown)
66cc end
Block 19: (Unknown)
280 end
Block 20: (Unknown)
0 dword size 4 bytes
Block 21: (Unknown)
0 dword 4 byte[255] 103 end
Block 22: (Unknown)
0 dword count 4 entries (8 bytes each) ---- 0 dword size 4 bytes
Block 23: (Unknown)
0 dword size of block (always 58h) 5c end
Block 24: (Unknown)
0 dword count 4 entries (68 bytes each)
Block 25: ENEX Connections
0 dword count 4 array of words ---- Followed by a weird array: 1. Read a word. 2. If it is -1, you've reached the end of this block. 3. Otherwise, it's an index. Read two more words for this entry and go back to 1.
Block 26: (Unknown)
0 Structure[14] ee0 byte[28] efc end
Structure: 0 byte[20] 14 dword[8] 34 dword[40] d4 dword[15] 110 end
Block 27: (Unknown)
0 byte[28][5] structures from opcode 0a40 8c end
Padding
Following the last data block is a variable amount of padding. Since every save file is exactly 0x31800 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. Because GTASA internally uses a buffer of 0xC800 bytes for writing a save, each byte of padding data is simply a repetition of the data located 0xC800 bytes before it. While it is not strictly necessary to follow this convention for the padding when writing a modified save file, it is consistent with the original game and makes modifications harder to detect.
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 0x317FC 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.