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: 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
 * – Windows 98 Example
 * – Windows XP Example
 * – Windows Vista Example

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.

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

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): 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.
 * 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)

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[70] 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[25]     each is 0x10 bytes in size; see details below 0x0710 InvisibleObject[20]       each is 8 bytes in size; see details below 0x07B0 dword[20]                 keeps model identifiers which are excluded from the carparking generation (similar to opcode 03C5). Unused. 0x0800 LodAssignment[10]         each is 8 bytes in size; see details below 0x0850 ScriptAssignment[8]       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                     priority 0x10  dword                    (unknown) 0x14                           end

Note:
 * These triggers are created with opcodes 0928, 0929

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 0x3A byte[2]                   (Align) 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                      (Unknown) 0xC9 byte                      (Unknown) 0xCA byte[2]                   (Align) 0xCC dword                     Wakeup Time 0xD0 word                      'if' parameter 0xD2 byte                      'not' flag 0xD3 byte                      'wb_check' flag 0xD4 byte[4]                   (Unknown) 0xD8 dword                     Skip Scene Pos (opcode 0707) 0xDC byte                      Is Mission 0xDD byte[3]                   (Align) 0xE0                           end

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

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[8]        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[3]   X, Y, Z   0x001C  float      Health 0x0020 float      Armor 0x0024 Weapon[13] 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[2]    (Align) 0x019C dword      size of the following data (0x84) 0x01A0 dword      chaos 0x01A4 byte       wanted level 0x01A5 byte[3]    (Align) 0x01A8 dword      CRC32 of filename for Torso model 0x01AC dword      CRC32 of filename for Head model 0x01B0 dword      CRC32 of filename for (unknown) 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)

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[8]      (unknown)

Object Structure: 0x00 dword        Handle 0x04 dword        Model ID   0x08  dword        constant 48 (size of the following data) 0x0C float[3]     X, Y, Z   0x18  byte[3]      CXYZ.right.xyz 0x1B byte[3]      CXYZ.top.xyz 0x1E byte[30]     (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         (Unknown) 0x000B dword         (Unknown) 0x000F dword         (Unknown) 0x0013 dword[4]      (Unknown) 0x0023 dword         (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[4]       (Unknown) 0x10 byte          Car Flags 0x11 byte          (Unknown) 0x12 word          Vehicle Model ID   0x14  word[15]      Installed Vehicle Mods (see veh_mods.ide) 0x32 byte[4]       Primary Color, Secondary Color, Tertiary Color, (Unknown) Quaternary Color? 0x36 byte          Radio Station [see below] 0x37 byte[2]       Vehicle Variation 0x39 byte          Bomb Type 0x3A byte          Paintjob 0x3B byte          Nitrous Count 0x3C byte[3]       Vector Rotation 0x3F byte          (unknown) Align

Garage Structure: 0x00 byte          Garage Type 0x01 byte[2]       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[4]      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[8]       Garage Name -- can be used by mission script to access garage 0x4C word          (Unknown) Possibly Original Type 0x4E byte[2]       (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: Wasted/Busted
Unknown data. Block can vary in size depending on number of entries; number of entries may be zero.

OFFSET TYPE            DESCRIPTION 0x00   dword           Number of Block4Struct structures 0x04   byte            Boolean: Lose stuff after wasted (opcode 08DD) 0x05   byte            Boolean: Lose stuff after busted (opcode 08DE) 0x06   byte            unknown Wasted_Busted Flag 0x07   dword           unknown Wasted_Busted time 0x0B   Block4Struct[]  unknown structures (UNUSED?) -- see details below

Block4Struct structure: 0x00 byte[12]        (unknown) 0x0C byte[4]         (unknown)

Block 5: Disabled Pathnode Cubes
0x00   dword           count 0x04   Entry[count]    entries  --0x1C size Entry structure: 0x00   float[6]        x1,x2,y1,y2,z1,z2 0x18   byte[4]         bools that somehow indicate which pathtypes are enabled


 * Note: these structures somehow related to opcodes 0606, 0607

Block 6: Pickups
0x0000  Pickup[620]     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[20]       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[3]        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[2]        (Align?)

Flags: Notes:
 * 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: (Unused)
(Usually empty)

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          (Unknown) 0x01   byte[12]      (Unknown) 0x0D   byte          (Unknown) 0x0E   byte          (Unknown) 0x0F   byte[12]      (Unknown) 0x1B   dword         (Unknown) 0x1F   dword         (Unknown) 0x23   byte[12]      (Unknown) 0x2F   dword         (Unknown) 0x33   dword         (Unknown)

Restart structure: 0x00 float[3]      coords 0x0C float         heading 0x10 dword         town (island) 0x14 end

Block 9: Markers
OFFSET TYPE           DESCRIPTION 0x0000 Markers[175]   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[3]      position X,Y,Z 0x14 word          index? 0x16 byte[2]       (Align) 0x18 float         sphere radius 0x1C word          icon size 0x1E byte[2]       (Align) 0x20 dword         (unknown) 0x24 byte          icon ID   0x25  byte[2]       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[100]   map fog array; see details below 0x0064 dword       number of opened map sectors

ZoneInfo Structure: 0x00 char[8]     zone name 0x08 char[8]     zone gxt key (for name displayed on-screen) 0x10 word[3]     x1,y1,z1 (rounded to ints) 0x16 word[3]     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[4]     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)

Notes:
 * 1) 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.
 * 2) 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: Gang Weapons
