All docs

Compiler

The 9-phase Rust compiler pipeline, multibank support, EPROM programmer, and project file format.

Vectrex Studio has two compiler backends selectable from the IDE Settings panel. Buildtools is recommended for all new projects. The Core backend is deprecated.


Backend 1 — Core (Deprecated)

Status: ⚠️ DEPRECATED — maintenance mode, no new features

Use Buildtools for all new projects. See the migration note at the bottom of this page.

Single-pass pipeline: lexer → parser → AST → optimizer → codegen → MC6809 assembly → binary. Always outputs a fixed 32 KB ROM. No PDB debug symbol generation.


Backend 2 — Buildtools (Recommended)

Status: ✅ Active — single-bank and multibank, all new features here

A modular multi-crate Rust pipeline with one crate per phase.

PhaseCrateResponsibility
1vpy_loaderLoad .vpyproj project file (TOML)
2vpy_parserParse VPy source to AST
3vpy_unifierMerge multi-file ASTs, resolve imports
4vpy_bank_allocatorAssign functions/data to ROM banks
5vpy_codegenAST → MC6809 assembly (with tree shaking)
6vpy_assemblerMC6809 assembly → machine code (two-pass)
7vpy_linkerSymbol resolution, inter-bank references
8vpy_binary_writerEmit final .bin ROM image
9vpy_debug_genGenerate .pdb debug symbol file

Buildtools handles both 32 KB (single-bank) and 64 KB+ (multibank) games. All new builtins, bug fixes, and hardware features ship here first.

Additional features

  • Variable-sized types (u8, i8, u16, i16) — declare with Python type-hint syntax (counter: u8 = 0). 1-byte types save RAM; defaults to i16 when no annotation is given. See the language manual for details.
  • Level system with horizontal scrolling — load .vplay scenes with LOAD_LEVEL("name"), render with SHOW_LEVEL(), and scroll with SET_CAMERA_X(x). Objects are culled automatically outside the viewport. See Level System below.

Multibank ROMs

VPy supports ROMs from 32 KB up to 4 MB with zero changes to your game code. Add two META directives:

META ROM_TOTAL_SIZE = 65536    # pick your target (see table below)
META ROM_BANK_SIZE  = 16384    # always 16 KB per bank

The compiler divides the ROM into 16 KB banks, assigns functions and assets automatically via call graph analysis, and generates all bank-switching wrappers. Banks 0 through N−2 are switched in at $0000–$3FFF; the last bank (helpers) is fixed at $4000–$7FFF.

Supported sizes

ROM_TOTAL_SIZEBanksCapacityRecommended chip
32768232 KB27C256 (single-bank, no switching)
65536464 KB27C512 ✅ fully tested
1310728128 KB27C010
26214416256 KB27C020
52428832512 KB27C040 / 29F040 Flash
1048576641 MB27C080 / 29F080
20971521282 MBM27C160
41943042564 MB29F320 Flash

Configurations larger than 4 banks compile, but cross-bank symbol resolution is still being completed. 4-bank (64 KB) is the recommended configuration for production today.

Memory map

$0000-$3FFF  Banked window (16 KB) — switches via STA $DF00
$4000-$7FFF  Helpers bank  (16 KB) — last bank, always visible

Level System

The level system lets you design game scenes visually in the Playground tab and load them at runtime.

Builtins

FunctionDescription
LOAD_LEVEL("name")Load a .vplay file into memory; resets CAMERA_X to 0
SHOW_LEVEL()Draw all visible objects at the current camera position
SET_CAMERA_X(x)Set the horizontal scroll offset (i16)
GET_LEVEL_TILE(x, y)Return the tile value at grid position (x, y)

Horizontal scrolling

Levels can be wider than the Vectrex screen (−128 to +127). Move the viewport with SET_CAMERA_X:

camera_x: i16 = 0
 
def loop():
    joy = J1_X()
    if joy > 20:
        camera_x = camera_x + 2
    if joy < -20:
        camera_x = camera_x - 2
    camera_x = clamp(camera_x, 0, 800)   # clamp to world width
    SET_CAMERA_X(camera_x)
    SHOW_LEVEL()

Objects outside the viewport are automatically culled. Only X-axis scrolling is supported.

.vplay file format

Files are authored in the IDE Playground and saved as JSON v2.0:

{
  "version": "2.0",
  "worldBounds": { "xMin": -96, "xMax": 863, "yMin": -128, "yMax": 127 },
  "layers": {
    "background": [ { "vectorName": "ground", "x": 0, "y": -60, ... } ],
    "gameplay":   [ { "vectorName": "player", "x": 0, "y":   0, ... } ],
    "foreground": []
  }
}

x/y are world coordinates. SHOW_LEVEL() subtracts CAMERA_X from each object's X to produce the screen position.


Project File Format (.vpyproj)

[project]
name        = "mygame"
version     = "0.1.0"
entry       = "src/main.vpy"
description = "My Vectrex game"
author      = "Your Name"
 
[build]
output         = "build/mygame.bin"
target         = "vectrex"
optimization   = 2
debug_symbols  = true   # required for source-level debugging
 
[sources]
vpy = ["src/**/*.vpy"]
 
[resources]
vectors = ["assets/vectors/*.vec"]
music   = ["assets/music/*.vmus"]
sfx     = ["assets/sfx/*.vsfx"]
FieldRequiredDescription
project.entryYesMain .vpy file
build.outputYesOutput .bin path
build.debug_symbolsNoEnable PDB generation (Buildtools only)
build.optimizationNo0–2, default 2

Building from the Command Line

# Build a project with Buildtools
cd buildtools && cargo run --bin vpy_cli -- build path/to/project.vpyproj
 
# Run compiler tests
cd buildtools && cargo test --all

Migrating from Core to Buildtools

  1. Create a .vpyproj file next to your main .vpy (see the project format section above).
  2. In the IDE Settings panel, switch the backend selector to Buildtools (New).
  3. Rebuild — single-bank output is identical to Core.

The only common issue is that Buildtools requires the .vpyproj file; there is no bare .vpy build mode.