Jump to content

» «

GTASA savefile format

8 replies to this topic
  • man2104

    MC Spy

  • Members
  • Joined: 12 Jun 2002


Posted 22 July 2005 - 07:22 AM Edited by man2104, 22 July 2005 - 03:06 PM.

This is the format of GTASA savefile so far I've discovered.
Hope someone will join and share the info. with us.
     GTA San Andreas Save File format v0.2

written by
1. Technetium([email protected])

This document is aimed to completely describe the format of savefiles for GTASA. It is still working in progress. Editing or adding info. into this document are welcome.

Marco strcuture
Savefiles consist of 32 blocks which are storing different kind of data. Sequency of the block determines what kind of data it stores.
At the end of the file, there is a dword storing the checksum, which is calcuated by Checksum-32 algorithm, which sum up all the bytes in the file.
Below is the sequency of blocks:
1: Header with global script indepentent variable
2: SCM global variable
3: CPedPool
4: Parked car in garages
5: Unknown
6: Unknown
7: Pickup
8: Unknown
9: Unknown
10: Unknown
11: Unknown(zone?)
12: Unknown
13: Car generator
17: Player_Status
Micro strcuture

Block 4 : Car in garages
char Header_perfex[5];// "BLOCK"
dword Garages_count;
char Unknown[31];
dword Unknown;
ParkedCar Pool[];
the structure of ParkedCar:
Since it is dumped from memory, its strucutre is completely identical to data in memory.
Its strcture:(credits: saracoglu, Quoted from http://www.gtaforums.com/index.php?showtopic=194199&st=60)
+ 0 X Coord (Float)
+ 4 Y Coord (Float)
+ 8 Z Coord (Float)
+14 BPDPEPFP (Word) coding
+16 Car ID (Word)
+47 Body Color ordinal (Byte)
+48 Stripe Color ordinal (Byte)
+60 Car Angle (Float)

Block 7 : Pickup
char Header_perfex[5];// "BLOCK"
char Unknown[16];
Pickup Pool[];
the structure of Pickup:
struct Pickup
word x, y, z;     // Coordination of pickup. To convert the coord. into GTA high percision unit, multiply 8 to the coord.
word Unknown;
char Pickup_Type1; // 0x66 = adrenaline, 0x6e = health, etc
char Pickup_Type2; // 0x01 = health dependent pickup, 0x04 = weapons pickup
char Unknown; // It always equal to 0x02
char Unknown;
word Pickup_Flag; // 0x15 = free pickup
dword Unknown;
dword Unknown;
word Unknown;
dword Ammo_count;
dword Unknown;

Block 13 : Car generator
char[5] Header_perfex; // "BLOCK"
dword Generator_count;
CarGen Pool[];
the structure of CarGen:
struct CarGen
word Unknown;
word Unknown;
word Car_ID;  // pls refer to vehicles.ide
char Unknown; // always -1. wheelmodelId? Please refer to mission coding reference.
char Unknown; // always -1. wheel scale?  Please refer to mission coding reference.
word x, y, z;     // Coordination of pickup. To convert the coord. into GTA high percision unit, multiply 8 to the coord.
word rotate_Z;
char Unknown; // Alarm?
char Unknown; // Door_lock?
word Unknown;
char Unknown;
dword Unknown; // always 10000. Please refer to mission coding reference.
dword Unknown;
dword Unknown;
word Unknown;

Block 17 : Player_Status
char[5] Header_perfex; // "BLOCK"
float Status_array[486];// for index id, please refer to statdisp.dat. P.S. some of the data are stored as long(e.g. repect).

  • charlieC

    Player Hater

  • Members
  • Joined: 09 Jun 2002


Posted 22 July 2005 - 07:15 PM

Good work!

Always nice to see more parts of GTASA reverse engineered.

You say that the save file consists of 32 blocks, but you only listed 17.
Are the others just empty, or haven't you looked at them yet?

  • man2104

    MC Spy

  • Members
  • Joined: 12 Jun 2002


Posted 23 July 2005 - 07:18 AM


they are still unknown.

  • Skiller

    Street Cat

  • Members
  • Joined: 09 Jan 2005


Posted 24 July 2005 - 02:34 AM

well dont exactly know how u have this set up ..
but i know one of the blocks is Map info ..
u can find the lable

u will jump into the section ..

0001c924 (THE Map Lable)

0001809c (Block Address)

Starting Offset i use was 00000000

0001ca04 all the 01 in this section add stuff to the map .. 01 them all an u will have a full map (view unlocked)

Sorry dont know much on Game saves its just something i Got into For a project on the PS2 thought i would try and Share my info smile.gif

one thing .. maybe throw some addresses on them Block numbers ..
then again .. im new to save stuff .. so it might just be something i find alot easyer lol smile.gif

and very nice .. work .. hope to see some updates . all throw what ever i can at ya ..
the above addresses are from using the PC saves.

  • charlieC

    Player Hater

  • Members
  • Joined: 09 Jun 2002


Posted 25 July 2005 - 02:05 AM

I've done some crunching with block 1.

Here's what I've managed to find, it's not much. But at least it's a step in the right direction.


word year;
word month;
word dayOfWeek;
word day;
word hour;
word minute;
word second;
word milliseconds;

float x;
float y;
float z;

struct generalBlock
dword versionChecksum; // Checksum from string "Apr 28 200510:28:55" (probably the build time generated by the compiler (preprocessor macro)
char lastMissionName[100];
dword unknown1; // 0x00B72910
dword unknown2; // 0x00B7290C
POSITION position; // 0x00B6F9CC
dword numMsPerSec; // 0x00B7015C
dword weather_timer; // 0x00B70158
byte unknown3; // 0x00B70155
byte unknown4; // 0x00B70154
byte currentHour; // 0x00B70153
byte currentMinute; // 0x00B70154
byte unknown5; // 0x00B7014E
byte unknown6; // 0x00B7014D
byte unknown7; // 0x00B7014C
byte unknown8; // 0x00B7014B
byte unknown9; // 0x00B7014A
byte unknown10; // 0x00B70144
word unknown11; // Dynamic address
dword unknown12; // 0x0096918C Boolean?
dword globalTimer; // 0x00B7CB84
float unknown13; // 0x00B7CB64
float unknown14; // 0x00B7CB5C
float unknown15; // 0x00B7CB58
dword unknown16; // 0x00B7CB4C
word unknown17; // 0x00C81320
word unknown18; // 0x00C8131C
word unknown19; // 0x00C81318
char placeholder1[2]; // Unknown, probably a word/2 bytes
dword unknown20; // 0x00C8130C
dword unknown21; // 0x00C81310
float unknown22; // 0x00C81324
dword unknown23; // 0x00B6F0DC
dword unknown24; // 0x00B6F0F0
dword unknown25; // 0x00B72914 - Look like boolean, but isn't? Maybe not a dword?
dword unknown26; // 0x00B73402 - Boolean?
dword unknown27; // 0x00B79E44
dword unknown28; // 0x00B7C484 - Boolean?
float unknown29; // 0x00B79E3C
dword unknown30; // 0x00B79E40
dword unknown31; // 0x00C228A0
dword unknown32; // 0x00B72958 and 0x00B72959 - Very strange dword - a bit field?
dword maxWantedLevel; // 0x008CDEE4
dword policeAggression; // 0x008CDEE8
byte unknown33; // 0x00B9B7EE
byte unknown34; // 0x00B9B7ED
byte unknown35; // 0x00B9B7EC
char placeholder4[45];
word unknown36; // 0x008CC381
SYSTEMTIME timestamp; // When file was created - Dynamic address of course :)
char placeholder5[2]; // Unknown, probably a word/2 bytes
dword unknown37; // 0x00BA6774
byte unknown38; // 0x00C0BC15
byte unknown39; // 0x0096918B Boolean
byte unknown40; // 0x0096918A Boolean

The addresses to the left of the slashes is where the variable is stored in memory when GTASA is running.
I think the checksum thing at top is used for version checking (so you can't load a save game from a different version of the game)
I'm pretty sure about the lastMissionName array size, everything bit of the puzzle tells me it's 100 bytes big (0x64).
The datatypes are almost 100% correct, could be some error here or there though.

Also, the "BLOCK" characters aren't part of this structure. I don't think it's part of any structure that GTASA saves.

I haven't cross-checked all the memory addresses I found with the mem address thread found here on the board or with Draco's wiki.
Maybe someone can help me out here? smile.gif Too tired for that right now, gotta get some sleep.

  • Un3462

    Mack Pimp

  • Members
  • Joined: 27 Jun 2002


Posted 25 July 2005 - 02:12 AM

i posted this elsewhere, but to prevent duplication of effort:
The SA savegame consists of 28 'blocks'. Each block consists of the word 'BLOCK' itself, and a certain amount of binary data. After all of the blocks comes an amount of slack and a checksum. The checksum is simply a dword and the sum of all of the preceding bytes. The slack is there to make the total filesize (including checksum) 31800h bytes. Because SA uses a buffer of C800h bytes for writing the savegame, the slack will simply be a repetition of what came C800h bytes before it. You can use this to write savegames identically to how SA does, making edits virtually undetectable to anyone.

The binary data in the blocks is loaded and saved by a set of functions conveniently listed in two jumptables:
_text:005D1B00 SavegameBlockReaders
_text:005D1734 SavegameBlockWriters

Documentation on the binary data for each block (offsets all hexadecimal):

>>> BLOCK 0 - Misc

offset  type            description
   0    dword           EXE ID (~crc32 of a string describing (I think) when the EXE was compiled)
   4    char[24]        title
  68    byte            current missionpack
  70    float[3]        camera coords
  7c    dword           length of in-game minute
  80    dword           weather timer
  86    byte            in-game hour
  87    byte            in-game minute
  94    dword           global timer
  98    float           game speed
  bc    dword           current camera view
 11e    word[8]         SYSTEMTIME struct (year, month, weekday, day, hour, minute, second, ms)
 138                    end

>>> BLOCK 1 - Script

---- global vars:
   0    dword           size of global var space
   4                    global var space
---- misc info from various opcodes and such:
   0                    unknown
 902                    end
---- threads:
   0    dword           number of threads
   4                    threads
Thread structure:
   0    word            index/handle
   2                    end
---- memory dump:
   0    dword           next pointer
   4    dword           prev pointer
   8    char[8]         name
  10    dword           absolute base address
  14    dword           absolute ip
  18    dword[8]        return stack
  38    word            stack pointer
  3c    dword[32]       local vars
  bc    dword[2]        local timers
  c4    byte
  c5    byte            if result
  c6    byte
  c7    byte            is extern
  c8    byte
  c9    byte
  cc    dword           wakeup time
  d0    word            if parameter
  d2    byte            not flag
  d3    byte            wb check flag
  d4    byte
  d8    dword           new script ip (0 if absolute ip has been calculated from this)
  dc    byte            is mission
  e0                    end
---- the absolute addresses depend on memory layout, so the savegame also contains relative addresses:
   0    dword           relative ip
   4    dword[8]        relative return stack
  24                    end
>>> BLOCK 2 - Objects

   0                    unknown bytes
 228                    end
---- objects
   0    dword           object count
   4                    objects
Object structure:
   4    dword           model
   c    float[3]        coords
  3c                    end

>>> BLOCK 3 - Garages

   0    dword           garage count
  27    GrgCar[20][4]   car entries
1427                    garages

GrgCar structure:
   0    float[3]        coords
  12    word            model
  40                    end

Garage structure:
   0    byte            type
   4    float[3]        coords
  10    float[4]        rotation
  20    float[3]        top z, width, depth
  2c    float[4]
  3c    float[2]
  44    char[8]         name
  4c    word            original type ?
  50                    end
>>> BLOCK 4
   0    dword           count
   b                    entries (16-byte structures)
>>> 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 - Empty

>>> BLOCK 8 - Restart positions

---- 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

   0    dword[4][10]
  a0                    end

>>> 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 - Empty

>>> BLOCK 14 - Empty

>>> BLOCK 15

   0    dword           size of block (always 28h)
   4                    some dwords, floats and bytes from the player structure
  2c                    end
>>> BLOCK 16 - 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

   0    dword           entries used
   4    byte[32][210]   entries
1a44                    end

>>> BLOCK 18

66cc                    end

>>> BLOCK 19

 280                    end
>>> BLOCK 20

   0    dword           size
   4                    bytes
>>> BLOCK 21

   0    dword
   4    byte[255]
 103                    end

>>> BLOCK 22

   0    dword           count
   4                    entries (8 bytes each)
   0    dword           size
   4                    bytes
>>> BLOCK 23

   0    dword           size of block (always 58h)
  5c                    end

>>> BLOCK 24

   0    dword           count
   4                    entries (68 bytes each)

>>> BLOCK 25

   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

   0    Structure[14]
 ee0    byte[28]
 efc                    end

   0    byte[20]
  14    dword[8]
  34    dword[40]
  d4    dword[15]
 110                    end

>>> BLOCK 27

   0    byte[28][5]     structures from opcode 0a40
  8c                    end

  • Skiller

    Street Cat

  • Members
  • Joined: 09 Jan 2005


Posted 26 July 2005 - 02:16 PM

Well here is a Semi Done Break down of the Stats section this section gets Double input bluck17 and Block34 Are exactly the same
i counted Every 1 Block as a Block if u want to fallow this order .
the addresses are just used for Refrince .. they probably will not be the same in yours
but the order inwitch the section goes will be ..
the Ps2 and PC game saves are exactly the same the A0080 are Ps2 addresses .. that i have not found out what that did ..
(the section should be the exact same on PC so here u are smile.gif
more to come .. i have almost the full section done..
(Note i started from a Block 1 start

ROM:0001E412 aBlock17:      
ROM:0001E417 aRankstat:    
ROM:0001E41B a00802164:    
ROM:0001E41F a00802168:      
ROM:0001E423 a0080216c:      
ROM:0001E427 a00802170:    
ROM:0001E42B a00802174:    
ROM:0001E42F a00802178:    
ROM:0001E433 a0080217C:    
ROM:0001E437 a00802180:      
ROM:0001E43B a00802184:      
ROM:0001E43F a00802188:      
ROM:0001E443 a0080218c:      
ROM:0001E447 a00802190:      
ROM:0001E44B a00802194:      
ROM:0001E44F aFashion_Budget:
ROM:0001E453 aProperty_Budget
ROM:0001E457 aAuto_RepairPainting_Buget
ROM:0001E45B a008021a4:      
ROM:0001E45F a008021a8:      
ROM:0001E463 a008021ac:      
ROM:0001E467 a008021b0:    
ROM:0001E46B aPlayer_Fat:  
ROM:0001E46F aPlayer_Stamina:
ROM:0001E473 aPlayer_Muscle:
ROM:0001E477 aPlayer_Health:
ROM:0001E47B aPlayer_Sex_Appeal
ROM:0001E47F a008021c8:      
ROM:0001E483 aDistance_Traveled_By_bicycle
ROM:0001E487 aDistance_Traveled_on_Treadmill
ROM:0001E48B a008021d4:      "
ROM:0001E48F aTattoo_Budget:
ROM:0001E493 aHairdressing_Budget
ROM:0001E497 a008021e0:    
ROM:0001E49B aProstitute_Budget
ROM:0001E49F a008021e8:      
ROM:0001E4A3 aMoney_Spent_gambling
ROM:0001E4A7 aMoney_Made_From_Pimpin
ROM:0001E4AB aMoney_Money_Won_gambling
ROM:0001E4AF aBiggest_gambling_win
ROM:0001E4B3 aGambling_Loss:
ROM:0001E4B7 aBurglary_Swag:
ROM:0001E4BB aMoney_Made_form_burglary
ROM:0001E4BF a00802208:    
ROM:0001E4C3 a0080220c:      
ROM:0001E4C7 aLongest_Treadmill_Time
ROM:0001E4CB aLongest_exercise_bike_time
ROM:0001E4CF aHeaviest_weight_on_bench
ROM:0001E4D3 aHeaviest_weight_on_dumbbells
ROM:0001E4D7 aBest_time_in_8_Track
ROM:0001E4DB aBMX_best_time:
ROM:0001E4DF a00802228:      
ROM:0001E4E3 aLongest_Chase_Time_with_5_Stars
ROM:0001E4E7 aLast_Chase_Time_With_5_Stars"
ROM:0001E4EB aWage_Bill:    
ROM:0001E4EF aStrip_Club_Budget
ROM:0001E4F3 aCar_mod_Budget"
ROM:0001E50F aTotal_Shopping_Budget
ROM:0001E517 aTotal_Respect: .
ROM:0001E51B a00802264:      
ROM:0001E51F a00802268:    
ROM:0001E523 a0080226C            
ROM:0001E527 a00802270:    
ROM:0001E52B aPistol:      
ROM:0001E52F aSillenced_Pistol
ROM:0001E533 aDesert_Eagle:
ROM:0001E537 aShotgun:      
ROM:0001E53B aSawn_Off:    
ROM:0001E53F aCombat_Shotgun
ROM:0001E543 aMachine_Pistol
ROM:0001E547 aSMG:          
ROM:0001E54B aAK47:        
ROM:0001E54F aM4:            
ROM:0001E553 aRifle:        
ROM:0001E557 a008022a0:      
ROM:0001E55B aGambling:      
ROM:0001E55F aPeople_Wasted_By_Others
ROM:0001E563 aPeople_Youve_Wasted
ROM:0001E567 aRoad_Vehicles_Destroyed
ROM:0001E56B aCrime_Boats_Destroyed
ROM:0001E56F aPlanes_Helicopters_Destroyed
ROM:0001E573 aCost_of_Property_Damaged
ROM:0001E577 aBullets_Fired
ROM:0001E57B aKGs_of_Explosives_Used
ROM:0001E57F aBullets_That_HIt
ROM:0001E583 aTires_Popped_With_Gunfire
ROM:0001E587 aNumber_of_Headshots
ROM:0001E58B aNumbe_of_Wanted_Stars_Attained
ROM:0001E58F aNumbe_of_Wanted_Stars_Evaded
ROM:0001E593 aDays_Passed
ROM:0001E597 aNumber_Of_Hospital_Visits
ROM:0001E59B aSafeHouse_Visits
ROM:0001E59F aTimes_Cheated
ROM:0001E5A3 aVehicle_Resprays
ROM:0001E5A7 aMaximum_Insane_Jump_Distance
ROM:0001E5AB aMaximum_Insane_Jump_Height
ROM:0001E5AF aMaximum_Insane_Jump_Flips
ROM:0001E5B3 aMaximum_Insane_Jump_Rotation
ROM:0001E5B7 aTimes_Busted              
ROM:0001E5BB a0080230c
ROM:0001E5BF aUnique_Jumps_Found
ROM:0001E5C3 aUnique_Jumps_Done
ROM:0001E5C7 aMission_Attempts
ROM:0001E5CB aMissions_Passed
ROM:0001E5CF a00802320:
ROM:0001E5D3 aCash_Made_in_A_Taxi
ROM:0001E5D7 aTaxi_Max_Fares
ROM:0001E5DB aCriminals_Killed_On_Vigilante_missions
ROM:0001E5DF aPeople_Saved_In_An_Ambulance
ROM:0001E5E3 aTotal_Fires_Extinguished
ROM:0001E5E7 aPackages_Deliverd
ROM:0001E5EB aAssassinations
ROM:0001E5EF aLast_Dance_Score

  • jarjar


  • Joined: 07 Aug 2005


Posted 02 February 2006 - 10:45 AM

Wow, i didn't know this even existed this topic. I have been working on a Save File Editor for SA for a while now, just decoding some of the save format when ever i get a chanch. And this will help me alot with the creation of it. Some of this stuff is quite amazing. I have only found abit of stuff, like the type of hair cut you have, the last missions, your percentage though the game, etc. But this would help alot. Is it okay if i use some of these for the editor? I will ofcourse give you the credit for your work.

Thanks in advanced...!

P.S. Great work, amazing what some people can do. Brilliant work guys.

  • zetski210

    Player Hater

  • Members
  • Joined: 17 Jan 2007


Posted 17 January 2007 - 05:14 AM

Sorry to bump this nearly 12 month old thread, but I was hoping there have been some developments in deciphering the save game format?!?

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users