Jump to content
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. Los Santos Drug Wars
      2. Updates
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Red Dead Online

      1. Blood Money
      2. Frontier Pursuits
      3. Find Lobbies & Outlaws
      4. Help & Support
    3. Crews

    1. Grand Theft Auto Series

      1. Bugs*
      2. St. Andrews Cathedral
    2. GTA VI

    3. GTA V

      1. Guides & Strategies
      2. Help & Support
    4. GTA IV

      1. The Lost and Damned
      2. The Ballad of Gay Tony
      3. Guides & Strategies
      4. Help & Support
    5. GTA San Andreas

      1. Classic GTA SA
      2. Guides & Strategies
      3. Help & Support
    6. GTA Vice City

      1. Classic GTA VC
      2. Guides & Strategies
      3. Help & Support
    7. GTA III

      1. Classic GTA III
      2. Guides & Strategies
      3. Help & Support
    8. Portable Games

      1. GTA Chinatown Wars
      2. GTA Vice City Stories
      3. GTA Liberty City Stories
    9. Top-Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    1. Red Dead Redemption 2

      1. PC
      2. Help & Support
    2. Red Dead Redemption

    1. GTA Mods

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Red Dead Mods

      1. Documentation
    3. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    4. Featured Mods

      1. Design Your Own Mission
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Rockstar Games

    2. Rockstar Collectors

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Movies & TV
      5. Music
      6. Sports
      7. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. Announcements

    2. Forum Support

    3. Suggestions

San Andreas Save File Companion


OrionSR
 Share

Recommended Posts

San Andreas Save File Companion

 

This topic is open to discussion of the details of all versions of San Andreas save files. It is intended to provide a wider context for the save structure than the wiki can provide, and a home for questions and investigations related to SA saves and documentation in the tradition of:

 

GTA III Save File Documentation and Vice City Save File Format

 

The official documentation of the save file structure for the PC version is available on the SA Save Wiki at GTAModding.com. This document serves as a baseline for all variations. The save wiki has been well tested for many years and is very accurate, but it could use a few updates, consistent formatting, and a modern naming convention for field variables.

 

SA Save Template for the 010 Editor: GTASA_010_BinaryTemplate_Xbox (on Google Drive)

 

010 templates can parse binary files into defined structures and variables. They are an invaluable tool for precisely documenting all known data and mapping out new structures. I'd prefer to use an open source tool but this is what we're working with now. Fortunately, the template files (*.bt) are in plain text and can serve as documentation for variations in saves of other systems.

 

SAS.bt - Original 010 template created by Seemann. PC version only. Includes checksum script.

SAS.multi.bt - Supports PC, PS2, PS2-J, and mobile versions of San Andreas.

GTASA_010_BinaryTemplate_2017 - Extended support for non-standard mobile saves, enumeration, and custom functions.

GTASA_010_BinaryTemplate_2019 - Minor adjustments to tasks, PopCycle, and names of structures.

GTASA_010_BinaryTemplate_Xbox - Latest Version - Added Support for OG Xbox Save Files (more info)

 

Always a work in progress.

 

Links to Related Topics:

 

Embedding Scripts in Save Files
SA Save File Glitch Detection and Repair

San Andreas Enex Documentation

[SA] girlfriend globals / bitmasks

Blip/Marker Struct - memory and save info

Cheat Code Creation - PS2 save editing using AR-Max, Codebreaker, etc.

Edited by OrionSR
Updated GTASA template
Link to comment
Share on other sites

Mobile version additionally saves an index (2 bytes) of script allocated to the object in CTheScripts::ScriptsForBrains array. Rest of fields, as named by DK22Pac (unless I renamed them for my convenience):

+24 byte bBonusValue

+26 word wCostValue

+28 dword nRemovalTime

+32 dword EntityFlags

+36 byte const 0

+40 dword ObjectFlags

+44 byte bObjectType

+45 byte bColDamageEffect

+46 byte bStoredColDamageEffect

+47 byte PhysicalFlags [partial, custom]:

1 DISABLE_COLLISION_FORCE

2 FREEZE_POSITION

4 IS_BULLETPROOF

8 IS_FIREPROOF

10 IS_COLLISIONPROOF

20 IS_MELEEPROOF

40 IS_EXPLOSIONPROOF

[+48 word wScriptTriggerIndex]

Edited by Nick007J
  • Like 2
Link to comment
Share on other sites

Thanks Nick. That will help a lot. Do you have the full reference? At first glance I'm having a difficult time aligning the hex and decimal offsets.

 

DK22Pac... So this a reference for objects in PCv1 memory?

 

I'm anxious to start mapping things out against save records and to experiment with the flags but first I need to figure out why the timer reset fix is breaking Vice City saves. I've got reports that shopkeepers are refusing to spawn after the fix, and a glitch in a published tool has priority status.

Edited by OrionSR
Link to comment
Share on other sites

DK22Pac... So this a reference for objects in PCv1 memory?

I used his field names for CObject structure in memory, as they are called in plugin-sdk.

https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CObject.h

 

As I see it now, I only changed hungarian notation prefixes for consistency with how I use it. I haven't got to CObject myself yet so can't comment too much on their exact meaning, but I don't see any reason not to trust his names.

 

 

I'm anxious to start mapping things out against save records and to experiment with the flags but first I need to figure out why the timer reset fix is breaking Vice City saves. I've got reports that shopkeepers are refusing to spawn after the fix, and a glitch in a published tool has priority status.

I will comment in relevant topic soon, I already know why it happens as this is a crucial knowledge for speedrunning Vice City.

Link to comment
Share on other sites

0x38 - bObjectType?

I think I found a strategy to flag objects so they won't be saved. At save object record offset 0x38 is what I suspect is the Type field. The value is always 2 in my current set of examples; I suspect these are type 2 mission objects. When this value was edited to 6 to indicate "OBJECT_MISSION2" the object is missing in the next save. In the PC version object type 0 will be removed, but on Android they are changed back to type 2 objects.

I managed a little progress on several of the flags. I'm not exactly sure if I've got the EntityFlags and ObjectFlags named properly. All offsets are for PC, and for these offsets anyway, appear to apply to Android as well. Unknown flags have been observed.

    0x2C Opcode	EntityFlags      01  0382:	collision detection      04  	unknown      20  0392:	moveable      80  0750:	visible    0100	unknown    1000	unknown    4000  0418:	draw last    8000	unknown  010000	unknown  020000  0905:	openable  200000	unknown08000000	unknown10000000	unknown
    0x34 Opcode	ObjectFlags      10	unknown      20	unknown      40	unknown    0200  035D:	targetable    0400  0723:	broken    2000  08E9:	liftable (stealable)    4000	unknown    8000	unknown  010000	unknown  040000  0916:	attractive_to_magnet  080000	unknown
