Learning GBVM

GBVM (Game Boy Virtual Machine) is the core of GB Studio 3’s powerful tools. While it’s entirely possible to make an excellent game in GB Studio without GBVM, knowing how to use it unlocks a lot of potential (like Animating Background Tiles) for more advanced game development. We did an in depth explainer into how GBVM works in the backend, and now it’s time to detail how a GB Studio user can learn to code with GBVM Script.

The GBVM Script Event

While it’s possible to use GBVM in other ways (more on that later), most users will take advantage of it using a [GBVM Script] event. There are no parameters or options, just a big empty box for you to type in the commands. There is no limit to how many characters you can use in one script, so there’s no requirement to split up commands into separate events. However, depending on how you intend to use and debug your scripts, it may be worthwhile to split up the different parts of the code for organization’s sake. It’s also possible to go all in with GBVM and code almost everything with it, but some math events and other commands are easier and more practical to execute with the “stock” events in GB Studio.

The GBVM Script event

The GBVM Syntax

Mimicking Assembly language, GBVM is fairly relaxed with syntax (at least compared to other programming languages I’ve used). Here are some of the basics to keep in mind when using GBVM for the first time.

Comments are denoted with a semicolon ( ; ) and any characters that appear after one in a line are ignored by the compiler. Use comments to break up and mark down your code and leave yourself notes to make it easier to read and debug later.

Code is executed line by line, and each line of code is ended with a line break. When using GB Studio, the text wrapping can make it appear to be multiple lines, but only a line break will end the current instruction. Accidentally hitting return/enter on your keyboard mid command and adding a line break will cause an error when it comes to compiling.

All GBVM commands start with the prefix VM_ followed by the command name. Commands typically follow a “Action, Where, What” logic, but certain commands also allow for extra parameters.

There’s a few other neat aspects of GBVM, but that’s all you need to know for now.

So where does one start when wanting to learn GBVM? Here’s a few different ways you can do that.

Tutorials

This may seem obvious, but there are quite a few tutorials already out there thanks to the efforts of the community. We released the Animating Background Tiles article as a teaser for what GBVM can do, and there are some other great ones on Itch, GitHub and on GB Studio’s Discord that can be found. If you have a question about GBVM, there’s a specific channel on the Discord where you can ask and get help, and we’ve seen some impressive stuff come out of discussions there.

Source Code

All of GBVM’s instruction set can be found at https://github.com/chrismaltby/gbvm/blob/master/include/vm.i – this is what’s used to actually build the GBVM code when GB Studio is compiled into an app. There’s not a lot of explanation on how the commands work, but brief descriptions do give a good start. A more detailed list of commands can also be found at https://gist.github.com/pau-tomas/92b0ad77506088d184a654af226f5b7d thanks to Pautomas. That list is a work in progress, but the explanation of how many commands work is an excellent start.

Exporting Game Data

This is my preferred way to learn GBVM. In the menu bar, select Game > Advanced > Export Project Data. This will take all the information, scripts and code that’s in your game and export it into the GBVM intermediate code that’s actually used to build your ROM. If you already have a complex game with multiple scenes and scripts, this will most likely look like a bunch of gibberish and will be hard to parse.

I recommend starting with a fresh empty project with only one scene and one event. For this example, I made a single scene and added a [Variable Set To ‘True’] event, and selected the Global “Variable 1” for simplicity. After exporting the project data, a folder appears in the Project’s “build” folder called src (stands for “source”). There are two main folders, “include” and “src” and within both are a series of files and folders pertaining to your game.

The “include” folder contains .h files. These are “header” files which contain definitions for the code, and can largely be ignored when learning GBVM. Inside “src” is where you’ll find the interesting stuff. There’s a lot of code to be found here and you can learn a lot about how the Game Boy, GBDK and GB Studio treats commands and variables, but for now we’ll turn our attention to the file named “script_s0_init.s“.

_script_s0_init::        VM_LOCK
        ; Variable Set To True        VM_SET_CONST            VAR_VARIABLE_1, 1
        ; Wait 1 Frame        VM_PUSH_CONST           1        VM_INVOKE               b_wait_frames, _wait_frames, 1, .ARG0
        ; Fade In        VM_SET_CONST_INT8       _fade_frames_per_step, 1        VM_FADE_IN              1
        ; Stop Script        VM_STOP

If it wasn’t apparent, this is the first scene’s script that runs On Init. There’s a bit going on here, but thankfully some helpful comments have been generated to make it easier to parse, and since our Variable Set To True event is the first one that gets executed, it shows up high in the list. This shows one of the simplest commands to use in GBVM. Let’s break it down:

;Variable Set To True

As stated before, this is a comment, and any text that follows the semicolon gets ignored by GB Studio when your game is compiled. This text is for you, the developer to know what’s happening in the code.

VM_SET_CONST

Since this starts with VM_ we know it’s the actual GBVM Command. It ‘sets’ a given variable to a Constant (const) value, that is to say an actual number value and not a pointer to another placeholder or variable.

VAR_VARIABLE_1

Something new! Hopefully this is apparent, but it’s the Variable 1 we selected in the GB Studio event. Global variables are called this way, using the prefix VAR_ and the variable name in all caps, substituting spaces with underscores.

