Saves (GTA SA)
This article deals with the format of a save game file for GTA San Andreas. 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, GTA SA 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 or use Save Game Path Editor
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.
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.
Note that many of the blocks contain data structures. These structures are aligned along 4-byte boundaries; thus if there's a field with size 1 or 2 bytes in the end of structure, there are also additional unused bytes present at the end of the structure which pad it to fill the remaining space. This type of gap can also occur in the middle of a structure. The convention used by this article is to mark such gaps as an array of bytes with the description (Align) .
Block 0: Miscellaneous
Game "meta-information" giving the overall state of things. This block has a constant length of 0x138 bytes
|0x0000||dword||version ID (checksum of a string describing the time of compilation)|
|0x0004||char||save name (long names are truncated on the save/load screen)|
|0x0068||byte||current mission pack|
|0x006C||dword||current town (island) (used when a replay playback is started/finished)|
|0x0070||float||camera coordinates (x,y,z)|
|0x007C||dword||length (ms) of in-game minute|
|0x0084||byte||current in-game month|
|0x0085||byte||current in-game month day|
|0x0089||byte||current in-game month (copy)|
|0x008A||byte||current in-game month day (copy)|
|0x008B||byte||game hour (copy)|
|0x008C||byte||game minute (copy)|
|0x008D||byte||Boolean: time copy flag|
|0x0090||byte||Boolean: has ever cheated flag|
|0x009C||float||frame delta time|
|0x00A0||float||tick time (time of an iteration of the major game loop)|
|0x00A4||dword||number of the frames processed from the beginning of the game|
|0x00A8||word||previous weather ID|
|0x00AA||word||current weather ID|
|0x00AC||word||forced weather ID|
|0x00B0||dword||weather interpolation value|
|0x00B4||dword||weather type in list|
|0x00B8||float||amount of rain|
|0x00BC||dword||vehicle camera view (opcode 09AD)|
|0x00C0||dword||onfoot camera view|
|0x00C8||byte||Boolean: invert look (unused on PC)|
|0x00CC||dword||extra (interior) color ID|
|0x00D0||byte||extra (interior) color toggle state|
|0x00D4||float||extra (interior) color interpolation value|
|0x00D8||dword||extra (interior) color weather ID|
|0x00DC||dword||current water configuration (always 0)|
|0x00E0||byte||Boolean: riot mode flag (opcode 06C8)|
|0x00E1||byte||Boolean: unknown, related to riots (always 0)|
|0x00E4||dword||max wanted level (opcode 01F0)|
|0x00EC||byte||is french language set (does nothing)|
|0x00ED||byte||is german game (opcode 040C; not affected by the language)|
|0x011C||byte||times left to display a cinematic camera help|
|0x0130||dword||Player target marker handle (handle of the red target icon in the map menu)|
|0x0134||byte||Boolean: the vehicle stealing help was shown|
|0x0135||byte||Boolean: All taxis have nitro (opcode 0572 flag)|
|0x0136||byte||Boolean: Prostitutes pay you (opcode 0A3D flag)|
^ 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
- 0x22 0xCC 0x31 0x5D -- Version 2.00 (German)
- 0xF6 0x8D 0x14 0xFD -- PS2 Version 2 (Greatest Hits)
- 0x4C 0xDC 0x1D 0x64 -- PS2 Version 1 (Original Edition)
^ 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 16.
^ Time copy flag shows whether the time data was saved using opcode 0253.
^ Chaos is a value need to be gained to get one more star. MaxChaos is a limit for current wanted level.
^ When the censore flag is set to 0, some actions are disabled in the game, such as money drop from the killed people, no more headshots, etc. This flag is controlled by what language you are using. If it's English, this flag is set to 1.
^ This is a number of how much times the cinematic camera help (about switching display modes) will be shown. Initially this value equals to 2. When it reaches zero, the help does not appear on cinematic camera enabling.
^ This is a flag, which is set to 1 when player first time stealing a vehicle and get a help message about it, to prevent displaying this message again.
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 ExternalScriptTrigger each is 0x14 bytes in size; see details below 0x0578 dword OnMissionFlag offset -- address of the global variable set by opcode 0180 0x057C dword time when last mission was passed (when either opcode 0318 or 0595 is executed) 0x0580 StaticReplacement each is 0x10 bytes in size; see details below 0x0710 InvisibleObject each is 8 bytes in size; see details below 0x07B0 dword keeps model identifiers which are excluded from the carparking generation (similar to opcode 03C5). Unused. 0x0800 LodAssignment each is 8 bytes in size; see details below 0x0850 ScriptAssignment each is 0x14 bytes in size; see details below 0x08F0 byte Boolean: unknown flag (UNUSED) 0x08F1 byte Boolean: unknown flag (UNUSED) 0x08F2 dword scm size 0x08F6 dword max mission size 0x08FA dword missions number 0x08FE dword highest local variable ever in a mission 0x0902 dword Number of Running Threads (nThreads) 0x0906 Thread[nThreads] Thread structures -- each is 0x106 bytes in size; see details below
ExternalScriptTrigger 0x00 word Index in the script.img 0x02 byte Attach type (actor or object) 0x03 byte Type? -- only for ObjectTrigger 0x04 dword Status? 0x08 float Radius -- vary only for ObjectTrigger (ActorTrigger uses a pre-defined radius of 5.0) 0x0C word modelID 0x0E word chance of initialization (in percents) 0x10 dword (unknown) 0x14 end
Thread Structure: 0x00 word Index/Handle 0x02 byte Thread Memory Dump -- see details below 0xE2 byte Relative Addresses -- see details below
Thread Memory Dump: 0x00 dword Next Pointer 0x04 dword Previous Pointer 0x08 char Thread Name 0x10 dword Absolute Base Address 0x14 dword Absolute IP 0x18 dword Absolute Return Stack 0x38 word Stack Pointer 0x3A byte (Align) 0x3C dword Local Variables 0xBC dword Local Timers 0xC4 byte Boolean: is active 0xC5 byte Boolean: 'if' statement result 0xC6 byte Boolean: uses mission cleanup 0xC7 byte Boolean: is external 0xC8 byte Boolean: overrides text box 0xC9 byte External script attach type 0xCA byte (Align) 0xCC dword Wakeup Time 0xD0 word Boolean: 'if' check result 0xD2 byte Boolean: 'not' flag 0xD3 byte Boolean: is Wasted/Busted check active 0xD4 byte Boolean: is Wasted/Busted 0xD5 byte (Align) 0xD8 dword Skip Scene Pos (opcode 0707) 0xDC byte Boolean: is mission 0xDD byte (Align) 0xE0 end
Relative Addresses Necessary here because the absolute addresses used in-game depend on memory layout 0x00 dword Relative IP 0x04 dword Relative Return Stack
StaticReplacement 0x00 dword type (always = 2) 0x04 dword handle of the static object (building) 0x08 dword new modelID 0x0C dword old modelID
Note: this structure related to opcode 03B6.
InvisibleObject 0x00 dword type 0x04 dword handle of the object
This structure contains handle and type of an object created as invisible one. There are 3 kinds of the types: 2 - static object; 3 - dynamic object; 4 - dummy. Via mission scripting it's only possible to create a first kind of such object (static) - using opcode 0363, so normally the 'type' parameter is equal to 2.
LodAssignment 0x00 dword Handle of the object 0x04 dword Handle of the LOD object
This structure related to opcode 0827.
ScriptAssignment 0x00 dword modelID of the actor we assing the external script to 0x04 char external script handle as created with opcode 0884 0x0C dword unknown 0x10 dword unknown
This structure related to opcode 08E8.
Block 2: Players & Objects
Information about players (commonly only one) and mission-script placed objects such as doors, etc.
OFFSET TYPE DESCRIPTION 0x00 dword Number of Players 0x04 Player Player structures -- each is 0x224 bytes in size; see details below 0x00 dword Number of Objects 0x04 Object Object structures -- each is 0x3C bytes in size; see details below
Player Structure: 0x0000 dword Handle of a player actor 0x0004 dword Model ID 0x0008 dword Ped type
0x000C dword size of the following data (0x18C) 0x0010 float X, Y, Z 0x001C float Health 0x0020 float Armor 0x0024 Weapon Weapon Structure -- each is 0x1C in size; see details below 0x0190 byte Ped reference (normally 2) 0x0191 byte Current weapon slot 0x0192 byte unknown 0x0193 byte (Align) 0x0194 dword unknown (ENEX related) 0x0198 byte melee style 1? 0x0199 byte melee style 2? 0x019A byte (Align)
0x019C dword size of the following data (0x84) 0x01A0 dword chaos 0x01A4 byte wanted level 0x01A5 byte (Align) 0x01A8 dword CRC32 of filename for Torso model 0x01AC dword CRC32 of filename for Head model 0x01B0 dword CRC32 of filename for Hands model 0x01B4 dword CRC32 of filename for Legs model 0x01B8 dword CRC32 of filename for Feet model 0x01BC dword CRC32 of filename for Chain model 0x01C0 dword CRC32 of filename for Watch model 0x01C4 dword CRC32 of filename for Shades model 0x01C8 dword CRC32 of filename for Hat model 0x01CC dword CRC32 of filename for Special model 0x01D0 dword CRC32 of filename for Torso texture 0x01D4 dword CRC32 of filename for Head texture 0x01D8 dword CRC32 of filename for Legs texture 0x01DC dword CRC32 of filename for Feet texture 0x01E0 dword CRC32 of filename for Upper Left Arm Tattoo texture 0x01E4 dword CRC32 of filename for Lower Left Arm Tattoo texture 0x01E8 dword CRC32 of filename for Upper Right Arm Tattoo texture 0x01EC dword CRC32 of filename for Lower Right Arm Tattoo texture 0x01F0 dword CRC32 of filename for Back Tattoo texture 0x01F4 dword CRC32 of filename for Left Chest Tattoo texture 0x01F8 dword CRC32 of filename for Right Chest Tattoo texture 0x01FC dword CRC32 of filename for Stomach Tattoo texture 0x0200 dword CRC32 of filename for Lower Back Tattoo texture 0x0204 dword CRC32 of filename for Chain texture 0x0208 dword CRC32 of filename for Watch texture 0x020C dword CRC32 of filename for Shades texture 0x0210 dword CRC32 of filename for Hat texture 0x0214 dword CRC32 of filename for Special texture 0x0218 float Body Fat (used for current body type) 0x022C float Body Muscle (used for current body type) 0x0230 dword (Align)
- The CRC32 is calculated of the uppercase filename without extension. After calculation the bits are inverted. The files/filenames can be found in data/shopping.dat and by extracting models/player.img. For example, for White Tank the value is 0xffffffff-crc32("VEST") = 0xbb1ca4cc for both model and texture.
Weapon Structure: 0x00 dword Weapon Type 0x04 dword (unknown) possibly Weapon state 0x08 dword (unknown) possibly Ammo in clip 0x0C dword Weapon Ammo 0x10 dword (unknown) possibly Shots fired 0x14 byte (unknown)
Object Structure: 0x00 dword Handle 0x04 dword Model ID 0x08 dword constant 48 (size of the following data) 0x0C float X, Y, Z 0x18 byte CXYZ.right.xyz 0x1B byte CXYZ.top.xyz 0x1E byte (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 Free Bombs 0x0005 byte Free Resprays (opcode 0335) 0x0006 byte Boolean: Respray Garages disabled (opcode 0A14) 0x0007 dword Cars collected (unused III/VC leftover) 0x000B dword Bank vans collected (unused III leftover) 0x000F dword Police cars collected (unused III leftover) 0x0013 dword Car types collected (unused VC leftover) 0x0023 dword Last time garage help message was displayed 0x0027 StoredCar Garage Car structures -- each is 0x40 bytes in size; see details below 0x1427 SaveGarage SaveGarage structures -- each is 0x50 bytes in size; see details below
Garage Car Structure (StoredCar): 0x00 float Coordinates (x,y,z) 0x0C dword Car Handling Flags 0x10 byte Car Flags 0x11 byte (Unknown) 0x12 word Vehicle Model ID 0x14 word Installed Vehicle Mods (see veh_mods.ide) 0x32 byte Primary Color, Secondary Color, Tertiary Color, (Unknown) Quaternary Color? 0x36 byte Radio Station [see below] 0x37 byte Vehicle Variation 0x39 byte Bomb Type 0x3A byte Paintjob 0x3B byte Nitrous Count 0x3C byte Vector Rotation 0x3F byte (unknown) Align
SaveGarage Structure: 0x00 byte Garage Type 0x01 byte Door Flags 0x03 byte (Unknown) Align 0x04 float X Coordinate for Lower Left Front 0x08 float Y Coordinate for Lower Left Front 0x0C float Z Coordinate for Floor 0x10 float Rotation (Quaternion Rx, Ry, Rz, Rw) 0x20 float Z Coordinate for Ceiling 0x24 float Width (dimension parallel to door in xy plane) 0x28 float Depth (dimension perpendicular to door in xy plane) 0x2C float Minimum X Coordinate 0x30 float Maximum X Coordinate 0x34 float Minimum Y Coordinate 0x38 float Maximum Y Coordinate 0x3C float Door is Open = 1 0x40 float (Unknown)door timer/timestamp? 0x44 char Garage Name -- can be used by mission script to access garage 0x4C word (Unknown) Possibly Original Type 0x4E byte (Align?) 0x50 end
Door Flags (hex value of bit) offset 0x01 0x01 door is open flag (0x3c changes door) offset 0x02 0x01 used mod shop (?) 0x02 inactive door 0x04 used Pay'n'Spray (?) 0x08 small door (reflective?) 0x10 up and in door 0x20 camera follows player 0x40 door is closed flag (0x3c changes door) 0x80 girlfriend PnS
Car Flags (hex value of bit) 0x01 bulletproof 0x02 fireproof 0x04 explosion proof 0x08 damage proof 0x10 5th immunity 0x20 bass boost 0x40 hydraulics 0x80 nitrous flag
Bomb Types 1 5 sec detonator (garage type 2) 2 ignition bomb unarmed (garage type 3) 3 remote detonator (garage type 4) 5 ignition bomb armed (garage type 3)
Radio Stations 0x00 vehicle has no radio 0x01 playback fm 0x02 k rose 0x03 k-dst 0x04 bounce fm 0x05 sf-ur 0x06 radio los santos 0x07 radio x 0x08 csr 103.9 0x09 k-jah west 0x0a master sounds 98.3 0x0b wctr 0x0c user track player 0x0d radio off
Block 4: Game Logic
Block can vary in size depending on number of entries; number of entries may be zero.
OFFSET TYPE DESCRIPTION 0x00 dword Number of after death start points (unused by the game) 0x04 byte Boolean: Lose stuff after wasted (opcode 08DD) 0x05 byte Boolean: Lose stuff after busted (opcode 08DE) 0x06 byte Game state (wasted/busted/on a rampage etc.) 0x07 dword Time of last event 0x0B AfterDeathStart array of after death start points (unused) -- see details below
AfterDeathStart structure: 0x00 float X, Y, Z 0x0C float Angle
Block 5: Disabled Pathnode Cubes
0x00 dword count 0x04 Entry[count] entries --0x1C size
Entry structure: 0x00 float x1,x2,y1,y2,z1,z2 0x18 byte bools that somehow indicate which pathtypes are enabled
Block 6: Pickups
0x0000 Pickup Pickups --Size 0x20 0x4D80 word Number of pickups being picked up (up to 20) 0x4D82 byte Weapon pickup message counter (see note 1 below) 0x4D83 dword Pickups being picked up (they don't exist, but could be checked by opcode 0214 0x4DD3 end
Pickup structure: 0x00 float current asset value 0x04 dword pointer to CObject 0x08 dword ammo (or max asset value) 0x0C dword timer 0x10 word x,y,z, all multiplied by 8 0x16 word asset rate 0x18 word model 0x1A word index 0x1C byte type 0x1D byte flags 0x1E byte (Align?)
- 0x01 used pickups?
- 0x02 dropped jetpack?
- 0x04 switched weapon?
- 0x08 collected pickup?
- 0x10 can buy property
- 0x20 can't buy property
- When you walk across over a weapon pickup having a weapon of same type, the game will propose you to replace this slot with new weapon by pressing Action key. Initially number of this message showing times equals to 10. Each time you see the message, this counter is decreased. This field stores how much times left to display the message.
Block 7: Phone info
Block 8: Restart Locations
OFFSET TYPE DESCRIPTION 0x00 word Wasted structures number 0x02 Restart Wasted structures 0x00 word Busted structures number 0x02 Restart Busted structures 0x00 byte Boolean: override restart 0x01 float Override next restart coordinates (opcode 016E) 0x0D byte Boolean: fade in after next death (always 1) 0x0E byte Boolean: fade in after next arrest (always 1) 0x0F float Override next hospital restart coordinates (opcode 08DF) 0x1B float Override next hospital restart radius 0x1F float Override next hospital restart heading 0x23 float Override next police restart coordinates (opcode 08E0) 0x2F float Override next police restart radius 0x33 float Override next police restart heading
Restart structure: 0x00 float coords 0x0C float heading 0x10 dword town (island) 0x14 end
^ Player has to die/be arrested within this radius in order for an override to happen.
Block 9: Markers
OFFSET TYPE DESCRIPTION 0x0000 Markers Marker structures -- each is 0x28 bytes in size, see details below 0x1B58 end
Marker structure: 0x00 dword color 0x04 dword entity handle this marker is attached to (opcodes 0186, 0187, etc) 0x08 float position X,Y,Z 0x14 word index? 0x16 byte (Align) 0x18 float sphere radius 0x1C word icon size 0x1E byte (Align) 0x20 dword (unknown) 0x24 byte icon ID 0x25 byte unknown flags 0x27 byte (Align) 0x28 end
Block 10: Zones
This block contains information about map zones in three arrays. The first array is for size and location information for the zones as initially defined in the data file info.zon. The second array contains entries for each of the uniquely-named zones defined in the first array and stores information about things like gang densities and popcycle.dat group info for each zone. Much of this info is set by specific opcodes such as 076C, 076A, 0767, and 0874.) The ID number for a given entry in the first array refers to an entry in the second array. The third array is another size/location array similar to the first but based on the data file map.zon.
One interesting note about this block is that a small amount of corruption here causes the "Taxi Glitch" situation where the taxi mission always tells you there are no fares nearby no matter where you are. The problem is that the first entry of the first array (the SAN_AND zone describing the entire map) gets mangled and the taxi mission references that zone to pick a passenger. For more on this glitch and how to fix it, see the GTAForums thread on it.
OFFSET TYPE DESCRIPTION 0x0000 dword current town (island) 0x0004 word Number of entries for first ZoneInfo Array 0x0006 word Number of entries for ZonePop Array 0x0008 word Number of entries for second ZoneInfo Array 0x000A ZoneInfo Array populated from file data/info.zon ... 0x0000 ZonePop Array of gang density and popcycle info ... 0x0000 ZoneInfo Array populated from file data/map.zon ... 0x0000 byte map fog array; see details below 0x0064 dword number of opened map sectors
ZoneInfo Structure: 0x00 char zone name 0x08 char zone gxt key (for name displayed on-screen) 0x10 word x1,y1,z1 (rounded to ints) 0x16 word x2,y2,z2 (rounded to ints) 0x1C word id 0x1E byte type 0x1F byte island 0x20 (end)
ZonePop Structure: 0x00 byte Gang 0 Density (set by opcode 076C) 0x01 byte Gang 1 Density (set by opcode 076C) 0x02 byte Gang 2 Density (set by opcode 076C) 0x03 byte Gang 3 Density (set by opcode 076C) 0x04 byte Gang 4 Density (set by opcode 076C) 0x05 byte Gang 5 Density (set by opcode 076C) 0x06 byte Gang 6 Density (set by opcode 076C) 0x07 byte Gang 7 Density (set by opcode 076C) 0x08 byte Gang 8 Density (set by opcode 076C) 0x09 byte Gang 9 Density (set by opcode 076C) 0x0A byte Dealer Density (set by opcode 076A) 0x0B byte RBGA color of zone on map/radar 0x0F byte Popcycle Group (set by opcode 0767)* see notes below 0x10 byte Ped-related (set by opcode 0874) 0x11 (end)
- The ZonePop byte at offset 0x0F appears to use the upper 3 bits for flags. Bit 0x20 will be set if gangs are present in the zone and cleared if no gangs are present. Bit 0x40 is unobserved, and cleared if set manually. Bit 0x80 is set with opcode 09B7 and disables the footcops in that zone.
- Map Fog Array: Each byte denotes the state of the certain map sector (00 = not visited / 01 = visited); byte order = N to S (10 rows), then E to W (10 cols).
Block 11: Gangs
OFFSET TYPE DESCRIPTION 0x0000 CGangInfo CGangInfo structures -- each is 0x10 bytes in size; see details below 0x00A0 (end)
CGangInfo 0x00 byte gang ped model override (-1 to disable; unused) 0x04 dword weaponID A 0x08 dword weaponID B 0x0C dword weaponID C 0x10 (end)
- Data can be changed by opcode 0237
Block 12: Car Generators
0x00 dword count 0x04 byte unknown counter (0..3) 0x05 byte unknown counter (0..20); when it's non-zero, the game doesn't check the timer (0x16) 0x06 CarGen[count] see details below ---- numberplates: 0x00 dword num entries used 0x04 Numplate number plates 0xf4 end
CarGen structure: 0x00 word index (0..499) 0x02 word model 0x04 byte colors 0x06 word x,y,z, all multiplied by 8 0x0C byte heading/360*256 0x0D byte alarm chance 0x0E byte locked chance 0x0F byte flags: bit 2=force spawn, bit 8=player owned 0x10 word unknown setting (IPL field 11, scm field 7) 0x12 word monetary value (unused?) 0x14 bytes unknown (align?) 0x16 dword timer 0x1A word unknown activity 0x1C word number of cars to generate (101 or higher means unlimited generation) 0x1E byte IPL stream of binary generators (non-zero records are not saved) 0x1F byte allocation flag (when game adds a new parked car it searches for the allocation = 0; then sets it to 1 and never set back to 0). 0x20 byte unknown (align?) 0x22 end
Numplate structure: 0x00 dword car generator handle (index) 0x04 char numberplate string 0x0C byte unknown (align?) 0x10 end
Block 13: Ped generators
Block 14: Audio script object
Block 15: Player data
OFFSET TYPE DESCRIPTION 0x00 dword size of block (always 28h) 0x04 dword money 0x08 word (unknown) 0x0A byte is wasted_or_busted flag 0x0B byte (Align) 0x0C float (unknown) 0x10 dword amount of money shown on screen 0x14 byte (unknown) 0x15 byte (Align) 0x18 dword (unused) hidden packages left 0x1C dword (unused) total hidden packages 0x20 byte infinite run (opcode 0330) 0x21 byte fast reload (opcode 0331) 0x22 byte fireproof (055D) 0x23 byte max health 0x24 byte max armor (opcode 055F) 0x25 byte free busted once 0x26 byte free wasted once (opcode 0414) 0x27 byte enable driveby (opcode 0501) 0x28 byte (unknown) 0x29 byte (Align) 0x2A word (unknown) 0x2C end
Block 16: Stats
0x0000 float float stats (numbered 0..81 in scm) 0x0148 dword int stats (numbered 120..342 in scm) 0x04C4 dword num peds killed of the type [id] 0x0544 char last mission passed (gxt key) 0x054C dword num times played radio station [id] 0x0584 dword num mission attempts for mission [id] 0x0714 byte has displayed stat message [id] (id as in statdisp.dat line number) 0x0794 end
Block 17: Police trigger zones
OFFSET TYPE DESCRIPTION 0x0000 dword Number of Police trigger zones 0x0004 PoliceTriggerZone Trigger structures -- each is 0x20 bytes in size; see details below 0x1A44 end
PoliceTriggerZone 0x00 dword police trigger last activation time 0x04 word police trigger zone point 1 (x,y) -- all multiplied by 8 0x08 word police trigger zone point 2 (x,y) -- all multiplied by 8 0x0C word police vehicle A starting point (x,y) -- all multiplied by 8 0x10 word police vehicle A initial direction (x,y) -- all multiplied by 8 0x14 word police vehicle B starting point (x,y) -- all multiplied by 8 0x18 word police vehicle B initial direction (x,y) -- all multiplied by 8 0x1C byte police trigger type; see details below 0x1D byte (Align) 0x20 end
Police Trigger Types
- 1 - On Foot with 1 star spawns 2 cop cars moving slowly
- 2 - In Vehicle with 2 stars spawns 1 cop car moving quickly
- 3 - In Vehicle with 2 stars spawns 1 cop car at medium speed
- 4 - On Foot with 1 star spawns 1 cop pedestrian
- 5 - On Foot with 1 star spawns 2 cop pedestrians
- 6 - In Vehicle with 2 stars spawns 2 cop cars moving quickly before hitting breaks
- 7 - In Vehicle with 2 stars spawns 2 cop cars moving quickly
- 8 - On Foot with 1 star spawns 2 cop cars at medium speed
- Police Triggers are a special zone consisting of a rectangle defined by 2 ends of the rectangle diagonal, and two rays defined by a starting point and point along the ray indicating the initial direction of travel.
- When the player is in the police trigger rectangle and meets the requirements of the police trigger type, then a cop will spawn at the endpoint of ray A headed in the direction of the 2nd defined point.
- If the police trigger type includes 2 police, then a cop will also spawn along ray B.
- The police are not bound to continue in the specified direction after their initial spawn.
- In order to trigger In Vehicle trigger types the vehicle must be moving.
- Police trigger zones are activated only once per 40 seconds (the first field is used to control this).
- Police trigger zones can be created using opcode 04F8
Block 18: Models
OFFSET TYPE DESCRIPTION 0x0000 byte (unknown) 0x66CC end
Block 19: Ped Acquaintances
OFFSET TYPE DESCRIPTION 0x000 PedAcquaintance PedAcquaintance structures, each is 20 bytes in size -- see details below 0x280 end
PedAcquaintance -- See notes below 0x00 dword respect bitmask 0x04 dword like bitmask 0x08 dword (unused) (ignore?) 0x0C dword dislike bitmask 0x10 dword hate bitmask
- This structure stores information about how a ped of given pedtype (each entry in PedAcquaintance is separate pedtype, starting from 0 (PLAYER1) to 31 (MISSION8)) behaves toward any ped of other type. Five dwords in this structure (only four of them are used) are the bitmasks, where a bit sets a flag of acquaintance type (respect, like, dislike, hate) to the pedtype of given index (=number of bit). Say, if the 4th bit (counting from zero) in PedAcquaintance.respect is set, it means that a ped of type CIVFEMALE (pedtype=5) respects a ped of type CIVMALE (pedtype=4).
- These structures are filled with data from the file ped.dat. The acquaintances flags could be changed via scripts (using opcode 0746 and similar).
Block 20: Tags
0x00 dword total number of the tags (count) 0x04 byte[count] tags paint status (0-255)
Block 21: IPL
0x0000 dword constant 256, value of ID IPL limit 0x0004 byte Flags to enable binary IPLs (see notes below) 0x0103 end
Notes: The order of the flags corresponds to the order the IPLs appear in gta3.img. These flags only affect non-stream IPLs; stream IPLs are always enabled regardless of flag value. (*plus something on the opcodes used to enable/disable the flags*)
IPL Version Map:
Hex Dec PCv1 PCv2v3 PS2v1v2 05 5 barriers1 countryn_stream0 levelmap_stream1 06 6 barriers2 countryn_stream1 countryn_stream0 2D 45 countryw_stream5 crack sfe_stream2 31 49 truthsfarm sfse_stream3 sfs_stream0 3E 62 crack truthsfarm crack 3F 63 sfse_stream0 barriers1 sfse_stream0 40 64 sfse_stream1 barriers2 sfse_stream1 52 82 vegasn_stream2 carter countryw_stream7 55 85 vegasn_stream5 lae2_stream2 truthsfarm 56 86 vegasn_stream6 lae2_stream3 barriers1 57 87 vegasn_stream7 lae2_stream4 barriers2 70 112 vegasw_stream6 lawn_stream3 carter 7F 127 carter countrye_stream5 lae_stream5
Usage: PCv1 can control the PCv2 carter objects by calling vegasn_stream2
Block 22: Shopping
0 dword count 4 entries (8 bytes each) ---- 0 dword size 4 bytes
Each byte represents the shopping items listed in the order of "section prices" at the beginning of shopping.dat. A short summary of the 544 flags is: CarMods, Clothes (torso, legs, shoes, necklace, watch, glasses, hats), Haircuts, Tattoos, Food, and Weapons.
Block 23: Gang wars
OFFSET TYPE DESCRIPTION 0x00 dword size of block (always 58h) 0x04 byte enable gang wars (opcode 0879) 0x05 byte (Align) 0x08 dword current gang war stage 0: no war 1: war provoked 2: first wave 3: first wave passed 4: second wave 5: second wave passed 6: third wave 0x0C dword time when last stage started 0x10 dword index of warzone in ZonePop array 0x14 dword index of warzone in ZoneInfo array 0x18 float XYZ: players location during a "3rd Kill" (gang war trigger) 0x24 dword attack/war gang ID 0x28 dword war gang 2 ID 0x2C dword gang strength (0 to 2, 3 is unused) 0x30 dword unknown time 0x34 dword hood under attack stage (?) 0x38 float next attack timer (counts down) 0x3C float XYZ: center of warzone 0x48 dword hood attack timeout (counts down) 0x4C dword hood attack marker handle (?) 0x50 byte (unknown) 0x51 byte (Align) 0x54 float previous territories under control (08E2) 0x58 float current territories under control (08E2) 0x5C end
Block 24: Unique Stunt Jumps
OFFSET TYPE DESCRIPTION 0x0000 dword Number of Unique Stunt Jumps (USJ) 0x0004 StuntJump Jump structures -- each is 0x44 bytes in size; see details below
StuntJump -- See note below 0x00 float Start zone point 1 (x,y,z) 0x0C float Start zone point 2 (x,y,z) 0x18 float Land zone point 1 (x,y,z) 0x24 float Land zone point 2 (x,y,z) 0x30 float Camera coordinates (x,y,z) 0x3C dword Reward amount (can be negative) 0x40 byte Boolean: is USJ done 0x41 byte Boolean: is USJ found 0x42 byte (Align)
The starting and landing zones are cubes; each is defined by 2 points -- point 1 is the lower, left, front of the cube and point 2 is the upper, right, rear. These cubes are aligned with the coordinate axes and not rotated at all. If a vehicle enters the starting zone while airborne, the USJ triggers (and is marked as 'found'); if the vehicle then lands inside the landing zone, the USJ is successful (and is marked as 'done') and the reward is given.
Block 25: ENEX Connections
0 dword count 4 word[count] source index of enex path ---- Structure: 0 word source index (break loop if value = -1) 2 word flags 4 word destination index ----
Enex Path: Normally 0 for outdoor saves, or 1 with the source index of the enex used to access the interior where the game was saved. The enex path may be longer on modified saves. Additional links are appended to the path. The enex path is used to display the zone name for the destination before CJ arrives in the zone.
BIT HEX DEC NAME DESCRIPTION 00 0001 1 unknown interior Only used for interior markers 01 0002 2 unknown pairing Used mostly for interior markers; also Big Ear & LS Skyscraper 02 0004 4 create linked pair Pair with unflagged mate during new game start 03 0008 8 reward interior Sets flag 0010 on pair mate when used 04 0010 16 used reward entrance Set by accessing reward interior 05 0020 32 cars and aircraft Enable for cars and aircraft 06 0040 64 bikes and motorcycles Enable for bikes and motorcycles 07 0080 128 disable on foot No foot traffic (use for cars and/or bikes only)
08 0100 256 accept NPC group Group members accepted at destination of pair (strips passengers) 09 0200 512 food date flag Set and cleared by food date (cut-scene related) 10 0400 1024 unknown burglary Set on Bayside and Temporary Burglary doors 11 0800 2048 disable exit Player can enter but cannot exit a two-way pair 12 1000 4096 burglary access Enabled and disabled during Burglary 13 2000 8192 entered without exit Set by Entrance, Cleared by Exit; Applies to one side of a two-way pair 14 4000 16384 enable access Enabled by default; often cleared by scripts 15 8000 32768 delete enex Enex is deleted when used
New enex connections can be added to the save after the save is created if temporary (burglary) connections are not present (indoor or isolated saves). The flags and links for existing connections will not be updated by changes in the IPL file. If the enex structure is removed from the block (except for the -1 terminator) the game will remap all connections based on the current IPL configuration.
Block 26: Radio Data
This block contains data relating to various radio stations. The bulk of the block is an array of data structures for each station. Not much is known about these structures currently but part of the data seems to be a record of which tracks have played recently. Following this array of structures there is a collection of byte flags which are related to high-number player Stats. These Stats are used to trigger different episodes and radio clips throughout the game. Note that the "set by" comments refer to missions in the original, unmodified game and they can obviously be set at different times instead.
0x0000 StationInfo State info for radio stations; each is 0x110 in size -- see details below 0x0EE0 byte Cities Unlocked (stat 181) 0x0EE1 byte (stat 327; set by "Learning to Fly") 0x0EE2 byte (stat 328; set by "The Meat Business") 0x0EE3 byte (stat 329; set by "St. Mark's Bistro") 0x0EE4 byte I Say / You Say Ep#2 (stat 318; set by "Local Liquor Store") 0x0EE5 byte (stat 320; set by "Monster") 0x0EE6 byte (stat 330; set by "Interdiction") 0x0EE7 byte (stat 331; set by "Learning to Fly") 0x0EE8 byte (stat 332; set by "Black Project") 0x0EE9 byte (stat 333; set by "Green Goo") 0x0EEA byte (stat 311; set by "Mike Toreno") 0x0EEB byte (stat 323; set by "Green Sabre") 0x0EEC byte News Ep#9 (stat 308; set by "Vertical Bird") 0x0EED byte (stat 310; set by "OG Loc") 0x0EEE byte (stat 335; set by "Riot") 0x0EEF byte (stat 336; set by "555 We Tip") 0x0EF0 byte (stat 337; set by "House Party") 0x0EF1 byte (stat 302; set by "Drive-Thru") 0x0EF2 byte (stat 338; set by "Are you going to San Fierro?") 0x0EF3 byte (stat 339; set by "High Noon") 0x0EF4 byte (stat 340; set by "The Green Sabre") 0x0EF5 byte (stat 341; set by "Small Town Bank") 0x0EF6 byte (stat 342; set by "Farewell My Love") 0x0EF7 byte month day when the stats above were updated 0x0EF8 byte hour when the stats above were updated 0x0EF9 byte hours to the next stats update (commonly 24 or 168) 0x0EFA byte updating flag (1,2,3) 0x0EFB byte last updated stat (in accordance with the given order) 0x0EFC (end)
StationInfo Structure: 0x000 byte Possibly a stack of indices of recently-played tracks 0x014 dword (Unknown) 0x034 dword (Unknown) 0x0D4 dword (Unknown) 0x110 (end)
Order of Stations for the StationInfo Structure Array IDX Stream Description 0 AA Emergency Band 1 CH Playback FM 2 CO KROSE 3 CR K-DST 4 DS Bounce 5 HC SFUR 6 MH Radio Los Santos 7 MR Radio X 8 NJ CSR 9 RE K-JAH West 10 RG Master Sounds 11 TK WCTR 12 -- User Track Player 13 ?? (Unknown)
Block 27: Entrance markers
|0x00||CEntranceMarker||entrance markers, can be created by opcode 0A40|
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.
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.
Available tools for editing of the save file content:
Allows editing of any save data directly in the hex editor. Also contains the script to recalculate the checksum.
- GTA SA Savegame Editor v3.0 by Paul Breeuwsma: http://www.paulinternet.nl/sa
- GTA:SA Save Game Editor v1.0 by Ryosuke: http://gtasamod.web.fc2.com/tool/sase/index.html
- GTA:SA Save Game Tool v1.0 http://home.comcast.net/~shamblertm/pages/gtasa_sgt.html
- http://www.paulinternet.nl/sadoc - some documentation of the savegame file used by the savegame editor of Paul Breeuwsma
- GTAForums: Early documentation topic
- GTAForums: SA Save File Glitch Detection and Repair - a topic by OrionSR
- GTAForums: Save File Conversion: PS2 to PC - a topic by marshmallow1304
|Grand Theft Auto: San Andreas|
|File Formats||.col • .cfg • .cut • .dff • .dat • .fxp • .gxt • .ide • .ifp • .img • .ipl • nodes*.dat • .ped • .rep • .rrr • .scm • .set • .txd|
|Documentation||Audio • Cryptography • Cutscenes • Game memory • Handling.cfg • Map Listing • Mission Packs • Opcodes • Paths • Replays • Saves • Scripts|
|Tools||CLEO • Collision File Editor II • ENBSeries • G-Tools • IMG Tool • Limit Adjuster • Map Editor • Mod Loader • San Andreas Audio Toolkit • Sanny Builder • TXD Workshop|
|Tutorials||San Andreas v2.0 Modding • How to create a mission • How to create a thread • How to use Map Editor • Vehicle Mod Installation|
|Modifications||Design Your Own Mission • Gostown Paradise • GTA: United • Myriad Islands|