0x3B	PhysicalFlags	  01	Disable_Collision_Force (0550: keep object in memory)  02	Freeze_Position  04	Is_Bulletproof (09CA:)  08	Is_Fireproof (09CA:)  10	Is_Collisionproof (09CA:)  20	Is_Meleeproof (09CA:)  40	Is_Explosionproof (09CA:)

Based on the reference posted by Nick, I suspect but haven't tested:

0x39 bColDamageEffect0x3A bStoredColDamageEffect

Opcodes that produced no changes in the save record:

0566: link_object $2658 to_interior 100654: make_object $2658 fireproof 1 (render scorched)071F: set_object $2658 health_to 4007F7: set_object $2658 destructible 1 // or 00875: set_object $2658 immune_to_nonplayer 1 // or 008D2: object $2658 scale_model 2.50906: set_object $2658 mass_to 1000.0 // float0908: set_object $2658 turn_mass_to 500 // float (whoops)04D9: set_object_records_collisions $2658 to 1

Specific Objects Blocking Missions

 

Burning Desire, Model ID 3029, cr1_door, $4052, $2665 PC, remove if handle does not match global

Architectural Espionage, Model ID 1491, Gen_doorINT01, remove all

 

Breaking the Bank at Caligula's...

  • 3037, warehouse_door2b, remove all
  • 3089, ab_casdorLok, $4090. $2703 PC, remove if handle doesn't match global
  • 2634, ab_vaultDoor, remove all
Edited by OrionSR
Link to comment
Share on other sites

Progress on the object structure has stalled, but I made enough progress on my templates to get a script working for the 010 editor that can remove the glitchy objects that block missions. I'm working to expand my scripts to remove most of the trash objects from mobile saves without removing the standard objects from the map. To do that, I needed a list of saved objects in an In the Beginning save and information on what's added or removed later by missions.

 

Saved Object List for In the Beginning

 

Index Opcode   MobVar   PC_Var   X          Y           Z        ModelID  ModelName           Description0     029B:    $4045    $2658    1903.383   967.62      11.438   3084     TRDCSGRGDOOR_LVS    Four Dragons garage door used in casinos and heists1     029B:    $4046    $2659    2167.82    -1518.193   20.237   3083     MD_POSTER           billboard poster removed during Reuniting the Families2     029B:    $4051    $2664    1055.629   2087.67     12.469   2938     SHUTTER_VEGAS       loading bay door moved in You've Had Your Chips3     0107:    $4052    $2665    2352.851   -1171.027   26.9669  3029     CR1_DOOR            gang house door replaced in Burning Desire4     029B:    $4053    $2666    -2179.353  661.232     50.214   3036     CT_GATEXR           no parking gate removed in Mountain Cloud Boys5     029B:    $4054    $2667    215.941    1874.571    13.903   2927     A51_BLASTDOORR      blast door in Black Project6     029B:    $4055    $2668    211.842    1874.571    13.903   2929     A51_BLASTDOORL      blast door in Black Project7     029B:    $4056    $2669    297.766    1842.618    6.764    2951     A51_LABDOOR         lab door in Black Project8     0107:    $4057    $2670    268.664    1884.06     15.925   3095     A51_JETDOOR         jetpack escape hatch in Black Project9     0107:    $4058    $2671    -2108.0    155.0       35.639   1684     PORTAKABIN          cabin in Doherty broken in Deconstruction10    0107:    $4059    $2672    -2089.0    172.0       35.639   1684     PORTAKABIN          cabin in Doherty broken in Deconstruction11    0107:    $4060    $2673    -2069.0    229.0       36.611   1684     PORTAKABIN          cabin in Doherty removed in Deconstruction12    0107:    $4061    $2674    -2077.0    271.0       35.337   1684     PORTAKABIN          cabin in Doherty broken in Deconstruction13    0107:    $4062    $2675    -2096.0    261.0       36.171   1684     PORTAKABIN          cabin in Doherty broken in Deconstruction14    0107:    $4063    $2676    -2129.0    306.0       35.314   1684     PORTAKABIN          cabin in Doherty broken in Deconstruction15    0107:    $4089    $2702    -2468.141  1547.938    22.7     2944     FREIGHT_SFW_DOOR    cabin door in The Da Nang Thang16    029B:    $4090    $2703    2168.644   1619.43     1000.3   3089     AB_CASDORLOK        door to loading area in Breaking the Bank at Caligula's17    0107:    $4093    $2706    1833.36    -1995.45    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects18    0107:    $4094    $2707    1819.81    -1994.66    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects19    0107:    $4095    $2708    1827.68    -1980.0     12.5     3061     AD_FLATDOOR         extra doors in El Corona projects20    0107:    $4096    $2709    1851.84    -1990.67    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects21    0107:    $4097    $2710    1867.29    -1984.96    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects22    0107:    $4098    $2711    1866.52    -1998.53    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects23    0107:    $4099    $2712    1899.75    -1984.95    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects24    0107:    $4100    $2713    1914.39    -1992.82    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects25    0107:    $4101    $2714    1899.01    -1998.5     12.5     3061     AD_FLATDOOR         extra doors in El Corona projects26    0107:    $4102    $2715    1900.89    -2020.11    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects27    0107:    $4103    $2716    1914.4     -2020.91    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects28    0107:    $4104    $2717    1906.54    -2035.52    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects29    0107:    $4105    $2718    1851.86    -2020.14    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects30    0107:    $4106    $2719    1865.42    -2020.89    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects31    0107:    $4107    $2720    1857.55    -2035.52    12.5     3061     AD_FLATDOOR         extra doors in El Corona projects32    029B:    $4108    $2721    2522.008   -1272.93    35.609   3059     IMY_SHASH_WALL      smash wall removed in End of the Line33    029B:    $4109    $2722    -2080.441  256.015     66.869   1383     TWRCRANE_M_04       Doherty crane34    029B:    $4110    $2723    -2080.441  256.007     99.408   1384     TWRCRANE_M_01       Doherty crane35    029B:    $4111    $2724    -2080.441  296.46      102.861  1385     TWRCRANE_M_02       Doherty crane36    029B:    $4112    $2725    -2080.441  256.015     66.869   1404     LODCRANE_M_04       Doherty crane37    029B:    $4113    $2726    -2080.441  256.007     99.408   1403     LODCRANE_M_01       Doherty crane38    029B:    $4114    $2727    -1547.978  123.9883    26.9332  1380     MAGNOCRANE_01       export crane39    029B:    $4115    $2728    -1547.978  123.988     26.933   1379     MAGNOCRANE_02       export crane40    029B:    $4116    $2729    -1546.573  125.662     35.443   1382     MAGNOCRANE_03       export crane41    029B:    $4117    $2730    -1547.978  123.988     26.933   1398     LODNOCRANE_01       export crane42    029B:    $4118    $2731    -1547.978  123.988     26.933   1399     LODNOCRANE_02       export crane43    029B:    $4119    $2732    -1546.573  125.662     35.443   1400     LODNOCRANE_03       export crane44    029B:    $4127    $2740    709.45     915.93      -19.66   16330    QUARRY_CRANEBASE    quarry crane45    029B:    $4128    $2741    709.45     915.93      -15.591  16328    QUARRY_CRANE        quarry crane46    029B:    $4129    $2742    709.45     915.93      -14.570  16329    QUARRY_CRANEARM     quarry crane47    029B:    $4130    $2743    2399.202   1879.139    37.55    1383     TWRCRANE_M_04       Venturas crane48    029B:    $4131    $2744    2399.202   1879.139    70.071   1384     TWRCRANE_M_01       Venturas crane49    029B:    $4132    $2745    2399.202   1899.139    73.860   1385     TWRCRANE_M_02       Venturas crane50    029B:    $4133    $2746    2399.202   1879.139    37.550   1404     LODCRANE_M_04       Venturas crane51    029B:    $4134    $2747    2399.202   1879.139    70.071   1403     LODCRANE_M_01       Venturas crane52    029B:    $1266    $1242    2401.75    -1714.477   13.125   1498     GEN_DOOREXT03       Denise's door53    029B:    $1267    $1243    -2574.495  1153.023    54.669   1505     GEN_DOOREXT07       Katie's door54    029B:    $1268    $1244    -1800.706  1201.041    24.12    1496     GEN_DOORSHOP02      Michelle's door55    029B:    $1269    $1245    -383.46    -1439.64    25.33    1501     GEN_DOOREXT04       Helena's door56    029B:    $1270    $1246    -1390.79   2639.33     54.973   1522     GEN_DOORSHOP3       Barbara's door57    029B:    $1271    $1247    2038.036   2721.37     10.53    1498     GEN_DOOREXT03       Millie's door58    029B:    $1272    $1248    -371.4     -1429.42    26.47    3093     c*ntGIRLDOOR        Helena's barn door59    029B:    $1219    $1195    -1543.742  -432.703    6.039    988      WS_APGATE           SF airport gate60    029B:    $1220    $1196    -1547.625  -428.82     6.039    988      WS_APGATE           SF airport gate61    029B:    $1221    $1197    -1222.953  53.826      14.134   988      WS_APGATE           SF runway gate62    029B:    $1222    $1198    -1218.206  68.883      14.134   988      WS_APGATE           SF runway gate63    029B:    $1223    $1199    1964.342   -2189.776   13.533   988      WS_APGATE           LS airport gate64    029B:    $1224    $1200    1958.851   -2189.777   13.553   988      WS_APGATE           LS airport gate65    029B:    $1225    $1201    1704.777   1605.165    10.058   988      WS_APGATE           LV airport gate66    029B:    $1226    $1202    1706.364   1610.422    10.058   988      WS_APGATE           LV airport gate67    0107:    $6561    $5177    245.968    1862.843    19.49    3117     A51_VENTCOVERB      area 51 vent cover68    029B:    $6674    $5290    -1465.797  501.289     1.145    3113     CARRIER_DOOR_SFSE   carrier back door69    029B:    $6675    $5291    -1414.453  516.453     16.688   3114     CARRIER_LIFT2_SFSE  carrier side lift70    029B:    $6676    $5292    -1456.719  501.297     16.953   3115     CARRIER_LIFT1_SFSE  carrier rear lift

 

 

 

