VM_CALL
is a fundamental GBVM instruction used to call a subroutine (function) within the same memory bank. It is analogous to a function call in traditional programming languages.
Purpose:
VM_CALL
allows you to organize your GBVM scripts into modular, reusable blocks of code. When VM_CALL
is executed, the GBVM:
VM_CALL
onto an internal stack. This is crucial for knowing where to return to after the subroutine finishes.ADDR
(the start of the subroutine).After the subroutine completes its execution (typically by encountering a VM_RET
instruction), the GBVM pops the saved address from the stack and resumes execution from that point. This mechanism enables structured programming and avoids code duplication.
Syntax:
VM_CALL ADDR
ADDR
: The address (label) of the subroutine to be called. This subroutine must reside in the same memory bank as the VM_CALL
instruction.Usage Example: Reusable Dialogue Function
Imagine you have several NPCs in your game, and each time the player interacts with them, a common dialogue sequence needs to play, perhaps with slight variations. You can create a DISPLAY_DIALOGUE
subroutine.
; Main game script
; Player interacts with NPC 1
VM_CALL DISPLAY_DIALOGUE
; ... continue main script after dialogue ...
; Player interacts with NPC 2
VM_CALL DISPLAY_DIALOGUE
; ... continue main script after dialogue ...
; --- Subroutine Definition ---
DISPLAY_DIALOGUE:
; Assume a global variable or a passed argument determines the specific text
VM_LOAD_TEXT DIALOGUE_TEXT_VAR
VM_DISPLAY_TEXT
VM_INPUT_WAIT ; Wait for player input to dismiss dialogue
VM_RET ; Return to where VM_CALL was made
; Dialogue text definitions (example)
DIALOGUE_TEXT_VAR:
.R_REF DIALOGUE_NPC1_GREETING
DIALOGUE_NPC1_GREETING:
.TEXT "Hello, adventurer!"
.TEXT_END
; ... other dialogue texts ...
In this example, VM_CALL DISPLAY_DIALOGUE
is used multiple times. Each time it’s called, the GBVM jumps to the DISPLAY_DIALOGUE
subroutine, executes the dialogue logic, and then returns to the exact point in the main script where it was called. This makes the dialogue logic reusable and easy to manage.
Analogy to other programming languages: This is directly analogous to calling a function or method in almost any programming language:
myFunction();
my_function()
myFunction();
The concept of pushing the return address onto a stack and then jumping to the function’s entry point is a fundamental mechanism for subroutine calls across many architectures and languages.