Files
akbasic/docs/09-files-and-disk.md
Andrew Kesterson cdaefcc941
Some checks failed
akbasic CI Build / cmake_build (push) Successful in 3m0s
akbasic CI Build / sanitizers (push) Successful in 3m45s
akbasic CI Build / coverage (push) Failing after 3m22s
akbasic CI Build / akgl_build (push) Failing after 21s
akbasic CI Build / mutation_test (push) Successful in 11m26s
Write the usage guide as thirteen chapters in docs/
Organised the way the C128 Programmer's Reference Guide is: the language
first, then each hardware area, then the reference sections. One markdown
file per chapter.

The verb and function references are generated from the interpreter's own
dispatch table, with an assertion that every row is described, so they cannot
drift out of step with what the program accepts. 98 verbs and 30 functions.

Every example was run before it was written down, which caught three claims
that were wrong: a whole FOR loop on one line prints nothing rather than
looping once, MID and INSTR count from zero where a C128 counts from one, and
a multi-line DEF returns a value the caller has to assign away.

Chapter 13 is the list a BASIC 7.0 programmer needs -- roughly sixty
documented differences, including the two known FOR defects and the fact that
drawing does not survive a frame.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 21:50:50 -04:00

111 lines
3.1 KiB
Markdown

# 9. Files and disk
There is no 1541. The disk verbs work against the filesystem where that means
something, and refuse by name where it does not.
## Program storage
```
DSAVE "myprogram.bas"
DLOAD "myprogram.bas"
VERIFY "myprogram.bas"
```
`SAVE` and `LOAD` are the same verbs under their other names, and `DVERIFY` is
`VERIFY`. A program is saved as plain text with its line numbers, so you can edit it in
anything.
`VERIFY` compares what is in memory against the file and prints `OK`, or reports how
many lines differ.
## Files
Ten channels, numbered 0 to 9.
```
10 DOPEN 1, "scores.txt", W
20 PRINT #1, "ADA 4000"
30 PRINT #1, "GRACE 3800"
40 DCLOSE 1
50 DOPEN 2, "scores.txt"
60 INPUT #2, LINE$
70 PRINT LINE$
80 DCLOSE 2
```
| Verb | What it does |
|---|---|
| `DOPEN n, "name"` | open for reading |
| `DOPEN n, "name", W` | open for writing |
| `APPEND n, "name"` | open for writing at the end |
| `DCLOSE n` | close one channel |
| `DCLOSE` | close all of them |
| `PRINT #n, expr` | write a line |
| `INPUT #n, VAR` | read a line |
| `RECORD n, r` | position at record `r` |
**Note the space before the `#`.** A C128 writes `PRINT#1,A$`; here the `#` has to be
its own word, because `PRINT#` would otherwise scan as a variable name. See Chapter 13.
Reading past the end of a file leaves the variable empty rather than raising, so a read
loop tests what it got:
```
10 DOPEN 1, "data.txt"
20 DO
30 INPUT #1, L$
40 IF L$ = "" THEN EXIT
50 PRINT L$
60 LOOP
70 DCLOSE 1
```
Reading a channel opened for writing — or writing one opened for reading — is refused,
as is using a channel that is not open.
`RECORD` counts *lines*, not fixed-length records: a filesystem file has no record
length to seek by, so it rewinds and reads forward.
## Managing files
```
10 COPY "a.txt", "b.txt"
20 CONCAT "a.txt", "b.txt"
30 RENAME "b.txt", "c.txt"
40 SCRATCH "c.txt"
```
`COPY` duplicates, `CONCAT` appends one file to another, `RENAME` moves, `SCRATCH`
deletes. Deleting a file that is not there is reported rather than ignored.
## Binary blocks
```
10 A$ = "BINARY DATA"
20 BSAVE "block.dat", POINTER(A$), POINTER(A$) + 12
30 BLOAD "block.dat", POINTER(B$), 12
```
`BSAVE` writes a range of memory and `BLOAD` reads one back. **`BLOAD` requires a
length**, unlike a C128's, because the address is a real address in this process and a
file longer than you expected would write past whatever you pointed at.
## What is refused, and why
| Verb | Why not |
|---|---|
| `HEADER` | formats a disk. On a filesystem that would have to mean "delete everything here" |
| `COLLECT` | validates a disk's block allocation map. There is no map |
| `BACKUP` | duplicates one disk onto another. There are no disks |
| `BOOT` | loads and runs a boot sector. There is no boot sector |
| `DIRECTORY` / `CATALOG` | needs a directory-reading wrapper the standard library does not have yet. Filed upstream |
`DCLEAR` is the exception among the drive verbs: resetting a drive also closes its
channels, and closing the channels is real, so that is what it does.
Each refusal names itself and says why:
```
? 10 : RUNTIME ERROR HEADER formats a disk, and there is no disk drive here -- only a filesystem
```