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:

AliasIndexUsage
.ARG0-1Top of stack / first argument
.ARG1-2Second from top
.ARG2 / .PARAM0-3First function parameter
.ARG3 / .PARAM1-4Second 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.

InstructionParametersDescription
VM_STOPStops execution of the current script context.
VM_PUSH_CONSTVALPushes an INT16 immediate value onto the stack.
VM_PUSH_VALUEIDXPushes the value of a variable onto the stack.
VM_PUSH_VALUE_INDIDXPushes a variable value indirectly — IDX contains the index of the variable to push.
VM_PUSH_REFERENCEIDXTranslates IDX into an absolute index and pushes the result. Converts stack-relative to heap-absolute.
VM_POPNRemoves N values from the top of the stack.
VM_SET_CONSTIDX, VALSets variable IDX to immediate value VAL.
VM_SETIDXA, IDXBCopies variable IDXB into variable IDXA.
VM_SET_INDIRECTIDXA, IDXBAssigns IDXB's value to the variable whose index is stored in IDXA.
VM_GET_INDIRECTIDXA, IDXBReads the variable whose index is in IDXB, stores result in IDXA.
VM_RESERVENReserves (positive) or disposes (negative) N stack slots.
VM_GET_FARIDX, SIZE, BANK, ADDRReads a byte (.GET_BYTE) or word (.GET_WORD) from a far pointer into a variable.
VM_GET_TLOCALIDXA, IDXBGets a thread-local variable. IDXB is the thread-local index.
VM_MEMSETDEST, VALUE, COUNTFills COUNT variables starting at DEST with the value in variable VALUE.
VM_MEMCPYDEST, SOUR, COUNTCopies 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

MacroDescription
.R_INT8 valPush an INT8 constant (sign-extended to 16-bit)
.R_INT16 valPush an INT16 constant
.R_REF varPush the value of a variable
.R_REF_IND varPush variable value indirectly (variable contains index)
.R_REF_SET varPop top of stack and store in variable
.R_REF_SET_IND varPop and store indirectly
.R_REF_MEM type, addrRead C memory at address (.MEM_I8, .MEM_U8, .MEM_I16)
.R_REF_MEM_SET type, addrPop and write to C memory at address
.R_REF_MEM_IND type, varRead C memory at address stored in variable
.R_OPERATOR opApply an operator (see table below)
.R_STOPEnd the RPN block

RPN Operators (Complete List)

CategoryOperatorDescription
Arithmetic.ADDAddition (a + b)
.SUBSubtraction (a - b)
.MULMultiplication (a * b)
.DIVDivision (a / b)
.MODModulo (a % b)
Bitwise.B_ANDBitwise AND
.B_ORBitwise OR
.B_XORBitwise XOR
.B_NOTBitwise NOT (unary)
Logical.ANDLogical AND
.ORLogical OR
.NOTLogical NOT (unary)
Comparison.EQEqual
.NENot equal
.LTLess than
.GTGreater than
.LTELess than or equal
.GTEGreater than or equal
Shift.SHLShift left
.SHRShift right
Math.MINMinimum of two values
.MAXMaximum of two values
.ABSAbsolute value (unary)
.NEGNegate (unary)
.ISQRTInteger square root (unary)
.ATAN2Two-argument arctangent (returns 0-255 angle)
.RNDRandom 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.

InstructionParametersDescription
VM_GET_UINT8IDX, ADDRRead unsigned 8-bit value from WRAM address into variable.
VM_GET_INT8IDX, ADDRRead signed 8-bit value from WRAM address into variable.
VM_GET_INT16IDX, ADDRRead signed 16-bit value from WRAM address into variable.
VM_SET_UINT8ADDR, IDXWrite variable value as unsigned 8-bit to WRAM address.
VM_SET_INT8ADDR, IDXWrite variable value as signed 8-bit to WRAM address.
VM_SET_INT16ADDR, IDXWrite variable value as signed 16-bit to WRAM address.
VM_SET_CONST_INT8ADDR, VALWrite immediate signed 8-bit constant to WRAM address.
VM_SET_CONST_UINT8ADDR, VALWrite immediate unsigned 8-bit constant to WRAM address.
VM_SET_CONST_INT16ADDR, VALWrite 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.

