c64bridge 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -5
- package/data/assembly/assembly-spec.md +24 -0
- package/data/assembly/examples/video/hello_world.asm +39 -0
- package/data/basic/basic-pitfalls.md +236 -0
- package/data/basic/basic-spec.md +507 -198
- package/data/video/petscii-style-guide.md +105 -0
- package/data/video/sprite-charset-best-practices.md +292 -0
- package/dist/c64Client.js +1 -0
- package/dist/prompts/registry.js +10 -2
- package/dist/rag/knowledgeIndex.js +111 -24
- package/dist/rag/retriever.js +110 -4
- package/dist/tools/audio.js +26 -13
- package/dist/tools/developer.js +34 -0
- package/dist/tools/graphics.js +6 -5
- package/dist/tools/memory.js +1 -1
- package/dist/tools/pollValidator.js +256 -0
- package/dist/tools/programRunners.js +352 -12
- package/dist/tools/rag.js +1 -7
- package/doc/MCP_SETUP.md +7 -1
- package/doc/bun/baseline-metrics.md +16 -0
- package/doc/bun/migration-checklist.md +55 -0
- package/doc/bun/migration.md +83 -0
- package/doc/developer.md +72 -10
- package/doc/improve-knowledge/notes.md +29 -0
- package/doc/improve-knowledge/plan.md +28 -3
- package/doc/improve-knowledge/rollout.md +39 -5
- package/doc/meta-tools/README.md +101 -0
- package/doc/meta-tools/analysis.md +255 -0
- package/doc/{meta-tools.md → meta-tools/catalog.md} +2 -2
- package/doc/meta-tools/notes.md +174 -0
- package/doc/meta-tools/rollout.md +343 -0
- package/mcp.json +1 -1
- package/package.json +17 -10
- package/scripts/c64-cli.mjs +42 -7
- package/scripts/c64-tool.sh +7 -1
- package/scripts/check-node-compat.mjs +107 -0
- package/scripts/invoke-bun.mjs +58 -0
- package/scripts/rag-rebuild.mjs +11 -13
- package/scripts/run-mcp-check.sh +10 -2
- package/scripts/run-tests.mjs +3 -3
- package/scripts/run-tests.ts +187 -0
- package/scripts/start.mjs +3 -26
- package/scripts/update-readme.ts +17 -1
- package/scripts/verify-package.mjs +0 -1
- package/data/assembly/examples/effects/sinewave.asm +0 -5
- package/doc/meta-tools-rollout.md +0 -211
- package/scripts/register-ts-node.mjs +0 -6
- /package/data/assembly/examples/{graphics/sprite/mover.asm → video/sprite_mover.asm} +0 -0
package/data/basic/basic-spec.md
CHANGED
|
@@ -1,49 +1,192 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Commodore 64 BASIC V2 Specification
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1. Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
C64 BASIC V2 is a line-numbered, interpreted, tokenised language stored in ROM.
|
|
6
|
+
Each program consists of linked line records beginning at `$0801`, and executes sequentially unless redirected by explicit control flow. The interpreter manages variables, arrays, and strings in RAM regions immediately following the program text.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 2. Memory and Program Layout
|
|
11
|
+
|
|
12
|
+
### 2.1 System Pointers (Zero Page)
|
|
13
|
+
|
|
14
|
+
| Name | Address | Meaning |
|
|
15
|
+
|------|----------|----------|
|
|
16
|
+
| **TXTTAB** | `$002B–002C` | Start of BASIC text (default `$0801`) |
|
|
17
|
+
| **VARTAB** | `$002D–002E` | Start of variable table |
|
|
18
|
+
| **ARYTAB** | `$002F–0030` | Start of array storage |
|
|
19
|
+
| **STREND** | `$0031–0032` | End of arrays (+1) |
|
|
20
|
+
| **FRETOP** | `$0033–0034` | Bottom of string storage |
|
|
21
|
+
| **MEMSIZ** | `$0037–0038` | Highest BASIC RAM address |
|
|
22
|
+
|
|
23
|
+
Variables grow upward from `TXTTAB`; strings grow downward from `MEMSIZ`.
|
|
24
|
+
`ARYTAB` always follows `VARTAB`; defining new scalars after arrays shifts array memory upward by 7 bytes per variable.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### 2.2 BASIC Program Storage (PRG Format)
|
|
29
|
+
|
|
30
|
+
Each BASIC program in memory (and on disk/tape) is a contiguous block:
|
|
8
31
|
|
|
9
|
-
|
|
32
|
+
| Field | Size | Description |
|
|
33
|
+
|--------|------|-------------|
|
|
34
|
+
| Load address | 2 bytes | `$0801` little-endian |
|
|
35
|
+
| Next line pointer | 2 bytes | Absolute address of next line |
|
|
36
|
+
| Line number | 2 bytes | 0–65535 |
|
|
37
|
+
| Tokenised PETSCII text | variable | Zero-terminated statement list |
|
|
38
|
+
| Terminator | 2 bytes | Final `$0000` sentinel |
|
|
39
|
+
|
|
40
|
+
Pointers increase monotonically. The final record’s pointer references the terminator.
|
|
41
|
+
Tokenisation replaces keywords by single-byte codes (`$80–$CB`), ignoring quoted strings and `REM` comments. Empty lines are stored as a single `$20` (space).
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 3. Variables and Data Model
|
|
46
|
+
|
|
47
|
+
### 3.1 Variable Types
|
|
48
|
+
|
|
49
|
+
All variables occupy **7 bytes** in the variable table.
|
|
50
|
+
The first two bytes encode the name and type; the remaining bytes store the data or descriptor.
|
|
10
51
|
|
|
11
52
|
| Type | Suffix | Range | Storage | Notes |
|
|
12
53
|
|------|---------|--------|----------|-------|
|
|
13
|
-
| **Real (Float)** | none | ±2.9×10⁻³⁸ … ±1.7×10³⁸ |
|
|
14
|
-
| **Integer** | `%` | −32768 … 32767 | 2 bytes |
|
|
15
|
-
| **String** | `$` | 0–255 chars |
|
|
54
|
+
| **Real (Float)** | none | ±2.9×10⁻³⁸ … ±1.7×10³⁸ | 1-byte exponent + 4-byte mantissa | Default numeric type, ≈9.6-digit precision. |
|
|
55
|
+
| **Integer** | `%` | −32768 … 32767 | 2 bytes (hi-lo) | High bit set on both name bytes; slower than float due to conversion. |
|
|
56
|
+
| **String** | `$` | 0–255 chars | 1-byte length + 2-byte pointer | High bit set on second name byte; pointer references PETSCII data. |
|
|
57
|
+
| **Boolean** | — | `0` (FALSE), `−1` or any non-zero (TRUE) | Numeric representation | Implemented via integers. |
|
|
16
58
|
|
|
17
|
-
|
|
59
|
+
#### Name Encoding
|
|
18
60
|
|
|
19
|
-
|
|
61
|
+
- Only first two letters significant (`CO`, `COCOS` → same variable).
|
|
62
|
+
- Letters A–Z, digits 0–9; must start with a letter.
|
|
63
|
+
- Case-insensitive; stored uppercase.
|
|
64
|
+
- Type suffix distinguishes variants (`A`, `A%`, `A$`).
|
|
65
|
+
- Reserved names: `ST`, `TI`, `TI$`, `FN`, and all keywords.
|
|
66
|
+
- Max name length ≈ 80 characters (logical line length).
|
|
20
67
|
|
|
21
|
-
|
|
22
|
-
- Type suffix (`%`, `$`) distinguishes otherwise identical names.
|
|
23
|
-
- Allowed: `A–Z`, `0–9`; must start with a letter.
|
|
24
|
-
- Keywords and system variables (`ST`, `TI`, `TI$`, `FN`) are reserved.
|
|
25
|
-
- Maximum logical name length ≈80 characters.
|
|
68
|
+
**Example collision:**
|
|
26
69
|
|
|
27
|
-
|
|
70
|
+
```
|
|
71
|
+
10 A$="1":AA$="2":AAA$="3":PRINT A$,AA$,AAA$
|
|
72
|
+
→ 1 3 3
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### 3.2 Internal Representation
|
|
78
|
+
|
|
79
|
+
| Offset | Field | Description |
|
|
80
|
+
|--------:|--------|-------------|
|
|
81
|
+
| 0–1 | Name (2 chars) with high bits as type markers | Identifier |
|
|
82
|
+
| 2–6 | Data payload | Depends on type |
|
|
83
|
+
|
|
84
|
+
**Encoding rules:**
|
|
85
|
+
|
|
86
|
+
- *Real*: ASCII name, 2nd byte zero if single char.
|
|
87
|
+
- *Integer*: both name bytes have high-bit set.
|
|
88
|
+
- *String*: only 2nd byte has high-bit set.
|
|
89
|
+
|
|
90
|
+
**Payload:**
|
|
91
|
+
|
|
92
|
+
- Real: exponent + mantissa (5 bytes).
|
|
93
|
+
- Integer: 2-byte value, 3 bytes padding 0.
|
|
94
|
+
- String: length (1 byte), pointer (2 bytes LE), padding 0s.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### 3.3 Arrays
|
|
99
|
+
|
|
100
|
+
Declared via `DIM`, e.g. `DIM A(7)` (indices 0–7).
|
|
101
|
+
If a program uses an array without prior `DIM`, BASIC auto-DIMs it to 11 elements per dimension (0–10).
|
|
102
|
+
Re-DIMing → `?REDIM'D ARRAY ERROR`.
|
|
103
|
+
Index < 0 or > 32767 → `?ILLEGAL QUANTITY ERROR`.
|
|
104
|
+
|
|
105
|
+
#### Internal Layout
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
name(2) , offset_to_next(2) , dimensions(1) ,
|
|
109
|
+
length1(2) [, length2(2)...] , data...
|
|
110
|
+
```
|
|
28
111
|
|
|
29
|
-
|
|
112
|
+
- Offset is relative to next array (for relocation).
|
|
113
|
+
- `dimensions` = number of axes (1–255 theoretical).
|
|
114
|
+
- Each element stored in ascending index order; leftmost index varies fastest.
|
|
115
|
+
- Element sizes: Real 5 B, Integer 2 B, String 3 B descriptor.
|
|
30
116
|
|
|
31
|
-
|
|
117
|
+
**Examples:**
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
DIM C%(2,3) → 3×4 = 12 integers
|
|
121
|
+
DIM S$(1,2,3) → 2×3×4 = 24 string descriptors
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### 3.4 Strings
|
|
127
|
+
|
|
128
|
+
Strings hold PETSCII text of up to 255 chars.
|
|
129
|
+
The descriptor’s pointer targets either:
|
|
130
|
+
|
|
131
|
+
- an in-place literal within BASIC text (for quoted constants), or
|
|
132
|
+
- an allocated region in the **string heap** (descending from `FRETOP`).
|
|
133
|
+
|
|
134
|
+
New strings are created whenever:
|
|
135
|
+
|
|
136
|
+
- concatenation (`+`),
|
|
137
|
+
- substring (`LEFT$`, `MID$`, `RIGHT$`),
|
|
138
|
+
- or runtime expression evaluation occurs.
|
|
139
|
+
|
|
140
|
+
No garbage collection exists. `CLR` or `NEW` frees all strings.
|
|
141
|
+
|
|
142
|
+
**Efficiency notes**
|
|
143
|
+
|
|
144
|
+
- Prefer `PRINT A$;B$` instead of `PRINT A$+B$` (no new allocation).
|
|
145
|
+
- Define and reuse variables to prevent heap growth.
|
|
146
|
+
- Direct-mode string operations always allocate temporary strings.
|
|
147
|
+
|
|
148
|
+
**Advanced manipulation:**
|
|
149
|
+
By modifying the descriptor at `VARTAB` (length and pointer), one can create scrolling or “windowed” text effects without copying data.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### 3.5 Variable Optimisation Guidelines
|
|
154
|
+
|
|
155
|
+
- Declare scalar variables before arrays (avoids array shifting).
|
|
156
|
+
- Use short two-character names for speed.
|
|
157
|
+
- Avoid redundant `LET`.
|
|
158
|
+
- Keep string operations minimal in loops.
|
|
159
|
+
- Use `FRE(0)` to inspect available memory (16-bit signed).
|
|
160
|
+
- To locate start of variable table:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
VT = PEEK(46)*256 + PEEK(45)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 4. Operators
|
|
32
169
|
|
|
33
170
|
| Rank | Operators | Description |
|
|
34
171
|
|------|------------|-------------|
|
|
35
172
|
| 1 | `^` | Exponentiation |
|
|
36
|
-
| 2 | unary
|
|
37
|
-
| 3 |
|
|
38
|
-
| 4 |
|
|
39
|
-
| 5 |
|
|
40
|
-
| 6 | `NOT` | Logical NOT |
|
|
41
|
-
| 7 | `AND` | Logical AND |
|
|
42
|
-
| 8 | `OR` | Logical OR |
|
|
173
|
+
| 2 | unary `+ −` | Sign prefix |
|
|
174
|
+
| 3 | `* /` | Multiplication / Division |
|
|
175
|
+
| 4 | `+ −` | Addition, Subtraction, String concatenation |
|
|
176
|
+
| 5 | `< <= = >= > <>` | Comparison |
|
|
177
|
+
| 6 | `NOT` | Logical NOT / bitwise invert |
|
|
178
|
+
| 7 | `AND` | Logical AND / bitwise AND |
|
|
179
|
+
| 8 | `OR` | Logical OR / bitwise OR |
|
|
180
|
+
|
|
181
|
+
Parentheses nest ≤ 10 levels.
|
|
182
|
+
Division by 0 → `?DIVISION BY ZERO`.
|
|
183
|
+
Logical ops on integers act bitwise on 16-bit values.
|
|
184
|
+
|
|
185
|
+
---
|
|
43
186
|
|
|
44
|
-
|
|
187
|
+
## 5. Syntax Definition (EBNF)
|
|
45
188
|
|
|
46
|
-
|
|
189
|
+
*(Complete grammar retained for program analysis)*
|
|
47
190
|
|
|
48
191
|
```
|
|
49
192
|
program = { line }, endmarker ;
|
|
@@ -51,180 +194,346 @@ line = nextptr word , lineno word , stmtlist , 0x00 ;
|
|
|
51
194
|
stmtlist = statement , { ":" , statement } ;
|
|
52
195
|
|
|
53
196
|
statement =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
expr
|
|
78
|
-
term
|
|
79
|
-
factor
|
|
80
|
-
relation
|
|
81
|
-
sum
|
|
82
|
-
product
|
|
83
|
-
power
|
|
84
|
-
unary
|
|
85
|
-
primary
|
|
86
|
-
|
|
87
|
-
fncall
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
printlist = [ expr | "#" , expr ] , { "," | ";" , [ expr | "#" , expr ] } ;
|
|
93
|
-
varlist = var , { "," , var } ;
|
|
94
|
-
datalist = datum , { "," , datum } ;
|
|
95
|
-
datum = number | string | expr ;
|
|
96
|
-
|
|
97
|
-
fname = string ; dev = expr ; secdev = expr ; fnameMode = string ;
|
|
98
|
-
lineno = 0..65535 ;
|
|
99
|
-
var = name [ "%" | "$" ] ; fnname = "FN" , name ;
|
|
100
|
-
name = letter , { letter | digit } ;
|
|
101
|
-
prompt = string , ";" ;
|
|
102
|
-
listRange = lineno | "-" , lineno | lineno , "-" ;
|
|
103
|
-
number = integer | float ; string = quoted PETSCII ;
|
|
197
|
+
"REM" , { <any PETSCII except CR> } |
|
|
198
|
+
"FOR" , var , "=" , expr , "TO" , expr , [ "STEP" , expr ] |
|
|
199
|
+
"NEXT" , [ var ] |
|
|
200
|
+
"IF" , expr , "THEN" , ( stmtlist | lineno ) |
|
|
201
|
+
( "GOTO" | "GO" , "TO" ) , lineno |
|
|
202
|
+
"GOSUB" , lineno | "RETURN" |
|
|
203
|
+
"ON" , expr , ( "GOTO" | "GOSUB" ) , lineno , { "," , lineno } |
|
|
204
|
+
"DEF" , "FN" , fnname , "(" , var , ")" , "=" , expr |
|
|
205
|
+
"INPUT" , [ prompt ] , varlist | "GET" , var | "PRINT" , [ printlist ] |
|
|
206
|
+
"OPEN" , expr , "," , expr , [ "," , expr , [ "," , fnameMode ] ] |
|
|
207
|
+
"CLOSE" , expr | "CMD" , expr , [ "," , exprlist ] |
|
|
208
|
+
"LOAD" , fname [ "," , dev [ "," , secdev ] ] |
|
|
209
|
+
"SAVE" , fname [ "," , dev [ "," , secdev ] ] |
|
|
210
|
+
"VERIFY" , fname [ "," , dev [ "," , secdev ] ] |
|
|
211
|
+
"READ" , varlist | "RESTORE" | "DATA" , datalist |
|
|
212
|
+
"POKE" , expr , "," , expr | "PEEK" , "(" , expr , ")" |
|
|
213
|
+
"WAIT" , expr , "," , expr , [ "," , expr ] |
|
|
214
|
+
"SYS" , expr , { "," , expr } | var , "=" , expr |
|
|
215
|
+
"USR" , "(" , expr , ")" |
|
|
216
|
+
"RUN" , [ lineno ] | "STOP" | "END" | "CONT" |
|
|
217
|
+
"LIST" , [ listRange ] | "NEW" | "CLR" |
|
|
218
|
+
"FRE" , "(" , expr , ")" ;
|
|
219
|
+
|
|
220
|
+
expr = term , { "OR" , term } ;
|
|
221
|
+
term = factor , { "AND" , factor } ;
|
|
222
|
+
factor= [ "NOT" ] , relation ;
|
|
223
|
+
relation = sum , { ( "=" | "<" | ">" | "<=" | ">=" | "<>" ) , sum } ;
|
|
224
|
+
sum = product , { ( "+" | "-" ) , product } ;
|
|
225
|
+
product = power , { ( "*" | "/" ) , power } ;
|
|
226
|
+
power = unary , { "^" , unary } ;
|
|
227
|
+
unary = [ "+" | "-" ] , primary ;
|
|
228
|
+
primary = number | string | var | fncall | "(" , expr , ")" ;
|
|
229
|
+
|
|
230
|
+
fncall = ( "SGN" | "INT" | "ABS" | "USR" | "FRE" | "POS" | "SQR" | "RND" |
|
|
231
|
+
"LOG" | "EXP" | "COS" | "SIN" | "TAN" | "ATN" | "PEEK" | "LEN" |
|
|
232
|
+
"STR$" | "VAL" | "ASC" | "CHR$" | "LEFT$" | "RIGHT$" | "MID$" |
|
|
233
|
+
"TAB" | "SPC" ), "(" , [ expr , { "," , expr } ] , ")" ;
|
|
104
234
|
```
|
|
105
235
|
|
|
106
|
-
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 6. Commands and Functions
|
|
239
|
+
|
|
240
|
+
**Flow Control**
|
|
241
|
+
`FOR–TO–STEP–NEXT`, `IF–THEN`, `GOTO`, `GOSUB`, `RETURN`, `ON–GOTO/GOSUB`, `DEF FN`.
|
|
242
|
+
|
|
243
|
+
**Input/Output**
|
|
244
|
+
`INPUT`, `INPUT#`, `GET`, `PRINT`, `PRINT#`, `SPC(n)`, `TAB(n)`, `POS()`.
|
|
245
|
+
|
|
246
|
+
**File Operations**
|
|
247
|
+
`LOAD`, `SAVE`, `VERIFY`, `OPEN`, `CLOSE`, `CMD`, `ST`.
|
|
248
|
+
|
|
249
|
+
**Data Access**
|
|
250
|
+
`DATA`, `READ`, `RESTORE`.
|
|
251
|
+
|
|
252
|
+
**Math / Logic**
|
|
253
|
+
`ABS`, `ATN`, `COS`, `EXP`, `INT`, `LOG`, `RND`, `SGN`, `SIN`, `SQR`, `TAN`;
|
|
254
|
+
Operators `+ − * / ^ AND OR NOT`.
|
|
255
|
+
|
|
256
|
+
**String Processing**
|
|
257
|
+
`LEN`, `LEFT$`, `RIGHT$`, `MID$`, `STR$`, `VAL`, `ASC`, `CHR$`, `+` (concat).
|
|
107
258
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
259
|
+
**Memory / System**
|
|
260
|
+
`PEEK`, `POKE`, `WAIT`, `SYS`, `USR`.
|
|
261
|
+
|
|
262
|
+
**Program Control**
|
|
263
|
+
`RUN`, `STOP`, `END`, `CONT`, `NEW`, `CLR`, `LIST`, `FRE(0)`.
|
|
264
|
+
|
|
265
|
+
Constants: `π`, `TI`, `TI$`.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## 7. Keywords and Abbreviations (BASIC V2)
|
|
270
|
+
|
|
271
|
+
| Hex | Keyword | Abbrev. | Keystroke | Description |
|
|
272
|
+
|------|----------|----------|------------|-------------|
|
|
273
|
+
| 80 | END | eN | E + Shift-N | End program |
|
|
274
|
+
| 81 | FOR | fO | F + Shift-O | Loop start |
|
|
275
|
+
| 82 | NEXT | nE | N + Shift-E | Loop end |
|
|
276
|
+
| 83 | DATA | dA | D + Shift-A | Literal data |
|
|
277
|
+
| 84 | INPUT# | iN | I + Shift-N | File input |
|
|
278
|
+
| 85 | INPUT | — | — | Keyboard input |
|
|
279
|
+
| 86 | DIM | dI | D + Shift-I | Array declaration |
|
|
280
|
+
| 87 | READ | rE | R + Shift-E | Read DATA |
|
|
281
|
+
| 88 | LET | lE | L + Shift-E | Assignment |
|
|
282
|
+
| 89 | GOTO | gO | G + Shift-O | Branch |
|
|
283
|
+
| 8A | RUN | rU | R + Shift-U | Execute program |
|
|
284
|
+
| 8B | IF | — | — | Conditional |
|
|
285
|
+
| 8C | RESTORE | reS | R,E + Shift-S | Reset DATA pointer |
|
|
286
|
+
| 8D | GOSUB | goS | G,O + Shift-S | Subroutine |
|
|
287
|
+
| 8E | RETURN | reT | R,E + Shift-T | Return |
|
|
288
|
+
| 8F | REM | — | — | Comment |
|
|
289
|
+
| 90 | STOP | sT | S + Shift-T | Halt |
|
|
290
|
+
| 91 | ON | — | — | Indexed branch |
|
|
291
|
+
| 92 | WAIT | wA | W + Shift-A | Wait for mask |
|
|
292
|
+
| 93 | LOAD | lO | L + Shift-O | Load file |
|
|
293
|
+
| 94 | SAVE | sA | S + Shift-A | Save file |
|
|
294
|
+
| 95 | VERIFY | vE | V + Shift-E | Verify file |
|
|
295
|
+
| 96 | DEF | dE | D + Shift-E | Define FN |
|
|
296
|
+
| 97 | POKE | pO | P + Shift-O | Write memory |
|
|
297
|
+
| 98 | PRINT# | pR | P + Shift-R | Output to file |
|
|
298
|
+
| 99 | PRINT | ? | ? key | Output to screen |
|
|
299
|
+
| 9A | CONT | cO | C + Shift-O | Continue |
|
|
300
|
+
| 9B | LIST | lI | L + Shift-I | List program |
|
|
301
|
+
| 9C | CLR | cL | C + Shift-L | Clear vars |
|
|
302
|
+
| 9D | CMD | cM | C + Shift-M | Redirect output |
|
|
303
|
+
| 9E | SYS | sY | S + Shift-Y | Call machine code |
|
|
304
|
+
| 9F | OPEN | oP | O + Shift-P | Open device |
|
|
305
|
+
| A0 | CLOSE | clO | C,L + Shift-O | Close device |
|
|
306
|
+
| A1 | GET | gE | G + Shift-E | Read char |
|
|
307
|
+
| A2 | NEW | — | — | Clear program |
|
|
308
|
+
| A3 | TAB( | tA | T + Shift-A | Tab cursor |
|
|
309
|
+
| A4 | TO | — | — | Range keyword |
|
|
310
|
+
| A5 | FN | — | — | Function prefix |
|
|
311
|
+
| A6 | SPC( | sP | S + Shift-P | Space in print |
|
|
312
|
+
| A7 | THEN | tH | T + Shift-H | IF branch |
|
|
313
|
+
| A8 | NOT | nO | N + Shift-O | Logical NOT |
|
|
314
|
+
| A9 | STEP | stE | S,T + Shift-E | Loop increment |
|
|
315
|
+
| AF | AND | aN | A + Shift-N | Logical AND |
|
|
316
|
+
| B0 | OR | — | — | Logical OR |
|
|
317
|
+
| B4 | SGN | sG | S + Shift-G | Sign |
|
|
318
|
+
| B5 | INT | — | — | Integer truncation |
|
|
319
|
+
| B6 | ABS | aB | A + Shift-B | Absolute |
|
|
320
|
+
| B7 | USR | uS | U + Shift-S | User routine |
|
|
321
|
+
| B8 | FRE | fR | F + Shift-R | Free memory |
|
|
322
|
+
| B9 | POS | — | — | Cursor position |
|
|
323
|
+
| BA | SQR | sQ | S + Shift-Q | Square root |
|
|
324
|
+
| BB | RND | rN | R + Shift-N | Random number |
|
|
325
|
+
| BC | LOG | — | — | Natural log |
|
|
326
|
+
| BD | EXP | eX | E + Shift-X | Exponent |
|
|
327
|
+
| BE | COS | — | — | Cosine |
|
|
328
|
+
| BF | SIN | sI | S + Shift-I | Sine |
|
|
329
|
+
| C0 | TAN | — | — | Tangent |
|
|
330
|
+
| C1 | ATN | aT | A + Shift-T | Arctangent |
|
|
331
|
+
| C2 | PEEK | pE | P + Shift-E | Read memory |
|
|
332
|
+
| C3 | LEN | — | — | String length |
|
|
333
|
+
| C4 | STR$ | stR | S,T + Shift-R | Number→String |
|
|
334
|
+
| C5 | VAL | vA | V + Shift-A | String→Number |
|
|
335
|
+
| C6 | ASC | aS | A + Shift-S | ASCII code |
|
|
336
|
+
| C7 | CHR$ | cH | C + Shift-H | Code→Char |
|
|
337
|
+
| C8 | LEFT$ | leF | L,E + Shift-F | Left substring |
|
|
338
|
+
| C9 | RIGHT$ | rI | R + Shift-I | Right substring |
|
|
339
|
+
| CA | MID$ | mI | M + Shift-I | Middle substring |
|
|
340
|
+
| CB | GO | — | — | Used for GOTO/GOSUB |
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## 8. System Constants and Status
|
|
345
|
+
|
|
346
|
+
| Name | Meaning | Typical Range |
|
|
347
|
+
|------|----------|----------------|
|
|
348
|
+
| `PI` | 3.14159265 | Constant |
|
|
349
|
+
| `ST` | Device status byte | Bit6=EOF, Bit7=No device |
|
|
350
|
+
| `TI` | System tick counter | 1/60s resolution |
|
|
351
|
+
| `TI$` | Time string | "hhmmss" |
|
|
352
|
+
| `FRE(0)` | Free memory in bytes | 0–38911 |
|
|
353
|
+
| `TRUE` | −1 ($FFFF) | Boolean |
|
|
354
|
+
| `FALSE` | 0 | Boolean |
|
|
118
355
|
|
|
119
356
|
---
|
|
120
357
|
|
|
121
|
-
##
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
###
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
358
|
+
## 9. Validation Rules
|
|
359
|
+
|
|
360
|
+
- Line numbers: 0–65535.
|
|
361
|
+
- Each program ends with `$0000` sentinel.
|
|
362
|
+
- Parentheses depth ≤10.
|
|
363
|
+
- Array redefinition prohibited.
|
|
364
|
+
- Division by zero → runtime error.
|
|
365
|
+
- Out-of-memory or string overflow → `?OUT OF MEMORY`.
|
|
366
|
+
- Keyword collision in variable name → `?SYNTAX ERROR`.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## 10. Performance and Optimisation Guidelines
|
|
371
|
+
|
|
372
|
+
C64 BASIC V2 is fully interpreted and float-based. Optimise by reducing parsing, conversions, and heap movement. Every line lookup and variable access incurs cost; fast programs minimise interpreter work.
|
|
373
|
+
|
|
374
|
+
### 10.1 Execution Model
|
|
375
|
+
|
|
376
|
+
- Each line is linked; `GOTO`, `GOSUB`, `IF` search from start. Keep hot loops in low line numbers.
|
|
377
|
+
- Keywords are tokenised; variables and literals parsed at runtime.
|
|
378
|
+
- Numeric work is float unless explicitly integer; type conversions are slow.
|
|
379
|
+
|
|
380
|
+
### 10.2 Variables
|
|
381
|
+
|
|
382
|
+
- Only first two name letters count—use short names.
|
|
383
|
+
- Define scalars before arrays; new scalars shift arrays by 7 B each.
|
|
384
|
+
- Floats faster than integers; mixed arithmetic incurs conversion.
|
|
385
|
+
- `FRE(0)` scans all variables—use sparingly.
|
|
386
|
+
- Use 0 and −1 for Boolean logic.
|
|
387
|
+
|
|
388
|
+
### 10.3 Arrays
|
|
389
|
+
|
|
390
|
+
- Always `DIM`; undeclared arrays auto-DIM 11 elements per dimension.
|
|
391
|
+
- Re-DIM → error; index 0–32767 only.
|
|
392
|
+
- Keep dimensions small and fixed; leftmost index varies fastest.
|
|
393
|
+
|
|
394
|
+
### 10.4 Arithmetic
|
|
395
|
+
|
|
396
|
+
- Replace `^` with multiplication; pre-compute constants and function results.
|
|
397
|
+
- `INT(X)` faster than truncation math; avoid mixing ints/floats.
|
|
398
|
+
- Keep loops tight; each iteration re-parses expressions.
|
|
399
|
+
|
|
400
|
+
### 10.5 Strings
|
|
401
|
+
|
|
402
|
+
- Heap grows downward, no garbage collection.
|
|
403
|
+
- Avoid `A$=A$+B$` in loops; prefer `PRINT A$;B$`.
|
|
404
|
+
- Reuse string vars; overwrite via `MID$` instead of reallocating.
|
|
405
|
+
- Use `CLR` to reclaim heap; `LEFT$/RIGHT$/MID$` create new descriptors—use sparingly.
|
|
406
|
+
|
|
407
|
+
### 10.6 Control Flow
|
|
408
|
+
|
|
409
|
+
- Prefer `FOR…NEXT` to manual `GOTO` loops.
|
|
410
|
+
- Keep `IF` expressions short; parser re-evaluates every branch.
|
|
411
|
+
- Combine short statements with `:` (< 80 chars per line).
|
|
412
|
+
- Limit nesting depth (< 5) for readability and speed.
|
|
413
|
+
|
|
414
|
+
### 10.7 Program Structure & I/O
|
|
415
|
+
|
|
416
|
+
- Put constants/setup early; `DATA` and rarely used routines last.
|
|
417
|
+
- Remove `REM` in loops; still parsed.
|
|
418
|
+
- Minimise disk/tape/printer I/O; buffer in memory.
|
|
419
|
+
- `CMD` redirection is slow—set once.
|
|
420
|
+
- Avoid frequent `TI$`; use loop counters instead.
|
|
421
|
+
- Use `SYS` for time-critical routines.
|
|
422
|
+
|
|
423
|
+
### 10.8 Memory Use
|
|
424
|
+
|
|
425
|
+
- Each scalar = 7 B; arrays store only element data.
|
|
426
|
+
- Pack short related statements on one line.
|
|
427
|
+
- Use abbreviations (`?`, `gO`, `sT`) to stay within 80 chars.
|
|
428
|
+
- Maintain ≥ 50 % free RAM for string heap stability.
|
|
429
|
+
- Call `CLR` to drop unused variables.
|
|
430
|
+
|
|
431
|
+
### 10.9 Summary
|
|
432
|
+
|
|
433
|
+
Fast BASIC = minimal parsing, fixed data, short names, reused strings, few allocations.
|
|
434
|
+
Define vars early, pre-DIM arrays, keep loops shallow, and avoid heap churn.
|
|
435
|
+
Typical speed gain: 2–5× over unoptimised code.
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## 11. Writing Games Efficiently in BASIC
|
|
440
|
+
|
|
441
|
+
C64 BASIC games rely on careful screen, input, and timing control. Interpreter speed limits frame rate; optimise for responsiveness, not raw throughput.
|
|
442
|
+
|
|
443
|
+
### 11.1 Core Strategy
|
|
444
|
+
|
|
445
|
+
- BASIC handles logic; graphics/sound via `POKE` to hardware.
|
|
446
|
+
- Use fixed variables and arrays; avoid runtime string creation.
|
|
447
|
+
- Keep main loop short and predictable.
|
|
448
|
+
|
|
449
|
+
### 11.2 Screen Handling
|
|
450
|
+
|
|
451
|
+
- Screen RAM $0400 (1024 dec); Colour RAM $D800 (55296 dec).
|
|
452
|
+
- `PRINT` is slow; use direct writes:
|
|
453
|
+
|
|
454
|
+
```basic
|
|
455
|
+
POKE1024+X+40*Y,CHR
|
|
456
|
+
POKE55296+X+40*Y,COLOR
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
- Redraw only modified cells; update deltas, not full screen.
|
|
460
|
+
- For static backgrounds, draw once, then update moving parts.
|
|
461
|
+
- To clear screen, loop over $0400/$D800 ranges.
|
|
462
|
+
|
|
463
|
+
### 11.3 Delta Updates
|
|
464
|
+
|
|
465
|
+
- Track old/new positions; erase previous cell, draw new one.
|
|
466
|
+
- Use flags or small arrays for active objects only.
|
|
467
|
+
- Skip unchanged elements; BASIC loops are costly.
|
|
468
|
+
|
|
469
|
+
### 11.4 Timing (Delays)
|
|
470
|
+
|
|
471
|
+
- **Do not delay by default**—BASIC is slower than 50 Hz refresh.
|
|
472
|
+
- Add timing only for pacing (slow motion, animation rhythm, cross-platform consistency, or sync with music).
|
|
473
|
+
- Implement fixed-step gating, not busy-waits:
|
|
474
|
+
|
|
475
|
+
```basic
|
|
476
|
+
IF TI-T0>=N THEN T0=TI:GOSUB UPDATE
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
→ limits maximum update rate without freezing input.
|
|
480
|
+
- Avoid `FOR T=1 TO N:NEXT` and tight wait loops; they waste CPU.
|
|
481
|
+
- If the game already runs slower than `N`, no wait occurs.
|
|
482
|
+
|
|
483
|
+
### 11.5 Movement & Input
|
|
484
|
+
|
|
485
|
+
- Move by arithmetic deltas (`X=X+DX`); keep signed `DX/DY`.
|
|
486
|
+
- Keyboard: `GET A$` (non-blocking). Avoid `INPUT`.
|
|
487
|
+
|
|
488
|
+
```basic
|
|
489
|
+
GETK$:IFK$<>""THEN...
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
- Joystick port 2 @ $DC00 (56320):
|
|
493
|
+
|
|
494
|
+
| Bit | Function | Mask |
|
|
495
|
+
|------|-----------|------|
|
|
496
|
+
| 0 | Up | 1 |
|
|
497
|
+
| 1 | Down | 2 |
|
|
498
|
+
| 2 | Left | 4 |
|
|
499
|
+
| 3 | Right | 8 |
|
|
500
|
+
| 4 | Fire | 16 |
|
|
501
|
+
Example:
|
|
502
|
+
`J=PEEK(56320):IF(JAND1)=0THENPY=PY-1`
|
|
503
|
+
|
|
504
|
+
### 11.6 Sprites & Graphics
|
|
505
|
+
|
|
506
|
+
- VIC sprite enable $D015; positions $D000–$D00F; colours $D027–$D02E.
|
|
507
|
+
- Pre-load sprite data; update only X/Y each frame via `POKE`.
|
|
508
|
+
- VIC renders asynchronously—BASIC handles motion logic only.
|
|
509
|
+
|
|
510
|
+
### 11.7 Sound
|
|
511
|
+
|
|
512
|
+
- SID base $D400.
|
|
513
|
+
- Store freq/envelope tables in DATA or arrays; `POKE` directly each frame.
|
|
514
|
+
|
|
515
|
+
### 11.8 Memory & Performance
|
|
516
|
+
|
|
517
|
+
- Use integer arrays for coordinates/counters.
|
|
518
|
+
- Keep < 26 variables for faster lookup.
|
|
519
|
+
- Avoid `PRINT` during play; write HUD directly to screen RAM.
|
|
520
|
+
- For scrolling, shift indices or viewport pointers instead of copying memory.
|
|
521
|
+
- Reuse data structures; avoid new strings inside loop.
|
|
522
|
+
|
|
523
|
+
### 11.9 Example Loop Skeleton
|
|
524
|
+
|
|
525
|
+
```basic
|
|
526
|
+
10 T0=TI:GETK$
|
|
527
|
+
20 GOSUB1000:REM LOGIC
|
|
528
|
+
30 GOSUB2000:REM DRAW
|
|
529
|
+
40 IF TI-T0<2 THEN GOTO40
|
|
530
|
+
50 GOTO10
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
→ adds frame pacing only if motion needs slowing.
|
|
534
|
+
|
|
535
|
+
### 11.10 Summary
|
|
536
|
+
|
|
537
|
+
Efficient BASIC games minimise interpreter overhead.
|
|
538
|
+
Use `POKE/PEEK` for graphics and input, delta redraw for movement, fixed-step gating only when required, and pre-allocated variables for state.
|
|
539
|
+
Result: smooth, responsive gameplay within BASIC’s limits.
|