Main.scm is a binary file containing either all or most of the game scripts in GTA III, VC and SA. Tools to open such as a file are most notably, Sanny Builder, Point, and Mission Builder.
Each instruction is represented by a number – opcode (operation code), which is UINT16. By this number the game engine identifies an action to perform. Say, opcode 0001 tells to wait for amount of time, 0003 shakes the camera, 0053 creates a player, etc.
This is how an opcode 0001 looks in a scm file:
* First part is the opcode number in a little-endian format.
* Second part is the data type
* Third part is a parameter value
When a mission script is disassembled, opcodes are written in a creature-readable format. The example above ^ will look something like this:
This is made for the end-user convenience only. The game does not know what the word wait means, but it knows what the opcode 0001 is, so when a mission script is assembled the commands are written back in raw byte form.
As it has been said, an opcode is UINT16 number. It means the minimum opcode is 0000 and maximum opcode is 0xFFFF.
As has been said, very little of the code was supplied with the game in a decompiled state (only two small files, both test scripts), so how, as asked, do we create our own scripts based on the original? With a decompiler - but how do these work (no decompilers have been provided by Rockstar).
The original SCM format was cracked shortly after the release of GTA 3 (the first game to use this mission coding method), with people having to first figure out what all the sections did (there are 5 segments is an SCM - memory, objects, mission defines, MAIN and missions (GTA SA has more, but only one of these (global variables) has had its use determined), where they started/ended etc, figuring out how many parameters each opcode had and a lot more. Once this was done, they knew where each opcode began and ended, so they could split them up to make it more readable, but the data on what each one does was lost in the compiling, so they still only had something that looked like this:
These scripts are in Sanny Builder format:
Press NO key to spawn an Infernus.
Sanny Builder
CLEO 3
GTAModding Wiki
In GTA4 the main.scm file has been replaced with .sco file, see this topics for tools for modifying the games data files:
SCO File
Spark IV
Open GTA IV
Editing with Sanny Builder
Opcodes
Each instruction is represented by a number – opcode (operation code), which is UINT16. By this number the game engine identifies an action to perform. Say, opcode 0001 tells to wait for amount of time, 0003 shakes the camera, 0053 creates a player, etc.
This is how an opcode 0001 looks in a scm file:
- Code:
0100 04 00
* First part is the opcode number in a little-endian format.
* Second part is the data type
* Third part is a parameter value
When a mission script is disassembled, opcodes are written in a creature-readable format. The example above ^ will look something like this:
- Code:
0001: wait 0 ms
This is made for the end-user convenience only. The game does not know what the word wait means, but it knows what the opcode 0001 is, so when a mission script is assembled the commands are written back in raw byte form.
As it has been said, an opcode is UINT16 number. It means the minimum opcode is 0000 and maximum opcode is 0xFFFF.
Cracking the SCM
As has been said, very little of the code was supplied with the game in a decompiled state (only two small files, both test scripts), so how, as asked, do we create our own scripts based on the original? With a decompiler - but how do these work (no decompilers have been provided by Rockstar).
The original SCM format was cracked shortly after the release of GTA 3 (the first game to use this mission coding method), with people having to first figure out what all the sections did (there are 5 segments is an SCM - memory, objects, mission defines, MAIN and missions (GTA SA has more, but only one of these (global variables) has had its use determined), where they started/ended etc, figuring out how many parameters each opcode had and a lot more. Once this was done, they knew where each opcode began and ended, so they could split them up to make it more readable, but the data on what each one does was lost in the compiling, so they still only had something that looked like this:
- Code:
:label035F78
0001: 0?
00D6: 0?
0256: 4??
SCM structure
- Code:
(02 00 01)h + 32 bit int Jump to second segment
byte Padding
(Global vars) Space for variable saving
(02 00 01)h + 32 bit int Jump to third segment
byte Segment id
32 bit int Number of models
(model names) 24 byte model names * number of models(model 0 not used)
(02 00 01)h + 32 bit int Jump to fourth segment
byte Segment id
32 bit int MAIN size
32 bit int Largest mission size
32 bit int Number of missions
32 bit int Highest number of locals used in mission/exernal
(mission addresses) 32 bit addresses * number of missions
(02 00 01)h + 32 bit int Jump to fifth segment
byte Segment id
32 bit int Largest external size
32 bit int Number of externals
(external data): 28 byte external data * number of externals
20 bytes Name of external
32 bit int Offset of external
32 bit int Size of external
(02 00 01)h + 32 bit int Jump to sixth segment
byte Segment id
32 bit int (Unused)
(02 00 01)h + 32 bit int Jump to seventh segment
byte Segment id
32 bit int Size of global var space
32 bit int (Unused)
(MAIN code) MAIN section, equal to size defined earlier
(mission code) The mission data, missions stored at offsets defined earlier
Sanny Builder format
- Code:
$ - global variable
s$ - global string variable
v$ - global long string variable
@ - label (text directly AFTER used to reference this label in jumps)
@ - local variable (number BEFORE denotes variable)
@s - local string variable (number BEFORE denotes variable)
@v - local long string variable (number BEFORE denotes variable)
'...' - string (first 8 bytes after opcode when compiled)
"..." - debug string text
# - model identifier (means you can enter the id name of a model rather than the number)
Mission Builder format
- Code:
? - small int (data type 04)
& - medium int (data type 05)
&& - big int (data type 01)
££ - global jump (data type 01)
£ - mission jump (data type 01 - negative addressing)
! - integer (data type 06)
$ - global variable (data type 02)
@ - local variable (data type 03)
?? - DMA global variable (like a global variable, only its memory position is its name, not assigned to it - data type 02)
: - label (text directly after used to reference this label in jumps)
"" - string (no data type, first 8 bytes after opcode when compiled)
# - model identifier (means you can enter the id name of a model rather than the number - data type 05 for the compiled number)
Examples
These scripts are in Sanny Builder format:
Press NO key to spawn an Infernus.
- Code:
{$CLEO}
0000:
:1Example
0001: wait 250 ms
00D6: if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @1Example
00D6: if
00E1: player 0 pressed_key 10
004D: jump_if_false @1Example
0247: load_model #infernus
:2Example
00d6: if
8248: not model #infernus available
004d: jump_if_false @3Example
0001: wait 0 ms
0002: jump @2Example
:3Example
04C4: store_coords_to 0@ 1@ 2@ from_actor $player_actor with_offset 0.0 8.0 0.0
0395: clear_area 1 at 0@ 1@ 2@ radius 5.0
00A5: 3@ = create_car #infernus at 0@ 1@ 2@
0249: release_model #infernus
01C3: remove_references_to_car 3@ // Like turning a car into any random car
0001: wait 1200
0002: jump @1Example
Links
Sanny Builder
CLEO 3
GTAModding Wiki
GTA4
In GTA4 the main.scm file has been replaced with .sco file, see this topics for tools for modifying the games data files:
SCO File
Spark IV
Open GTA IV