Saved Objects Changed by Missions

 

Total  Opcode    MobVar    PC_Var    X           Y            Z          ModelID  ModelName       Description70     029B:     $4046     $2659     2167.82     -1518.193    20.237     3083     MD_POSTER       billboard poster removed during Reuniting the Familes74     029B:     $4047     $2660     2322.845    8.304        25.483     2947     CR_DOOR_01      cafe back door added by Small Town Bank74     029B:     $4048     $2661     2316.233    0.712        25.742     2947     CR_DOOR_01      bank back door added by Small Town Bank74     029B:     $4049     $2662     2304.257    -17.744      25.742     2946     CR_DOOR_03      bank front door added by Small Town Bank74     029B:     $4050     $2663     2304.257    -14.583      25.742     2946     CR_DOOR_03      bank front door added by Small Town Bank73     0107:     $4060     $2673     -2069.0     229.0        36.611     1684     PORTAKABIN      cabin in Doherty removed in Deconstruction72     029B:     $4053     $2666     -2179.353   661.232      50.214     3036     CT_GATEXR       no parking gate removed in Mountain Cloud Boys73     IMPEXPM   [email protected]       [email protected]       -1573.881   135.3845     2.535      3077     NF_BLACKBOARD   blackboard used by import/export thread72     029B:     $4108     $2721     2522.008    -1272.93     35.609     3059     IMY_SHASH_WALL  smash wall removed in End of the Line 

 

 

 

Notes:

Known to delete Export Blackboard if repeated after it's creation - very rare.
0108: destroy_object $201($200,46i) // Back to  School0108: destroy_object $201($200,46i) // Bike School

It looks like the doors added by Small Town Bank were intended to be added during the initial game setup along with most of the other objects but they weren't removed from the mission cleanup list. These handles might reference objects that no longer exist early in the game.

 

Object groups like the bridge barriers are not controlled by this process.

Replacement objects for YKBB are controlled by another process.

 

Missions that use saved objects often destroy and replace the object during the mission. The replacement object will probably have a new handle which will change the index associated with each object within the save.

Edited by OrionSR
Link to comment
Share on other sites

Notes on modifying San Andreas 010 templates to parse mobile saves:

 

I'm gathering the info I need for a multi-version SA template.

 

Block 0 - Misc: All messed up. I'll come back to this.

 

Block 1 - Script:

 

Extra 4 bytes (int?) at +8.

    short   index;    /* Script Thread */    int     pNext <format=hex>, pPrev <format=hex>;    int     mobileStuff0; //mobile

Mobile threads have 40 local variables.

    int     locals[40]; //mobile