1

The value that the variable is set to. In GB Studio, all variables start with the value 0 which gets interpreted as False when using an “If” event, and any positive number is interpreted as True. When setting a variable to True, it simply sets it to 1.

Neat, eh? So what can we do with this information? Let’s try using this command into a GBVM Script event in GB Studio and see how it behaves. Add a [GBVM Script] event at the end of your On Init script. You can then either type out everything yourself, or simply copy and paste those lines into the event.

A space is needed between the command and parameters, but otherwise whitespace is ignored so feel free to add or remove spaces to your liking to make it easier to read. Remember that text after the semicolon is ignored, so the Command needs to be on a new line. I’ve left the comment in there to make it easier for myself. This command doesn’t do much by itself, so add a [Display Dialogue] event to confirm that it’s functioning. Typing in a dollar sign ($) followed by a variable name the text window will bring up a drop down, select “Variable 1” to display its value. I like to write it out fully as “Variable 1 = $Variable 1” so that it is clearly labeled when it’s displayed.

It works!

Sweet! Our GBVM script is working with no errors. If you do see one appear in the build window when it’s compiling, check your spelling and spacing/line breaks.

Let’s see if we can replicate the code with a different variable and value for a different result. I’ll keep adding lines of code to the current GBVM script event instead of adding a new one. This time, let’s change Variable 2 to the value of 35, just so we can see some double digits.

        ; Set Variable 2 to 35
        VM_SET_CONST            VAR_VARIABLE_2, 35

To confirm that it’s working, I’ll add another line of text to the Display Dialogue event, “Variable 2 = $Variable 2”.

Feels great when the result is expecteed.

Woot! It worked as expected. Notice that we’ve been doing everything within GB Studio events? The Exported Game Data does not work backwards, so you cannot edit code there and expect those changes to be reflected within your game. It may be possible in a future version, but for now the Export Data is a way for you to see what’s going under the hood of your game when you add an event and inspect other aspects of the code.

You can use Export Project Source and compile it yourself into a ROM, but that’s beyond the scope of this tutorial and moves beyond working with GB Studio – although it’s also possible to combine those exported data files with other scripts and tools outside of GB Studio, that will have to wait for another day. Let’s try exporting the Game Data again and see what’s changed since we’ve added these events.

        ; Variable Set To True
        VM_SET_CONST            VAR_VARIABLE_1, 1

        ; Variable Set To True
            VM_SET_CONST VAR_VARIABLE_1, 1
       
        ; Set Variable 2 to 35
            VM_SET_CONST            VAR_VARIABLE_2, 35
       

        ; Text Dialogue
        VM_LOAD_TEXT            2
        .dw VAR_VARIABLE_1, VAR_VARIABLE_2
        .asciz "Variable 1 = %d\nVariable 2 = %d"
        VM_OVERLAY_CLEAR        0, 0, 20, 4, .UI_COLOR_WHITE, ^/(.UI_AUTO_SCROLL | .UI_DRAW_FRAME)/
        VM_OVERLAY_MOVE_TO      0, 14, .OVERLAY_IN_SPEED
        VM_DISPLAY_TEXT
        VM_OVERLAY_WAIT         .UI_MODAL, ^/(.UI_WAIT_WINDOW | .UI_WAIT_TEXT | .UI_WAIT_BTN_A)/
        VM_OVERLAY_MOVE_TO      0, 18, .OVERLAY_OUT_SPEED
        VM_OVERLAY_WAIT         .UI_MODAL, ^/(.UI_WAIT_WINDOW | .UI_WAIT_TEXT)/

        ; Stop Script
        VM_STOP

Conveniently, GBVM Script events get put into the Game Data verbatim, another reason to comment your code well. Also notice that the original “Variable Set To True” Event is still present at the top of the script, which has now become redundant. But wow, that’s a lot of lines of code for what seems like a simple dialogue window. It is possible to take that code, copy and paste it into a GBVM Script and edit some of the lines to display what you want, but in this scenario is it worth it for the result? I would argue not, and using the GBVM event makes more sense. You’ll often find other events like Math Expressions that require many more lines of code In GBVM as opposed to a single event in GB Studio. So why use GBVM?

Why Use GBVM?

It turns out there are a number of features within GB Studio and GBVM that don’t have an event or interface to call on. We already showed how Background Tiles can be swapped using GBVM, and the reason it’s not available as a “stock” event is due to the challenge in representing all that data in an easy to use event interface. The development team behind GB Studio has opted so far to provide a more approachable experience for beginners than overcomplicating things. Those who wish to explore more advanced tools have the ability to do so with GBVM Scripts. However, even in a simple scenario like above, you could see the benefit in using GBVM for setting a complex or large number of Variables. Instead of many Variable events, you could have one GBVM Script with many lines of (hopefully well commented) code.

There’s a tonne more to learn about GBVM, including other commands that are exclusive to it and how they can be used, but we’d rather create actionable tutorials than abstract concepts and theory. Expect more tutorials from us in the future that take advantage of GBVM. In the meantime, try out GBVM for yourself and maybe play with exporting Data to see how events translate and what you can do with it. Happy coding!

Liked it? Take a second to support GB Studio Central on Patreon!
Become a patron at Patreon!