Open Spiral Bitcode: Difference between revisions
(Created page with "'''O'''pen '''S'''piral '''B'''itcode (OSB) is an intermediary representative format designed to store OSL instructions in a form that makes them readable quickly and efficien...") |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 17: | Line 17: | ||
|01 | |01 | ||
|Add Dialogue | |Add Dialogue | ||
| | |2 | ||
| | | | ||
|- | |- | ||
|02 | |02 | ||
|Add Dialogue (Variable Speaker) | |Add Dialogue (Variable Speaker) | ||
| | |2 | ||
| | | | ||
|- | |- | ||
Line 204: | Line 204: | ||
Sets a variable value. Reads a UTF-8 null terminated string as the variable name, and an argument (See [[#Read Argument]]). | Sets a variable value. Reads a UTF-8 null terminated string as the variable name, and an argument (See [[#Read Argument]]). | ||
--- | ---- | ||
== Arguments == | == Arguments == |
Latest revision as of 10:50, 1 March 2020
Open Spiral Bitcode (OSB) is an intermediary representative format designed to store OSL instructions in a form that makes them readable quickly and efficiently, without having to bundle ANTLR in it's entirety.
Specification
OSB Opcodes | |||
---|---|---|---|
Hex Opcode | Name | Argument Count | Comments |
00 | Set Version | 3 | |
01 | Add Dialogue | 2 | |
02 | Add Dialogue (Variable Speaker) | 2 | |
03 | Add Function Call | 1+ | |
04 | Add If Check | 3+ | This is a meta check; use Add Flag Check for in game flag checks |
05 | Add Flag Check | 3+ | |
06 | Add Tree | 0 | |
06 | Add Load Map | 0 | |
... | |||
70 | Add Opcode | 1+ | |
71 | Add Opcode (Variable Argument(s)) | 1+ | |
72 | Add Named Opcode | 1+ | |
73 | Add Named Opcode (Variable Argument(s)) | 1+ | |
... | |||
80 | Add Label | — | Not currently implemented; see tracking issue |
81 | Add Parameter | — | Not currently implemented; see tracking issue |
82 | Add Text | — | Not currently implemented; see tracking issue |
... | |||
8F | Set Variable | 2 |
00 - Set Version
Sets the version of OSB to use. Only necessary if you plan on changing implementations based on version.
Reads 3 bytes - major, minor, patch.
The current version is 2.0.0
01 - Add Dialogue
Adds a line of dialogue to the current script. Reads a null terminated UTF-8 String as the speaker name, and an argument (See #Read Argument) for the dialogue.
How the speaker name is handled is up to the visitor.
02 - Add Dialogue (Variable Speaker)
Adds a line of dialogue to the current script. Reads a null terminated UTF-8 String as the variable name, and an argument (See #Read Argument) for the dialogue.
This opcode should get the data corresponding to the variable passed in, and then pass that value on to the speaker.
03 - Add Function Call
Calls a function. Reads a null terminated UTF-8 String as the function name, and then a single byte as the argument count, then reads (argument count) function parameters.
A function parameter is defined as a null terminated UTF-8 String (which may be just a single null terminator to omit it) as the parameter name, then the value (See #Read Argument).
The function calls that are exposed are up to the individual visitor, however a list of standards is provided here.
04 - Add If Check
Runs an expression, and only parses the following block if the expression is true.
Reads the following values:
- Value to compare (See #Read Argument)
- Comparison method (single byte)
- Value to compare against (See #Read Argument)
- Else If Branch Count (single byte, 0-127)
If a comparison of the two values with the provided method is true, then we run the first provided block. Otherwise, we repeat until we get a check that returns true.
If the Branch Count has the ELSE flag set (0x80), then the final block is an else block, and will be run if none of the checks returned true.
A block is simply an int32 for length, followed by more OSB code. If the block should be run, create a subparser with the visitor and an incremented level, otherwise simply skip that many bytes.
05 - Add Flag Check
Adds a flag check to the game.
Reads the following values:
- Condition count (int8, must be at least 1)
- Flag to compare (See #Read Argument)
- Flag comparison method (int8)
- Flag value to compare against (See #Read Argument)
- An array of subconditions (condition count - 1)
- Logical operator (int8)
- Flag to compare (See #Read Argument)
- Flag comparison method (int8)
- Flag value to compare against (See #Read Argument)
- Else Check Flag Branch Count (single byte, 0-127)
For each flag check, read an int32 for length, then that many bytes for the eventual block that will be parsed.
Each else check flag block also first must read it's own check:
- Condition count (int8, must be at least 1)
- Flag to compare (See #Read Argument)
- Flag comparison method (int8)
- Flag value to compare against (See #Read Argument)
- An array of subconditions (condition count - 1)
- Logical operator (int8)
- Flag to compare (See #Read Argument)
- Flag comparison method (int8)
- Flag value to compare against (See #Read Argument)
If the Branch Count has the ELSE flag set (0x80), then the final block is an else block.
06 - Add Tree
Adds a type of tree. A tree here is defined as a block of OSB code that operates within a certain context, such as scripts that need to use the Branch opcode
Reads an int8 as the tree type, then an int32 as the block length, then that many bytes of OSB code.
Tree Types | |||
---|---|---|---|
Hex Opcode | Name | ||
0 | Present Selection |
07 - Load Map
Adds a call to load a map. While this is currently lin-centric, it will eventually encompass DRv3 as well (see tracking issue).
Reads three arguments (See #Read Argument) - map ID, state, and an unknown. State defaults to 0, and unknown defaults to 0xFF, if a null-like argument is provided, however three arguments must be provided!.
An int32 is then read as the length of the following block, then that many bytes of OSB code is read.
70 - Add Opcode
Adds a numerical opcode. Reads an int8 as the opcode, an int8 as the argument count, then that many variable int16's.
71 - Add Opcode (Variable Arguments)
Adds a numerical opcode. Reads an int8 as the opcode, an int8 as the argument count, then that many arguments (See #Read Argument).
72 - Add Opcode
Adds a named opcode. Reads a UTF-8 null terminated string as the opcode name, an int8 as the argument count, then that many variable int16's.
73 - Add Opcode (Variable Arguments)
Adds a named opcode. Reads a UTF-8 null terminated string as the opcode name, an int8 as the argument count, then that many arguments (See #Read Argument).
8F - Set Variable
Sets a variable value. Reads a UTF-8 null terminated string as the variable name, and an argument (See #Read Argument).
Arguments
OSB has a few clever ways of supporting varying argument types and supplying them to the underlying compiler.
Read Argument
Read an int8 for the argument type, then check the corresponding entry for how to handle it
Argument Types | |||
---|---|---|---|
Hex Opcode | Name | ||
60 | Label | ||
61 | Parameter | ||
62 | Text | ||
63 | Long Label | ||
64 | Long Parameter | ||
65 | Long Reference | ||
... | |||
6A | Boolean | ||
6B | Function Call | ||
6C | Variable Reference | ||
... | |||
6F | Null | ||
70 | Int8 | ||
71 | Int16LE | ||
72 | Int16BE | ||
73 | Int24LE | ||
74 | Int24BE | ||
75 | Int32LE | ||
76 | Int32BE | ||
... | |||
7E | Arbitrary Integer | ||
7F | Arbitrary Float |
Label Argument
Read a null terminated UTF-8 String.
Parameter Argument
Read a null terminated UTF-8 String.
Text Argument
Read a null terminated UTF-8 String.
Boolean Argument
Read an int8 as a truthy (0 is false, anything else is true) value.
Function Call Argument
Reads a null terminated UTF-8 String as the function name, and then a single byte as the argument count, then reads (argument count) function parameters.
A function parameter is defined as a null terminated UTF-8 String (which may be just a single null terminator to omit it) as the parameter name, then the value (See #Read Argument).
Variable Reference Argument
Reads a null terminated UTF-8 String as the variable name.
Numerical Arguments
All fixed-type numerical arguments (int8, int16, int32) are read as expected. Arbitrary integers are read as an int64LE, and arbitrary decimals are read as a float32LE.
Variable Int16
Read the first byte. If that byte is less than 0x80, that is the value.
If it's greater than 0x80, get the value returned by performing a bitwise AND with 0x7F.
Read the second byte, and shift it right by 7 bits, and perform a bitwise OR with the first value.
In Python:
(first_byte & 0x7F) | (f.get_u8() << 7)