This will probably be my last emulator for a while so I can return to normal projects. I’d wanted to emulate the Apple 1 for quite a while, and didn’t think it should take more than a couple of hours to make a usable emulator.
The Apple 1 is a surprisingly simple device, with 1MHz 6502 CPU, 4K RAM (expandable to 32K) and a tiny 256-byte monitor ROM. Slots on the main board allowed for add-on ROMs for BASIC, cassette functions, assembler, etc. The user manual includes comprehensive hardware details plus a fully commented disassembly of the monitor ROM.
There aren’t many original Apple 1 devices anymore, but there are a few modern replicas available. Most of them use the 65C02 CPU, so it’s probably just as well I added support for it recently! The original ROMs don’t use the extended instructions but a 3rd party assembler supports for them so it was worth having them covered.
Input and output is via a dumb terminal style interface, supporting only upper-case letters and a slightly cut-down symbol set. I/O speed is tied to the terminal display, giving a 60 characters/second maximum on the original. Both input and output have data and control ports, with the latter used to indicate whether the terminal is busy outputting a character or has a key available for input.
For the emulation, the limited terminal output speed means at most 1 character (plus cursor) needs to be drawn each interrupt. Until that is processed the terminal appears busy and the running program will wait before outputting more. SAM’s 50Hz interrupt frequency reduces the output speed slightly, but not by enough to worry about. Adding a line interrupt in the middle of the frame (312/2-68 = line 88) double this to 100Hz very easily, so Sym-1 and Sym-2 can be used to change the terminal speed.
When a character is written or a key is read, the terminal must update the control ports with the new status. This must happen as part of the read/write to prevent the running program doing anything further until it has been processed. The 6502 core was enhanced to trap memory writes for the Orao emulator, so the display could be updated immediately. The Apple 1 emulation also needs the same enhancement for memory reads, so it can update the input control port.
The output terminal is 40x24 characters, giving a maximum character set size of 6x8 pixels for a 256x192 mode 2 SAM screen mode. Mode 3 would have allowed up to 12x8 thin pixels, but there wasn’t really much benefit from the extra resolution, and the 24K display was 4 times slower to scroll. Perhaps the only drawback in using mode 2 is that Spectrum-style masking and rotating needed to draw each character.
Input is entirely character based, and doesn’t need support for multiple simultaneous key presses (just Shift for symbols). For that reason I decided to use SAM’s ROM keyboard scanner rather than rolling my own version. All I had to do was page the ROM in and ask for the next key, with the ROM debouncing the input and buffering fast typing. The returned key symbols are then converted to Apple 1 keys, converting lower-case to upper-case, and mapping a few special keys including Delete, Tab and Escape.
Normal monitor use is 100% speed, as most of the time is spent waiting for key presses. To test the underlying speed I ran an empty loop in BASIC: FOR X=1 TO 1000 : NEXT X which takes 1.2 seconds on the original device and 10 seconds in my emulator. The 10-15% running speed matches the results for the Orao emulator, and probably applies to anything else that uses my 6502 core.
The completed emulator (plus source code) is now available on my website.