There is extra information at the end of this block. I'm not sure what it does but I think I've managed to map it's structure well enough to handle most 1.06+ saves with the following changes to the end of block1's structure.

    int                 mobileStuff1; //mobile    tThread             threads[nRunningThreads];    WORD                unknownMobileCount;     WORD                unknownMobileA;    WORD                unknownMobileB;    struct tUnknownMobileStruct        {            int                unknownMobile;            WORD               unknownMobile1;            WORD               unknownMobile2;            WORD               unknownMobile3;        } unknownMobileStruct[unknownMobileCount];} block1;

Block 2 - Player and Objects

 

Modified tPlayer struct

 

 

struct tPlayer{    DWORD       handle;    int         modelID;    int         pedType;    DWORD       _size1<format=hex>;    /*0x18C*/    RwV3D       pos;    int         unknown_mobileP;  //mobile    float       health, armor;    tWeapon     weapons[13];    byte        ref;    byte        weaponSlot;    byte        unknown;    byte        __gap1[13];    int         unknown_enex;    byte        unknown_melee1;    byte        unknown_melee2;    byte        __gap2[10];    DWORD       _size2<format=hex>;    /*0x84*/    int         chaos;    byte        wantedLevel;    DWORD       texturesCRC[28]<format=hex>;    byte        __gap3[3];    float       fat, muscle;    DWORD       __gap4;    int         mobileJunk[6];  //mobile};

 

 

 

Modified Object Struct

 

struct tObject{       DWORD       handle;    int         modelID;    DWORD       _size;    /*52*/    RwV3D       pos; // 3 floats    byte        pos_right[3];    byte        pos_top[3];    int         unknownModel0 <format=hex>;    int         unknownModel1 <format=hex>;    byte        unknown[6];    int         entityFlags <format=hex>;    int         unknownModel2 <format=hex>;    int         objectFlags <format=hex>;    byte        bObjectType;    byte        bColDamageEffect;    byte        bStoredColDamageEffect;    byte        physicalFlags <format=hex>;    WORD        unknownMobile1; //mobile only (swap these for iOS)    WORD        unknownMobile2; //mobile only (last in Android)};

 

 

 

Block 9 - Markers

 

They added more markers in the 1.06 patch.

// Block 9: Markersstruct tBlock09_Markers{    tblockHeader    header;        tMarker         markers[250]; // mobile} block9;

Block 23 - Gangwars

 

An extra byte at end.

    byte            unknown4mobile; // mobile} block23;
Edited by OrionSR
Link to comment
Share on other sites

I'm trying to identify and document the fields of a "player car" structure unique to SA Mobile quick saves and auto-saves. I'm hoping that if I can fill in enough details that the structure's elements might start to look familiar to people more experienced with this type of data.

 

The player car structure is located at +580 within the player struct of the Player and Objects block.

The structure length is 176 bytes for vehicles without passenger seats.

Vehicles that can support passengers have an additional 24 byte structure, which throws off the offsets at the end.

 

+0 dword vehicleHandle, unconfirmed

+4 dword modelID

+8 dword size of following data without optional structures

+12 72 bytes struct CMatrix

+84 byte radioStation (enum?)

+85 4 bytes colors

+89 (align)

+90 word alarmState

+92 byte nPassengers seats available

+96 float wheelState

+100 float gasPedalState
+104 float breakPedalState
+108 8 bytes vehicleFlags

+116 float health

+120 int doorLock

+124 4 bytes physicalFlags

+126 byte immunity flags

+128 float mass

+132 float turnmass

+136 float buoyancy

+140 24 bytes optional damageManager struct

+140 2 bytes struct trains

+140 driverHandle

+144 8 dwords passengerHandles

The offsets above have been updated with available information.

The screenshots below were created with early guesses.

 

BMX and Camper: SGMIQdcm.jpg

 

Expanded Rotations JTfO6Zqs.jpg

 

Properties not saved in the player car structure are: mod parts, nitro, hydraulics, paintjobs, extra part variations, bombs, and custom plates. I don't expect to find handling flags if hydraulics don't save.

Edited by OrionSR
Link to comment
Share on other sites

Additions to the structure I managed to find.

+12 CMatrix (geometrical description of vehicle position in the world, three vectors and position (all with dummy 4 bytes after three floats), and 2 more zeros after it (unused in saved matrix), structure is 72 bytes)

+90 (2 bytes) alarm state

+96 (float) wheel state

+100 (float) gas pedal state

+104 (float) break pedal state

+108 (8 bytes) vehicle flags

+120 (int) [most likely 'projectile fire time' or 'door lock', I would say the latter, can't give exact answer because of minor vehicle structure shift in mobile version]

+124 (4 bytes) physical flags

+136 (float) buoyancy?

[optional fields]

+140 (for automobiles only) (CDamageManager) damaged state, 24 bytes

+140 (for trains only) unknown 2 bytes value; if train is a mission train, followed by value of CTrain::bDisableRandomTrains (1 byte)

[end of optional fields]

+140 (+offset) (int) driver handle

+144 (+offset) (int[8]) passengers handles

Link to comment
Share on other sites

Trains? I doubt I would have thought of that. Thanks. But that means my template is still broken. I'm not sure if these are the same question but...

 

Have you seen any sign of an IS_TRAIN flag? Are the vehicle flags (and physical flags) well documented in other structures?

 

Alarm State: a word? or state 0 and state 1?

 

Um... okay. It'll take a while to fill in the fields. I'll hold anymore questions until then.

 

No, wait. Damage manager? Okay, that makes sense but automobiles only? I'll recheck on a motorcycle but I thought I checked this on an NRG. My thought was the bicycles don't have this structure, which makes sense since bicycles don't take damage unless they flip perfectly and explode. I'm not sure how to flag this structure if nPassengers doesn't hold true. I think I'll take another look at your vehicle flags and see if I can align anything with the modelFlags in handling.cfg.

 

Edit 1) Dummy data in CMatrix: There is definitely data in these floats in a couple of these 100% SnP saves - BMX and NRG-500. It looks like the player was getting 100% from the Chiliad Challenge and the game saved while the bike was in motion. However, the vehicle doesn't seem to be moving during the fade-in from loading.

 

Edit 2) +120 confirmed as door lock. I locked the door with my editor and tweaked the ped handle so CJ would spawn on top of the camper. It should have been an easy test but the ped handle I chose put a driver in the car and she drove off when CJ jumped off the roof. So... driverHandle at +140(+offset) has been confirmed as well. CJ is driving if driverHandle == .player.handle, or -1.

 

+136 float values for:

