A compact reference: one line per command, in JBB's single canonical form.
JBB is declare-first: every variable is declared (with AS type) before
use; the $/% suffix is just a name character. Integers are 64-bit. FOR
comes in two shapes: declare the counter inline with FOR i AS INTEGER = ...
(loop-local, gone after the loop) or reuse a variable declared earlier with
FOR i = ... (it keeps its value after the loop).
For worked examples and fuller explanations see the manual (a work in progress); this reference lists the forms, the manual will teach them.
IF cond THEN stmt [ELSE stmt] single-line IF
IF cond THEN / ... / ELSEIF cond THEN / ... / ELSE / ... / ENDIF block IF
FOR i AS INTEGER = a TO b [STEP s] / ... / NEXT i counted loop, inline counter (AS INTEGER or AS FLOAT); loop-local, gone after the loop
FOR i = a TO b [STEP s] / ... / NEXT i counted loop reusing a variable declared earlier; keeps its value after the loop
DO / ... / LOOP loop forever
DO / ... / LOOP UNTIL cond loop until true
DO WHILE cond / ... / LOOP loop while true
EXIT FOR | EXIT DO | EXIT SUB | EXIT FUNCTION leave the named block
CONTINUE FOR | CONTINUE DO next iteration
SELECT CASE expr / CASE v[,v] / ... / CASE ELSE / ... / END SELECT multi-way
GOTO label jump
GOSUB label / ... / RETURN call/return by label
ON expr GOTO label[,label...] computed jump
END stop the program
DIM name AS INTEGER | FLOAT | STRING declare a scalar
DIM a, b AS INTEGER declare several (one type)
DIM name(size) AS type [= (v1, v2, ...)] declare an array (+ values)
DIM name AS TypeName declare a struct variable
name = expr assignment (coerced to type)
INC var [, amount] fast in-place add
CONST name = expr a constant (no reassignment)
LOCAL name AS type a SUB/FUNCTION-local variable
STATIC name AS type keeps its value between calls
REDIM [PRESERVE] name(size) resize an array
ERASE name [, name...] delete arrays
CLEAR drop all variables/constants
TYPE Name / member AS type / ... / END TYPE define a structure
SUB name(p AS type, ...) / ... / END SUB define a subprogram
FUNCTION name(p AS type, ...) AS type / ... / END FUNCTION define a function
CALL name(args) | name args call a SUB
PRINT expr [; | ,] ... print (";" no newline, "," tab)
CLS clear the screen
CURSOR x, y move the text cursor
COLOUR fg, bg (also COLOR) set text colours (0..63)
INPUT [;"prompt";] var [, var...] read typed input
LINE INPUT [#n,] [;"prompt";] string read a whole line
PAUSE ms wait milliseconds
INKEY$ next buffered key, or ""
POS current cursor column
GRAPHICS OPEN col, row, w, h [, scale [, dbuf]] open a bitmap window
GRAPHICS CLOSE close it (back to text)
PIXEL x, y [, colour] set a pixel (PIXEL(x,y) reads)
LINE x1, y1, x2, y2 [, colour] draw a line
BOX x, y, w, h [, colour [, fill]] rectangle (outline or filled)
CIRCLE x, y, r [, colour [, fill]] circle (outline or filled)
TRIANGLE x1,y1,x2,y2,x3,y3 [, colour [, fill]] triangle
RBOX x, y, w, h, r [, colour [, fill]] rounded rectangle
ARC x, y, r, a1, a2 [, colour] arc between two angles
RGB(r, g, b) build a 0..63 colour
SOUND hz, duration_ms play a tone at a frequency (blocking)
SOUND OFF silence all channels
PLAY note, duration_ms play a MIDI note (60 = C4, blocking)
SOUND TEMPO bpm set the beat for note values
SOUND WAVE ch, type channel waveform (0=sine 1=square 2=saw 3=triangle)
SOUND ENVELOPE ch, attack, decay, sustain, release channel ADSR (ms; sustain 0-255)
SOUND VOLUME ch, vol channel volume (0-255)
SOUND PAN ch, pan channel pan (0=left 128=mid 255=right)
SOUND PLAY ch, note, notevalue trigger a note on a channel (non-blocking, polyphonic)
SOUND WAIT notevalue tempo-aware rest (1=whole 2=half 4=quarter 8=eighth)
The per-channel SOUND form exposes the platform's 4-channel synth: set a
channel's instrument (waveform + envelope) then play notes on it. SOUND PLAY
is non-blocking so several channels sound together (polyphony); SOUND WAIT
spaces them at the current tempo. Apps (not BASIC) can also stream raw 16-bit
PCM straight to the platform via japi_audio_stream.
OPEN name$ FOR INPUT | OUTPUT | APPEND AS #n open a file
PRINT #n, expr ... write to a file
LINE INPUT #n, string read a line from a file
CLOSE #n close a file
FILES ["drive:"|"path"] list a directory
KILL name$ delete a file
MKDIR name$ make a directory
EOF(n) · LOF(n) · LOC(n) · INPUT$(count, #n) file-state functions
DIR$(pattern, type) · CWD$ directory listing / current dir
DATA v1, v2, ... inline constant data
READ var [, var...] read the next DATA values
RESTORE [label] rewind the DATA pointer
ON ERROR ABORT | IGNORE | SKIP [n] | CLEAR how run-time errors behave
ERROR ["message"] raise an error
MM.ERRNO · MM.ERRMSG$ last error number / message
TRON | TROFF | TRACE ON|OFF|LIST line-trace
RANDOMIZE [seed] seed RND
TIMER = ms set the millisecond timer
TIMER read the timer (function)
DATE$ = "dd-mm-yyyy" | TIME$ = "hh:mm:ss" set the wall clock
UPTIME seconds since power-on (function)
MEMORY · SETTITLE s$ · QUIT · EDIT report / title / halt
^ power (always float)
- + unary sign
* / \ MOD multiply, real divide, integer divide, remainder
+ - add/subtract (+ also concatenates strings)
<< >> bit shift left/right
NOT logical NOT (0 -> 1, else 0)
< > <= >= <> = comparison (=< => accepted; result 1/0)
AND OR XOR bitwise/logical
Math ABS ACOS ASIN ATN ATAN2 ATAN3 COS COSH SIN SINH TAN TANH
EXP LOG LOG10 SQR PI DEG RAD FIX INT CINT SGN MAX MIN RND CHOICE
Strings LEN ASC CHR$ LEFT$ RIGHT$ MID$ INSTR UCASE$ LCASE$ TRIM$
SPACE$ STRING$ FORMAT$ FIELD$
Convert VAL STR$ HEX$ OCT$ BIN$ BIN2STR$ STR2BIN BIT BYTE
Date/time DATE$ TIME$ NOW DATETIME$ EPOCH DAY$ UPTIME
Arrays BOUND(array[, dim]) (SORT is a statement)
Longstr LLEN LGETBYTE LGETSTR$ LINSTR (LONGSTRING ... statements)
Advanced MATH(...) (incl. PID) · EVAL(expr$)
RMDIR and RENAME are implemented and hardware-verified (2026-06-22, via
japi_rmdir/japi_rename). CHDIR/CWD$ stay deferred: littlefs (C:) has no working-directory concept, so they would be FatFs-only. Random access (OPEN FOR RANDOM, SEEK, GET/PUT) is implemented (japi_fseek).