# 13. Differences from BASIC 7.0 If you already write Commodore BASIC, this is the chapter to read first. Everything here is deliberate, and everything is recorded in the repository's `TODO.md` with the reasoning — this is the short version. ## The language ### Variables carry a type suffix, and the suffixes differ | | Integer | Float | String | |---|---|---|---| | C128 | `A%` | `A` | `A$` | | akbasic | `A#` | `A%` | `A$` | There is **no such thing as an unsuffixed variable**. A bare name is a label. ### `=` works in a condition, and `==` works everywhere `IF A = 5 THEN` does what you expect. `==` also means equality and is what the older programs in this repository use. Outside a condition `=` is assignment, as always. ### `AND`, `OR` and `NOT` in conditions These work, and a condition is a whole expression rather than a single comparison, so `IF A = 1 AND B = 2 THEN` parses. Truth is nonzero, so `IF A THEN` works too. ### `MID` and `INSTR` count from zero A C128 counts from one. A failed `INSTR` gives -1 rather than 0. ### `THEN` needs a verb `IF X THEN 100` is not a jump. Write `IF X THEN GOTO 100`. ### Strings are 255 characters and cannot contain a quote There is no escape character. ### Numbers Integers are 64-bit and floats are IEEE doubles, so `PRINT 1.5` gives `1.500000`. A leading zero is not octal; `0x` is hexadecimal. ## Block structure **A whole loop on one line does not loop.** ```basic 10 FOR I# = 1 TO 3 : PRINT I# : NEXT I# 20 PRINT "DONE" ``` ```output DONE ``` The loop prints nothing. Block skipping walks source *lines*, so a `NEXT` on the same line as its `FOR` is never reached. The same applies to `DO`/`LOOP`. Write loops across lines. ## Two known defects in `FOR` Both are recorded, both have tests asserting the correct behaviour, and both are waiting on a decision rather than on work: - **A step that overshoots runs the body one extra time.** `FOR I = 1 TO 9 STEP 3` runs with 1, 4, 7 *and 10*. - **`FOR I = 1 TO 1` does not run its body at all**, where every other BASIC runs it once. The two errors cancel out for a step of 1, which is why they went unnoticed. Fixing them would change the output of a checked-in acceptance file, which is not something this project does silently. **A loop counter does not survive its loop.** It lives in the loop's own scope, so reading it afterwards gives zero. ## Direct mode A statement typed with no line number runs immediately, as it should. This was not true until recently — the interpreter used to file everything but a handful of verbs as program text. ## Errors `ER` and `EL` are **`ER#` and `EL#`**, ordinary global variables. `ER#` holds this interpreter's error code, which bears no relation to a Commodore error number. Print `ERR(ER#)` for the text. ## Graphics - **A coordinate is a window pixel, not one of 320 by 200.** A C128 listing therefore draws in the top-left corner of a larger window; `SCALE 1, 319, 199` gives it the whole window back. `RGR(1)` and `RGR(2)` report the size, and are ours rather than 7.0's — where 7.0's `RGR` takes only field 0, the `GRAPHIC` mode. - **`SSHAPE` puts a handle in the string, not the pixels.** You can pass it to `GSHAPE` and `SPRSAV`; you cannot save it or take its `LEN`. - **`WIDTH` is emulated** by drawing parallel passes. - **Drawing does not persist across frames.** The verbs draw straight to the renderer, so anything drawn is overwritten on the next frame unless the program redraws it. This is a defect, not a design. - **`CHAR` ignores its colour argument** and needs a text device with a cursor. ## Sound - **`PLAY` and `SOUND` do not block.** The statement after them runs immediately. - **`FILTER` is refused.** There is no filter stage to configure. - **`PLAY`'s `M` is accepted and does nothing.** - **`TEMPO`'s calibration is a choice**, not a transcription. ## Sprites - **Coordinates are window pixels**, not the VIC-II's raster space, and `SCALE` does not apply to them. - **`SPRSAV` takes an integer array**, not a string, for the data form — a string here cannot hold a zero byte. It also takes an **image file path**, which a C128 cannot. - **A sprite loaded from a file keeps the image's own size**, not 24 by 21. - **`MOVSPR`'s speed unit is a choice.** The manual does not say what a unit is worth. - **Collision is by bounding box**, not by pixel, and only type 1 exists. - **Priority and multicolour are recorded but not drawn.** - **`SPRDEF` is out of scope.** ## Files - **`PRINT #` and `INPUT #` need a space before the `#`.** `PRINT#1` scans as a variable name. - **`RECORD` counts lines**, not fixed-length records. - **`BLOAD` requires a length.** - **`HEADER`, `COLLECT`, `BACKUP` and `BOOT` are refused.** They operate on a physical disk. - **`DIRECTORY` is refused** pending a wrapper in the standard library. ## Machine - **`SYS` is refused.** There is no 6502 and no ROM. - **`FETCH` and `STASH` are the same byte copy.** There is no expansion RAM to tell them apart. - **`POKE`, `PEEK` and `POINTER` use real process addresses.** A wrong one is a segmentation fault, not an error message. - **`BANK`, `FAST` and `MONITOR` do not exist.** ## Formatting - **`PRINT USING` renders one field per statement.** `PRINT USING "### ###"; A, B` is not supported. - **Exponential fields (`^^^^`) are not implemented.** ## Console - **`SLEEP` and `WAIT` hold the program without blocking the host.** `SLEEP` with no host clock does nothing at all rather than waiting forever. - **`TI` and `TI$` are `TI#` and `TI$`**, refreshed once per step. - **`WAIT` polls ordinary process memory.** Nothing changes it but the host. - **`KEY` stores macros and nothing expands them.** ## Limits | | | |---|---| | Source lines | 9999 | | Line length | 255 | | String length | 255 | | Variables | 128 | | Array elements | 1024 per array, 4096 in total | | Scopes | 32 | | Labels | 64 | | `DATA` items | 512 | | File channels | 10 | | Operations per line | roughly 16 | Every one is a fixed pool. Nothing in the interpreter calls `malloc`, which is what makes it safe to embed in a game that cannot afford a surprise allocation.