GBVM Instruction Set Reference
Complete reference for all GBVM (Game Boy Virtual Machine) instructions in GB Studio 4.2 — a custom bytecode assembly language that runs game scripts at runtime.
Overview
GBVM (Game Boy Virtual Machine) is GB Studio's custom bytecode interpreter. Every event script — On Init, On Interact, On Update, input handlers, timers — compiles down to GBVM assembly. You can write raw GBVM via the "GBVM Script" event in GB Studio's editor.
Architecture
- Stack-based — most operations push/pop 16-bit (INT16) values on a per-thread stack
- 16 concurrent contexts (
VM_MAX_CONTEXTS) — scripts run as cooperative threads, yielding every 16 instructions
- 64-word stack per context (
VM_CONTEXT_STACK_SIZE)
- 768-word shared heap (
VM_HEAP_SIZE) — global variables accessible by all threads
- Built-in RPN calculator for arithmetic and logic expressions
- Big-endian argument encoding, left-to-right parameter order
Variable Addressing
Variables are referenced by index. Positive indices address the shared heap (global variables). Negative indices address the thread-local stack relative to the stack pointer:
| Alias | Index | Usage |
.ARG0 | -1 | Top of stack / first argument |
.ARG1 | -2 | Second from top |
.ARG2 / .PARAM0 | -3 | First function parameter |
.ARG3 / .PARAM1 | -4 | Second function parameter |
... up to .ARG16 (-17) / .PARAM16 (-19) |
How to Use
In GB Studio, add a "GBVM Script" event and write assembly directly. The compiler also generates GBVM from visual events — you can view the output in build/src/src/data/ after exporting.
Instruction Count
This reference covers all ~130 GBVM instructions defined in
vm.i, organized by category. Each entry shows the macro name, parameters, and a brief description. Code examples are included for the most commonly used instructions.
Core / Stack Operations
Fundamental instructions for managing the VM stack, variables, and control flow.
| Instruction | Parameters | Description |
VM_STOP | — | Stops execution of the current script context. |
VM_PUSH_CONST | VAL | Pushes an INT16 immediate value onto the stack. |
VM_PUSH_VALUE | IDX | Pushes the value of a variable onto the stack. |
VM_PUSH_VALUE_IND | IDX | Pushes a variable value indirectly — IDX contains the index of the variable to push. |
VM_PUSH_REFERENCE | IDX | Translates IDX into an absolute index and pushes the result. Converts stack-relative to heap-absolute. |
VM_POP | N | Removes N values from the top of the stack. |
VM_SET_CONST | IDX, VAL | Sets variable IDX to immediate value VAL. |
VM_SET | IDXA, IDXB | Copies variable IDXB into variable IDXA. |
VM_SET_INDIRECT | IDXA, IDXB | Assigns IDXB's value to the variable whose index is stored in IDXA. |
VM_GET_INDIRECT | IDXA, IDXB | Reads the variable whose index is in IDXB, stores result in IDXA. |
VM_RESERVE | N | Reserves (positive) or disposes (negative) N stack slots. |
VM_GET_FAR | IDX, SIZE, BANK, ADDR | Reads a byte (.GET_BYTE) or word (.GET_WORD) from a far pointer into a variable. |
VM_GET_TLOCAL | IDXA, IDXB | Gets a thread-local variable. IDXB is the thread-local index. |
VM_MEMSET | DEST, VALUE, COUNT | Fills COUNT variables starting at DEST with the value in variable VALUE. |
VM_MEMCPY | DEST, SOUR, COUNT | Copies COUNT variables from SOUR to DEST. |
Example: Set and copy variables
; Set variable 10 to value 42
VM_SET_CONST VAR_HEALTH, 42
; Copy VAR_HEALTH into VAR_DISPLAY
VM_SET VAR_DISPLAY, VAR_HEALTH
; Push a constant, use it, then clean up
VM_PUSH_CONST 100
; ... use .ARG0 ...
VM_POP 1
RPN Calculator
The built-in Reverse Polish Notation calculator evaluates complex expressions inline. Begin with VM_RPN, push operands and apply operators, then store results or leave them on the stack.
RPN Operand Types
| Macro | Description |
.R_INT8 val | Push an INT8 constant (sign-extended to 16-bit) |
.R_INT16 val | Push an INT16 constant |
.R_REF var | Push the value of a variable |
.R_REF_IND var | Push variable value indirectly (variable contains index) |
.R_REF_SET var | Pop top of stack and store in variable |
.R_REF_SET_IND var | Pop and store indirectly |
.R_REF_MEM type, addr | Read C memory at address (.MEM_I8, .MEM_U8, .MEM_I16) |
.R_REF_MEM_SET type, addr | Pop and write to C memory at address |
.R_REF_MEM_IND type, var | Read C memory at address stored in variable |
.R_OPERATOR op | Apply an operator (see table below) |
.R_STOP | End the RPN block |
RPN Operators (Complete List)
| Category | Operator | Description |
| Arithmetic | .ADD | Addition (a + b) |
.SUB | Subtraction (a - b) |
.MUL | Multiplication (a * b) |
.DIV | Division (a / b) |
.MOD | Modulo (a % b) |
| Bitwise | .B_AND | Bitwise AND |
.B_OR | Bitwise OR |
.B_XOR | Bitwise XOR |
.B_NOT | Bitwise NOT (unary) |
| Logical | .AND | Logical AND |
.OR | Logical OR |
.NOT | Logical NOT (unary) |
| Comparison | .EQ | Equal |
.NE | Not equal |
.LT | Less than |
.GT | Greater than |
.LTE | Less than or equal |
.GTE | Greater than or equal |
| Shift | .SHL | Shift left |
.SHR | Shift right |
| Math | .MIN | Minimum of two values |
.MAX | Maximum of two values |
.ABS | Absolute value (unary) |
.NEG | Negate (unary) |
.ISQRT | Integer square root (unary) |
.ATAN2 | Two-argument arctangent (returns 0-255 angle) |
.RND | Random number (unary, uses top as limit) |
Example: Arithmetic expression
; Calculate: result = (x + 10) * 2
VM_RPN
.R_REF VAR_X
.R_INT16 10
.R_OPERATOR .ADD
.R_INT16 2
.R_OPERATOR .MUL
.R_REF_SET VAR_RESULT
.R_STOP
Example: Read/write C memory
; Read the unsigned byte 'hide_sprites' into a variable
VM_RPN
.R_REF_MEM .MEM_U8, _hide_sprites
.R_REF_SET VAR_TEMP
.R_STOP
; Write a constant byte to C memory
VM_RPN
.R_INT8 1
.R_REF_MEM_SET .MEM_I8, _hide_sprites
.R_STOP
Example: Clamp a value
; Clamp VAR_SPEED to range [0, 255]
VM_RPN
.R_REF VAR_SPEED
.R_INT16 0
.R_OPERATOR .MAX ; max(speed, 0)
.R_INT16 255
.R_OPERATOR .MIN ; min(result, 255)
.R_REF_SET VAR_SPEED
.R_STOP
Memory Access (C Variable I/O)
These convenience macros wrap VM_RPN to read/write C variables in WRAM. They provide direct access to engine internals.
| Instruction | Parameters | Description |
VM_GET_UINT8 | IDX, ADDR | Read unsigned 8-bit value from WRAM address into variable. |
VM_GET_INT8 | IDX, ADDR | Read signed 8-bit value from WRAM address into variable. |
VM_GET_INT16 | IDX, ADDR | Read signed 16-bit value from WRAM address into variable. |
VM_SET_UINT8 | ADDR, IDX | Write variable value as unsigned 8-bit to WRAM address. |
VM_SET_INT8 | ADDR, IDX | Write variable value as signed 8-bit to WRAM address. |
VM_SET_INT16 | ADDR, IDX | Write variable value as signed 16-bit to WRAM address. |
VM_SET_CONST_INT8 | ADDR, VAL | Write immediate signed 8-bit constant to WRAM address. |
VM_SET_CONST_UINT8 | ADDR, VAL | Write immediate unsigned 8-bit constant to WRAM address. |
VM_SET_CONST_INT16 | ADDR, VAL | Write immediate signed 16-bit constant to WRAM address. |
Memory Type Codes
.MEM_I8 = signed 8-bit (
'i'),
.MEM_U8 = unsigned 8-bit (
'u'),
.MEM_I16 = signed 16-bit (
'I'). These are used in the underlying
.R_REF_MEM /
.R_REF_MEM_SET RPN operations.
Example: Read and modify engine field
; Read 'camera_offset_x' (BYTE) into a variable
VM_GET_INT8 VAR_TEMP, _camera_offset_x
; Set 'hide_sprites' to 1 (constant)
VM_SET_CONST_UINT8 _hide_sprites, 1
Control Flow
Branching, looping, and conditional execution.
| Instruction | Parameters | Description |
VM_JUMP | LABEL | Unconditional jump to a label. |
VM_IF | COND, IDXA, IDXB, LABEL, N | Compare two variables; jump to LABEL if condition is true. Pop N stack values after. |
VM_IF_CONST | COND, IDXA, B, LABEL, N | Compare variable to immediate value; jump if true. Pop N after. |
VM_SWITCH | IDX, SIZE, N | Switch on variable value. Followed by SIZE .CASE entries. Pop N on exit. |
VM_LOOP | IDX, LABEL, N | Loops while variable IDX is non-zero, jumping to LABEL. Pop N on exit. |
VM_RATE_LIMIT_CONST | N, IDX, LABEL | If last execution was less than N frames ago, jump to LABEL. Uses IDX to store timestamp. |
Comparison Operators
Used with VM_IF and VM_IF_CONST:
| Operator | Value | Meaning |
.EQ | 1 | Equal |
.LT | 2 | Less than |
.LTE | 3 | Less than or equal |
.GT | 4 | Greater than |
.GTE | 5 | Greater than or equal |
.NE | 6 | Not equal |
Example: Conditional branch
; If health <= 0, jump to game_over
VM_IF_CONST .LTE, VAR_HEALTH, 0, label_game_over$, 0
; ... normal gameplay code ...
VM_JUMP label_continue$
label_game_over$:
; Handle game over
VM_STOP
label_continue$:
Example: Switch statement
; Branch based on day of week
VM_SWITCH VAR_WEEKDAY, 3, 0
.CASE 1, label_monday$
.CASE 2, label_tuesday$
.CASE 3, label_wednesday$
; Default: fall through here
VM_JUMP label_default$
label_monday$:
; Monday logic
VM_JUMP label_done$
label_tuesday$:
; Tuesday logic
VM_JUMP label_done$
label_wednesday$:
; Wednesday logic
VM_JUMP label_done$
label_default$:
; Default logic
label_done$:
Example: Loop
; Count down from 5
VM_SET_CONST VAR_COUNTER, 5
loop_start$:
; ... do something each iteration ...
VM_RPN
.R_REF VAR_COUNTER
.R_INT8 1
.R_OPERATOR .SUB
.R_REF_SET VAR_COUNTER
.R_STOP
VM_LOOP VAR_COUNTER, loop_start$, 0
Subroutines & Threading
Calls & Returns
| Instruction | Parameters | Description |
VM_CALL | ADDR | Call subroutine by near address (same bank). |
VM_RET | — | Return from near call. |
VM_RET_N | N | Return from near call and pop N arguments. |
VM_CALL_FAR | BANK, ADDR | Call subroutine by far address (cross-bank). |
VM_RET_FAR | — | Return from far call. |
VM_RET_FAR_N | N | Return from far call and pop N arguments. |
VM_CALL_NATIVE | BANK, PTR | Call a native C function. The function receives the SCRIPT_CTX pointer. |
VM_INVOKE | BANK, ADDR, N, PARAMS | Invoke a C function repeatedly until it returns true (blocking). Pop N on completion. |
Thread Management
| Instruction | Parameters | Description |
VM_LOCK | — | Lock the VM — blocks state_update, events_update, timers_update. Prevents context switching. |
VM_UNLOCK | — | Unlock the VM. Re-enables blocked updates. |
VM_IDLE | — | Yield execution for one frame. Signals the thread is in a waitable state. |
VM_STOP | — | Stop the current script context. |
VM_BEGINTHREAD | BANK, PROC, HTHREAD, NARGS | Spawn a new thread. HTHREAD receives the handle. NARGS values are copied from the current stack. |
VM_JOIN | IDX | Wait for thread IDX to complete (blocking). |
VM_TERMINATE | IDX | Kill thread by handle. |
VM_CONTEXT_PREPARE | SLOT, BANK, ADDR | Assign a script to a slot (used with VM_INPUT_ATTACH). |
VM_LOCK Pitfall
On Init scripts auto-generate
VM_LOCK at the start and
VM_UNLOCK at the end. If the script contains an infinite loop (
LOOP_WHILE),
VM_UNLOCK never executes, permanently blocking
state_update(). Never use infinite loops in On Init if the scene type needs
state_update().
Exceptions
| Instruction | Parameters | Description |
VM_RAISE | CODE, SIZE | Raise an exception. Stack data of SIZE bytes is passed to the handler. |
Exception codes: EXCEPTION_RESET (1), EXCEPTION_CHANGE_SCENE (2), EXCEPTION_SAVE (3), EXCEPTION_LOAD (4).
Miscellaneous
| Instruction | Parameters | Description |
VM_POLL_LOADED | IDX | Check if VM state was restored from save. Resets the restore flag. |
VM_TEST_TERMINATE | FLAGS | Terminate unit testing. .TEST_WAIT_VBL waits for VBlank first. |
Random Numbers
| Instruction | Parameters | Description |
VM_INIT_RNG | IDX | Initialize RNG seed from the value in variable IDX. |
VM_RANDOMIZE | — | Initialize RNG seed from hardware DIV register and game_time (macro). |
VM_RAND | IDX, MIN, LIMIT | Store a random value in [MIN, MIN + LIMIT) in variable IDX. |
Example: Random number
; Generate random number between 1 and 6 (inclusive)
VM_RANDOMIZE
VM_RAND VAR_DICE, 1, 6
Actor Operations
Instructions for positioning, animating, and controlling actors. Many use pseudo-struct patterns where a stack index points to the first word of a multi-word structure.
Position & Movement
| Instruction | Parameters | Description |
VM_ACTOR_SET_POS | IDX | Set actor position. Pseudo-struct: [ID, X, Y] at IDX. |
VM_ACTOR_GET_POS | IDX | Get actor position into pseudo-struct: [ID, X, Y] at IDX. |
VM_ACTOR_MOVE_TO | IDX | Smoothly move actor (blocking). Pseudo-struct: [ID, X, Y, ATTR]. Legacy — prefer INIT + XY pattern. |
VM_ACTOR_MOVE_TO_INIT | IDX, ATTR | Initialize smooth movement. Pseudo-struct: [ID, X, Y]. ATTR controls collision/diagonal/snap. |
VM_ACTOR_MOVE_TO_X | IDX, ATTR | Move actor along X-axis only (blocking). |
VM_ACTOR_MOVE_TO_Y | IDX, ATTR | Move actor along Y-axis only (blocking). |
VM_ACTOR_MOVE_TO_XY | IDX, ATTR | Move actor along both axes simultaneously (blocking). |
VM_ACTOR_MOVE_TO_SET_DIR_X | IDX | Face actor toward X destination (no movement). |
VM_ACTOR_MOVE_TO_SET_DIR_Y | IDX | Face actor toward Y destination (no movement). |
VM_ACTOR_SET_ANIM_MOVING | IDX | Set actor to moving animation for current direction. |
VM_ACTOR_MOVE_CANCEL | ACTOR | Cancel any in-progress movement. |
Movement Attributes
| Flag | Value | Description |
.ACTOR_ATTR_H_FIRST | 0x01 | Move horizontal before vertical |
.ACTOR_ATTR_CHECK_COLL_WALLS | 0x02 | Check wall collisions |
.ACTOR_ATTR_DIAGONAL | 0x04 | Allow diagonal movement |
.ACTOR_ATTR_RELATIVE_SNAP_PX | 0x08 | Coordinates are relative, in pixels |
.ACTOR_ATTR_RELATIVE_SNAP_TILE | 0x10 | Coordinates are relative, in tiles |
.ACTOR_ATTR_CHECK_COLL_ACTORS | 0x20 | Check actor-to-actor collisions |
.ACTOR_ATTR_CHECK_COLL | 0x22 | Check both wall and actor collisions |
Activation & Visibility
| Instruction | Parameters | Description |
VM_ACTOR_ACTIVATE | ACTOR | Activate an actor (add to active list, start rendering). |
VM_ACTOR_DEACTIVATE | ACTOR | Deactivate an actor. Sets ACTOR_FLAG_DISABLED to prevent re-activation by streaming. |
VM_ACTOR_SET_HIDDEN | ACTOR, HIDDEN | Show (.ACTOR_VISIBLE) or hide (.ACTOR_HIDDEN) an actor. Macro wrapping VM_ACTOR_SET_FLAGS. |
Direction & Animation
| Instruction | Parameters | Description |
VM_ACTOR_SET_DIR | ACTOR, DIR | Set actor facing. .DIR_DOWN(0), .DIR_RIGHT(1), .DIR_UP(2), .DIR_LEFT(3). |
VM_ACTOR_GET_DIR | IDX, DEST | Get actor direction into DEST. |
VM_ACTOR_GET_ANGLE | IDX, DEST | Get actor movement angle (0-255) into DEST. |
VM_ACTOR_SET_ANIM | ACTOR, ANIM | Set actor animation state (e.g. idle, walking). |
VM_ACTOR_SET_ANIM_SET | ACTOR, OFFSET | Set actor animation set number. |
VM_ACTOR_SET_ANIM_FRAME | ACTOR | Set animation frame. Pseudo-struct: [ID, FRAME] at ACTOR. |
VM_ACTOR_GET_ANIM_FRAME | ACTOR | Get animation frame. Pseudo-struct: [ID, FRAME] at ACTOR. |
VM_ACTOR_SET_ANIM_TICK | ACTOR, TICK | Set animation tick speed. 255 = ANIM_PAUSED (stops auto-advance). |
VM_ACTOR_SET_MOVE_SPEED | ACTOR, SPEED | Set actor movement speed in subpixels per frame. |
Properties & Flags
| Instruction | Parameters | Description |
VM_ACTOR_SET_FLAGS | ACTOR, FLAGS, MASK | Set/clear actor flags by bitmask. |
VM_ACTOR_SET_COLL_ENABLED | ACTOR, ENABLED | Enable/disable actor collision. Macro. |
VM_ACTOR_SET_BOUNDS | IDX | Set collision bounds. Pseudo-struct: [ID, LEFT, RIGHT, TOP, BOTTOM]. |
VM_ACTOR_SET_SPRITESHEET | ACTOR, BANK, SHEET | Change actor spritesheet by far pointer. |
VM_ACTOR_SET_SPRITESHEET_BY_REF | ACTOR, FAR_PTR | Change spritesheet using variables. Pseudo-struct: [BANK, DATA] at FAR_PTR. |
VM_ACTOR_REPLACE_TILE | ACTOR, TARGET, BANK, DATA, START, LEN | Replace tiles within actor's spritesheet in VRAM. |
VM_ACTOR_EMOTE | ACTOR, BANK, AVATAR | Show an emote bubble above actor. |
Actor Flags
| Flag | Value | Description |
.ACTOR_FLAG_PINNED | 0x01 | Pin actor to screen (not world coordinates) |
.ACTOR_FLAG_HIDDEN | 0x02 | Hide actor from rendering |
.ACTOR_FLAG_ANIM_NOLOOP | 0x04 | Stop animation at last frame |
.ACTOR_FLAG_COLLISION | 0x08 | Enable collision detection |
.ACTOR_FLAG_PERSISTENT | 0x10 | Persist across scene changes |
Update Scripts
| Instruction | Parameters | Description |
VM_ACTOR_BEGIN_UPDATE | ACTOR | Begin an actor's update script (runs every frame via script_runner_update). |
VM_ACTOR_TERMINATE_UPDATE | ACTOR | Stop an actor's update script. |
Example: Move actor to position
; Set up position struct on stack: [ActorID, X, Y]
VM_RESERVE 3
VM_SET_CONST .ARG2, 1 ; Actor index 1
VM_SET_CONST .ARG1, 80 ; X = 80 pixels (in subpixels: 80 * 8 = 640 tiles)
VM_SET_CONST .ARG0, 64 ; Y = 64 pixels
; Initialize and execute smooth movement
VM_ACTOR_MOVE_TO_INIT .ARG2, .ACTOR_ATTR_CHECK_COLL
VM_ACTOR_MOVE_TO_XY .ARG2, .ACTOR_ATTR_CHECK_COLL
VM_POP 3
Example: Set animation frame (pause auto-animation)
; Pseudo-struct for SET_ANIM_FRAME: [ID, FRAME]
VM_RESERVE 2
VM_SET_CONST .ARG1, 1 ; Actor index 1
VM_SET_CONST .ARG0, 3 ; Frame 3
VM_ACTOR_SET_ANIM_FRAME .ARG1
VM_ACTOR_SET_ANIM_TICK .ARG1, 255 ; Pause animation to prevent auto-advance
VM_POP 2
Camera
| Instruction | Parameters | Description |
VM_CAMERA_MOVE_TO | IDX, SPEED, AFTER_LOCK | Smoothly move camera to position (blocking). Pseudo-struct: [X, Y] at IDX. SPEED controls movement rate. |
VM_CAMERA_SET_POS | IDX | Instantly set camera position. Pseudo-struct: [X, Y] at IDX. |
Camera Lock Flags
| Flag | Value | Description |
.CAMERA_UNLOCK | 0b00000000 | Camera follows player |
.CAMERA_LOCK_X | 0b00000001 | Lock X-axis position |
.CAMERA_LOCK_Y | 0b00000010 | Lock Y-axis position |
.CAMERA_LOCK | 0b00000011 | Lock both axes |
.CAMERA_LOCK_X_MIN | 0b00000100 | Clamp X minimum |
.CAMERA_LOCK_X_MAX | 0b00001000 | Clamp X maximum |
.CAMERA_LOCK_Y_MIN | 0b00010000 | Clamp Y minimum |
.CAMERA_LOCK_Y_MAX | 0b00100000 | Clamp Y maximum |
Example: Move camera and lock
; Set up camera target position: [X, Y]
VM_RESERVE 2
VM_SET_CONST .ARG1, 10 ; X position in tiles
VM_SET_CONST .ARG0, 8 ; Y position in tiles
VM_CAMERA_MOVE_TO .ARG1, 3, .CAMERA_LOCK
VM_POP 2
Scene Management
| Instruction | Parameters | Description |
VM_SCENE_PUSH | — | Push the current scene onto the scene stack (max depth: 8). |
VM_SCENE_POP | — | Pop and load the last scene from the stack. |
VM_SCENE_POP_ALL | — | Pop all scenes and load the first (bottom) one. |
VM_SCENE_STACK_RESET | — | Clear the scene stack without loading anything. |
Scene Changes
Actual scene transitions are triggered by
VM_RAISE EXCEPTION_CHANGE_SCENE with scene data on the stack. The GB Studio compiler handles this automatically — you rarely need to write the raise manually.
UI & Text
Instructions for the overlay window, text rendering, and menus.
Text Loading & Display
| Instruction | Parameters | Description |
VM_LOAD_TEXT | NARGS | Load text string into memory. Followed by optional .dw variable list and .asciz string. |
VM_LOAD_TEXT_EX | N | Load text with parameters from stack (varargs). Pop N after. |
VM_DISPLAY_TEXT | — | Render loaded text in overlay (obsolete macro, uses defaults). |
VM_DISPLAY_TEXT_EX | OPTIONS, START_TILE | Render text with options. .DISPLAY_PRESERVE_POS preserves cursor. .TEXT_TILE_CONTINUE (0xFF) continues from current position. |
VM_SET_FONT | FONT_INDEX | Set active font for text rendering. |
VM_SET_PRINT_DIR | DIRECTION | Set print direction: .UI_PRINT_LEFTTORIGHT or .UI_PRINT_RIGHTTOLEFT. |
VM_SWITCH_TEXT_LAYER | LAYER | Switch text output: .TEXT_LAYER_BKG (background) or .TEXT_LAYER_WIN (overlay). |
VM_SET_TEXT_SOUND | BANK, ADDR, MASK | Set sound effect for text output. |
Text Format Specifiers
| Specifier | Description |
%d | Render variable value as decimal number |
%Dn | Render variable value with n-digit width |
%c | Render character from variable value |
Text Escape Sequences
| Sequence | Description |
\001\x | Set text speed (x = 1-8, frames = 2^(x-2)) |
\002\x | Set text font |
\003\x\y | Set cursor position (absolute) |
\004\x\y | Set cursor position (relative to last char) |
\005 | Escape the next character |
\006\mask | Wait for input before continuing |
\007\n | Invert colors (\002 = on, \001 = off) |
\010\x | Print direction (01 = LTR, 02 = RTL) |
\011 | Zero-width symbol |
\n | Next line |
\013\x | Set UI palette number |
\r | Scroll text one line up |
Overlay Window
| Instruction | Parameters | Description |
VM_OVERLAY_SHOW | X, Y, COLOR, OPTIONS | Show overlay. COLOR: .UI_COLOR_BLACK/.UI_COLOR_WHITE. OPTIONS: .UI_DRAW_FRAME, .UI_AUTO_SCROLL. |
VM_OVERLAY_HIDE | — | Hide overlay (moves to Y = .MENU_CLOSED_Y). |
VM_OVERLAY_SETPOS | X, Y | Set overlay position instantly (in tiles). |
VM_OVERLAY_MOVE_TO | X, Y, SPEED | Animate overlay to new position. Speeds: .OVERLAY_IN_SPEED, .OVERLAY_OUT_SPEED, .OVERLAY_SPEED_INSTANT. |
VM_OVERLAY_CLEAR | X, Y, W, H, COLOR, OPTIONS | Clear a rectangular area of the overlay. |
VM_OVERLAY_SCROLL | X, Y, W, H, COLOR | Scroll a rectangular area of the overlay up by one row. |
VM_OVERLAY_SET_SCROLL | X, Y, W, H, COLOR | Define automatic scroll area for text overflow. |
VM_OVERLAY_WAIT | IS_MODAL, WAIT_FLAGS | Wait for overlay operations to complete. |
VM_OVERLAY_SET_MAP | IDX, X, Y, BANK, BKG | Copy a tilemap to overlay at a tile position. |
VM_OVERLAY_SET_SUBMAP | X, Y, W, H, SX, SY | Copy a rectangular area from the scene background to overlay. |
VM_OVERLAY_SET_SUBMAP_EX | PARAMS_IDX | Extended submap copy using pseudo-struct: [x, y, w, h, scene_x, scene_y]. |
Overlay Wait Flags
| Flag | Value | Description |
.UI_WAIT_NONE | 0 | No wait |
.UI_WAIT_WINDOW | 1 | Wait for window animation to finish |
.UI_WAIT_TEXT | 2 | Wait for text rendering to finish |
.UI_WAIT_BTN_A | 4 | Wait for A button press |
.UI_WAIT_BTN_B | 8 | Wait for B button press |
.UI_WAIT_BTN_ANY | 16 | Wait for any button press |
Menu / Choice
| Instruction | Parameters | Description |
VM_CHOICE | IDX, OPTIONS, COUNT | Execute a choice menu. IDX receives selected item. Followed by COUNT .MENUITEM entries. |
.MENUITEM X, Y, iL, iR, iU, iD — defines cursor position and navigation for each menu item.
Menu options: .UI_MENU_STANDARD (0), .UI_MENU_LAST_0 (1), .UI_MENU_CANCEL_B (2), .UI_MENU_SET_START (4).
Example: Display text with variable
; Display "Score: 42"
VM_LOAD_TEXT 1
.dw VAR_SCORE
.asciz "Score: %d"
VM_OVERLAY_SHOW 0, 14, .UI_COLOR_WHITE, .UI_DRAW_FRAME
VM_OVERLAY_MOVE_TO 0, 14, .OVERLAY_IN_SPEED
VM_DISPLAY_TEXT
VM_OVERLAY_WAIT .UI_MODAL, .UI_WAIT_TEXT | .UI_WAIT_BTN_A
VM_OVERLAY_HIDE
Example: Choice menu
VM_LOAD_TEXT 0
.asciz "Yes\nNo"
VM_OVERLAY_SHOW 0, 14, .UI_COLOR_WHITE, .UI_DRAW_FRAME
VM_DISPLAY_TEXT
VM_CHOICE VAR_RESULT, .UI_MENU_CANCEL_B, 2
.MENUITEM 1, 1, 0, 0, 1, 1 ; "Yes" at (1,1)
.MENUITEM 1, 2, 0, 0, 0, 0 ; "No" at (1,2)
VM_OVERLAY_HIDE
Game Boy Hardware
Direct hardware control: tilesets, sprites, input, sprite mode.
| Instruction | Parameters | Description |
VM_LOAD_TILESET | IDX, BANK, BKG | Load tileset into VRAM starting at tile ID IDX. |
VM_REPLACE_TILE | TARGET, BANK, DATA, START, LEN | Replace LEN background tiles starting at TARGET with tiles from a tileset. |
VM_REPLACE_TILE_XY | X, Y, BANK, DATA, START | Replace a single background tile at position (X, Y). |
VM_GET_TILE_XY | TILE_IDX, X_IDX, Y_IDX | Get the tile ID at background position (X, Y). |
VM_SET_SPRITE_VISIBLE | MODE | Show (.SPRITES_SHOW) or hide (.SPRITES_HIDE) all sprites. Has priority over per-actor visibility. |
VM_SHOW_SPRITES | — | Macro for VM_SET_SPRITE_VISIBLE .SPRITES_SHOW. |
VM_HIDE_SPRITES | — | Macro for VM_SET_SPRITE_VISIBLE .SPRITES_HIDE. |
VM_SET_SPRITE_MODE | MODE | Set sprite size: .MODE_8X8 or .MODE_8X16. |
Timers
Timers fire every INTERVAL * 16 frames (checked in timers_update when game_time & 0x0F == 0).
| Instruction | Parameters | Description |
VM_TIMER_PREPARE | TIMER, BANK, ADDR | Load a script into a timer slot. |
VM_TIMER_SET | TIMER, INTERVAL | Start timer, calling every INTERVAL * 16 frames. |
VM_TIMER_STOP | TIMER | Stop a running timer. |
VM_TIMER_RESET | TIMER | Reset timer countdown to 0 (restarts interval). |
Example: Timer-based event
; Set up timer 0 to fire every ~2 seconds (120 frames = ~7.5 * 16)
VM_CONTEXT_PREPARE 0, ___bank_script_timer_0, _script_timer_0
VM_TIMER_PREPARE 0, ___bank_script_timer_0, _script_timer_0
VM_TIMER_SET 0, 8 ; 8 * 16 = 128 frames
Screen Fade
| Instruction | Parameters | Description |
VM_FADE | FLAGS | Fade screen. Combine: .FADE_IN/.FADE_OUT + .FADE_MODAL/.FADE_NONMODAL. |
VM_FADE_IN | IS_MODAL | Fade in (macro). 1 = modal (blocking), 0 = nonmodal. |
VM_FADE_OUT | IS_MODAL | Fade out (macro). 1 = modal (blocking), 0 = nonmodal. |
Example: Fade out and back in
VM_FADE_OUT 1 ; Modal fade out (blocks until complete)
; ... change state ...
VM_FADE_IN 1 ; Modal fade in
Sound & Music
| Instruction | Parameters | Description |
VM_MUSIC_PLAY | BANK, ADDR, LOOP | Start playing a music track. LOOP parameter is obsolete (has no effect). |
VM_MUSIC_STOP | — | Stop playing music. |
VM_MUSIC_MUTE | MASK | Mute/unmute channels. Bits: .MUTE_CH1(1), .MUTE_CH2(2), .MUTE_CH3(4), .MUTE_CH4(8). |
VM_MUSIC_ROUTINE | ROUTINE, BANK, ADDR | Attach script to music event routine (0-3). |
VM_MUSIC_SETPOS | PATTERN, ROW | Set playback position in current song. |
VM_SFX_PLAY | BANK, ADDR, MASK, PRIO | Play sound effect. Priority: .SFX_PRIORITY_MINIMAL(0), .SFX_PRIORITY_NORMAL(4), .SFX_PRIORITY_HIGH(8). |
VM_SOUND_MASTERVOL | VOL | Set master volume. |
Channel Mute Aliases
| Alias | Value | Channel |
.MUTE_CH1 / .MUTE_DUTY1 | 1 | Pulse 1 (Duty) |
.MUTE_CH2 / .MUTE_DUTY2 | 2 | Pulse 2 (Duty) |
.MUTE_CH3 / .MUTE_WAVE | 4 | Wave |
.MUTE_CH4 / .MUTE_NOISE | 8 | Noise |
Example: Play sound effect
; Play SFX on channel 4 (noise) with normal priority
VM_SFX_PLAY ___bank_sound_beep, _sound_beep, .MUTE_NOISE, .SFX_PRIORITY_NORMAL
Palettes & Color
| Instruction | Parameters | Description |
VM_LOAD_PALETTE | MASK, OPTIONS | Load palettes. MASK is a bitmask of which palettes (0-7). OPTIONS: .PALETTE_COMMIT, .PALETTE_BKG, .PALETTE_SPRITE. Followed by palette data. |
Palette Data Macros
| Macro | Parameters | Description |
.DMG_PAL | COL1, COL2, COL3, COL4 | Define a DMG palette (4 shades, 0-3). |
.CGB_PAL | R1,G1,B1 R2,G2,B2 R3,G3,B3 R4,G4,B4 | Define a CGB palette (4 colors, 5-bit RGB per channel). |
Example: Load a CGB palette
; Load background palette 0 with custom colors
VM_LOAD_PALETTE 1, .PALETTE_BKG | .PALETTE_COMMIT
.CGB_PAL 31,31,31 20,20,20 10,10,10 0,0,0
Save & Load
| Instruction | Parameters | Description |
VM_SAVE_PEEK | RES, DEST, SOUR, COUNT, SLOT | Read COUNT variables from save slot without loading the full state. RES = result (success/fail). |
VM_SAVE_CLEAR | SLOT | Erase data in a save slot. |
Full save/load operations use VM_RAISE with EXCEPTION_SAVE (3) or EXCEPTION_LOAD (4).
Math Functions
| Instruction | Parameters | Description |
VM_SIN_SCALE | IDX, IDX_ANGLE, SCALE | Compute scaled sine. IDX = scale factor (multiplied into result) and target variable. SCALE = accuracy 0-7. |
VM_COS_SCALE | IDX, IDX_ANGLE, SCALE | Compute scaled cosine. Same parameter pattern as VM_SIN_SCALE. |
Angle system: 0 = up, 64 = right, 128 = down, 192 = left. Full circle = 256 steps.
Projectiles
| Instruction | Parameters | Description |
VM_PROJECTILE_LOAD_TYPE | DEST_TYPE, SRC_TYPE, BANK, ADDR | Load projectile data into a slot. |
VM_PROJECTILE_LAUNCH | TYPE, IDX | Launch a projectile from a slot. Pseudo-struct at IDX: [pos.x, pos.y, angle]. |
Serial I/O (Link Cable)
| Instruction | Parameters | Description |
VM_SIO_SET_MODE | MODE | Set serial mode: .SIO_MODE_NONE(0), .SIO_MODE_MASTER(1), .SIO_MODE_SLAVE(2). |
VM_SIO_EXCHANGE | SOUR, DEST, SIZE | Exchange SIZE bytes via serial link. |
Real-Time Clock
| Instruction | Parameters | Description |
VM_RTC_LATCH | — | Latch current RTC value for reading. |
VM_RTC_GET | IDX, WHAT | Read RTC value: .RTC_SECONDS, .RTC_MINUTES, .RTC_HOURS, .RTC_DAYS. |
VM_RTC_SET | IDX, WHAT | Write RTC value. |
VM_RTC_START | START | Start (.RTC_START) or stop (.RTC_STOP) the RTC. |
Super Game Boy
| Instruction | Parameters | Description |
VM_SGB_TRANSFER | — | Transfer SGB packet(s). Variable-length data follows the instruction (16-byte packet multiples). |
Miscellaneous
| Instruction | Parameters | Description |
VM_RUMBLE | ENABLE | Enable (1) or disable (0) rumble on supported carts. |
VM_ASM | — | Begin inline native (Z80) assembly. End with VM_ENDASM. |
VM_ENDASM | — | End inline native assembly block (pops HL, restarts VM). |
VM_PRINTER_DETECT | ERROR, DELAY | Detect GB Printer. ERROR receives result, DELAY = timeout. |
VM_PRINT_OVERLAY | ERROR, START, HEIGHT, MARGIN | Print overlay rows to GB Printer (must be multiple of 2). |
Common GBVM Patterns
Complete working examples for frequently needed tasks.
1. Move Actor to Position
; Move actor 2 to tile position (10, 8) with collision checking
VM_RESERVE 3
VM_SET_CONST .ARG2, 2 ; Actor index 2
VM_SET_CONST .ARG1, 10 ; X position (tiles)
VM_SET_CONST .ARG0, 8 ; Y position (tiles)
VM_ACTOR_MOVE_TO_INIT .ARG2, .ACTOR_ATTR_CHECK_COLL | .ACTOR_ATTR_DIAGONAL
VM_ACTOR_MOVE_TO_XY .ARG2, .ACTOR_ATTR_CHECK_COLL | .ACTOR_ATTR_DIAGONAL
VM_POP 3
2. Conditional Branch with Variable
; If the player has the key item, open the door
VM_IF_CONST .GTE, VAR_HAS_KEY, 1, has_key$, 0
; No key -- show locked message
VM_LOAD_TEXT 0
.asciz "The door is locked."
VM_OVERLAY_SHOW 0, 14, .UI_COLOR_WHITE, .UI_DRAW_FRAME
VM_DISPLAY_TEXT
VM_OVERLAY_WAIT .UI_MODAL, .UI_WAIT_TEXT | .UI_WAIT_BTN_A
VM_OVERLAY_HIDE
VM_JUMP done$
has_key$:
; Has key -- proceed
VM_SET_CONST VAR_HAS_KEY, 0 ; Consume the key
done$:
3. Display Text with Variable Substitution
; "Day 3 - Score: 1250"
VM_LOAD_TEXT 2
.dw VAR_DAY, VAR_SCORE
.asciz "Day %d - Score: %d"
VM_OVERLAY_SHOW 0, 14, .UI_COLOR_WHITE, .UI_DRAW_FRAME
VM_DISPLAY_TEXT
VM_OVERLAY_WAIT .UI_MODAL, .UI_WAIT_TEXT | .UI_WAIT_BTN_A
VM_OVERLAY_HIDE
4. Play Sound Effect with Music Muting
; Mute noise channel for music, play SFX on noise channel
VM_MUSIC_MUTE .MUTE_NOISE
VM_SFX_PLAY ___bank_sound_explosion, _sound_explosion, .MUTE_NOISE, .SFX_PRIORITY_HIGH
; Unmute after SFX finishes (handled automatically by sound engine)
5. Frame-Counted Wait (Using VM_INVOKE)
; Wait for 60 frames (~1 second)
VM_PUSH_CONST 60
VM_INVOKE ___bank__wait_frames, _wait_frames, 1, .ARG0
6. Read/Write Engine Internals
; Disable sprites by writing to the C variable
VM_SET_CONST_UINT8 _hide_sprites, 1
; Read camera position
VM_GET_INT16 VAR_TEMP, _camera_x
; Write to an engine field
VM_SET_CONST_INT8 _elevator_auto_scroll, 0
7. Spawn a Background Thread
; Spawn a parallel script that runs independently
VM_BEGINTHREAD ___bank_script_background, _script_background, VAR_THREAD_HANDLE, 0
; ... later, wait for it to finish
VM_JOIN VAR_THREAD_HANDLE
Opcode Reference Table
Complete opcode-to-instruction mapping for all GBVM instructions.
| Opcode | Instruction | Section |
0x00 | VM_STOP | Core |
0x01 | VM_PUSH_CONST | Core |
0x02 | VM_POP | Core |
0x04 | VM_CALL | Subroutines |
0x05 | VM_RET / VM_RET_N | Subroutines |
0x06 | VM_GET_FAR | Core |
0x07 | VM_LOOP | Control Flow |
0x08 | VM_SWITCH | Control Flow |
0x09 | VM_JUMP | Control Flow |
0x0A | VM_CALL_FAR | Subroutines |
0x0B | VM_RET_FAR / VM_RET_FAR_N | Subroutines |
0x0D | VM_INVOKE | Subroutines |
0x0E | VM_BEGINTHREAD | Threading |
0x0F | VM_IF | Control Flow |
0x10 | VM_PUSH_VALUE_IND | Core |
0x11 | VM_PUSH_VALUE | Core |
0x12 | VM_RESERVE | Core |
0x13 | VM_SET | Core |
0x14 | VM_SET_CONST | Core |
0x15 | VM_RPN | RPN Calculator |
0x16 | VM_JOIN | Threading |
0x17 | VM_TERMINATE | Threading |
0x18 | VM_IDLE | Threading |
0x19 | VM_GET_TLOCAL | Core |
0x1A | VM_IF_CONST | Control Flow |
0x1B | VM_ASM | Misc |
0x1C | VM_RATE_LIMIT_CONST | Control Flow |
0x23 | VM_INIT_RNG | Random |
0x24 | VM_RAND | Random |
0x25 | VM_LOCK | Threading |
0x26 | VM_UNLOCK | Threading |
0x27 | VM_RAISE | Exceptions |
0x28 | VM_SET_INDIRECT | Core |
0x29 | VM_GET_INDIRECT | Core |
0x2A | VM_TEST_TERMINATE | Misc |
0x2B | VM_POLL_LOADED | Misc |
0x2C | VM_PUSH_REFERENCE | Core |
0x2D | VM_CALL_NATIVE | Subroutines |
0x2E | VM_SAVE_PEEK | Save/Load |
0x2F | VM_SAVE_CLEAR | Save/Load |
0x30 | VM_ACTOR_MOVE_TO | Actors |
0x31 | VM_ACTOR_ACTIVATE | Actors |
0x32 | VM_ACTOR_SET_DIR | Actors |
0x33 | VM_ACTOR_DEACTIVATE | Actors |
0x34 | VM_ACTOR_SET_ANIM | Actors |
0x35 | VM_ACTOR_SET_POS | Actors |
0x36 | VM_ACTOR_EMOTE | Actors |
0x37 | VM_ACTOR_SET_BOUNDS | Actors |
0x38 | VM_ACTOR_SET_SPRITESHEET | Actors |
0x39 | VM_ACTOR_REPLACE_TILE | Actors |
0x3A | VM_ACTOR_GET_POS | Actors |
0x3C | VM_ACTOR_GET_DIR | Actors |
0x3D | VM_ACTOR_SET_ANIM_TICK | Actors |
0x3E | VM_ACTOR_SET_MOVE_SPEED | Actors |
0x3F | VM_ACTOR_SET_FLAGS | Actors |
0x40 | VM_LOAD_TEXT | UI/Text |
0x41 | VM_DISPLAY_TEXT / VM_DISPLAY_TEXT_EX | UI/Text |
0x42 | VM_OVERLAY_SETPOS | UI/Overlay |
0x43 | VM_LOAD_TEXT_EX | UI/Text |
0x44 | VM_OVERLAY_WAIT | UI/Overlay |
0x45 | VM_OVERLAY_MOVE_TO | UI/Overlay |
0x46 | VM_OVERLAY_SHOW | UI/Overlay |
0x47 | VM_OVERLAY_CLEAR | UI/Overlay |
0x48 | VM_CHOICE | UI/Menu |
0x4B | VM_SET_FONT | UI/Text |
0x4C | VM_OVERLAY_SET_SUBMAP_EX | UI/Overlay |
0x4D | VM_OVERLAY_SCROLL | UI/Overlay |
0x4E | VM_OVERLAY_SET_SCROLL | UI/Overlay |
0x4F | VM_OVERLAY_SET_SUBMAP | UI/Overlay |
0x50 | VM_LOAD_TILESET | Hardware |
0x51 | VM_SET_SPRITE_VISIBLE | Hardware |
0x52 | VM_INPUT_WAIT | Input |
0x53 | VM_INPUT_ATTACH | Input |
0x54 | VM_INPUT_GET | Input |
0x55 | VM_CONTEXT_PREPARE | Threading |
0x56 | VM_OVERLAY_SET_MAP | UI/Overlay |
0x57 | VM_FADE | Fade |
0x58 | VM_TIMER_PREPARE | Timers |
0x59 | VM_TIMER_SET | Timers |
0x5A | VM_GET_TILE_XY | Hardware |
0x5B | VM_REPLACE_TILE | Hardware |
0x5C | VM_POLL | Input |
0x5D | VM_SET_SPRITE_MODE | Hardware |
0x5E | VM_REPLACE_TILE_XY | Hardware |
0x5F | VM_INPUT_DETACH | Input |
0x60 | VM_MUSIC_PLAY | Sound |
0x61 | VM_MUSIC_STOP | Sound |
0x62 | VM_MUSIC_MUTE | Sound |
0x63 | VM_SOUND_MASTERVOL | Sound |
0x65 | VM_MUSIC_ROUTINE | Sound |
0x66 | VM_SFX_PLAY | Sound |
0x67 | VM_MUSIC_SETPOS | Sound |
0x68 | VM_SCENE_PUSH | Scenes |
0x69 | VM_SCENE_POP | Scenes |
0x6A | VM_SCENE_POP_ALL | Scenes |
0x6B | VM_SCENE_STACK_RESET | Scenes |
0x6C | VM_SIO_SET_MODE | Serial I/O |
0x6D | VM_SIO_EXCHANGE | Serial I/O |
0x70 | VM_CAMERA_MOVE_TO | Camera |
0x71 | VM_CAMERA_SET_POS | Camera |
0x72 | VM_TIMER_STOP | Timers |
0x73 | VM_TIMER_RESET | Timers |
0x74 | VM_ACTOR_TERMINATE_UPDATE | Actors |
0x75 | VM_ACTOR_SET_ANIM_FRAME | Actors |
0x76 | VM_MEMSET | Core |
0x77 | VM_MEMCPY | Core |
0x78 | VM_RTC_LATCH | RTC |
0x79 | VM_RTC_GET | RTC |
0x7A | VM_RTC_SET | RTC |
0x7B | VM_RTC_START | RTC |
0x7C | VM_LOAD_PALETTE | Palettes |
0x7E | VM_SGB_TRANSFER | SGB |
0x7F | VM_RUMBLE | Misc |
0x80 | VM_PROJECTILE_LAUNCH | Projectiles |
0x81 | VM_PROJECTILE_LOAD_TYPE | Projectiles |
0x83 | VM_ACTOR_GET_ANIM_FRAME | Actors |
0x84 | VM_ACTOR_SET_ANIM_SET | Actors |
0x85 | VM_SWITCH_TEXT_LAYER | UI/Text |
0x86 | VM_ACTOR_GET_ANGLE | Actors |
0x87 | VM_ACTOR_SET_SPRITESHEET_BY_REF | Actors |
0x88 | VM_ACTOR_MOVE_CANCEL | Actors |
0x89 | VM_SIN_SCALE | Math |
0x8A | VM_COS_SCALE | Math |
0x8B | VM_SET_TEXT_SOUND | Sound |
0x8C | VM_PRINTER_DETECT | GB Printer |
0x8D | VM_PRINT_OVERLAY | GB Printer |
0x8E | VM_ACTOR_BEGIN_UPDATE | Actors |
0x8F | VM_ACTOR_MOVE_TO_INIT | Actors |
0x90 | VM_ACTOR_MOVE_TO_X | Actors |
0x91 | VM_ACTOR_MOVE_TO_Y | Actors |
0x92 | VM_ACTOR_MOVE_TO_XY | Actors |
0x93 | VM_ACTOR_MOVE_TO_SET_DIR_X | Actors |
0x94 | VM_ACTOR_MOVE_TO_SET_DIR_Y | Actors |
0x95 | VM_ACTOR_SET_ANIM_MOVING | Actors |