InstructionParametersDescription
VM_JUMPLABELUnconditional jump to a label.
VM_IFCOND, IDXA, IDXB, LABEL, NCompare two variables; jump to LABEL if condition is true. Pop N stack values after.
VM_IF_CONSTCOND, IDXA, B, LABEL, NCompare variable to immediate value; jump if true. Pop N after.
VM_SWITCHIDX, SIZE, NSwitch on variable value. Followed by SIZE .CASE entries. Pop N on exit.
VM_LOOPIDX, LABEL, NLoops while variable IDX is non-zero, jumping to LABEL. Pop N on exit.
VM_RATE_LIMIT_CONSTN, IDX, LABELIf 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:

OperatorValueMeaning
.EQ1Equal
.LT2Less than
.LTE3Less than or equal
.GT4Greater than
.GTE5Greater than or equal
.NE6Not 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

InstructionParametersDescription
VM_CALLADDRCall subroutine by near address (same bank).
VM_RETReturn from near call.
VM_RET_NNReturn from near call and pop N arguments.
VM_CALL_FARBANK, ADDRCall subroutine by far address (cross-bank).
VM_RET_FARReturn from far call.
VM_RET_FAR_NNReturn from far call and pop N arguments.
VM_CALL_NATIVEBANK, PTRCall a native C function. The function receives the SCRIPT_CTX pointer.
VM_INVOKEBANK, ADDR, N, PARAMSInvoke a C function repeatedly until it returns true (blocking). Pop N on completion.

Thread Management

InstructionParametersDescription
VM_LOCKLock the VM — blocks state_update, events_update, timers_update. Prevents context switching.
VM_UNLOCKUnlock the VM. Re-enables blocked updates.
VM_IDLEYield execution for one frame. Signals the thread is in a waitable state.
VM_STOPStop the current script context.
VM_BEGINTHREADBANK, PROC, HTHREAD, NARGSSpawn a new thread. HTHREAD receives the handle. NARGS values are copied from the current stack.
VM_JOINIDXWait for thread IDX to complete (blocking).
VM_TERMINATEIDXKill thread by handle.
VM_CONTEXT_PREPARESLOT, BANK, ADDRAssign 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

InstructionParametersDescription
VM_RAISECODE, SIZERaise 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

InstructionParametersDescription
VM_POLL_LOADEDIDXCheck if VM state was restored from save. Resets the restore flag.
VM_TEST_TERMINATEFLAGSTerminate unit testing. .TEST_WAIT_VBL waits for VBlank first.

Random Numbers

InstructionParametersDescription
VM_INIT_RNGIDXInitialize RNG seed from the value in variable IDX.
VM_RANDOMIZEInitialize RNG seed from hardware DIV register and game_time (macro).
VM_RANDIDX, MIN, LIMITStore 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

InstructionParametersDescription
VM_ACTOR_SET_POSIDXSet actor position. Pseudo-struct: [ID, X, Y] at IDX.
VM_ACTOR_GET_POSIDXGet actor position into pseudo-struct: [ID, X, Y] at IDX.
VM_ACTOR_MOVE_TOIDXSmoothly move actor (blocking). Pseudo-struct: [ID, X, Y, ATTR]. Legacy — prefer INIT + XY pattern.
VM_ACTOR_MOVE_TO_INITIDX, ATTRInitialize smooth movement. Pseudo-struct: [ID, X, Y]. ATTR controls collision/diagonal/snap.
VM_ACTOR_MOVE_TO_XIDX, ATTRMove actor along X-axis only (blocking).
VM_ACTOR_MOVE_TO_YIDX, ATTRMove actor along Y-axis only (blocking).
VM_ACTOR_MOVE_TO_XYIDX, ATTRMove actor along both axes simultaneously (blocking).
VM_ACTOR_MOVE_TO_SET_DIR_XIDXFace actor toward X destination (no movement).
VM_ACTOR_MOVE_TO_SET_DIR_YIDXFace actor toward Y destination (no movement).
VM_ACTOR_SET_ANIM_MOVINGIDXSet actor to moving animation for current direction.
VM_ACTOR_MOVE_CANCELACTORCancel any in-progress movement.

