The Sinclair ZX81 is my first computer, in 1982 (kit). It is one of those home computers very popular in the '80s and affordable (£49.95 in kit). Other very popular computers were the Commodore 64 and the Apple II but were far more expensive (ZX81 was ten times cheaper than Apple II Plus). The successor of the ZX81 is the ZX Spectrum even more popular than the ZX81.
The ZX81 computer is based on a 8-bit processor (
Z80A from Zilog or
µPD780C from NEC) at 3.5 MHz with 1 KiB of RAM and 8 KiB of ROM. The 1 KiB of RAM can be expanded with a RAM extension (I had a 16 KiB one). There is only 4 chips (far less than other home computers): the ROM, the RAM, the processor and a custom logic chip made by Ferranti (ULA).
The ZX81 does not include a display. You connect it to an ordinary UHF television set to deliver a monochrome picture. The processor (
Z80) spends most if its time driving the display.
The characters set is not based on
ASCII but is custom and includes only capital letters. It includes also some graphic characters:
Using these characters, it is possible to make some graphics but it is very limited (64x48). Using some tricks (and sometimes some hardware modifications), it is possible to achieve (more or less) 256x192 (more or less because it is not possible to get all pixel combinations per line).
The keyboard is very simple: it is a flat, pressure-sensitive membrane QUERTY keyboard:
Data are saved or loaded with an audio cassette recorder at an average rate of 307 bps (the machine has no built-in storage capabilities). The recorder is connected to two 3.5 mm jacks (EAR and MIC) on the side of the ZX81.
The 8 KiB ROM contains a BASIC interpreter (called Sinclair BASIC) and there is no actual operating system, only a set of subroutines at known ROM addresses.
The machine was delivered with a very good manual: Sinclair ZX81 BASIC Programming by Steven Vickers. It was both a reference and a training course for completely beginners.
From BASIC, it is possible to directly access memory (with
POKE instructions) and to execute
Z80 machine code using the
USR instruction (often with the
RAND statement, a trick to ignore the value returned by
USR). Most of the time, machine code is placed in a
REM statement at the beginning of the program.
One of my first programs was a
Z80 disassembler. Unfortunately, I lost it. I have also programmed some games and I still have one of them:
FACTORY (originally called
USINE in French). It is written with a mix of
BASIC (to display the menu, the rules of the game, etc) and
Z80 assembly code (for the game itself). If you want to play with it, it available (in an emulator, see bellow) on my Biography page.
The source code of the game itself (BASIC and Z80 assembly) will be the subject of my next post.
This is a schematic of the keyboard:
The positions of the keys are thus given by the following table:
Note: NL is New Line, SH is Shift, SP is Space.
|Address (hex)||Address (dec)||Description|
|0000-1FFF||0 - 8191||ROM (8 KiB)|
|2000-3FFF||8192 - 16383||Shadow ROM|
|4000-7FFF||16384 - 32767||RAM (in the case of a 16K extension)|
Note: The exact layout of ROM and RAM are dependent of the quantity of external RAM installed. In some cases, ROM and RAM are mirrored at other addresses.
|4000 / 16384||System Area|
||BASIC Calculator Stack|
||Machine Stack/Free Memory|
||Machine Stack/In Use (SP Z80 register)|
||1 less than the report code.|
||Various flags to control the BASIC system.|
||Address of first item on machine stack (after
||Address of first byte above BASIC system area.|
||Line number of statement currently being executed.|
||0 Identifies ZX81 BASIC in saved programs.|
||Number of current line (with program cursor).|
||Pointer to Video Memory (BG map).|
||Pointer to BASIC Variables Area.|
||Address of variable in assignment.|
||Pointer to Input Buffer/Workspace, and to the end of the area saved.|
||Address of the next character to be interpreted.|
||Address of the character preceding the marker.|
||Pointer to BASIC Calculator Stack.|
||Pointer to bottom of Machine Stack.|
||Address of area used for calculator's memory.|
||The number of lines (including one blank line) in the lower part of the screen.|
||The number of the top program line in automatic listings.|
||Shows which keys pressed.|
||Key release delay.|
||Number of blank lines above or below picture: 55 for 50Hz, 31 for 60Hz.|
||Address of next program line to be executed.|
||Line number of which
||Length of string type destination in assignment.|
||Address of next item in syntax table.|
||The seed for
||Counts the frames displayed on the television.|
||x-coordinate of last point ^PLOT`ted.|
|16439||4037||1||Yes||y-coordinate of last point PLOTted.|
||Less significant byte of address of next position for
||Column number for
|16442||403A||1||Yes||Line number for
||Various flags. Bit 7 is on (1) during compute & display mode.|
||Printer buffer (33rd character is
||Calculator's memory area.|
The BASIC program begins at address
16509h (just after System variables). Instructions have these general format:
|2||Line number in big endian|
|2||Length of the line (including terminal NEWLINE character, exluding line number and length)|
If the program contains Z80 machine code, it is often stored in a
REM comment at the very beginning of the program. The layout is thus:
|16511||407F||2||Length of the line (including terminal NEWLINE character, exluding line number and length)|
|16514||4082||x||Data (machine code)|
Z80 Machine code starts at address
4082h). The jump to this address from BASIC is often performed with this instruction:
RAND USR 16514
RAND is used because in BASIC, it is not possible to ignore the return value of
USR (call to user-defined code).
RAND takes a parameter and has very little side-effects.
Programs are stored on audio tapes this way:
|x seconds||Your voice, saying "filename" (optional)|
|x seconds||Video noise|
|1-127 bytes||File name (bit 7 set in last char)|
||Data, loaded to address 4009h,
|1 pulse||Video retrace signal if display was enabled|
|x seconds||Silence / video noise|
The data contains system area, basic program, video memory, VARS. The last byte of a (clean) file should be 80h (the last byte of VARS). Files should usually not exceed 16 KiB.
The system area should contain proper data. In particular:
|4014h||Defines the end address (used to calculate the file length)|
|4029h||Points to the next executed (autostarted) BASIC line|
|403Bh||Indicates if program runs in SLOW or FAST mode (bit 6)|
.81 files are similar. They consist of the raw data as saved by the ZX81 tape saving routine (without the filename). They can store only one program.
.p files typically contain some garbage at the end.
.p81 files are like
.p files except they begin with the file name (127 bytes, last byte ORed with
Data are copies of the memory area
4009h (16393) up to
There are emulators available, written in various languages. In particular:
EightyOne, witten in C++. Copyright © 2003-2006 Michael D Wynne and by others.
JtyOnebased on EightyOne (translation) and written in Java. Copyright © 2006 Simon Holdsworth and others.
There are several web sites and forums discussing Sinclair ZX81, ZX80 or Spectrum. For example: