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.
| Phase | Crate | Responsibility |
|---|---|---|
| 1 | vpy_loader | Load .vpyproj project file (TOML) |
| 2 | vpy_parser | Parse VPy source to AST |
| 3 | vpy_unifier | Merge multi-file ASTs, resolve imports |
| 4 | vpy_bank_allocator | Assign functions/data to ROM banks |
| 5 | vpy_codegen | AST → MC6809 assembly (with tree shaking) |
| 6 | vpy_assembler | MC6809 assembly → machine code (two-pass) |
| 7 | vpy_linker | Symbol resolution, inter-bank references |
| 8 | vpy_binary_writer | Emit final .bin ROM image |
| 9 | vpy_debug_gen | Generate .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 toi16when no annotation is given. See the language manual for details. - Level system with horizontal scrolling — load
.vplayscenes withLOAD_LEVEL("name"), render withSHOW_LEVEL(), and scroll withSET_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 bankThe 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_SIZE | Banks | Capacity | Recommended chip |
|---|---|---|---|
32768 | 2 | 32 KB | 27C256 (single-bank, no switching) |
65536 | 4 | 64 KB | 27C512 ✅ fully tested |
131072 | 8 | 128 KB | 27C010 |
262144 | 16 | 256 KB | 27C020 |
524288 | 32 | 512 KB | 27C040 / 29F040 Flash |
1048576 | 64 | 1 MB | 27C080 / 29F080 |
2097152 | 128 | 2 MB | M27C160 |
4194304 | 256 | 4 MB | 29F320 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
| Function | Description |
|---|---|
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"]| Field | Required | Description |
|---|---|---|
project.entry | Yes | Main .vpy file |
build.output | Yes | Output .bin path |
build.debug_symbols | No | Enable PDB generation (Buildtools only) |
build.optimization | No | 0–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 --allMigrating from Core to Buildtools
- Create a
.vpyprojfile next to your main.vpy(see the project format section above). - In the IDE Settings panel, switch the backend selector to Buildtools (New).
- 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.