This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
mission_impossible:sool_engine [2019/06/17 00:50] shygoo created (wip) |
mission_impossible:sool_engine [2019/07/01 18:25] (current) shygoo last minute notes on sool file structure |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== SOOL Engine ====== | ====== SOOL Engine ====== | ||
- | Scenaric Object Oriented Language | + | SOOL (Scenaric Object Oriented Language) is a proprietary scripting language and engine used by Mission Impossible. |
- | * [[https://hackmd.io/D7_UZ5kGSWCAZb_nM2-xHg?edit|Rough decompilation of the SOOL Engine]] | + | * [[https://hackmd.io/@shygoo/Byq2TYWkr|SOOL Interpreter partial decomp]] |
---- | ---- | ||
- | ===== Commands ===== | + | ===== SOOL File structure ===== |
+ | |||
+ | ==== File header ==== | ||
+ | ^Offset^Type^Name^Description^ | ||
+ | |0x00|char|signature[4] |"SOOL"| | ||
+ | |0x04|u32 |fileSize |Size of the sool file.| | ||
+ | |0x08|u16 |numSections |Number of interactor sections.| | ||
+ | |0x0A|u8 |padding[2] |Alignment padding.| | ||
+ | |0x0C|u32 |sectionOffsets[]|Array of interactor section offsets. The length of this array is defined by the ''numSections'' field.| | ||
+ | |....|u32 |unknownData[] |Unknown data. Always the same size as ''sectionOffsets''.| | ||
+ | |||
+ | ==== Interactor sections ==== | ||
+ | ^Offset^Type^Name^Description^ | ||
+ | |0x00|u16 |offsVars |Offset of the interactor's variables.| | ||
+ | |0x02|u16 |offsVarsEnd |End offset of the interactor's variables.| | ||
+ | |0x04|u16 |offsElements |Offset of the interactor's elements. 0xFFFF if ''numElements'' is zero.| | ||
+ | |0x06|u16 |numElements |Number of elements.| | ||
+ | |0x08|u16 |unk08 |Unknown - always 0xFFFF?| | ||
+ | |0x0A|u16 |specialMethodIdx|An index of ''methodOffsets''. Unknown purpose.| | ||
+ | |0x0C|u16 |offsMethodsEnd |End offset of the method code.| | ||
+ | |0x0E|u16 |numMethods |Number of methods.| | ||
+ | |0x10|u16 |methodOffsets[] |Array of method offsets. The length of this array is defined by the ''numMethods'' field.| | ||
+ | |....|u16 |variables[] |Variable definitions. The position and length of this array are defined by the ''offsVars'' and ''offsVarsEnd'' fields.| | ||
+ | |....|u8 |methodCode[] |Method bytecode. See commands below.| | ||
+ | |....|u8 |garbage[] |If ''offsMethodsEnd'' is uneven, there will be one padding byte of an arbitrary value here for alignment.| | ||
+ | |....|elem|elements[] |Element lookup table. Each entry contains two u16 fields for the key and value.| | ||
---- | ---- | ||
- | ====00: set_flag_1 ==== | + | ===== Commands ===== |
+ | ====00: exit ==== | ||
''00'' | ''00'' | ||
- | Unknown purpose. Sets flag 1 and does not increment the command pointer. | + | ASM Summary: Sets flag 1 and does not increment the command pointer. |
---- | ---- | ||
====01: unk_ret0 ==== | ====01: unk_ret0 ==== | ||
Line 16: | Line 43: | ||
Unknown purpose. | Unknown purpose. | ||
- | ASM Summary: Returns 0 in the opcode processing function and does not increment command pointer. | + | ASM Summary: Returns 0 in the native opcode processing function and does not increment command pointer. |
---- | ---- | ||
- | ====02: branch (or return?) ==== | + | ====02: return ==== |
''02'' | ''02'' | ||
- | Pop offset and context id from the stack, branch to offset and set m_ExecCtx to the context. | + | Return from method call: Pop offset and context ID from the stack, set the current execution context to the context specified by ''returnCtxId'' and jump to ''returnOffs''. |
+ | |||
+ | This command is at the end of every method that would be invoked via a call_method or call_ctx_method command. | ||
- | Stack: ''[...] [ctxId] [offset] -> [...]'' | + | Stack: ''[...] [returnCtxId] [returnOffs] -> [...]'' |
---- | ---- | ||
====03: branch_imm_cond ==== | ====03: branch_imm_cond ==== | ||
Line 95: | Line 124: | ||
Stack: ''[...] -> [...] [immValue1] [immValue2]'' | Stack: ''[...] -> [...] [immValue1] [immValue2]'' | ||
---- | ---- | ||
- | ====0B: load_ctx_var_offs ==== | + | ====0B: load_ctx_elem ==== |
''0B'' | ''0B'' | ||
- | Pop variable id and context id from the stack, push offset of variable to the stack. | + | Pop element key and context id from the stack, push context's element value to the stack. |
- | Stack: ''[...] [ctxId] [varId] -> [...] [varOffset]'' | + | Stack: ''[...] [ctxId] [elemKey] -> [...] [elemValue]'' |
---- | ---- | ||
- | ====0C: load_ctx_var_offs_keep_ctx ==== | + | ====0C: load_ctx_elem_keep_ctx ==== |
''0C'' | ''0C'' | ||
- | Pop variable id from the stack, load context id from top of stack (do not pop context id). Push offset of variable to the stack. | + | Pop element key from the stack, load context id from top of stack (do not pop context id). Push context's element value to the stack. |
- | Stack: ''[...] [ctxId] [varId] -> [...] [ctxId] [varOffset]'' | + | Stack: ''[...] [ctxId] [elemKey] -> [...] [ctxId] [elemValue]'' |
---- | ---- | ||
- | ====0D: load_ctx_var ==== | + | ====0D: load_ctx_elem_var ==== |
''0D'' | ''0D'' | ||
- | Pop variable id and context id from the stack. Push context's variable value to the stack. | + | Pop element key and context id from the stack. Using the element's value as a variable offset, push context's variable to the stack. |
- | Stack: ''[...] [ctxId] [varId] -> [...] [varValue]'' | + | Stack: ''[...] [ctxId] [elemKey] -> [...] [varValue]'' |
---- | ---- | ||
====0E: unk0E ==== | ====0E: unk0E ==== | ||
Line 179: | Line 208: | ||
''17'' | ''17'' | ||
- | Pop 2 values from the stack, if both values are non-zero, push 1, else push 0. | + | Logical and (''&&''). Pop 2 values from the stack, if both values are non-zero, push 1, else push 0. |
Stack: ''[...] [value2] [value1] -> [...] [value1 != 0 && value2 != 0]'' | Stack: ''[...] [value2] [value1] -> [...] [value1 != 0 && value2 != 0]'' | ||
Line 186: | Line 215: | ||
''18'' | ''18'' | ||
- | Pop 2 values from the stack, if either value is non-zero, push 1, else push 0. | + | Logical or (''||''). Pop 2 values from the stack, if either value is non-zero, push 1, else push 0. |
Stack: ''[...] [value2] [value1] -> [...] [value1 != 0 || value2 != 0]'' | Stack: ''[...] [value2] [value1] -> [...] [value1 != 0 || value2 != 0]'' | ||
Line 403: | Line 432: | ||
''39'' | ''39'' | ||
- | Pop method id from the stack. Push opOffs and return offset to the stack. Jump to method offset. | + | Call local context's method: Pop method id from the stack. Push the current context ID and return offset to the stack and jump to the method's offset. |
- | Stack: ''[...] [methodId] -> [...] [opOffs] [returnOffs]'' | + | The called method will pop ''returnCtxId'' and ''returnOffs'' from the stack before returning; they are not visible to the caller. |
- | TODO what is opOffs for? | + | Stack: ''[...] [methodId] -> [...] [returnCtxId] [returnOffs] -> [...]'' |
---- | ---- | ||
====3A: call_ctx_method ==== | ====3A: call_ctx_method ==== | ||
''3A'' | ''3A'' | ||
- | Pop context id and method id from the stack. Push opOffs and return offset to the stack. Replace m_ExecCtx with context and jump to method offset. | + | Call another context's method: Pop method ID and context ID from the stack. Push current execution context ID and return offset to the stack. Set the current execution context to the context specified by ctxId and jump to the method's offset. |
- | Stack: ''[...] [ctxId] [methodId] -> [...] [opOffs] [returnOffs]'' | + | The called method will pop ''returnCtxId'' and ''returnOffs'' from the stack before returning; they are not visible to the caller. |
+ | |||
+ | Stack: ''[...] [methodId] [ctxId] -> [...] [returnCtxId] [returnOffs] -> [...]'' | ||
---- | ---- | ||
====3B: pop_nop ==== | ====3B: pop_nop ==== | ||
Line 421: | Line 452: | ||
Pop value from the stack and do nothing with it. | Pop value from the stack and do nothing with it. | ||
---- | ---- | ||
- | ====3C...4A: unk3C ==== | + | ====3C...4A: call_vnative==== |
''3C''...''4A'' | ''3C''...''4A'' | ||
- | Call a function with ''(command byte - 0x3B)'' arguments on the stack? | + | Call a native void function with ''n'' arguments on the stack where ''n'' = ''(command byte - 0x3C)''. The function to call is specified by the function ID at the top of the stack. Function IDs 0x00 through 0x98 are valid. |
+ | |||
+ | Stack: ''[...] [argument(s)] [functionId] -> [...]'' | ||
---- | ---- | ||
- | ====50...5E: unk50 ==== | + | ====50...5E: call_native ==== |
''50''...''5E'' | ''50''...''5E'' | ||
- | Call a function with ''(command byte - 0x4F)'' arguments on the stack and push the return value to the stack? | + | Call a native function with ''n'' arguments on the stack where ''n'' = ''(command byte - 0x50)'', push the return value to the stack. The function to call is specified by a function ID at the top of the stack. Function IDs 0x00 through 0x47 are valid. |
+ | |||
+ | Stack: ''[...] [argument(s)] [functionId] -> [...] [result]'' | ||
---- | ---- | ||
====Invalid opcodes ==== | ====Invalid opcodes ==== | ||
27, 33, 4B, 4C, 4D, 4E, 4F, 5F...FF. | 27, 33, 4B, 4C, 4D, 4E, 4F, 5F...FF. | ||