LHVM (Lionhead Virtual Machine)
Matt Stevens edited this page Sep 3, 2019
·
1 revision
Lionhead Virtual Machine (LHVM) is a simple stack based virtual machine used to execute bytecode generated from a proprietary scripting language to generate the narrative world of Black & White.
The virtual machine consists of a total of 31 different opcodes, each instruction also
has two additional enum values: access type
is either 1
: use stack or 2
: use variable.
And data type
which can can be any of the following:
-
0x01
: Integer Value -
0x02
: Float Value -
0x03
: Vector Value (Tends to be 3 floats pushed and popped on the stack equally) -
0x04
: ? -
0x05
: ? -
0x06
: Boolean value (0 = false
,1 = true
)
Below is a list of defined behaviours combinations of opcodes and data types should use, this should be a comprehensive list of all needed to implement a fully working LHVM, however it is unknown if compiled bytecodes have any undefined behaviours.
Opcode | Data Type | Mnemonic | Description |
---|---|---|---|
0x00 |
END |
Stops the execution of the current script task. | |
0x01 |
WAIT |
Waits at this instruction until a value can be popped from the stack. | |
0x02 |
PUSH |
Pushes a literal value onto the stack, Value can either be literal or a reference to a variable depending on Access . |
|
0x03 |
POP |
Pops a value from the stack either into null or into a referenced variable. | |
0x04 |
0x01 |
ADD |
Pops 2 ints , adds them, pushes 1 int . |
0x04 |
0x02 |
ADDF |
Pops 2 floats , adds them, pushes 1 float . |
0x04 |
0x03 |
ADDV |
Pops 6 vfloats , adds them, pushes 3 vfloats . |
0x05 |
CALL |
Calls a "native" function using the Value as the function identifer. (0 -> 464) |
|
0x06 |
0x01 |
MINUS |
Pops 2 ints , minuses them, pushes 1 int . |
0x06 |
0x02 |
MINUSF |
Pops 2 floats , minuses them, pushes 1 float . |
0x06 |
0x03 |
MINUSV |
Pops 6 vfloats , minuses them, pushes 3 vfloats . |
0x07 |
0x01 |
UMINUS |
Pops 1 int and pushes the negated 1 int . |
0x07 |
0x02 |
UMINUSF |
Pops 1 float and pushes the negated 1 float . |
0x07 |
0x03 |
UMINUSV |
Pops 3 vfloat and pushes the negated 3 vfloat . |
0x08 |
0x01 |
TIMES |
Pops 2 ints , multiplies them, pushes 1 int . |
0x08 |
0x02 |
TIMESF |
Pops 2 floats , multiplies them, pushes 1 float . |
0x08 |
0x03 |
TIMESV |
Pops 6 vfloats , multiplies them, pushes 3 vfloats . |
0x09 |
0x01 |
DIVIDE |
Pops 2 ints , divides them, pushes 1 int . |
0x09 |
0x02 |
DIVIDEF |
Pops 2 floats , divides them, pushes 1 float . |
0x09 |
0x03 |
DIVIDEV |
Pops 6 vfloats , divides them, pushes 3 vfloats . |
0x0A |
0x01 |
MODULUS |
Pops 2 ints , modulus them, pushes 1 int . |
0x0A |
0x02 |
MODULUSF |
Pops 2 floats , modulus them, pushes 1 float . |
0x0B |
NOT |
Pops 1 value, checks if it's equal to zero, pushes 1 boolean . |
|
0x0C |
AND |
Pops 2 values, val1 && val2 , pushes 1 boolean . |
|
0x0D |
OR |
Pops 2 values, `val1 |
|
0x0E |
0x01 |
EQ |
Pops 2 integer values, checks equality, pushes 1 boolean value. |
0x0E |
0x02 |
EQ |
Pops 2 float values, checks equality, pushes 1 boolean value. |
0x0E |
0x0* |
EQ |
Pops zero values, pushes 1 false boolean value. |
0x0E |
0x06 |
EQ |
Pops 2 boolean values, checks equality, pushes 1 boolean value. |
0x0F |
0x01 |
NEQ |
Pops 2 integer values, checks equality, pushes 1 boolean value. |
0x0F |
0x02 |
NEQ |
Pops 2 float values, checks equality, pushes 1 boolean value. |
0x0F |
0x0* |
NEQ |
Pops zero values, pushes 1 false boolean value. |
0x0F |
0x06 |
NEQ |
Pops 2 boolean values, checks equality, pushes 1 boolean value. |
0x10 |
0x01 |
GEQ |
Pops 2 integer values, checks greater than or equal to, pushes 1 boolean value. |
0x10 |
0x02 |
GEQ |
Pops 2 float values, checks greater than or equal to, pushes 1 boolean value. |
0x10 |
0x0* |
GEQ |
Pops zero, pushes 1 false boolean value. |
0x11 |
0x01 |
LEQ |
Pops 2 integer values, checks less than or equal to, pushes 1 boolean value. |
0x11 |
0x02 |
LEQ |
Pops 2 float values, checks less than or equal to, pushes 1 boolean value. |
0x11 |
0x0* |
LEQ |
Pops zero, pushes 1 false boolean value. |
0x12 |
0x01 |
GT |
Pops 2 integer values, checks greater than, pushes 1 boolean value. |
0x12 |
0x02 |
GT |
Pops 2 float values, checks greater than, pushes 1 boolean value. |
0x12 |
0x0* |
GT |
Pops zero, pushes 1 false boolean value. |
0x13 |
0x01 |
LT |
Pops 2 integer values, checks less than, pushes 1 boolean value. |
0x13 |
0x02 |
LT |
Pops 2 float values, checks less than, pushes 1 boolean value. |
0x13 |
0x0* |
LT |
Pops zero, pushes 1 false boolean value. |
0x14 |
JUMP |
Sets the current instruction address to the value . |
|
0x15 |
SLEEP |
Pops 1 float and sleeps for that specific time. Pushes 1 boolean . |
|
0x16 |
EXCEPT |
todo... | |
0x17 |
INTCAST |
Pops 1 value , casts it to an integer and pushes 1 integer value. |
|
0x18 |
RUN |
Runs another script task independently. Value is script id. |
|
0x19 |
ENDEXCEPT |
todo... | |
0x1A |
RETEXCEPT |
todo... | |
0x1B |
FAILEXCEPT |
todo... | |
0x1C |
BRKEXCEPT |
todo... | |
0x1D |
0x01 |
SWAP |
Pops 2 ints , swaps their order, pushes 2 ints . |
0x1D |
SWAP |
todo... | |
0x1E |
LINE |
Nothing, just specifies the source code file line. |
todo: auto generate these from IDA