Retroapple iibasiccassetteretrocomputingself-modifying code
An Apple II Phonebook Saved Your Contacts to Cassette by Saving Itself, Because BASIC Couldn't Work the Tape Deck
The base machine shipped without a floppy drive, and a running program had no say over the tape: no start, stop, rewind or advance. Chen also admits he can't swear the records sat in DATA lines instead of comments.

The base Apple II was sold without a floppy drive. That is where Raymond Chen starts a story about a phone directory he remembers from the machine’s early days, in a post on The Old New Thing dated November 3, 2026. His answer to how you build a database with no random-access storage fits in one sentence: “You just store it all in memory, in your own program.”
The only external storage was a cassette port, and BASIC could not drive it. A program couldn’t start the tape, stop it, rewind it or advance it. Whatever the user wanted saved went onto tape in one go, and whatever they wanted back came off the same way.
So the directory became its own filing cabinet. Chen describes a BASIC listing that opened with a comment block warning the owner not to edit any line before 1000. Below it sat the owner’s own phone directory, typed out as DATA statements, followed by some dummy DATA statements. DATA is the BASIC statement for tables of precalculated values that the program reads with READ and never changes. This one was a phone book wearing a lookup table’s clothes.
Reading a contact used READ, the normal way. Changing one used a trick: the program wrote new values back into its own DATA lines with POKE, which is self-modifying code in a program whose whole job was remembering your dentist. When the owner was finished, the program prompted them to turn on the cassette player and ran SAVE. The directory was part of the program, so saving the program saved the directory. To use it again, you loaded the program from tape and ran it.
Chen spells out why the obvious alternative lost. The monitor ROM could save a block of memory, but that would have meant two trips to the tape deck, one for the program and one for the data. Saving the program as a whole turned two loads into one. On a tape deck you work by hand, one pass was the feature.
The post also carries its own caveat, and it deserves to be repeated. Chen writes: “At least, I think it was DATA statements. Maybe it was comments. But the same principle applies.” He is working from memory, and he says so. The principle he’s confident about is the one that matters: the data lived inside the program, so the program’s save was the database’s save.
This story runs on Chen’s recollection alone. His post begins with the “mystery comment” that Beej’s Bit Bucket was investigating, which “reminded me of a similar trick in an Apple ][ telephone directory program.” That is the whole trail, and it makes the phonebook a good reminder of how little of this era sits in a manual.
The shape of that trick has outlived the cassette. Any system that offers one place to save invites the same move, which is to put the data inside the thing that gets saved. A few modern examples already look like it, from spreadsheets with their own scripts to single-file apps that carry their settings inside themselves. It tends to come back when storage is dumb and the user is in a hurry. The next device with a single save slot will probably get the treatment from some clever owner, who will then forget to write it down.
It also explains why old software is so hard to document. The warning at the top of the listing, don’t touch lines before 1000, was the only schema this database had. Lose that comment and the next person to open the listing sees a program with strangely wordy DATA lines.
A phonebook with no Side B.