Movement Attributes

FlagValueDescription
.ACTOR_ATTR_H_FIRST0x01Move horizontal before vertical
.ACTOR_ATTR_CHECK_COLL_WALLS0x02Check wall collisions
.ACTOR_ATTR_DIAGONAL0x04Allow diagonal movement
.ACTOR_ATTR_RELATIVE_SNAP_PX0x08Coordinates are relative, in pixels
.ACTOR_ATTR_RELATIVE_SNAP_TILE0x10Coordinates are relative, in tiles
.ACTOR_ATTR_CHECK_COLL_ACTORS0x20Check actor-to-actor collisions
.ACTOR_ATTR_CHECK_COLL0x22Check both wall and actor collisions

Activation & Visibility

InstructionParametersDescription
VM_ACTOR_ACTIVATEACTORActivate an actor (add to active list, start rendering).
VM_ACTOR_DEACTIVATEACTORDeactivate an actor. Sets ACTOR_FLAG_DISABLED to prevent re-activation by streaming.
VM_ACTOR_SET_HIDDENACTOR, HIDDENShow (.ACTOR_VISIBLE) or hide (.ACTOR_HIDDEN) an actor. Macro wrapping VM_ACTOR_SET_FLAGS.

Direction & Animation

InstructionParametersDescription
VM_ACTOR_SET_DIRACTOR, DIRSet actor facing. .DIR_DOWN(0), .DIR_RIGHT(1), .DIR_UP(2), .DIR_LEFT(3).
VM_ACTOR_GET_DIRIDX, DESTGet actor direction into DEST.
VM_ACTOR_GET_ANGLEIDX, DESTGet actor movement angle (0-255) into DEST.
VM_ACTOR_SET_ANIMACTOR, ANIMSet actor animation state (e.g. idle, walking).
VM_ACTOR_SET_ANIM_SETACTOR, OFFSETSet actor animation set number.
VM_ACTOR_SET_ANIM_FRAMEACTORSet animation frame. Pseudo-struct: [ID, FRAME] at ACTOR.
VM_ACTOR_GET_ANIM_FRAMEACTORGet animation frame. Pseudo-struct: [ID, FRAME] at ACTOR.
VM_ACTOR_SET_ANIM_TICKACTOR, TICKSet animation tick speed. 255 = ANIM_PAUSED (stops auto-advance).
VM_ACTOR_SET_MOVE_SPEEDACTOR, SPEEDSet actor movement speed in subpixels per frame.

Properties & Flags

InstructionParametersDescription
VM_ACTOR_SET_FLAGSACTOR, FLAGS, MASKSet/clear actor flags by bitmask.
VM_ACTOR_SET_COLL_ENABLEDACTOR, ENABLEDEnable/disable actor collision. Macro.
VM_ACTOR_SET_BOUNDSIDXSet collision bounds. Pseudo-struct: [ID, LEFT, RIGHT, TOP, BOTTOM].
VM_ACTOR_SET_SPRITESHEETACTOR, BANK, SHEETChange actor spritesheet by far pointer.
VM_ACTOR_SET_SPRITESHEET_BY_REFACTOR, FAR_PTRChange spritesheet using variables. Pseudo-struct: [BANK, DATA] at FAR_PTR.
VM_ACTOR_REPLACE_TILEACTOR, TARGET, BANK, DATA, START, LENReplace tiles within actor's spritesheet in VRAM.
VM_ACTOR_EMOTEACTOR, BANK, AVATARShow an emote bubble above actor.

Actor Flags

