# Applesoft BASIC

This document describes the syntax, commands, and features of Applesoft BASIC — the dialect of BASIC shipped with the Apple II computer (1977). Based on the tutorial by Yuri Yakimenko (https://www.hoist-point.com/applesoft_basic_tutorial.htm). Online simulator: https://www.calormen.com/jsbasic/

## Syntax

Each line starts with a line number (0–63999), typically in increments of 10. Multiple commands on one line are separated by `:`.

```basic
10 REM This is a comment
20 HOME : TEXT
30 LET A = 5 : B = 10   :REM multiple commands on one line
40 PRINT "HELLO"
50 END
```

`REM` — comment until end of line. `END` terminates the program. Empty lines are allowed.

## Full Command List

### Input/Output
| Command | Description |
|---------|-------------|
| `PRINT expr` | Output to screen (`, ` = tab, `;` = no newline) |
| `INPUT ["prompt";] var` | Read keyboard input |
| `GET var` | Wait for a single keypress |
| `HOME` | Clear the screen |
| `TEXT` | Switch to 40×24 text mode |
| `VTAB n` | Set cursor vertical position (1–24) |
| `HTAB n` | Set cursor horizontal position (1–40) |
| `SPEED= n` | Output speed (0–255, 0 = slow) |
| `INVERSE` / `NORMAL` / `FLASH` | Text color modes |

### Control Flow
| Command | Description |
|---------|-------------|
| `IF cond THEN cmds` | Conditional execution |
| `IF cond GOTO line` | Conditional jump (alternative to THEN) |
| `GOTO line` | Unconditional jump |
| `GOSUB line` | Call subroutine |
| `RETURN` | Return from subroutine |
| `ON X GOTO a1,a2,...` | Computed GOTO |
| `ON X GOSUB a1,a2,...` | Computed GOSUB |
| `FOR V = S TO E [STEP N]` | Loop start |
| `NEXT [V]` | Loop end |
| `END` / `STOP` / `CONT` | Stop / pause / continue |

### Data
| Command | Description |
|---------|-------------|
| `LET V = expr` | Assignment (LET is optional) |
| `DIM V(n)` | Declare an array |
| `DATA v1, v2, ...` | Static in-program data |
| `READ V` | Read from DATA |
| `RESTORE` | Reset DATA pointer to start |
| `DEF FN name(X) = expr` | Single-line user function |

### Graphics (Low-res — 40×40, 16 colors)
| Command | Description |
|---------|-------------|
| `GR` | Enter low-res graphics mode |
| `COLOR= n` | Set color (0–15) |
| `PLOT x,y` | Draw a pixel |
| `HLIN x1,x2 AT y` | Horizontal line |
| `VLIN y1,y2 AT x` | Vertical line |
| `SCRN(x,y)` | Get pixel color |

### Graphics (Hi-res — 280×192, 6 colors)
| Command | Description |
|---------|-------------|
| `HGR` | Hi-res 280×160 + 4 text rows |
| `HGR2` | Hi-res 280×192, full screen |
| `HCOLOR= n` | Set color (0=black, 1=green, 2=violet, 3=white, 4=black, 5=orange, 6=blue, 7=white) |
| `HPLOT x,y` | Draw a pixel |
| `HPLOT x1,y1 TO x2,y2` | Draw a line |
| `HPLOT x1,y1 TO x2,y2 TO x3,y3` | Polyline |

### Error Handling & System
| Command | Description |
|---------|-------------|
| `ONERR GOTO line` | Jump to line on any error |
| `POKE 216,0` | Disable ONERR |
| `PEEK(222)` | Get last error code |
| `PEEK(49152)` | Check if key pressed (>127 = pressed) |
| `CALL -936` | Clear screen (ROM-based HOME) |
| `CALL -3072` | Switch to hi-res output |
| `TRACE` / `NOTRACE` | Debug mode (show line numbers as executed) |

### Applesoft BASIC Error Codes
| Code | Description |
|------|-------------|
| 22 | RETURN without GOSUB |
| 42 | Out of data |
| 53 | Illegal quantity |
| 69 | Overflow |
| 77 | Out of memory |
| 107 | Bad subscript |
| 133 | Division by zero |
| 163 | Type mismatch |
| 224 | Undefined function |

## Variables

| Type | Format | Example |
|------|--------|---------|
| Numeric | 1–2 letters + optional digit | `A`, `B5`, `AB` |
| String | Same rules + `$` | `A$`, `S$`, `N1$` |
| Numeric array | `DIM A(N)` | `A(5)` |
| String array | `DIM A$(N)` | `A$(10)` |

**IMPORTANT:** Applesoft BASIC only uses the FIRST 2 CHARACTERS of a variable name. `TOTAL` and `TOMATO` are the same variable (`TO`). `A` and `A1` are also the same.

## Functions

### Math
| Function | Result |
|----------|--------|
| `INT(x)` | Integer part |
| `SQR(x)` | Square root |
| `ABS(x)` | Absolute value |
| `SGN(x)` | Sign (-1, 0, 1) |
| `RND(x)` | Pseudo-random [0, 1). `RND(1)` = next, `RND(0)` = repeat last, `RND(-N)` = seed |
| `SIN(x)` / `COS(x)` / `TAN(x)` | Trigonometry (x in radians) |
| `ATN(x)` | Arctangent (result in radians) |
| `EXP(x)` / `LOG(x)` | Exponential / natural log |

### String
| Function | Result |
|----------|--------|
| `LEN(s$)` | String length |
| `VAL(s$)` | String → number |
| `STR$(n)` | Number → string |
| `CHR$(code)` | ASCII code → character |
| `ASC(s$)` | First character → ASCII code |
| `LEFT$(s$, n)` | First n characters |
| `RIGHT$(s$, n)` | Last n characters |
| `MID$(s$, b, l)` | Substring starting at b, length l |

### DEF FN
```basic
10 DEF FN ROUND(X) = INT(X + 0.5)
20 DEF FN POW2(N) = N * N
30 PRINT FN POW2(5)   :REM → 25
```

Limitations: 1 argument, 1 line. Name must not conflict with built-ins (first 3 letters checked). `FN COSD` is an error (conflicts with `COS`), use `FN DCOS` instead.

## What Applesoft BASIC is MISSING

| Missing | Workaround |
|---------|------------|
| IF-THEN-ELSE | `IF cond THEN ... : GOTO skip` + `skip REM else code` |
| MOD (modulo) | `C = A - INT(A/B)*B` |
| DO/WHILE | `IF cond GOTO line` |
| EXIT FOR | `I = 9999 : NEXT I` |
| INKEY$ | `PEEK(49152)` + `GET K$` |
| Local variables | Everything is global |
| Bitwise ops (AND/OR/XOR) | Not available (these are logical operators only) |

### IF-THEN-ELSE workaround
```basic
10 IF A > B THEN PRINT "A > B" : GOTO 30
20 PRINT "A <= B"
30 REM continue
```

### MOD workaround
```basic
C = A - INT(A/B) * B
```

### EXIT FOR workaround
```basic
100 FOR I = 1 TO 100
110   IF X(I) = 0 THEN I = 100 : GOTO 130
120   PRINT X(I)
130 NEXT I
```

## Examples

### Fibonacci (from the tutorial)
```basic
05 HOME : TEXT : REM Fibonacci numbers
10 LET MAX = 5000
20 LET X = 1 : LET Y = 1
30 IF (X > MAX) GOTO 100
40 PRINT X
50 X = X + Y
60 IF (Y > MAX) GOTO 100
70 PRINT Y
80 Y = X + Y
90 GOTO 30
100 END
```

### Euclidean Algorithm (GCD)
```basic
05 REM Greatest Common Divisor (Euclidean Algorithm)
10 HOME : TEXT
20 LET A = 1071 : LET B = 462
30 IF A < B THEN C = A : A = B : B = C
40 PRINT A, B
50 LET C = A - INT(A / B) * B : REM C = A MOD B
60 LET A = B : B = C
70 IF B > 0 GOTO 40
80 PRINT "GCD is "; A
90 END
```

### String reverse with GOSUB
```basic
10 TEXT : HOME
20 INPUT "Enter a string: "; S$
30 IF LEN(S$) = 0 GOTO 90
40 GOSUB 400
50 PRINT "------------"
60 PRINT R$
80 GOTO 20
90 PRINT "FINISHING"
100 END

300 REM reverse a string (MID$ method)
310 LET L = LEN(S$) : R$ = ""
320 FOR I = L TO 1 STEP -1
330   R$ = R$ + MID$(S$, I, 1)
340 NEXT
350 RETURN

400 REM reverse a string (LEFT$/RIGHT$ method)
410 LET L = LEN(S$) : R$ = ""
420 FOR I = 1 TO L
430   R$ = R$ + LEFT$(RIGHT$(S$, I), 1)
440 NEXT
450 RETURN
```

### Data-driven bitmap letter
```basic
5 GR : HOME
10 COLOR = 9
15 FOR ROW = 0 TO 10
20   FOR COL = 0 TO 7
25     READ N : IF N = 0 GOTO 40
30     PLOT COL + 10, ROW + 10
35     FOR D = 1 TO 100 : NEXT D
40   NEXT COL
45 NEXT ROW
50 FOR D = 1 TO 500 : NEXT D : COLOR = 5 : GOTO 15
1000 DATA 0,0,1,1,1,1,0,0
1010 DATA 0,1,0,0,0,0,1,0
1020 DATA 1,0,0,0,0,0,0,1
1030 DATA 1,0,0,0,0,0,0,1
1040 DATA 1,0,0,0,0,0,0,1
1050 DATA 1,0,0,0,0,1,1,0
1060 DATA 1,0,0,0,0,0,0,1
1070 DATA 1,0,0,0,0,0,0,1
1080 DATA 1,0,0,0,0,0,0,1
1090 DATA 0,1,0,0,0,0,1,0
1100 DATA 0,0,1,1,1,1,0,0
```

### Circle drawing (midpoint algorithm)
```basic
10 HGR2 : INPUT "RADIUS (1-96): "; R
15 R2 = R * R : X = 0 : Y = R : HCOLOR = 3
30 HPLOT X, Y : HPLOT -X, Y : HPLOT X, -Y : HPLOT -X, -Y
50 HPLOT Y, X : HPLOT -Y, X : HPLOT Y, -X : HPLOT -Y, -X
60 X = X + 1 : Y = SQR(R2 - X * X)
70 IF X <= Y GOTO 30
80 END
```

### Circle with COS/SIN
```basic
10 HGR2 : PI = 3.14159265 : R = 96
30 FOR A = 0 TO 2 * PI STEP PI / 30
40   X = R * COS(A) + 140 : Y = R * SIN(A) + 96
50   IF A = 0 THEN HPLOT X,Y : GOTO 70
60   HPLOT TO X, Y
70 NEXT A
```

### Non-blocking keyboard (Snake prototype)
```basic
10 TEXT : HOME
20 X = 20 : Y = 12
30 POKE -16368, 0
40 IF PEEK(49152) < 128 GOTO 40
50 GET K$ : C = ASC(K$)
70 IF C = 8 THEN X = X - 1  :REM left arrow
80 IF C = 21 THEN X = X + 1 :REM right arrow
90 IF C = 11 THEN Y = Y - 1 :REM up
100 IF C = 10 THEN Y = Y + 1 :REM down
110 VTAB Y : HTAB X : PRINT "A";
130 GOTO 30
```

### Random seed + dice histogram (advanced)
```basic
10 REM uses GET + counter for random seed
20 PRINT "PRESS ANY KEY TO START"
30 GET K$ : IF K$ = "" THEN C = C + 1 : GOTO 30
40 X = RND(-C)
50 REM now RND(1) produces different sequences
```

## ASCII key codes

| Key | ASCII | Notes |
|-----|-------|-------|
| ← (left) | 8 | |
| → (right) | 21 | |
| ↑ (up) | 11 | |
| ↓ (down) | 10 | |
| Space | 32 | |
| Escape | 27 | |
| '0'-'9' | 48–57 | |
| 'A'-'Z' | 65–90 | |
| 'a'-'z' | 97–122 | |

## Dithering (mixing HGR colors)

To get more than 6 colors — draw a checkerboard pattern of two colors:
- Even rows color A, odd rows color B (50/50 mix)
- Diagonal lines of colors A and B

This yields up to 21 distinct colors from 6 base colors.

## Pitfalls

1. **2-character variable names:** `TOTAL` and `TOMATO` are the same variable (`TO`)
2. **DATA reading order:** DATA lines are merged in line-number order, NOT source-file order
3. **HOME doesn't clear HGR:** HOME only works in TEXT mode
4. **HGR resets HCOLOR:** must set `HCOLOR=` again after entering HGR/HGR2
5. **Missing END before subroutines:** the main code will fall through into subroutines
6. **ONERR must be disabled:** call `POKE 216,0` after handling an error
7. **ON GOTO with 0:** not an error — just proceeds to the next line
8. **FOR with float STEP:** rounding errors accumulate
9. **Execution order:** by line number, not file order

## Full command list (alphabetical)

`ABS`, `AND`, `ASC`, `ATN`, `CALL`, `CHR$`, `CLEAR`, `COLOR=`, `CONT`, `COS`, `DATA`, `DEF FN`, `DEL`, `DIM`, `END`, `EXP`, `FLASH`, `FOR`, `FRE`, `GET`, `GOSUB`, `GOTO`, `GR`, `HCOLOR=`, `HGR`, `HGR2`, `HLIN`, `HOME`, `HPLOT`, `HTAB`, `IF`, `INPUT`, `INT`, `INVERSE`, `LEFT$`, `LEN`, `LET`, `LOG`, `MID$`, `NEW`, `NEXT`, `NORMAL`, `NOT`, `NOTRACE`, `ON`, `ONERR`, `OR`, `PDL`, `PEEK`, `PLOT`, `POKE`, `POP`, `POS`, `PRINT`, `READ`, `RECALL`, `REM`, `RESTORE`, `RESUME`, `RETURN`, `RIGHT$`, `RND`, `RUN`, `SAVE`, `SCRN(`, `SGN`, `SIN`, `SPEED=`, `SQR`, `STEP`, `STOP`, `STORE`, `STR$`, `TAB(`, `TAN`, `TEXT`, `THEN`, `TO`, `TRACE`, `USR`, `VAL`, `VLIN`, `VTAB`, `WAIT`, `XPLOT`, `XDRAW`

## Useful links

- Online simulator: https://www.calormen.com/jsbasic/
- 20-lesson tutorial: https://www.hoist-point.com/applesoft_basic_tutorial.htm
- Example code files: https://www.hoist-point.com/basic/*.txt
- Applesoft BASIC Reference Manual
