Ultimate Basic — VS Code Extension
Language support for Ultimate Basic (.ub), a modern BASIC-like language that compiles directly to 6502 machine code for the Commodore 64. Write C64 programs with syntax highlighting, code snippets and one-click build & run in VICE — all from VS Code.
© 2026 Zsolt Tarczali
Getting started
- Install the extension from the Extensions view (search for Ultimate Basic), or from the command line:
code --install-extension zsolt-tarczali.ultimate-basic
- Download the Ultimate Basic compiler from the releases
and, if it is not on your
PATH, set ultimateBasic.compilerPath to it. For Build & Run set
ultimateBasic.vicePath as well.
- Open a
.ub file and choose Ultimate Basic: Build & Run in VICE from the editor's context menu or the
Command Palette.
Features
- Syntax highlighting — keywords, types, C64-specific statements, numbers (decimal, hex
$D020, binary %1010), comments (#, rem, QBasic '), QBasic-style DIM … AS, FUNCTION, ELSEIF, DO … LOOP, WHILE … WEND, SELECT CASE, LEFT$/RIGHT$/MID$, <>; floating-point literals (2.5, .5, 1E6), ^, SQR/TAN/ATN/EXP/LOG/FIX/CINT/CSNG/CDBL, PRINT USING, option basic print / option strings, TYPE … END TYPE with STRING * n fields and AS TypeName struct parameters
- 230+ code snippets —
if, for, while, repeat, sub, fn, select, sprdef, chardef, mainloop, bitmapskel and more
- Auto-indent — smart indentation for
if/end, for/next, sub/end, sprdef/end, while/end, repeat/until blocks, plus QBasic IF … ELSEIF … END IF, FUNCTION/SUB … END, DO … LOOP [UNTIL|WHILE], WHILE … WEND, SELECT CASE … END SELECT, TYPE … ENDTYPE / END TYPE
- Build & Run commands — compile and launch directly in VICE with a single command
- Context menu — right-click any
.ub file for quick access to Build / Build & Run
- Task integration — works with the VS Code Task system (
Ctrl+Shift+B)
Requirements
Settings
| Setting |
Default |
Description |
ultimateBasic.compilerPath |
ub |
Full path to the compiler executable |
ultimateBasic.vicePath |
x64sc |
Full path to the VICE C64 emulator executable |
ultimateBasic.viceArgs |
[] |
Extra arguments passed to VICE, e.g. ["-fullscreen"] |
ultimateBasic.defaultOutputDir |
(source directory) |
Output directory for compiled files, created if missing. Absolute or relative to the workspace folder (e.g. ./samples/out) |
ultimateBasic.d64AddFiles |
[] |
Extra files to embed in the .d64 disk image (passed as --add file for each entry) |
ultimateBasic.exomizerPath |
exomizer |
Full path to the Exomizer executable |
ultimateBasic.exomizerMode |
sfx sys |
Exomizer mode: sfx sys, sfx basic, or mem |
ultimateBasic.exomizerSuffix |
_exo |
Suffix appended to the output file name (e.g. prog_exo.prg) |
ultimateBasic.explicitMode |
false |
Always pass --explicit to the compiler (require :type on every var / sub-param / fn-param) |
ultimateBasic.basicPrint |
false |
Always pass --basic-print to the compiler (C64 BASIC PRINT spacing; same as option basic print in the source) |
Example (settings.json):
{
"ultimateBasic.compilerPath": "C:\\tools\\ub.exe",
"ultimateBasic.vicePath": "C:\\VICE\\x64sc.exe",
"ultimateBasic.viceArgs": ["-fullscreen"]
}
Commands
Access via Ctrl+Shift+P → Ultimate Basic: ... or by right-clicking a .ub file.
| Command |
Description |
| Build (.prg) |
Compile the active .ub file to a .prg |
| Build (verbose) |
Compile with zero-page layout and hex dump output |
| Build + D64 disk image |
Compile and also produce a .d64 disk image |
| Build & Run in VICE |
Compile, then automatically launch VICE on success |
| Build D64 & Run in VICE |
Produce a .d64 disk image, then launch VICE |
| Build + Exomize |
Compile, then run Exomizer on the resulting .prg |
| Build + Exomize & Run in VICE |
Compile, Exomize, then launch VICE with the compressed file |
| Build (debug symbols) |
Compile with --debug — also produces .sym / .dbg / .vs debugger files |
| Build (asm listing) |
Compile with --asm — also produces a readable 6502 codegen .asm listing |
| Build (.crt cartridge) |
Compile to a Magic Desk type-19 .crt cartridge image |
Snippets
| Prefix |
Inserts |
var, varw, vars, vara, varaw, varf |
variable declaration (int / word / string / array / word array / float) |
const |
compile-time constant |
if, ife |
if/then, if/then/else block |
for, fors |
for..next loop (with or without step) |
while, loop, loopc |
while / infinite / counted loop |
repeat |
repeat/until do-while loop |
select |
select/case statement |
dim, dimi |
QBasic-style DIM name AS type (with / without initializer) — 1.6.3 |
dima, dima2 |
DIM name(9) AS type / DIM name(2, 3) AS type arrays (bound = highest index) — 1.6.3 |
function, subq |
QBasic FUNCTION … AS type … END FUNCTION (return by name) / SUB … END SUB — 1.6.3 |
ifq, ifelseif, elseif, ifl |
IF … END IF, IF … ELSEIF … ELSE … END IF, ELSEIF branch, single-line IF … THEN … ELSE — 1.6.3 |
dow, dou, wend |
DO WHILE\|UNTIL … LOOP, DO … LOOP UNTIL\|WHILE, WHILE … WEND — 1.6.3 |
selectcase |
SELECT CASE with lists, TO ranges, CASE IS, CASE ELSE — 1.6.3 |
exitq |
EXIT FOR / DO / WHILE / FUNCTION / SUB — 1.6.3 |
left, right, mid |
LEFT$ / RIGHT$ / MID$ runtime string functions — 1.6.3 |
concat, prints, inputq |
runtime string +, PRINT a; b, INPUT "prompt"; x — 1.6.3 |
dimd, floatfn, pow, forf |
DIM x AS DOUBLE, floating-point builtins (SQR, ATN, CINT, …), ^ power, FOR … STEP 0.1 — 1.6.4 |
rndf, printusing, optbp |
floating-point RND (0 ≤ x < 1), PRINT USING "###.##"; x, option basic print — 1.6.6 |
optstr |
option strings n, m — string variable / string-array element capacity |
typeq, typefield, substruct |
QBasic TYPE … END TYPE (defaults, STRING * n), struct field with default, SUB s(p AS TName) struct parameter |
break, conti |
exit loop / skip to next iteration |
label, goto |
label definition / jump |
sub |
subroutine definition |
fn, fnw |
function definition (returns a value / with 16-bit word return type) |
inc, dec |
increment / decrement variable |
print, printv |
print string / print label + variable |
ctext, cborder, cbg, colors |
color text / border / bg / all three |
cls, clsf |
screen clear / fast screen clear |
gcls |
clear bitmap RAM |
bye |
exit to BASIC |
cursor |
move cursor to column, row |
getch, inkey, joy |
keyboard (blocking / non-blocking) / joystick read |
mousex, mousey, mousebtn |
mouse X / Y position / button state |
scrollx, scrolly |
hardware horizontal / vertical fine scroll |
scrollxn, scrollxw |
scroll X narrow (38-col) / scroll X wide (40-col) |
scrollrow |
shift screen RAM row left (software text scroll) |
speed, speedmax, speedoff |
U64 CPU speed (MHz / max / 1 MHz) |
badlon, badloff |
U64 badline timing on / off |
turbo |
check if U64 turbo is active |
val |
runtime PETSCII decimal string → integer |
intf |
extract integer part from Q8.8 float |
printat |
print text at column, row |
spc, tab |
print N spaces / move to column N |
screen, screenc |
write char to screen RAM (with optional color) |
poke, peek |
memory write / read (8-bit) |
poke16, peek16 |
memory write / read (16-bit) |
fill |
fill memory range with value |
memcopy |
copy memory block |
sound |
SID sound |
sidvol |
set SID master volume (0–15) |
sidstop |
silence SID (volume 0, gates off) |
loadsid |
embed SID music file at compile time |
wait, waitr, delay |
wait N raster transitions / wait for raster line / wait N PAL frames |
waitkey |
CIA1 keyboard scan — blocks until key pressed, returns PETSCII code |
gosub |
call label-based subroutine (paired with return) |
times |
counted loop alias (times N … end) |
onerr |
register KERNAL I/O error handler (onerr goto label) |
musicplay, musicstop, musicpause, musicresume |
high-level SID music control |
tune |
inline SID tracker tune block (speed/inst/order/pat) |
inst, pat |
tune instrument definition / pattern row |
imod, ifilt, igate, itab |
tune instrument vibrato/PWM, filter sweep, gate timer/hard restart, wave/arpeggio table (1.6.2) |
map_load_addr, map_view, map_scroll |
map data at a fixed address, smooth double-buffered map scrolling (1.6.1) |
sfx |
non-blocking SID note, safe inside game loops |
org |
continue subroutine code at a given address, zero-filling the gap |
charseton, charsetoff |
point VIC-II at the custom charset RAM / restore the ROM charset |
mplot |
set multicolor bitmap pixel (x, y, color-index 0–3) |
bnot |
bitwise NOT operator (XOR 255) |
clamp |
8-bit unsigned clamp (clamp(x, lo, hi)) |
spritex, spritey |
read current sprite X / Y position |
sprframe |
set sprite data pointer (sprite_frame id, addr) |
chardef, charset |
define custom character / load charset from binary file |
strn |
integer → 3-digit decimal string (str$(n)) |
reudet |
check REU present — alias for reu_present() |
fillscr, fillcol |
fill screen RAM / color RAM with a constant value |
gonb |
graphics on block — 80×50 block-pixel mode |
plot4, plot4e |
set / clear block pixel (0-79, 0-49) in block mode |
lowercase, uppercase |
switch VIC-II charset mode (lowercase ↔ uppercase/graphics) |
plot, plote, plotx |
set / erase / toggle pixel |
line, circle |
line and circle drawing |
paint |
4-connected flood fill |
drawmem |
2D blit (source, dst, width, height, stride) |
gon, gonm, goff |
graphics on / multicolor / off |
don, doff |
display on / off (VIC DEN bit) |
sprdef |
21-row sprite data block template |
sprite |
sprite setup (position + enable + color) |
spron, sproff |
sprite enable / disable |
sprcol |
sprite color |
sprmc |
sprite multicolor on/off |
sprex, sprey |
sprite expand x / expand y |
sprpri |
sprite priority (behind/in front of background) |
sprhit, sprbghit |
sprite collision checks |
sprmov |
sprite position update (no data pointer) |
data, read |
data table / read next byte |
data_array |
initialize a declared array/array_word with constant values |
numstr |
write number as 3-digit decimal string |
strtoint |
compile-time string to integer |
len, asc |
string length / first character PETSCII code |
hex, bin, decp |
print as 2-digit hex / 8-bit binary / right-justified decimal |
chrp |
print single character by PETSCII code (chr$) |
abs, min, max, sgn |
absolute value / min / max / sign |
rnd, rndn |
random 0–255 / random 0–(N-1) |
sin, cos |
sine / cosine lookup (0–255 angle, 0–255 result) |
input, inputp |
keyboard input (with / without prompt) |
load, loada, save |
load from disk / load to address / save memory range |
chain |
load another program over this one and RUN it (boot/title → game) |
open, openp, close |
open / close serial file channel |
printhash |
send output to logical file (print#) |
irq |
raster IRQ setup with handler skeleton |
irqexit |
exit IRQ handler (restores registers, RTI) |
nmi |
NMI handler setup ($0318/$0319 vector) |
nmiexit |
exit NMI handler (JMP $FE47) |
ciatimer |
CIA1 timer A periodic IRQ setup |
include, incbin |
source file include / binary embed |
reustash, reufetch, reuswap |
REU memory transfer |
reupresent |
check if REU is present |
sys, sysa |
JSR to KERNAL/ROM routine (plain / with A register preloaded) |
asm |
inline assembly block |
mainloop |
full main loop skeleton (keyboard handling, Q = quit) |
bitmapskel |
bitmap graphics skeleton |
Building from source
npm ci
npx @vscode/vsce package
This creates ultimate-basic-<version>.vsix; install it with Extensions: Install from VSIX….
License
MIT — see LICENSE.
| |