Difference between revisions of "SCM Instruction"

From GTAMods Wiki
Jump to navigation Jump to search
Line 1: Line 1:
 
{{This|This article deals with the technical information on the opcode format. For the opcodes documentation see [[list of opcodes]]}}
 
{{This|This article deals with the technical information on the opcode format. For the opcodes documentation see [[list of opcodes]]}}
Each script instruction is represented by a number called '''opcode''' or [[Wikipedia:Opcode|operation code]] which is implemented using an [[Wikipedia:UINT16|16 bit unsigned integer]]. 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.  
+
Each script instruction is represented by a number called '''opcode''' or [[Wikipedia:Opcode|operation code]] which is implemented using an [[Wikipedia:UINT16|16 bit unsigned integer]]. By this number the game engine identifies an action to perform. Say, an opcode [[0001]] tells to wait for amount of time, [[0003]] shakes the camera, [[0053]] creates a player, etc.  
  
 
__TOC__
 
__TOC__
  
This is how a script instruction <code>wait</code> looks like in a SCM file:
+
== Format ==
 +
 
 +
Initially the instructions are written in a human-readable form. For example, a ''wait'' instruction could look like this:
 +
wait 0
 +
where the word ''wait'' is a compiler-dependent representation of the opcode 0001 and the number <code>0</code> is a single parameter for this particular instruction. When a mission script is assembled, the instructions are written back in raw byte form:
 +
 
 
  {{hint|0100|opcode}}&nbsp;{{hint|04|Data type}}&nbsp;{{hint|00|Parameter value}}
 
  {{hint|0100|opcode}}&nbsp;{{hint|04|Data type}}&nbsp;{{hint|00|Parameter value}}
  
Line 10: Line 15:
 