FlagValueDescription
.ACTOR_FLAG_PINNED0x01Pin actor to screen (not world coordinates)
.ACTOR_FLAG_HIDDEN0x02Hide actor from rendering
.ACTOR_FLAG_ANIM_NOLOOP0x04Stop animation at last frame
.ACTOR_FLAG_COLLISION0x08Enable collision detection
.ACTOR_FLAG_PERSISTENT0x10Persist across scene changes

Update Scripts

InstructionParametersDescription
VM_ACTOR_BEGIN_UPDATEACTORBegin an actor's update script (runs every frame via script_runner_update).
VM_ACTOR_TERMINATE_UPDATEACTORStop 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

InstructionParametersDescription
VM_CAMERA_MOVE_TOIDX, SPEED, AFTER_LOCKSmoothly move camera to position (blocking). Pseudo-struct: [X, Y] at IDX. SPEED controls movement rate.
VM_CAMERA_SET_POSIDXInstantly set camera position. Pseudo-struct: [X, Y] at IDX.

Camera Lock Flags

FlagValueDescription
.CAMERA_UNLOCK0b00000000Camera follows player
.CAMERA_LOCK_X0b00000001Lock X-axis position
.CAMERA_LOCK_Y0b00000010Lock Y-axis position
.CAMERA_LOCK0b00000011Lock both axes
.CAMERA_LOCK_X_MIN0b00000100Clamp X minimum
.CAMERA_LOCK_X_MAX0b00001000Clamp X maximum
.CAMERA_LOCK_Y_MIN0b00010000Clamp Y minimum
.CAMERA_LOCK_Y_MAX0b00100000Clamp 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

InstructionParametersDescription
VM_SCENE_PUSHPush the current scene onto the scene stack (max depth: 8).
VM_SCENE_POPPop and load the last scene from the stack.
VM_SCENE_POP_ALLPop all scenes and load the first (bottom) one.
VM_SCENE_STACK_RESETClear 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

InstructionParametersDescription
VM_LOAD_TEXTNARGSLoad text string into memory. Followed by optional .dw variable list and .asciz string.
VM_LOAD_TEXT_EXNLoad text with parameters from stack (varargs). Pop N after.
VM_DISPLAY_TEXTRender loaded text in overlay (obsolete macro, uses defaults).
VM_DISPLAY_TEXT_EXOPTIONS, START_TILERender text with options. .DISPLAY_PRESERVE_POS preserves cursor. .TEXT_TILE_CONTINUE (0xFF) continues from current position.
VM_SET_FONTFONT_INDEXSet active font for text rendering.
VM_SET_PRINT_DIRDIRECTIONSet print direction: .UI_PRINT_LEFTTORIGHT or .UI_PRINT_RIGHTTOLEFT.
VM_SWITCH_TEXT_LAYERLAYERSwitch text output: .TEXT_LAYER_BKG (background) or .TEXT_LAYER_WIN (overlay).
VM_SET_TEXT_SOUNDBANK, ADDR, MASKSet sound effect for text output.

Text Format Specifiers

SpecifierDescription
%dRender variable value as decimal number
%DnRender variable value with n-digit width
%cRender character from variable value

Text Escape Sequences

SequenceDescription
\001\xSet text speed (x = 1-8, frames = 2^(x-2))
\002\xSet text font
\003\x\ySet cursor position (absolute)
\004\x\ySet cursor position (relative to last char)
\005Escape the next character
\006\maskWait for input before continuing
\007\nInvert colors (\002 = on, \001 = off)
\010\xPrint direction (01 = LTR, 02 = RTL)
\011Zero-width symbol
\nNext line
\013\xSet UI palette number
\rScroll text one line up

Overlay Window