  • Coach. 84.44444
  • Greenwood, 18.28572
  • Brown Streak, 48.88889
  • Camper, 17.88235
  • Tampa, 19.42857
  • MtBike & BMX, 0.776699

+89 byte, align? (unused bytes that pad memory so the next word. dword or structure can start on a doubly-even offset)

Edited by OrionSR
Link to comment
Share on other sites

Dummy data in CMatrix: There is definitely data in these floats in a couple of these 100% SnP saves - BMX and NRG-500. It looks like the player was getting 100% from the Chiliad Challenge and the game saved while the bike was in motion. However, the vehicle doesn't seem to be moving during the fade-in from loading.

Oh right, you are correct, first 4 bytes (between first two vectors, so at +24) represent flags. I don't know their meaning, however.

 

 

Trains? I doubt I would have thought of that. Thanks. But that means my template is still broken. I'm not sure if these are the same question but...

 

Have you seen any sign of an IS_TRAIN flag? Are the vehicle flags (and physical flags) well documented in other structures?

Game uses "type" column from vehicles.ide to identify vehicle as a train. Besides general model info data, which holds this information, each vehicle contains a vehicle type in its memory structure.

 

Vehicle flags are described here:

https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CVehicle.h

(starting with 'unsigned char bIsLawEnforcer : 1; // Is this guy chasing the player at the moment')

 

Physical flags are described here:

https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CPhysical.h

(starting with 'unsigned int b01 : 1;')

 

I have minor additions to it:

b01 => bIsHeavy

bInvulnerable => bIsOnlyDamagedByPlayer

 

I also have notes about b17 that it is calculated during collision testing and that it probably affects how collision should be processed this frame.

 

 

Alarm State: a word? or state 0 and state 1?

A word. -1 for "car has alarm system", values >=0 mean 'how many milliseconds remaining for alarm to be active' (when alarm is triggered this value is set to 15000).

 

 

No, wait. Damage manager? Okay, that makes sense but automobiles only? I'll recheck on a motorcycle but I thought I checked this on an NRG. My thought was the bicycles don't have this structure, which makes sense since bicycles don't take damage unless they flip perfectly and explode. I'm not sure how to flag this structure if nPassengers doesn't hold true. I think I'll take another look at your vehicle flags and see if I can align anything with the modelFlags in handling.cfg.

To be more certain, automobiles and everything derived from them (helis, monster trucks, planes, quadbikes and trailers). Bikes should not have this structure. This structure is described here:

https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CDamageManager.h

 

 

+89 byte, align? (unused bytes that pad memory so the next word. dword or structure can start on a doubly-even offset)

Alignment, yes.

 

 

+136 float values for:

  • Coach. 84.44444
  • Greenwood, 18.28572
  • Brown Streak, 48.88889
  • Camper, 17.88235
  • Tampa, 19.42857
  • MtBike & BMX, 0.776699

Buoyancy is calculated as

B = m * 0.8 / ps

where m is mass of vehicle and ps is 'percent submerged' in handling data. Values you provide seem to correspond to this formula.

Link to comment
Share on other sites

Thanks again. I won't be able to investigate this until after work but, when I saved a Brown Streak I had it running in full speed reverse but that dummy data was still blank. So, maybe something specific to a MtBike. Brake pedal state was active though.

 

Updated:______________________________________________________________________

 

As expected, an NRG broke my script. I'll get to work

 

If I understand correctly, there's nothing in the save preceding the option fields to indicate vehicle type other than model IDs. So if I want to find the type properly then I need to parse vehicle.ide for use by my template. I may consider that later but for now I think I'll consider the automobile structure as default and run options for motorcycles and bicycles), and train models. I guess I'll learn more as I dig through the file.

 

trains:

 

590 freibox569 freiflat537 freight538 streak570 streakc449 tram
bikes:

 

581	bf400523	copbike462	faggio521	fcr900463	freeway522	nrg500461	pcj600448	pizzaboy468	sanchez586	wayfarer
bmx:

 

481	bmx509	bike510	mtbike
boat:

 

472 coastg473 dinghy493 jetmax595 launch484 marquis430 predator453 reefer452 speeder446 squalo454 tropic

 

Damn. It'd be so much easier if it just saved these flags instead of that other useless junk.

Edited by OrionSR
Link to comment
Share on other sites

Can anyone explain this ped/object/weapon structure that was tacked onto the end of the script block? I've got it mapped out, but I don't understand what I'm reading well enough to label much of anything.

 

h5Xwdqjs.jpg

 