* Second part is the [[#Data types|data type]]
 
* Second part is the [[#Data types|data type]]
 
* Third part is the parameter value
 
* Third part is the parameter value
 
When a mission script is disassembled, instructions are written in a human-readable format. The example above will look something like this:
 
wait 0
 
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 does, so when a mission script is assembled, the instructions 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. However due to a specific of the [[SCM language]], any numbers above 0x7FFF denote negative [[Conditional statement|conditional opcodes]]. The original unmodded game supports a way smaller amount of opcodes (maximum [[0A4E]] for [[San Andreas]]), but there are tools adding new ones, most notably [[CLEO|CLEO Library]].
 
As it has been said, an opcode is UINT16 number. It means the minimum opcode is [[0000]] and maximum opcode is 0xFFFF. However due to a specific of the [[SCM language]], any numbers above 0x7FFF denote negative [[Conditional statement|conditional opcodes]]. The original unmodded game supports a way smaller amount of opcodes (maximum [[0A4E]] for [[San Andreas]]), but there are tools adding new ones, most notably [[CLEO|CLEO Library]].
Line 19: Line 20:
 
There could be zero or more instruction parameters following the opcode number{{Ref|05B6|[*]}}.
 
There could be zero or more instruction parameters following the opcode number{{Ref|05B6|[*]}}.
  
== Data types ==
+
=== Parameters ===
A parameter's [[data type]] is determined with a single byte written before it{{ref|vcstr|[*]}}. The purpose of it is to tell to the game how much bytes to read next and what kind of data it is.  
+
The game engine knows amount of parameters for each instruction (1 for [[0001]], 2 for [[0004]], 13 for [[014B]], etc). If the script contains other number of parameters it causes a crash.
 +
 
 +
The value of a parameter could be one of following types:
 +
* Immediate values
 +
** integer numbers
 +
** floating-point numbers
 +
** [[#Strings|fixed-length strings]]
 +
** {{icon|sa}} [[#Strings|variable-length strings]]
 +
* Variables
 +
** global variables
 +
** local variables
 +
* {{icon|sa}} {{icon|lcs}} {{icon|vcs}} [[#Arrays|arrays]]
 +
 
 +
A concrete type of the value is determined by a single byte written before it{{ref|vcstr|[*]}}. This byte is called a data type. The purpose of it is to tell to the game how much bytes to read and how to treat it.
 +
 
 +
==== Data types ====
 +
A '''[[wikipedia:Data type|data type]]''' is a classification of identifying the type of a value. Types commonly used in GTA include integer numbers, floating-point numbers, and strings. The amount of data allowed to be stored is limited by the type and size of the data. For integers there are two ways to represent the data, signed and unsigned, whereas floating-point values are always signed. A signed data range includes negative numbers while unsigned do not include negatives. The following list shows the types and sizes of data in bytes.
  
 
{|class="mw-collapsible mw-collapsed wikitable"
 
{|class="mw-collapsible mw-collapsed wikitable"
Line 142: Line 159:
 
|}
 
|}
  
As it might be seen from the table two bytes <code>{{hint|02 00|Little-endian order}}</code> could have 3 different meanings as a parameter: if it's preceeded by a data type of 02 it is a global variable (<span style="color:blue">$2</span>), data type of 03 - local variable (<span style="color:blue">2@</span>), data type of 05 - 16-bit number (<span style="color:maroon">2</span>), so only the data type allows the game to determine the correct parameter meaning.
+
Depending of the preceeding data type, the parameter value compiled in two bytes <code>{{hint|02 00|Little-endian order}}</code>, could be treated either as the global variable <code style="color:blue">$2</code>, or a local variable <code style="color:blue">2@</code> or a number of <code style="color:maroon">2</code>. The data type allows the game to determine the correct parameter meaning.
  
 
Data types for [[Liberty City Stories]] and [[Vice City Stories]] are much different. First of all, many data types itself denote an immediate value. For example, data type 01 is a value of 0, data type 02 the value 0.0, etc. Floating-point values are packed (1, 2 or 3 bytes of length instead of the [[Wikipedia:IEEE_754-1985#Single-precision_32-bit|common 4]]). Some data types itself are somewhat the identifier of a variable.
 
Data types for [[Liberty City Stories]] and [[Vice City Stories]] are much different. First of all, many data types itself denote an immediate value. For example, data type 01 is a value of 0, data type 02 the value 0.0, etc. Floating-point values are packed (1, 2 or 3 bytes of length instead of the [[Wikipedia:IEEE_754-1985#Single-precision_32-bit|common 4]]). Some data types itself are somewhat the identifier of a variable.
Line 251: Line 268:
 
{{Incomplete}}
 
{{Incomplete}}
  
== Parameters ==
+
==== Integer numbers ====
The game engine knows amount of parameters for each instruction (1 for [[0001]], 2 for [[0004]], 13 for [[014B]], etc). If the script contains other number of parameters it causes a crash.  
+
 
 +
An '''[[wikipedia:Integer (computer science)|integer]]''' is a number without a decimal or fractional component.
 +
 
 +
{| class="wikitable"
 +
!rowspan="2"| Size<br>({{hint|bytes|Each byte is 4 bits}}) ||colspan="6"| Range
 +
|-
 +
! || Signed || Name || || Unsigned || Name
 +
|-
 +
| 1 || || -128 to 127 || INT8, [[wikipedia:Character_(computing)|CHAR]] || || 0 to 255 || UINT8, BYTE
 +
|-
 +
| 2 || || -32,768 to 32,767 || INT16, SHORT || || 0 to 65,535 || UINT16, [[wikipedia:Word (computer architecture)|WORD]], USHORT
 +
|-
 +
| 4 || || -2,147,483,648 to 2,147,483,647 || INT32, LONG || || 0 to 4,294,967,295 || UINT32, DWORD, ULONG
 +
|}
 +
 
 +
==== Floating-point numbers ====
 +
A '''[[wikipedia:Floating point|floating point]]''' is a number with a decimal component and can store extremely large or small numbers while sacrificing significant digits. This is achieved by internally using exponents in scientific notation.
  
The parameters could be one of following kinds:
+
{| class="wikitable"
* Immediate values
+
! Size<br>({{hint|bytes|Each byte is 4 bits}}) || Range || Name
** integer numbers
+
|-
** floating-point numbers
+
| || [[wikipedia:Single precision floating-point format|SINGLE]], FLOAT
** [[#Strings|short strings]]
+
|}
** {{icon|sa}} [[#Strings|long strings]]
 
* Variables
 
** global variables
 
** local variables
 
* {{icon|sa}} {{icon|lcs}} {{icon|vcs}} [[#Arrays|arrays]]
 
{{Incomplete}}
 
  
=== Strings ===
+
==== Strings ====
''Strings'' are sequences of characters. Those include {{hint|letters|A..Z}}, {{hint|numbers|0..9}}, and other symbols like _ or @. Unlike other programming languages a string could start with any character, even a space.
+
A ''string'' is a sequence of characters not treated as numbers. Those include {{hint|letters|A..Z}}, {{hint|numbers|0..9}}, and other symbols like _ or @. Unlike other programming languages a string could start with any character, even a space.
  
 
There are two kinds of strings.
 
There are two kinds of strings.
  
{{note|str8}} '''Short string''' or a null-terminated string. This is the most common type been used since [[GTA 3]]. The term ''short'' means that the string length is strongly limited. It may contain up to 7 characters and the last one (8th) is a [[Wikipedia:null terminator|null terminator]] byte. When compiled these strings occupy 8 bytes of a [[SCM]] file even if they are actually shorter (the rest of bytes is filled with zero bytes).
+
{{note|str8}} A '''fixed-length string''' or a null-terminated string. This is the most common type been used since [[GTA 3]]. The string length is fixed. When compiled these strings occupy 8 bytes of a [[SCM]] file even if they are actually shorter (the rest is filled with [[Wikipedia:null terminator|zero bytes]]).
  
 
{{note|sa16}} San Andreas introduces data type 15 for strings containing up to 15 symbols. They behave same as 8 bytes strings, but always occupy 16 bytes in a SCM file. These strings are only supported by [[Sanny Builder]].
 
{{note|sa16}} San Andreas introduces data type 15 for strings containing up to 15 symbols. They behave same as 8 bytes strings, but always occupy 16 bytes in a SCM file. These strings are only supported by [[Sanny Builder]].
Line 284: Line 311:
 
| <span style="color:red">'SAVE_OUR_SOULS!'</span>||{{hint|0F|Data type}}&nbsp;&nbsp;&nbsp;{{hint|53 41 56 45 5F 4F 55 52 5F 53 4F 55 4C 53 21 00|ASCII code of string characters}}
 
| <span style="color:red">'SAVE_OUR_SOULS!'</span>||{{hint|0F|Data type}}&nbsp;&nbsp;&nbsp;{{hint|53 41 56 45 5F 4F 55 52 5F 53 4F 55 4C 53 21 00|ASCII code of string characters}}
 
|}
 
|}
{{note|str16}} '''Long string'''. This type was first introduced in San Andreas. Maximum length depends on the instruction{{Ref|longstringslimits|[*]}} (the longest parameter ever read has got 40 characters).
+
{{note|str16}} A '''variable-length string'''. This type was first introduced in San Andreas. Maximum length depends on the instruction{{Ref|longstringslimits|[*]}} (the longest parameter ever read has got 40 characters).
  
 
{{Incomplete}}
 
{{Incomplete}}
  
=== Arrays ===
+
==== Arrays ====
 
{{note|varray}} Native ''[[Wikipedia:Array|arrays]]'' support was introduced in GTA SA, however there were different implementations of [[VC_Arrays|arrays in Vice City]]. In SA SCM arrays are assembled as 2 ''UINT16''s, 1 ''INT8'' and a ''UINT8'':
 
{{note|varray}} Native ''[[Wikipedia:Array|arrays]]'' support was introduced in GTA SA, however there were different implementations of [[VC_Arrays|arrays in Vice City]]. In SA SCM arrays are assembled as 2 ''UINT16''s, 1 ''INT8'' and a ''UINT8'':
 
  2b - UINT16 - array offset{{ref|arrayoffset|[*]}}
 
  2b - UINT16 - array offset{{ref|arrayoffset|[*]}}
Line 299: Line 326:
 
{{note|arrayindex}} An array index is a variable number (global or local one) that holds the value of array index. For example, if array index is 3 (<code>{{hint|03 00|Little-endian order}}</code>), the game will read either global variable <span style="color:blue">$3</span> or local variable <span style="color:blue">3@</span> depending on the array properties (see below). This variable holds the number which is array element ID to work with. For example, if the array index is <span style="color:blue">$3</span>, and <span style="color:blue">$3</span> holds number <span style="color:maroon">5</span>, the game will read 5th element of the array.
 
{{note|arrayindex}} An array index is a variable number (global or local one) that holds the value of array index. For example, if array index is 3 (<code>{{hint|03 00|Little-endian order}}</code>), the game will read either global variable <span style="color:blue">$3</span> or local variable <span style="color:blue">3@</span> depending on the array properties (see below). This variable holds the number which is array element ID to work with. For example, if the array index is <span style="color:blue">$3</span>, and <span style="color:blue">$3</span> holds number <span style="color:maroon">5</span>, the game will read 5th element of the array.
  
==== Properties ====
+
===== Properties =====
 
Array properties describe the data type of each array element, held by the first 7 bits of the reference field, plus a flag which signals if the array was declared in a global scope, as the most significant bit indicates:
 
Array properties describe the data type of each array element, held by the first 7 bits of the reference field, plus a flag which signals if the array was declared in a global scope, as the most significant bit indicates:
  

Revision as of 10:41, 10 September 2016

This article deals with the technical information on the opcode format. For the opcodes documentation see list of opcodes

Each script instruction is represented by a number called opcode or operation code which is implemented using an 16 bit unsigned integer. By this number the game engine identifies an action to perform. Say, an opcode 0001 tells to wait for amount of time, 0003 shakes the camera, 0053 creates a player, etc.

Format

Initially the instructions are written in a human-readable form. For example, a wait instruction could look like this:

wait 0

where the word wait is a compiler-dependent representation of the opcode 0001 and the number 0 is a single parameter for this particular instruction. When a mission script is assembled, the instructions are written back in raw byte form:

0100 04 00
  • First part is the opcode number in a little-endian format.
  • Second part is the data type
  • Third part is the parameter value

As it has been said, an opcode is UINT16 number. It means the minimum opcode is 0000 and maximum opcode is 0xFFFF. However due to a specific of the SCM language, any numbers above 0x7FFF denote negative conditional opcodes. The original unmodded game supports a way smaller amount of opcodes (maximum 0A4E for San Andreas), but there are tools adding new ones, most notably CLEO Library.

There could be zero or more instruction parameters following the opcode number[*].

Parameters

The game engine knows amount of parameters for each instruction (1 for 0001, 2 for 0004, 13 for 014B, etc). If the script contains other number of parameters it causes a crash.

The value of a parameter could be one of following types:

A concrete type of the value is determined by a single byte written before it[*]. This byte is called a data type. The purpose of it is to tell to the game how much bytes to read and how to treat it.

Data types

A data type is a classification of identifying the type of a value. Types commonly used in GTA include integer numbers, floating-point numbers, and strings. The amount of data allowed to be stored is limited by the type and size of the data. For integers there are two ways to represent the data, signed and unsigned, whereas floating-point values are always signed. A signed data range includes negative numbers while unsigned do not include negatives. The following list shows the types and sizes of data in bytes.

Data type
(hex)
Arg.
length
Target
game
Description 
Typified
00 0 GTA III Vice City San Andreas End of argument list (EOAL, 004F or 0913 and similar)[*]
01 4 GTA III Vice City San Andreas Immediate 32-bit signed int
scriptParam.m_iIntValue = *(int *)m_pScriptPC;
m_pScriptPC += 4;
02 2 GTA III Vice City San Andreas Global integer/floating-point variable
scriptParam.m_usGlobalOffset = *(unsigned short *)m_pScriptPC;
m_pScriptPC += 2;
03 2 GTA III Vice City San Andreas Local integer/floating-point variable
scriptParam.m_sLocalVar = *(short *)m_pScriptPC;
m_pScriptPC += 2;
04 1 GTA III Vice City San Andreas Immediate 8-bit signed int
scriptParam.m_iIntValue = *(char *)m_pScriptPC++;
05 2 GTA III Vice City San Andreas Immediate 16-bit signed int
scriptParam.m_iIntValue = *(short *)m_pScriptPC;
m_pScriptPC += 2;
06 2 GTA III Immediate 16-bit fixed-point (see remark)
scriptParam.m_fFloatValue = (float)(*(short *)m_pScriptPC) / 16.0f;
m_pScriptPC += 2;
06 4 Vice City San Andreas Immediate 32-bit floating-point
scriptParam.m_fFloatValue = *(float *)m_pScriptPC;
m_pScriptPC += 4;
07 6 San Andreas Global integer/floating-point array[*]
scriptParam.m_usGlobalOffset = *(unsigned short *)m_pScriptPC;
scriptParam.m_sArrayIndexVar = *(short *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 4);
scriptParam.m_arrayProperties = *(ArrayProperties *)(m_pScriptPC + 5);
m_pScriptPC += 6;
08 6 San Andreas Local integer/floating-point array[*]
scriptParam.m_sLocalVar = *(short *)m_pScriptPC;
scriptParam.m_sArrayIndexVar = *(short *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 4);
scriptParam.m_arrayProperties = *(ArrayProperties *)(m_pScriptPC + 5);
m_pScriptPC += 6;
09 8 San Andreas Immediate 8-byte string[*]
strcpy(scriptParam.m_szTextLabel, (char *)m_pScriptPC);
m_pScriptPC += 8;
0A 2 San Andreas Global 8-byte string variable
scriptParam.m_usGlobalOffset = *(unsigned short *)m_pScriptPC;
m_pScriptPC += 2;
0B 2 San Andreas Local 8-byte string variable
scriptParam.m_sLocalVar = *(short *)m_pScriptPC;
m_pScriptPC += 2;
0C 6 San Andreas Global 8-byte string array[*]
scriptParam.m_usGlobalOffset = *(unsigned short *)m_pScriptPC;
scriptParam.m_sArrayIndexVar = *(short *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 4);
scriptParam.m_arrayProperties = *(ArrayProperties *)(m_pScriptPC + 5);
m_pScriptPC += 6;
0D 6 San Andreas Local 8-byte string array[*]
scriptParam.m_sLocalVar = *(short *)m_pScriptPC;
scriptParam.m_sArrayIndexVar = *(short *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 4);
scriptParam.m_arrayProperties = *(ArrayProperties *)(m_pScriptPC + 5);
m_pScriptPC += 6;
0E 1 + (n - 1) San Andreas Immediate variable-length string[*] (non null-terminated)
char cStrLength = *(char *)m_pScriptPC++;
strncpy(scriptParam.m_szTextLabel, (char *)m_pScriptPC, cStrLength);
memset(&scriptParam.m_szTextLabel[cStrLength], '\0', ucMaxLength - cStrLength);
m_pScriptPC += cStrLength;
0F 16 San Andreas Immediate 16-byte string[*]
strcpy(scriptParam.m_szTextLabel, (char *)m_pScriptPC);
m_pScriptPC += 16;
10 2 San Andreas Global 16-byte string variable
scriptParam.m_usGlobalOffset = *(unsigned short *)m_pScriptPC;
m_pScriptPC += 2;
11 2 San Andreas Local 16-byte string variable
scriptParam.m_sLocalVar = *(short *)m_pScriptPC;
m_pScriptPC += 2;
12 6 San Andreas Global 16-byte string array[*]
scriptParam.m_usGlobalOffset = *(unsigned short *)m_pScriptPC;
scriptParam.m_sArrayIndexVar = *(short *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 4);
scriptParam.m_arrayProperties = *(ArrayProperties *)(m_pScriptPC + 5);
m_pScriptPC += 6;
13 6 San Andreas Local 16-byte string array[*]
scriptParam.m_sLocalVar = *(short *)m_pScriptPC;
scriptParam.m_sArrayIndexVar = *(short *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 4);
scriptParam.m_arrayProperties = *(ArrayProperties *)(m_pScriptPC + 5);
m_pScriptPC += 6;
Untypified
N/A 8 GTA III Vice City Immediate 8-byte string[*]
strcpy(scriptParam.m_szTextLabel, (char *)m_pScriptPC);
m_pScriptPC += 8;
N/A 128 San Andreas Immediate 128-byte string
strcpy(scriptParam.m_szString, (char *)m_pScriptPC);
m_pScriptPC += 128;

Depending of the preceeding data type, the parameter value compiled in two bytes 02 00, could be treated either as the global variable $2, or a local variable 2@ or a number of 2. The data type allows the game to determine the correct parameter meaning.

Data types for Liberty City Stories and Vice City Stories are much different. First of all, many data types itself denote an immediate value. For example, data type 01 is a value of 0, data type 02 the value 0.0, etc. Floating-point values are packed (1, 2 or 3 bytes of length instead of the common 4). Some data types itself are somewhat the identifier of a variable.

Data type
(hex)
Arg.
length
Target
game
Description 
Typified
00 0 Liberty City Stories Vice City Stories End of argument list (EOAL)
01 0 Liberty City Stories Vice City Stories Immediate 8-bit signed integer constant 0
scriptParam.m_iIntValue = 0;
02 0 Liberty City Stories Vice City Stories Immediate 8-bit floating-point constant 0.0
scriptParam.m_fFloatValue = 0.0f;
03 1 Liberty City Stories Vice City Stories Immediate 8-bit packed floating-point
unsigned int uiUnpackedFloat = *(unsigned char *)m_pScriptPC++ << 24;
scriptParam.m_fFloatValue = *(float *)&uiUnpackedFloat;
04 2 Liberty City Stories Vice City Stories Immediate 16-bit packed floating-point
unsigned int uiUnpackedFloat = *(unsigned short *)m_pScriptPC << 16;
scriptParam.m_fFloatValue = *(float *)&uiUnpackedFloat;
m_pScriptPC += 2;
05 3 Liberty City Stories Vice City Stories Immediate 24-bit packed floating-point
unsigned int uiUnpackedFloat
    = (*(unsigned short *)m_pScriptPC << 16)
    | (*(unsigned char *)(m_pScriptPC + 2) << 8);
scriptParam.m_fFloatValue = *(float *)&uiUnpackedFloat;
m_pScriptPC += 3;
06 4 Liberty City Stories Vice City Stories Immediate 32-bit signed integer
scriptParam.m_iIntValue = *(int *)m_pScriptPC;
m_pScriptPC += 4;
07 1 Liberty City Stories Vice City Stories Immediate 8-bit signed integer
scriptParam.m_iIntValue = *(char *)m_pScriptPC++;
08 2 Liberty City Stories Vice City Stories Immediate 16-bit signed integer
scriptParam.m_iIntValue = *(short *)m_pScriptPC;
m_pScriptPC += 2;
09 4 Liberty City Stories Vice City Stories Immediate 32-bit floating-point
scriptParam.m_fFloatValue = *(float *)m_pScriptPC;
m_pScriptPC += 4;
0A n + NUL Vice City Stories Immediate null-terminated string[*]
strcpy(scriptParam.m_szTextLabel, (char *)m_pScriptPC);
m_pScriptPC += strlen((char *)m_pScriptPC) + 1;
Untypified (script variables)
T<0C 1 Liberty City Stories Local timers (TIMERA, TIMERB)
scriptParam.m_sLocalVar = *(unsigned char *)m_pScriptPC++ + 0x5E;
T<0D 1 Vice City Stories Local timers (TIMERA, TIMERB)
scriptParam.m_sLocalVar = *(unsigned char *)m_pScriptPC++ + 0x5D;
T<6C 1 Liberty City Stories Local integer/floating-point variable
scriptParam.m_sLocalVar = *(unsigned char *)m_pScriptPC++ - 0x0C;
T<6D 1 Vice City Stories Local integer/floating-point variable
scriptParam.m_sLocalVar = *(unsigned char *)m_pScriptPC++ - 0x0D;
T<CC 3 Liberty City Stories Local integer/floating-point array
scriptParam.m_sLocalVar = *(unsigned char *)m_pScriptPC - 0x6C;
scriptParam.m_sArrayIndex = *(unsigned char *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 3);
m_pScriptPC += 3;
T<CD 3 Vice City Stories Local integer/floating-point array
scriptParam.m_sLocalVar = *(unsigned char *)m_pScriptPC - 0x6D;
scriptParam.m_sArrayIndex = *(unsigned char *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 3);
m_pScriptPC += 3;
T<E6 2 Liberty City Stories Global integer/floating-point variable
unsigned short usBigEndianWord = *(unsigned short *)m_pScriptPC - 0x00CC;
scriptParam.m_sGlobalVar = (short)((usBigEndianWord << 8) | (usBigEndianWord >> 8));
m_pScriptPC += 2;
Vice City Stories Global integer/floating-point variable
unsigned short usBigEndianWord = *(unsigned short *)m_pScriptPC - 0x00CD;
scriptParam.m_sGlobalVar = (short)((usBigEndianWord << 8) | (usBigEndianWord >> 8));
m_pScriptPC += 2;
T>=E6 4 Liberty City Stories Vice City Stories Global integer/floating-point array
unsigned short usBigEndianWord = *(unsigned short *)m_pScriptPC - 0x00E6;
scriptParam.m_sGlobalVar = (short)((usBigEndianWord << 8) | (usBigEndianWord >> 8));
scriptParam.m_sArrayIndex = *(unsigned char *)(m_pScriptPC + 2);
scriptParam.m_ucArraySize = *(unsigned char *)(m_pScriptPC + 3);
m_pScriptPC += 4;
N/A 8 Liberty City Stories Immediate 8-byte string
strcpy(scriptParam.m_szTextLabel, (char *)m_pScriptPC);
m_pScriptPC += 8;

^ This type was introduced in VCS due to the presence of string variables.

All the data types above haven't been tested in a decompiling process yet, hence they still need a practical confirmation.

This section is incomplete. You can help by fixing and expanding it.

Integer numbers

An integer is a number without a decimal or fractional component.

Size
(bytes)
Range
Signed Name Unsigned Name
1 -128 to 127 INT8, CHAR 0 to 255 UINT8, BYTE
2 -32,768 to 32,767 INT16, SHORT 0 to 65,535 UINT16, WORD, USHORT
4 -2,147,483,648 to 2,147,483,647 INT32, LONG 0 to 4,294,967,295 UINT32, DWORD, ULONG

Floating-point numbers

A floating point is a number with a decimal component and can store extremely large or small numbers while sacrificing significant digits. This is achieved by internally using exponents in scientific notation.

-38<38 || SINGLE, FLOAT
Size
(bytes)
Range Name

Strings

A string is a sequence of characters not treated as numbers. Those include letters, numbers, and other symbols like _ or @. Unlike other programming languages a string could start with any character, even a space.

There are two kinds of strings.

^ A fixed-length string or a null-terminated string. This is the most common type been used since GTA 3. The string length is fixed. When compiled these strings occupy 8 bytes of a SCM file even if they are actually shorter (the rest is filled with zero bytes).

^ San Andreas introduces data type 15 for strings containing up to 15 symbols. They behave same as 8 bytes strings, but always occupy 16 bytes in a SCM file. These strings are only supported by Sanny Builder.

String Equivalent in SCM
'MAIN' 09   4D 41 49 4E 00 00 00 00
'MODDING' 09   4D 4F 44 44 49 4E 47 00
'SAVE_OUR_SOULS!' 0F   53 41 56 45 5F 4F 55 52 5F 53 4F 55 4C 53 21 00

^ A variable-length string. This type was first introduced in San Andreas. Maximum length depends on the instruction[*] (the longest parameter ever read has got 40 characters).

This section is incomplete. You can help by fixing and expanding it.

Arrays

^ Native arrays support was introduced in GTA SA, however there were different implementations of arrays in Vice City. In SA SCM arrays are assembled as 2 UINT16s, 1 INT8 and a UINT8:

2b - UINT16 - array offset[*]
2b - UINT16 - array index[*]
1b - INT8   - array size
1b - UINT8  - array properties

^ An array offset is basically a variable number. If it's a global array, the offset is a global variable index from which the array begins. For example, if the global array offset is 150 (96 00) it means that the first element of the array is $150, the second one is $151, etc. Same valid for the local arrays (offset is a local variable index).

^ An array index is a variable number (global or local one) that holds the value of array index. For example, if array index is 3 (03 00), the game will read either global variable $3 or local variable 3@ depending on the array properties (see below). This variable holds the number which is array element ID to work with. For example, if the array index is $3, and $3 holds number 5, the game will read 5th element of the array.

Properties

Array properties describe the data type of each array element, held by the first 7 bits of the reference field, plus a flag which signals if the array was declared in a global scope, as the most significant bit indicates:

enum eArrayElementType
{
	ELEMTYPE_INT,
	ELEMTYPE_FLOAT,
	ELEMTYPE_TEXT_LABEL,
	ELEMTYPE_TEXT_LABEL16
};

struct ArrayProperties
{
	unsigned char m_nElementType : 7;
	unsigned char m_bIsIndexGlobalVar : 1;
};
Array Equivalent in SCM
$150(3@,6f) 07   96 00 03 00 06 01
10@(9@,5s) 0D   0A 00 09 00 05 02

Notes

^ In GTA 3, Vice City and Liberty City Stories short strings (8 bytes) have no data type preceeding it. If the byte does not fit data type range (00-06 for GTA 3 and VC), it's recognized as a beginning of a string and next 8 bytes are read.

^ Some instructions have variable amount of parameters. The most known one is 004F that creates a new thread and passes arguments to it. The number of such parameters could vary, so the special data type denotes the end of parameters.

The maximum amount of parameters for any instruction is 16 for GTA 3 and VC, 32 for SA, LCS and VCS. However, those that admit an undefined amount of arguments can pass 18 parameters for GTA 3 and VC, 34 for SA, 106 for LCS and VCS (this information still needs confirmation).

^ San Andreas Opcode 05B6 is a special instruction that defines a table. Immediately after opcode number the stream of data (128 bytes) follows, without a data type.

^ Post.png GTAForums: Post by Seemann describing limits for the long strings in SA

See also