InstructionParametersDescription
VM_OVERLAY_SHOWX, Y, COLOR, OPTIONSShow overlay. COLOR: .UI_COLOR_BLACK/.UI_COLOR_WHITE. OPTIONS: .UI_DRAW_FRAME, .UI_AUTO_SCROLL.
VM_OVERLAY_HIDEHide overlay (moves to Y = .MENU_CLOSED_Y).
VM_OVERLAY_SETPOSX, YSet overlay position instantly (in tiles).
VM_OVERLAY_MOVE_TOX, Y, SPEEDAnimate overlay to new position. Speeds: .OVERLAY_IN_SPEED, .OVERLAY_OUT_SPEED, .OVERLAY_SPEED_INSTANT.
VM_OVERLAY_CLEARX, Y, W, H, COLOR, OPTIONSClear a rectangular area of the overlay.
VM_OVERLAY_SCROLLX, Y, W, H, COLORScroll a rectangular area of the overlay up by one row.
VM_OVERLAY_SET_SCROLLX, Y, W, H, COLORDefine automatic scroll area for text overflow.
VM_OVERLAY_WAITIS_MODAL, WAIT_FLAGSWait for overlay operations to complete.
VM_OVERLAY_SET_MAPIDX, X, Y, BANK, BKGCopy a tilemap to overlay at a tile position.
VM_OVERLAY_SET_SUBMAPX, Y, W, H, SX, SYCopy a rectangular area from the scene background to overlay.
VM_OVERLAY_SET_SUBMAP_EXPARAMS_IDXExtended submap copy using pseudo-struct: [x, y, w, h, scene_x, scene_y].

Overlay Wait Flags

FlagValueDescription
.UI_WAIT_NONE0No wait
.UI_WAIT_WINDOW1Wait for window animation to finish
.UI_WAIT_TEXT2Wait for text rendering to finish
.UI_WAIT_BTN_A4Wait for A button press
.UI_WAIT_BTN_B8Wait for B button press
.UI_WAIT_BTN_ANY16Wait for any button press

Menu / Choice

InstructionParametersDescription
VM_CHOICEIDX, OPTIONS, COUNTExecute 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.

InstructionParametersDescription
VM_LOAD_TILESETIDX, BANK, BKGLoad tileset into VRAM starting at tile ID IDX.
VM_REPLACE_TILETARGET, BANK, DATA, START, LENReplace LEN background tiles starting at TARGET with tiles from a tileset.
VM_REPLACE_TILE_XYX, Y, BANK, DATA, STARTReplace a single background tile at position (X, Y).
VM_GET_TILE_XYTILE_IDX, X_IDX, Y_IDXGet the tile ID at background position (X, Y).
VM_SET_SPRITE_VISIBLEMODEShow (.SPRITES_SHOW) or hide (.SPRITES_HIDE) all sprites. Has priority over per-actor visibility.
VM_SHOW_SPRITESMacro for VM_SET_SPRITE_VISIBLE .SPRITES_SHOW.
VM_HIDE_SPRITESMacro for VM_SET_SPRITE_VISIBLE .SPRITES_HIDE.
VM_SET_SPRITE_MODEMODESet sprite size: .MODE_8X8 or .MODE_8X16.

Input

InstructionParametersDescription
VM_INPUT_WAITMASKWait until specified input buttons are pressed (blocking).
VM_INPUT_ATTACHMASK, SLOTAttach a prepared script (from VM_CONTEXT_PREPARE) to input buttons. .OVERRIDE_DEFAULT (0x80) overrides default input handling.
VM_INPUT_DETACHMASKRemove attached input script.
VM_INPUT_GETIDX, JOYIDGet current joypad state. .JOY0 through .JOY3 (SGB multi-player).
VM_POLLIDX_EVENT, IDX_VALUE, MASKWait for input (.POLL_EVENT_INPUT) or music routine (.POLL_EVENT_MUSIC) event.

Timers

Timers fire every INTERVAL * 16 frames (checked in timers_update when game_time & 0x0F == 0).

InstructionParametersDescription
VM_TIMER_PREPARETIMER, BANK, ADDRLoad a script into a timer slot.
VM_TIMER_SETTIMER, INTERVALStart timer, calling every INTERVAL * 16 frames.
VM_TIMER_STOPTIMERStop a running timer.
VM_TIMER_RESETTIMERReset 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