What's not shown in the screenshots is that the models tend to be added in reverse. Mobile2[0] is 75 (max records) if there is only one record in the structure, and 74 if there are two. MobileA = Mobile2[0] - 1.

    if (isMobile == 1) {        WORD                MobileCount;    // nRecords        WORD                MobileA;        // minIndex        WORD                MobileB;        //         struct tMobileStruct        {            struct tModel            {                int                modelID;           // modelID                WORD               Mobile1;          // type?                WORD               Mobile2;          // index? [string length]                WORD               Mobile3;          // maxIndex?                if (modelID >= 290 && 299 >= modelID) {                    char modelName[Mobile2];                    int MobileInt <format=hex>;              //handle?                }            } Model[MobileCount] <optimize=false>;        } MobileStruct;    }

So... objects and weapons and ped (oh my). I've got it mapped and don't know what it does. I've read reports of extra Denise's hanging around after save exploits but I haven't looked into it yet. Any suggestions?

Edited by OrionSR
Link to comment
Share on other sites

Description of struct CMatrix (72 bytes):

 

I'm having a difficult time sorting out how I want to rework and describe the CMatrix structure. My thought is to organize most of the data into 4 structs of 4 floats, currently described as X, Y, Z and dummy. Description for structs would be:

 

+0 struct LevelToGround

+16 struct LookingDirection

+32 struct dymamic flight data?

+48 struct position

+64 dword unknownA

+68 dword unknownB

+72 (end)

I'm not at all confident in any of the descriptions besides position and (end).

Edited by OrionSR
Link to comment
Share on other sites

This mobile structure is generated by CScriptResourceManager::Save().

 

I documented this structure (for PC version) as follows:

 

 

struct CScriptResourceManager{  CScriptResourceEntry m_asResources[75];};struct CScriptResourceEntry{  int m_nResourceID;  CRunningScript *m_pScript;  short m_wType;  char gap_10[2];};
This structure holds information about which resources were requested. Following opcodes register resource in manager:

 

Type 1 (animation - values starting with 25575)

REQUEST_ANIMATION [+]

REMOVE_ANIMATION [-]

 

Type 2 (model - model ids; special chars have models 290-299)

LOAD_SPECIAL_CHARACTER [+]

REQUEST_MODEL [+]

MARK_MODEL_AS_NO_LONGER_NEEDED [-]

UNLOAD_SPECIAL_CHARACTER [-]

 

Type 3 (decision maker - likely to be high values)

COPY_SHARED_CHAR_DECISION_MAKER [+]

REMOVE_DECISION_MAKER [-]

 

(command IDs and opcode names correspond as here: http://pastebin.com/raw/kCwS6rdG)

 

If I understand correctly, this is how (probably) it should be stored in a save:

 

WORD count;struct ResourceManager {  WORD index; //index in manager array  WORD scriptIndex; //index of a script  int resourceID;  WORD type;  if (type == 2 && resourceID >= 290 && resourceID <= 299){    int length;    char modelName[length]  }} [count];
Edited by Nick007J
Link to comment
Share on other sites

Oh yeah. That's what I was watching when you were showing how the dealers spawn.

 

Hm... To align with what I see, maybe...

WORD count;struct ResourceManager {  int resourceID;  WORD type;  WORD index; //index in manager array  WORD scriptIndex; //index of a script  if (type == 2 && resourceID >= 290 && resourceID <= 299){    char modelName[index]    int dunno;  }} [count];

Using index for length saves me the trouble of creating a local variable length = index. It doesn't make sense grammatically but that's how the data is used here.

 

 

Type 2 (model - model ids; special chars have models 290-299)

LOAD_SPECIAL_CHARACTER [+]
REQUEST_MODEL [+]
MARK_MODEL_AS_NO_LONGER_NEEDED [-]
UNLOAD_SPECIAL_CHARACTER [-]

How best to flag resources so they are removed when the save is loaded, or at least not saved again? I'm thinking 0 if that does everything with a [-] designation.

 

Do you have any suggestions for intentionally saving resources? Some saves may have as many as 5 or 6. I was amazed when I came across a save with the resources maxed out at 75. What would that do to a save?

Link to comment
Share on other sites

How best to flag resources so they are removed when the save is loaded, or at least not saved again? I'm thinking 0 if that does everything with a [-] designation.

 

Do you have any suggestions for intentionally saving resources? Some saves may have as many as 5 or 6. I was amazed when I came across a save with the resources maxed out at 75. What would that do to a save?

Originally, resource manager is just informational, as far as I understand. It just registers that something was requested or marked as no longer needed. The only time this array is actually being checked is at the end of cutscenes, when presence of a model in the manager may block marking stuff as no longer needed. Presence of many resources may suggest that either mission might be badly programmed, or that one of missions was incorrectly finished (something related to duping, for example), or that a mission is currently running.

 

The manager in mobile version is more useful, most notably allowing saving during missions, so that models are loaded upon reload.

 

Is your first question about how to remove these resources from save? Probably setting type to 0 and resourceID to -1 should do the trick.

Link to comment
Share on other sites

Yes, I'm looking towards strategies to edit the saves; documentation is an important early step. The primary focus is always on glitch detection and repair, but I always have an eye out for strategies to customize saved games. Can the resource manager be responsible for extra Denise's hanging around after dating exploits? Reports suggest that her body will persist if killed. I'm starting to doubt that these issues are related.

 

Removal strategy: Type 0 to force the game to remove the resource, that makes sense. Disabled modelID resourceID, to prevent changes to active resources when the save first loads? Disabling the resourceID will break my template if I run it on this save as the special actors will still have strings.

 

To answer the question I was going to ask: resourceID is a super-set of model ID that also includes animation IDs and decision IDs.

 

Pending an extra Denise save to investigate, the next major save structure is liable to be difficult. Those slot 10 mission saves are larger by 65000 bytes; enough to hold the largest mission. I'm not sure what to expect. I haven't even adjusted my PC template for this purpose. Players can save missions on PC using a basic saveanywhere script that doesn't check for OM0. The saves just won't load unless you put the mission thread to sleep for a while, and that's harder to do with a broken template. (I could use an strategy to kill threads and missions using an editor. I always use cleo for this purpose.)

 

Here's a link to that save with 75 extra player resources. It's a 100% save named Wrong Side of the Tracks, so I would suspect some exploits were being used. Or a mission select mod.

 

I've been able to save one player vehicle but not 2 or 3 like in some of these saves.

Edited by OrionSR
Link to comment
Share on other sites

My first efforts to adapt my template for the larger slot 10 mission saves have failed miserably. I'll document what I've learned so far as a lead-in to another investigation.

 

If a PC player saves during a mission using a saveanywhere script that doesn't check for OM0 (not that that matters much anymore) the save will crash when loaded, but the glitch can be fixed by putting the thread to sleep and killing it with cleo. These saves load just fine in my template without modification, but it doesn't look like the "mission" gets saved, it's just a "thread" with the properties of the mission. SASE also reads these threads without issue.

 

I tried again to kill an active mission thread on PC without any luck. Setting the wake time to something large keeps it from crashing right away, but tweaking other variables isn;t helping.

 

isActive = 0 loads but cleo scripts don't work so I can't save.

isActive = -1 can be saved but the mission thread persists in the save.

Fiddling with the short index at the start of the record always produced a crash.

 

I can't think of anything else that might cause the thread to end by randomly fiddling with the settings. Instead I think I'll look for something in the standard scripts that can kill a sleeping thread for me if I rename it properly. Any suggestions?

 

Can anyone explain the "range" of the pointers at the start of the thread structures. I'm trying to estimate the range of possible pointer values for pPrev (+6) and currentIP (+22) of the main thread, which should always be located at a static offset in mobile saves. My hypothesis is that I can detect the difference between iOS and Android pointers. Android uses global and local memory addresses quite differently than PC, leading to huge values for most pointers.

 

pPrev (dword preceding "main"):

A2886CF0 - Android

006B59B4 - iOS

00A90590 - PCv1

 

I'm not sure what to expect from the Remastered version. I have no known examples to work with. And I only have known iOS saves from one source, which isn't helping. Anyone have a save to donate? Anything will do - start a new game, move away from the bike so the safehouse icons can appear, and pause to produce a slot 10 quicksave. Android saves are useful too. I assume most of what I see are Android saves but I can't tell for sure yet.

 

Missions in Mobile Saves

 

From what I can tell the whole mission is saved in-line with the other threads as I see plenty of strings that associate with this mission, and there's a chance that other threads can exist after a mission thread. The structure varies from a thread right away - the thread name is offset by -5 and not even the index looks right. So... stumped again for a while. I think I'll go back to my global variable translation table and look for a what to convert it for 010 so I can finally get my object cleanup scripts working.

 

Added:_________________________________________

 

Can anyone explain the function of the short index that begins each thread? It seems to be the only hint that a mission is impending in a mobile save. Scanning through thread indexes I find a lot of values in the 0x45 range, give or take a dozen or so, but I haven't worked out a meaning of the values. But when I encounter a mission as the next thread, this example reads as 0x8046. So I'm thinking that 80 byte is flagging it as a mission. The index short is followed by an unknown mobile dword, always -1 as far as I've seen. Then I get 03A4: name_thread 'CRASH1' 0050: gosub and I get lost as I'm not as good at decompiling as Sanny is. How am I supposed to know where the mission ends? I just want to block around it.

Edited by OrionSR
Link to comment
Share on other sites

SA Mobile Mission Saves - got it working for a single example.

Mission saves are created by the checkpoint system of some missions, and can also be enabled during other missions by failing and trying again. Mission saves are typically found in slot 10, the slot that is loaded when resuming a game after a fresh start or retying a failed mission. They are easily overwritten by quick-saving while pausing, but can easily be renamed to another slot. Mission saves are 65000 bytes larger than other mobile saves.

It doesn't make sense to define saves by their slot or save/load strategy. Any save will work in any slot. Auto-saves are written to and read from slot 9, and quick/checkpoint/resume saves are assigned to slot 10. Manage the slots to best suit your needs.

Before making changes to accommodate a mission thread, I had to move my unknown mobileStuff0 int before the pointers. To get the normal threads fixed. Then, if the index is negative then reserve 73096 bytes for mission code. I suspect there's stuff besides just code in this data, like local variables, but for now it's good enough for testing.

Update: I found the locals hiding behind the couch. 69000 bytes for mission code as documented elsewhere, and 1024 dwords for local variables. They're all empty though, except for a nominal value in the timers.



struct tThread{    short   index;    /* Script Thread */    if (isMobile==1) int mobileStuff0 <format=hex>; //mobile    if (index < 0) missionThread = 1;    if (index < 0) byte   missionCode[69000];    if (index < 0) DWORD  localvar[1024];       int     pNext <format=hex>, pPrev <format=hex>;    char    name[8];    int     baseIP <format=hex>;    int     currentIP <format=hex>;

If there's a missionThread then an 8 byte character field for the mission name is created at the end of all structures, follow by an unknown dword, and then the start of the next BLOCK begings.

 

Update: The character field for the mission name isn't holding true for other missions. 8 bytes are still required to round out the structure for mission saves but I'm not sure what these bytes are for.

        if (missionThread == 1) {            char missionName[8];            int uMobile1;        }    }} Script;[size=4][/size]
Edited by OrionSR
Link to comment
Share on other sites

int mobileStuff0 is an index of a streamed script, if saved script is streamed. I am not sure if they can actually be saved (they certainly are not on PC).

 

There is a variable before block with mission name and "uMobile1", which is a value of "IsOddJob", which is set to 1 if a command CHECKPOINT_SAVE_ODDJOB (0A77) [with an exception of "crane2" in combination with OM1] has been executed before mission cleanup; or by command SCRIPT_NAME (03A4) with parameter "copcar", "ambulan", "firetruck" or "stunt". It being set to 0 + save having a mission script causes these two fields to be added.

 

uMobile1 is a value of a variable "missionReplaySetting". It is set to:

- 0 by CHECKPOINT_SAVE_ODDJOB (0A77) [same exception applies as above],

- 0 by LOAD_AND_LAUNCH_MISSION_INTERNAL (0417)

- 1 by CHECKPOINT_SAVE (0A6F) [unless first parameter is 99],

- 1 by SCRIPT_NAME (03A4) if current script is mission script, not a streamed script, currently on OM1 and IsOddJob == 0.

 

'missionName' is actually a name of mission text (LOAD_MISSION_TEXT, 054C), not the script itself (e.g. mission name of Management Issues is 'MUSIC3' and of mission text 'STRAP3').

 

As you correctly determined, game intentionally sets a bit in an index to mark script as a mission script (game checks by logical and with 0x8000 but checking sign does the same).

Edited by Nick007J
Link to comment
Share on other sites

Ah, and there's that other structure we renamed in the topic but it never propagated to the script.

 

Search and Replace:

uMobile1 with IsOddJob

missionName with missionText

local missionThread with isMissionThread

 

What is the proper form of the logical and with 0x8000? I haven't performed that operation yet.

        if (isMissionThread == 1) {            char missionText[8];            int isOddJob;        }

The isMissionThread evaluation occurs at a lower level of the template so I can't query the index directly. I prefer to limit my locals if I can. As it turned out, I don't need to track isSlot10 (large mobile save). isMissionThread should be true if any of the threads were mission threads.

 

I'll review the logic in your description but the primary question is, Is if (isMissionThread == 1) a complete evaluation? Are the Mission Code + Local Array and Mission Text + OddJob structures always paired or can I get some parts without the others?

Edited by OrionSR
Link to comment
Share on other sites

You probably misunderstood me (or I misunderstood the code). Following mission text there is "missionReplaySetting". "IsOddJob" is a variable (4 bytes) that preceeds this block. So, if I understand it right, it should be

 

 

int IsOddJob;if (isMissionThread == 1 && IsOddJob == 0){  char missionText[8];  int missionReplaySetting;}
Edited by Nick007J
Link to comment
Share on other sites

Ah. I think I found it.

    if (isMobile == 1)  int mobileStuff1;    //mobile    tThread             threads[nRunningThreads] <optimize=false>;

So mobileStuff1 with isOddJob and missionReplaySettings fixed. How to test it?

 

And then I'm into the resource manager that never got updated in my template. I've got a lot of cleanup work to do but overall structure is the priority.

 

Thanks again for the support. I doubt I would have found the odd job stuff by experimentation.

Edited by OrionSR
Link to comment
Share on other sites

Hm, I would expect this variable to be right after resource manager and certainly after scripts. The variable before threads array is called SaveGameStateType.

 

Possible values are:

0 - done by CHECKPOINT_SAVE (0A6F)

1 - done by AUTO_SAVE (0A72)

2 - done by TERMINATE_THIS_SCRIPT (004E)

3 - done by OS_ApplicationEvent (possible when 'close app' event is triggered?)

4 - done by CHECKPOINT_SAVE_ODDJOB (0A77) and function CPad::CheckPointSave() [hard to say what latter one is, but it seems to be triggered when player is in a vehicle, and there are checks for model ids 537, 538 and 570)

5 - done by SCRIPT_NAME (03A4)

Edited by Nick007J
Link to comment
Share on other sites

Okay, I was hoping to clean up the resource manager struct first but for now, here's a wider view on the structure.

    int                 nRunningThreads;    if (isMobile == 1)  int SaveGameStateType;    //mobile    tThread             threads[nRunningThreads] <optimize=false>;    if (isMobile == 1) {        WORD                MobileCount;    // nRecords        WORD                MobileA;        // minIndex        WORD                MobileB;        // maxIndex <= unexplained data        struct tMobileStruct            (snipped resource manager)        if (isMissionThread == 1) {//        if (isMissionThread == 1 && isOddJob == 0) {            char missionText[8];            int missionReplaySetting;        }    }} Script; // end of block

It looks like the missionText string is often full of garbage data. MobileB looks like the most likely candidate. MobileA was usually consistent with the next available record index.

 

It looks like I was never able to align your predictions for the resource manager structure with what I saw in the saves.

Edited by OrionSR
Link to comment
Share on other sites

Based on function CTheScripts::Save() in mobile version, this is what I would expect from a mobile save in this block.

 

 

int sizeOfVars;char scriptSpace[*]; //* this block seems to be in chunks of 51200 bytes in PC version, and in chunks of 65000 bytes in mobile version, e.g. formally if sizeOfVars is 63000, the size should be 102400 on PC, and 65000 in mobiletScriptForBrains scriptsForBrains[70]; (sizeof(tScriptForBrains) == 20)int CTheScripts::OnAMissionFlag;int CTheScripts::LastMissionPassedTime;t2 CTheScripts::BuildingSwapArray[25] (t2: int type (2 or 0), int handle, int newModel, int oldModel)t3 CTheScripts::InvisibilitySettingArray[20]; (t3: int type, int handle)int CTheScripts::VehicleModelsBlockedByScript[20];t4 CTheScripts::ScriptConnectLodsObjects[10] (t4: int objectId, int lodId)t5 CTheScripts::ScriptAttachedAnimGroups[8] (t5: int model, char name[16])char CTheScripts::bUsingAMultiScriptFile;char CTheScripts::bPlayerHasMetDebbieHarry;int CTheScripts::MainScriptSize;int CTheScripts::LargestMissionScriptSize;short CTheScripts::NumberOfMissionScripts;short CTheScripts::NumberOfExclusiveMissionScripts;int CTheScripts::LargestNumberOfMissionScriptLocalVariables;int SaveGameStateType; //mobile only!int totalActiveScripts;CRunningScript scripts[totalActiveScripts];-- PC save block ends here --short resourcesCount;tResourceManagerEntry resources[resourcesCount];int IsOddJob;if (IsOddJob != 1 && isMissionThread == 1){  char missionText[8];  int missionReplaySetting;}struct tResourceManagerEntry{  WORD index; //index in manager array  WORD scriptIndex; //index of a script  int resourceID;  WORD type;  if (type == 2 && resourceID >= 290 && resourceID <= 299){    int length;    char modelName[length]  }}
Of course, I may be wrong. Edited by Nick007J
Link to comment
Share on other sites

I wonder if I can replace a missionThread with something of my own, and execute custom cleo-like missions on iOS and Remastered versions.

 

Thanks again. I've got a busy work weekend so progress may slow for a bit. But I'll review what I've got and try to get things updated for another round.

 

In case you missed my added comment, please review my reply to your comments on the resource manager.

Link to comment
Share on other sites

Do you mean different scructure than what I posted now? I may be checking too old (too new) version, maybe it was changed at some point? Because what I see is that game clearly writes length of a string, followed by string itself, and in that particular order. I will try to find different android versions to check.

 

Edit: Checked 1.01 and 1.08, in both special model block is saved as 4 bytes of length of string + the string itself. Weird.

 

Edit 2: I modified your template into following structure (sorry for bad names, just wanted to try):

 

 

    if (isMobile == 1) {        WORD                MobileCount;    // nRecords        struct tMobileStruct        {            struct tModel            {                WORD                MobileA;        // minIndex                WORD                MobileB;        // maxIndex                int                Mobile;           // modelID [290 to 299                WORD               Mobile1;          // type?                if (Mobile >= 290 && 299 >= Mobile) {                    int t;                    char mobileString[t]; //modelName                }            } Model[MobileCount] <optimize=false>;        } MobileStruct;    }    int oddjob;
and I think successfully opened a savefile you provided earlier. Edited by Nick007J
Link to comment
Share on other sites

I am unaware of any changes to the save structure since v1.06. Anything before that is so cluttered with garbage bytes that revising the template to compensate is a hopeless proposition.

 

It seems that we are out of sync with expectations and observations. I'm not even sure what structures were taking about now.

 

On some occasions I find it useful to seed unique data into the save and observe where it ends up in memory. Or the other way around.

 

Full Script Struct.

// Block 1: Scriptstruct tBlock01{    tblockHeader header;        int                 varSpaceSize;    int                 globalVar[varSpaceSize/4];    tExternalScriptTrigger trigger[70];    int                 onMissionFlagOffset;    int                 lastMissionTime;    struct tStaticReplacement    {        DWORD       type; /*always 2*/        int         handle;        int         newModelID, oldModelID;    } staticReplacement[25];       struct tInvisibleObject    {        int   type, handle;    } invisibleObject[20];    int                 disabledCarparkingModels[20];    struct tLodAssignment    {        int   objHandle, lodHandle;    } LodAssignment[10];    struct tScriptAssignment    {        int     actorModelID;        char    scriptName[8];        DWORD   unknown[2];        } ScriptAssignment[8];    byte                unknown1, unknown2;    int                 scmMainSize;    int                 largestMissionSize;    int                 missionsNumber;    int                 highestLocalVariable;    int                 nRunningThreads;    if (isMobile == 1)  int SaveGameStateType;    //mobile    tThread             threads[nRunningThreads] <optimize=false>;    if (isMobile == 1) {        WORD                MobileCount;    // nRecords        WORD                MobileA;        // minIndex        WORD                MobileB;        //         struct tMobileStruct        {            struct tModel            {                int                modelID;           // modelID                WORD               Mobile1;          // type?                WORD               Mobile2;          // index? [string length]                WORD               Mobile3;          // maxIndex?                if (modelID >= 290 && 299 >= modelID) {                    char modelName[Mobile2];                    int MobileInt <format=hex>;              //handle?                }            } Model[MobileCount] <optimize=false>;        } MobileStruct;        if (isMissionThread == 1) {//        if (isMissionThread == 1 && isOddJob == 0) {            char missionText[8];            int missionReplaySetting;        }    }} Script;
Edited by OrionSR
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.