Skip to content

LHVM (Lionhead Virtual Machine)

Matt Stevens edited this page Sep 3, 2019 · 1 revision

Lionhead Virtual Machine Specification

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.

Opcodes

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.

Native Functions

todo: auto generate these from IDA