InstructionParametersDescription
VM_FADEFLAGSFade screen. Combine: .FADE_IN/.FADE_OUT + .FADE_MODAL/.FADE_NONMODAL.
VM_FADE_INIS_MODALFade in (macro). 1 = modal (blocking), 0 = nonmodal.
VM_FADE_OUTIS_MODALFade 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

InstructionParametersDescription
VM_MUSIC_PLAYBANK, ADDR, LOOPStart playing a music track. LOOP parameter is obsolete (has no effect).
VM_MUSIC_STOPStop playing music.
VM_MUSIC_MUTEMASKMute/unmute channels. Bits: .MUTE_CH1(1), .MUTE_CH2(2), .MUTE_CH3(4), .MUTE_CH4(8).
VM_MUSIC_ROUTINEROUTINE, BANK, ADDRAttach script to music event routine (0-3).
VM_MUSIC_SETPOSPATTERN, ROWSet playback position in current song.
VM_SFX_PLAYBANK, ADDR, MASK, PRIOPlay sound effect. Priority: .SFX_PRIORITY_MINIMAL(0), .SFX_PRIORITY_NORMAL(4), .SFX_PRIORITY_HIGH(8).
VM_SOUND_MASTERVOLVOLSet master volume.

Channel Mute Aliases

AliasValueChannel
.MUTE_CH1 / .MUTE_DUTY11Pulse 1 (Duty)
.MUTE_CH2 / .MUTE_DUTY22Pulse 2 (Duty)
.MUTE_CH3 / .MUTE_WAVE4Wave
.MUTE_CH4 / .MUTE_NOISE8Noise

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

InstructionParametersDescription
VM_LOAD_PALETTEMASK, OPTIONSLoad palettes. MASK is a bitmask of which palettes (0-7). OPTIONS: .PALETTE_COMMIT, .PALETTE_BKG, .PALETTE_SPRITE. Followed by palette data.

Palette Data Macros

MacroParametersDescription
.DMG_PALCOL1, COL2, COL3, COL4Define a DMG palette (4 shades, 0-3).
.CGB_PALR1,G1,B1 R2,G2,B2 R3,G3,B3 R4,G4,B4Define 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

InstructionParametersDescription
VM_SAVE_PEEKRES, DEST, SOUR, COUNT, SLOTRead COUNT variables from save slot without loading the full state. RES = result (success/fail).
VM_SAVE_CLEARSLOTErase data in a save slot.

Full save/load operations use VM_RAISE with EXCEPTION_SAVE (3) or EXCEPTION_LOAD (4).

Math Functions

InstructionParametersDescription
VM_SIN_SCALEIDX, IDX_ANGLE, SCALECompute scaled sine. IDX = scale factor (multiplied into result) and target variable. SCALE = accuracy 0-7.
VM_COS_SCALEIDX, IDX_ANGLE, SCALECompute scaled cosine. Same parameter pattern as VM_SIN_SCALE.

Angle system: 0 = up, 64 = right, 128 = down, 192 = left. Full circle = 256 steps.

Projectiles

InstructionParametersDescription
VM_PROJECTILE_LOAD_TYPEDEST_TYPE, SRC_TYPE, BANK, ADDRLoad projectile data into a slot.
VM_PROJECTILE_LAUNCHTYPE, IDXLaunch a projectile from a slot. Pseudo-struct at IDX: [pos.x, pos.y, angle].

Serial I/O (Link Cable)

InstructionParametersDescription
VM_SIO_SET_MODEMODESet serial mode: .SIO_MODE_NONE(0), .SIO_MODE_MASTER(1), .SIO_MODE_SLAVE(2).
VM_SIO_EXCHANGESOUR, DEST, SIZEExchange SIZE bytes via serial link.

Real-Time Clock

InstructionParametersDescription
VM_RTC_LATCHLatch current RTC value for reading.
VM_RTC_GETIDX, WHATRead RTC value: .RTC_SECONDS, .RTC_MINUTES, .RTC_HOURS, .RTC_DAYS.
VM_RTC_SETIDX, WHATWrite RTC value.
VM_RTC_STARTSTARTStart (.RTC_START) or stop (.RTC_STOP) the RTC.

