Remove Unicode em dashes (U+2014) and en dashes (U+2013) from all Markdown files. Use ASCII -- for parenthetical breaks and - for hyphenation, matching standard plain-text conventions.
16 KiB
Language Reference
Data Types
| Type | Suffix | Description |
|---|---|---|
| INTEGER | % |
16-bit signed |
| SINGLE | ! |
32-bit float |
| DOUBLE | # |
64-bit float |
| STRING | $ |
Up to 255 bytes |
Operators
+, -, *, /, ^, \ (integer div), MOD, AND, OR, XOR, EQV,
IMP, NOT, <, =, >, <=, >=, <>
Numeric Functions
SGN, INT, ABS, SQR, SIN, COS, TAN, ATN, LOG, EXP, RND,
FIX, CINT, CSNG, CDBL
RND can be called with or without parentheses: RND is equivalent to RND(1).
String Functions
LEN, ASC, CHR$, VAL, STR$, LEFT$, RIGHT$, MID$, SPACE$,
STRING$, HEX$, OCT$, INSTR, INPUT$
File Functions
EOF, LOC, LOF
Memory Functions
FRE(x)-- free bytes in the string space pool.FRE("")triggers a garbage collection pass before reporting;FRE(0)reports without collecting.VARPTR(var)/VARPTR$(var)-- variable address (internal index)
Pseudo-variables
ERL, ERR, CSRLIN, INKEY$, DATE$, TIME$, TIMER, POS(0)
Literals
Decimal, &H hex, &O octal, D exponent (double), E exponent (single),
type suffixes (%, !, #)
Statements
| Category | Statements |
|---|---|
| Output | PRINT, LPRINT, LLIST, PRINT USING, WRITE, CLS |
| Variables | LET, DIM, ERASE, SWAP, DEFINT, DEFSNG, DEFDBL, DEFSTR |
| Control flow | GOTO, GOSUB/RETURN, FOR/NEXT, IF/THEN/ELSE, WHILE/WEND, ON...GOTO, ON...GOSUB |
| Input | INPUT, LINE INPUT, DATA/READ/RESTORE, INKEY$ |
| Program control | RUN, RUN "file", CONT, STOP, END, NEW, LIST, CLEAR, AUTO, RENUM, DELETE, EDIT |
| Sequential I/O | OPEN, CLOSE, PRINT#, WRITE#, INPUT#, LINE INPUT# |
| Random-access I/O | FIELD, LSET, RSET, PUT, GET, CVI/CVS/CVD, MKI$/MKS$/MKD$ |
| Program I/O | SAVE (binary/ASCII), LOAD (auto-detects), MERGE, CHAIN, COMMON |
| Event trapping | ON TIMER(n) GOSUB, TIMER ON/OFF/STOP, ON KEY(n) GOSUB, KEY(n) ON/OFF/STOP |
| Error handling | ON ERROR GOTO, RESUME, RESUME NEXT, RESUME n, ERROR, ERR, ERL |
| User functions | DEF FN, RANDOMIZE |
| File management | KILL, NAME, FILES, MKDIR, RMDIR, CHDIR, SHELL, RESET |
| Date/time | DATE$, TIME$, TIMER (read/write; DATE$/TIME$ assignment accepted) |
| Environment | ENVIRON, ENVIRON$ |
| Screen | LOCATE, COLOR, WIDTH, SCREEN, KEY ON/OFF/LIST, KEY n,"string" |
| Graphics | PSET, PRESET, LINE, CIRCLE, DRAW, PAINT, GET, PUT, VIEW, WINDOW, PALETTE, PMAP |
| Sound | SOUND, BEEP, PLAY (MML parser, PulseAudio backend) |
| Memory | DEF SEG, PEEK, POKE, BSAVE, BLOAD |
| Hardware I/O | OUT, INP, WAIT, MOTOR, STICK, STRIG |
| Device stubs | ERDEV, ERDEV$, IOCTL, IOCTL$, COM, LCOPY |
| Misc | KEY, TRON/TROFF, OPTION BASE, MID$ assignment |
| System | SYSTEM |
Program I/O (SAVE / LOAD)
SAVE writes the current program to a file. The default format is tokenized
binary (compact, fast to load), matching the original GW-BASIC behavior:
SAVE "myprog.bas" ' tokenized binary (default)
SAVE "myprog.bas",A ' ASCII text (human-readable, editable)
LOAD reads a program file, auto-detecting the format from the first byte:
LOAD "myprog.bas" ' auto-detects binary or ASCII
LOAD "myprog.bas",R ' load and run immediately
Binary files use the standard GW-BASIC 0xFF header format. Command-line
loading (./gwbasic file.bas) also auto-detects format.
MERGE loads an ASCII file without clearing the current program, overlaying
lines by number. CHAIN loads and runs a new program, optionally preserving
variables listed by COMMON.
INKEY$ Extended Keys
INKEY$ returns a zero-length string when no key is available, a one-byte
string for regular ASCII keys, or a two-byte string for extended keys:
K$ = INKEY$
IF LEN(K$) = 2 THEN scan = ASC(MID$(K$, 2, 1))
Extended keys return CHR$(0) as the first byte and the IBM PC scan code
as the second. Common scan codes:
| Key | Scan | Key | Scan |
|---|---|---|---|
| F1-F10 | 59-68 | Home | 71 |
| Up | 72 | PgUp | 73 |
| Left | 75 | Right | 77 |
| End | 79 | Down | 80 |
| PgDn | 81 | Ins | 82 |
| Del | 83 |
Printer Output (LPRINT / LLIST)
LPRINT works identically to PRINT but sends output to the printer:
- Default: output is appended to
LPT1.TXTin the current directory --lpt /dev/lp0(Linux) or--lpt LPT1(FreeDOS): send to real hardware--lpt report.txt: redirect to a custom file
LLIST lists the program to the printer, with optional line number ranges
(LLIST, LLIST 10-50, LLIST -100).
Both support PRINT USING, semicolons, commas, TAB(), and SPC().
Graphics
Graphics mode is activated with SCREEN 1 (320x200, 4 colors) or
SCREEN 2 (640x200, monochrome). Drawing commands render to an internal
framebuffer and output via Sixel graphics,
which works in terminals like xterm, mlterm, foot, and WezTerm.
Drawing Commands
PSET (x,y), color/PRESET (x,y)-- set/reset individual pixelsLINE (x1,y1)-(x2,y2), color [,B|BF]-- lines, boxes, filled boxesCIRCLE (cx,cy), r [,color [,start, end [,aspect]]]-- circles and arcsPAINT (x,y), fill, border-- flood fillDRAW string-- turtle graphics mini-language (U/D/L/R/E/F/G/H, M, C, S, B, N)POINT (x,y)-- read pixel colorCOLOR fg, bg-- set foreground/background colors
Sprite Capture and Blit (GET / PUT)
GET (x1,y1)-(x2,y2), array-- capture a screen rectangle into an integer arrayPUT (x,y), array [, action]-- blit a captured sprite back to the screen
The action parameter controls how the sprite combines with the existing screen:
| Action | Effect |
|---|---|
XOR (default) |
Exclusive OR -- drawing twice erases the sprite |
PSET |
Overwrite screen with sprite pixels |
PRESET |
Overwrite screen with inverted sprite pixels |
AND |
Bitwise AND of screen and sprite |
OR |
Bitwise OR of screen and sprite |
Sprite data is stored in CGA-compatible packed format: word 0 is the width in bits, word 1 is the height, and remaining words contain packed pixel data matching the original GW-BASIC representation.
VIEW / WINDOW / PALETTE
VIEW [[SCREEN] (x1,y1)-(x2,y2) [,[fill][,border]]]-- define a graphics viewport. WithoutSCREEN, drawing coordinates are relative to the viewport origin. WithSCREEN, coordinates remain absolute. Without arguments, resets to full screen.WINDOW [[SCREEN] (x1,y1)-(x2,y2)]-- map logical coordinates onto the viewport. WithoutSCREEN, Y increases upward (Cartesian); withSCREEN, Y increases downward. Without arguments, resets to physical coordinates.PALETTE [attribute, color]-- remap a color attribute to a different physical color (0-15). Without arguments, resets to the default CGA palette.PMAP(coordinate, function)-- convert between logical and physical coordinates. Function 0/1 = logical→physical X/Y; 2/3 = physical→logical X/Y.
Example
SCREEN 1
LINE (0,0)-(319,199), 1
CIRCLE (160,100), 80, 2
PAINT (160,100), 3, 2
DEF SEG / PEEK / POKE
DEF SEG, PEEK, and POKE provide access to a virtual 8086 address space
that emulates the memory layout programs expected on a real IBM PC:
DEF SEG = &HB800 ' select CGA video buffer segment
POKE 0, 65 ' write 'A' to top-left screen cell
PRINT PEEK(1) ' read the color attribute
DEF SEG ' reset to default segment
Emulated Memory Regions
| Segment | Address Range | Description |
|---|---|---|
0040 |
BIOS data area | Video mode (0049), column count (004A), cursor position (0050-0051), timer ticks (006C-006F), screen rows (0084), keyboard shift flags (0017: bit 7 = insert mode) |
B800 |
CGA text buffer | Character/attribute pairs in text mode (even byte = char, odd byte = attr, 80 columns × 25 rows = 4000 bytes) |
B800 |
CGA graphics buffer | In SCREEN 1/2: CGA interlaced layout (even rows at offset 0, odd rows at 0x2000, 80 bytes/row) |
All other segments read as 0 and writes are silently discarded. The timer
tick counter at 0040:006C tracks real time at the original 18.2 Hz rate.
BSAVE / BLOAD
BSAVE saves a block of virtual memory to a binary file with a 7-byte header.
BLOAD loads it back. These operate on whichever segment was last set by
DEF SEG.
DEF SEG = &HB800
BSAVE "screen.bin", 0, 4000 ' save the CGA text buffer
CLS
BLOAD "screen.bin" ' restore it
BLOAD "screen.bin", 100 ' load to a different offset
The file format is compatible with the original GW-BASIC: byte 0 = 0xFD,
bytes 1-2 = segment (LE), bytes 3-4 = offset (LE), bytes 5-6 = length (LE),
followed by the raw data bytes.
String Space and Garbage Collection
All string data lives in a contiguous pool (default 32,768 bytes), matching the original GW-BASIC's string space architecture. Allocation is a bump pointer; dead strings are reclaimed by a compacting garbage collector that runs automatically at statement boundaries when the pool is running low.
CLEAR ,8192 ' set string space to 8KB and clear variables
PRINT FRE("") ' trigger GC and print free bytes
CLEAR n (or CLEAR ,n) resizes the string space to n bytes and clears
all variables. FRE("") forces a garbage collection pass and returns the
free bytes; FRE(0) returns the current free count without collecting.
Hardware I/O (OUT / INP / WAIT)
OUT, INP, and WAIT provide access to emulated IBM PC I/O ports, enabling
classic programs that drive hardware directly -- speaker tones via the 8253 PIT,
CGA palette tricks, and serial port polling.
OUT &H43, &HB6 ' PIT channel 2: lobyte/hibyte, mode 3
OUT &H42, &HD3 : OUT &H42, &H04 ' set frequency divisor (1235 → 966 Hz)
OUT &H61, INP(&H61) OR 3 ' speaker on
OUT &H61, INP(&H61) AND &HFC ' speaker off
Emulated Ports
| Port | Device | Behavior |
|---|---|---|
&H42-&H43 |
8253 PIT channel 2 | Speaker frequency divisor (1193180 / divisor Hz) |
&H61 |
PPI Port B | Bits 0-1 control speaker; both set = tone on, either clear = off |
&H3D8 |
CGA mode control | Mode register; writes with changed mode bits trigger SCREEN changes |
&H3D9 |
CGA color select | Background color (bits 0-3) and palette select (bit 5) |
&H201 |
Game port | Returns &HF0 (no joystick connected) |
&H3F8-&H3FE |
COM1 serial | Minimal stub; LSR (&H3FD) returns &H60 (transmitter ready) |
| Default | -- | Reads return &HFF (floating bus), writes silently discarded |
Related Functions
INP(port)-- read a byte from an I/O portSTICK(n)-- joystick axis position (returns 128 = center, n = 0-3)STRIG(n)-- joystick button state (returns 0 = not pressed)WAIT port, mask [, xor_mask]-- busy-wait until(INP(port) XOR xor_mask) AND maskis nonzero; Ctrl+C breaks outMOTOR [n]-- accepted and silently ignored (cassette motor control)
When the PPI speaker bits are set, the PIT frequency divisor is used to
generate a continuous tone via PulseAudio (same backend as SOUND / PLAY).
Environment Variables
ENVIRON "var=value"-- set an environment variable (uses the Cputenv()call)ENVIRON$("var")-- read an environment variable (returns "" if not set)
ENVIRON "GREETING=Hello"
PRINT ENVIRON$("GREETING") ' prints: Hello
PRINT ENVIRON$("PATH") ' prints the system PATH
Date/Time Assignment
DATE$ and TIME$ can be assigned to set the date and time:
DATE$ = "01-15-2026"
TIME$ = "14:30:00"
These assignments are accepted for compatibility but do not modify the
system clock. Reading DATE$ and TIME$ always returns the current
system date and time.
Device Stubs
The following device-related statements and functions are accepted for compatibility with programs that reference them, but return stub values since there is no real device hardware:
ERDEV-- device error code (always 0)ERDEV$-- device error name (always "")IOCTL [#n,] string-- device control string output (accepted, ignored)IOCTL$(n)-- device control string input (always "")COM ON/COM OFF/COM STOP-- serial port event trapping (accepted, ignored)LCOPY [n]-- screen dump to printer (accepted, ignored)CALL/CALLS-- machine code execution (raises Illegal function call)RESET-- close all open files (equivalent toCLOSE)
Sound
SOUND frequency, duration-- play a tone (frequency in Hz, duration in clock ticks)BEEP-- play the default beepPLAY string-- Music Macro Language (MML) string for melodies
Sound output uses PulseAudio when available; commands are silently ignored otherwise.
Full-Screen Editor (TUI)
When running interactively, GW-BASIC 2026 presents the authentic full-screen editor:
- 25×80 screen buffer by default, or full terminal size with
--full - Press Enter on any screen line to re-enter it as BASIC input
- Insert/Overwrite toggle (Insert key)
- Home/End/Delete/Backspace/Escape for line editing
- Ctrl+C interrupts running programs
- Uses the ANSI alternate screen buffer for clean terminal restore on exit
Function Keys
Default F1-F10 bindings match the original GW-BASIC:
| Key | Default | Key | Default |
|---|---|---|---|
| F1 | LIST |
F6 | ,"LPT1:" + Enter |
| F2 | RUN + Enter |
F7 | TRON + Enter |
| F3 | LOAD" |
F8 | TROFF + Enter |
| F4 | SAVE" |
F9 | KEY |
| F5 | CONT + Enter |
F10 | SCREEN 0,0,0 + Enter |
KEY ON-- show the function key bar on line 25KEY OFF-- hide the barKEY LIST-- display all definitionsKEY n, "string"-- redefine a function key
Piped Mode
When stdin is not a terminal (piped input), the TUI is not activated. The interpreter reads lines from stdin and writes output directly to stdout, suitable for scripting and test harnesses.
Program Editing
EDIT [linenum]-- display a program line for editing in the TUI; press Enter to re-store itAUTO [start][,increment]-- automatic line numbering modeRENUM [new][,[old][,increment]]-- renumber program lines (patches all GOTO/GOSUB references)DELETE range-- delete program lines (DELETE 10-50,DELETE -100,DELETE 200-)
Event Trapping
GW-BASIC supports event-driven programming through trap handlers that fire between statements during program execution.
Timer Events
ON TIMER(n) GOSUB line ' register handler (fires every n seconds)
TIMER ON ' enable timer trapping
TIMER STOP ' suspend trapping (events are queued)
TIMER OFF ' disable trapping (events are discarded)
Function Key Events
ON KEY(n) GOSUB line ' register handler for F-key n (1-10)
KEY(n) ON ' enable trapping for key n
KEY(n) STOP ' suspend trapping (events are queued)
KEY(n) OFF ' disable trapping
Event handlers execute as implicit GOSUBs. The RETURN statement returns
to the interrupted code and clears the handler's in-progress flag. Events do
not fire inside their own handler (re-entrant protection).
TIMER STOP / KEY(n) STOP queue events while stopped; switching to
TIMER ON / KEY(n) ON fires the pending event immediately.
References
- Microsoft Corporation. Microsoft GW-BASIC: User's Guide and Reference. Microsoft Press, 1989. ISBN 978-1-55615-260-3.
- Inman, Don and Bob Albrecht. The GW-BASIC Reference. Osborne McGraw-Hill, 1990. ISBN 978-0-07-881644-4.
- Ahl, David H. BASIC Computer Games: Microcomputer Edition. Workman, 1978. ISBN 978-0-89480-052-8.
- Microsoft Corporation. GW-BASIC User's Manual. Microsoft, 1987. (OEM bundled; no ISBN.)
- Microsoft Corporation. GW-BASIC Source Code. Released 2020.