This is intended as a quick reference for the Applesoft BASIC in JavaScript by Joshua Bell.
Extensions beyond Applesoft BASIC are called out with footnotes.
See also:
GOSUB
into a GOTO
ONERR GOTO
;
concatenates,
,
advances to next tab stop. A trailing ;
suppresses line break.
expr can include SPC(aexpr)
to advance by
multiple spaces, or TAB(aexpr)
to advance to column.
POKE 32,n
— Text window left edge
POKE 33,n
— Text window width
POKE 34,n
— Text window top edge
POKE 35,n
— Text window bottom
POKE 36,n
— Text cursor x
POKE 37,n
— Text cursor y
POKE 216,n
— ONERR flag (n < 128 disables ONERR handler)
POKE 230,n
— Hi-Res plotting page (32 = page 1, 64 = page 2)
POKE 49168,0
or POKE -16368,0
— clear keyboard strobe
POKE 49200,0
or POKE -16336,0
— toggle speaker (no-op)
POKE 49232,0
or POKE -16304,0
— graphics mode
POKE 49233,0
or POKE -16303,0
— text mode
POKE 49234,0
or POKE -16302,0
— full graphics mode
POKE 49235,0
or POKE -16301,0
— mixed text/graphics mode
POKE 49236,0
or POKE -16300,0
— display page 1
POKE 49237,0
or POKE -16299,0
— display page 2
POKE 49238,0
or POKE -16298,0
— lores graphics mode
POKE 49239,0
or POKE -16297,0
— hires graphics mode
CALL 54915
or CALL -10621
— clear stack (pop all FOR
/NEXT
, GOSUB
/RETURN
, and ONERR
/RESUME
entries)
CALL 62248
or CALL -3288
— pop ONERR
/RESUME
entry from stack
CALL 62436
or CALL -3100
— reveal hi-res page 1
CALL 62450
or CALL -3086
— clear current hi-res page to black
CALL 62454
or CALL -3082
— clear current hi-res page to current color
CALL 64500
or CALL -1036
— move cursor right
CALL 64528
or CALL -1008
— move cursor left
CALL 64538
or CALL -998
— move cursor up
CALL 64578
or CALL -958
— clear text from cursor to bottom of window
CALL 64614
or CALL -922
— move cursor down
CALL 64668
or CALL -868
— clear text from cursor to end of line
CALL 64780
or CALL -756
— wait for keypress
CALL 65152
or CALL -384
— set inverse text mode
CALL 65156
or CALL -380
— set normal text mode
PR#0
— set 40 column mode
PR#3
— set 80 column mode
PR#4
— write to Thunderclock
IN#0
— read input from keyboard or DOS
IN#4
— read from Thunderclock
PEEK(32)
— Text window left edge
PEEK(33)
— Text window width
PEEK(34)
— Text window top edge
PEEK(35)
— Text window bottom
PEEK(36)
— Text cursor x
PEEK(37)
— Text cursor y
PEEK(78)
& PEEK(79)
— Random-Number Field
PEEK(222)
— Last error code
PEEK(230)
— Hi-Res plotting page (32 = page 1, 64 = page 2)
PEEK(49152)
or PEEK(-16384)
— Read Keyboard
PEEK(49168)
or PEEK(-16368)
— Clear Keyboard strobe
PEEK(49178)
or PEEK(-16358)
— See if text mode (> 127) or graphics mode (< 128)
PEEK(49179)
or PEEK(-16357)
— See if mixed mode (> 127) or full mode (< 128)
PEEK(49180)
or PEEK(-16356)
— See if page2 (> 127) or page1 (< 128)
PEEK(49181)
or PEEK(-16355)
— See if hires mode (> 127) or lores mode (< 128)
PEEK(49182)
or PEEK(-16354)
— See if mousetext mode (> 127)
PEEK(49183)
or PEEK(-16353)
— See if 80-column mode (> 127)
PEEK(49200)
or PEEK(-16336)
— Click Speaker (no-op)
PEEK(49248)
or PEEK(-16288)
— Read Paddle Button #3 — Use the PageDown key
PEEK(49249)
or PEEK(-16287)
— Read Paddle Button #0 — Use the Home key
PEEK(49250)
or PEEK(-16286)
— Read Paddle Button #1 — Use the End key
PEEK(49251)
or PEEK(-16285)
— Read Paddle Button #2 — Use the PageUp or Shift key
Operators are listed vertically in order of precedence, from highest to lowest. Operators on the same line are of the same priority, and in an expression are executed from left to right. This order differs from the order in some other dialects of BASIC, but does match Applesoft.
( )
+ - NOT
(unary operators)
^
* /
+ -
= < > <= =< >= => <> ><
AND
OR
Error codes can be determined by calling
PEEK(222)
in an ONERR handler.
See also
Other DOS commands are NOT IMPLEMENTED.
Some sample files are present in a server-side store loaded on-demand into a client-side virtual file system (VFS). Creating or writing to a file will write to the VFS. Subsequent reads will read from the VFS. Files may be deleted from the VFS. These changes will not persist if the browser is refreshed or closed.
Error codes can be determined by calling
PEEK(222)
in an ONERR handler.
The page attempts to emulate an Apple II keyboard. Note that the keyboard API available in Web browsers is not standardized and is poorly defined; a best-effort has been made testing on available systems and browsers.
The Open Apple and Closed Apple keys on later Apple II models correspond to the Button #0 and Button #1 inputs and are emulated on modern keyboards with the Left Alt and Right Alt keys respectively if possible, otherwise the Home and End keys respectively.
Since the Tab key is necessary for keyboard access to browser functions and
the rest of the web page, it is not available. Otherwise, special keys can be detected
using GET
(blocking) or PEEK(49152)
or PEEK(-16384)
(non-blocking):
CHR$(8) | Left arrow |
CHR$(10) | Down arrow |
CHR$(11) | Up arrow |
CHR$(13) | Enter or Return |
CHR$(21) | Right arrow |
CHR$(24) | Clear |
CHR$(27) | Escape |
CHR$(127) | Delete or Backspace |
The page attempts to emulate the display of an Apple II system with
80-column card firmware, which can be activated with the
PR#3
statement.
When printing characters, CHR$()
functions as expected for values
from 32-126 (printable ASCII). Control characters have the typical Apple II meanings:
CHR$(4) | DOS command escape prefix |
CHR$(7) | Make a "beep" (if your browser supports it) |
CHR$(8) | Backspace (move cursor left, wrap up) |
CHR$(10) | Line feed (move cursor down) |
CHR$(13) | Carriage return (move cursor down and to left edge) |
CHR$(127) | Displays a cursor glyph |
If 80-column firmware is active, the following additional codes are available:
CHR$(11) | Clears from the cursor position to the end of the window |
CHR$(12) | Move cursor to upper left and clear window |
CHR$(14) | Set normal text output |
CHR$(15) | Set inverse text output |
CHR$(17) | Set display to 40 columns |
CHR$(18) | Set display to 80 columns |
CHR$(21) | Deactivate the 80-column firmware |
CHR$(22) | Scroll display down, preserving cursor position |
CHR$(23) | Scroll display up, preserving cursor position |
CHR$(24) | Disable mousetext |
CHR$(25) | Move cursor to upper left (but do not clear window) |
CHR$(26) | Clear the current line |
CHR$(27) | Enable mousetext |
CHR$(28) | Forward space (move cursor right, wrap down) |
CHR$(29) | Clear from cursor position to end of line |
The text window can be changed and cursor finely controlled
with POKE 32,n
... POKE 37,n
For the even geekier in the audience...
Compilation is done by splitting the input into tokens which are then consumed by a recursive descent parser which outputs a JavaScript object representing the program.
The token types (treated as terminals) are
reserved
,
identifier
,
string-literal
,
number-literal
[5],
operator
,
line-number
,
separator
,
remark
,
data-declaration
— take a peek at the code if you want the gruesome details. Source lines may
only start with line numbers or (as an extension) separators. Special statement
parsing is done while lexing: REM
consumes anything to the next
line break, and DATA
statements yield an array of strings
from the comma-delimited, optionally-quoted values in the source.
Overall program parsing is done with a recursive descent parser.
Program = Line { Line } Line = line-number Statement { separator Statement } Statement = data-declaration | remark | Command | EmptyStatement Command = identifier /*...*/ | reserved /*...*/
Due to the irregular structure of the BASIC language, statements ("commands" in the above grammar) are parsed with distinct cases for each statement type. Most statements compile into a function call to a library of Applesoft routines. Expressions are parsed with a standard recursive descent parser. The parser generates JavaScript expressions for each expression, which are used as arguments for the library calls.
Expression = OrExpression OrExpression = AndExpression { 'OR' AndExpression } AndExpression = RelationalExpression { 'AND' RelationalExpression } RelationalExpression = AdditiveExpression { ('=' | '<' | '>' | '<=' | '=<' | '>=' | '=>' | '<>' | '><') AdditiveExpression } AdditiveExpression = MultiplicativeExpression { ( '+' | '-' ) MultiplicativeExpression } MultiplicativeExpression = PowerExpression { ( '*' | '/' ) PowerExpression } PowerExpression = UnaryExpression { '^' UnaryExpression } UnaryExpression = ( '+' | '-' | 'NOT' ) UnaryExpression | FinalExpression FinalExpression = number-literal | string-literal | 'FN' user_function_name '(' Expression ')' | reserved '(' Expression { ',' Expression } ')' | identifier [ '(' Expression { ',' Expression } ')' ] | '(' Expression ')'
Since Applesoft supports re-entrant error handling and synchronous input, the output of the compiler is an array of statement-functions plus an executor function which implements the logic for walking over the array.
DEF FN
supports string and integer functions
e.g. DEF FN IN$(X$) = " " + X$
— the return type must match the argument type, so string-to-number or number-to-string functions
can not be implemented.
==
is supported for equality comparisons, with the same meaning as "single equals" =
CHR$()
values greater than 255 generate glyphs that might be useful for implementing certain maze games. (An earlier version of this page allowed arbitrary Unicode characters to be displayed, but the text is now displayed using bitmaps so that is not possible.)
HSCRN(x,y)
is added to allow reading the
hires screen. On a real Apple II this required a machine-language routine (or a shape table and XDRAW
) and
extensive knowledge of the Apple II's color generation scheme.
$
as a prefix, e.g. POKE $C010, 0