Super Game Boy

InstructionParametersDescription
VM_SGB_TRANSFERTransfer SGB packet(s). Variable-length data follows the instruction (16-byte packet multiples).

Miscellaneous

InstructionParametersDescription
VM_RUMBLEENABLEEnable (1) or disable (0) rumble on supported carts.
VM_ASMBegin inline native (Z80) assembly. End with VM_ENDASM.
VM_ENDASMEnd inline native assembly block (pops HL, restarts VM).
VM_PRINTER_DETECTERROR, DELAYDetect GB Printer. ERROR receives result, DELAY = timeout.
VM_PRINT_OVERLAYERROR, START, HEIGHT, MARGINPrint 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.

OpcodeInstructionSection
0x00VM_STOPCore
0x01VM_PUSH_CONSTCore
0x02VM_POPCore
0x04VM_CALLSubroutines
0x05VM_RET / VM_RET_NSubroutines
0x06VM_GET_FARCore
0x07VM_LOOPControl Flow
0x08VM_SWITCHControl Flow
0x09VM_JUMPControl Flow
0x0AVM_CALL_FARSubroutines
0x0BVM_RET_FAR / VM_RET_FAR_NSubroutines
0x0DVM_INVOKESubroutines
0x0EVM_BEGINTHREADThreading
0x0FVM_IFControl Flow
0x10VM_PUSH_VALUE_INDCore
0x11VM_PUSH_VALUECore
0x12VM_RESERVECore
0x13VM_SETCore
0x14VM_SET_CONSTCore
0x15VM_RPNRPN Calculator
0x16VM_JOINThreading
0x17VM_TERMINATEThreading
0x18VM_IDLEThreading
0x19VM_GET_TLOCALCore
0x1AVM_IF_CONSTControl Flow
0x1BVM_ASMMisc
0x1CVM_RATE_LIMIT_CONSTControl Flow
0x23VM_INIT_RNGRandom
0x24VM_RANDRandom
0x25VM_LOCKThreading
0x26VM_UNLOCKThreading
0x27VM_RAISEExceptions
0x28VM_SET_INDIRECTCore
0x29VM_GET_INDIRECTCore
0x2AVM_TEST_TERMINATEMisc
0x2BVM_POLL_LOADEDMisc
0x2CVM_PUSH_REFERENCECore
0x2DVM_CALL_NATIVESubroutines
0x2EVM_SAVE_PEEKSave/Load
0x2FVM_SAVE_CLEARSave/Load
0x30VM_ACTOR_MOVE_TOActors
0x31VM_ACTOR_ACTIVATEActors
0x32VM_ACTOR_SET_DIRActors
0x33VM_ACTOR_DEACTIVATEActors
0x34VM_ACTOR_SET_ANIMActors
0x35VM_ACTOR_SET_POSActors
0x36VM_ACTOR_EMOTEActors
0x37VM_ACTOR_SET_BOUNDSActors
0x38VM_ACTOR_SET_SPRITESHEETActors
0x39VM_ACTOR_REPLACE_TILEActors
0x3AVM_ACTOR_GET_POSActors
0x3CVM_ACTOR_GET_DIRActors
0x3DVM_ACTOR_SET_ANIM_TICKActors
0x3EVM_ACTOR_SET_MOVE_SPEEDActors
0x3FVM_ACTOR_SET_FLAGSActors
0x40VM_LOAD_TEXTUI/Text
0x41VM_DISPLAY_TEXT / VM_DISPLAY_TEXT_EXUI/Text
0x42VM_OVERLAY_SETPOSUI/Overlay
0x43VM_LOAD_TEXT_EXUI/Text
0x44VM_OVERLAY_WAITUI/Overlay
0x45VM_OVERLAY_MOVE_TOUI/Overlay
0x46VM_OVERLAY_SHOWUI/Overlay
0x47VM_OVERLAY_CLEARUI/Overlay
0x48VM_CHOICEUI/Menu
0x4BVM_SET_FONTUI/Text
0x4CVM_OVERLAY_SET_SUBMAP_EXUI/Overlay
0x4DVM_OVERLAY_SCROLLUI/Overlay
0x4EVM_OVERLAY_SET_SCROLLUI/Overlay
0x4FVM_OVERLAY_SET_SUBMAPUI/Overlay
0x50VM_LOAD_TILESETHardware
0x51VM_SET_SPRITE_VISIBLEHardware
0x52VM_INPUT_WAITInput
0x53VM_INPUT_ATTACHInput
0x54VM_INPUT_GETInput
0x55VM_CONTEXT_PREPAREThreading
0x56VM_OVERLAY_SET_MAPUI/Overlay
0x57VM_FADEFade
0x58VM_TIMER_PREPARETimers
0x59VM_TIMER_SETTimers
0x5AVM_GET_TILE_XYHardware
0x5BVM_REPLACE_TILEHardware
0x5CVM_POLLInput
0x5DVM_SET_SPRITE_MODEHardware
0x5EVM_REPLACE_TILE_XYHardware
0x5FVM_INPUT_DETACHInput
0x60VM_MUSIC_PLAYSound
0x61VM_MUSIC_STOPSound
0x62VM_MUSIC_MUTESound
0x63VM_SOUND_MASTERVOLSound
0x65VM_MUSIC_ROUTINESound
0x66VM_SFX_PLAYSound
0x67VM_MUSIC_SETPOSSound
0x68VM_SCENE_PUSHScenes
0x69VM_SCENE_POPScenes
0x6AVM_SCENE_POP_ALLScenes
0x6BVM_SCENE_STACK_RESETScenes
0x6CVM_SIO_SET_MODESerial I/O
0x6DVM_SIO_EXCHANGESerial I/O
0x70VM_CAMERA_MOVE_TOCamera
0x71VM_CAMERA_SET_POSCamera
0x72VM_TIMER_STOPTimers
0x73VM_TIMER_RESETTimers
0x74VM_ACTOR_TERMINATE_UPDATEActors
0x75VM_ACTOR_SET_ANIM_FRAMEActors
0x76VM_MEMSETCore
0x77VM_MEMCPYCore
0x78VM_RTC_LATCHRTC
0x79VM_RTC_GETRTC
0x7AVM_RTC_SETRTC
0x7BVM_RTC_STARTRTC
0x7CVM_LOAD_PALETTEPalettes
0x7EVM_SGB_TRANSFERSGB
0x7FVM_RUMBLEMisc
0x80VM_PROJECTILE_LAUNCHProjectiles
0x81VM_PROJECTILE_LOAD_TYPEProjectiles
0x83VM_ACTOR_GET_ANIM_FRAMEActors
0x84VM_ACTOR_SET_ANIM_SETActors
0x85VM_SWITCH_TEXT_LAYERUI/Text
0x86VM_ACTOR_GET_ANGLEActors
0x87VM_ACTOR_SET_SPRITESHEET_BY_REFActors
0x88VM_ACTOR_MOVE_CANCELActors
0x89VM_SIN_SCALEMath
0x8AVM_COS_SCALEMath
0x8BVM_SET_TEXT_SOUNDSound
0x8CVM_PRINTER_DETECTGB Printer
0x8DVM_PRINT_OVERLAYGB Printer
0x8EVM_ACTOR_BEGIN_UPDATEActors
0x8FVM_ACTOR_MOVE_TO_INITActors
0x90VM_ACTOR_MOVE_TO_XActors
0x91VM_ACTOR_MOVE_TO_YActors
0x92VM_ACTOR_MOVE_TO_XYActors
0x93VM_ACTOR_MOVE_TO_SET_DIR_XActors
0x94VM_ACTOR_MOVE_TO_SET_DIR_YActors
0x95VM_ACTOR_SET_ANIM_MOVINGActors