OFFSET TYPE            DESCRIPTION 0x0000 GangWeapons[10] GangWeapons structures -- each is 0x10 bytes in size; see details below 0x00A0 (end)

GangWeapons[] 0x00 byte[4]         unused 0x04 dword           weaponID A   0x08  dword           weaponID B   0x0C  dword           weaponID C   0x10  (end)

Notes:
 * 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[15]        number plates 0xf4                       end

CarGen structure: 0x00   word             index (0..499) 0x02   word             model 0x04   byte[2]          colors 0x06   word[3]          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[2]         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[2]          unknown (align?) 0x22                    end

Numplate structure: 0x00   dword            car generator handle (index) 0x04   char[8]          numberplate string 0x0C   byte[4]          unknown (align?) 0x10                    end

Block 13: (Unused)
(Usually Empty)

Block 14: (Unused)
(Usually Empty)

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[3]         (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[82]       float stats (numbered 0..81 in scm) 0x0148  dword[223]      int stats (numbered 120..342 in scm) 0x04C4  dword[32] 0x0544  char[8]         last mission passed (gxt key) 0x054C  byte[56] 0x0584  dword[100] 0x0714  byte[128] 0x0794                   end

Block 17: Police trigger zones
OFFSET TYPE                   DESCRIPTION 0x0000 dword                  Number of Police trigger zones 0x0004 PoliceTriggerZone[210] Trigger structures -- each is 0x20 bytes in size; see details below 0x1A44                        end

PoliceTriggerZone 0x00 dword                police trigger last activation time 0x04 word[2]              police trigger zone point 1 (x,y) -- all multiplied by 8 0x08 word[2]              police trigger zone point 2 (x,y) -- all multiplied by 8 0x0C word[2]              police vehicle A starting point (x,y) -- all multiplied by 8 0x10 word[2]              police vehicle A initial direction (x,y) -- all multiplied by 8 0x14 word[2]              police vehicle B starting point (x,y) -- all multiplied by 8 0x18 word[2]              police vehicle B initial direction (x,y) -- all multiplied by 8 0x1C byte                 police trigger type; see details below 0x1D byte[3]              (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

Notes:
 * 1) 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.
 * 2) 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.
 * 3) If the police trigger type includes 2 police, then a cop will also spawn along ray B.
 * 4) The police are not bound to continue in the specified direction after their initial spawn.
 * 5) In order to trigger In Vehicle trigger types the vehicle must be moving.
 * 6) Police trigger zones are activated only once per 40 seconds (the first field is used to control this).
 * 7) Police trigger zones can be created using opcode 04F8
 * 8) http://www.gtaforums.com/index.php?showtopic=260803

Block 18: Models
OFFSET TYPE          DESCRIPTION 0x0000 byte[26316]   (unknown) 0x66CC               end

Block 19: Ped Acquaintances
OFFSET TYPE                       DESCRIPTION 0x000  PedAcquaintance[32]        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[32] 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[5].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 0x0004   byte[255]       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[3]         (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[3]        unknown XYZ 0x24   dword           (unknown) 0x28   dword           (unknown) 0x2C   dword           (unknown) 0x30   dword           unknown time 0x34   dword           hood under attack stage (?) 0x38   dword           next attack time (?) 0x3C   float[3]        unknown XYZ 0x48   dword           hood attack notify time (?) 0x4C   dword           hood attack marker handle (?) 0x50   byte            (unknown) 0x51   byte[3]         (Align) 0x54   float           territories under control (08E2) 0x58   float           same as above (0x54) 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[3]    Start zone point 1 (x,y,z) 0x0C float[3]    Start zone point 2 (x,y,z) 0x18 float[3]    Land zone point 1 (x,y,z) 0x24 float[3]    Land zone point 2 (x,y,z) 0x30 float[3]    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[2]     (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.

ENEX Flags 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[14] 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[20]        Possibly a stack of indices of recently-played tracks 0x014  dword[8]        (Unknown) 0x034  dword[40]       (Unknown) 0x0D4  dword[15]       (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)

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.

Savegame Editor documentation
The source code and documentation of the Savegame Editor of Paul Breeuwsma is put online. You can download it or view the documentation online. Feel free to use/copy/edit it if you want to.

Tools
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 Save Template for 010 Editor, by Seemann: http://sannybuilder.com/dev/SaveTool.rar
 * GTA SA Savegame Editor v2.8 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