Adhoc Compiled/Header¶
Applies to GT4, GT5, GTPSP, GT6, GT Sport, GT7 · Extension: .adc
· Endian: Little
This is the main header for Adhoc Scripts. Most games will have a certain level of backwards compatibility, but it's better to keep them at the latest that the engine supports. This format has changed quite a bit over time.
Dissasembling¶
The GTAdhocToolchain can be used to dissasemble compiled .adc
scripts into an assembly-like text file. Compiled builds can be acquired from the Actions page, clicking on the latest build, and scrolling to the bottom for a build's executable.
Header¶
Field | Offset | Type | Description |
---|---|---|---|
ADCH |
0x00 |
Int |
Magic, (Enforced, cannot be different) |
Version | 0x04 |
char[3] |
Version, i.e 012 . |
Symbol Table | N/A | Symbol Table |
Symbol Table (V9 to V12) |
Top Level Frame | N/A | Code Frame |
The top-level code frame. |
Symbol Table¶
Note
Version 9 to 12 only.
Field | Type | Description |
---|---|---|
Symbol Count | VarInt |
Number of symbols in the script |
Symbols | Symbol[] |
Array of symbols. |
Code Frame¶
If version < 8
Field | Type | Description |
---|---|---|
Source Path | Symbol |
Source file name for this script. |
Subroutine Parameter Count | Int |
Number of parameters for this subroutine. |
Subroutine Parameters | Symbol[] |
Subroutine parameters. |
If version >= 8
Field | Type | Description |
---|---|---|
Source Path | Symbol |
Source file name for this script. |
Frame Version | byte |
Adhoc version of the frame. Should match with main header. |
Has Rest Element | bool |
Whether this frame has a rest element. function myFunc(arg, args...) |
Subroutine Parameter Count | Int |
Number of parameters for this subroutine. |
Subroutine Parameters | Symbol[] |
Subroutine parameters. |
Captured Callback Param Count | Int |
Number of parameters to be captured from the parent frame. |
Captured Callback Parameters | Symbol[] |
Parameters to be captured from the parent frame. |
Unknown | Int |
? |
Stack Setup¶
The stack holds the actual object stack, and a storage of the local variables for the current frame.
If version <= 10
Field | Type | Description |
---|---|---|
Variable Storage Size | Int |
Variable storage size. Unlike later versions, locals and statics are combined. |
Stack Size | Int |
Object Stack size. |
If version >= 12
Field | Type | Description |
---|---|---|
Stack Size | Int |
Object Stack size. |
Local Variable Storage Size | Int |
Storage size for local variables. |
Static Variable Storage Size | Int |
Storage size for static variables. |
Instruction Table¶
Field | Type | Description |
---|---|---|
Instruction Count | Int |
Number of instructions for this frame. |
Instructions | Inst[] |
Instructions. |
Instruction¶
Field | Type | Description |
---|---|---|
Source Line Number | UInt |
Line number for this instruction - originating from the location of the compiled expression. |
Opcode/Instruction Type | InstructionOpCode |
The type of instruction. |
Instruction Data | ... |
Instruction data. Refer to GTAdhocToolchain for how they are read. |
Opcode Table (click to expand)
Opcodes fits within a byte
.
Value | Name | Description |
---|---|---|
0 | ARRAY_CONST_OLD | Defines an array. |
1 | ASSIGN | Pops two object from the stack, assigns the last to the previous one, pushes it to the stack. |
2 | ATTRIBUTE_DEFINE | Defines a new attribute onto the current module. |
3 | ATTRIBUTE_PUSH | Pops the last object, pushes an object to it as an attribute. myObj.myAttr = 5 |
4 | BINARY_ASSIGN_OPERATOR | Pops two objects from the stack, assigns the previous through an operator, pushes the result to the stack. |
5 | BINARY_OPERATOR | Pops two objects from the stack, applies an operator operation, pushes the result to the stack. |
6 | CALL | Pops the number of provided arguments plus the previous variable as the function, calls it, pushes a result to the stack. |
7 | CLASS_DEFINE | Defines a new class onto the current module. |
8 | EVAL | Pops an object, evaluates it. Pushes the result to the stack. |
9 | FLOAT_CONST | Pushes a new float to the stack. var myFloat = 1.0 |
10 | FUNCTION_DEFINE | Defines a new function onto the current module. |
11 | IMPORT | Imports a (or all) members from the specified module path. import myModule::* , import myMember as member |
12 | INT_CONST | Pushes a new int to the stack. |
13 | JUMP | Sets the adhoc thread's instruction pointer to the specified instruction index. |
14 | JUMP_IF_TRUE | Pops an object, sets the adhoc thread's instruction pointer to the specified instruction index if the object evaluates to true. |
15 | JUMP_IF_FALSE | Pops an object, sets the adhoc thread's instruction pointer to the specified instruction index if the object evaluates to false. |
16 | LIST_ASSIGN_OLD | Pops an object, deconstructs it as an array. |
17 | LOCAL_DEFINE | ? |
18 | LOGICAL_AND_OLD | Pops an object, jumps to the specified instruction index if it evaluates to false. Pushes the result. |
19 | LOGICAL_OR_OLD | Pops an object, jumps to the specified instruction index if it evaluates to true. Pushes the result. |
20 | METHOD_DEFINE | Defines a new method onto the current module. |
21 | MODULE_DEFINE | Defines or enters a new module onto the current module. |
22 | NIL_CONST | Pushes a new nil object to the stack. var obj = nil |
23 | NOP | NOP. |
24 | POP_OLD | Pops an object from the stack. |
25 | Pops an object and prints its contents to TTY/Console. This is stubbed in retail builds. print "hello world" |
|
26 | REQUIRE | Pops an object, toString() 's it to a path and loads it a script file. Contents are loaded onto the current module. |
27 | SET_STATE_OLD | Sets the adhoc thread's state. 0 = EXIT (exits the scope), 1 = RETURN (exits subroutine). |
28 | STATIC_DEFINE | Defines a new static member onto the current module. |
29 | STRING_CONST | Pushes a new string object to the stack. var myString = "hello" |
30 | STRING_PUSH | Pops the specified amount of objects, combines them together as a string and pushes the result. var myString = "hello, %{name} !" |
31 | THROW | Throws an adhoc exception. Normally not used. throw "my error" |
32 | TRY_CATCH | Defines a new try-catch frame. Sets the adhoc thread's instruction pointer to the specified instruction index if an exception is caught. |
33 | UNARY_ASSIGN_OPERATOR | Pops an object from the stack, assigns the previous through an unary operator, pushes the result to the stack. |
34 | UNARY_OPERATOR | Pops an object from the stack, applies an unary operator, pushes the result to the stack. |
35 | UNDEF | Undefines the specified module member. undef myAttr |
36 | VARIABLE_PUSH | Pushes an object to the specified variable. Pushes it to the stack too. |
37 | ATTRIBUTE_EVAL | Pops an object, evaluates it as an attribute. Pushes it to the stack. |
38 | VARIABLE_EVAL | Pops an object, evaluates it as a variable. Pushes it to the stack. |
39 | SOURCE_FILE | Sets the adhoc thread's source file, for debugging. |
40 | FUNCTION_CONST | Pushes a new function object/callback onto the stack. |
41 | METHOD_CONST | Pushes a new method object/callback onto the stack. |
42 | MAP_CONST_OLD | Pushes a new map/key-value dictionary object onto the stack. |
43 | LONG_CONST | Pushes a new long/int64 onto the stack. |
44 | ASSIGN | Pops two object from the stack, assigns the last to the previous one. |
45 | LIST_ASSIGN | Pops an object, deconstructs it as an array. |
46 | CALL_OLD | ? (Never seen used) |
47 | OBJECT_SELECTOR | Pops two objects, Selects a member from an object, pushes the result. myObject.*myMember |
48 | SYMBOL_CONST | Pushes a new symbol const onto the stack. var mySymbol = 'my symbol' |
49 | LEAVE | Leaves the scope - wipes the local variable storage to the specified index, also sets the current module depth (Stubbed starting GT6). |
50 | ARRAY_CONST | Pushes a new array object onto the stack. |
51 | ARRAY_PUSH | Pops an object, pushes to the array. |
52 | MAP_CONST | Pushes a new map/key-value dictionary object onto the stack. |
53 | MAP_INSERT | Pops two object object, inserts to the map. |
54 | POP | Pops an object from the stack. |
55 | SET_STATE_OLD | Sets the adhoc thread's state. 0 = EXIT (exits the scope), 1 = RETURN (exits subroutine). |
56 | VOID_CONST | Pushes a new void object onto the stack (for function returns) |
57 | ASSIGN_POP | Pops 2 pointers off the stack, and copies the second item to the first item, and pops it. |
58 | U_INT_CONST | Pushes a new unsigned integer object onto the stack. var uint = 5u |
59 | U_LONG_CONST | Pushes a new unsigned long object onto the stack. var ulong = 5ul |
60 | DOUBLE_CONST | Pushes a new double object onto the stack. var double = 5d |
61 | ELEMENT_PUSH | Pops two objects (one array, one value), pushes the value to the array, pushes the result to the stack. myObj[0] = myValue |
62 | ELEMENT_EVAL | Pops two objects (one array, one value), evaluates the array with the value, pushes the result to the stack. var myValue = myObj[0] |
63 | LOGICAL_AND | Pops an object, jumps to the specified instruction index if it evaluates to false. Pushes the result. |
64 | LOGICAL_OR | Pops an object, jumps to the specified instruction index if it evaluates to true. Pushes the result. |
65 | BOOL_CONST | Pushes a new bool object onto the stack. var myBool = true |
66 | MODULE_CONSTRUCTOR | Defines a constructor for a module variable. module (myObj) { ... } |
67 | VA_CALL (>= GT6) | Variadic function call |
68 | CODE_EVAL (>= GT6) | ? |
70 | DELEGATE_DEFINE (>= GT Sport) | Pops an object, sets the adhoc thread's instruction pointer to the specified instruction index if the object is not nil. var myObject == doThing() ?? false |
71 | LOGICAL_OPTIONAL (>= GT Sport) | Pops an object, jumps to the specified instruction index if it evaluates to nil. Pushes the result (?). |
Symbols¶
String Encoding
String encoding is set to EUC-JP for version under 10. You can set it up in C# this way:
In version 8 and earlier, there is no string table, symbols are just prefixed by a short length.
In version 9 and later, symbols are indexed by an index into the symbol table. Indices are encoded with a variable integer.
Variable Ints¶
Here's a sample on how to read/write them:
public void WriteVarInt(int value)
{
if ((value & 0xFFFFFF80) == 0)
{
Write((byte)value);
return;
}
var bytesToWrite = 1;
uint mask = 0x80;
long retVal = 0;
do
{
retVal = (retVal + mask) << 8;
mask <<= 7;
bytesToWrite++;
} while ((value & -mask) > 0);
var finalValue = retVal | value;
for (var i = bytesToWrite; i > 0; i--)
Write((byte)(finalValue >> (i - 1) * 8));
}