Sei sulla pagina 1di 102

ZX81

Video: 32x24 Characters (256x192 pixels), 64x48 Dots Block Graphics


Characters: 64 Characters, defined in ROM area
Attributes: Normal and Inverted (separately for each char)
Memory
8 Kbytes ROM
1 KByte RAM built-in
Expanision RAM: 16KBytes (most popular) up to 56KBytes
ZX80/ZX81 Keyboard Assignment
----------------------------Here's the ZX81 keyboard assignment. The Graphics column is meant to be
Shift+Graphics (Graphic without Shift just returns inverted 'normal'
characters).
The two columns to the right are for the ZX80, as there's no Function mode,
ZX80 function names (such like CHR$) can be (and must be) typed by hand as
single characters.
<-key-> <------------- ZX81 -----------> <------ZX80------>
NORMAL COMMAND SHIFT FUNCTION GRAPHICS ZX80/CMD ZX80/SHFT
1
1
<edit> -1000
1
NOT
2
2
AND
-0100
2
AND
3
3
THEN
-0001
3
THEN
4
4
TO
-0010
4
TO
5
5
<left> -0101
5
<left>
6
6
<down> -0011
6
<down>
7
7
<up>
-1100
7
<up>
8
8
<right> -0101
8
<right>
9
9
<graphics> --9
<hide???>
0
0
<rubout> --0
<rubout>
Q
PLOT
""
SIN
0111
NEW
1010
W
UNPLOT OR
COS
1011
LOAD
0011
E
REM
STEP
TAN
1110
SAVE
1000
R
RUN
<=
INT
1101
RUN
0100
T
RAND
<>
RND
0110
" "
0022
Y
RETURN >=
STR$
1001
REM
"
U
IF
$
CHR$
-IF
$
I
INPUT
(
CODE
-INPUT
(
O
POKE
)
PEEK
-PRINT
)
P
PRINT
"
TAB
-"?"
*
A
NEW
STOP
ARCSIN 2222
LIST
2222
S
SAVE
LPRINT ARCCOS 2200
STOP
0110
D
DIM
SLOW
ARCTAN 0022
DIM
0010
F
FOR
FAST
SGN
2211
FOR
0001
G
GOTO
LLIST
ABS
1122
GO TO
2200
H
GOSUB
**
SQR
2222
POKE
**
J
LOAD
VAL
-RANDOMISE K
LIST
+
LEN
-LET
+
L
LET
=
USR
-"?"
=
ENTER
newline function
-newline <edit>
SHIFT
------Z
COPY
:
LN
-"?"
:
X
CLEAR
;
EXP
-CLEAR
;
C
CONT
?
AT
-CLS
?
V
CLS
/
--GO SUB
/
B
SCROLL *
INKEY$ -RETURN
OR
N
NEXT
<
NOT
-NEXT
<
M
PAUSE
>
PI
-"?"
>
.
,
--"."
,
SPACE
BREAK
pound
-1111
BREAK
pound
40-key ZX80/ZX81 Keyboard
| 1
2
3
4
5
6
7
8
9
0
|
| Q
W
E
R
T
Y
U
I
O
P
|
|
A
S
D
F
G
H
J
K
L ENTER|
|SHF Z
X
C
V
B
N
M
.
SPACE|
Keyboard Translation
When the keyboard translation option is used, special characters such like
comma, quotes, plus, etc. are mapped to the respective PC keys. In result, the
meaning of the ZX key combinations SHIFT+1..4 changes also. The respective
functions are remapped to the following PC-keys:
ZX81 ZX80 PC
EDIT NOT
!
AND
AND
&
THEN THEN #
TO
TO
%
Some other remapped keys are Cursor=Cursor, Rubout=Backspace, Graphics=Alt,
Function/Symbol=Ctrl, Break=End.

ZX80/ZX81 I/O Map


----------------I/O Ports
xx0Fh.W
xx1Dh.R
xx2Fh.R
xx3Fh.R
FF7Eh.R
xx9Fh.W
xxBFh.R
xxDFh.W
xxDFh.W
xxDFh.R
xxDFh.R
xxEFh.R
xxF5h.R
xxF5h.W
xxF6h.R
xxF6h.W
xxFBh.R
xxFBh.W
xxFDh.W
xxFEh.W
NNFEh.R
xxFFh.W

PSG data (Bi-Pak ZON-X81 Sound)


Zebra Joystick adapter
Memopak I/F Centronics Interface status (IN status,[dd3Fh]);dd=data
Memopak I/F Centronics Interface finish (IN dummy,[dd3Fh]) ;dd=data
Lambda - read PAL/NTSC flag (A7=row) (via diode from A7 to KEYB.0)
PSG index (Timedata ZXM Sound Box)
PSG data (Timedata ZXM Sound Box/Joystick Read)
PSG index (Bi-Pak ZON-X81 Sound) (default address) (sometimes CFh)
PSG data (Timedata ZXM Sound Box)
Mikro-Gen digital joystick
AGB - JOYSTICK II (port A) (or B ?)
AGB - JOYSTICK II (port B) (or A ?)
Lambda - toggle sound output level
Lambda - select charset line number (00..07)
Lambda - read selected charset data (8 pixels)
Lambda - select charset char number (00..3F)
Sinclair Printer Status
Sinclair Printer Output
Disable NMI (ZX81 only)
Enable NMI (ZX81 only)
Keyboard read, when NMI=Off: also enter VSYNC and set CAS.OUT=Low
Terminate Vsync and restart LINECNTR and set CAS.OUT=High

Accidently Used I/O Port Mirrors


0Eh.R
Faulty mirror of FEh.R (used by a GRAND-PRIX game)
CFh.W
PSG index (Bi-Pak ZON-X81 Sound) (used accidently in Bi-Pak manual)
CFh.W
PSG index (Bi-Pak ZON-X81 Sound) (used by Lunar 10)
FEh.W
Faulty mirror of FFh.W (used by animated Space Invaders for ZX80)
Memory Mapped Ports
3E80h.R/W Mikro-Gen analog joystick A/D board
7FFFh.W
PSG index (Quicksilva QS Sound board)
7FFEh.R/W PSG data (Quicksilva QS Sound board)
IR Register
I=00h Pseudo HiRes (Madjump II)
I=08h Pseudo HiRes (Bipods, Micromouse)
I=0Ch Pseudo HiRes (Rock Crush, Dans Revenge, etc.)
I=1Eh ZX81 ROM Charset (or QS CHRS board RAM)
I=2xh dk'tronics UDG ROM (or unknown UDG RAM)
I=3xh dk'tronics UDG RAM
I=40h Xtricator IM2 vector at [40FFh] (with databus assumed to be FFh)
IR=x
True hires bitmap address
R=x
Interrupt counter for "compressed" text output (INT wired to A6)
R=x+EI Interrupt execution forces HSYNC (on ZX81: also resets NMI counter)
ZX80/ZX81 I/O Ports
------------------Output to Port FFh (or ANY other port)
Writing any data to any port terminates the Vertical Retrace period, and
restarts the LINECNTR counter. The retrace signal is also output to the
cassette (ie. the Cassette Output becomes High).
Input from Port FEh (or any other port with A0 zero)
Reading from this port initiates the Vertical Retrace period (and accordingly,
Cassette Output becomes Low), and resets the LINECNTR register to zero,
LINECNTR remains stopped/zero until user terminates retrace - In the ZX81, all
of the above happens only if NMIs are disabled.
Bit Expl.
0-4 Keyboard column bits (0=Pressed)
5
Not used
(1)
6
Display Refresh Rate (0=60Hz, 1=50Hz)
7
Cassette input
(0=Normal, 1=Pulse)
When reading from the keyboard, one of the upper bits (A8-A15) of the I/O
address must be "0" to select the desired keyboard row (0-7).
(When using IN A,(nn), the old value of the A register is output as upper
address bits and <nn> as lower bits. Otherwise, ie. when using IN r,(C) or INI
or IND, the BC register is output to the address bus.)

The ZX81/ZX80 Keyboard Matrix


Port____Line____Bit__0____1____2____3____4__
FEFEh 0 (A8)
SHIFT Z
X
C
V
FDFEh 1 (A9)
A
S
D
F
G
FBFEh 2 (A10)
Q
W
E
R
T
F7FEh 3 (A11)
1
2
3
4
5
EFFEh 4 (A12)
0
9
8
7
6
DFFEh 5 (A13)
P
O
I
U
Y
BFFEh 6 (A14)
ENTER L
K
J
H
7FFEh 7 (A15)
SPC
.
M
N
B
Port FDh Write (ZX81 only)
Writing any data to this port disables the NMI generator.
Port FEh Write (ZX81 only)
Writing any data to this port enables the NMI generator.
NMIs (Non maskable interrupts) are used during SLOW mode vertical blanking
periods to count the number of drawn blank scanlines.
Note
Beside for the actual I/O ports, the IR register, the most significant bit of
the program counter, and (if that bit was set) the opcodes on the databus are
also relevant for video output. For details refer to chapters about Video.
ZX80/ZX81 Video Mode Text and Blockgraphics
------------------------------------------This is the ZX standard video mode. The display area consists of 32x24
characters of 8x8 pixels each. The user cannot set single pixels though, only
64 predefined characters can be used. However, some of these characters are
split into 2x2 blocks (4x4 pixel each), allowing to display 64x48 block low
resolution graphics.
Video Memory
Video memory is addressed by the D_FILE pointer (400Ch) in ZX80/81 system area.
The first byte in VRAM is a HALT opcode (76h), followed by the data (one byte
per character) for each of the 24 lines, each line is terminated by a HALT
opcode also. In case that a line contains less than 32 characters, the HALT
opcode blanks (white) the rest of the line up to the right screen border. (Thus
left-aligned text will take up less memory than centered or right-aligned
text.)
Character Data, VRAM Size
Character data in range 00h..3Fh displays the 64 characters, normally black on
white. Characters may be inverted by setting Bit 7, ie. C0h..FFh represents the
same as above displayed white on black.
The fully expanded VRAM size is 793 bytes (32x24 + 25 HALTs, almost occupying
the whole 1Kbyte of internal RAM), an empty fully collapsed screen occupies
only 25 bytes (HALTs).
Character Set
The character set is addressed by the I register multiplied by 100h. In the
ZX81 this is 1Eh for 1E00h..1FFFh, in ZX80 0Eh for 0E00h..0FFFh. Setting
I=40h..7Fh in attempt to define a custom charset in RAM rather than ROM does
not work.
Display procedure Tech Details
The display data is more or less 'executed' by the CPU. When displaying a line,
the BIOS takes the address of the first character, eg. 4123h, sets Bit 15, ie.
C123h, and then jumps to that address.
The hardware now senses A15=HIGH and /M1=LOW (signalizing opcode read), upon
this condition memory is mirrored from C000-FFFF to 4000-7FFF. The 'opcode' is
presented to the databus as usually, the display circuit interpretes it as
character data, and (if Bit 6 is zero) forces the databus to zero before the
CPU realizes what is going on, causing a NOP opcode (00h) to be executed. Bit 7
of the stolen opcode is used as invert attribute, Bit 0-5 address one of the 64
characters in ROM at (I*100h+char*8+linecntr), the byte at that address is
loaded into a shift register, and bits are shifted to the display at a rate of
6.5MHz (ie. 8 pixels within 4 CPU cycles).
However, when encountering an opcode with Bit 6 set, then the video circuit
rejects the opcode (displays white, regardless of Bit 7 and 0-5), and the CPU
executes the opcode as normal. Usually this would be the HALT opcode - before
displaying a line, BIOS enables INTs and initializes the R register, which will
produce an interrupt when Bit 6 of R becomes zero.
In this special case R is incremented at a fixed rate of 4 CPU cycles (video
data executed as NOPs, followed by repeated HALT), so that line display is
suspended at a fixed time, regardless of the collapsed or expanded length of
the line.

As mentioned above, an additional register called linecntr is used to address


the vertical position (0..7) whithin a character line. This register is reset
during vertical retrace, and then incremented once per scanline. The BIOS thus
needs to 'execute' each character line eight times, before starting to
'execute' the next character line.
ZX80/ZX81 Video Mode Pseudo Hi-Res Graphics
------------------------------------------This method is used to display 256x192 pixels graphics, limited to max 128
combinations within each row of 8 pixels though. Even though not supported by
the BIOS, a couple of games are using this video mode: Rock Crush, Dans
Revenge, Rocketman, Forty Niner, Madjump II, Bipods, Micromouse, and possibly
others.
Basically it is working much like Text video mode, the character height is
reduced to a single scanline, so each tile consists of 8x1 pixels rather than
8x8 pixels. And the screen consists of 32x192 of these 'flat' characters, each
line usually terminated by a RET opcode (C9h), thus occupying 6176 bytes of
memory.
A special display procedure is required which forces the linecntr register to
zero by issuing a very short 'vertical retrace' signal each scanline
(preferably simultaneously to the hardware generated horizontal retrace
signal). In result, only the topmost row of each character will be displayed,
as the topmost row of most of the normal characters is just blank, it'd be
recommended to change the characterset pointer in the I register to another
address in ROM.
For example, setting I=0Ch would select the area 0C00h..0DFFh (in steps of
eight: topmost rows of chars #0, #1, #2 at C00h, C08h, C10h, etc). The machine
code bytes in this memory region are then used as 'randomly' predefined pixel
rows, which may or may not match the programmers requirements. Each of the 64
rows may be inverted as normal text characters, so theoretical a total of 128
different 8-pixel rows can be used, practically less because most likely a
couple of rows will be duplicated.
As the interrupt based BIOS display procedure at 0038h does not support above,
a raw software based handler is used in most cases, that's why each line is
terminated by a RET rather than HALT opcode.
Observe that the TS1500 BIOS version contains some patched opcodes, so graphics
may appear different as with original ZX81/TS1000 BIOS (the most commonly used
region, with I=0Ch, is same in both BIOS versions).
ZX80/ZX81 Video Mode True Hi-Res Graphics
----------------------------------------This mode produces a 256x192 pix graphics screen, and, unlike Pseudo Hi-Res, it
allows to set each pixel separately. The downside is that it does not work with
most external RAM Paks (memory expansions can be quite easily upgraded by using
two diodes and a resistor though, see chapter Hardware Modifications for
details).
However, it does work with internal RAM and with modified RAM Paks.
When using internal RAM, take care about these two limitiations: Only a small
picture will fit into 1K memory (so the display procedure must increase
horizontal and/or vertical blanking times), and external RAM must be
disconnected (as it'd otherwise disable internal RAM).
The true hi-res technique is used by the games Guus Flater, Starfight, and by
some demos such like WRX1K.
The general idea is to move the character set into RAM at 4000h..7FFFh by
setting I to 40..7Fh. Now this does NOT work as expected, ie. as
(I*100h+char*8+linecntr) as for text mode. Both the executed opcode (character
number) and the linecntr value are ignored. Instead, pixels are directly read
from memory at (IR). Each eight bits of each byte represent eight pixels. The
picture is defined in form of a common monochrome bitmap.
The bitmap data can be located anywhere in RAM, and as it is not 'executed' as
in other display modes, only raw data is required (ie. and no HALT or RET
opcodes need to be attached to each line). Note that only the lower seven bits
of the R register are incremented by the CPU; care should be taken that it does
not overflow within a line. For example, a bitmap of 256 pixels width (32
bytes) should be aligned to 32 in memory.
The main display procedure should load the MSB of the current bitmap line into
the I register, and the LSB into the A register, then jump to a dummy D_FILE
display procedure in memory with A15=HIGH. This dummy procedure should copy the

LSB from A into R register, and then execute a stream of 32 NOP opcodes (00h:
Bit 7 indicates not inverted output, Bit 6 disables blanking, data is directly
read from (IR), so that the character number in Bit 0-5 is ignored), and return
to the main procedure - which'd then issue some delays, prepare new address in
I and A and start over with the next line (using the same dummy procedure
again), until the whole screen has been displayed.
ZX80/ZX81 Video Blanking and Retrace
-----------------------------------Display becomes white during blanking time. That is: when Bit 15 of the program
counter (PC) is "0", and/or when Bit 6 of the current opcode is "1".
Theoretically the CPU could execute whatever program code during blanking however, as there is only limited interrupt feedback, this time is usually
spent on HALT opcodes or other delay loops, required to keep the CPU
synchronized to visible display output.
Vertical Blanking
Upper and lower screen borders are displayed above/below of the actual picture,
the height of these borders depends on the display refresh rate. The BIOS
permanently reads out the preferred refresh rate (50Hz or 60Hz) when checking
for keystrokes, and uses this to re-calculate the desired border height for
each frame - allowing to export the ZX to other countries without having to
reboot it ;-)
ZX80 Vertical Blanking ("PAUSE")
The ZX80 points to a HALT opcode in the D_FILE area, which is repeatedly
executed to display blank upper and lower screen borders (much like empty lines
in a collapsed screen). The CPU thus wastes all its energies just on drawing
blank lines (and on decreasing a remaining lines counter).
ZX81 Vertical Blanking ("SLOW")
Even though the ZX81 supports the above method either, it'd usually use NMI
based blanking which allows program code to be executed during blanking time.
NMIs (non maskable interrupts) are enabled by I/O, the NMI handler is then
called each scanline. The handler increases a counter and (if the counter does
not overflow) returns to the user program, otherwise it executes a HALT opcode
to synchronize the CPU to the display at one-cycle resolution and terminates
the blanking procedure.
Horizontal Blanking
In both ZX80 and ZX81, the CPU cannot be used to execute user programs during
horizontal blanking periods - it is required to execute delays to be kept
synchronized to video hardware. This could be gained by a hardcoded delay.
However, ZX video is required to support variable length blanking when using
collapsed screens, in that case the width of the right screen border must be
increased when drawing an empty (or incomplete) line. This is gained by loading
a counter value into the R register (before drawing the line), and terminating
the line by a HALT opcode which is kept executed until Bit 6 of R becomes zero.
Retrace
The cathode ray is moved back to the begin of the scanline / top of display
during horizontal / vertical retrace periods.
Horizontal retrace is generated by the video hardware, so care should be taken
to keep the display procedure synchronized to retrace signals.
Vertical retrace must be manually initiated and terminated by I/O, a fixed
length delay should be issued during v-retrace in order to produce a stable
display.
ZX80/ZX81 Video Interrupts (INTs and NMIs)
-----------------------------------------INTs
Maskable Interrupts (INTs) are generated when Bit 6 of the R (refresh) register
becomes zero. As the R register is incremented once for each opcode (twice for
prefixed opcodes), there is no linear relationship between clock cycles and
refresh cycles.
In the ZX, INTs are used to terminate scanline drawing, the display data is
'executed' identical as NOP instructions, followed by a HALT opcode (which is
identical as repeated NOPs), so that in this special case (as both HALTs and
NOPs increment R once per 4 clock cycles) INTs can be used to produce a regular
interval.
The above INT/HALT combination is used as variable length delay, which is
required for variable length scanlines (ie. mixed collapsed and expanded
scanlines) only. Fixed length scanlines could be terminated by hardcoded
delays.
In IM 1 (default), the INT handler is located at 0038h in BIOS ROM. INTs are
enabled by EI instruction, and are automatically disabled upon execution (or
when issuing DI instruction).

NMIs (ZX81 only)


Non maskable interrupts (NMIs) are requested during horizontal retrace time
(ie. at the end of each scanline), the CPU is forced into WAIT state for the
duration of NMI request (unless when executing a HALT opcode which is allowed
to complete without WAIT states).
NMIs are used to count the number of drawn scanlines during vertical blanking
periods. This is allowing the user program to be executed in SLOW mode while
drawing upper and lower screen borders, and to pass control back to the
display/retrace procedure once the NMI handler decides to terminate the
blanking period.
The NMI handler is located at 0066h in BIOS ROM (independently of IM interrupt
mode). NMIs are enabled/disabled by I/O instructions - the CPU cannot disable
NMIs (ie. DI/EI has no effect on NMIs).
ZX80/ZX81 Video Display Timings
------------------------------Horizontal Scanline Timings
Horizontal Display
128 cycles (32 characters, 256 pixels)
Horizontal Blanking
64 cycles (left and right screen border)
Horizontal Retrace
15 cycles
Total Scanline Time
207 cycles
Horizontal retrace rate and duration are fixed. The display procedure might
increase or decrease the width of the display area (by respectively adjusting
the blanking time) even though larger screens might exceed the visible
dimensions of the attached TV set or monitor.
Vertical Timings (50Hz)
Upper Blanking
11592
Display Area
39744
Lower Blanking
ca.11592
Vertical Retrace
1235

cycles
cycles
cycles
cycles

56
192
ca. 56
ca. 6

scanlines (7 charlines)
scanlines (24 charlines)
scanlines (or a bit less)
scanlines

Vertical Timings (60Hz)


Upper Blanking
6624
Display Area
39744
Lower Blanking
ca. 6624
Vertical Retrace
1235

cycles
cycles
cycles
cycles

32
192
ca. 32
ca. 6

scanlines (4 charlines)
scanlines (24 charlines)
scanlines (or a bit less)
scanlines

User Available Blank Lines


Even though upper screen border consists of 56 scanlines (32 in 60Hz mode),
only 54 scanlines (60Hz: 30 scanlines) are available for user program
execution. The first of the remaining scanlines is occupied by a HALT opcode
(which is suspended by a NMI; providing exact retrace synchronisation), and the
next scanline is spent on a collapsed D_FILE row. Lower screen borders are
idientical as above, except that no collapsed D_FILE line is drawn at the
bottom. Instead, some cycles are spent upon incrementing the FRAMES counter.
User Available Blanking Time
The total of 207 cycles per scanline isn't available for user program, even
during blanking periods: An NMI is generated each line, including some
NMI-waitstates, the CALL 66h execution, and the execution of the NMI handler
(which is counting the number of drawn scanlines).
Item
Original ZX81 Tuned ZX81
Total scanline time
207 cycles
207 cycles
NMI WAIT
- 14 cycles
- 0 cycles (WAITMOD by Wilf Rigter)
NMI CALL 66h
- 12 cycles
- 12 cycles
NMI handler
- 32 cycles
- 29 cycles (NMIPATCH by Nocash)
Remaining user time
= 149 cycles
= 166 cycles
Recursing both upper and lower border, 54*2 scanlines per frame are available
for user programs in 50Hz mode; only 30*2 in 60Hz mode.
Resulting User Available CPU Time
SLOW, 50Hz Effective Speed 0.804600
SLOW, 50Hz Effective Speed 0.896400
SLOW, 60Hz Effective Speed 0.536400
SLOW, 60Hz Effective Speed 0.597600
FAST, Total CPU Speed
3.250000
ZX80/PAUSE/INPUT
0.0 MHz
For more info on tuning, see:
--> HW Making the ZX81 Faster

MHz
MHz
MHz
MHz
MHz

(54*2*149 cycles, 50 frames)


(54*2*166 cycles, 50 frames)
(30*2*149 cycles, 60 frames)
(30*2*166 cycles, 60 frames)
(display disabled)
(user program stopped)

(ori)
(tuned)
(ori)
(tuned)

ZX80/ZX81 Video Character Set


----------------------------First, here's the ZX81 character set (64 characters)
____0___1___2___3___4___5___6___7___8___9___A___B___C___D___E___F____
00 SPC [' ][ '][''][. ][: ][.'][:']{::}{..}{''} " GBP $
:
? 0F
10 (
)
>
<
=
+
*
/
;
,
.
0
1
2
3 1F
20 4
5
6
7
8
9
A
B
C
D
E
F
G
H
I
J 2F
30 K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z 3F
For the ZX80, some characters are located at other positions:
____0___1___2___3___4___5___6___7___8___9___A___B___C___D___E___F____
00 SPC " [: ][..][' ][ '][. ][ .][.']{::}{..}{''}GBP $
:
? 0F
10 (
)
+
*
/
=
>
<
;
,
.
0
1
2
3 1F
20 4
5
6
7
8
9
A
B
C
D
E
F
G
H
I
J 2F
30 K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z 3F
For both ZX80 and ZX81, all characters can be displayed normal (Bit 7 cleared)
or inverted (Bit 7 set). For SPC and GRA see below, GBP means the 'pounds'
currency symbol.
Block Graphics
For [solid] symbols, all 16 combinations of block graphics (with any number of
4x4 pixel dots at any position within a 8x8 pixel character) can be produced by
using the invert-attribute bit. Only limited combinations are possible for
{dithered} symbols.
ZX81 charset is stored at 1E00h-1FFFh in BIOS ROM (I register I=1Eh), ZX80
charset at 0E00h-0FFFh (I=0Eh).
The lower 9 bits (A8-A0) of the characterset are addressed by the 'display
controller' (overriding the CPU supplied address signals, which outputs the
whole IR register to the address bus) - the special address bits are output to
the ROM chip only (but not to RAM, nor to Expansion Port), so neither internal,
not external RAM can be used to store character data.
ZX80/ZX81 Memory Map and System Area
-------------------------Overview
0000-1FFF
BIOS ROM (8KBytes)
2000-3FFF
not used
4000-43FF
Internal RAM (1 KByte)
4000-7FFF
External RAM (16 KBytes)
Internal RAM is disabled (and cannot be accessed) when external RAM is
installed.
ZX81 RAM Map
4000
System Area (see below)
407D
BASIC Program
D_FILE
Video Memory (BG Map)
VARS
BASIC Variables
E_LINE-1 Byte 80h
E_LINE
Input Buffer/Workspace
STKBOT
BASIC Calculator Stack
STKEND
Machine Stack/Free Memory
SP
Machine Stack/In Use (SP is meant to be the CPUs SP register)
ERR_SP
GOSUB Stack
RAMTOP
USR Programs (Begin of unused/reserved memory)
ZX81 System Area
Addr. Name
Expl
4000
ERR_NR Errorcode-1
4001
FLAGS
Various BASIC Control flags
Bit0=used (purpose unknown)
Bit1=Redirect Output to printer
Bit2=used (purpose unknown)
Bit3-5=not used
Bit6=used (purpose unknown)
Bit7=used (purpose unknown)
4002
ERR_SP Pointer to top of Machine Stack / Bottom of GOSUB Stack
4004
RAMTOP Pointer to unused/free memory (Changes realized
at next NEW or CLS)
4006
MODE
Selects [K], [L], [F], or [G] Cursor
4007
PPC
Line Number of most recently executed BASIC line
---Begin of Save Area--4009
VERSN
Should be 00h to identify ZX81 cassette files (FFh=Lambda)
400A
E_PPC
Line Number of currently selected line [>] Cursor
400C
D_File Pointer to Video Memory (BG Map) / End of Basic Program
400E
DF_CC
Pointer to VRAM Address for PRINT
4010
VARS
Pointer to BASIC Variables Area
4012
DEST
Pointer to Variable when assigning a value to it

4014
4016
4018

E_LINE
CH_ADD
X_PTR

401A

STKBOT

401C
401E
401F
4021
4022

STKEND
BERG
MEM
DF_SZ

4023
4025
4027
4028

S_TOP
LAST_K
DEBOUN
MARGIN

4029

NXTLIN

402B
402D

OLDPPC
FLAGX

402E
4030
4032
4034

STRLEN
T_ADDR
SEED
FRAMES

4036
4038
4039
403B

COORDS
PR_CC
S_POSN
CDFLAG

403C
405D
407B

PRBUFF
MEMBOT
-

Pointer to Input Buffer/Workspace, and to --End of Save Area-Pointer to next interpreted character
Pointer to character prior to [S] Symbol (=Syntax Error) (or
ptr to aborted/breaked line)
Pointer to BASIC Calculator Stack / End of
Input Buffer/Workspace
Pointer to bottom of Machine Stack / End of Calculator Stack
Calculator B-Register
Pointer to Calculator Memory (usually same as MEMBOT)
Not used
Number of lines in lower display section (including 1 blank
line)
Line Number of first line for automatic LISTing
Keyboard - Recently pressed key (4025=row, 4026=shift/column)
Keyboard - Debounce State (key release delay)
Vertical Border Height (55 lines at top/bottom for 50Hz,
31 for 60Hz)
Address of next BASIC line which is to be executed,
pointing to a byte >=40h when stopped, indicates
autostart address in cassette files.
Line Number for CONT
Various Flags
Bit0
used (purpose unknown)
Bit1
used (purpose unknown)
Bit2-4 not used
Bit5
used (purpose unknown)
Bit6
used (purpose unknown)
Bit7
not used
Length of string during assignment
Pointer to next item in Syntax Table (or INPUT's old S_POSN)
Random Number Seed
Decrementing Video Frame Counter (Bit15: 0=PAUSE, ie.
display ON, program PAUSEd)
X-Coordinate of last PLOT, Y-Coordinate of last PLOT
Least significant byte of PRBUFF printer buffer pointer
X-Coordinate for PRINT, Y-Coordinate for PRINT
Various Flags
Bit7: Current Speed (1=SLOW (Display Enable), 0=FAST)
Bit6: Requested Speed (or old speed during
pause/cassette io, etc)
Bit5-1: Not used
Bit0: Keystroke (0=None, 1=Yes)
Printer Buffer 32 characters + NEWLINE (76h)
Default workspace for BASIC Calculator
Not used (2 bytes)

ZX80 Memory Map


4000..4027
4028..(4008)-1
(4008)..(4004 or 400A)-1
(4004 or 400A)..(400C)-1
(400C)...
...

System Area
Basic Program
VARS
Input Buffer, and probably something else ???
VRAM

ZX80 System Area


4000 ERR_NR
Error Number (one less than report code)
4001 FLAGS
Various Flags to control BASIC System
7 1-Syntax off
0-Syntax on
6 1-Numeric result
0-String result
5 1-Evaluating function (not used)
3 1-K cursor
0-L cursor
2 1-K mode
0-L mode
0 1-No leading space 0-Leading space
4002 PPC
Line number which is to be executed next (bit15: 1=stopped)
4004 P_PTR
Position in RAM of [K] or [L] cursor
4006 E_PPC
Line Number of current line with [>] cursor (for LIST)
4008 VARS
Address of start of variables area (end of BASIC Program)
400A E_LINE
Address of start of Edit Line (end of VARS) (-save area end-)
400C D_FILE
Start of Display File (VRAM) (end of Edit Line/Input Buffer)
400E DF_EA
Address of the start of lower screen
4010 DF_END
Display File End
4012 DF_SZ
Number of lines in lower screen
4013 S_TOP
The number of first line on screen
4015 X_PTR
Address of the character preceding the [S] marker
4017 OLDPPC
Line number to which CONTINUE jumps
4019 FLAGX
More flags.
7 1-K mode
0-L mode
6 1-Numeric result
0-String result
5 1-Inputting
0-Editing
401A T_ADDR
Address of next item in syntax table

401C SEED
The seed for the random number
401E FRAMES
Count of frames shown since start-up (incrementing)
4020 DEST
Address of variable in statement
---Active/Basic:
4022 RESULT
Value of the last expression
4024 S_POSN_X Column number for print position
4025 S_POSN_Y Line number for print position
4026 CH_ADD
BASIC program pointer (address of next char/token)
---Pause/Input:
4022 Keyboard debounce
4023 MARGIN
Screen border height
4024
?
4026 LAST_K
Keyboard last key pressed (4026=row, 4027=column)
ZX80/ZX81 Memory Mirrors and Expansions
--------------------------------------Memory Overview
RAM is originated at 4000h, for 1K RAM: at 4000h-43FFh; 48K: at 4000h-FFFFh,
the area below 4000h is used only when more than 48K are installed.
In the ZX world, memory accesses can be split into three categories: data read,
data write, and opcode read. Opcode read is sensed by the CPUs /M1 signal, and
behaves different than normal data read in case that A15 is HIGH, ie. for
addresses in range from 8000h-FFFFh.
address
code read write
0000..1FFF ROM
ROM
--;all ZX81's
2000..3FFF RAM4 RAM4 RAM4
;ZX81 with 56K only
4000..7FFF RAM1 RAM1 RAM1
;ZX81 with 16K or more RAM
8000..BFFF VRAM2 RAM2 RAM2
;ZX81 with 32K or more RAM
C000..FFFF VRAM1 RAM3 RAM3
;ZX81 with 48K or more RAM (*)
(*) That, for the RAM3 part, VRAM1 is of course found in all ZX with 16K
The memory region 8000h-FFFFh cannot be used to execute machine code programs;
any opcodes in that region with Bit 6 cleared are treated as video output (and
are executed as NOPs).
Opcodes/video data at C000-FFFFh are read from memory at 4000h-7FFFh - the
software should usually write video data into memory at 4000h-7FFF, and
'execute' the data in the mirrored region at C000-FFFF.
1K RAM
Default ZX81 includes only 1K RAM at 4000h-43FFh. However, the default RAM and
ROM select signals are mirroring ROM across 0000h-3FFFh and 8000h-BFFFh, and
RAM at 4000h-7FFFh and (including 'data read' accesses) at C000h-FFFFh.
The ZX81 mainboard provides space for either two 1K x 4bit SRAM chips, or one
1K x 8bit SRAM chip (with L1 jumper closed).
2K RAM
The american 'ZX81' (Timex TS1000) appears to have been delivered with 2K
internal memory. The socket for 1K x 8bit SRAM on the ZX81 mainboard may be
used (by closing L2 jumper) for a 2K x 8bit SRAM chip.
16K RAM
Even though above described 1K RAM signals are providing memory space for up to
16K RAM, the Memotech expansions (not sure about Sinclair or other expansions)
are supplying their own RAM and ROM select signals; ROM is then located at
0000-1FFF only, and RAM at 4000-7FFFh only, all other areas are unused,
typically 'FFh filled'. Except that, video memory opcode reads (but not data
reads) from C000h-FFFFh are mirrored to 4000h-7FFFh as usually.
Timex TS1500 has been delivered with 16K built-in RAM.
The 16K RAM configuration may be more or less treated as standard configuration
- programmers should recurse that below expansions of 32K or more RAM haven't
been very popular - thus any programs that require more than 16K memory won't
work on most ZX computers.
32K RAM
RAM is located at 4000h-BFFFh, whereas the upper half may be used to store data
and/or to 'execute' video code, but not for normal machine code program code.
Note that the BIOS memory detection ends at 8000h, the BIOS will detect only a
maximum of 16K RAM - and the stack pointer will be then initiated at 8000h.
Thus, loading large cassette files will overwrite the stack. When using more
than 16K RAM, the RAMTOP identifier in the system area must be changed manually
by POKE instructions, and then applied by a NEW instruction (or by a short
program that moves stack data and stack pointers to the new addresses).
Care should be taken that video memory may not cross the 7FFFh/8000h boundary;
Video data at 7FFFh is executed by addressing FFFFh, and thus the next address
will be 0000h instead 8000h! Ie. video memory may be located in either one of
the two 16K blocks, not in both.
48K RAM
RAM is located at 4000h-FFFFh, same restrictions as for 32K RAM apply. The

memory at C000h-FFFFh can be used as data storage only, but not for machine
code execution, and not for video data 'execution'.
When patching the RAMTOP value use the maximum of FFFFh (indicating 48K minus
one byte), as video memory must be below C000h, BASIC program code is
restricted to less than 32K as well, BASIC variables may use the additional
memory though.
Some 16K expansions can be combined with 32K expansions to gain a total of 48K
RAM.
64K RAM
Even though called "64K" expansions, most or all of these expansions do not
seem to support bank switching which'd allow to switch RAM into the 8K BIOS ROM
area at 0000h-1FFFh, so only 56K of RAM at 2000h-FFFFh can be used.
As for 48K RAM, the highest RAMTOP value would be FFFFh, the 'RAMBASE' is fixed
at 4000h, so that the additional memory at 2000h-3FFFh cannot be used by the
BIOS/BASIC interpreter.
ZX80/ZX81 Memory Binary Data/Machine Code Programs
-------------------------------------------------Depositing Binary Data/Program in Memory
The ZX81 does not directly support loading binary files from cassette, when
using LOAD, a memory image is loaded which contains the BIOS system variables,
the BASIC program, the video memory, and the BASIC variables.
The following are places that can be used as reserved area for binary code.
Using a REM instruction (in the program area)
Preferably locate the REM in the first line number (ensuring that it is located
at a fixed memory address), the length of the comment must provide enough space
for the program, then use POKE or else to fill the program code into it.
RESTRICTION: The comment may not contain the value 76h (the NEWLINE character).
Thus, the assembler program should not contain a "HALT" instruction (opcode
76h), or any other opcodes with operand 76h such like LD A,76h or JP 4276h
etc., or any data definitions such like "DB 76h".
Using a string (in the variables area)
Define a string such like A$ and fill it by binary character numbers. Note that
all variables are saved by SAVE command, it is not necessary that the program
itself contains the LET A$=... definition.
RESTRICTION: The position of the string in memory may change when (re-)defining
other variables, when modifying the BASIC program, or when altering video
memory contents.
Using memory above RAMTOP (outside of the known memory)
By default, RAMTOP (4004h) points to the address following to the detected RAM
area (4400h for 1KByte RAM). The user can alter this address by using POKE,
then type NEW to let the BIOS realize the new value, all memory above RAMTOP
may now be used for whatever purposes.
RESTRICTION: The (standard) SAVE instruction does not save this area to
cassette.
ZX80/ZX81 Cassette File Images
-----------------------------.81 and .80 Files
These are 1:1 copies of the content of real ZX81 and ZX80 cassette files.
ZX81 files are copies of the memory area 4009h up to E_LINE-1, the filename
(which is usually part of ZX81 files) is not included in the file.
ZX80 files are copies of the memory area 4000h up to E_LINE-1, the filename is
obviously not included as real ZX80 files do not have names.
.P and .O Files
Basically, these are identical as .81 (.P) and .80 (.O) files, except that an
unpredictable amount of garbage is meant to be attached to each file.
Older versions of the Xtender emulator seem to have attached 1 byte of garbage.
The current Xtender version apparently dropped this behaviour, and saves
correct length. Files at ftp.nvg randomly contain between 28-38 bytes of
garbage, probably caused by a cassette-to-disk transfer program. And some files
appear to have went through a CP/M filesystem, which caused the length to be
rounded up to multiples of 128 bytes.
Programs that deal with these files should determine the correct length (by
examining the header/system area), and truncate the extra bytes.
.P Files with Filename
Some .P files contain the original "FILENAME.P" (in ZX81 charset) at 003Fh
(within the PRBUFF area) (the purpose is probably to "preserve" long filenames
in MSDOS) (the preceeding bytes at 003Ch are usually 00-1A-1C, or in
FROGGER-HR: 00-1C-1C (unknown purpose)).
.TZX Files

This format was originally designed for the Spectrum, mainly intended to encode
nonstandard formats (copy-protections / turbo loaders). It can be also used
(via ID 19h) for ZX80/ZX81 programs. The format is quite complicated - it's
advantage is that it can contain more than one file (a feature required for
games that are split into two or more files).
--> Spectrum Cassette TZX Format
.C and .S and .V and .B or else
These are not actually real ZX files, programs that include such files won't
work on real ZX81 or ZX80, nor in no$zx. The Xtender emulator includes several
custom functions, allowing the user to create or delete directories on the
harddisk, probably as well as to format it, and to save these kind of files.
ZX80/ZX81 Cassette File Content
------------------------------ZX81 Data Field (excluding filename)
The data field is loaded to address 4009h, and it contains the system area
(excluding the first 9 bytes), the basic program, the video memory, and VARS
area.
The system area should contain proper data. Some entries are of special
interest:
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)
Memory at 403Ch and up may be misused for whatever purpose, video memory is
required to contain 25 HALT opcodes if the file was saved in SLOW mode.
ZX80 Data Field
The data field is loaded to address 4000h, and it contains the whole system
area, the basic program, and VARS area. Video memory is NOT included in ZX80
files.
The system area should contain proper data. The entry at 400Ah defines the end
address (used to calculate the file length). Memory at 4028h and up may be
misused for whatever purpose.
Normally, ZX80 files cannot be autostarted - except via "nocash LD H,L trick":
;nocash LD H,L trick for autostarting ZX80 files, 9/2009 by martin korth
4000h 8 x 00h
;System area: Zerofilled stuff
4008h 402Ch
;System area: Pointer to VARS
400Ah nn3Dh
;System area: Pointer to End of file
400Ch 1Ch x 00h
;System area: Zerofilled stuff
4028h 00h,01h,65h,76h ;BASIC program: Line 0001, LD H,L opcode, NEWLINE
402Ch 80h
;VARS area: End code
402Dh 13h x 00h
;Unused/padding (for entryoint 4040h)
4040h ...
;Machine code (entrypoint at 4040h)
xxxxh (xx3Dh-$) x 00h ;Unused/padding (for end address xx3Dh)
xx3Dh
;End of file (must be at xx3Dh)
After loading, the BASIC line is LISTed on the screen. The ZX80 BIOS doesn't
replace invalid tokens in range of 40h..7Fh by question marks, so Token 65h is
written as-is to VRAM (ie. as LD H,L opcode). The file must end at xx3Dh, so
the first character line starts at xx40h, which is (normally) excecuted 8 times
via JP HL from inside of the IRQ handler. After first execution, the LD H,L
opcode changes HL=xx40h to HL=4040h, so the next IRQ jumps to the autostart
entryoint at 4040h. That is still done with IRQs enabled, so the first opcode
at 4040h should be a DI.
Note: Emulators that do not handle opcodes in VRAM should reproduce autostart
as "IF [402Ah]=7665h THEN JP 4040h" after loading the file (that, preferably
with registers and memory initialized as on real hardware).
Maximum File Length
Files should usually not exceed 16 KBytes. The memory detection procedure in
both ZX80 and ZX81 BIOS stops after 16 KBytes (at 8000h), and initializes the
stack pointer at that address, even if more memory is installed. Thus loading
files of 16K or more would destroy the stack area (unless a separate loader has
previously moved the stack area to another location).
However, most ZXes don't have more than 16K RAM, so bigger files won't work on
most computers anyways.

ZX80/ZX81 Cassette Signals


-------------------------ZX81 Cassette File Structure
x seconds
your voice, saying "filename" (optional)
x seconds
video noise
5 seconds
silence (only some clock cycles required for ZX81)
1-127 bytes filename (bit7 set in last char)
LEN bytes
data, loaded to address 4009h, LEN=(4014h)-4009h.
1 pulse
video retrace signal (only if display was enabled)
x seconds
silence / video noise
The data field contains the system area, the basic program, the video memory,
and VARS area.
ZX80 Cassette File Structure
x seconds
your voice, saying "filename" (optional)
x seconds
video noise
5 seconds
silence (at least 0.5 seconds REQUIRED for ZX80)
LEN bytes
data, loaded to address 4000h, LEN=(400Ah)-4000h.
x seconds
silence / video noise
ZX80 files do not have filenames, and video memory is not included in the file.
File End
For both ZX80 and ZX81 the fileend is calculated as shown above. In either
case, the last byte of a (clean) file should be 80h (ie. the last byte of the
VARS area), not followed by any further signals except eventually video noise.
Bits and Bytes
Each byte consists of 8 bits (MSB first) without any start and stop bits,
directly followed by the next byte. A "0" bit consists of four high pulses, a
"1" bit of nine pulses, either one followed by a silence period.
0: /\/\/\/\________
1: /\/\/\/\/\/\/\/\/\________
Each pulse is split into a 150us High period, and 150us Low period. The
duration of the silence between each bit is 1300us. The baud rate is thus 400
bps (for a "0" filled area) downto 250 bps (for a "1" filled area). Average
medium transfer rate is approx. 307 bps (38 bytes/sec) for files that contain
50% of "0" and "1" bits each.
Hardware, Connectors, Upgrading
------------------------------Hardware Plugs'n'Pins
--> HW External Connectors
--> HW Internal Pins
Hardware Modifications
Below are some ideas of how to attack ZX hardware just by using a few
resistors, diodes and/or some wires. Ie. it's all very simple stuff, not
requiring special hardware or etched circuit boards, but nethertheless quite
useful and effective.
-->
-->
-->
-->
-->
-->
-->
-->

HW
HW
HW
HW
HW
HW
HW
HW

Replacing the ZX81 ROM by an EPROM


56K RAM Upgrade
Connecting a Joystick
Making the ZX81 Faster
Upgrading RamPaks for True Hi-Res Graphics
Connecting a Monitor
Getting rid of the 9V DC Power Supply
Uploading Programs from the PC to the ZX81

HW External Connectors
---------------------TV - Video Output - UHF Channel 36 (Cinch, female)
Ring: Shield
Tip: TV Signal
Note that modern TV sets (such manufactured after 1981, especially such with
automatic channel-detection) might have problems to detect/handle the signal.
If necessary, adjust the contrast/brightness, and (as far as supported) adjust
the channel manually.
EAR - Cassette Input (from recorder earphone socket to ZX81)
Ring: Ground
Tip: Cassette Input
MIC - Cassette Output (from ZX81 to recorder microphone socket)
Ring: Ground
Tip: Cassette Output
This is in fact the video signal, output through resistor and capaciator,

causing black and white stripes to be displayed during cassette output.


9V DC - Power Supply
Ring: Ground
Tip: 9V DC
Even though using the official 9V ZX power supply, the voltage is rather 11V
than 9V in my computer. Internally, the ZX81 is operated at 5V, generated from
a 7805 voltage regulator, so the input voltage could be anything in range from
7V up to I think 24V. However, a higher voltage would heat up the regulator
even more, and be aware that it is output to the expansion port, possibly
damaging attached hardware if it is too high.
Power Consumption
Internal 5V, 0.31A, ie. 1.55W, without 16K RAM
Internal 5V, 0.39A, ie. 1.95W, with Memotech Mempak 16KB
Expansion Port (46 Pin Cartridge Slot, male)
Only 44 pins are actually used, the two ---SLOT--- marked pins are cut-out,
used as polarisation mark. When attaching a 46pin female plug, note that you
must cut off the plastic at the left and right ends, preferably before doing
any soldering work.
Upper Side
Lower Side
1A D7
1B 5V DC
2A /RAM CS
2B 9V DC
3A ---SLOT--3B ---SLOT--4A D0
4B 0V
5A D1
5B 0V
6A D2
6B CLK
7A D6
7B A0
8A D5
8B A1
9A D3
9B A2
10A D4
10B A3
11A /INT
11B A15
12A /NMI
12B A14
13A /HALT
13B A13
14A /MREQ
14B A12
15A /IORQ
15B A11
16A /RD
16B A10
17A /WR
17B A9
18A /BUSAK
18B A8
19A /WAIT
19B A7
20A /BUSRQ
20B A6
21A /RESET
21B A5
22A /M1
22B A4
23A /REFSH
23B /ROM CS
Expansion cartridges should have a male connector at the rear side - allowing
to connect further cartridge(s) - one to each other.
HW Internal Pins
---------------ZX81 Keyboard Connector
Pin 1-8: A15, A14, A8, A13, A9, A12, A10, A11.
Pin 9-13: KBD0, KBD1, KBD2, KBD3, KBD4.
Video Signal
The video output consists of a /SYNC signal (low during horizontal and vertical
retrace), and the actual VIDEO signal (low=black, high=white). In the ZX81 both
signals are internally mixed into a single signal, and then output as shown
below at Pin 16 of the Ferranti chip.
Reportedly these voltages are output on Pin 16 (no idea if/when that happens in
reality, maybe on US versions with VHF-modulator):
0V
sync
2.5V black
5V
white
On my own ZX81 with UHF modulator (ie. without the VHF pulldown resistors):
2.5V sync
3.7V black
5.0V white
When connecting Pin16 directly to the AV-input of my television set:
0.0V sync
0.5V black
1.0V white
50Hz/60Hz Refresh Rate Jumper
Even though the display refresh rate is actually software based, the BIOS
determines the local desired rate by reading from I/O port FEh. In the ZX81,
the setting depends on whether Pin 22 of the Ferranti chip is shortcut to
ground or not.
When it is grounded, by a 0 Ohm "resistor" called R 30, then vertical blanking

time is reduced for 60Hz timing - note that this heavily reduces the
user-available CPU time in SLOW mode.
ZX81 Ferranti ULA
1 A7'
2 A8'
3 A2'
4 A1'
5 A0'
6 /RD
7 /IORQ
8 /WR
9 /MREQ
10 M1
11 A14
12 /RAMCS
13 /ROMCS
14 OSC (EXPANSION)
15 /NMI
16 TV/TAPE
17 /HALT
18 A15
19 D7
20 TAPE.IN
21 D6
22 /NTSC
23 D5
24 D4
25 KDB4
26 D3
27 KDB3
28 D2
29 KDB2
30 D1
31 KDB1
32 D0
33 KBD0
34 GND
35 OSC (CERAM)
36 A3'
37 A4'
38 A5'
39 A6'
40 +5V
HW Replacing the ZX81 ROM by an EPROM
------------------------------------Even though the ZX81 includes a 24 pin 8K
with a 28 pin socket - matching for an 28
must be exchanged:
- Disconnect A11 from Pin 20.
- Disconnect A12 from Pin 23.
- Connect /OE Pin 22 to /CE Pin 20.
- Connect A11 to Pin 23.
(Each counted in 28 pin device units, ie.
Caution:
Best use a 2764 EPROM, CMOS chips (27C64)
probably they are too fast and/or outputs

ROM, it should be usually delivered


pin 8K EPROM. However, a few pins

Pin 14 is lower left.)


don't seem to work very well aren't amplified enough.

HW 56K RAM Upgrade


-----------------Upgrading to 56K RAM by krbaker
ROM is enabled at 0000h-1FFFh (8K), RAM at 2000h-FFFFh. /MREQ is for normal
memory access, /RFSH is for character pattern & hires bitmap memory fetches.
/M1 mirrors 0000h-7FFFh to 8000h-FFFFh on opcode fetches (aka BG map), in
result, memory at 8000h-FFFFh can be used for data storage only, machine code
cannot be executed in that area.
____
__________________________________
/M1 ----|AND \__|__ ____
____
RAM A15
A15 ----|____/
|OR \______|INV \_____ ____
A14 ----|OR \_____|____/
| |____/ ___|OR \___ /RAMCS
A13 ----|____/
|
|
|____/
/MREQ --|AND \_____________ | ________|___|OR \___ /ROMCS
/RFSH --|____/
|_____________|____/
Parts List: 7404 hex inverter, 7408 quad 2-input AND gate, 7432 quad 2-input OR
gate, and 128Kx8bit static RAM. Notes: Remove the resistors in the /ROMCS and
/RAMCS lines on the board, connect RAM A16 to VCC or GND. Circuit tested &

working with either 74LSxx or 74HCxx chips.


Caution: Mapping RAM to address 2000h works only with ZX80 and ZX81/TS1000
BIOSes (the TS1500 BIOS checks for [2000h]=01h, and if so, treats it as
expansion ROM).
Compatibility Problem: Memopak expansions do allow d_file at 4000h-BFFFh (eg.
30K BASIC programs, followed by d_file at Bxxxh), but, above circuit supports
only 4000h-7FFFh. To fix this, RAM A15 should be also HIGH whenever A15=1 AND
A14=0.
HW Connecting a Joystick
-----------------------As far as I know, there isn't any (in-)official standard for sticks, nor do any
games support a standard keyboard/joystick control scheme. Anyways, a digital
four direction/one button joystick could be easily connected to one of the
keyboard rows.
I'd personally vote for row 4, Bits 0-4 used as Fire, Left, Right, Up, Down,
and the A12-diode as /Select. Using this method, the Keys for Right, Up, Down,
comply with ZX cursor controls (Shift+8,7,6). As used for my 'Starfight' game.
Caution: When having a PC data transfer cable connected to the keyboard lines
as well, the joystick cable may disturb the data transfer. If so, insert diodes
(1N4148 or else) into each of the four direction lines, ring pointing to the
joystick side (nocash upload data lines), and if necessary for fire button also
(nocash upload clock line).
HW Making the ZX81 Faster
------------------------Wilf Rigter's WAITMOD (7/2005) speedup 9%
The ZX81 generates a 14-cycle WAIT along with every NMI. However, the WAIT is
actually required only after the HALT opcode at 0079h (ie. on the final NMI at
the end of the upper/lower blanking period). Rewiring the R1 resistor, and
adding another 10K resistor and a PNP transistor (eg. BC557) causes the WAIT to
be generated only after HALT opcodes, and thus saves 14-cycles on all other
NMIs.
Before:
------- R1 ---------------- /HALT CPU.18
After:
----+-- R1 ------+--/cut/-- /HALT CPU.18
|
___
|
+-----|C | +--------- GND
| B|_____________
VCC--10K--|E__|
/WAIT CPU.24
All basic/machine code software with video output enabled will run 9% faster,
there should be no compatibility problems, except, eventually with a few
unstable (bugged) programs.
Nocash NMI Patch (5/2010) speedup 2%
Removing the useless 10-cycle "JP @@blah" causes the 7-cycle "JR @@zero" to be
executed instead, thus saving 3-cycles per NMI. After the HALT, a final NMI is
executed, and in this case, the 10-cycle "JP @@blah" is required as delay, this
is solved by moving the JP @@blah after the HALT opcode.
<---- Original NMI Handler ---->
<----- Tuned NMI Handler ----->
0066 08
ex
af,af
0066 08
ex
af,af
0067 3C
inc a
0067 3C
inc a
0068 FA 6D 00
jp
m,@@blah
0068 28 02
jr
z,@@zero
006B 28 02
jr
z,@@zero
006A 08
ex
af,af
@@blah:
006B C9
ret
006D 08
ex
af,af
@@zero:
006E C9
ret
006C 08
ex
af,af
@@zero:
006D F5
push af
006F 08
ex
af,af
006E C5
push bc
0070 F5
push af
006F D5
push de
0071 C5
push bc
0070 E5
push hl
0072 D5
push de
0071 2A 0C 40
ld
hl,[400Ch]
0073 E5
push hl
0074 CB FC
set 7,h
0074 2A 0C 40
ld
hl,[400Ch]
0076 76
halt
0077 CB FC
set 7,h
0077 C3 7A 00
jp
@@blah
0079 76
halt
@@blah:
007A D3 FD
out [0FDh],a
007A D3 FD
out [0FDh],a
007C DD E9
jp
ix
007C DD E9
jp
ix
All basic/machine code software with video output enabled will run 2% faster,
there should be no compatibility problems, with a few exceptions: buggy
programs (with unstable timings), programs that jump to addresses 0068..0079,
and, pseudo-hires programs that use I=0 (only Madjump II does do that).

Nocash Increased Blanking Time - speedup around 50% possible


Finally, the CPU speed can be (greatly) improved by increasing the number of
blank lines. There are three ways to do this:
1) Decrease Vertical Picture Size, increase upper/lower blanking accordingly
2) Decrease Vertical Retrace Time, increase upper blanking accordingly
3) Decrease Frame Rate by increasing upper/lower blanking
Method 1) is perfectly legal and can be about 250% faster - but works only with
small pictures. Methods 2) and 3) can be around 50% faster, but might cause
problems with some TV sets, so, using them should be made optional. If desired,
Method 3) can be also implemented at BIOS level (increase the byte at 02E2h) that patch will speedup all BASIC programs & most machine code programs.
HW Upgrading RamPaks for True Hi-Res Graphics
--------------------------------------------When using "True Hi-Res" software, pixel data is read from RAM rather than ROM
area. Pixel data is requested by a /RFSH (refresh) signal, rather than by a
normal /RD (read) signal. So, RAM is required to output data whenever when /RD
or /RFSH are low.
Internal RAM does support the above combination, but external RAM usually
generates its own read signal - which senses /RD only. Below example for fixing
this problem is taken from Wilf Ritgers ZX81VID.TXT document:
ZX81.+5V

--------------------+-----+---- RAMPACK.+5V
|
|
ZX81./RFSH ----|<|---+--[4K7]--+
+---- RAMPACK./RFSH ;ALWAYS HIGH
|
ZX81./RD
----|<|---+-------------------- RAMPACK./RD
;/RD AND /RFSH
The RAMPACK is modified to enable the data output at RFSH time by cutting the
RD and RFSH lines at the edge connector and installing 2 only 1N34A Germanium
diodes and a 4.7K pullup resistor.
Note: ZX hardware often uses a couple of small RAM chips (instead of a single
28 pin SRAM chip), anyways these are SRAM chips either (so cutting the RFSH
signal shouldn't cause problems). Ie. you can be quite sure that no DRAM is
used because the refresh register is used as interrupt counter.
HW Connecting a Monitor
----------------------Internally the ZX81 is producing a more or less crystal clear video signal,
which is normally converted into a TV signal by the UHF modulator in the
computer, and then re-decoded by the de-modulator in the TV Set, most likey
resulting in a more than bad display quality.
Anyways, the 'raw' video signal can be found at pin 16 of the ZX81 Ferranti
chip, that is: 0V=Sync, 2.5V=black, 5V=white, which might or might not work
with various types of computer displays. Some displays might not understand the
refresh rates, and others might require other voltages - which might be
adjusted by one or more resistors.
I've currently only tried to connect a GT65 Green Monitor (for
Amstrad/Schneider CPC homecomputers): Connect Ground as such, and connect the
Video signal to both /Sync, and (preferably through a 1kOHm resistor) to
Luminance. The voltage is apparently much too high (not actually blowing the
display, but the picture appears very bright), the resistor is more or less
healing this.
HW Getting rid of the 9V DC Power Supply
---------------------------------------When connecting the ZX81 to the PC, the external ZX 9V power supply becomes
more or less useless, and it might be recommended to use the PC supply instead.
Two possible methods are:
Using 12V DC (Yellow cable in PCs)
The official ZX so-called-9V-supply actually outputs about 11V, thus the
slightly higher voltage wouldn't cause much more overheat, but keep in mind
that the voltage is forwarded to any connected hardware expansions, if
necessary lower the voltage to approx. 11V by inserting a 1N4004 diode into the
12V line.
Using 5V DC (Red cable in PCs)
The ZX81 is internally operated at 5V only, the additional volts are just blown
into heat by the 7805 voltage regulator. So, connecting 5V directly to the 7805
output does work (and prevents the keyboard from heating up). However, the "9V"
voltage is output to the expansion port, and some hardware expansions
(including 16K Memotech RAM Paks) actually require this voltage.

A separate ground signal isn't forcefully required if the ZX is connected to


the PCs parallel port, as the existing ground/shield connection could be badly
mis-used as ground.
HW Uploading Programs from the PC to the ZX81
--------------------------------------------The Transmit function in no$zx Utility menu supports three different transfer
methods, each using the PCs parallel port to output data to the ZX (only into
that direction, not vice versa):
1) Nocash Highspeed (transmission time 100-1300ms)
This is a very simple six-diodes-network. The transmission rate is approx.
12500 bytes/sec (about 300 times faster than 38 bytes/sec cassette loading).
The ZX is automatically reset and immediately switched into read-mode, even a
huge 16K file is transferred in less than 1.5 seconds - ways faster than the
unpatched ZX81/16K CLS boot procedure.
However, this method requires a patched BIOS ROM, and it's thus restricted to
more or less serious users only. Data is transferred in units of 4 Bits,
synchronized by a separate clock signal, thus making the timing rather
uncritical, even when using a multitasking operating system.
2) Mixed (transmission time 3-4 seconds)
This method combines the above/below protocols, but works well without patched
BIOS ROM. Before transmission, you'll have to type LOAD "" manually on remote
side, a small loader will be then transferred by using the slow transfer method
(approx 3 seconds), followed by the actual file using highspeed transfer
(approx 0-1 second).
3) ZXTAPE (transmission time up to 7 minutes)
This protocol is transferring data at original cassette speed (38 bytes per
second), similar to Wilf Ritger's ZXTAPE program. A possible advantage is that
you won't need to open the ZX81, and won't need to install any diodes, just
connect parallel port pin 2 and ground to the ZX EAR socket, and ignore further
instructions below.
Note that this method won't work very well with multi-tasking operating
systems.
You need:
1 PC with Parallel Port, and a normal Centronics Printer Cable
1 Centronics plug (36 pins, female)
1 EPROM (2764 non-CMOS) and EPROM burner (optional)
6 Diodes (for example 1N4148, ie. the most cheapest standard ones)
and some short isolated wires
Schematic
ZX Mainboard Side
Cassette Input (EAR)
Keyb Col0/Pin9 (CLK)
Keyb Col1/Pin10 (D0)
Keyb Col2/Pin11 (D1)
Keyb Col3/Pin12 (D2)
Keyb Col4/Pin13 (D3)
Expansion 21A (RESET)
ROM Pin26 (A13)
VCC
Expansion 4B/5B (GND)

Centronics Side
------------- Centr.Pin2 (D0)
-----|>|----- Centr.Pin3 (D1)
-----|>|----- Centr.Pin4 (D2)
-----|>|----- Centr.Pin5 (D3)
-----|>|----- Centr.Pin6 (D4)
-----|>|----- Centr.Pin7 (D5)
-----|>|----- Centr.Pin8 (D6)
------------- Centr.Pin9 (D7) (LO=ZX80, HI=ZX81)
----[10K]---- Centr.Pin9 (D7)
------------- Centr.Pin24 (GND)
_______
CPU.Pin36 (A6)
--|D1
Q1|-- Centr.Pin10 (ACK)
CPU.Pin20 (/IORQ)
--|CK1
|
CPU.Pin26 (/RESET)
--|SET1
| 74LS74 FlipFlop
VCC ---------------------|RES1
|
|_______|

Step 1 - The Diodes


Connect the diodes to Pin 3-8 of the Centronics plug. The end with the black
ring (or other color) must point to the plug, the other end will be connected
to the ZX81 mainboard. The diodes are required because otherwise the strong PC
LPT port pulls up the ZX81 address signals when pressing a key. (Even though
bi-directional LPT ports might be able to avoid that.)
Step 2 - Connecting the Data Lines.
When looking on top of the ZX81 board, you will see the keyboard connector in
lower right. Counted from the right end, pin 1-8 are A8-A15 signals (in no
specific order) - ignore these. Pin 9-13 are Keyboard Columns 0-4 (in exactly
that order) - connect these to the diodes at Pin 3-7 of the Centronics plug.
Step 3 - Connecting Ground, Reset and Cassette.
Connect Ground (found at Pin 4B and 5B of the expansion port) to Pin 24 or else

of the Centronics plug. Connect Reset (Pin 21A of expansion port) to the diode
at Pin 8 of Centronics plug (the reset signal isn't actually required, but it's
quite comfortable if the transmission program can reset the ZX81). Finally,
connect the Cassette Input (EAR) to Pin 2 of the Centronics plug (this is
required only if you are not using patched BIOS).
Step 4 - Connecting the ACK Flipflop
Connect the 74LS74 flipflop as shown
info and EPROM version string to the
more complicated than necessary, but
problems.

(NEW, added 2010)


above. This is allowing to send feedback
PC. It's making the circuit a little bit
it's rather useful to solve connection

Software
The transmit function (for uploading .P .O .81 .80 files to the ZX80/ZX81) is
found in no$zx's "Utility" menu. The "Utility" menu also contains a function
called Create Patched BIOS Image, which creates a file called XMITZX81.ROM,
which is to be stored in the EPROM; the ROM-image is 16K in size, containing
the original ZX80/ZX81 BIOSes, and the upload software.
Keep in mind that some pins of the ROM socket must be reconnected for EPROM use
(see chapter about replacing BIOS ROM by EPROM).
Joystick Compatibility
When having a joystick connected to the ZX keyboard lines as well, then above
nocash/mixed transfer methods may not work. This can be fixed by disconnecting
the joystick, or by inserting diodes (1N4148 or else) into the joystick
connectors data lines (Keyboard Bits 1-4).
Due to the rather high transfer rate, the incoming signal will run into the
joystick cable, and as there are no 'terminators' (resistors) at the end of the
cable (as for ethernet networks for example), the signal will 'bounce back' at
the cable end and run back to the ZX, confusing the transmission program that
simultaneously wants to read arrived data.
History
2002 - original circuit for zx81
2010 - added feedback-flipflop, added zx80 support, changed eprom content
ZX Spectrum
----------Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum
--> Spectrum

Models
I/O Map
Memory Maps
System Variables
ULA
VRAM
Video Connectors
Timings
Sound
Disc and Tape Drives
Interrupts
Keyboards
Joystick Ports
Mouse Ports
Light Guns
Printer Ports
Serial Port
Expansion Ports
ROM Cartridges
Chipset Pinouts
Xboo

Z80 CPU
--> Z80 CPU Specifications
The BASIC Interpreter
--> BASIC Interpreter
"What is a Computer Good For?
Your new Timex Sinclair 2000 computer is a very special instrument. It is a
tool that can increase the power of your mind as a hammer or a wheelbarrow
assists your muscles." - quoted from TS2068 User Manual
Spectrum Models
--------------Original Spectrums (by Sinclair, later by Amstrad)
1982 Spectrum 16K - original low-cost version (only 16K RAM)
1982 Spectrum 48K - original full version (48K RAM)
1984 Spectrum +
- new keyboard, reset button

1985
1986
1987
1987
1987

Spectrum 128 - 128K-RAM,PSG,MIDI,RS232,RGB,32K-ROM


Amstrad +2 (typewriter keyboard, built-in cas drive, two joy ports)
Amstrad +2A (manufactured in Taiwan) (+3 style mainboard, Centronics)
Amstrad +2B (same as +2A but manufactured in China instead of Taiwan)
Amstrad +3 (more ROM, RAM map-able at 0000h for CP/M, built-in disk)

Timex (licensed Spectrum clones)


1983 TS2068 special video modes, timex bios, PSG, 48K RAM, NTSC (USA)
1984 TC2068 special video modes, timex bios, PSG, 48K RAM, PAL (Portugal)
1984 TC2048 special video modes, spectrum bios, no PSG, 16K RAM, PAL (Portu.)
Unlicensed Spectrum Clones
There are about 50 unlicensed spectrum clones: Mass-produced clones (like
russian pentagon and scorpion), as well as homebrew modifications.
Spectrum I/O Map
---------------The original spectrum did use only one I/O address (the ULA at port FEh). And
only one pre-assigned expansion I/O address (the ZX printer at port FDh).
Although that original design was very simple, the lack of further pre-assigned
addresses resulted in a mess. For example, there are at least 5 different
"standards" for connecting joysticks, 3 for PSG sound chips (probably more),
many dozens of floppy and centronics standards, etc.
Spectrum I/O Ports (accessed via IN/OUT opcodes)
Port Binary Address
Dir Description
xxFF ................ R
Spectrum Current VRAM Data (dirt effect)
xxFE nnnnnnnn.......0 R
Spectrum ULA (Keyboard, and CAS Input)
xxFE ...............0 W
Spectrum ULA (Border Color, Speaker/CAS Output)
F7FE ....0..........0 R
Spectrum +2/+2A/+3 Joystick 2
EFFE ...0...........0 R
Spectrum +2/+2A/+3 Joystick 1
F7FE ...10..........0 R
Interface 2 Joystick 2
EFFE ...01..........0 R
Interface 2 Joystick 1
FFFD 11............0. W
Spectrum 128K/+2/+2A/+3 PSG index register
FFFD 11............0. R
Spectrum 128K/+2/+2A/+3 PSG data read (and RS232)
BFFD 10............0. W
Spectrum 128K/+2/+2A/+3 PSG data write (and RS232)
7FFD 0.............0. W
Spectrum 128K/+2 Memory Control
BFFD 10............0. R
Spectrum +2A/+3 Mirror of Port FFFDh (+2A/+3 only)
7FFD 01............0. W
Spectrum +2A/+3 Memory Control A
1FFD 0001..........0. W
Spectrum +2A/+3 Memory Control B and Disk Motor
0FFD 0000..........0.
Spectrum +2A/+3 Centronics
3FFD 0011..........0. R/W Spectrum +3 Floppy FDC NEC uPD765 data
2FFD 0010..........0. R
Spectrum +3 Floppy FDC NEC uPD765 status
xxFB .............0.. R/W ZX Printer
xxF7 ...........10... R/W Interface 1 RS232/Network Data (1bit send/receive)
xxEF ...........01... R/W Interface 1 Microdrive/RS232/Network Control
xxE7 ...........00... R/W Interface 1 Microdrive Data
(8bit send/receive)
xx1F ........000..... R
Kempston joystick
Timex I/O Ports
xxFF ........11111111
xxFE nnnnnnnn11111110
xxFE ........11111110
xxF4 ........11110100
xxF6 ........11110110
x1F6 .......111110110
x2F6 ......1.11110110
xxF5 ........11110101
xxFB ........11111011
xx1F ..........0.....
xxEF ........???0????

R
W
R/W
R/W
R/W
W
R/W
R
R/W

Timex
Timex
Timex
Timex
Timex
Timex
Timex
Timex
Timex
Timex
Timex

Display Mode
ULA (Keyboard, and CAS Input)
ULA (Border Color, Speaker/CAS Output)
Memory Mapping
TS2068/TC2068 PSG data R/W (sound registers)
TS2068/TC2068 PSG data R/W (and joystick 1)
TS2068/TC2068 PSG data R/W (and joystick 2)
TS2068/TC2068 PSG index
Printer (TS2040 or Alphacom 32)
TC2048 joystick (kempston-style, A5-only)
FDD Interface (for FDD or FDD-3000 drive)

Expansion I/O Stuff (Audio related)


0007
W
Cheetah Sweet Talker - Speech Output (halts CPU)
007F
0
W
DK'Tronics Speech Synthesiser - Speech Output
007F
0
R
DK'Tronics Speech Synthesiser - Speech Status
xx7F ........011
R
Fuller Box - Joystick port
xx3F ........00
W
Fuller Box - PSG index (also DK'Tronics PSG)
xx3F ........00
R
Fuller Box - PSG data read (maybe also DK'Tronics?)
xx5F ........010
W
Fuller Box - PSG data write (also DK'Tronics PSG)
xx9F ........ 00
W
Fuller Orator / Box Master Unit - Speech Output
xxBF ........ 01
R
Fuller Orator / Box Master Unit - Speech Status
xx9F ........ 00
W
William Stuart Systems Music Synthesiser PSG index
xxDF ........ 10
W
William Stuart Systems Music Synthesiser PSG data
xxFF ........1..11111 W
Bi-Pak ZON X Soundbox PSG index
xx7F ........0..11111 W
Bi-Pak ZON X Soundbox PSG data write
0038 0000000000111000 R
Currah uSpeech enable/disable BIOS (mirror)
Expansion I/O Stuff (Storage, Centronics, etc.)

xx7F ........01111111
Aerco Centronics Interface
xx8F ........10001111
JLO status/command
xx9F ........10011111
JLO track
xxAF ........10101111
JLO sector
xxBF ........10111111
JLO data
xxB7 ........10110111
JLO select
xxFB ........1....0..
ZX LPrint III Enable ROM, and Write=Data, Read=Busy
xx7B ........0....0..
ZX LPrint III Disable ROM
E3BF
0
W
Kempston Centronics Ctrl (b0=0=Strobe)(0Eh,0Fh,81h)
E2BF
0
R
Kempston Centronics Status (b0=1=Busy)
E0BF
0
W
Kempston Centronics Data Output
xxBB ........
R
DK'Tronics Centronics Status (b7=1=Busy)
xxBB ........
W
DK'Tronics Centronics Ctrl (b1=0=Strobe) (02h,00h)
xx9B ........
W
DK'Tronics Centronics Data
xxDB ........
W
DK'Tronics Centronics Config 1 (set to 3Fh)
xxFB ........
W
DK'Tronics Centronics Config 2 (set to FFh,80h)
dd0E dddddddd
R
Wafadrive Centronics Data Out ;via "IN A,(dd0Eh)"
x00A
s
R
Wafadrive Centronics Strobe Out;via "IN A,(s00Ah)"
0002
R
Wafadrive Centronics Busy In ;returned in bit5
xxFB ........
W
Indescomp Centronics Data
xxFB ........
R
Indescomp Status (b0=Busy,b1=Rs232Busy,b2=RxD)
xx7F ........
W
Indescomp Control (b0=Strobe,b1=TxD,b2=CTS)
xx1B ........
0
W
Disciple FDC Command
xx1B ........
0
R
Disciple FDC Status
xx5B ........
0
R/W Disciple FDC Track
xx9B ........
0
R/W Disciple FDC Sector
xxDB ........
0
R/W Disciple FDC Data
xx1F ........
W
Disciple Control Register
xx1F ........
R
Disciple Joystick/Printer/Network
xx3B ........
0
?
Disciple Network Wait
F7FE
0
0 R
Disciple Disciple Joystick
EFFE
0
0 R
Disciple Disciple Joystick
xxBB ........
0
R
Disciple Enable Internal ROM/RAM
xxBB ........
0
W
Disciple Disable Internal ROM/RAM
xxFB ........
0
W
Disciple Centronics Data
xx7B ........
0
R
Disciple Map ROM=0000h, RAM=2000h
xx7B ........
0
W
Disciple Map ROM=2000h, RAM=0000h
xxE3 ........
000
W
PlusD FDC Command
xxE3 ........
000
R
PlusD FDC Status
xxE7 ........
001
R
PlusD Enable Internal ROM/RAM
xxE7 ........
001
W
PlusD Disable Internal ROM/RAM
xxEB ........
010
R/W PlusD FDC Track
xxEF ........
011
W
PlusD Control Register
xxF3 ........
100
R/W PlusD FDC Sector
xxF7 ........
101
W
PlusD Centronics Data
xxF7 ........
101
R
PlusD Centronics Busy
xxFB ........
110
R/W PlusD FDC Data
xx1F ........
W
Beta Disk FDC Command
xx1F ........
R
Beta Disk FDC Status
xx3F ........
R/W Beta Disk FDC Track
xx5F ........
R/W Beta Disk FDC Sector
xx7F ........
R/W Beta Disk FDC Data
xxFF ........
R
Beta Disk Status
xxFF ........
W? Beta Disk Control
And many more. See Floppy Disc and Centronics chapters for details on some
various further expansion ports.
Other
xx9F
xx1F
xxBF
xx9F
xx3F
xx3F
xx3F
xxBF
7F3F
1F3F
FF3F
FFBF
FF7F
FADF
FBDF
FFDF
xx1F
xx3F
xx5F
xx7F
xxDF
xxDF

........
........
........
........
........
........
........
........

Multiface I In
Multiface I Out
Multiface 128 In
Multiface 128 In v2 (Disciple) (uh/what?)
Multiface 128 Out
Multiface III Button
Multiface III In
Multiface III Out
Multiface III P7FFD (uh?)
Multiface III P1FFD (uh?)
British Micro Grafpad Pen up/down
British Micro Grafpad Pen position X coordinate
British Micro Grafpad Pen position Y coordinate
......?0..0....?
Kempston Mouse Buttons (b0=Right,b1=Left,b2=Mid)
.....0?1..0....?
Kempston Mouse X
.....1?1..0....?
Kempston Mouse Y
........000..... R/W AMX Mouse Z80PIO Data A: X, CentronicsLSBs/Strobe
........001..... R/W AMX Mouse Z80PIO Data B: Y, CentronicsMSBs/Busy
........010.....
AMX Mouse Z80PIO Ctrl A: X, CentronicsLSBs/Strobe
........011.....
AMX Mouse Z80PIO Ctrl B: Y, CentronicsMSBs/Busy
........110..... R
AMX Mouse 74LSXX Logic: Mouse Buttons (R)
........
R
Stack Light Rifle (R) (light gun trigger/sensor)

Memory Mapped Ports (eg. triggered on opcode fetches from that addresses)
0008h,1708h
Interface 1 - Enable external ROM
0700h
Interface 1 - Disable external ROM
0008h
Wafadrive - Enable external ROM
0008h,0048h,1708h
Discovery - Enable external ROM/RAM/WD/PIA
1748h
Discovery - Disable external ROM/RAM/WD/PIA
2800h..2803h
Discovery - WD1770 registers (disk)
3000h..3003h
Discovery - PIA6821 registers (centronics, etc.)
0000h,0008h,0066h,028Eh
Disciple and PlusD - Enable external ROM/RAM
0000h,0008h
Timex FDD Interface - Enable ROM/RAM
0604h
Timex FDD Interface - Disable ROM/RAM
0038h.Read
Currah uSpeech enable/disable BIOS
1000h.Read
Currah uSpeech Status (R)
1000h.Write
Currah uSpeech Output (W)
3C00h..3CFFh
Beta/BetaPlus Disk
- Enable ROM and I/O Ports
3D00h..3DFFh
Beta128 Disk
- Enable ROM and I/O Ports
4000h..FFFFh
Beta/BetaPlus/Beta128 - Disable ROM and I/O Ports
Note: Disciple and PlusD do only have the <enable> functions mapped to memory
(whilst <disable> is done via I/O ports).
Spectrum Memory Maps
-------------------Spectrum 16K Memory Map
0000h-3FFFh ROM (BASIC)
4000h-7FFFh RAM (Work RAM and VRAM)
8000h-FFFFh N/A
Spectrum 48K/Spectrum + Memory Map
0000h-3FFFh ROM (BASIC)
4000h-7FFFh RAM (Work RAM and VRAM)
8000h-FFFFh Additional RAM

(with waitstates)

(with waitstates)

Spectrum 128K/+2 Memory Map


0000h-3FFFh ROM0 (EDITOR) or ROM1 (BASIC) (see Port 7FFDh.Bit4)
4000h-7FFFh RAM Page 5 (VRAM)
(with waitstates)
8000h-BFFFh RAM Page 2 (Work RAM)
C000h-FFFFh RAM Page 0..7 (see Port 7FFDh.Bit0-2) (Page1,3,5,7=waitstates)
Spectrum +2A/+3 Memory Map (in normal mode)
0000h-3FFFh ROM0..ROM3 (see Port 7FFDh.Bit4 and 1FFDh.Bit2)
4000h-7FFFh RAM Page 5 (VRAM)
(with waitstates)
8000h-BFFFh RAM Page 2 (Work RAM)
C000h-FFFFh RAM Page 0..7 (see Port 7FFDh.Bit0-2) (Page 4-7 with waitstates)
Spectrum +2A/+3 Memory Map
0000h-3FFFh RAM Page 0,
4000h-7FFFh RAM Page 1,
8000h-BFFFh RAM Page 2,
C000h-FFFFh RAM Page 3,

(in special mode) (with RAM at 0000h for CP/M)


4, 4, or 4 (see Port 1FFDh.Bit0-2)
5, 5, or 7 (see Port 1FFDh.Bit0-2)
6, 6, or 6 (see Port 1FFDh.Bit0-2)
7, 3, or 3 (see Port 1FFDh.Bit0-2)

Timex TC2048 Memory Map (see Port F4h, and Port FFh)
Address
HOME
EX-ROM
0000h-1FFFh BIOS
Expansion Bank 0
2000h-3FFFh BIOS
Expansion Bank 1
4000h-5FFFh VRAM (Screen 0) Expansion Bank 2
6000h-7FFFh VRAM (Screen 1) Expansion Bank 3
8000h-9FFFh N/A
Expansion Bank 4
A000h-BFFFh N/A
Expansion Bank 5
C000h-DFFFh N/A
Expansion Bank 6
E000h-FFFFh N/A
Expansion Bank 7

DOCK
N/A
N/A
N/A
N/A
N/A
N/A
N/A
N/A

Timex TC2068/TS2068 Memory Map (see Port F4h, and Port FFh)
Address
HOME
EX-ROM
DOCK
0000h-1FFFh BIOS
Extended BASIC ROM
Cartridge Bank 0
2000h-3FFFh BIOS
Expansion Bank 1
Cartridge Bank 1
4000h-5FFFh VRAM (Screen 0) Expansion Bank 2
Cartridge Bank 2
6000h-7FFFh VRAM (Screen 1) Expansion Bank 3
Cartridge Bank 3
8000h-9FFFh RAM (Work RAM) Expansion Bank 4
Cartridge Bank 4
A000h-BFFFh RAM (Work RAM) Expansion Bank 5
Cartridge Bank 5
C000h-DFFFh RAM (Work RAM) Expansion Bank 6
Cartridge Bank 6
E000h-FFFFh RAM (Work RAM) Expansion Bank 7
Cartridge Bank 7
EX-ROM bank 0 is reportedly mirrored to EX-ROM banks 1-7 (which conflicts with
external EX-ROM banks) (external DOCK banks have no such problems).
Spectrum 128K/+2/+2A/+3 Memory Banks
The RAM pages are used as:
RAM Page 0 - Main RAM at C000h-FFFFh
RAM Page 2 - Main RAM at 8000h-BFFFh

RAM Page 5 - Main RAM at 4000h-7FFFh (with first VRAM block and system area)
RAM Page 7 - Second VRAM block and Editor variables
RAM Page 1,3,4,6 - RAM Disk
Upon Reset, ROM0 is mapped.
Expansion ROM/RAM
On Spectrum machines, the 16K ROM at 0000h-3FFFh (or smaller portions of it)
can be externally disabled by dragging the /ROMCS pin HIGH, allowing to replace
that region by external ROM and/or RAM. (Eg. Interface 1 ROM or Interface 2
ROM, or Interface 2 Cartridge ROM) (also external disk drives usually contain
both ROM and RAM).
Timex machines don't have external /ROMCS pin, instead, the memory mapping is
handled via the internal Port F4h and FFh registers. And, Timex machines can
map external memory anywhere at 0000h..FFFFh (rather than at 0000h-3FFFh only).
Spectrum System Variables
------------------------Spectrum RAM Map
4000h VRAM Bitmap
(256x192 pixels)
5800h VRAM Attributes (32x24 characters)
5B00h System Area
5CB6h Memory (starting with CHANS)
Memory
CHANS
channels
(usually at 5CB6h)
PROG
basic program (usually at 5CCBh)
VARS
basic variables
E_LINE
input buffer
WORKSP
temporary work space
STKBOT
bottom of calculator stack (same as WORKSP when empty)
STKEND
start of spare space (same as STKBOT when empty)
RAMTOP
CPU stacktop+1 (usually FF57h)
UDG
User-defined graphics (charset) (usually FF58h)
P_RAMT
physical RAM top (FFFFh for 48K RAM, or 7FFFh for 16K RAM)
Variants
Expansion hardware like Interface 1 and Beta Disk may allocate memory between
5CB6h and CHANS. Other hardware like Currah uSpeech may allocate memory between
RAMTOP and UDG.
TS2068 Memory Map
0000h..3FFFh
BIOS ROM
4000h..57FFh
VRAM Bitmap (1800h bytes)
5800h..5AFFh
VRAM Attr (300h bytes)
5B00h..5BFFh
Printer Buffer
5C00h..5FFFh
System Variables
Next, for 1 Display File:
6000h..61FFh
Machine Stack (200h bytes)
6200h..683Fh
OS RAM-Resident Code
6840h..ARSBUF (Machine Code Variables)
ARSBUF
CHANS
PROG
VARS
E_LINE
WORK_SP
STKBOT
STKEND
RAMTOP..P_RAMT UDG (user defined graphics)
Or, for 2 Display Files:
6000h..77FFh
VRAM Bitmap 2 (1800h bytes)
7800h..7AFFh
VRAM Attr 2 (300h bytes)
7B00h..ARSBUF (Machine Code Variables)
ARSBUF..RAMTOP (as above)
RAMTOP..F7BFh UDG (user defined graphics)
F7C0h..F9BFh
Machine Stack (200h bytes)
F9C0h..P_RAMT OS RAM-Resident Code
Spectrum System Area (parts accessed via IY=5C3Ah)
5B00h 256 PRBUFF LPRINT Buffer (32x8 pixel bitmap)
(On Spectrum 128/+2/+2A/+3, PRBUFF is used
as Extended System Area, see below)
5C00h 8
KSTATE Used in reading the keyboard.
5C08h 1
LASTK
Stores newly pressed key.
5C09h 1
REPDEL Time (in 50ths of a second) that a key
must be held down before it
repeats. This starts off at 35, but
you can POKE in other values.
5C0Ah 1
REPPER Delay (in 50ths of a second) between
successive repeats of a key held down - initially 5.
5C0Bh 2
DEFADD Address of arguments of user defined

5C0Dh l
5C0Eh 2
5C10h 38

K_DATA
TVDATA
STRMS

5C36h 2

CHARS

5C38h 1
5C39h 1
5C3Ah 1

RASP
PIP
ERRNR

5C3Bh
5C3Ch
5C3Dh
5C3Fh
5C41h
5C42h
5C44h

1
1
2
2
1
2
1

FLAGS
TVFLAG
ERRSP
LISTSP
MODE
NEWPPC
NSPPC

5C45h 2
5C47h 1
5C48h 1

PPC
SUBPPC
BORDCR

5C49h
5C4Bh
5C4Dh
5C4Fh
5C51h
5C53h
5C55h
5C57h
5C59h
5C5Bh
5C5Dh

2
2
2
2
2
2
2
2
2
2
2

E_PPC
VARS
DEST
CHANS
CURCHL
PROG
NXTLIN
DATADD
E_LINE
K_CUR
CH_ADD

5C5Fh
5C61h
5C63h
5C65h
5C67h
5C68h

2
2
2
2
1
2

X_PTR
WORKSP
STKBOT
STKEND
BREG
MEM

5C6Ah 1
5C6Bh 1

FLAGS2
DF_SZ

5C6Ch
5C6Eh
5C70h
5C71h
5C72h
5C74h
5C76h
5C78h
5C7Bh
5C7Dh
5C7Fh
5C80h

2
2
1
1
2
2
2
3
2
2
1
2

S_TOP
OLDPPC
OSPPC
FLAGX
STRLEN
T_ADDR
SEED
FRAMES
UDG
COORDS
P_POSN
PRCC

5C82h 2

ECHO_E

5C84h
5C86h
5C88h
5C89h
5C8Ah
5C8Ch

2
2
1
1
2
1

DF_CC
DF_CCL
S_POSN

5C8Dh 1

ATTR_P

SPOSNL
SCR_CT

function (if one is being evaluated), otherwise 0.


Stores 2nd byte of colour controls entered from keyboard.
Stores bytes of colour, AT and TAB controls going to TV.
Addresses of channels attached to streams.
(16bit pointers for Stream FDh..FFh, and 00..0Fh)
256 less than address of character set
(which starts with space and carries
on to (C)). Normally in ROM, but you
can set up your down in RAM and make
CHARS point to it.
Length of warning buzz.
Length of keyboard click.
1 less than the report code. Starts
off at 255 (for -1) so 'PEEK 23610' gives 255.
Various flags to control the BASIC system.
Flags associated with the TV.
Address of item on machine stack to be used as error return
Address of return address from automatic listing.
Specifies 'K', 'L', 'C', 'E' or 'G' cursor.
Line to be jumped to.
Statement number in line to be jumped to. Poking first
NEWPPC and then NSPPC forces a jump to a specified
statement in a line.
Line number of statement currently being executed.
Number within line of statement currently being executed.
Border colour multiplied by 8; also
contains the attributes normally used
for the lower half of the screen.
Number of current line (with program cursor).
Address of variables. (End of BASIC Program)
Address of variable in assignment.
Address of channel data (usually 5CB6h)
Address of current I/O channel (CHANS+n)
Address of BASIC program. (End of CHANS)
Address of next line in program. (PROG+n, or 0000h=None)
Address of terminator of last DATA item. (initially PROG-1)
Address of input buffer (aka line editor) (End of VARS)
Address of cursor in input buffer (E_LINE+n)
Address of the next character to be interpreted
(the character after the argument of PEEK,
or the NEWLINE at the end of a POKE statement)
Address of the character after the [] marker. (or 00D7h?)
Address of temporary work space.
Address of bottom of calculator stack.
Address of start of spare space.
Calculator's B register.
Address of area used for calculator's memory
(usually MEMBOT, but not always).
More flags. (Bit3 set when CAPS SHIFT or CAPS LOCK is on.)
Number of lines in lower part of screen (including one
blank line)
The number of the top program line in automatic listings.
Line number to which CONTINUE jumps.
Number within line of statement to which CONTINUE jumps.
Various flags.
Length of string type destination in assignment.
Address of next item in syntax table.
The seed for RND. This is set by RANDOMIZE.
Frame counter incremented at 50Hz (or 60Hz) (24bit)
Address of first user-defined graphic (usually FF58h)
X,Y coordinates of last point plotted.
33-column number of printer position.
Address of Current Column in PRBUFF (5B00h..5B1Fh)
[Not used in 128K mode or when certain peripherals
are attached]
33-column number and 24-line number
(in lower half) of end of input buffer.
Address in display file of PRINT position.
Like DF_CC for lower part of screen.
33-column number for PRINT position.
24-line number for PRINT position.
Like S_POSN for lower part.
Counts scrolls - it is always 1 more
than the number of scrolls that will
be done before stopping with
'scroll?'. If you keep poking this
with a number bigger than 1 (say 255),
the screen will scroll on and on
without asking you.
Permanent current colours, etc., (as

5C8Eh 1

MASK_P

5C8Fh 1

ATTR_T

5C90h 1
5C91h 1
5C92h 30

MASK_T
P_FLAG
MEMBOT

5CB0h 2

NMIADD

5CB2h 2
5CB4h 2

RAMTOP
P_RAMT

set up by colour statements).


Used for transparent colours, etc. Any
bit that is 1 shows that the
corresponding attribute bit is taken
not from ATTR_P, but from what is
already on the screen.
Temporary current colours, etc., (as
set up by colour items).
Like MASK_P, but temporary.
More flags.
Calculator's memory area - used to
store numbers that cannot conveniently
be put on the calculator stack.
Holds the address of the users NMI service routine.
NOTE - On previous machines, this did
not work correctly and these two bytes
were documented as 'Not used.'
Programs that used these two bytes for
passing values may need to be
modified.
Address of last byte of BASIC system area.(usually FF57h)
Address of last byte of physical RAM.
(usually FFFFh)

Timex 2068 - Extended System Area


5CB6h 2
ERRLN
Line number to GOTO on error
5CB8h 2
ERRLN
Line number in which error occurred
5CBAh 1
ERRS
Statement number within line in which error occurred
5CBBh 1
ERRT
Error number (Report Code)
5CBCh 2
SYSCON Pointer to System Configuration Table
5CBEh 1
MAXBNK Number of Expansion Banks in System
5CBFh 1
CURCBN Current Channel Bank Number
5CC0h 2
MSTBOT Address of location above machine stack
5CC2h 1
VIDMOD Video Mode (non-zero if 2nd display file is used)
5CC3h 1
<undocumented/unused byte> ?
5CC4h 7
"Various variables used for BASIC cartridges" ...details?
5CCBh 1
STRMNM Current Stream number
5CCCh 334h Not used (except, some stuff at 5EF3h..5EF6h is used?)
Spectrum 128/+2/+2A/+3 - Extended System Area (formerly Printer buffer)
Addr Siz Name
Expl.
Below is for Spectrum 128/+2:
5B00h 20 SWAP
Paging subroutine.
5B14h 9
YOUNGER Paging subroutine.
5B1Dh 18 ONERR
Paging subroutine.
5B2Fh 5
PIN
5B34h 22 POUT
5B4Ah 14 POUT2
Below is for Spectrum +3:
5B00h 16 SWAP
Paging subroutine.
5B10h 17 STOO
Paging subroutine. Entered with IRQs disabled, AF,BC pushed
5B21h 9
YOUNGER Paging subroutine.
5B2Ah 16 REGNUOY Paging subroutine.
5B3Ah 24 ONERR
Paging subroutine.
5B52h 2
OLDHL
Temporary register store while switching ROMs.
5B54h 2
OLDBC
Temporary register store while switching ROMs.
5B56h 2
OLDAF
Temporary register store while switching ROMs.
Below is for both Spectrum 128 and +3:
5B58h 2
TARGET Subroutine address in ROM 3.
5B5Ah 2
RETADDR Return address in ROM 1.
5B5Ch 1
BANKM
Copy of last byte output to I/O port 7FFDh.
5B5Dh 1
RAMRST RST 8 instruction. Used by ROM 1 to
report old errors to ROM 3.
5B5Eh 1
RAMERR Error number passed from ROM 1 to ROM
3. Also used by SAVE/LOAD as temporary drive store.
5B5Fh 2
BAUD
RS232 bit period in T states/26. Set by FORMAT LINE.
5B61h 2
SERFL
Second-character-received-flag, and data.
5B63h 1
COL
Current column from 1 to width.
5B64h 1
WIDTH
Paper column width. Defaults to 80. (on +3 at least)
5B65h 1
TVPARS Number of inline parameters expected by RS232.
5B66h 1
FLAGS3 Various flags. Bits 0, 1, 6 and 7
unlikely to be useful. Bit 2 is set
when tokens are to be expanded on
printing. Bit 3 is set if print output
is RS232. The default (at reset) is
Centronics (on +3) and whatever? (on 128/+2).
Bit 4 is set if a disk
interface is present. Bit 5 is set if
drive B: is present.
Below is for Spectrum 128/+2:
5B67h 10 NSTR1

5B71h
5B72h
5B74h
5B76h
5B78h
5B7Ah
5B7Bh
5B7Dh
5B7Fh
5B81h
5B83h
5B85h
5B88h
5B89h
5B8Ah
5B8Bh
5B8Dh
5B92h
5B94h
5B96h
5B98h
5BA0h
5BA8h
5BFFh
Below
5B67h
5B68h
5B69h
5B6Ah
5B6Ch
5B6Eh
5B73h
5B75h
5B77h
5B79h
5B7Ah
5B7Bh

5B7Ch
5B84h
5B8Ch
5BFFh

1
HD00
2
HD0B
2
HD0D
2
HD0F
2
HD11
1
SC00
2
SC08
2
SC0D
2
SC0F
2
OLDSP
2
SFNEXT
3
SPSPACE
1
ROW01
1
ROW23
1
ROW45
2
SYNRET
5
LASTV
2
RNLINE
2
RNFIRST
2
RNSTEP
8
STRIP1
8
STRIP2
87 TSTACK
1
N/A
is for Spectrum +3:
1
BANK678 Copy of last byte output to I/O port 1FFDh.
1
XLOC
Holds X location when using the unexpanded COPY command.
1
YLOC
Holds Y location when using the unexpanded COPY command.
2
OLDSP
Old SP (stack pointer) when TSTACK is in use.
2
SYNRET Return address for ONERR.
5
LASTV
Last value printed by calculator.
2
RCLINE Current line being renumbered.
2
RCSTART Starting line number for renumbering. The default is 10.
2
RCSTEP Incremental value for renumbering. The default is 10.
1
LODDRV Holds 'T' if LOAD, VERIFY, MERGE are
from tape, otherwise 'A', 'B' or 'M'.
1
SAVDRV Holds 'T' if SAVE is to tape, otherwise 'A', 'B' or 'M'.
1
DUMPLF Holds the number of 1/216ths inch used for
line feeds in 'COPY EXP'. This is
normally set to 9. If problems are
experienced fitting a dump onto a
sheet of A4 paper, POKE this
location with 8. This will reduce the
size of the dump and improve the
aspect ratio slightly.
8
STRIP1 Stripe one bitmap. ;\allowed to be destroyed by
8
STRIP2 Stripe two bitmap. ;/Temporary stack
115 TSTACK Temporary stack (when RAM7 is mapped to C000h-FFFFh)
1
N/A
Not used

In 48 BASIC mode, all the variables and routines below 5C00h (23552) do not
exist; instead there is a buffer between 5B00h (23296) and 5C00h (23552) which
is used for controlling the printer. This was quite a popular location for
small machine code programs on the old 48K Spectrum, and if any of these
routines are tried in +3 BASIC, the computer will invariably crash. Any old
program that uses PEEK, POKE and USR is therefore a safer bet if it is run in
48 BASIC mode (although it can be entered in +3 BASIC mode and transferred
using the SPECTRUM command). If there is a chance that a program might
inadvertently address the added I/O ports of the +3, then 'OUT 32765,48' will
set bit 5 in port 7FFDh to disable further use of the added ROM/RAM switching.
Spectrum ULA
-----------Port nnFEh - Sinclair ULA (R)
0-4 Keyboard Inputs (0=Pressed, 1=Released)
5
Not used
6
EAR Input (CAS LOAD)
7
Not used
A8..A15 Keyboard Address Output (0=Select)
Port FEh - Sinclair ULA (W)
0-2 Border Color
3
MIC Output (CAS SAVE)
4
Beep Output (ULA Sound)
5-7 Not used

(0..7) (always with Bright=off)


(0=On, 1=Off)
(0=Off, 1=On)

Port FFh (or other) (R) Spectrum Current VRAM Data (dirt effect)
Reading from an unused port (eg. Port FFh) does return the byte being most
recently read from VRAM via video DMA. During Vblank and Hblank, the return

value is always FFh. During the scanline drawing periods, the return value may
be FFh, or bitmap data, or attribute data (depending on when exactly the port
is read).
Some games are using this dirt effect to synchronize the program with the
cathode ray beam (eg. Arkanoid is using display timings to generate in-game
sound frequencies).
The method does NOT work on all computers: All Timex machines are using Port
FFh for something else, though the effect may still work with other unused
ports (if there are any unused ports). And, newer Spectrum machines (eg.
Spectrum +3) don't produce the effect at all.
Port FFh - Timex Video and Memory Control
0-2 Screen mode. 000=screen 0, 001=screen 1, 010=hi-colour, 110=hi-res
3-5 INK color in hi-res mode (INK=0..7) (with PAPER=INK XOR 7, BORDER=PAPER)
6
Disable Frame Interrupt (0=Normal, 1=Disable)
7
External memory mode (0=DOCK/Cartridge Slot, 1=EX-ROM/Expansion Port)
Screen 0 is the normal screen at 4000h. Screen 1 uses the same format but at
6000h.
Port F4h - Timex Memory Mapping
0 Memory at 0000h-1FFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=BIOS, EX-ROM=BASIC
1 Memory at 2000h-3FFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=BIOS
2 Memory at 4000h-5FFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=VRAM
3 Memory at 6000h-7FFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=VRAM
4 Memory at 8000h-9FFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=RAM
5 Memory at A000h-BFFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=RAM
6 Memory at C000h-DFFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=RAM
7 Memory at E000h-FFFFh (0=HOME, 1=DOCK or EX-ROM) ;HOME=RAM
The TC2048 has only 16K BIOS, the TS2068/TC2068 have an additional 8K BASIC
extension in the first EX-ROM bank. Whether DOCK (Cartridge) or EX-ROM
(Expansion) is mapped depends on Port FFh.Bit7.
Note: This register is often called "Horizontal Select Register", that name has
nothing to do with video resolution or coordinates, instead, the name is based
on treating the memory as a two-dimensional array (with y=16bit Z80 memory
address, and x=bank number).
Port 7FFDh - Spectrum 128K/+2/+2A/+3 Memory Bank Register (W) (and RAM 5B5Ch)
(initially 00h)
0-2 RAM Page to be mapped to C000h-FFFFh (0..7=Page 0..7)
3
RAM Page to be used as VRAM
(0=Page 5, 1=Page 7)
4
ROM Page (0=New "128K" ROM0, 1=Old "48K" ROM1)
5
Lock Port 7FFDh (0=Normal/No change, 1=Lock/Until Reset)
6-7 Not used
On +2A/+3:
RAM Pages 0..3 are "uncontended" (aka accessed solely by the Z80)
RAM Pages 4..7 are "contended" (aka accessed by both the Z80, and by the ULA)
On 128/+2:
RAM Pages 0,2,4,6 are "uncontended" (aka accessed solely by the Z80)
RAM Pages 1,3,5,7 are "contended" (aka accessed by both the Z80, and by ULA)
(ie. the ULA can access Page 5 or 7 as VRAM; although the ULA accesses only ONE
of that two pages at a time, and NEVER accesses Page 4 or 6, the whole Page
4..7 region is treated as "contended", meaning that the whole region suffers
under video waitstates).
Port 1FFDh - Spectrum +2A/+3 Memory (W) (and RAM 5B67h=R/W)
0
Paging mode (0=Normal; ROM and RAM, 1=Special; RAM only)
1-2 In special mode: RAM mapping mode (RAM only, for CP/M)
Mode 0000h..3FFFh 4000h..7FFFh
8000h..BFFFh C000h..FFFFh
0
Bank0
Bank1
Bank2
Bank3
1
Bank4
Bank5/Screen1 Bank6
Bank7/Screen2
2
Bank4
Bank5/Screen1 Bank6
Bank3
3
Bank4
Bank7/Screen2 Bank6
Bank3
1
In normal mode, ignored.
2
In normal mode, MSB of ROM selection (LSB is in Port 7FFDh.Bit4)
The four ROMs banks are (mapped to 0000h..3FFFh):
ROM 0: 128k editor, menu system and self-test program
ROM 1: 128k syntax checker
ROM 2: +3DOS
ROM 3: 48 BASIC
3
Disk motor; 1=on, 0=off
4
Printer port strobe.
5-7 Not used
RAM banks 1,3,4 and 6 are used for the disc cache and RAMdisc, while Bank
7 contains the second VRAM bank, editor scratchpads, and +3DOS workspace.
Spectrum VRAM
------------Bitmap Area (4000h..57FFh) (1800h bytes) (6K)
Bitmap Address

A0..A4
Horizontal Coordinate in 8-pixel steps (0..31)
A5..A7
Vertical Coordinate in 8-pixel steps (0..7) ;Vertical Charline
A8..A10 Vertical Coordinate in 1-pixel steps (0..7) ;Vertical Scanline
A11..A12 Vertical Coordinate in 64-pixel steps (0..2) ;Vertical Block
Bitmap Data
D0..D7
Pixels (0=Paper, 1=Ink) (D7=Left-most ... D0=Right-most)
Note: A0..A7 are arranged that a single /RAS signal can be used for reading
both Bitmap and Attribute via DMA. A8..A10 are arranged that an address in HL
can be vertically manipulated via INC H opcodes.
Attribute Area (5800h..5AFFh) (300h bytes) (0.75K)
Attribute Address
A0..A4
Horizontal Coordinate in 8-pixel steps (0..31)
A5..A9
Vertical Coordinate in 8-pixel steps (0..23)
Attribute Data
D0..D2
Ink
(0..7 = color used for "1" bits in bitmap data)
D3..D5
Paper (0..7 = color used for "0" bits in bitmap data)
D6
Bright (brightness for both Ink and Paper) (0=Dark, 1=Bright)
D7
Flash (0=Normal, 1=Blink; 16 frames normal, 16 frames inverted)
Note: The Screen Border color can be set via Port FEh (the border is always
having Bright=off). Except, the Timex hi-res mode sets the border equal to the
paper color (which is the inverse of the hi-res INK value in Port FFh, and
which is always having Bright=on, for both INK and PAPER/BORDER).
Color Palette (via TV Modulator or Composite Video)
Below table shows the normal TV palette (as seen on Spectrum 48K Issue 2).
Whereas, "r,g,b" = basic Red/Green/Blue intenstity on color display, "i" =
basic intensity on monochrome display, "R,G,B,I" = additional intensity when
the Bright bit is set.
0 Black
............... ............... ............... .......
1 Blue
g.............. r.............. bbbbbbbbB...... i......
2 Red
gg............. rrrrrrrrRR..... bb............. ii.....
3 Magenta ggG............ rrrrrrrrrRR.... bbbbbbbbbBB.... iiI....
4 Green
gggggggggGGG... rrrR........... bbbB........... iiiI...
5 Cyan
ggggggggggGGG.. rrrrR.......... bbbbbbbbbbBBB.. iiiiI..
6 Yellow ggggggggggGGGG. rrrrrrrrrrRRRR. bbbbBB......... iiiiII.
7 White
gggggggggggGGGG rrrrrrrrrrrRRRR bbbbbbbbbbbBBBB iiiiiII
On a color display, there would be theoretically 16 colors possible, however,
Dark Black is exactly same as Bright Black, so there are only 15 different
colors (also, Dark Blue isn't much different than Bright Blue). Note: If the
color isn't 100% properly adjusted via VR1 and VR2 on the mainboard, then
White/Gray tend to appear a bit yellowish.
On a monochrome display, only the eight Bright colors are relevant, and the
Dark colors are just duplicating some bright colors (for example, Dark Blue is
almost same as Bright Blue, and Dark Cyan or Dark Yellow are almost same as
Bright Green).
Palette on CGA Monitors (via TTL output on TS2068/TC2068 or Spectrum 128)
TS2068 outputs only R,G,B (but NOT intensity, ie. bright is ignored)
TC2068 and Spectrum 128 do output R,G,B,I
(with intensity)
CGA shows intensity=1 as FULL intensity
(unlike darker blue/red on TV)
CGA shows intensity=0 as HALF intensity or so (unlike 80% of bright on TV)
CGA shows dark-yellow as brown
(unlike Dark-Yellow on TV)
CGA shows bright-black as dark-gray
(unlike Black on TV)
The bright-black effect may be fixed by masking I when R,G,B are all zero.
Palette on TVs with RGB input (via Analogue output on Spectrum +2A/+3)
Spectrum +2A/+3 have a RGB output with analog levels, which can be wired to
21pin Scart connectors (most TVs with Scart sockets support only Composite A/V,
but not RGB though), and which may (or may not?) produce same colors as the
standard TV output.
Second Screen
Spectrums with 128K RAM (Spectrum 128/+2/+2A/+3) can use two frame buffers, the
normal one at 4000h..5AFFh, and the second one in RAM Page 7; which can be
mapped to CPU addresses C000h..DAFFh (see Port 7FFDh).
All Timex machines (TC2048/TC2068/TS2068) can use two frame buffers, too. The
normal one at 4000h..5AFFh, and the second one at 6000h..7AFFh (see Port FFh).
Timex Hi-Color (Timex only, not supported on any Spectrums)
In this mode, the 32x24 attributes (per 8x8 pixels) at 5800h..5AFFh are unused,
and instead 32x192 attributes are read from 6000h..77FFh (per 8x1 pixels). The
Attribute Data is same as in Standard mode, but the Attribute Address bits are
arranged in the same way as the Bitmap address.
Timex Mono Hi-Res (Timex only, not supported on any Spectrums)
In this mode, the horizontal resolution is doubled, ie. instead of reading 1
bitmap and 1 attribute byte, it reads 2 bitmap bytes. The colors (for the whole
screen) can be set via Port FFh. The bitmap data is located at 4000h..57FFh and
6000h..77FFh. The data is horizontally interlaced, each 8 pixels at 4000h,

6000h, 4001h, 6001h, and so on, the vertical addresses are same as in the other
modes.
Spectrum Video Connectors
------------------------Spectrum 128 - RGB Connector
1 Composite PAL (75 Ohms, 1.2 Volts pk-pk)
.. ..
2 GND
(0 Volts DC)
/ '-' \
3 Bright output (TTL)
. 7
6 .
4 Composite sync (TTL)
| 3 8 1 |
5 Vertical sync (TTL)
' 5
4 '
6 Green
(TTL)
\
2
/
7 Red
(TTL)
'---'
8 Blue
(TTL)
128K Composite Video Output:
Pin 1 is composite PAL, 2 is GND. The picture is a bit dull unless your TV's
video input is High Z (high impedance) However, that's quite unlikely. Normally
the impedance of the video input is around 75 Ohms. To alleviate this problem,
short the 68 Ohms resistor inside the Speccy that's in series with pin 1
(follow the track on the PCB). Or you can hook it directly to the input of the
RF modulator.
There's no audio on any pin of the RGB connector. The audio can be taken from
the MIC socket but a better balance between 48K and 128K sound is obtained
directly from pin 5 of IC38.
Spectrum +2A/+3 - RGB Connector
1 +12V
2 GND (0V)
3 Audio Out
4 /Composite Sync (TTL)
5 +12V
6 Green (Analogue 1.67V p-p)
7 Red
(Analogue 1.67V p-p)
8 Blue (Analogue 1.67V p-p)

.. ..
'-' \
. 7
6 .
| 3 8 1 |
' 5
4 '
\
2
/
'---'
/

TS2068: If the RGB output is used, BRIGHT is ignored.


Spectrum Timings
---------------Maker
Version
CPU Osc
Color Osc
CPU Clock
PSG Clock
HorizontalTotal
HorizontalDraw
HorizontalBlank
Vertical Total
Screen
Upper Border
Lower Border
Frame Rate
Flash Rate
First Delay at
Delay Pattern
Port FEh Delay
VRAM Delay at
Snow Effect

Spectrum
16K/48K/+
14.000MHz
4.4336MHz
3.500000MHz
N/A
224 clks
128 clks
96 clks
312 lines
192 lines
64 lines
56 lines
50.08Hz/PAL
50/32=1.6Hz
14335 clks
6..1,0,0
Yes
4000h-7FFFh
Yes

Spectrum
128/+2
17.73447MHz
CPU Osc/4
3.54690MHz
1.7734MHz
228 clks
128 clks
100 clks
311 lines
192 lines
63 lines
56 lines
50.01Hz/PAL
50/32=1.6Hz
?
?
Yes
RAM1,3,5,7
Yes/Crash

Spectrum
+2A/+3
?
CPU Osc/n
3.54690MHz
1.7734MHz
228 clks
128 clks
100 clks
?
192 lines
?
?
50.?Hz/PAL
50/32=1.6Hz
14361 clks
1,0,7..2
No
RAM4,5,6,7
?

Timex
TC2048/2068
?
?
3.50000MHz
? (if any)
?
128 clks
?
?
192 lines
?
?
50.?Hz/PAL
50/32=1.6Hz
?
?
Yes
4000h-7FFFh
No?

Timex
TS2068
14.112MHz
3.579545MHz
3.52800MHz
1.764(75)?
224 clks
128 clks
?
262 lines
192 lines
?
?
60.11Hz/NTSC
60/32=1.9Hz
?
?
Yes
4000h-7FFFh
Yes/No?

Some Clones
The russian Scorpion seems to have same timings as Spectrum 48K. The russian
Pentagon has 320 lines total (64+192+48+16), and, it generates INT at begin of
its 16-lines Vsync period (all other computers have INT at end of Vsync, aka
begin of upper border). Horizontal total is 224 clks on both Pentagon and
Scorpion, but hsync position is slightly different on each. Both Scorpion and
Pentagon do not have slow (contended) memory.
VRAM Waitstates (aka "contended memory" waitstates)
Within each 8 cycles, the ULA reads 2 bitmap bytes and 2 attribute bytes via
video DMA (which takes up 4 clks), followed by 4 cycles where bus is free for
the CPU. Although there are 4 free cycles, the ULA allows the CPU to invoke a
RAM access (or a Port FEh access) only during 2 of that 4 cycles:
UUUUUUccUUUUUUccUUUUUUcc..
;<--- U=Blocked by ULA, c=Free for CPU access
654321006543210065432100..
;<--- Number of waitstates (0=none)
For whatever reason, the access pattern is different on the +2A/+3:
UcUUUUUUUcUUUUUUUcUUUUUU..
;<--- U=Blocked by ULA, c=Free for CPU access
107654321076543210765432..
;<--- Number of waitstates (0=none)

Waitstates occur only during drawing, ie. not during Vblank and Hblank. The
first ULA access appears 14335 (or 14361) cycles after the Vsync IRQ (or
unknown number of cycles on NTSC and others). The above access pattern is then
repeated throughout the 128 cycles drawing time, and pauses throughout the 96
(or 100) cycles hblank time.
Although a screen with attributes consists of only 6.75Kbytes, the waitstates
apply on any access to memory chips that are connected to the ULA (ie. the
whole 16K at 4000h..7FFFh) (or one half of RAM on 128K machines, either in
banks 1,3,5,7 on Spectrum 128/+2, or in banks 4,5,6,7 on Spectrum +2A/+3).
Other portions of RAM (and ROM) can be accessed without waitstates.
Details on VRAM-DMA Access Timings
As said above, within each 8 cycles, the ULA reads 2 bitmap bytes and 2
attribute bytes, the LSBs of the bitmap address are the same as of the
attribute address, so two bytes (1x bitmap, and 1x attr) can be fetched with a
single long /RAS signal (1.5 clks low) and two short /CAS signals (0.5 clks
low):
|-----8 clks----||-----8 clks----|-----H/V-Blank...-----/RAS (RAM.Pin4) -___-___---------___-___-------------------------------/CAS (RAM.Pin15) -_-_-_-_---------_-_-_-_-------------------------------During drawing, the ULA outputs all /RAS addresses in range 00h..7Fh (though
not in linear order) to the memory, so the above /RAS signals do also serve as
refresh signals.
Details on CPU Access Timings
CPU memory accesses are slower than video DMA (the CPU outputs /CAS and /RAS
low for 1.5 clks, while DMA uses only 0.5 clks for /CAS). Normally, the CPU
does also output a "dummy" /RAS for refresh (1.0 clks low), so a stream of NOP
opcodes would look like so:
|-----8 clks----||-----8 clks----|
/RAS (RAM.Pin4) -___-__--___-__--___-__--___-__;four NOP opcodes
/CAS (RAM.Pin15) -___-----___-----___-----___---When accessing "contended" memory, the ULA takes care of refresh, so the CPU's
refresh signal can be suppressed, and a stream of NOP opcodes would look like
so (assuming that no VRAM-DMA is taking place, eg. during Hblank):
|-----8 clks----||-----8 clks----|
/RAS (RAM.Pin4) -___-----___-----___-----___---;four NOP opcodes
/CAS (RAM.Pin15) -___-----___-----___-----___---Scanline Effects
The Spectrum doesn't have a Scanline interrupt, so changing video attributes in
specfic scanlines (for using more than 2 colors per 8x8 pixels), or changing
the horizontal resolution in a given scanline (on Timex machines) can be
implemented only by waiting so-and-so-many clock cycles after the Vsync
interrupt has occurred. That method wastes a lot of CPU load, and its difficult
to get it compatible with all computers (due to different horizontal and
vertical timings, and different waitstates).
Another approach would be reading from Port FFh (or other unused ports), and to
wait until contains a specific color attribute, that method is more flexible
than hardcoded delays, but, it doesn't work on all computers (see Port FFh info
in ULA chapter for details).
Refresh and Snow
The Z80 CPU generates refresh signals used for the non-contended RAM only.
The contended VRAM uses a different refresh signal generated from the ULA.
Although contended VRAM doesn't use CPU refresh signal, the ULA can get
"confused" when the CPU refresh occurs with the address bus containing a
contended memory address (ie. when the IR register pair points to 4000h..7FFFh;
aka when the I register is 40h..7Fh), in that case the ULA thinks that the CPU
wants to access memory, causing the ULA not to load new data from VRAM (and to
re-use old data), which results in "snow" on the screen. On Spectrum 128K/+2,
the snow effect does exist, but it does reportedly "crash the machine shortly
after I is set to point to contended memory".
Hmmm.......... assuming that the effect doesn't just block VRAM reads, but also
VRAM refresh.... then it actually CRASH programs (and BIOS code) that have
code/data located in the "contended" memory regions.... eg. the 16K spectrum
has ONLY contended memory, so the program would survive on a few seconds or
so.... the reported crash on 128K/+2 might have the same reason (but could be
simply avoided by using only uncontended memory)...?
Spectrum Sound
-------------Standard ULA Beeper
--> Spectrum Sound ULA
--> Spectrum Sound Speaker/Amplifier/Modulator
Programmable Sound Generator
The 3-channel PSG is used in the Spectrum 128/+2/+2A/+3 (and occassionally
supported by newer games).

--> Spectrum Sound PSG (Programmable Sound Generator)


The same PSG chip is also used in Timex TS2068/TC2068 computers and in various
expansion boxes (but at different I/O addresses, and rarely supported by any
games).
Speech Hardware
--> Spectrum Sound
--> Spectrum Sound
--> Spectrum Sound
--> Spectrum Sound
--> Spectrum Sound
--> Spectrum Sound

Speech
Speech
Speech
Speech
Speech
Speech

Overview
I/O Ports
SP0256 Voice Generator
SP0256 Instruction Set
SP0256 Allophones/Words
SP0256 Pin-Outs

Digital Sound (Playback/Recording)


--> Spectrum Sound Digital Playback/Sampling
MIDI Interfaces
Cheetah MIDI Interface (Cheetah)
EMR MIDI Interface (Electro Music Research)
MIDISYNC (Icon Design Ltd.)
MIDI Sync Boxes (XRI Systems)
Siel MIDI Interface (Siel UK Ltd)
Upstream MIDI Interface (Upstream Computer Systems Ltd)
XRI Micon MIDI Interface (XRI Systems)
ZX Spectrum 128 +2 to MIDI Lead (Cheetah)
Music Machine (see Digial Sound chapter for details)
Spectrum Sound ULA
-----------------Sound Frequency vs Video Waitstates
Observe that video waitstates occur when drawing the bitmap area (but not
during Hblank and Vblank), so the presence/absence of waitstates can have some
nasty effects on software generated sound frequencies.
Basically, do not use code/data in RAM at 4000h..7FFFh when generating sounds.
Waitstates do also occur on accessing Port FEh, which may become a problem with
high-frequency PWM sounds, a workaround would be to access Port FEh only within
multiples of 8 clock cycles (so it runs in sync with video DMA).
Aside from waitstates, it may be also good to disable IRQs to prevent the sound
to get paused during IRQ handling (or at least to use a custom fast IRQ
handler).
Sound Volume via Bit3 (not recommended / unstable results)
The ULA has two separate control bits for Sound and Cassette output:
Port FEh.Bit4 = Audio Output
(0 = 0.3 Volts, 1 = 3.7 Volts)
Port FEh.Bit3 = Cassette Output (0 = 0.3 Volts, 1 = 0.7 Volts)
However, it does output both signals on the same pin.
Port FEh = 18h --> 3.7V
Port FEh = 10h --> 3.6V
Port FEh = 08h --> 0.7V
Port FEh = 00h --> 0.3V
Below are examples for a Spectrum 48K with Issue 2 mainboard; one column shows
results for the internal speaker, the other column shows results for the MIC
output passed to an external amplifier (eg. to the Audio Input of a TV set).
Furthermore, results may differ on other mainboards (after issue 2, Sinclair
seem to have added a transistor as internal amplifier).
Toggle between
Internal Speaker
External Amplifier
00h and 10h
Volume = #####
Volume = #####
;normal
00h and 08h
Volume = .....
Volume = ##...
;unpredictable
10h and 18h
Volume = ##...
Volume = #....
;unpredictable
Normally, sound should be generated by toggling bit4 of Port FEh. As shown
above, messing with bit3 has rather unpredictable results; toggling between 00h
and 08h has a good voltage difference which is audible on external amplifiers,
but not enough amperes to drive the internal speaker; for toggling between 10h
and 18h it's vice versa, the voltage difference is smaller, but there are more
amperes (it becomes audible on internal speaker, but the volume drops with
external amplifier).
Spectrum Sound Speaker/Amplifier/Modulator
-----------------------------------------Internal Speaker (Spectrum 16K/48K/Plus and Timex TS/TC20xx)
Older Spectrums with 16K/48K RAM are containing an internal speaker, used to
output the ULA sound (and PSG sound in case of the Timex 2068). The dimensions
(and volume) of the internal speaker would be more suitable for headphones. The
TV modulator generates a raw video signal (so the TV speaker is not used).
Internal Audio UHF Modulator (Spectrum 128/+2/+2A/+3)
Newer Spectrums with 128K RAM don't include an internal speaker, instead, the
ULA sound (and PSG sound) is passed to the TV set via the UHF modulator.

External Speakers/Amplifiers and Modulators


To "boost" the volume, several companies offered external amplifiers with
bigger external speakers. Most external PSG/Speech devices do also mix and
amplify the ULA sound with the PSG/Speech sound.
For using the TV speakers, several companies have offered internal and external
UHF modulators which mixed the audio signal with the video signal (for modern
TVs with A/V inputs sets it'd be easier/cheaper to pass MIC/VID to A/V input of
the TV set, which'd also give better picture quality than UHF).
External Sound Connectors
In general, sound can be obtained from the MIC port (or anywhere from the
mainboard). The Timex TS2068 does also output PSG/ULA on the expansion port.
The Spectrum expansion Port doesn't have a sound output (however, external
hardware could easily reconstruct ULA sound by latching D4 upon /IORQULA and
/WR). The analogue RGB output on the Spectrum +2A/+3 does also include an audio
pin (unlike the TTL RGB output on the Spectrum 128).
Mono/Stereo Sound
The standard spectrum hardware supports only mono sound output. Some of the
external PSG devices allow to produce stereo sounds by passing one PSG channel
to left, one to right, and the third channel to both left and right speakers;
but, external PSG devices are rarely supported by any games, and there's no
real standard which channel is passed to which speaker.
Spectrum Sound PSG (Programmable Sound Generator)
------------------------------------------------I/O Ports of known PSG devices
Model
Spectrum 128/+2/+2A/+3
Didaktik Melodik (spectrum 128 style)
Timex TS2068 (NTSC)
Timex TC2068 (PAL)
Fuller Box
Fuller Box Master Unit (with Orator)
DK'Tronics 3 Channel Sound Synthesiser
Timedata ZXM Soundbox (ZX81)
Timedata ZXM Soundbox (Spectrum)
William Stuart Systems Music Synthesiser
Bi-Pak ZON X81 Soundbox (ZX81)
Bi-Pak ZON X Soundbox (Spectrum)
Ricoll RISG Sound Generator
Ricoll RIFG Sound Generator with filters
Petron Trichord (includes PROM)
Signpoint Sound Synthesiser Plus
Datel 3 Channel Sound Synthesiser
Investronica INAXEL Sound & Joystick

Index.W
FFFDh
FFFDh
xxF5h
xxF5h
xx3Fh
xx3Fh
xx3Fh
xx9Fh
xx9Fh
xx9Fh
xxDFh
xxFFh
?
?
?
?
?
?

Data.W
BFFDh
BFFDh
xxF6h
xxF6h
xx5Fh
xx5Fh
xx5Fh
xxDFh
xxDFh
xxDFh
xx0Fh
xx7Fh
?
?
?
?
?
?

Data.R
FFFDh
FFFDh
xxF6h
xxF6h
xx3Fh
xx3Fh
?
xxBFh
xxBFh
?
N/A?
N/A
?
?
?
?
?
?

Chip
8912
891x
8912
8912
8912
8912
8912
8912
8912
891x
891x
8912
8910
8910
8910
8910
?
?

Year
1985
19xx
1983
1984
1983
1983
1984
198x
198x
1983
198x
1982
1983
1983
1983
1984
1989
?

Clock Frequency
The "3.5xxMHz/32" in the formulas are meant to be the CPU clock divided by 32
(externally divided by 2 on the mainboard, and internally divided by 16 inside
of the PSG). The CPU clock for different models is:
Model
CPU Clock Divide by
Spectrum 128/+2/+2A/+3
3.54690MHz / 32
Timex TC2068 (PAL)
3.50000MHz / 32
Timex TS2068 (NTSC)
3.52800MHz / 32
For Spectrum 16K/48K/Plus and Timex TC2048, external PSGs are available, but in
most cases the clock and divider is unknown (the CPU clock on the expansion
port gets stopped on VRAM waitstates, so it isn't suitable for sound, and the
expansion hardware requires to include its own oscillator):
ZON X81 Soundbox (ZX81)
3.25MHz
/ 32
ZON X Soundbox (Spectrum) 3.5MHz
/ ?
Other Models...
? MHz
/ ?
Timedata ZXM Soundbox (ZX81)
approx 100000 Hz (probably means 3.25/32)
Timedata ZXM Soundbox (Spectrum) approx 100000 Hz (probably means 3.xx/32)
00h
01h
02h
03h
04h
05h
The
F

= Tone Frequency channel A, low (0-255)


= Tone Frequency channel A, high (0-15)
= Tone Frequency channel B, low (0-255)
= Tone Frequency channel B, high (0-15)
= Tone Frequency channel C, low (0-255)
= Tone Frequency channel C, high (0-15)
actual listened frequency in Hertz is calculated as follows:
= 3.5xxMHz / 32 / nn
;with nn in range 1..4095 (nn=0 acts as nn=1)

06h = Noise Frequency (0-31)


The actual noise frequency in Hertz is calculated as follows:
F = 3.5xxMHz / 32 / nn
;with nn in range 1..31 (nn=0 acts as nn=1)
Noise can be output on all 3 channels, but there is only one noise generator

(so all channels share the same noise frequency). The noise generator consists
of 17bit shift register, and a 1bit noise level (0=LOW or 1=HIGH). These are
updated at the selected frequency as follows:
noise_level = noise_level XOR shiftreg.bit0
newbit = shiftreg.bit0 XOR shiftreg.bit3
shiftreg = (shiftreg SHR 1) + (newbit SHL 16)
Note that level isn't set equal to bit0, instead, it toggles when bit0=1.
07h = Mixer Control
Bit Expl.
0
Channel A tone enable
(0=Enable, 1=Disable)
1
Channel B tone enable
(0=Enable, 1=Disable)
2
Channel C tone enable
(0=Enable, 1=Disable)
3
Channel A noise enable
(0=Enable, 1=Disable)
4
Channel B noise enable
(0=Enable, 1=Disable)
5
Channel C noise enable
(0=Enable, 1=Disable)
6
I/O port A mode
(0=Input, 1=Output)
7
I/O port B mode
(0=Input, 1=Output)
If both Tone and Noise are disabled on a channel, then a constant HIGH level is
output (useful for digitized speech). If both Tone and Noise are enabled on the
same channel, then the signals are ANDed (the signals aren't ADDed) (ie. HIGH
is output only if both are HIGH).
08h = Volume channel A (0-15, 16=Envelope)
09h = Volume channel B (0-15, 16=Envelope)
0Ah = Volume channel C (0-15, 16=Envelope)
Defines the volume, 0=off, 15=max. If bit4=1, then the volume is taken from the
envelope generator. The volume is non-linear:
amplitude = max / sqrt(2)^(15-nn)
;(according to datasheet)
eg. 15 --> max/1, 14 --> max/1.414, 13 --> max/2, etc.
The volume affects only HIGH levels. LOW levels are always NULL. Ie. sound
output toggles between +VOL and NULL (not between +VOL and -VOL).
Digitized samples can be written to the volume registers (mind that volume is
non-linear). When doing that, it's best to switch the channel to constant HIGH
level (by disabling both Tone and Noise). Another method would be to set tone
frequency to 000h or 001h (the resulting frequency is too high to be audible,
so the HIGH/LOW levels sound like a constant HALF level).
0Bh = Volume Envelope Frequency, low (0-255)
0Ch = Volume Envelope Frequency, high (0-255)
Envelope step frequency (tone or noise) calculated as follows:
F = 3.5xxMHz / 32 / nn
;with nn in range 0..65535 (nn=0 acts as nn=1)
Depending on the envelope shape, the volume is incremented from 0 to 15, or
decremented from 15 to 0. In either case it takes 16 steps to complete, the
completion time for 16 steps is therefore:
T = nn*512 / 3.5xxMHz
;with nn in range 1..65535 (0 .. ca. 9.5 seconds)
0Dh = Volume Envelope shape (0-15)
Writing to this register (re-)starts the envelope. Additionally, the written
value specifies the envelope shape, the four bits have the following meaning:
CONT ATT ALT HLD
0
0
X
X \_________ 0-3 (same as 9)
0
1
X
X /_________ 4-7 (same as F)
1
0
0
0 \\\\\\\\\\ 8
(Repeating)
1
0
0
1 \_________ 9
1
0
1
0 \/\/\/\/\/ A
(Repeating)
1
0
1
1 \""""""""" B
1
1
0
0 ////////// C
(Repeating)
1
1
0
1 /""""""""" D
1
1
1
0 /\/\/\/\/\ E
(Repeating)
1
1
1
1 /_________ F
0Eh = I/O port A (with external pinouts on AY-3-8910 and AY-3-8912)
0Fh = I/O port B (with external pinouts on AY-3-8910 only)
These are two general purpose 8bit I/O ports (direction can be set via register
7). Port A exists on both AY-3-8910 and AY-3-8912 chips. Port B exists on
AY-3-8910 only (or actually, it does internally exist even on the smaller
AY-3-8912, but it doesn't have external pinouts).
Model
Port A
Port B
Timex TC2068 and TS2068 Joysticks (*)
N/A (uses 8912 chip)
Spectrum 128/+2/+2A/+3
RS232/Keypad
N/A (uses 8912 chip)
Fuller Box
?
N/A (uses 8912 chip)
DK'Tronics
Unused?
N/A (uses 8912 chip)
Timedata ZXM Soundbox
Joystick/User Port
N/A (uses 8912 chip)
Signpoint
ioport
ioport
Other expansions...?
?
?
(some do use 8910 chip)
(*) Timex also passes Bit5 of Port A to Expansion Port Pin 30 on upper side.
Spectrum 128/+2/+2A/+3 PSG Software
Some newer games (made after the Spectrum 128 was released in 1985) do support

its PSG hardware (eg. Cybernoid, Exolon, Into the Eagles Nest, Head Over
Heels), but many other newer games don't do so.
Fuller Box and DK'Tronics PSG Software (compatible with each other)
Fuller Box Demonstration Program (Fuller)
Sound Designer (DK'Tronics)
Invasion of the Body Snatchas
Aside from the Fuller Box and DK'Tronics demonstration tapes, there seems to be
almost no other software that supports these PSGs (even DK'Tronics didn't
support their own hardware in their own games).
William Stuart Systems Music Synthesiser Software
Composer (William Stuart Systems)
Timex 2068 Software
The TS2068 (USA) wasn't very popular, and the TC2068 (Portugal/Poland) was
mainly used with 'normal' european Spectrum 48K software - so there are
probably not too many (if any?) commercial games that support the PSG in Timex
computers.
Spectrum Sound Speech Overview
-----------------------------Known "General Instrument SP0256-AL2 Narrator" Speech devices
Currah MicroSpeech (1983) - uses SP0256-AL2 speech processor, output via TV
Fuller Orator - Speech Synthesis (1984) - uses G1-SP0256 AL voice chip
Fuller Box Master Unit (PSG and Orator)
Cheetah Sweet Talker (1983) (crude thing that HALTs the CPU during speech)
DK'Tronics Speech Synthesiser (1985) - uses the SLO/256 chip
The Currah MicroSpeech (aka Currah uSpeech) seems to be the most popular speech
device, possibly because of it's easy to use BIOS extension, although that
extension causes very serious compatibility problems with other software.
Other known Speech devices
Spirit Instruments - Spectrum Speech Synthesiser (1983)
SS1 Speech Synthesiser (1983)
VTR Vocal Synthesizer (1985)
Timedata ZXS Speech Synthesiser (1983)
William Stuart Systems Chatterbox (1983)
William Stuart Systems Chatterbox II (1985) (with intonation)
Zebra Talker Speech Synthesiser (for Timex)
Datel Vox Box (1984) (allophone)
DCP Microdevelopments S-Pack (1983) - vocabulary of 71 words (upgradeable)
DCP Microdevelopments Speech Pack (1982) for ZX81
There isn't much known about these devices, most are probably containing
SP0256-AL2 chips, too. One exception are the devices from DCP, which contain
Digitalker chips from National Semiconductor, and which use a fixed vocabulary
instead of allophones. Not too sure if Datel has actually manfactured any
hardware (possibly they've just renamed and redistributed hardware from other
companies).
Cheetah Sweet Talker Software
Chatbox (Demonstration Program by Cheetah Marketing Ltd.)
Fuller Orator / Master Unit Speech Software
Spectrum Voice Chess (Fuller Box version; ie. NOT the ULA version) (Artic)
DK'Tronics Speech Software
Speech Software (Demonstration Program by DK'Tronics Ltd.)
Currah MicroSpeech Software
Title
3-D Monster Chase
All or Nothing
Arrow of Death Part 1
Arrow of Death Part 2
Atic Atac
Auf Wiedersehen Pet
Bingo
Birds and the Bees, The
Blade Alley
Blastermind!
Blob, The
Bongo
Cagara
Colour Clash
Connect 4
Covenant, The
Crazy Golf
Currah MicroSpeech

Publisher
Romik Software
Abbex Electronics
Digital Fantasia
Digital Fantasia
Ultimate Play The Game
Tynesoft
Tynesoft
Bug-Byte Software Ltd
PSS
Martech Games Ltd
16/48 Tape Magazine
Anirog Software
Players Software
Romik Software
John Westhead
PSS
Mr. Micro Ltd
Currah Computer Components Ltd

Currah MicroSpeech Software


Cecomsa
Evil Dead, The
Palace Software
Fruit Snapper
LiveWire Software
Giant's Revenge
Thor Computer Software
Golden Baton
Digital Fantasia
Grand Prix Driver
Britannia Software Ltd
Gremlins
Thor Computer Software
Harlequin
Mr. Micro Ltd
Hunchback
Ocean Software Ltd
Insult Generator
Greg Fox
Island, The
Crystal Computing
Jack and the Beanstalk
Thor Computer Software
Learn with Ted
Playground Software
Lunar Jetman
Ultimate Play The Game
Lunar Rescue
Lyversoft
Max Headroom
Quicksilva Ltd
Maze of Terror
Kevin Hillyer
Maziacs
DK'Tronics Ltd
Mega Fruit
Thor Computer Software
Mined-Out
Quicksilva Ltd
Moon Alert
Ocean Software Ltd
Mr. Wimpy
Ocean Software Ltd
Mystic Tower
Aardvark Software
Night Stalker
Thor Computer Software
Pi-Balled
Automata UK Ltd
Pogo
Ocean Software Ltd
Pontoon
Oxford Computer Publishing
Psi-Spy
Postern Ltd
Punchy
Mr. Micro Ltd
Rainy Day
CCS
Rockfall
Crash
Rockfall II
Crash
Roulette
Oxford Computer Publishing
Sexy Black Jack
Load 'n' Run [Ita]
Shark Attack
Romik Software
Skelby - The Schizophrenic Droid
Q Bit
Spectrum Voice Chess
Artic Computing Ltd
Spiders Web
Thor Computer Software
Sport of Kings
Mastertronic Added Dimension
Spyship SOS
Dynamic Software
Starbike
The Edge Software
Steve Davis Snooker
CDS Microsystems
Terrahawks
CRL Group PLC
Timebomb
CDS Microsystems
Time Machine, The
Digital Fantasia
Titanic
R&R Software Ltd
Twin Kingdom Valley
Bug-Byte Software Ltd
War of the Worlds, The
CRL Group PLC
Xavior
PSS
Zepherus
National Software Library
Zig Zag
DK'Tronics Ltd
Not verified if the above list is correct (Spectrum Voice Chess seems to be
wrong, versions that support ULA and Fuller speech do exist, but there seems to
be no Currah version).
Spectrum Sound Speech I/O Ports
------------------------------xx9Fh - Fuller Orator / Fuller Box Master Unit - Speech Output (W)
0-5 SP0256-AL2 Allophone number
6-7 Unknown
xxBFh - Fuller Orator / Fuller Box Master Unit - Speech Status (R)
0-6 Unknown
7
Load Request (LRQ) (0=Buffer full, 1=Ready to receive data)
007Fh - DK'Tronics Speech Synthesiser - Speech Output (W)
0-5 SP0256-AL2 Allophone number
6-7 Unknown
007Fh - DK'Tronics Speech Synthesiser - Speech Status (R)
0-6 Unknown
7
Load Request (LRQ) (0=Ready to receive data, 1=Not ready)
DK'Tronics Speech Synthesiser - Software Driver
The DK'Tronics hardware doesn't include a BIOS/BASIC extension ROM, but, the
BASIC demonstration program includes a machine code driver, which allows the
LPRINT command with backslash to be used to output speech, eg.:
LPRINT "\d k tronics"
LPRINT "print this\speak this"

the DK'Tronics driver does attempt to properly pronounce words automatically,


without needing to use special codes like (aa) (dth) as used by Currah.
0007h - Cheetah Sweet Talker - Speech Output (halts CPU) (W)
0-5 SP0256-AL2 Allophone number
6-7 Unknown
This poor piece of hardware doesn't seem to have a status register that
indicates when new data can be sent, instead, it does simply HALT the CPU when
speech is busy. Not sure if halting is bound to the SBY or /LRQ pin (?) (in the
latter case one could still execute some program code when implementing complex
timings in software).
Read from Memory Address 0038h - Enable/Disable Currah uSpeech BIOS
Reading from this memory address enables/disables the 2K uSpeech BIOS (and
probably also the uSpeech command/status register), ie. on each second read it
gets enabled (at 0000h..07FFh), on each other read it gets disabled.
0-7 Data/Opcode from the (newly) activated ROM
Usually the enable takes place when the CPU jumps to the vblank IRQ handler at
0038h, which is then redirected to the uSpeech BIOS, which does then do it's
job, and jumps to 0038h, which re-enables the Spectrum BIOS and executes the
normal IRQ handler.
There are no further BIOS hooks; initialization (upon reset) is also done from
inside of the hooked IRQ handler.
Read from Memory Address 1000h - Currah uSpeech Status (R)
This port is probably accessible only when enabled via address 0038h.
0
Load Request (LRQ) (1=Buffer full, 0=Ready to receive data)
1-7 Unknown/unused
Bit0 seems to be the /LRQ pin of the SP0256 chip. Unknown if the SBY pin
(indicating when all data is finished) is also found in this register?
The size of the buffer is unknown, maybe it can only hold only a single value
(additionally to the sound being currently played)...?
Write to Memory Address 1000h - Currah uSpeech Output (W)
This port is probably accessible only when enabled via address 0038h.
0-5 SP0256-AL2 Allophone Number (00h..3Fh)
6
Intonation
(0=Decrease Pitch, 1=Increase Pitch)
7
Unknown/unused
(should be zero)
Data can be written to this register when the Status.Bit0 indicates ready (not
sure happens when it doesn't). The last allophone should be followed by a pause
(eg. 00h=Pause10ms), otherwise the SP0256 does reportedly gets stuck repeating
the last allophone (not sure what gets repeated exactly, maybe it repeats only
the end of the last allophone, ie. "shhhhhhh" for "sh", or maybe the whole last
allophone, ie. "shshshsh"?)
The intonation bit seems to be a special feature of the Currah hardware (not a
feature of the SP0256 voice chip itself). Unknown how it is implemented... it
might modify the CLK passed to the SP0256... so, aside from the frequency, this
would also alter the durations, ie. the length of a "100ms" pause would vary...
or it might modify whatever kind of external low-pass and/or high-pass
filter...? The intonation does increase step-by-step (rather than changing
abruptly from low to high)... the stepping rate, and the max/min values are
unknown?
Currah uSpeech Mirrors of 0038h and 1000h and ROM
Reads from memory address 0038h are also mirrored to reads from I/O address
0038h (used by Rockfall to detect the uSpeech), apparently the port is decoded
by checking only A0..A15 and /RD.
For address 1000h it's still unknown if there are mirrors, possibly, only /RD,
/WR, A12, A14, A15 are decoded (probably together with the uSpeech BIOS enable
flag which gets set/cleared via 0038h); if so, mirrors would occur at
1000h-1FFFh and 3000h-3FFFh in both memory and I/O region? If so, using the I/O
mirrors would be not too recommended since they could conflict with other
internal/external I/O ports.
For the ROM it's unknown if it's mirrored, too. Might be mirrored to 800h..FFFh
and 2000h-2FFFh?
Currah uSpeech BIOS/BASIC extension
Unlike most or all other speech devices, the Currah hardware includes a BIOS
extension. Currah related BASIC commands are:
LET keys=0
;disable spoken keystrokes (recommended for LOAD/SAVE)
LET keys=1
;enable spoken keystrokes (default)
LET s$="he(ll)(oo)" ;say hello (normal lowercase)
LET s$="hE(ll)(oO)" ;say hello (with raised intonation on "e" and "(oo)")
PAUSE 1
;wait for Vblank IRQ (where s$ is processed)
CLEAR n
;change RAMTOP (speech buffer is between RAMTOP and UDG)
IF PEEK(65364)=81
;buffer pointer LSB, [FF54h]=51h=buffer_empty (on 48K)
IF s$(TO 1)="*"
;check if s$ was processed (copied to speech buffer)
IF s$(TO 1)="?"
;check if s$ was rejected (contained invalid characters)
IF s$(TO 1)=other
;check if s$ was not yet processed (or buffer full)
On power up, the Currah BIOS allocates 256 bytes between RAMTOP and UDG,

containing a 6-byte "header", and a 250-byte buffer; which contains allophone


numbers (and intonation flag in bit6), in the format as written to address to
1000h (ie. not in ASCII format as used in the BASIC s$ variable). On the
Spectrum this region is at FFxxh (on Spectrum 16K it's at 7Fxxh):
FF57h - Flag byte
FF56h - Spare (unused general purpose byte; NOT reserved for anything)
FF55h - Hi byte of buffer pointer ;\contains FF51h when empty
FF54h - Lo byte of buffer pointer ;/
FF53h - Spare (unused general purpose byte; NOT reserved for anything)
FF52h - Spare (unused general purpose byte; NOT reserved for anything)
FF51h..FE58h - Speech buffer (default size=250) [FF51h]=next allophone
In BASIC, the spoken keystrokes and s$ strings are good for a first "oh it does
really speak" impression, although after soon, the keystroke feature may become
annoying, and the automatic modification of the first character in s$ may cause
compatibility problems with various BASIC programs that do use s$ for other
purposes.
Moreover, allocating 256 bytes between RAMTOP and UDG may cause problems with
many machine code programs. And, hooking the IRQ handler changes Vblank
handling timings which may also cause problems with a few programs.
Spectrum Sound Speech SP0256 Voice Generator
-------------------------------------------Voice Generator
The voice generator relies on the Amplitude, Pitch, F0..F5, and B0..B5
registers, which are processed like so:
Amplitude
--> F0 --> F1 --> F2 --> F3 --> F4 --> F5 --> PWM --> External
Pitch/Noise
B0
B1
B2
B3
B4
B5
5kHz Filter
Another important register is the Repeat counter, which indicates when the next
opcode shall be executed (and which may then load new values into the above
registers).
Sample Rate and Repeat Timings
The SP0256 is (usually) driven by a 3.12MHz oscillator, and it uses 7bit PWM
output, which is clocked at 3.12MHz/2. To obtain a 10kHz sample rate, the chip
issues some dummy steps with constant LOW level additionally to the 128 steps
needed for 7bit PWM, making it a total number of 156 steps per sample.
Sample Rate = 3.12MHz/2/156 = 10.0kHz
;100us per sample
Which means one sample is 100us long, that value multiplied by 64 or 91 gives
the following timings per repeat:
6.4ms per repeat (noise and pause), or
9.1ms per repeat (tone with pitch=91)
Note: Some speech interfaces have the chip overclocked to 4MHz, resulting in
higher pitch & sample rate, and shorter timings as with the normal 3.12MHz.
Amplitude/Pitch/Repeat
The 8bit amplitude register defines the volume in floating point form,
Amplitude = lower5bit SHL upper3bit
The pitch defines the frequency, counted in numbers of samples per period.
For pitch=91, one HIGH sample (amplitude) is output, followed by 90 zero
samples (null). That pattern is repeated as many times as specified in the
repeat count, for example, with repeat=3:
__ Amplitude level (+)
|
|
|
|________|________|________
__ Zero level
PITCH
<-Pitch->
__ Amplitude level (-)
<--------repeat=3--------->
As shown above, the generated waveform is NOT a square wave (which would have
50% high, and 50% low). After applying filters, the final waveform may look
somewhat like so:
__ Amplitude level (+)
|
|
|
|_|_.____|_|_.____|_|_.____
__ Zero level
PITCH+FILTERS
| |
| |
| |
|
|
|
__ Amplitude level (-)
Note that (aside from noise) the AL2 ROM uses only one pitch value: 5Bh aka 91
decimal (meaning that all vowels are using the same base frequency, and they
differ only by using different filter settings).
Amplitude/Noise/Repeat
Noise is activated when setting pitch=0. The timings are then same as when
pitch=64, but instead of outputting HIGH and NULL levels, the hardware does now
randomly output HIGH or LOW levels, for example, pitch=0 and repeat=5:
__ Amplitude level (+)
||| || | | | || |
|| ||| |
|||_|| |__|_|__||_|___|| |||_| __ Zero level
NOISE
| | || | || | ||| |
|
<-64->| || | || | ||| |
|
__ Amplitude level (-)
<----------repeat=5---------->

The exact random algorithm is unknown (probably some shift/xor stuff?), the
random levels seem to be output on each sample (not only on the first sample of
a repeat). Like normal pitch, the noise is passed to the 6 filters.
Pause/Repeat
The pause command sets amplitude=0. The timings are then same as when pitch=64,
but the output is always NULL, for example, pause and repeat=5:
__ Amplitude level (+)
______________________________

__ Zero level

PAUSE (SILENCE)

<-64->
__ Amplitude level (-)
<----------repeat=5---------->
Pause does reset the filters to 0, so the silence is not affected by filters.
Digital Filters
As shown above, the amplitude/pitch/noise output is passed through six digital
filter stages (using the F0..F5 and B0..B5 registers), each stage looks like
so:
_____
_____
------------------>|
|------------------->|
|-----+----->
_____
| SUB |
______
| SUB |
|
+--->| *B |--->|_____|
+--->| *2*F |-->|_____|
|
|
|_____|
_____
|
|______|
_____
|
+---------------|OLDER|<---+---------------| OLD |<----+
|_____|
|_____|
Ie. the incoming samples are adjusted like so:
for i=0 to 5
;filter number
sample = sample - quant_table[F.i] * OLD.i * 2
;F0..F5 registers
sample = sample - quant_table[B.i] * OLDER.i
;B0..B5 registers
OLDER.i = OLD.i
OLD.i
= sample
next i
Whereas, quant_table is a non-linear translation table that translates the
signed 8bit registers to signed 10bit factors (with 9bit fractional part, ie.
511 means 0.99), with following entries:
0 ,9 ,17 ,25 ,33 ,41 ,49 ,57 ,65 ,73 ,81 ,89 ,97 ,105,113,121
129,137,145,153,161,169,177,185,193,201,209,217,225,233,241,249
257,265,273,281,289,297,301,305,309,313,317,321,325,329,333,337
341,345,349,353,357,361,365,369,373,377,381,385,389,393,397,401
405,409,413,417,421,425,427,429,431,433,435,437,439,441,443,445
447,449,451,453,455,457,459,461,463,465,467,469,471,473,475,477
479,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495
496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511
Above shows only positive values for index 0..127. Values for index -1..-128
should be 0..-511, or maybe -9..-512.
Spectrum Sound Speech SP0256 Instruction Set
-------------------------------------------Memory
The SP0256 can address 60Kbytes (480Kbits) of internal or external ROM,
however, usally the ROMs are only 2Kbytes (16Kbit). The ROM contains plain
program code, without any kind of data arrays.
The upper 4bit of the program counter cannot be zero, so the memory starts at
byte-address 1000h, and ends at FFFFh. The first 512 bytes are entrypoints,
usually containing JUMP opcodes for up to 256 allophones or words.
The opcodes and their parameters are transferred serially, LSB first (except,
for some reason, the JUMP/CALL/SETPAGE "Target" values are MSB first).
The JUMP/CALL/RET opcodes can address only byte-aligned addresses, however,
opcodes aren't always multiples of 8bits in size, so following opcodes may
begin on any bit boundary.
Opcode Summary
0000b SETPAGE/RET
0001b SETMODE
0010b LOAD_23
0011b LOAD_56
0100b LOAD_56D
0101b SETMSB_3
0110b SETMSB_23
0111b LOAD_PA
1000b LOAD_ALL
1001b DELTA_56
1010b SETMSB_3P
1011b DELTA_23
1100b SETMSB_3D
1101b CALL
1110b JUMP
1111b PAUSE

Set Page for JUMP/CALL, or Return from CALL


Set the MODE bits and Repeat MSBs
Load Pitch, Amplitude, 2-3 Coefficients
Load Pitch, Amplitude, 5-6 Coefficients
Load Pitch, Amplitude, 5-6 Coefficients, Delta
Load Amplitude, MSBs of 3 Coefficients
Load Amplitude, MSBs of 2 or 3 Coeffcients
Load Pitch, Amplitude
Load All Parameters (at full 8bit precision)
Add Delta to Amplitude, Pitch, 5 or 6 Coefficients
Load Amplitude, MSBs of 3 Coefficients, Pitch
Add Delta to Amplitude, Pitch, 2 or 3 Coefficients
Load Amplitude, MSBs of 3 Coefficients, Delta
Jump to Subroutine (12-bit PAGE-Relative Address)
Jump to 12-bit PAGE-Relative Address
Silent Pause

Each opcode starts with a 4bit parameter field, followed by the 4bit opcode
number, eventually followed by further Nbit parameter(s).
Opcode 1110b - JUMP - Jump to 12-bit PAGE-Relative Address
Opcode 1101b - CALL - Jump to Subroutine (12-bit PAGE-Relative Address)
4
Target bit8-11 (in reversed bit-order!)
4
Opcode (must be 1110b or 1101b)
8
Target bit0-7 (in reversed bit-order!)
0..7 Byte-alignment for next opcode (should be padded with 0 bits)
Jumps to the specified memory address, Target bit12-15 are taken from the PAGE
register (which is usually 01h, set like so on power up, but can be set to
other values in range 01h..0Fh via SETPAGE).
CALL pushes the 16bit byte-aligned return address onto stack, and marks the
stack as not empty. The previous contents of the stack are lost (the stack is
only one entry deep).
Opcode 0000b with Zero-Operand - RET - Return from Subroutine (or HALT)
4
Zero for RET (00h=Return)
4
Opcode (must be 0000b)
0..7 Byte-alignment for next opcode (should be padded with 0 bits)
If the stack was not empty: Jumps to the pushed return address (ie. to the next
byte after the most recent CALL opcode), and marks the stack as empty.
If the stack was already empty: Enters HALT state until/unless new data is/was
input via /ALD pin. As soon as new data is available, it jumps to 1000h+data*2.
Note: HALT state stops program execution, but does not stop the sound generator
- to obtain silence, issue a short PAUSE (or another opcode that sets
amplitude=0).
Opcode 0000b with Nonzero-Operand - SETPAGE - Set the PAGE register
4
Target bit12-15 (in reversed bit-order!) (01h..0Fh=Page)
The above target bits are used for ALL following JUMP/CALL opcodes
4
Opcode (must be 0000b)
The PAGE register retains its setting until the next SETPAGE is encountered.
(Note that address loads via ALD appear to ignore PAGE, and set the four MSBs
to $1000. They do not modify the PAGE register, so subsequent JUMP/CALL
instructions will jump relative to the current value in PAGE.)
Opcode 0001b - SETMODE - Set the MODE bits and Repeat MSBs
2
Repeat Count bit4-5 (expands the next ONE opcode that uses 4bit repeat)
1
WIDTH for ALL following opcodes (0=Smaller, 1=Bigger bit-width)
1
EXTRA for ALL following opcodes (0=Exclude, 1=Include optional params)
4
Opcode (must be 0001b)
Some opcodes have coefficient parameters of variable width (for example "3/6"
means 3bit or 6bit), the smaller width is used when WIDTH=0, the bigger when
WIDTH=1.
Some opcodes have optional parameters (for example "(8)" means an optional 8bit
parameter), which is included in the opcode only when EXTRA=1.
Opcode 1111b - PAUSE - Silent Pause
4
Repeat Count
4
Opcode (must be 1111b)
Provides a silent pause of varying length. The pause behaves identially to a
pitch with Amplitude=0 and Period=64. All coefficients are cleared, as well.
Opcode
4
4
6
8

0111b - LOAD_PA - Load Pitch, Amplitude


Repeat Count
Opcode (must be 0111b)
Amplitude MSBs (upper 3bit are exponent)
Pitch (00h=Noise)

Opcode
4
4
8
8
8
8
8
8
8
8
8
8
8
8
8
8
(8)
(8)
Notes:

1000b - LOAD_ALL - Load All Parameters (at full 8bit precision)


Repeat Count
Opcode (must be 1000b)
Amplitude unsigned (upper 3bit are exponent)
Pitch unsigned (00h=Noise)
Coeff B0 signed
;\coeff pair 0
Coeff F0 signed
;/
Coeff B1 signed
;\coeff pair 1
Coeff F1 signed
;/
Coeff B2 signed
;\coeff pair 2
Coeff F2 signed
;/
Coeff B3 signed
;\coeff pair 3
Coeff F3 signed
;/
Coeff B4 signed
;\coeff pair 4
Coeff F4 signed
;/
Coeff B5 signed
;\coeff pair 5
Coeff F5 signed
;/
Amplitude Interpolation, signed
;\when EXTRA=1 only
Pitch Interpolation, signed
;/
The pitch and amplitude deltas that are available when EXTRA=1 are

applied every pitch period, not just once. Wraparound may occur. If the Pitch
goes to zero, the periodic excitation switches to noise.
Opcode 0010b - LOAD_23 - Load Pitch, Amplitude, 2-3 Coefficients
Opcode 0011b - LOAD_56 - Load Pitch, Amplitude, 5-6 Coefficients
Opcode 0100b - LOAD_56D - Load Pitch, Amplitude, 5-6 Coefficients, Delta
4
Repeat Count
4
Opcode (must be 0010b or 0011b or 0100b)
6
Amplitude MSBs (upper 3bit are exponent)
8
Pitch (00h=Noise)
3/6 Coeff B0 Bit4/1..6 unsigned ;\coeff pair 0
;\
5/6 Coeff F0 Bit3/2..7 signed
;/
;
3/6 Coeff B1 Bit4/1..6 unsigned ;\coeff pair 1
; opcode LOAD_56D,
5/6 Coeff F1 Bit3/2..7 signed
;/
; and LOAD_56 only
3/6 Coeff B2 Bit4/1..6 unsigned ;\coeff pair 2
;
5/6 Coeff F2 Bit3/2..7 signed
;/
;/
4/6 Coeff B3 Bit3/1..6 unsigned ;\coeff pair 3
6/7 Coeff F3 Bit2/1..7 signed
;/
7/8 Coeff B4 Bit1/0..7 signed
;\coeff pair 4
6/8 Coeff F4 Bit2/0..7 signed
;/
(8) Coeff B5 Bit0..7 signed
;\coeff pair 5
;\when EXTRA=1 only
(8) Coeff F5 Bit0..7 signed
;/
;/
5
Amplitude Interpolation LSBs, unsigned
;\opcode LOAD_56D only
5
Pitch Interpolation LSBs, unsigned
;/
Sets the unspecified coefficients to 0. The "unsigned" B0,B1,B2,B3 values are
zero-expanded from N bits to (N+1) bits, and are then copied to the upper (N+1)
bits of the register.
Opcode 0110b - SETMSB_23 - Load Amplitude, MSBs of 2 or 3 Coeffcients
Opcode 0101b - SETMSB_3 - Load Amplitude, MSBs of 3 Coefficients
Opcode 1010b - SETMSB_3P - Load Amplitude, MSBs of 3 Coefficients, Pitch
Opcode 1100b - SETMSB_3D - Load Amplitude, MSBs of 3 Coefficients, Delta
4
Repeat Count
4
Opcode (must be 0101b or 0110b or 1010b or 1100b)
6
Amplitude MSBs (upper 3bit are exponent)
[8] Pitch (00h=Noise)
;-Opcode SETMSB_3P only
5/6 New F0 MSBs signed
;\
5/6 New F1 MSBs signed
; Opcode SETMSB_3/3P/3D only
5/6 New F2 MSBs signed
;/
6/7 New F3 MSBs signed
;\
6/8 New F4 MSBs signed
; Opcode SETMSB_23 only
(8) New F5 MSBs signed (when EXTRA=1 only)
;/
(0) Set F5=0 and B5=0 (when EXTRA=0 only)
[5] Amplitude Interpolation LSBs, unsigned
;\Opcode SETMSB_3D only
[5] Pitch Interpolation LSBs, unsigned
;/
All other coefficient bits are unaffected (ie. all coefficients that aren't
accessed by the specific opcode, as well as LSBs of accessed coefficients).
Opcode 1001b - DELTA_56 - Add Delta to Amplitude, Pitch, 5 or 6 Coefficients
Opcode 1011b - DELTA_23 - Add Delta to Amplitude, Pitch, 2 or 3 Coefficients
4
Repeat Count
4
Opcode (must be 1001b or 1011b)
4
Amplitude Interpolation 6 MSBs signed
5
Pitch Interpolation LSBs signed
3/4
B0 4,7 MSBs signed ;\
;\
3/4
F0 5,6 MSBs signed ;/
;
3/4
B1 4,7 MSBs signed ;\
; opcode DELTA_56 only
3/4
F1 5,6 MSBs signed ;/
;
3/4
B2 4,7 MSBs signed ;\
;
3/4
F2 5,6 MSBs signed ;/
;/
3/4
B3 5,7 MSBs signed ;\
4/5
F3 6,7 MSBs signed ;/
4/5
B4 x,8 MSBs signed ;\ <---- DELTA_56: x=6, and DELTA_23: x=7 (?)
4/5
F4 6,8 MSBs signed ;/
(5)
B5 (8) MSBs signed ;\
;\when EXTRA=1 only
(5)
F5 (8) MSBs signed ;/
;/
Performs a delta update, adding small 2s complement numbers to a series of
coefficients. The 2s complement updates for the various filter coefficients
only update some of the MSBs -- the LSBs are unaffected. The exact bits which
are updated are noted above.
Normal 2s complement arithmetic is performed, and no protection is provided
against overflow. Adding 1 to the largest value for a bit field wraps around to
the smallest value for that bitfield.
Notes: The delta update is applied only once (even if the repeat count is
bigger than 1).
The delta updates are applied to the 8-bit encoded forms of the coefficients,
not the 10-bit decoded forms.
The update to the amplitude register is a normal 2s complement update to the
entire register. This means that any carry/borrow from the mantissa will change
the value of the exponent. The update doesn't know anything about the format of

that register.
Program Counter and Stack Note
As seen in the datasheets for external speech ROMs, the Program Counter & Stack
seem to be part of the ROM (not of the microprocessor). So, when using external
ROMs, one would theoretically have separate stacks for each ROM. NB. this
explains why the Target values are reversed; apparently the ROMs use different
bit-order (for memory addresses) than the microprocessor does for its own
values (ie. the opcodes and voice-parameters).
Credits
The SP0256 opcodes were reverse engineered by Joe Zbiciak and Frank Palazzolo.
Repeat Count = 0
According to Joe and Frank, a repeat count of zero "causes the instruction to
not execute" (and not to fetch any of its following paramters, so the opcode
becomes only 8bits long; or to fetch, but not apply them?), however, they've
also mentioned that "conflicting documentation suggests there's more going on".
XXX...
Bit fields narrower than 8 bits are MSB justified unless specified otherwise,
meaning that the least significant bits are the ones that are missing. These
LSBs are filled with zeros.
When updating filter coefficients with a delta-update, the microsequencer
performs plain 2s-complement arithmetic on the 8-bit value in the coefficient
register file. No attention is paid to the format of the register.
Spectrum Sound Speech SP0256 Allophones/Words
--------------------------------------------SP0256-AL2 Allophone List
Num Name Example Funny
Actual
Num Name Example Funny
Actual
00h PA1
PAUSE
10ms
6.4ms
20h /AW/ Out
370ms 254.8ms
01h PA2
PAUSE
30ms
25.6ms
21h /DD2/ Do
160ms
72.1ms
02h PA3
PAUSE
50ms
44.8ms
22h /GG3/ Wig
140ms 110.5ms
03h PA4
PAUSE
100ms
96.0ms
23h /VV/ Vest
190ms 127.4ms
04h PA5
PAUSE
200ms 198.4ms
24h /GG1/ Got
80ms
72.1ms
05h /OY/ Boy
420ms 291.2ms
25h /SH/ Ship
160ms 198.4ms
06h /AY/ Sky
260ms 172.9ms
26h /ZH/ Azure
190ms 134.1ms
07h /EH/ End
70ms
54.6ms
27h /RR2/ Brain
120ms
81.9ms
08h /KK3/ Comb
120ms
76.8ms
28h /FF/ Food
150ms 108.8ms
09h /PP/ Pow
210ms 147.2ms
29h /KK2/ Sky
190ms 134.4ms
0Ah /JH/ Dodge
140ms
98.4ms
2Ah /KK1/ Can't
160ms 115.2ms
0Bh /NN1/ Thin
140ms 172.9ms
2Bh /ZZ/ Zoo
210ms 148.6ms
0Ch /IH/ Sit
70ms
45.5ms
2Ch /NG/ Anchor
220ms 200.2ms
0Dh /TT2/ To
140ms
96.0ms
2Dh /LL/ Lake
110ms
81.9ms
0Eh /RR1/ Rural
170ms 127.4ms
2Eh /WW/ Wool
180ms 145.6ms
0Fh /AX/ Succeed
70ms
54.6ms
2Fh /XR/ Repair
360ms 245.7ms
10h /MM/ Milk
180ms 182.0ms
30h /WH/ Whig
200ms 145.2ms
11h /TT1/ Part
100ms
76.8ms
31h /YY1/ Yes
130ms
91.0ms
12h /DH1/ They
290ms 136.5ms
32h /CH/ Church
190ms 147.2ms
13h /IY/ See
250ms 172.9ms
33h /ER1/ Letter
160ms 109.2ms
14h /EY/ Beige
280ms 200.2ms
34h /ER2/ Fir
300ms 209.3ms
15h /DD1/ Could
70ms
45.5ms
35h /OW/ Beau
240ms 172.9ms
16h /UW1/ To
100ms
63.7ms
36h /DH2/ Bath
240ms 182.0ms
17h /AO/ Aught
100ms
72.8ms
37h /SS/ Vest
90ms
64.0ms
18h /AA/ Hot
100ms
63.7ms
38h /NN2/ No
190ms 136.5ms
19h /YY2/ Yes
180ms 127.4ms
39h /HH2/ Hoe
180ms 126.0ms
1Ah /AE/ Hat
120ms
81.9ms
3Ah /OR/ Store
330ms 236.6ms
1Bh /HH1/ He
130ms
89.6ms
3Bh /AR/ Alarm
290ms 200.2ms
1Ch /BB1/ Business 80ms
36.4ms
3Ch /YR/ Clear
350ms 245.7ms
1Dh /TH/ Thin
180ms 128.0ms
3Dh /GG2/ Guest
40ms
69.4ms
1Eh /UH/ Book
100ms
72.8ms
3Eh /EL/ Saddle
190ms 136.5ms
1Fh /UW2/ Food
260ms 172.9ms
3Fh /BB2/ Business 50ms
50.2ms
Mind that completion of an allophone doesn't mute the voice generator (it'll
keep repeating the end of the allophone until receiving a new allophone). To
mute the voice generator, output a short pause (eg. PA1) after your last
allophone.
The "Funny" timings are from the SP0256-AL2 data sheet (these values are
totally wrong). The "Actual" timings are calculated from the pitch/repeat
values in the AL2 ROM (these values should be 100% correct, when clocked at
3.12MHz).
<--------------- Currah Codes --------------->
Num ASCII Num ASCII Num ASCII
Num ASCII
18h a
27h r
14h (aa)/(ay) 29h (ck)
1Ch b
37h s
13h (ee)
3Ch (ear)
08h c
11h t
06h (ii)
1Ah (eh)
15h d
0Fh u
35h (oo)/(eau) 33h (er)
07h e
23h v
3Fh (bb)
34h (err)

28h
24h
1Bh
0Ch
0Ah
2Ah
2Dh
10h
0Bh
17h
09h
-

f
g
h
i
j
k
l
m
n
o
p
q "kw"

2Eh
31h
2Bh

w
21h (dd)
x "ks" 3Dh (gg)
y
22h (ggg)
z
39h (hh)
3Eh (ii)
36h N/A
38h (nn)
00h EOL
0Eh (rr)
01h '
0Dh (tt)
02h N/A
19h (yy)
03h SPACE 3Bh (ar)
04h ,
2Fh (aer)
04hx2 .
32h (ch)

2Ch
3Ah
16h
1Fh
20h
05h
25h
1Dh
12h
1Eh
30h
21h

(ng)
(or)
(ou)
(ouu)
(ow)
(oy)
(sh)
(th)
(dth)
(uh)
(wh)
(zh)

Other Allophone/Word Sets


For curiosity, below are some other SP0256-xx variants (none of the known
Spectrum devices is using that variants though).
SP0256-012 Word List
This chip is used in the "Intellivoice" expansion module for Mattel's
Intellivision.
00h (SPB640
08h One
14h Thirteen
20h Seventy
Speech
09h Two
15h Fourteen
21h Eighty
FIFO)
0Ah Three
16h Fifteen
22h Ninety
01h pause4
0Bh Four
17h Sixteen
23h Hundred
02h pause3
0Ch Five
18h Seventeen
24h Thousand
03h pause2
0Dh Six
19h Eighteen
25h -teen
04h pause1
0Eh Seven
1Ah Nineteen
26h -ty
05h pause0
0Fh Eight
1Bh Twenty
27h Press
06h "Mattel
10h Nine
1Ch Thirty
28h Enter
Electronics 11h Ten
1Dh Fourty
29h Or
Presents"
12h Eleven
1Eh Fifty
2Ah And
07h Zero
13h Twelve
1Fh Sixty
There isn't much known about the SPB640 FIFO, as far as I understand, it does
have three functions: It can hold up to 64 word/allophone numbers (to be
injected to A1..A8 pins of the SP0256), it can hold opcodes/parameters (to be
injected to SER IN pin of the SP0256), and it includes a general purpose I/O
port.
SP0256-017 Word List
00h Oh
09h
01h One
0Ah
02h Two
0Bh
03h Three
0Ch
04h Four
0Dh
05h Five
0Eh
06h Six
0Fh
07h Seven
10h
08h Eight
11h

Nine
Ten
Eleven
Twelve
Thirteen
Fourteen
Fifteen
Sixteen
Seventeen

12h
13h
14h
15h
16h
17h
18h
19h
1Ah

Eighteen
Nineteen
Twenty
Thirty
Forty
Fifty
It is
A.M.
P.M.

1Bh
1Ch
1Dh
1Eh
1Fh
20h
21h
22h
23h

Hour
Minute
Hundred Hour
Good Morning
Attention Please
Please Hurry
Melody A
Melody B
Melody C

SP0256-019 (or rather SP0256B-019) Allophone/Word/Phrase List


This chip is used in "The Voice", an expansion module for the Odyssey 2. The
chip contains the following allophones and words:
80h..BFh Allophones (same as 00h..3Fh on SP0256-AL2)
C0h "Enemy"
C1h "All clear"
C2h "Please"
C3h "Get off"
C4h "Open fire"
C5h "Watch out"
C6h "Mercy"
C7h "Hit it"
C8h "You blew it"
C9h "Do it again"
CAh "Incredible" FAh "U.F.O."
FBh "Monster!"
Not sure why bit7 is set in the codes (it should be written like so to the O2
I/O ports, but maybe the bit isn't actually passed to the SP0256 chip)?
Additionally, the expansion module contains 3 built-in speech ROMs with sound
effects and various words/phrases like "Amazing", "Come on", "Outch", etc.
Moreover, Odyssey 2 game cartridges can contain up to 5 external speech ROMs.
For details see "Odyssey 2 Technical Specs" from Daniel Boris.
Spectrum Sound Speech SP0256 Pin-Outs
------------------------------------SP0256 - Speech chip
1 GND
2 /RESET
3 ROM DISABLE
4 C1
5 C2
6 C3
7 VCC1
8 SBY
9 /LRQ
10 A8
11 A7
12 SER OUT
13 A6

14 A5
15 A4
16 A3
17 A2
18 A1
19 SE
20 /ALD
21 SER IN
22 TEST
23 VCC2
24 PWM OUT
25 /SBY RESET
26 ROM CLK
27 OSC1
28 OSC2
The oscillator should be 3.12MHz
Allows to output sounds up to 5kHz (ie. the output is updated at 10kHz rate).
The SP0256 is reportedly expandable to "491 K of ROM" (probably bullshit).
The SP0256B is reportedly expandable to "480 K of ROM" (probably K=Kbits).
The TEST pin of the SP0256 chip can be used (among others) to dump its internal
ROM. Note: Details on TEST are found in the "SP0256B" datasheet - but not in
the "SP0256" datasheet - not sure if the pin works identical for both chip
types, nor if there's a difference between them at all.
SPR16 (16kbit) and SPR32 (32kbit) - External Serial-bus Speech ROM
1 GND
2 C3
3 NC
4 ROM CLK
5..6 NC
7 CS1
8 /CS2
9 /ROM ENABLE
10 SERIAL OUT
11 VCC
12..13 NC
14 SERIAL IN
15 C1
16 C2
SPR128 (128kbit) - External Serial-bus Speech ROM
1 GND
2 C3
3 NC
4 ROM CLK
5..10 NC
11 CS1
12 /CS2
13 /ROM ENABLE
14 SERIAL OUT
15 VCC
16..21 NC
22 SERIAL IN
23 C1
24 C2
Spectrum Sound Digital Playback/Sampling
---------------------------------------Cheetah Specdrum (Playback)
OUT DFh
;output unsigned sample data (80h=silence)
Advertised as Drum machine, although hardware-wise it's simply a general
purpose D/A playback device. Supported by the included SpecDrum software, and
by additional Afro Kit, Electro Kit, Latin Kit tapes. Functionally same as the
Cheetah Sound Sampler's playback, but using a different port address.
Latin/Electro/Afro-KitSideB --> OUTs to DF,FF,9F,BF
Cheetah - Sound Sampler (Playback/Recording)
OUT 7Fh
;write any data to start sampling (to be followed by delay)
IN BFh
;read sampled data (after OUT 7Fh)
OUT BFh
;output (unsigned?) sample data (write twice?)
Supported only by the included software. Functionally same as Datel's sampler,
but with port addresses BFh and 7Fh exchanged.
Datel - Digital Sound Sampler (Playback/Recording)
OUT BFh
;write any data to start sampling (to be followed by delay)
IN 7Fh
;read sampled data (after OUT BFh)
OUT 7Fh
;output (unsigned?) sample data (output)
Supported only by the included software. Functionally same as Cheetah's

sampler, but with port addresses BFh and 7Fh exchanged.


RAM Electronics - Music Machine (Playback/Recording/MIDI)
IN DFh
;dummy read to start sampling (followed by delay, and then IN BFh)
IN BFh
;read sampled data (unsigned, 80h=silence) (after IN DFh)
OUT 9Fh
;output 8bit unsigned sample data (80h=silence)
OUT 5Fh
;maybe MIDI (used 4 times with values 00h,01h)
;-INTERRUPT?
OUT FC7Fh ;maybe MIDI (used 5 times with values 03h,91h,31h,11h) ;\
OUT FD7Fh ;maybe MIDI (used 1 time with variable value)
; ACIA?
-- FE7Fh ;maybe MIDI (not used by existing software?)
;
IN FF7Fh ;maybe MIDI (used 1 time)
;/
Note: The Amstrad CPC version has these MIDI ports:
&F8E8(Write only) INTERUPT SEL Writing 01 to this port disables internal
Amstrad interrupts and replaces the IRQ signal from ACIA.
Writing 00 restores normality.
&F8EC(Write only) ACIA Control
See 6850 ACIA chip for details
&F8ED(Write only) ACIA Data write See 6850 ACIA chip for details
&F8EE(Read only)
ACIA Status
See 6850 ACIA chip for details
&F8EF(Read only)
ACIA Data read See 6850 ACIA chip for details
Supported only by the included software.
Spectrum Disc and Tape Drives
----------------------------Disc and Tape Overviews
--> Spectrum Disc and Tape Drive Summary
--> Spectrum Disc and Tape Commands
Standard Audio Cassette Drives
--> Spectrum Cassette
--> Spectrum Cassette TZX Format
Some other more or less popular Disc and Tape drives
--> Spectrum Interface 1 (Microdrive, Network, RS232)
--> Spectrum Disc Spectrum +3 Disc Controller (NEC uPD765)
--> Spectrum Disc Opus Discovery
--> Spectrum Disc Disciple and Plus D
--> Spectrum Disc Beta/BetaPlus/Beta128 Disk Interface (TRDOS)
XXX
x--> Spectrum Disc I/O Ports
x--> Spectrum Disc Formats
Disc Controllers
--> Spectrum Disc Controller (Western Digital WD177x)
--> Spectrum Disc Spectrum +3 Disc Controller (NEC uPD765)
--> Spectrum Disc Controller (Other)
Timex FDD Interface
The interface uses a logic circuit to page in the 4KB FDD ROM whenever there is
a call to 0x0000 or 0x0008 and page it out again whenever there is a call to
0x0604. When it is needed the FDD ROM is paged in at 0x0000 and 0x1000 and the
area 0x2000-0x3fff holds eight copies of 1K of RAM or four copies of 2K of RAM.
The disk drive is controlled by port 0xef
NMI Snapshot Button
Many disk interfaces have a NMI button, allowing to save a snapshot of the RAM
and CPU registers to disk. Since most spectrum programs are sold on cassettes,
this is a useful feature; allowing to "copy" the program to disk, it can be
also useful for saving game postition on disks in games that don't support
saving (or that only support saving to cassette).
Floppy I/O Ports
Interface
Chip Type Cmd/Stat Track Sector Data
Misc
MFT PlusD
1772 IO
E3h
EBh
F3h
FBh
EFh,E7h,F7h
MFT Disciple
1772 IO
1Bh
5Bh
9Bh
DBh
1Fh,3Bh,7Bh,BBh,FBh
Beta Disk
1793 IO
1Fh
3Fh
5Fh
7Fh
FFh
Didaktik D80
?
IO
81h
83h
85h
87h
89h
JLO
?
IO
8Fh
9Fh
AFh
BFh
B7h
Putnik 1991
1772 IO
F1h
F3h
F5h
F7h
DFh/1Fh
Putnik 1998
1772 IO
73h
F3h
77h
F7h
DFh/1Fh
Opus Discovery 1770 MEM 2800h
2801h 2802h 2803h 3000h-3003h, IO:1Fh
Spectrum +3
765 IO
N/A
N/A
N/A
3FFDh 2FFDh,1FFDh
IO: Accessed via IN/OUT opcodes, MEM: Accessed via LD opcodes (memory mapped).
The first 4 ports are used to access the disc controller.
The "Misc" port(s) can have various (non-standarized) purposes: Reading the
controllers DRQ or IRQ signal (not supported by all interfaces), outputting
Drive Select signals (or Drive Number), Motor enable (done automatically by
WD1770/WD1772), Side Select, and/or non-disk related add-ons like joysticks,
centronics ports, etc.

Stepping
Compatible
MotorOn
Pin20
WD179x Slow
No
WD1770 Slow
Yes(Pin20)
MO
WD1772 Faster
Yes(Pin20)
MO
WD1773 Slow
WD1793
No
END/RDY
The newer WD177x chips contain a digital data separator and write
precompensation circuitry (meaning that they require less external components
than the older WD179x chips).
28pin 177x Pinouts
1 /CS
2 R/W
3 A0
4 A1
5 D0
6 D1
7 D2
8 D3
9 D4
10 D5
11 D6
12 D7
13 /RES
14 GND

28
27
26
25
24
23
22
21
20
19
18
17
16
15

INTRQ
DRQ
/DDEN
/WRPT
/IP
/TR00
WD
WG
MO
/RD
CLK
SD
STEP
+5V

->
->
<- Double Density Enable
<<- Index Hole
<Write Data
->
Write Gate
->
Motor On
->
Read Data
<8MHz
<Step-Direction
->
Step
->

40pin 179x Pinouts


...?
Putnik Port 1Fh/DFh (decoded via A5)
0-4 Kempston Joystick
5
Not used (always 0)
6
INTRQ (from FDC chip)
7
DRQ (from FDC chip)
The interface contains a manual side select switch. The interface doesn't
include a ROM, maybe it's intended to be used with a patched BASIC ROM, or
additional ROM cartridge, or with a boot cassette.
(Note: There's also a "Putnik RomSwitch" circuit, which uses Port A9h, probably
that's intended to be used in combination with the floppy circuit.)
IDE Interface I/O Ports
Type
divIDE Vehmaa
ZXCF
Data
&xxA3 &00BF
Error
&xxA7 &01BF
Count
&xxAB &02BF
Sector
&xxAF &03BF
CylinderLo &xxB3 &04BF
CylinderHi &xxB7 &05BF
Drive
&xxBB &06BF
Command
&xxBF &07BF
DataLo
&08BF
DataHi
&09BF
Error
&0EBF
AltStatus
&0FBF
Control
&xxE3
ROM selection
Type
Vehmaa
ZXCF
Range
&00-&3F
Page ROM
&10BF,n
ZX ROM
&10BF,&80+x
RESET ROM
&00

Vehmaa
ZXATASP
&039F?
&039F?
&039F?
&039F?
&039F?
&039F?
&039F?
&039F?
&009F?
&019F?

1-Chip Putnik
8bitv1
&00EF &xx2B
&01EF &xx2F
&10EF &xx6B
&11EF &xx6F
&20EF &xxAB
&21EF &xxAF
&30EF &xxEB
&31EF &xxEF

Vehmaa
ZXATSP
&00-&3F
&029F,n

Putnik
RomSwitch
&00-&03
&xxA9,n

&00

&03

Putnik
8bitv2
&00BF
&01BF
&10BF
&11BF
&20BF
&21BF
&30BF
&31BF

Putnik
16bitv1
&xx69
&xx79
&xx6B
&xx7B
&xx6D
&xx7D
&xx6F
&xx7F

JGH
ROMBox
&00-&F0
&xxFD,16*n
&xxFD,&10
&00

Putnik
16bitv2
&xx2B
&xx2F
&xx6B
&xx6F
&xxAB
&xxAF
&xxEB
&xxEF

SAfri
16bit
&xx59
&xx5B
&xx5D
&xx5F
&xx79
&xx7B
&xx7D
&xx7F

Sinclair
Spectrum128
&00-&10
&7FFD,16*n
&7FFD,&10
&00

Spectrum Disc and Tape Drive Summary


-----------------------------------The standard media for Spectrum software are regular Audio Cassettes. Instead
of supporting disk drives, Sinclair has focused on selling Microdrive
Cartridges as alternative media, until, finally Amstrad released an "official"
disk drive in the Spectrum +3. However, at that time third-party companies have
had already produced various disk drives, all incompatible with each other,
using different controllers, I/O ports, BIOSes, file systems, and different
physical dimensions (2.8", 3", 3.5", and 5.25").
Standard Audio Cassette Drives
Any standard data or audio Cassette Recorder connected to MIC/EAR sockets
Spectrum +2/+2A with internal cassette recorder
Challenge Research Ltd: Challenge Sprint (quad-speed "audio" cassette drive)

Challenge Research Ltd: Challenge Sprint Mk II (new: Interface 1 compatible)


Evesham Micro Centre: Doubler (external tape input for tape-to-tape copy)
Evesham Micro Centre: Doubler Mk II (new: more compatible with more tape decks)
Sequential Disk/Tape Drives
Sinclair Microdrive (endless tape drive) (85K..100K) (requires Interface 1)
Rotronics Wafadrive (endless tape drive) (16K, 64K, 128K)
Crescent Quick Disk (2.8" disk, with single spiral-track, 128K or 256K)
Triton Quick Disk (2.8" disk, with single spiral-track, 100K)
Floppy Disk Drives/Interfaces
Opus: Discovery (1985) (centronics, video out, kempston stick, intern 3.5" drv)
Opus: Spectra Disc Interface (1984) (centronics, external 3.5" or 5.25" drive)
Miles Gordon Technology: MGT Plus D Interface (for MGT Lifetime Drive) (1988)
Miles Gordon Technology/Rockford Products: Disciple (1987)
Spectrum +3 (internal 3" disk drive) (1987)
Technology Research: Beta Disk Interface (1984)
Technology Research: Beta Plus Disk Interface (1985) (magic button)
Technology Research: Beta 128 Disk Interface (1986)
Timex FDD and FDD-3000 Disk Drives (with external Z80 CPU)
Omnitronix Ltd: Pacer Disk Interface
John Oliger Company: JLO TS2068 Disk System
Ramex Millenia K disk interface (SPDOS, or alternately LKDOS)
Acme Electric Robot Company: AERCO FD-68 (for TS2068) (Aerco DOS, or LKDOS)
LarKen: Disk Interface and LKDOS cartridge (for TS2068)
Kempston: Disc Interface (KDOS)
Logitek: Disc Interface (connect a Commodore 1541 drive to spectrum)
Sixword Ltd.: Swift Disc
Circuit Design: CS-DISK Interface
Haytech: Cyborg Disk Drive with Spectrum Personality Module
Statacom: Datafax Disk System
Cumana Ltd: Double Density Disk Interface
Dove Microtronix Ltd: Dove Disk Interface
8BC: MB-02+ Disk Interface
Morex Peripherals Ltd: Morex Floppy Disk System
Saga Systems Ltd: Saga Disk Interface
Saga Systems Ltd: Saga Disk Interface II (with printer port)
Thurnall Electronics Ltd: Thurnall Disk System (MCD-1)
Interactive Instruments Ltd: Viscount Disk Drive System
ITL & Tyrell Systems: Byte Drive 500
Ergo Systems Ltd/Video Vault Ltd: Clive Drive
Didaktik D40
Didaktik D80
Putnik 1991 (homebrew schematic) (uses A1, incompatible with Spectrum 128)
Putnik 1998 (homebrew schematic) (uses A7, now compatible with Spectrum 128)
Compact Disc Interface
Code Masters CD Games Pack (load games from Audio CD via joystick port)
Other Interfaces
Additonally, there are a number of newer harddisk and compact flash interfaces,
though they are probably rather rarely used.
Spectrum Disc and Tape Commands
------------------------------General Spectrum Load/Save commands (cas/disk)
LOAD ""
;load basic program (by wildcard)
LOAD <filename>
;load basic program (by name)
LOAD "picture.bin" CODE
;load binary to original addr
LOAD "picture.bin" CODE dest(,len_verify) ;load binary to other addr
LOAD "picture.bin" CODE SCREEN$
;load binary to VRAM
LOAD <filename> DATA a ()
;load numeric array
LOAD <filename> DATA a$ ()
;load character array
SAVE <filename>
;save basic program
SAVE <filename> LINE <linenumber>
;save basic program with autostart
SAVE "picture.bin" CODE SCREEN$
;save binary file (VRAM at 4000h)
SAVE "picture.bin" CODE 16384,6912
;save binary file (same as SCREEN$)
SAVE "picture.bin" CODE start,length
;save binary file (custom area)
SAVE <filename> DATA a ()
;save numeric array
SAVE <filename> DATA a$ ()
;save character array
VERIFY <filename> ;compare file with program in in RAM
MERGE <filename>
;merge file with program in in RAM
Disk commands (Spectrum +3)
filename="DISK"
;default name for "loader" option in +3 BIOS menu
filename="filename.ext" ;max 8.3 characters (for CP/M-style filesystem)
MOVE oldname newname
;rename (or move to other drive)
MOVE oldname TO attr
;change attr "+p" "+s" "+a" or "-p" "-s" "-a"
COPY oldname newname
;copy

COPY textfile TO SCREEN$


COPY textfile TO LPRINT
COPY binfile TO SPECTRUM
LOAD "d:"
;set default
SAVE "d:"
;set default
CAT (#stream),"filename"
ERASE filename
FORMAT drive
FORMAT LINE baudrate
FORMAT LPRINT "r"
Streams:
OPEN #n,"k"
;keyboard
OPEN #n,"s"
;screen
OPEN #n,"p"
;printer

FORMAT
;creates binfile.HED (with binary HEaDer)
load drive (a:disk1, b:disk2, m:ramdisk, t:tape)
save drive (a:disk1, b:disk2, m:ramdisk, t:tape)
;show directory (on stream #n)
;delete
;set RS232 baudrate
;redirect printer ("p") to RS232 ("r") stream
(default=#1)
(default=#2)
(default=#3)

RAM-Disk (Spectrum 128/+2/+2A/+3)


On the Spectrum 128/+2/+2A/+3, 64Kbytes of RAM are used as RAM-Disk, which can
be accessed by appending an exclamation mark to cassette commands,
LOAD! SAVE! MERGE! CAT! ERASE! --> access RAM disk
On the Spectrum +2A/+3, one can additionally/alternately access the RAM-Disk by
specifying drive letter M as part of the filename, eg. LOAD "m:filename".
Microdrive (Sinclair Interface I)
LOAD * "m" ;1; "filename"
SAVE * "m" ;1; "filename"
FORMAT "m" ;1; "filename"
CAT 1
The microdrive syntax is also used by the Opus Discovery.
Rotronics Wavadrive
CAT *
;directory for default drive
CAT * "a:"
;directory for drive A
CAT # "a:"
;set A as default drive and load (but do not show) directory
POKE 23767,n
;set default drive (0=A, 1=B)
SAVE * "a:name" ;save on drive A
SAVE * "name"
;save on default drive
The thing also has a one-directional centronics port (stream "c"), and a RS232
port with RXD,TXD,RTS,CTS lines (stream "r").
Extended System Area occupies 102 bytes of RAM (starting at 23734), read/write
buffer occupies 1026 bytes (at 23836), directory A and B occupy 582 bytes each
(at 24862 and 25444).
Opus Discovery
Uses microdrive-style syntax. Additional commands are:
FORMAT "j";1
;enable kempston joystick port in opus discovery
FORMAT "j";0
;disable kempston joystick port in opus discovery
Includes a kempston joystick port (which must be enabled as described above),
and a centronics port. The centronics port can be also use as network
interface, via LOAD/SAVE/VERIFY * "b".
Technology Research - Beta Disk Interface (TRDOS)
In BASIC:
LET DOS=15360 ;=3C00h ;for Beta and Beta Plus (TRDOSv1 or TRDOSv4)
LET DOS=15616 ;=3D00h ;for Beta 128 (TRDOSv5)
RANDOMIZE USR DOS+3:REM:LOAD"D:FILENAME" ;load from drive D
RANDOMIZE USR DOS+0
;switch from BASIC to TRDOS
In TRDOS:
LIST (K-key)
;show directory ;<B>=bootable
LOAD (J-key) or RUN (R-key)
;load a file
USR
;set disk password
RETURN (Y-key)
;switch from TRDOS to BASIC
Kempston Disk Interface (K-DOS)
Uses a rather strange syntax where disk-commands are preceeded by "PRINT #4:",
and in some cases followed by ":PRINT parameter(s)", eg:
PRINT #4:LOAD"filename"
PRINT #4:CAT:PRINT d
;d=drive number (1..4)
Larken (LARKEN DOS aka LKDOS)
Uses similar syntax as Kempston, but must be first initialized as:
RANDOMIZE USR 100: OPEN# 4, "dd"
Thereafter, "PRINT #4:" can be used to preceed disk-commands, eg.
PRINT #4:LOAD"filename"
The built-in joystick port is accessed via IN 31 (kempston style).
There are also LKDOS versions for use with Ramex and Aerco disk interfaces.
Spectrum Cassette
----------------The cassette is accessed via bits in ULA Port FEh (see ULA chapter). Cassette

input is received from EAR port, output is passed to MIC port. For the bizarre
part, the MIC and EAR leads cannot be simultaneously connected, so one of the
leads must be disconnected/reconnected for loading/saving. There is no Motor On
signal, so PLAY/STOP must be pressed manually.
Spectrum Cassette Blocks
Silence (low level)
8063 (Header) or 3223 (Data) Pilot Pulses (2168 clks/pulse) (619us/pulse)
1st Sync Pulse (667 clks/pulse) (190us/pulse)
2nd Sync Pulse (735 clks/pulse) (210us/pulse)
Blocktype Byte (00h=Header, FFh=Data)
Data Byte(s) (two 855 or 1710 clks/pulse per bit) (244 or 488 us/pulse)
Checksum Byte (above Blocktype and Data Bytes XORed with each other)
End pulse (opposite level of last pulse)
Silence (low level)
Spectrum Pilot/Sync/Bits/Bytes
/"""\__/
Sync Pulses (1st=667, 2nd=735 clks/pulse)
/""""\____/
"0"-Bit (two pulses, 855 clks/pulse)
/"""""""""\_________/
"1"-Bit (two pulses, 1710 clks/pulse)
/""""""""""""\____________/ etc.
Pilot Pulses (2168 clks/pulse)
Bytes are transferred MSB (Bit7) first. Signals may be inverted.
Spectrum Header Block
Pre 1
Blocktype (aka Flag Byte) (must be 00h for Header blocks)
0
1
Filetype (0..3, see below)
1
10
Filename (padded with blanks, ie. chr(20h))
11
2
Length of following Data Block (LEN)
13
4
Parameters (depends on Filetype, see below)
Post 1
Checksum (above 18 bytes XORed with each other)
Spectrum Data Block
Pre 1
Blocktype (aka Flag Byte) (must be FFh for Data Blocks)
0
LEN Data
Post 1
Checksum (above LEN+1 bytes XORed with each other)
Spectrum Filetypes/Parameters (Bytes 13..16 of Header Blocks)
For Filetype=00h / BASIC Program File (Program and Variables):
13
2
Autostart LINE Number (or 8000h..FFFFh if no autostart)
15
2
Size of the PROG area aka start of the VARS area
For Filetype=01h / BASIC Number Array, or Filetype=02h / BASIC Character Array:
13
1
Unknown
14
1
Name of the variable
15
2
Unknown
For Filetype=03h / Binary CODE File (or SCREEN$ file):
13
2
Memory Address
15
2
Unused (Should be 8000h)
A SCREEN$ file is a CODE file with Memory Address 4000h and LEN=1B00h.
.TAP Files (Standard Cassette-Image for normal unprotected files)
A .TAP file can contain one or more spectrum file(s). Each file should usually
consist of two blocks (header and data). Each block is preceeded by a 16bit
length value (eg. 0013h for Header blocks), followed by "length" bytes which
contain the same information as stored on real cassettes (including the leading
Blocktype byte, and ending Checksum byte).
TAP files do not contain pilot/sync pulses, nor baudrate information, so they
can be used only for standard files (as used by the BIOS functions), not for
copyprotected software.
.TZX Files (Standard Cassette-Image for copy-protected files)
--> Spectrum Cassette TZX Format
Spectrum Cassette TZX Format
---------------------------For some general definitions, see:
--> Spectrum Cassette TZX Notes
TZX Header (length: 0Ah bytes)
00h 8 TZX signature ("ZXTape!",1Ah)
08h 1 TZX major revision number (currently 01h, for v1.20)
09h 1 TZX minor revision number (currently 1Ah, for v1.20)
ID 10h - Standard Speed Data Block (length: [02h..03h]+4)
This block must be replayed with the standard Spectrum BIOS timings - see the
values in curly {} brackets in block ID 11h.
00h 2 Pause after this block (ms) (0=none) {1000}
02h 2 Length of data that follow (N)
04h N Data as in .TAP files (first byte implies number of pilot pulses)
The pilot tone consists of 8063 pulses if the first data byte (flag byte) (aka

block_type) is < 128, or 3223 pulses otherwise. This block can be used for the
BIOS loading routines AND for custom loading routines that use the same timings
as BIOS ones do.
ID 11h 00h 2
02h 2
04h 2
06h 2
08h 2
0Ah 2
0Ch 1

Turbo Speed Data Block (length: [0Fh..11h]+12h)


Length of PILOT pulse
{2168} ;-occurs P times at begin
Length of SYNC first pulse
{667} ;-occurs ONCE after above
Length of SYNC second pulse
{735} ;-occurs ONCE after above
Length of ZERO bit pulse
{855} ;-occurs TWICE per bit
Length of ONE bit pulse
{1710} ;-occurs TWICE per bit
Number of PILOT pulses (P)
{8063 for header, 3223 for data)
Number of used bits in the last byte {8}
(e.g. if this is 6, then the bits used (x) in the last byte are:
xxxxxx00, where MSb is the leftmost bit, LSb is the rightmost bit)
0Dh 2 Pause after this block (ms) (0=none) {1000}
0Fh 3 Length of data that follow (N)
12h N Data as in .TAP files
{block_type, data[N-2], chksum}
This block is very similar to the normal TAP block but with some additional
info on the timings and other important differences. The same tape encoding is
used as for the standard speed data block. If a block should use some
non-standard sync or pilot tones (i.e. all sorts of protection schemes) then
use the next three blocks to describe it.
ID 12h - Pure Tone (length: 04h)
00h 2 Length of one pulse in T-states
02h 2 Number of pulses
This will produce a tone which is basically the same as the pilot tone in the
ID 10h, ID 11h blocks. You can define how long the pulse is and how many pulses
are in the tone.
ID 13h - Pulse sequence (length: [00h]*2+1)
00h 1
Number of pulses (N)
01h 2*N Pulse lengths (16bit each)
This will produce N pulses, each having its own timing. Up to 255 pulses can be
stored in this block; this is useful for non-standard sync tones used by some
protection schemes.
ID 14h 00h 2
02h 2
04h 1
05h 2
07h 3
0Ah N
Same as

Pure Data Block (length: [07h..09h]+0Ah)


Length of ZERO bit pulse
Length of ONE bit pulse
Used bits in last byte (other bits should be 0)
(e.g. if this is 6, then the bits used (x) in the last byte are:
xxxxxx00, where MSb is the leftmost bit, LSb is the rightmost bit)
Pause after this block (ms) (0=none)
Length of data that follow (N)
Data as in .TAP files
in the turbo loading data block, but without pilot and sync pulses.

ID 15h 00h 2
02h 2
04h 1

Direct Recording (length: [05h..07h]+08h)


Number of T-states per sample-bit (usually 158 or 79)
Pause after this block (ms) (0=none)
Used bits (samples) in last byte of data (1..8)
(eg. 2 means only first two samples of the last byte will be played)
05h 3 Length of sample data in bytes (N)
08h N Sample data. Each bit represents a state on the EAR port
(i.e. one sample). MSb is played first.
This block is used for tapes which have some parts in a format such that the
turbo loader block cannot be used. This is not like a VOC file, since the
information is much more compact. Each sample value is represented by one bit
only (0 for low, 1 for high) which means that the block will be at most 1/8 the
size of the equivalent VOC.
The preferred sampling frequencies are 22050 or 44100 Hz (158 or 79
T-states/sample), this will ensure correct playback when using PC's soundcards.
Please, if you can, don't use other sampling frequencies.
Please use this block only if you cannot use any other block.
ID 16h - C64 BIOS Type Data Block (length: [00h..03h]+0 or 4?) (v1.13 only)
ID 17h - C64 Turbo Tape Data Block (length: [00h..03h]+0 or 4?) (v1.13 only)
These two blocks were defined (although rarely/never used) in TZX version v1.13
only, intended to support Commodore 64 files.
Bug: Blocks invented after v1.10 are stated to have a length of "[00h..03h]+4"
bytes, while the C64 blocks invented in v1.13 were ALSO stated by "[00h..03h]"
in length, so it's somewhat unclear how to the C64 blocks. Anyways, they should
never show up in Spectrum files, and as far as I know the format wasn't
actually used in the C64 world either.
ID 18h 00h 4
04h 2
06h 3

CSW Recording (length: [00h..03h]+4) (v1.20 and up)


Block length (without these four bytes) (10h+N)
Pause after this block (ms) (0=none)
Sampling rate

09h 1 Compression type (01h=RLE, 02h=Z-RLE)


0Ah 4 Number of stored pulses (after decompression, for validation purposes)
0Eh N CSW data, encoded according to the CSW file format specification.
This block contains a sequence of raw pulses encoded in Ramsoft's CSW format v2
(Compressed Square Wave). The encoding of the RLE and Z-RLE data is
undocumented. It can reportedly compress a 12MB 44kHz VOC file to 1MB, which is
still very bloated, so better don't use the CSW stuff.
ID 19h - Generalized Data Block (length: [00h..03h]+4) (v1.20 and up)
This block has been specifically developed to represent an extremely wide range
of data encoding techniques.
--> Spectrum Cassette TZX Format ID 19h
ID 20h - Pause (silence) or 'Stop the Tape' command (length: 2)
00h 2 Pause after this block (ms) (or 0=stop tape, ie. infinite pause)
This will make a silence for a given time in milliseconds. If the value is 0
then the emulator or utility should (in effect) STOP THE TAPE, ie. it should
make a pause of infinite length (until the user or emulator requests to restart
the tape motor). As usually, the first 1 ms of the pause must be opposite of
the old level, the remaining milliseconds must be low level.
ID 21h - Group start (length: [00h]+1)
00 1 Length of the group name string (L)
01 L Group name in ASCII format (please keep it under 30 characters long)
This block marks the start of a group of blocks which are to be treated as one
single (composite) block. This is very handy for tapes that use lots of
subblocks like Bleepload (which may well have over 160 custom loading blocks).
You can also give the group a name (example 'Bleepload Block 1').
For each group start block, there must be a group end block. Nesting of groups
is not allowed.
ID 22h - Group end (length: 0)
This indicates the end of a group. This block has no body.
ID 23h - Jump to block (length: 2)
00h 2 Relative jump value (number of blocks, from current block)
This block will enable you to jump from one block to another within the file.
Some examples:
Jump +0 = Loop Forever
;this should never happen
Jump +1 = Go to the next block ;acts as a NOP in assembler
Jump +2 = Skip one block
Jump -1 = Go to the previous block
All blocks are included in the block count!
ID 24h - Loop start (length: 2) (v1.10 and up)
00h 2 Number of repetitions (greater than 1)
If you have a sequence of identical blocks, or of identical groups of blocks,
you can use this block to tell how many times they should be repeated. This
block is the same as the FOR statement in BASIC.
For simplicity reasons don't nest loop blocks!
ID 25h - Loop end (length: 0) (v1.10 and up)
This is the same as BASIC's NEXT statement. It means that the utility should
jump back to the start of the loop if it hasn't been run for the specified
number of times. This block has no body.
ID 26h - Call sequence (length: [00h..01h]*2+2) (v1.10 and up)
00h 1
Number of calls to be made (N)
02h 2*N Array of call block numbers (relative-signed 16bit offsets)
This block is an analogue of the CALL Subroutine statement. It basically
executes a sequence of blocks that are somewhere else and then goes back to the
next block. Because more than one call can be normally used you can include a
list of sequences to be called. The 'nesting' of call blocks is also not
allowed for the simplicity reasons. You can, of course, use the CALL blocks in
the LOOP sequences and vice versa. The value is relative for the obvious
reasons - so that you can add some blocks in the beginning of the file without
disturbing the call values. Please take a look at 'Jump To Block' for reference
on the values.
ID 27h - Return from sequence (length: 0) (v1.10 and up)
This block indicates the end of the Called Sequence. The next block played will
be the block after the last CALL block (or the next Call, if the Call block had
multiple calls). This block has no body.
ID 28h - Select block (length: [00h..01h]+2) (v1.10 and up)
00h 2 Length of the whole block (without these two bytes)
02h 1 Number of selections (N)
03h .. List of selections
Each selection has the following format:
00 2 Relative Offset (16bit)

02 1 Length of description text (L)


03 L Description text in ASCII (please use single line and max 30 chars)
This block is useful when the tape consists of two or more separately-loadable
parts. With this block, you are able to select one of the parts and the
utility/emulator will start loading from that block. For example you can use it
when the game has a separate Trainer or when it is a multiload. Of course, to
make some use of it the emulator/utility has to show a menu with the selections
when it encounters such a block. All offsets are relative signed words.
ID 2Ah - Stop the tape if in 48K mode (length: 4) (v1.xx? and up)
00h 4 Length of the block without these four bytes (=0)
When this block is encountered, the tape will stop ONLY if the machine is an
48K Spectrum. This block is to be used for multiloading games that load one
level at a time in 48K mode, but load the entire tape at once if in 128K mode.
This block has no body of its own, but follows the extension rule.
ID 2Bh - Set signal level (length: 5) (v1.20 and up)
00h 4 Block length (without these four bytes) (=1)
04h 1 Signal level (0=low, 1=high)
This block sets the current signal level to the specified value (high or low).
It should be used whenever it is necessary to avoid any ambiguities, e.g. with
custom loaders which are level-sensitive.
ID 30h - Text description (length: [00h]+1)
00h 1 Length of the text description (N)
01h N Text description in ASCII format
This is meant to identify parts of the tape, so you know where level 1 starts,
where to rewind to when the game ends, etc. This description is not guaranteed
to be shown while the tape is playing, but can be read while browsing the tape
or changing the tape pointer.
The description can be up to 255 characters long but please keep it down to
about 30 so the programs can show it in one line (where this is appropriate).
Please use 'Archive Info' block for title, authors, publisher, etc.
ID 31h - Message block (length: [01h]+2)
00h 1 Time (in seconds) for which the message should be displayed
01h 1 Length of the text message (N)
02h N Message that should be displayed in ASCII format
This will enable the emulators to display a message for a given time. This
should not stop the tape and it should not make silence. If the time is 0 then
the emulator should wait for the user to press a key.
The text message should:
stick to a maximum of 30 chars per line;
use single 0x0D (13 decimal) to separate lines;
stick to a maximum of 8 lines.
If you do not obey these rules, emulators may display your message in any way
they like.
ID 32h - Archive info (length: [00h..01h]+2)
00h 2 Length of the whole block (without these two bytes)
02h 1 Number of text strings (N)
03h N List of Text Structures
Text Structure format:
00h 1 Text identification byte (see list below)
01h 1 Length of text string (L)
02h L Text string in ASCII format
Text identification byte values:
00h Full title
01h Software house/publisher
02h Author(s)
03h Year of publication
(eg. 1982) (in ASCII, too)
04h Language
(v1.10 and up) (eg. English) (=default)
05h Game/utility type
(v1.12 and up) (eg. arcade adventure, puzzle)
06h Price with currency
(v1.12 and up) (eg. GBP 5.99, or chr(A3h)=GBP)
07h Protection scheme/loader (v1.12 and up) (eg. Speedlock 1, Alkatraz)
08h Origin
(v1.12 and up) (eg. Original, Budget re-release)
FFh Comment(s)
xxh Reserved for future
(decoders should skip any unknown entries)
When using this block, store it at the beginning of the tape. The information
about what hardware the tape uses is in the 'Hardware Type' block, so no need
for it here. According to the tzx format release notes, v1.10 and up allows
multiple lines in the 'Archive info' (ID 32h) block.
ID 33h - Hardware type (length: [00h]*3+1)
00h 1
Number of machines and hardware types for which info is supplied (N)
01h 3*N List of machines and hardware
This blocks contains information about the hardware that the programs on this
tape use. For details, see:
--> Spectrum Cassette TZX Format HW
This feature is (theoretically) the main advantage of the TZX format over the

TAP format, however, in practice, most (or all) existing TZX files don't use
this feature. So, for that matter, one could as well keep using normal TAP
files.
ID 34h - Emulation info (length: 8) (up to v1.13 only)
This block was defined (although rarely used) in TZX versions up to v1.13 only.
00h 2 General emulation flags:
bit 0 : R-register emulation [1]
bit 1 : LDIR emulation [1]
bit 2 : high resolution colour emulation with true interrupt freq. [1]
bit 3,4 : video synchronisation (1=high, 3=low, 0,2=normal) [0]
bit 5 : fast loading when BIOS load routine is used [1]
bit 6 : border emulation [1]
bit 7 : screen refresh mode (0=off, 1=on) [1]
bit 8 : start playing the tape immediately (0=no, 1=yes) [0]
bit 9 : auto type LOAD"" or press ENTER when in 128k mode [0]
02h 1 Update screen every N frames (1..255) (used only when flags.bit7=1)
03h 2 Interrupt Frequency in Hertz (0..999)
05h 3 Reserved for future expansion
This is a special block that would normally be generated only by emulators.
Those bits that are not used by the emulator that stored the info, should be
left at their [default] values.
ID 35h - Custom info block (length: [10h..13h]+14h) (works in v1.01 and up)
00h 16 Identification string (in ASCII) (usually padded with spaces)
10h 1 Length of the custom info (L)
14h L Custom info
This block can be used to save any information you want. For example, it might
contain some information written by a utility, extra settings required by a
particular emulator, or even poke data.
--> Spectrum Cassette TZX Format Custom
Note: The Length of the ID string was accidently documented as 15 bytes in
v1.00 (although it should have been 16), this has been fixed in v1.01.
ID 40h - Snapshot block (length: [01h..03h]+4) (v1.10..v1.13 only)
This block was defined (although rarely used) in tzx versions v1.10..v1.13
only.
00h
1 Snapshot type (00h=.Z80 format, 01h=.SNA format)
01h
3 Snapshot length (L)
04h
L The Snapshot itself
Allows to snapshot the game at the start and still have all the tape blocks
(level data, etc.) in the same file. The emulator should take care of that the
snapshot is not taken while the actual Tape loading is taking place. When an
emulator encounters the snapshot block it should load it and then continue with
the next block.
ID 5Ah (aka "Z") - Glue block (length: 09h)
00h 9 ZXTape Header (excluding the "Z", ie. "XTape!",1Ah,MajR,MinR)
This block is generated when you merge two ZX Tape files together. It is here
so that you can easily copy the files together and use them. Of course, this
means that resulting file would be 10 bytes longer than if this block was not
used. If you can avoid using this block for this purpose, then do so; it is
preferable to use a utility to join the two files and ensure that they are both
of the higher version number.
ID xxh - Reserved (length [00h..03h]+4)
00h 4 Block length (32bit) (without these four bytes)
04h .. Reserved
Reserved for future. As shown above, all new blocks added after v1.10 should
begin with a 32bit Block length entry in the first 4 bytes; the length value
should exclude that first 4 bytes). With that definition, decoders may skip
unknown blocks - and may still work (if the blocks contain only comments or
so).
A special case are the C64 blocks (ID 16h and ID 17h) where the TZX format does
"clearly" define BOTH to include AND to exclude first 4 bytes in the length
entry (that blocks should never show up in Spectrum files, so it should be no
problem, as far as I know they even weren't ever actually used for the C64).
Spectrum Cassette TZX Format HW
------------------------------ID 33h - Hardware type (length: [00h]*3+1)
00h 1
Number of machines and hardware types for which info is supplied (N)
01h 3*N List of machines and hardware (HWINFO)
HWINFO structure format:
00h 1 Hardware type
(00h..10h; see the headlines of the ID lists)
01h 1 Hardware ID
(00h..xxh; see the ID list entries)
02h 1 Hardware information (00h..03h; see the small table below)
This blocks contains information about the hardware that the programs on this
tape use. Please include only machines and hardware for which you are 100% sure

that it either runs (or doesn't run) on or with, or you know it uses (or
doesn't use) the hardware or special features of that machine.
If the tape runs only on the ZX81 (and TS1000, etc.) then it clearly won't work
on any Spectrum or Spectrum variant, so there's no need to list this
information.
If you are not sure or you haven't tested a tape on some particular
machine/hardware combination then do not include it in the list.
The list of hardware types and IDs is somewhat large, and may be found at the
end of the format description.
Hardware information (3rd byte)
00h The tape RUNS on this hardware
01h The tape RUNS and DOES use the
02h The tape RUNS but DOES-NOT use
03h The tape DOES-NOT-WORK on this

(and may or may not use its features)


special features of the hardware
the special features of the hardware
hardware

Hardware information reference


This is the list of all hardware types and hardware identification ID's that
are used in the 'Hardware info' block. Please send any additions you might have
to the TZX maintainers so that they can be included.
By default you don't have to write any of the information if the game is made
for the ZX Spectrum and complies with the following:
- runs on ZX Spectrum 48K
- runs on, but doesn't use any of the special hardware of ZX Spectrum 128K
- doesn't run on ZX Spectrum 16K
If, for example, game works on BOTH ZX 48K and 128K, and uses the hardware of
the 128K Spectrum, then you would just include the 128K Spectrum in the list
(because by default it has to work on 48K too).
If the game is 128K ONLY then you would include two entries: The game works on
AND uses the hardware of a 128K Spectrum AND the game DOESN'T work on a 48K
Spectrum.
If the game works on both 48K and 128K Spectrum, but it only uses the sound
chip (AY) of the 128K Spectrum and none of its extra memory then you would only
include the entry that says that the game uses the 'Classic AY hardware
(Spectrum 128 compatible sound device)'.
These were only some examples of the usage of this block.
Computer Types (first byte = 00h)
00h ZX Spectrum 16k
01h ZX Spectrum 48k, Plus
02h ZX Spectrum 48k ISSUE 1
03h ZX Spectrum 128k + (Sinclair)
04h ZX Spectrum 128k +2 (grey case)
05h ZX Spectrum 128k +2A, +3
06h Timex Sinclair TC-2048
07h Timex Sinclair TS-2068
08h Pentagon 128
09h Sam Coupe
0Ah Didaktik M
0Bh Didaktik Gama
0Ch ZX-80 (via ID 19h, generalized data block, supported in v1.20 and up)
0Dh ZX-81 (via ID 19h, generalized data block, supported in v1.20 and up)
0Eh ZX Spectrum 128k, Spanish version
0Fh ZX Spectrum, Arabic version
10h Microdigital TK 90-X
11h Microdigital TK 95
12h Byte
13h Elwro 800-3
14h ZS Scorpion 256
Below in v1.02 and up (For Amstrad, use extension .CDT instead of .TZX)
15h Amstrad CPC 464
16h Amstrad CPC 664
17h Amstrad CPC 6128
18h Amstrad CPC 464+
19h Amstrad CPC 6128+
Below in v1.12 and up
1Ah Jupiter ACE
1Bh Enterprise
Below in v1.13 only
1Ch (was intended for Commodore 64)
1Dh (was intended for Commodore 128)
Below in v1.20 and up
1Eh Inves Spectrum+
1Fh Profi
20h GrandRomMax
21h Kay 1024
22h Ice Felix HC 91
23h Ice Felix HC 2000
24h Amaterske RADIO Mistrum
25h Quorum 128

26h
27h
28h
29h
2Ah
2Bh
2Ch
2Dh

MicroART ATM
MicroART ATM Turbo 2
Chrome
ZX Badaloc
TS-1500
Lambda
TK-65
ZX-97

External storage types (first byte = 01h)


00h ZX Microdrive
01h Opus Discovery
02h MGT Disciple
03h MGT Plus-D
04h Rotronics Wafadrive
05h TR-DOS (BetaDisk)
06h Byte Drive
07h Watsford
08h FIZ
09h Radofin
0Ah Didaktik disk drives
0Bh BS-DOS (MB-02)
0Ch ZX Spectrum +3 disk drive
0Dh JLO (Oliger) disk interface
0Eh Timex FDD3000
0Fh Zebra disk drive
10h Ramex Millenia
11h Larken
Below in v1.20 and up
12h Kempston disk interface
13h Sandy
14h ZX Spectrum +3e hard disk
15h ZXATASP
16h DivIDE
17h ZXCF
ROM/RAM type add-ons (first byte = 02h)
00h Sam Ram
01h Multiface ONE
02h Multiface 128k
03h Multiface +3
04h MultiPrint
05h MB-02 ROM/RAM expansion
Below in v1.20 and up
06h SoftROM
07h 1k
08h 16k
09h 48k
0Ah Memory in 8-16k used
Sound
00h
01h
02h
03h
04h
05h
Below
06h
07h
08h
09h
0Ah
0Bh
0Ch

devices (first byte = 03h)


Classic AY hardware (compatible with 128k ZXs)
Fuller Box AY sound hardware
Currah microSpeech
SpecDrum
AY ACB stereo (A+C=left, B+C=right); Melodik
AY ABC stereo (A+B=left, B+C=right)
in v1.20 and up
RAM Music Machine
Covox
General Sound
Intec Electronics Digital Interface B8001
Zon-X AY
QuickSilva AY
Jupiter ACE

Joysticks (first byte = 04h)


00h Kempston
01h Cursor, Protek, AGF
02h Sinclair 2 Left (12345)
03h Sinclair 1 Right (67890)
04h Fuller
Mice (first byte = 05h)
00h AMX mouse
01h Kempston mouse
Other controllers (first byte = 06h)
00h Trickstick
01h ZX Light Gun

02h Zebra Graphics Tablet


Below in v1.20 and up
03h Defender Light Gun
Serial ports (first byte = 07h)
00h ZX Interface 1
01h ZX Spectrum 128k
Parallel ports (first byte = 08h)
00h Kempston S
01h Kempston E
02h ZX Spectrum +3
03h Tasman
04h DK'Tronics
05h Hilderbay
06h INES Printerface
07h ZX LPrint Interface 3
08h MultiPrint
09h Opus Discovery
0Ah Standard 8255 chip with ports 31,63,95
Printers (first byte = 09h)
00h ZX Printer, Alphacom 32 & compatibles
01h Generic printer
02h EPSON compatible
Modems (first byte = 0Ah)
00h Prism VTX 5000
01h T/S 2050 or Westridge 2050
Digitizers (first byte = 0Bh)
00h RD Digital Tracer
01h DK'Tronics Light Pen
02h British MicroGraph Pad
Below in v1.20 and up
03h Romantic Robot Videoface
Network adapters (first byte = 0Ch)
00h ZX Interface 1
Keyboards & keypads (first byte = 0Dh)
00h Keypad for ZX Spectrum 128k
AD/DA converters (first byte = 0Eh)
00h Harley Systems ADC 8.2
01h Blackboard Electronics
EPROM programmers (first byte = 0Fh)
00h Orme Electronics
Graphics (first byte = 10h)
Below in v1.20 and up
00h WRX Hi-Res
01h G007
02h Memotech
03h Lambda Colour
Spectrum Cassette TZX Format ID 19h
----------------------------------ID 19h - Generalized Data Block (length: [00h..03h]+4) (v1.20 and up)
00h 4 Block length (without these four bytes)
04h 2 Pause after this block (ms) (0=none)
06h 4 Total number of symbols in pilot/sync block (can be 0) (TOTP) ;\pilot
0Ah 1 Maximum number of pulses per pilot/sync symbol
(NPP) ; hdr
0Bh 1 Number of pilot/sync symbols in alphabet table (0=256) (ASP) ;/
0Ch 4 Total number of symbols in data stream (can be 0)
(TOTD) ;\data
10h 1 Maximum number of pulses per data symbol
(NPD) ; hdr
11h 1 Number of data symbols in the alphabet table (0=256)
(ASD) ;/
12h .. Pilot/Sync symbols definition table
(only if TOTP>0) ;\pilot
.. .. Pilot/Sync RLE-compressed stream (PRLE)
(only if TOTP>0) ;/stream
.. .. Data symbols definition table
(only if TOTD>0) ;\data
.. .. Data stream (as in .TAP files)
(only if TOTD>0) ;/stream
Can be used to encode nonstandard copy-protected files. Also used for ZX81
files.
Symbol Definition Table entry format (for both Pilot/Sync and Data)
00h 1
Symbol flags (b0-b1: starting symbol polarity)
0: opposite to current level (make an edge, as usual) - default
1: same as current level (no edge - prolongs previous pulse)

2: force low level


3: force high level
01h 2*MAXP Pulse lengths (16bit) (padded with 0000h if less than MAXP used)
The number of table entries is ASP or ASD. The size per entry is 1+2*MAXP,
where MAXP is NPP or NPD.
Run-Length Encoded Pilot/Sync Stream format (PRLE)
00h 1 Symbol to be output
(eg. a symbol that defines the Pilot pulse)
01h 2 Number of repetitions (eg. number of Pilot pulses)
The number of entries is TOTP, each entry is 3 bytes in size.
Data Stream format
Most commonly, 2 symbols are used, so the 1st symbol is in bit7 of 1st byte.
If 3 or 4 symbols are used, then the 1st symbol is in bit7-6 of 1st byte.
Example (Standard Spectrum Block)
00h 0000xxxxh
;Total block length (28h+LEN)
04h 03E8h
;Pause after this block (ms)
06h 00000002h
;Total number of pilot/sync symbols
TOTP;\
0Ah 02h
;Max pulses per symbol
NPP ; pilot header
0Bh 02h
;Number of symbols in pilot/sync alphabet ASP ;/
0Ch LEN*8
;Total number of data symbols
TOTD;\
10h 02h
;Max pulses per data symbol
NPD ; data header
11h 02h
;Number of symbols in data alphabet
ASD ;/
12h 00h,02168,00000
;Pilot Symbol 0 (single pilot pulse)
17h 00h,00667,00735
;Pilot Symbol 1 (two sync pulses)
1Ch 00h,08063
;PRLE: take Pilot-Symbol 0, and repeat it 8063 times
1Fh 01h,00001
;PRLE: take Pilot-Symbol 1, and repeat it 1 times
22h 00h,00855,00855
;Data Symbol 0
27h 00h,01710,01710
;Data Symbol 1
2Ch Data (LEN bytes: block_type, data[LEN-2], chksum)
Example (Standard ZX81 Block)
00h 0000xxxxh
;Total block length (58h+LEN)
04h 03E8h
;Pause after this block (ms)
06h 00000000h
;Total number of pilot/sync records
TOTP;\no pilot
0Ah 00h
;Max pulses per symbol
NPP ; for zx81
0Bh 00h
;Number of symbols in pilot/sync alphabet ASP ;/
0Ch LEN*8
;Total number of data symbols
TOTD;\
10h 12h
;Max pulses per data symbol
NPD ; data header
11h 02h
;Number of symbols in data alphabet
ASD ;/
12h 3,530,520,530,520,530,520,530
;\Data Symbol 0
4689,0,0,0,0,0,0,0,0,0,0
;/
37h 3,530,520,530,520,530,520,530
;\Data Symbol 1
520,530,520,530,520,530,520,530,520,530,4689 ;/
5Ch Data (LEN bytes: ZX81 filename, followed by memory [4009h..E_LINE-1])
Note: As usually, data symbol definitions are referred to spectrum-style 3.5MHz
clock frequency (ie. not to ZX81-style 3.25MHz).
ZX80/ZX81 Filetype Detection
ZX80/ZX81 files SHOULD have a Hardware Info block (ID 33h) that identifies them
as ZX80/ZX81 file. Unfortunately, in practice, they usually do NOT contain that
information. So, to detect a ZX80/ZX81 file, one would need to check if the
first data block has ID 19h, and if so, if it contains the above Symbols. To
separate between ZX80 and ZX81 one may need to examine the presence of the ZX81
filename, and the values in the System Area.
ZX80/ZX81 Leading Silence
ZX80/ZX81 files are preceeded by leading silence (instead of a pilot tone). For
the ZX80 this leading silence is REQUIRED (must be at least around 500ms). For
ZX81, it can be shorter, and it is required only if the signal is preceeded by
noise (if loading starts at the exact time when the 1st pulse is output, then
the ZX81 BIOS doesn't need the silence).
The ID 19h block itself doesn't support leading silence, so ZX80 files MUST
have it preceeded by Pause block (ID 20h) - one could almost expect that people
will violate that rule, if so, software must automatically insert the leading
pause.
Spectrum Cassette TZX Format Custom
----------------------------------Custom Info Blocks...
Some of the most common uses of the Custom info block (ID 35h) have become
standardized in the past revisions, although now they are deprecated:
POKEs block (v1.10..v1.13 only)
The purpose of this custom block is to hold any amount of different trainers
for the game.
00h
16 Custom block ID ("POKEs" + 11 spaces)
10h
4 Length of data that follow

14h
1 General description length (L)
15h
L General description in ASCII format
15h+L
1 Number of trainer definitions (N)
15h+L+1 .. Trainer definitions
Each trainer can have its own description and any number of POKEs.
TRAINER structure format
00h
1 Trainer description length (L)
01h
L Trainer description in ASCII format
01h+L
1 Number of poke definitions in this trainer (N)
01h+L+1 .. POKEs definitions
For each POKE entry you can supply the memory page number and/or the original
value of the address (if you want to restore it some way through the game).
Normally you would enter these pokes with the help of some freezer-type tool
like Multiface, but hopefully in the future the emulators will support this
block directly, in which case you could use the 'User inserts the POKE value'
feature. You can specify the point at which to insert the POKEs in the 'General
description' field.
NOTE: All ASCII Descriptions can use more than one line. Please use only up to
30 characters per line and separate the lines by one CR (13 decimal).
POKE structure format
00h 1 POKE type:
bit 0-2 : memory page number
bit 3
: ignore memory page number
bit 4
: user inserts the POKE value
bit 5
: unknown original value
01h 2 POKE address
03h 1 POKE value (leave 0 if 'user inserts' bit set)
04h 1 POKE original value (leave 0 if 'unknown' bit set)
Instructions block (v1.10..v1.13 only)
This block can hold any general .TXT file, with the main purpose of storing the
instructions to the program or game that is in the tape.
To ensure consistency with all other ASCII texts in this format please use a
single CR character (13 decimal, 0Dh) to separate lines; also please use only
up to 80 characters per line.
00h 16 Custom block ID ("Instructions" + 4 spaces)
10h 4 Length of the following data (L)
14h L Instructions text in ASCII format
Spectrum screen block (v1.10..v1.13 only)
If the game on the tape is not an original and lacks the original loading
screen then you can supply it separately within this block. This is also very
handy when you want the loading screen stored separately because the original
is either encrypted (like with the 'Speedlock' or 'Alkatraz' loaders) or it is
corrupted by some on-screen info (like the 'Bleepload' loader). Of course not
only loading screens can be stored here... you can use it to store maps or any
other picture that is in Spectrum Video format (that's why the Description is
there for), but because the Loading Screen will be the most common you can just
set the description length field to 0 when you use it for that. Also the border
colour can be specified.
00h
16
Custom block ID ("Spectrum Screen" + 1 space)
10h
4
Length of data that follow
14h
1
Description length (L) (if 0 then handle it as 'Loading Screen')
15h
L
Description of the picture in ASCII format
15h+L
1
BORDER Colour in Spectrum colour format (0=black, 1=blue, ...)
15h+L+1 6912 Screen in standard Spectrum video format
ZX-Edit document block (v1.12..v1.13 only)
This block can hold files created with the new utility called ZX-Editor. This
utility gives documents the look and feel of ZX-Spectrum and its documents can
contain text, graphics (with Spectrum attributes), different type faces,
colours, etc. Normally these files use extension .ZED. Also the description is
added, in case you want to use it for something else than 'Instructions' - you
can use it for MAPs, etc.
00h
16 Custom block ID ("ZX-Edit document")
10h
4 Length of data that follow
14h
1 Description length (L) (if 0 then handle it as 'Instructions')
15h
L Description of the document in ASCII format
15h+L .. The ZX-Editor document (.ZED file)
Picture block (v1.12..v1.13 only)
Finally you can include any picture (in supported formats) in the TZX file too.
So cover pictures, maps, etc. can now be included in full colour (or whatever
the formats supports). The best way for utilities to use this block is to spawn
an external viewer, or the authors can write their own viewers (yeah, right ;)
). For inlay cards and other pictures that have zillions of colours use the
JPEG format, for more simple pictures (drawing, maps, etc.) use the GIF format.
00h
16 Custom block ID ("Picture" + 9 spaces)
10h
4 Length of data that follow
14h
1 Picture format (00h=GIF, 1=JPEG)

15h
1 Description length (L) (if 0 then handle it as 'Inlay Card')
16h
L Description of the document in ASCII format
16h+L .. The picture itself
Spectrum Cassette TZX Notes
--------------------------Format revision: v1.20, 19 Dec 2006
Introduction
TZX is a file format designed to preserve all (hopefully) of the tapes with
turbo or custom loading routines. Even though some of the newer and 'smarter'
emulators can find most of the info about the loader from the code itself, this
isn't possible if you want to save the file to tape, or to a real Spectrum. And
with all this information in the file, the emulators don't have to bother with
finding out the timings and other things.
This file format is explicitly targeted to the ZX Spectrum compatible computers
only. Specialized versions of the TZX format have been defined for other
machines too, e.g. the Amstrad CPC and C64, but they are now available as
distinct file formats with other filename extensions.
At the end of this document you can find a description of encoding differences
between these machines and a table which displays timings used by their
respective BIOS loading routines (some of them are not official). If you know
of any other machines that have similar encoding that could be represented with
this file format then let us know.
If you're looking for TZX files, you can find an extensive collection at
Martijn van der Heide's 'World of Spectrum'.
The format was first started off by Tomaz Kac who was maintainer until revision
1.13, and then passed to Martijn v.d. Heide. After that, Ramsoft were the
maintainers for a brief period during which the v1.20 revision was put
together. If you have any questions about the format, visit the forums at World
of Spectrum and ask.
The default format file extension is "TZX" and hopefully this won't have to
change in the future; for RISC OS, the current TAP file type will be used.
Amstrad CPC files should use the extension "CDT" to distinguish them from the
ZX Spectrum files, otherwise the inner structure is totally the same.
Rules and definitions
- All values are stored in little endian format (i.e. LSB first)
- All unused bits should be set to zero
- All timings are given in 3.5MHz clock cycles (unless otherwise stated)
- All ASCII texts use the ISO 8859-1 (Latin 1) encoding
- Some ASCII texts can have several lines, to be separated by chr(0Dh)
- MSB = most significant byte, LSB = least significant byte
- MSb = most significant bit, LSb = least significant bit
- The values in curly brackets {} are the default values as used by BIOS
High and low levels
This document refers to 'high' and 'low' pulse levels. Whether this is
implemented as ear=1 and ear=0 respectively or the other way around is not
important, as long as it is done consistently.
Zeros and ones in 'Direct recording' blocks mean low and high pulse levels
respectively. The 'current pulse level' after playing a Direct Recording block
of CSW recording block is the last level played.
The 'current pulse level' after playing the blocks ID 10h,11h,12h,13h,14h or
19h is the opposite of the last pulse level played, so that a subsequent pulse
will produce an edge.
An emulator should put the 'current pulse level' to 'low' when starting to play
a TZX file, either from the start or from a certain position. The writer of a
TZX file should ensure that the 'current pulse level' is well-defined in every
sequence of blocks where this is important, i.e. in any sequence that includes
a 'Direct recording' block, or that depends on edges generated by 'Pause'
blocks. The recommended way of doing this is to include a Pause after each
sequence of blocks.
Silence (pause, stop, end of tzx file)
Some blocks allow to define a pause of N milliseconds (ms) duration. If the old
level was low, then the first 1 ms of that pause should be high (required to
terminate the last pulse), and the remaining N-1 ms should be low. If the old
level was high, then the full N ms should be low.
The same requirement applies also when stopping the tape (on stop command, or
at end of tzx file): if the old level was low, then output 1ms high before
stopping the motor (required because some files do not include a pause after
the last data block which would imply the 1ms thing)
Pause of 0 ms duration is completely ignored, so the 'current pulse level' will
NOT change in this case. If there is no pause between two data blocks then the
second one should follow immediately; not even so much as one T state between

them.
Machine specific information
Currently supported machines are: ZX Spectrum, Amstrad CPC, SAM Coupe, ZX-81
Jupiter ACE and Enterprise. Only ZX-81 (or the old Timex 1000) and Jupiter ACE
use different tape encoding than the others.
Jupiter ACE encoding
See a dedicated site.
ZX Spectrum, Amstrad CPC, SAM Coupe & Enterprise tape encoding
These computers share the same tape encoding, which is normal frequency type
encoding. Each bit is represented by one 'wave' of different duration for bit 0
and bit 1. Normally bit 1 is twice as big as bit 0. In the blocks, the timings
are presented with Z80 T-states (cycles) per pulse. One wave is made from two
pulses.
The standard data blocks have always the same structure: first there is the
PILOT tone, then the two SYNC pulses (one wave) and after that the actual DATA
(which can include a FLAG byte at the beginning and a CHECKSUM byte at the
end).
Here is a table showing the pulse timings for each part of the standard BIOS
load/save routine for each of these machines. If you have more accurate
information then we would be glad to include it here. Enterprise has two
loading speeds so timings for both are included.
Machine
Pilot pulse Length Sync1 Sync2
Bit 0 Bit 1
ZX Spectrum
2168
(1)
667
735
855
1710
SAM Coupe'
58+19*W
6000
58+9*W 113+9*W 10+8*W 42+15*W (*)
Amstrad CPC
Bit 1
4096
Bit 0 Bit 0
(2)
(2)
Enterprise (fast) 742
?
1280
1280
882
602 (**)
Enterprise (slow) 1750
?
2800
2800
1982
1400 (**)
Notes:
(1) The Spectrum uses different pilot lengths for header and data blocks.
Header blocks have 8063 and data blocks have 3223 pilot pulses.
(2) Amstrad CPC BIOS load/save routine can use variable speed for loading,
so the bit 1 pulse must be read from the pilot tone and bit 0 can be
read from the sync pulses, and is always half the size of bit 1. The
checksum is also different than the other two machines. The speed can
vary from 1000 to 2000 baud.
(*) The SAM Coupe' timings can be user selected by a system variable. The
standard value is 112, which is VERY close to ZX Spectrum loading
speed, and therefore the 'Standard Speed Data' block can be used for
those blocks. However if this system variable is changed then the
timings will change accordingly. In the above table the value of this
variable is given as 'W', the 'H' value is 'W/2'. Of course the best
way to determine it is to calculate it from the timings you get when
sampling the Pilot tone. The values in the table could be by a
fraction of the real ones, but it should not matter. Note: All timings
are written in 3.5MHz clock. Also, there might be some junk bits
(usually 7 or 8) AFTER the checksum (XOR) byte at the end of the
block, but they can just be ignored.
(**) The Enterprise stores data in a different way than all other computers
do. It stores the LSb first, but the data blocks require the data to
be MSb first. This might lead to some confusion, but if the same
mechanism is used to replay data for all machines then there will be
no problem. Just store the data as MSb first, but if you want to view
the raw data in the TZX file then you will have to mirror each byte to
get the correct values.
IMPORTANT: The ZXTape format has ALL timings written according to a 3.5MHz
clock (the standard Spectrum 16/48K clock), so if the tape should be used on an
Amstrad CPC with 4MHz clock then you should multiply ALL timings with 4/3.5
when you use that tape (this should be trivial). Similarly goes for SAM Coupe,
that uses a 6MHz clock and Jupiter ACE that uses 3.2448 MHz and Enterprise that
uses 4 MHz!
Spectrum Interface 1 (Microdrive, Network, RS232)
------------------------------------------------Sinclair Interface 1 Features
Allows to connect up to 8 Microdrives (endless tape drives), allows to set up a
network with up to 64 computers, allows to connect a RS232 printer.
Memory Mapped Ports
0008h,1708h - Interface 1 - Enable external ROM (8K) (error and close#)
0700h
- Interface 1 - Disable external ROM (8K) (ret)
Port E7h (R/W)
0-7 Microdrive Data (send/receive)
Accessing this port will HALT the Z80 until the Interface I has collected 8
bits from the microdrive head; therefore, if the microdrive motor isn't
running, or there is no formatted cartridge in the microdrive, the Spectrum

hangs. This is the famous 'IN 0 crash'.


Port EFh (R)
0
Microdrive
1
Microdrive
2
Microdrive
3
RS232 DTR
4
Busy (what
5-7 Not used

Write Protected
Sync
Gap
busy?)

Port EFh (W)


0
Microdrive Comms Data (and Mode for Write to PortF7.Bit0)
1
Microdrive Comms Clk
2
Microdrive R/W
3
Microdrive Erase
4
RS232 CTS
5
Network Wait (used to synchronize)
6-7 Not used
Port F7h (R)
0
Network Input
1-6 Not used
7
RS232 TXDATA
Port F7h (W)
0
Network Output or RS232 RXDATA (depending on Port EFh.Bit0.Write)
1-7 Not used
If the microdrive is not being used, the COMMS DATA output selects the function
of bit0 of out-port F7h.
Spectrum Disc Spectrum +3 Disc Controller (NEC uPD765)
-----------------------------------------------------The Spectrum +3 uses Plus3DOS (which is based on AMSDOS for Amstrad CPC), like
the CPC it's using a NEC uPD765 floppy disk controller.
Port 1FFDh - Spectrum +2A/+3 Memory Control B and Disk Motor (W)
Port 2FFDh - Spectrum +3 Floppy FDC NEC uPD765 status (R)
Port 3FFDh - Spectrum +3 Floppy FDC NEC uPD765 data (R/W)
Accessing the FDC 765
The Data Register (Port 3FFDh) is used to write Commands and Parameters, to
read/write data bytes, and to receive result bytes. These three operations are
called Command-, Execution-, and Result-Phase. The Main Status Register
signalizes when the FDC is ready to send/receive the next byte through the Data
Register.
Command Phase
A command consists of a command byte (eventually including the MF, MK, SK
bits), and up to eight parameter bytes.
Execution Phase
During this phase, the actual data is transferred (if any). Usually that are
the data bytes for the read/written sector(s), except for the Format Track
Command, in that case four bytes for each sector are transferred.
Result Phase
Returns up to seven result bytes (depending on the command) that are containing
status information. The Recalibrate and Seek Track commands do not return
result bytes directly, instead the program must wait until the Main Status
Register signalizes that the command has been completed, and then it must (!)
send a Sense Interrupt State command to 'terminate' the Seek/Recalibrate
command.
FDC Command Table
Command
Parameters
02+MF+SK
HU TR HD ??
03
XX YY
04
HU
05+MT+MF
HU TR HD SC
06+MT+MF+SK HU TR HD SC
07
HU
08
09+MT+MF
HU TR HD SC
0A+MF
HU
0C+MT+MF+SK HU TR HD SC
0D+MF
HU SZ NM GP
0F
HU TP
11+MT+MF+SK HU TR HD SC
19+MT+MF+SK HU TR HD SC

Exm
SZ NM GP SL <R>
SZ LS GP SL <W>
SZ LS GP SL <R>
SZ LS GP SL <W>
SZ LS GP SL <R>
FB
<W>
SZ LS GP SL <W>
SZ LS GP SL <W>

Result
Description
S0 S1 S2 TR HD NM SZ read track
specify spd/dma
S3
sense drive state
S0 S1 S2 TR HD LS SZ write sector(s)
S0 S1 S2 TR HD LS SZ read sector(s)
recalib.seek TP=0
S0 TP
sense int.state
S0 S1 S2 TR HD LS SZ wr deleted sec(s)
S0 S1 S2 TR HD LS SZ read ID
S0 S1 S2 TR HD LS SZ rd deleted sec(s)
S0 S1 S2 TR HD LS SZ format track
seek track n
S0 S1 S2 TR HD LS SZ scan equal
S0 S1 S2 TR HD LS SZ scan low or equal

1D+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan high or eq.


Parameter bits that can be specified in some Command Bytes are:
MT Bit7 Multi Track (continue multi-sector-function on other head)
MF Bit6 MFM-Mode-Bit (Default 1=Double Density)
SK Bit5 Skip-Bit (set if secs with deleted DAM shall be skipped)
Parameter/Result bytes are:
HU b0,1=Unit/Drive Number, b2=Physical Head Number, other bits zero
TP Physical Track Number
TR Track-ID (usually same value as TP)
HD Head-ID
SC First Sector-ID (sector you want to read)
SZ Sector Size (80h shl n) (default=02h for 200h bytes)
LS Last Sector-ID (should be same as SC when reading a single sector)
GP Gap (default=2Ah except command 0D: default=52h)
SL Sectorlen if SZ=0 (default=FFh)
Sn Status Register 0..3
FB Fillbyte (for the sector data areas) (default=E5h)
NM Number of Sectors (default=09h)
XX b0..3=headunload n*32ms (8" only), b4..7=steprate (16-n)*2ms
YY b0=DMA_disable, b1-7=headload n*4ms (8" only)
Format Track: output TR,HD,SC,SZ for each sector during execution phase
Read Track: reads NM sectors (starting with first sec past index hole)
Read ID: read ID bytes for current sec, repeated/undelayed read lists all IDs
Recalib: walks up to 77 tracks, 80tr-drives may need second recalib if failed
Seek/Recalib: All read/write commands will be disabled until succesful senseint
Senseint: Set's IC if unsuccesful (no int has occured) (until IC=0)
FDC Status Registers
The Main Status register can be always read through Port 2FFDh. The other four
Status Registers cannot be read directly, instead they are returned through the
data register as result bytes in response to specific commands.
Main Status Register (Port 2FFDh)
b0..3 DB FDD0..3 Busy (seek/recalib active, until succesful sense intstat)
b4
CB FDC Busy (still in command-, execution- or result-phase)
b5
EXM Execution Mode (still in execution-phase, non_DMA_only)
b6
DIO Data Input/Output (0=CPU->FDC, 1=FDC->CPU) (see b7)
b7
RQM Request For Master (1=ready for next byte) (see b6 for direction)
Status Register 0
b0,1
US Unit Select (driveno during interrupt)
b2
HD Head Adress (head during interrupt)
b3
NR Not Ready (drive not ready or non-existing 2nd head selected)
b4
EC Equipment Check (drive failure or recalibrate failed (retry))
b5
SE Seek End (Set if seek-command completed)
b6,7
IC Interrupt Code (0=OK, 1=aborted:readfail/OK if EN, 2=unknown cmd
or senseint with no int occured, 3=aborted:disc removed etc.)
Status Register 1
b0
MA Missing Adress Mark (Sector_ID or DAM not found)
b1
NW Not Writeable (tried to write/format disc with wprot_tab=on)
b2
ND No Data (Sector_ID not found, CRC fail in ID_field)
b3,6
0
Not used
b4
OR Over Run (CPU too slow in execution-phase (ca. 26us/Byte))
b5
DE Data Error (CRC-fail in ID- or Data-Field)
b7
EN End of Track (set past most read/write commands) (see IC)
Status Register 2
b0
MD Missing Address Mark in Data Field (DAM not found)
b1
BC Bad Cylinder (read/programmed track-ID different and read-ID = FF)
b2
SN Scan Not Satisfied (no fitting sector found)
b3
SH Scan Equal Hit (equal)
b4
WC Wrong Cylinder (read/programmed track-ID different) (see b1)
b5
DD Data Error in Data Field (CRC-fail in data-field)
b6
CM Control Mark (read/scan command found sector with deleted DAM)
b7
0
Not Used
Status Register 3
b0,1
US Unit Select (pin 28,29 of FDC)
b2
HD Head Address (pin 27 of FDC)
b3
TS Two Side (0=yes, 1=no (!))
b4
T0 Track 0 (on track 0 we are)
b5
RY Ready (drive ready signal)
b6
WP Write Protected (write protected)
b7
FT Fault (if supported: 1=Drive failure)
Motor On/Off Flipflop
The motor is controlled via a bit in Port 1FFDh (see ULA chapter), the bit
controls motors for ALL drive(s), it is not possible to turn on/off the motor
of a specific drive separately.

Notes:
Before accessing a disk you should first Recalibrate the drive, that'll move
the head backwards until it reaches Track 0 (that's required to initialize the
FDCs track counter). On a 80 track drive you may need to repeat that in case
that the first recalibration attempt wasn't successful (that's because the FDC
stops searching after 77 steps).
Now if you want to format, read or write a sector on a specific track you must
first Seek that track (command 0Fh). That'll move the read/write head to the
physical track number. If you don't do that, then the FDC will attempt to
read/write data to/from the current physical track, independendly of the
specified logical Track-ID.
The Track-, Sector-, and Head-IDs are logical IDs only. These logical IDs are
defined when formatting the disk, and aren't required to be identical to the
physical Track, Sector, or Head numbers. However, when reading or writing a
sector you must specify the same IDs that have been used during formatting.
Despite of the confusing name, a sector with a "Deleted Data Address Mark"
(DAM) is not deleted. The DAM-flag is just another ID-bit, and (if that ID-bit
is specified correctly in the command) it can be read/written like normal data
sectors.
At the end of a successful read/write command, the program should send a
Terminal Count (TC) signal to the FDC. However, in the CPC (and probably also
in the Spectrum) the TC pin isn't connected to the I/O bus, making it
impossible for the program to confirm a correct operation. For that reason, the
FDC will assume that the command has failed, and it'll return both Bit 6 in
Status Register 0 and Bit 7 in Status Register 1 set. The program should ignore
this errormessage.
The CPC doesn't support floppy DMA transfers, and the FDCs Interrupt signal
isn't used in the CPC also.
Usually single sided 40 Track 3" disk drives are used in CPCs, whereas 40
tracks is the official specification, practically 42 tracks could be used. The
FDC controller can be used to control 80 tracks, and/or double sided drives
also, even though AMSDOS isn't supporting such formats. AMSDOS is supporting a
maximum of two disk drives only.
Spectrum Disc Opus Discovery
---------------------------MEM:0008h,0048h,1708h - Discovery - Enable external ROM/RAM/WD/PIA
MEM:1748h - Discovery - Disable external ROM/RAM/WD/PIA
Opcode fetches from these addresses enable/disable the Discovery hardware, when
enabled, the following is mapped to first 16K of memory:
0000-1FFF ROM (8K)
2000-27FF RAM (2K)
2800-2803 WD 1770 Ports (floppy controller)
3000-3003 PIA 6821 Ports (drive/side select, centronics etc.)
DRQ (Data Request)
The DRQ output from WD 1770 is inverted and connected to /NMI input (unlike as
most other drives which map DRQ to a status register bit, and which use /NMI as
snapshot button).
MEM:2800h - FDC Command (W)
MEM:2800h - FDC Status (R)
MEM:2801h - FDC Track (R/W)
MEM:2802h - FDC Sector (R/W)
MEM:2803h - FDC Data (R/W)
--> Spectrum Disc Controller (Western Digital WD177x)
MEM:3000h when CRA.Bit2=1 - PIA Peripheral Interface A (PA0..7)
MEM:3000h when CRA.Bit2=0 - PIA Data Direction Reg. A (0=Input, 1=Output)
MEM:3001h - PIA Control Register A (CRA)
MEM:3002h when CRB.Bit2=1 - PIA Peripheral Interface B (PA0..7)
MEM:3002h when CRB.Bit2=0 - PIA Data Direction Reg. B (0=Input, 1=Output)
MEM:3003h - PIA Control Register B (CRB)
The PIA 6821 lines are connected as such:
PA0
drive 2 select (and enable motors for both drives)
PA1
drive 1 select (and enable motors for both drives)
PA4
side select
PA5
double density enable
PA6
centronics busy (input)
PA7
enable kempston joystick port on A5=0 (from BASIC: type FORMAT "j";1)
PB0..7 centronics data
CA2
centronics ack
CB2
centronics strobe

The PA2,PA3,CA1,CB1,/IRQA,/IRQB pins are not used.


PIA Control Register A (CRA)
0
CA1 Input Control (0..3)
0 = Set IRQA1 when CA1=Negative, but do not trigger /IRQA
1 = Set IRQA1 when CA1=Negative, and do trigger /IRQA
2 = Set IRQA1 when CA1=Positive, but do not trigger /IRQA
3 = Set IRQA1 when CA1=Positive, and do trigger /IRQA
2
DDRA Access (0=Data Direction Register A, 1=Data Register A)
3-5 CA2 Input/Output Control (0..7)
0 = Set IRQA2 when CA2=Negative, but do not trigger /IRQA
1 = Set IRQA2 when CA2=Negative, and do trigger /IRQA
2 = Set IRQA2 when CA2=Positive, but do not trigger /IRQA
3 = Set IRQA2 when CA2=Positive, and do trigger /IRQA
4 = Handshake Output Mode (CA2=High on CA1, CA2=Low on "Read A Data")
5 = Pulse Output Mode
(CA2=Low for 1 clk after "Read A Data")
6 = Manual Output, set CA2=Low
7 = Manual Output, set CA2=High
6
IRQA2 Flag (CA2 input)
7
IRQA1 Flag (CA1 input)
PIA Control Register B (CRB)
Same as CRA, but using Port B, CB1, CB2, IRQB, etc. And, CRB handshake/pulse
modes are bound to "Write B Data" instead of "Read A Data" conditions.
IO:1Fh - Discovery Joystick Port (uses A5 only, eg. mirrored to DFh)
0-4 Kempston Joystick (disabled by default)
5-7 Not used
Unlike normal kempston joystick ports this port is disabled by default
(presumably for best compatibility with other hardware that uses Port 1Fh, or
mirrors like DFh, for something else). The port can be enabled via PA7 bit, or
by typing FORMAT "j";1 in BASIC (type ;0 to disable it again).
PIA
1
2
3
4
5

6821 Pin-Outs
VSS
6 PA4
11 PB1
PA0
7 PA5
12 PB2
PA1
8 PA6
13 PB3
PA2
9 PA7
14 PB4
PA3
10 PB0 15 PB5

16
17
18
19
20

PB6
PB7
CB1
CB2
VCC

21
22
23
24
25

R/W
CS0
/CS2
CS1
PHI2

26
27
28
29
30

D7
D6
D5
D4
D3

31
32
33
34
35

D2
D1
D0
/RES
RS0(A0)

36
37
38
39
40

RS1(A1)
/IRQB
/IRQA
CA2
CA1

DOS Replacement for Opus Discovery


The MegaSoft QuickDOS package consists of a disc, manual, and replacement ROM
which contains faster load/save routines than the original Opus ROM.
Spectrum Disc Disciple and Plus D
--------------------------------The Disciple and PlusD are both developed by Miles Gordon Technology, both
contain 16K ROM, 8K RAM, a Snapshot/NMI button (works only when SHIFT held
down?), a Western Digital disk controller, and a centronics port (although
using different I/O addresses).
The older Disciple (1987) does additionally contain Joystick and Network ports,
and a feature to swap ROM and RAM addresses, and a Inhibit button (to lock out
the interface). The newer PlusD (1988) does not include these extras (so the
"Plus D" is actually a "Disciple Minus Extras").
1Bh/E3h Disciple/PlusD - FDC
1Bh/E3h Disciple/PlusD - FDC
5Bh/EBh Disciple/PlusD - FDC
9Bh/F3h Disciple/PlusD - FDC
DBh/FBh Disciple/PlusD - FDC
--> Spectrum Disc Controller

Command (W)
Status (R)
Track (R/W)
Sector (R/W)
Data (R/W)
(Western Digital WD177x)

EFh PlusD only - PlusD Control Register (W)


0
Drive A Select
1
Drive B Select
2
Single/double density
3
ROM bank select (first/second 8K of total 16K ROM)
4
Not used
5
Ext. select (?)
6
Centronics Strobe
7
Side select
1Fh Disciple only - Disciple Control Register (W)
0
Drive select
1
Side select
2
Single/double density
3
ROM bank select (first/second 8K of total 16K ROM)
4
Inhibit switch control
5
Ext. select (?)

6
7

Centronics Strobe
Network Data Output (0=0V, 1=5V)

1Fh Disciple only - Disciple Joystick 2 aka Kempston, and Printer/Network (R)
0-4 Kempston Joystick Port (also mapped to Port F7FEh)
5
Not used
6
Centronics Busy
7
Network Data Input (0=0V, 1=5V)
3Bh Disciple only - Network Wait when Network Input is 1=5V (R or W ?)
Port 3Bh is used for network synchronization (same as bit 5 of Interface
One's port EFh). Any OUT to port 3Bh will halt the Spectrum until the
logic level on the network is 0. It is used to wait for the start bit
of a transmission frame.
The network bus carries TTL logic levels (0 = 0 Volts, 1 = 5 Volts).
The bit rate is 87.5 Kbps and data is exchanged in packets of max 256
bytes using a simple data-link level protocol.
Network is an Interface 1 compatible net.
F7FEh Disciple only - Disciple Joystick 1 aka Sinclair Joystick 2 (R)
EFFEh Disciple only - Disciple Joystick 2 aka Sinclair Joystick 1 (R)
These are standard Sinclair joystick ports (although numbered in opposite
order, otherwise same as in Interface 2 and Spectrum +2/+2A/+3). Disciple
Joystick 1 aka Sinclair Joystick 2 is also mapped to Port 1Fh.
FBh/F7h Disciple/PlusD - Centronics Data (W)
0-7 Printer Data
F7h PlusD Only - Centronics Busy (R)
0-6 Not used
7
Printer Busy
BBh/E7h Disciple/PlusD - Enable Internal ROM/RAM (R)
BBh/E7h Disciple/PlusD - Disable Internal ROM/RAM (W)
MEM:0000h,0008h,0066h,028Eh - Enable Internal ROM/RAM (R)
Reading/Writing from these Ports (or opcode fetches from MEM addresses)
enables/disables the internal ROM/RAM (instead of the Spectrum BIOS).
In the PlusD, the ROM is always at 0000h-1FFFh, and RAM at 2000h-3FFFh. In the
Disciple it is the same on reset, but can be changed via Port 7Bh.
7Bh Disciple only - Map ROM at 0000h, RAM at 2000h (R) (default on Boot)
7Bh Disciple only - Map ROM at 2000h, RAM at 0000h (W) (default in GDOS)
Allows to swap ROM and RAM locations.
DOS versions
GDOS
--> Built-in in Disciple
G+DOS
--> Built-in in PlusD
Beta DOS
--> Third-party DOS Replacement for PlusD
UniDOS
--> Third-party DOS Replacement for PlusD and Disciple
Beta DOS (from Beta Soft / Andy Wright) is an alternate DOS for the Plus D
(from MGT), it doesn't have anything to do with the "Beta Disk Interface" (from
Technology Research). Beta DOS boots from diskette (it doesn't seem to require
a ROM replacement).
UniDOS is another DOS replacement that can be used on both Disciple and PlusD,
it consists of a software diskette and a replacement ROM (there are two ROM
versions, one for PlusD, and one for Disciple).
Spectrum Disc Beta/BetaPlus/Beta128 Disk Interface (TRDOS)
---------------------------------------------------------The Beta (1984), Beta Plus (1985), and Beta 128 (1987) Disk Interfaces with
TRDOS ROM were developed by Technology Research and may have been more or less
popular in Europe.
In Russia, it became the standard disk interface (even more popular than
cassettes), the Beta I/O addresses, and TRDOS ROM were used in Spectrum clones
like Pentagon (1989) and Scorpion.
Versions
Interface
Beta
Beta Plus
Beta 128
Pentagon

Year
1984
1985
1986
1989

TRDOS
v1
v4
v5.0x
v5.0x

Description
original version
auto-boot, drive-detect, magic-button, seq/rnd access
changed USR addresses, auto-boot-disable-switch
russian spectrum clone with beta 128 disk interface

Features
The Interface is quite simple, it consists of the TRDOS ROM, the FDC chip, and
eventually a Magic button and/or Reset button. It doesn't include RAM, nor any
extras like Centronics or Joystick ports.
Since there's no built-in RAM, it allocates 70h bytes at 5CB6h (or at higher
address if other hardware like Interface 1 has already allocated memory).

Additionally, it does temporarily allocate a 100h bytes as sector buffer while


accessing the disk.
MEM:3C00h..3CFFh - Enable ROM & I/O Ports (Beta/TRDOSv1 and BetaPlus/TRDOSv4)
MEM:3D00h..3DFFh - Enable ROM & I/O Ports (Beta128/TRDOSv5.0x)
The enable region was originally at 3Cxxh (which is FFh-filled in Spectrum
16K/48K/Plus BIOSes), and was invoked via RANDOMIZE USR 15360 and 15363 from
BASIC. For compatibility with the Spectrum 128 (which contains BIOS code in
that region), the region was moved to 3Dxxh (which contains only character set
data, but no program code) and is now invoked via USR 15616 and 15619. The
first address is used to enter TRDOS,
RANDOMIZE USR 15360 or 15616 --> switch from BASIC to TRDOS ;3C00h/3D00h
RETURN (aka Y-key)
--> switch from TRDOS to BASIC
The second address is used as prefix to normal BASIC commands, eg.:
RANDOMIZE USR 15363 or 15619:REM:LOAD"filename"
;3C03h/3D03h
MEM:4000h..FFFFh - Disable ROM & I/O Ports (all versions)
Opcode fetches outside of the ROM region (ie. at 4000h..FFFFh) do automatically
disable the TRDOS ROM and I/O ports.
MEM:0000h? - Enable ROM & I/O Ports (BetaPlus/TRDOSv4 and Beta128/TRDOSv5.0x)
The Beta Plus and Beta 128 have an Auto-Boot feature that automatically enters
TRDOS instead of BASIC on power-up. Unknown which opcode address activates
TRDOS... probably 0000h.
The Auto-Boot feature works only on Spectrum 48K/Plus, but isn't compatible
with the Spectrum 128 (the Beta 128 includes a "system switch" that allows to
disable auto-boot for Spectrum 128 compatibility, ie. on the Spectrum 128 TRDOS
can be started only manually via RANDOMIZE USR 15616).
MEM:0066h? - Enable ROM & I/O Ports (BetaPlus/TRDOSv4 and Beta128/TRDOSv5.0x)
The Beta Plus and Beta 128 have a Magic button, presumably triggering an /NMI
and thus needing to enable ROM on address 0066h (?) although in poor quality
schematics it looks more like /RESET than /NMI. The button does usually allow
to save snapshots (except, on the Scorpion, it launches a Service-Monitor
program).
I/O Port Activation
Below I/O ports are enabled only while the ROM is enabled, too. Ie. when
disabled, there's no conflict with Kempston Joysticks (Port 1Fh) or with the
VRAM Garbage effect (Port FFh). Mind that ROM and I/O ports are automatically
disabled when accessing opcodes at 4000h..FFFFh (so the I/O ports can be
accessed ONLY from inside of the TRDOS ROM).
1Fh - Beta Disk FDC Command (W)
1Fh - Beta Disk FDC Status (R)
3Fh - Beta Disk FDC Track (R/W)
5Fh - Beta Disk FDC Sector (R/W)
7Fh - Beta Disk FDC Data (R/W)
--> Spectrum Disc Controller (Western Digital WD177x)
According to some untitled schematics, the interface uses a FD1793-02 chip
(which is maybe correct), according to Sinclair User magazine it uses a 1771
chip (such a thing probably doesn't exist at all), according to russian source
it uses a KR1818VG93 aka VG93 chip (which is probably a 1793 clone).
FFh 0-5
6
7

Beta Disk Status (R)


Unused?
DRQ (data request)
INTRQ (command completion)

FFh 0-1
2
3
4
5
6-7

Beta Disk Control (W?)


Drive select (0..3 = Drive A..D)
Hardware microcontroller reset (0=reset, 1=normal)
Blocks signal HLT of microcontroller (=disk controller?) (1=normal)
Head select (0=First/bottom, 1=Second/Top)
Density select (0=FM, 1=MFM)
Unused

Spectrum Disc Controller (Western Digital WD177x)


------------------------------------------------Command description
Commands should only be loaded in the Command Register when the Busy status bit
is off (Status bit 0). The one exception is the Force Interrupt command.
Whenever a command is being executed, the Busy status bit is set.
At the completion of every command an INTRQ is generated. INTRQ is reset by
either reading the status register or by loading the command register with a
new command. In addition, INTRQ is generated if a Force Interrupt command
condition is met.
When a command is completed, an interrupt is generated and the busy status bit
is reset. The Status Register indicates whether the completed command

encountered an error or was fault free.


Command Summary (models 1791, 1792, 1793, 1794)
Type Command
b7 b6 b5 b4 b3
b2
I
Restore
0
0
0
0
h/M V
I
Seek
0
0
0
1
h/M V
I
Step
0
0
1
T
h/M V
I
Step-In
0
1
0
T
h/M V
I
Step-Out
0
1
1
T
h/M V
II
Read Sector
1
0
0
m
S/M E
II
Write Sector
1
0
1
m
S/M E
III Read Address
1
1
0
0
0/M E
III Read Track
1
1
1
0
0/M E
III Write Track
1
1
1
1
0/M E
IV
Force Interrupt 1
1
0
1
i3
i2

(and
b1
r1
r1
r1
r1
r1
C/0
C/P
0
0
0/P
i1

1770,1772,1773)
b0
r0
r0
r0
r0
r0
0
a0
0
0
0
i0

Flag Summary
r1,r0 Stepping Motor Rate (0..3 = 6ms,12ms,20ms,30ms) (WD179X,WD1770/WD1773)
r1,r0 Stepping Motor Rate (0..3 = 2ms,3ms,5ms,6ms) (WD1772 Preliminary docs)
r1,r0 Stepping Motor Rate (0..3 = 6ms,12ms,2ms,3ms) (WD1772 Other docs... ?)
V
Track Number Verify Flag (0: no verify, 1: verify on dest track)
h
Head Load Flag (1: load head at beginning, 0: unload head) (WD179X)
T
Track Update Flag (0: no update, 1: update Track Register)
a0
Data Address Mark (0: FB, 1: F8 (deleted DAM))
C
Side Compare Flag (0: disable, 1: enable) (WD179X only) (and WD1773?)
E
15 ms delay (0: no 15ms delay, 1: 15 ms delay)
S
Side Compare Flag (0: compare for side 0, 1: compare for side 1)
m
Multiple Record Flag (0: single record, 1: multiple records)
P
Write Precompensation (0=On, 1=Off) (WD1770/WD1772 only) (and WD1773?)
M
Motor On (0=on, 1=off)
(WD1770/WD1772 only)
Interrupt Condition Flags
i3-i0 0 = Terminate with no interrupt (INTRQ)
i3
1 = Immediate interrupt, requires a reset
i2
1 = Index pulse
i1
1 = Ready to not ready transition (Not used on WD1770/WD1772)
i0
1 = Not ready to ready transition (Not used on WD1770/WD1772)
Type I commands (Restore, Seek, Step-Out, Step-In, Step)
Used to move the read/write head. The stepping motor rate should be usally set
to 6ms (r1 and r0 bits set to zero) for a 3.5-inch floppy disk drive. An
optional verification of head position can be performed by setting bit 2 (V=1)
in the command word.
When V=1: When the seek is completed, the drive automatically goes into read
mode, the track number from the first encountered Sector ID Field is then
compared against the contents of the Track Register (or Data Register?), if the
track numbers compare (and the ID Field CRC is correct) the verify operation is
complete and an INTRQ is generated with no errors. If these track numbers do
not match, the Seek Error bit of the status register is set.
When V=0: When the seek is completed, the track position is not verified (this
mode is required for unformatted disks). The command ends once the last step
pulse is output. Since the result is that there is not enough time for step
stability, the host system must use its software to make the floppy disk wait a
certain period before reading or writing the track just arrived at.
When the seek command is complete, the interrupt request is set and at the same
time, the Busy bit in the status register is set to 0. When the CPU reads the
status register, it resets the interrupt request signal.
Restore (Seek Track 0)
If TR00 is not active, stepping pulses are issued until the TR00 input is
activated. The Track Register is set to zero, and an interrupt is generated
when track 0 has been reached.
Seek
This command assumes that the Track Register contains the <current> position of
the head, and that the Data Register contains the <desired> destination track
number. The FD179X will update the Track Register and issue stepping pulses in
the appropriate direction until the contents of the Track and Data Register are
equal to each other. An interrupt is generated at the completion of the
command.
Step-Out, Step-In, Step
Issues one stepping pulse to the disk drive. Step-Out: towards track 0.
Step-In: towards track 76 (that feature is not useful for 80-track drives).
Step: same direction as for previous step command. The track register is
updated (ie. incremented or decremented) only if the "T" bit has been set in
the command word. An interrupt is generated at the end of each command.

Type II commands (Read Sector, Write Sector)


Prior to loading the Type II command into the Command Register, the computer
must load the Sector Register with the desired sector number. Upon receipt of
the Type II command, the busy status bit is set. The FD179X must find an ID
field with a matching Track number and Sector number, otherwise the Record not
found status bit is set and the command is terminated with an interrupt.
Each of the Type II commands contains an m flag which determines if multiple
records (sectors) are to be read or written. If m=0, a single sector is read or
written and an interrupt is generated at the completion of the command. If m=1,
multiple records are read or written with the sector register internally
updated so that an address verification can occur on the next record. The
FD179X will continue to read or write multiple records and update the sector
register in numerical ascending sequence until the sector register exceeds the
number of sectors on the track or until the Force Interrupt command is loaded
into the Command Register.
The Type II commands for 1791-94 also contain side select compare flags. When
C=0 (bit 1), no comparison is made. When C=1, the LSB of the side number is
read off the ID Field of the disk and compared with the contents of the S flag.
Read Sector
Upon receipt of the command, the head is loaded, the busy status bit set and
when an ID field is encountered that has the correct track number, correct
sector number, correct side number, and correct CRC, the data field is
presented to the computer.
An DRQ is generated each time when the CPU must read a byte from the data
register, the Lost Data bit is set if the CPU didn't read data in time, and the
Read operation continues until the end of sector is reached.
At the end of the Read operation, the type of Data Address Mark encountered in
the data field is recorded in the Status Register (bit 5).
Write Sector
Upon receipt of the command, the head is loaded, the busy status bit set and
when an ID field is encountered that has the correct track number, correct
sector number, correct side number, and correct CRC, a DRQ is generated.
The FD179X counts off 22 bytes (in double density) from the CRC field and the
Write Gate output is made active if the DRQ is serviced (ie. the DR has been
loaded by the computer). If DRQ has not been serviced, the command is
terminated and the Lost Data status bit is set. If the DRQ has been serviced,
12 bytes of zeroes (in double density) are written to the disk, then the Data
Address Mark as determined by the a0 field of the command.
The FD179X then writes the data field and generates DRQ's to the computer. If
the DRQ is not serviced in time for continuous writing the Lost Data Status bit
is set and a byte of zeroes is written on the disk and the command continues
until the last byte of the sector is reached.
After the last data byte has been written on the disk, the two-byte CRC is
computed internally and written on the disk followed by one byte of logic ones.
Type III commands
Read Address
Upon receipt of the Read Address command, the head is loaded and the Busy
Status bit is set. The next encountered ID field is then read in from the disk,
and the six data bytes of the ID field are assembled and transferred to the DR,
and a DRQ is generated for each byte. The six bytes of the ID field are : Track
address, Side number, Sector address, Sector Length, CRC1, CRC2. Although the
CRC bytes are transferred to the computer, the FD179X checks for validity and
the CRC error status bit is set if there is a CRC error. The track address of
the ID field is written into the sector register so that a comparison can be
made by the user. At the end of the operation, an interrupt is generated and
the Busy status bit is reset.
Read Track
Upon receipt of the Read Track command, the head is loaded, and the busy status
bit is set. Reading starts with the leading edge of the first encountered index
pulse and continues until the next index pulse. All gap, header, and data bytes
are assembled and transferred to the data register and DRQ's are generated for
each byte. The accumulation of bytes is synchronized to each address mark
encountered. An interrupt is generated at the completion of the command. The ID
Address Mark, ID field, ID CRC bytes, DAM, Data and Data CRC bytes for each
sector will be correct. The gap bytes may be read incorrectly during
write-splice time because of synchronization.
Write Track (formatting a track)
Upon receipt of the Write Track command, the head is loaded and the Busy Status
bit is set. Writing starts with the leading edge of the first encountered index
pulse and continues until the next index pulse, at which time the interrupt is
activated. The Data Request is activated immediately upon receiving the
command, but writing will not start until after the first byte has been loaded
into the DR. If the DR has not been loaded by the time the index pulse is
encountered, the operation is terminated making the device Not Busy, the Lost

Data status bit is set, and the interrupt is activated. If a byte is not
present in the DR when needed, a byte of zeroes is substituted. This sequence
continues from one index mark to the next index mark.
Normally, whatever data pattern appears in the data register is written on the
disk with a normal clock pattern. However, if the FD179X detects a data pattern
of F5 thru FE in the data register, this is interpreted as data address marks
with missing clocks or CRC generation. The CRC generator is initialized when an
F5 data byte is about to be transferred (in MFM). An F7 pattern will generate
two CRC bytes. As a consequence, the patterns F5 thru FE must not appear in the
gaps, data fiels, or ID fiels. Tracks may be formatted with sector lengths of
128, 256, 512 or 1024 bytes. See "Formatting" below for more info and example.
Type IV command (Force Interrupt)
The Forced Interrupt command is generally used to terminate a multiple sector
read or write command or insure Type I status register. This command can be
loaded into the command register at any time. If there is a current command
under execution (busy status bit set), the command will be terminated and the
busy status bit reset.
Status Register
Upon receipt of any command, except the Force Interrupt command, the Busy
Status bit is set and the rest of the status bits are updated or cleared for
the new command.
The user has the option of reading the status register through program control
or using the DRQ line with DMA or interrupt methods. When the DR is read the
DRQ bit in the Status register and the DRQ line are automatically reset. A
write to the DR also causes both DRQ's to reset. The busy bit in the status may
be monitored with a user program to determine when a command is complete, in
lieu of using the INTRQ line. When using the INTRQ, a busy status check is not
recommended because a read of the status register to determine the condition of
busy will reset the INTRQ line.
Status for Type I commands
Bit Expl.
0
Busy
(1=Command is in progress)
1
Index
(1=Index mark detected from drive)
2
Track 0
(1=Read/Write head is positioned to Track 0)
3
CRC Error
(1=CRC encountered in ID field)
4
Seek Error
(1=Desired track was not verified) (reset 0 when updated)
5
Head Loaded (1=Head loaded an engaged) (WD1770/WD1772: Spin-up ready)
6
Protected
(1=Disk write protected)
7
Not Ready
(1=Drive not ready)
(WD1770/WD1772: Motor On)
Status for type II
Bit Expl.
0
Busy
1
Data Request
2
Lost Data
3-4 Error Code
5
Fault/Type
6
Protected
7
Not Ready
Notes: Bit 1-6 are

& III commands


(1=Command is under execution)
(1=CPU must read/write next data byte) (DRQ)
(1=CPU did not respond to DRQ in one byte time)
(1=Bad Data CRC, 2=Sector not found, 3=Bad ID Field CRC)
(Any Write:1=Write Fault, Read Sector:1=Deleted Data Mark)
(Any Write:1=Write Protect, Any Read:Not used)
(1=Drive not ready)
(WD1770/WD1772: Motor On)
reset when updated. Bit 3-4 not used for read/write track.

Status for type IV command


If the Force Interrupt command is received while a command is under execution,
the Busy status bit is reset and the rest of the status bits are unchanged.
If the Force Interrupt command is received when there is no command under
execution, the Busy Status bit is reset and the rest of the status bits are
updated or cleared. In this case, Status reflects the Type I commands.
External Circuit
The floppy disk controller itself cannot select the drive number, side, disk
density, and it cannot turn on/off the drive motor(s). These settings must be
set up by an external circuit, which are (as far as they aren't set to a fixed
setting) controlled through separate I/O addresses. For details have a look at
the MSX FDC I/O addresses.
Note that the FDC contains only one track register which is used for all
drives. The current track position for each drive should be backed up in
memory, and the track register should be updated each time when changing the
current drive number.
The external circuit might also use the INTRQ and DRQ lines to handle FDC
operations by DMA transfers, and/or to produce interrupts upon completion. In
the MSX these methods are not used, however, most MSX adapters allow to read
out the state of INTRQ and DRQ from a custom I/O address (this isn't actually
required because INTRQ is just a inverted copy of the Status Busy bit, and DRQ
can be read out from the normal Status register either.

Formatting
This table shows DATA PATTERNs and their FD179X interpretation in MFM.
00-F4
Write 00 thru F4
F5
Write A1, preset CRC
F6
Write C2
F7
Generate 2 CRC bytes
F8-FF
Write F8 thru FF
Formatting Example
The example below shows the data stream that must be presented to the Write
Track command for the "IBM system 34 format" (256 bytes/sector), note that the
MSX usually uses 512 bytes/sector. The left values in the tables below identify
the write-repeat count (in decimal) for the values to the right. First the
Track Header must be written, followed by Sector ID and Sector Data Fields (for
each sector). Finally 4E bytes must be written until the command has completed.
Track Header
80 x 4E
12 x 00
3 x F6 (writes C2)
1 x FC (index mark)
50 x 4E
1st Sector ID Field
12 x 00
3 x F5 (writes A1, preset CRC)
1 x FE (ID address mark)
1 x Track number
1 x Side number
1 x Sector number
1 x 01 (sector length=256)
1 x F7 (write 2 CRC bytes)
22 x 4E
1st Sector Data Field
12 x 00
3 x F5 (writes A1, preset CRC)
1 x FB (data address mark)
256 x DATA
1 x F7 (write 2 CRC bytes)
54 x 4E
2nd Sector ID Field (as above)
2nd Sector Data Field (as above)
etc.
Track End (Fill unused bytes)
.. x 4E (padding until index hole interrupt)
Spectrum Disc Controller (Other)
-------------------------------Challenge Research Ltd: Challenge Sprint and Sprint Mk II
This is a quad-speed "audio" cassette drive, it connects to the expansion port,
apparently spins faster than normal cassette drives, and works with existing
cassette software (that was recorded at slow speed). The included BIOS replaces
the normal cassette functions by faster functions, works only with software
that uses the BIOS functions, eg. not with copyprotected games.
Evesham Micro Centre: Doubler Mk I / Double Mk II
External input for 2nd tape drive, for tape-to-tape transfers. The included
software executes an endless loop that forwards input from the Double I/O port
to the normal ULA cassette port.
Version Hardware
Software
Mk I : Port BFh, Bit0
I.R.Lavell (quite efficently coded)
Mk II : Port 1Fh, Bit3
Draysoft (less efficiently coded)
The Mk II version is advertised to be more compatible with different tape
decks.
Sinclair: Microdrive (endless tape drive)
Rotronics Wafadrive (endless tape drive) (not Microdrive compatible)
These are tape-drives, so, obviously, they don't use standard floppy disk
controllers.
Unlike normal cassette recorders, these drives can seek files (or free space)
automatically (without needing to press any play/stop/forward buttons), ie.
they do have a disk-like filesystem, however, they must wind the tape until it
reaches the desired location, so the seek-time is relative slow. Wafadrive
cartridges are manufactured with 16K, 64K, 128K capacity (of which 16K has the
shortest tape, and therefore fastest seek-time).
Crescent Quick Disk (2.8" disk, with single spiral-track, 128K or 256K)
Triton Quick Disk (2.8" disk, with single spiral-track, 100K)
Quick Disks (also used by Nintendo's Famicom Disk System) have only a single
spiral-shaped track (like CDROMs and music records), so, obviously, they don't

use standard floppy disk controllers.


Note: Quick Disk drives don't have a stepping motor for random access, instead
the head is following the spiral windings in sequential access fashion (giving
it a relative slow seek-time; similar to endless tape drives).
Timex FDD and FDD-3000
These drives are using standard a Western Digital controller, but, the
controller is connected to a separate Z80 CPU. So the spectrum is communicating
with that external Z80 CPU rather than directly with the WD chip.
Logitek: Disc Interface (connect a Commodore 1541 drive to spectrum)
An adaptor for communicating with Commodore 1541 drive (the standard disk drive
for the C64) via serial data cable. The 1541 doesn't contain any standard disk
controller (it consists of a 6502 CPU and a bunch of TTL logic). Although the
drive uses standard 5.25" disks, the sector encoding isn't compatible with that
used by Western Digital WD177x and NEC uPD765 disk controllers.
Spectrum CD Games Pack (Code Masters) (1989)
The pack consists of a Audio CD with about 30 spectrum games (each one recorded
twice), and a connection cable (cd player's 3.5mm (or 6.3mm via adapter) stereo
headphone socket to spectrum 9pin DSUB joystick port) (for Spectrum 128/+2/+3
or 48K with Kempston interface), and loading software on tape, once when a game
is loaded one can press Q,U,I,T on keyboard to load a new game (without needing
to load tape loader again).
No info if/how the stereo signal is used (maybe one channel used as CLOCK, and
the other channel as DATA...?) The cable does reportedly contain a 1bit A/D
converter, which is probably a single transistor or so (so it's mono, not
stereo?). The CD capacity is said to be "12 Megs" (presumably meaning 12
Megabit = 60 tracks with 25Kbytes each).
Unknown Controllers
For most spectrum disk interfaces it is still unknown if they do contain a
standard disk controller chip, and if so, which one (the WD177x chips seem to
be quite popular in the spectrum world, so many of the unknown interfaces are
probably using that chips, too).
Spectrum Interrupts
-----------------The IRQ is triggered on each vsync.
With IM1 opcode, the interrupt handler is at 0038h in BIOS ROM.
With IM2 opcode, the interrupt handler is at [I*100h+databus].
IRQ (IM1)
The normal IM1 handler does solely execute in ROM (without redirecting to a RAM
vector), so, since ROM is read-only, the IM1 vector cannot be hooked (unless by
external hardware that replaces the BIOS by other data, as done in the Currah
uSpeech).
To wait for an interrupt, one can use the HALT opcode, and/or check if the
FRAMES system variable has changed.
IRQ (IM2)
This mode allows to use a custom IRQ handler at [I*100h+databus]. Because of
the Display Snow bug, the table may not be at 4000h..7FFFh.
Normally [I*100h+databus] would be table in RAM at 8000h..FFFFh, however, some
games have it in ROM: Spectrum 48K has [3B00h..3C00h]=FFh, and Spectrum 128 and
up have [3BFFh..3C00h]=FFh filled, the handler is then at FFFFh, which would be
usually set to 18h (a JR opcode) whose parameter byte is read from address
0000h in BIOS, which is F3h (a DI opcode), thus forming a JR FFF4h opcode.
Assuming that the databus contains a "random" number in range of 00h..FFh upon
IRQs, it requires a table with 101h bytes at [I*100h+0..100h]. On the Spectrum
128 and up the databus seems to be stable FFh, needing only a 2 bytes at
[I*100h+FFh..100h].
External IRQ
The /IRQ signal is available on the expansion port, eventually allowing
external hardware to sense when vblanks occur, or allowing external hardware to
inject additional IRQs (done by the AMX Mouse in IM2), though it's problematic
to distingush external IRQs from normal vblank IRQs, especially if they occur
simultaneously.
External NMI
The NMI handler is at 0066h in BIOS. On the Spectrum 16K/48K/+/128/+2, and on
Timex TC2048/TC2068/TS2068, the BIOS handler does (accidently) do this:
IF [5CB0h]=0000h then JMP [5CB0h]
;ie. jump to 0000h (bullshit)
On the Spectrum +2A/+3, the bug was fixed, and it does:
IF [5CB0h]<>0000h then JMP [5CB0h]
A couple of disk-interfaces are hooking address 0066h (or address 0000h, which
can be easier decoded and which works too, due to the bug, except in the
bug-fixed Spectrum +2A/+3 versions), the most common use is a Snapshot

function, allowing to load/save the entire RAM to/from disk (useful because
most spectrum programs support only cassette loading/saving). Some disk
interfaces are using NMI to handle data requests (not so useful as that could
be also done without NMIs).
Spectrum Keyboards
-------------------> Spectrum Keyboard Assignment
Keyboard Matrix
Port
Bit4
FEFEh A8
V
FDFEh A9
G
FBFEh A10
T
F7FEh A11
5
EFFEh A12
6
DFFEh A13
Y
BFFEh A14
H
7FFEh A15
B

Bit3
C
F
R
4
7
U
J
N

Bit2
X
D
E
3
8
I
K
M

Bit1
Z
S
W
2
9
O
L
SYM

Bit0
SHIFT
A
Q
1
0
P
ENTER
SPACE

40-key Spectrum Keyboard (like ZX80/ZX81, but with SYM instead DOT)
| 1
2
3
4
5
6
7
8
9
0
|
| Q
W
E
R
T
Y
U
I
O
P
|
|
A
S
D
F
G
H
J
K
L ENTER|
|SHF Z
X
C
V
B
N
M
SYM
SPACE|
42-key TC2048/TS2068 Keyboard
| 1
2
3
4
5
6
7
8
9
0
|
| Q
W
E
R
T
Y
U
I
O
P
|
|
A
S
D
F
G
H
J
K
L ENTER|
|SHF Z
X
C
V
B
N
M
SYM BRK SHF|
|
[---------SPACE---------]
|
The two SHIFT keys are probably the same in the matrix, and BRK is probably
just SHIFT+SPC or so, so the matrix has only 40 keys.
58-key Spectrum +/128/+2/+3 Keyboard, and 18-key Spectrum 128 Keypad
|TRUE INV 1
2
3
4
5
6
7
8
9
0 ESC|
| /
*
( ) |
|DEL TAB
Q
W
E
R
T
Y
U
I
O
P
|
| 7
8
9 - |
|EXT COPY
A
S
D
F
G
H
J
K
L
RET|
| 4
5
6 + |
|SHIFT CAPS
Z
X
C
V
B
N
M
.
SHIFT|
| 1
2
3 RET|
|SYM ; " LEFT RIGHT
SPACE
UP DOWN , SYM|
|
0
.
|
In 48K mode: TAB=GRAPH, COPY=EDIT.
Concerning the keyboard matrix, the keyboard has only 40 real keys, plus two
duplicated SHIFT/SYM keys, plus 16 keys with SHIFT/SYM+key combinations (eg.
UP=SHIFT+7).
The external 18-key numeric keypad can be connected via a special serial cable,
it was shipped only with early Spectrum 128 models in Spain, but soon
discontinued.
Spectrum Keyboard Assignment
---------------------------Spectrum
NORMAL
1
2
3
4
5
6
7
8
9
0
q
w
e
r
t
y
u
i
o
p
a
s
d
f
g

SHIFT
EDIT
CAPS
TRUE_V
INV_V
LEFT
DOWN
UP
RIGHT
GRAPH
DELETE
Q
W
E
R
T
Y
U
I
O
P
A
S
D
F
G

CMD
1
2
3
4
5
6
7
8
9
0
PLOT
DRAW
REM
RUN
RAND
RETURN
IF
INPUT
POKE
PRINT
NEW
SAVE
DIM
FOR
GOTO

SYMBOL
!
@
#
$
%
&
'
(
)
_
<=
<>
>=
<
>
AND
OR
AT
;
"
STOP
NOT
STEP
TO
THEN

EXT
EXT+SYM
P=BLUE
DEF FN
P=RED
FN
P=MAGENT.LINE
P=GREEN OPEN#
P=CYAN
CLOSE#
P=YELLOW MOVE
P=WHITE ERASE
(BRIGHT) POINT
(DARK)
CAT
P=BLACK FORMAT
SIN
ASN
COS
ACS
TAN
ATN
INT
VERIFY
RND
MERGE
STR$
[
CHR$
]
CODE
IN
PEEK
OUT
TAB
RESET (C)
READ
FREE
~
RESTORE STICK |
DATA
\
\
SGN
ON_ERR {
ABS
SOUND }

EXT+SHIFT
I=BLUE
I=RED
I=MAGENT.
I=GREEN
I=CYAN
I=YELLOW
I=WHITE
FLASH=OFF
FLASH=ON
I=BLACK
ASN
ACS
ATN
VERIFY
MERGE
[
]
IN
OUT
RESET (C)
FREE
~
STICK |
\
\
ON_ERR {
SOUND }

GRAPH
[ ']
[' ]
['']
[ .]
[ :]
['.]
[':]
[ ]
GRA=OFF
DELETE
USR.Q
INKEY$
USR.E
USR.R
USR.T
FN
USR.U
USR.I
USR.O
USR.P
USR.A
USR.S
USR.D
USR.F
USR.G

GRAPH+SHFT
[:.]
[.:]
[..]
[:']
[: ]
[.']
[. ]
[::]
GRA=OFF
DELETE
USR.Q
INKEY$
USR.E
USR.R
USR.T
FN
USR.U
USR.I
USR.O
USR.P
USR.A
USR.S
USR.D
USR.F
USR.G

h
j
k
l
ENTER
SHIFT
z
x
c
v
b
n
m
SYMBOL
SPACE

H
J
K
L
ENTER
SHIFT
Z
X
C
V
B
N
M
EXT=ON
SPACE

GOSUB
LOAD
LIST
LET
ENTER
SHIFT
COPY
CLEAR
CONT
CLS
BORDER
NEXT
PAUSE
SYMBOL
SPACE

^
+
=
ENTER
EXT=ON
:
pound
?
/
*
,
.
SYMBOL
SPACE

SQR
VAL
LEN
USR
ENTER
SHIFT
LN
EXP
LPRINT
LLIST
BIN
INKEY$
PI
SYMBOL
SPACE

CIRCLE
VAL$
SCREEN$
ATTR
ENTER
EXT=OFF
BEEP
INK
PAPER
FLASH
BRIGHT
OVER
INVERSE
SYMBOL
SPACE

CIRCLE
VAL$
SCREEN$
ATTR
ENTER
SHIFT
BEEP
INK
PAPER
FLASH
BRIGHT
OVER
INVERSE
EXT=OFF
SPACE

USR.H
USR.J
USR.K
USR.L
ENTER
SHIFT
POINT
PI
USR.C
RND
USR.B
USR.N
USR.M
SHIFT
SPACE

USR.H
USR.J
USR.K
USR.L
ENTER
SHIFT
POINT
PI
USR.C
RND
USR.B
USR.N
USR.M
EXT=ON
SPACE

Timex TS2068 and TC2068


The DELETE, RESET, FREE, STICK, ON_ERR, SOUND keywords exist on Timex TS2068
and TC2068 only. FREE/STICK are premanently mapped (not allowing to use "~" and
"|" on these computers). The other four commands are mapped only when the [K]
cursor is shown (to use the backspace function with [K] cursor: Keep Shift+1
held down for 2-3 seconds, the key-repeat does then act as backspace instead of
repeatedly showing up the DELETE keyword).
Spectrum 128/+2/+2A/+3
On the Spectrum 128/+2/+2A/+3 all keywords must be entered letter-by-letter
(ie. type P,L,O,T instead of pressing Q), letters and punctuation marks are
kept at the same locations as in the above table, the EDIT key shows the
options menu (which includes a RENUMBER function).
Spectrum Joystick Ports
----------------------Joystick Ports and Data Bits (U=Up, D=Down, L=Left, R=Right, F=Fire)
Port_Joystick_Type___________________________7_6_5_4_3_2_1_0___Data Bits___
xx1F Kempston (and Timex TC2048)
? ? ? F U D L R
(1=Pressed)
xx7F Fuller Box
F ? ? ? R L D U
(0=Pressed)
EFFE Protek (cursor mode, A12, keys 6,7,8,0) - - - D U R - F
(0=Pressed)
F7FE Protek (cursor mode, A11, key 5)
- - - L - - - (0=Pressed)
DFFE AGF
(2nd Joystick, A13, keys Y,U,I,P) - - - D U R - F
(0=Pressed)
FBFE AGF
(2nd Joystick, A10, key T)
- - - L - - - (0=Pressed)
EFFE Sinclair Port 1 (keys 6,7,8,9,0)
- - - L R D U F
(0=Pressed)
F7FE Sinclair Port 2 (keys 5,4,3,2,1)
- - - F U D R L
(0=Pressed)
E7FE Sinclair Garbage or Nothing
- - - x x x x x
(0=Pressed)
01F6 Timex TS2068/TC2068 PSG Reg 14, Port 1 F ? ? ? R L D U
(0=Pressed)
02F6 Timex TS2068/TC2068 PSG Reg 14, Port 2 F ? ? ? R L D U
(0=Pressed)
03F6 Timex TS2068/TC2068 PSG Reg 14, Both
F ? ? ? R L D U
(0=Pressed)
xxBF Timedata ZXM Sound Box, PSG Reg 14
0 F U D L R y x
(0=Pressed)
?
Rotronics Wafadrive Joystick Adaptor
? ? ? ? ? ? ? ?
(?=Select)
Recommended Controls
When making Spectrum software, best support ALL of the following controls:
6,7,8,9,0
--> Interprete as Sinclair Joystick Port 1
SHIFT+5,6,7,8,SPACE
--> Interprete as Cursor Keys (for use in emulators)
Q,A,O,P,SPACE
--> Interprete as Keyboard Keys
Port 1Fh
--> Interprete as Kempston Joystick Port
Kempston Port Notes
This is a quite popular standard, and should be supported by most games. There
are a lot of homebrew clones, including some released in magazines, many
variants are decoding only A5=0, ignoring A6 and A7. Some variants are using
the upper data bits (D5-D7) as centronics busy input, or as floppy interrupt or
data requests.
Sinclair Port Notes
Sinclair ports are supported by the Interface 2 adaptor, by the Disciple disk
interface, and are built-in in Spectrum +2/+3. The Sinclair joysticks are
equivalent to keyboard keys 1,2,3,4,5 (port2) and 6,7,8,9,0 (port1), both
keyboard groups are arranged as L,R,D,U,F (that keyboard arrangement is why the
data bits are in opposite order for port1 and port2) (note: the arrangement
does NOT comply with the cursor keys on keys 5,6,7,8). Reading both ports at
once doesn't work well: Interface 2 doesn't respond to reads from Port E7FEh,
Spectrum +2/+3 does respond to it (but, due to the reversed data bit
arrangement, it returns rather useless garbage, eg. Up1 ANDed with Fire2).
Protek Port Notes
The original Protek supports only cursor mode, newer variants can be reportedly
switched to three modes (probably cursor, kempston, and sinclair or so).
AGF and Thurnall support Cursor+Rubout, too. AGF additionally supports
T-Y-U-I-P as second joystick. Thurnall additionally supports Q-A-Z-X for

whatever usage.
Timex TS2068/TC2068 Port Notes
Timex Ports are using PSG register 14, which must be configured properly: Clear
Bit6 of PSG Register 7 (input direction), write FFh or 8Fh or so to PSG
register 14 (output HIGH levels), and set PSG index to 14. For details see
PSG/sound specs.
Rotronics Wafadrive Joystick Adaptor
According to the Rotronics Wafadrive manual, one can connect a joystick to the
centronics port of the Wafadrive via an adaptor. There's no info on how to
build that adaptor, but the manual says it is sold separately (if that adaptor
was actually ever produced, then it didn't became very popular). Because the
Wafadrive centronics port is one-directonal, it is probably using the joystick
switches in reversed direction (ie. outputting LOW levels to L,R,U,D,F via some
of the Data lines, and reading the result from the common pin via the Busy
input).
Joystick Port Pin-outs
The five switches are connected to Pin8 as a common pin, in the Atari standard
that'd be GND, but in some variants it is a /SELECT signal that goes low when
reading from the joystick port (that method works with joystick that consists
of raw switches; but won't work with sticks that contain autofire functions or
other logic that requires +5V/GND supply at Pin7/Pin8).
Kempston Homebrew TS2068/TC2068 Interface2
Spectrum+2
Protek
Pin Joy1
Joy1
Joy1 Joy2
Joy1 Joy2
Joy1 Joy2
Joy1
1
Up
Up
Up
Up
Up
Up
N/A? N/A?
Up
2
Down
Down
Down Down
Down Down
MA3
MA4
Down
3
Left
Left
Left Left
Left Left
N/A? N/A?
Left
4
Right
Right
Right Right
Right Right
Fire Fire
Right
5
N/A
N/A
N/A
N/A
N/A
N/A
Up
Up
?
6
Fire
Fire
Fire Fire
Fire Fire
Right Right Fire
7
+5V
(Fire 2) +5V
+5V
N/A
N/A
Left Left
?
8
GND
+5V
/A8
/A9
GND
GND
MA3
MA4
?
9
N/A
N/A
GND
GND
N/A
N/A
Down Down
?
Amstrad's Spectrum +2 uses standard DSUB-9 ports, but with nonstandard pinouts
(so it works only when re-wiring the connection on the mainboard, using an
external adaptor, or buying an original "SJS1" joystick from Amstrad) (the
MA3/MA4 lines are DRAM row/column address bits; essentially same as A11/A12 at
time when reading the ports).
Spectrum Mouse Ports
-------------------Kempston Mouse (hardware counters)
This is probably the most popular, best working, and most often supported mouse
interface.
--> Spectrum Mouse - Kempston Mouse
The original package consists of a Kempston Mouse and Kempston Mouse Interface,
there are also compatible interfaces that can be used with Amiga, PS/2, or USB
mice, and maybe also some for RS232, Atari, or even analog mice.
AMX Mouse (IM2 interrupts)
This is almost as powerful as the Kempston Mouse, but conflicts with various
other hardware expansions, the AMX Mouse is rarely supported by any programs.
--> Spectrum Mouse - AMX Mouse (Advanced Memory Systems)
The I/O addresses conflict with various other expansions like Kempston
Joysticks (Port 1Fh), Beta Disk, Fuller Box, etc.
Amiga/Atari Mice (software counters)
Amiga/Atari mice can be connected directly to Kempston Joystick ports (which
have +5V and GND), without needing any mouse interface. Although it's simple at
hardware side, it's supported only by a dozen of programs.
--> Spectrum Mouse - Amiga Mouse or Atari Mouse in Kempston Joystick port
The problem is that the mickeys must be counted by software, meaning that the
software must check Port 1Fh more than 500 times per second, ie. much more
often than it could be done via the 50Hz vblank interrupt.
Other Mice
Some other less popular and/or less powerful solutions are:
--> Spectrum Mouse - Other Mice
Double Speed Threshold
Don't forget to implement Threshold in software, ie. if you have received more
than so-and-so-many mickeys per frame, multiply that value by two.
Spectrum Mouse - Kempston Mouse
------------------------------FADFh - Kempston Mouse Buttons (R)

0
Right Button (0=Pressed, 1=Released)
1
Left Button
(0=Pressed, 1=Released)
2
Middle Button (not supported in original Kempston Mouse interface)
3
Not used
4-7 Mouse Wheel Counter (supported in some russian interfaces only)
The wheel "Counter is 4-bit and its value increases with the movement of wheels
down, decrases the movement up." Whatever that means...? normally the wheel
turns away from, or towards to user (where "away from user" should look
UP-wards in a document; which means the screen scrolls DOWN-wards).
FBDFh - Kempston Mouse X (R)
FFDFh - Kempston Mouse Y (R)
0-7 Counter (mickeys)
"8bit reverse counters" whatever that means... increasing or decreasing when
moving towards where? The counters aren't reset after reading, and may wrap
from FFh to 00h, or vice versa, when exceeding the 8bit range. To get mickeys
since last read, subtract old/new value.
Notes
Usually deconds A5, A7, A8, A10, /RD, /IORQ, sometimes also /RD, A9, and/or A0.
Uh, why A0...?
There is port conflict with incompletely implemented Kempston Joystick ports
that decode only A5 (eg. Timex TC2048).
Spectrum Mouse - AMX Mouse (Advanced Memory Systems)
---------------------------------------------------1Fh 0
1-2
3
4-7

AMX Mouse - Z80PIO Data Reg A, Mouse X,


Mouse X Direction (XB input from mouse)
Not used
Centronics Strobe
(should be usually
Centronics Data LSBs (should be usually

Centronics LSBs/Strobe (R/W)


(?=Left, ?=Right)

3Fh 0
1-2
3
4-7

AMX Mouse - Z80PIO Data Reg B, Mouse Y, Centronics MSBs/Busy (R/W)


Mouse Y Direction (YB input from mouse) (?=Up, ?=Down)
Not used
Centronics Busy
(should be usually input in Mode 3)
Centronics Data MSBs (should be usually output in Mode 3)

output in Mode 3)
output in Mode 3)

5Fh - AMX Mouse - Z80PIO Control Register A, Horizontal Control (W)


Used to configure Port A and Interrupt A by writing 1 or 2 byte(s) to this
register, the meaning depends on the LSBs of the 1st byte:
1stByte 2ndByte Function
vvvvvvv0 N/A
Set Interrupt Vector
exxx0011 N/A
Set Interrupt Enable
eah00111 N/A
Set Interrupt Enable/Control
(for Mode 3 only)
eah10111 mmmmmmmm Set Interrupt Enable/Control/Mask (for Mode 3 only)
00xx1111 N/A
Set Mode 0 (all 8 data bits = Output)
01xx1111 N/A
Set Mode 1 (all 8 data bits = Input)
10xx1111 N/A
Set Mode 2 (all 8 data bits = Bidirectional) (Port A only)
11xx1111 dddddddd Set Mode 3 and Direction bits (0=Out, 1=In)
Whereas,
vvvvvvv Interrupt Vector (Bit0=0, Bit1-7=vvvvvvv, Bit8..15="I"-Register)
e
Interrupt Enable (0=Disable, 1=Enable; trigger on each mickey)
a
Interrupt AND/OR (for Mode3 only)
h
Interrupt HI/LO (for Mode3 only)
mmmmmmmm Interrupt Mask
(for Mode3 only) (0=Monitor, 1=Mask)
dddddddd Data Direction bits 0-7 (0=Output, 1=Input)
7Fh - AMX Mouse - Z80PIO Control Register B, Vertical Control (W)
Same as Control Register A (see there), but for Port B accordingly.
DFh - AMX Mouse - 74LSXX Logic, Mouse Buttons (R)
0-4 Not used
5
Right Button
6
Middle Button
7
Left Button
Buttons are handled via separate 74LSxx chips. Although, theoretically, they
could be mapped to bit1-2 of the Z80PIO data ports; maybe the whole 8bit data
ports are latched on interrupts; which would freeze the state of bit1-2.
Interrupts
The AMX mouse triggers an interrupt and outputs an IM2 interrupt vector on the
databus on each mickey, the CPU should be in IM2, and the CPUs I-register
should contain MSB of the interrupt table, the Z80 does then do am indirect
"CALL [I*100h+databus]" on interrupts. Mind that trying to set I=40h..7Fh
results in ULA Snow bug.
The two Z80PIO interrupt vectors should point to the address of X and Y motion
handler; which should read the X or Y direction bit, and inrease/decrease the
mickey counter accordingly. If both X and Y mickeys occor simultaneously, then

the Z80PIO would first produce vector A, and then vector B (after vector A was
processed).
The normal Vblank interrupt doesn't output anything on databus, so databus
should be (hopefully) FFh, causing a "CALL [I*100h+FFh]" on vblank. If mickeys
occur simulaneously with vblank, then the vblank interrupt is probably lost...?
which would be bad for general animation synchronizations, keyboard handling,
as well as for mouse specific threshold calculations.
Notes
The Z80PIO is reset on power-up (when raising VCC) only, but NOT on /RESET.
The AMX Mouse is supported by Minesweeper (new version - EN), and Artist II.
Spectrum Mouse - Amiga Mouse or Atari Mouse in Kempston Joystick port
--------------------------------------------------------------------Pinouts
Pin Amiga Mouse
Atari Mouse
Kempston Joystick Kempston Mouse
1
YA
XB
Joystick up
+5V
2
XA
XA
Joystick down
XA
3
YB
YA
Joystick left
YB
4
XB
YB
Joystick right
Left Button
5
Middle Button
Not connected
Not connected
Right Button
6
Left Button
Left Button
Fire button
GND
7
+5V
+5V
+5V
Not connected
8
GND
GND
GND
YA
9
Right Button
Right Button
Not connected
XB
As shown in 1st/2nd column, Amiga and Atari have XA/XB/YA/YB arranged
differently. 3rd column shows how the signals are mapped on the joystick port.
The 4th column is just for curiosity, it shows the connection between Kempston
Mouse and Kempston Mouse Interface (aside from the different pinouts it's much
the same as Amiga/Atari mice, the big difference is that the Kempston Mouse
Interface contains hardware counters, without needing to count mickeys by
software).
Motion Signals
The XA/XB indicate horizontal motion (and YA/YB vertical motion), like so:
One Direction
Opposite Direction
XA _______----____
_____----______
XB _____----______
_______----____
The signal timings depend on how fast the mouse is moved (ie. if the mouse is
not moved, then it may stop anywhere in the above diagram, eg. while XA and XB
are both high, both low, or one high and one low).
The simpliest approach is to wait for raising edge on XA, and then to check XB
(either XB is already high, or XB is still low) and increase/decrease the
software's mickey counter accordingly. In situations where the direction
changes, it may be also recommended to handle "half mickeys" on falling edges
on XA, eg.:
One Direction
Stop
Opposite Direction
XA _______---------------------------______
XB _____-------------------------------____
In the above case, checking only raising XA would miss the direction change on
falling XA (if that happens repeatedly, then the mouse would disappear towards
the screen border, eg. if the mouse is in an unstable position, without
actually being moved).
Notes
Mind that the Kempston Joystick port inverts all signals (that is don't care
for XA,XB,YA,XB, but the button bit may be opposite as expected). And, of
course, a Kempston Joystick port does have only one Fire button (so only the
Left mouse button can be read).
Games that support BOTH Amiga and Atari mouse: Godzilla, Ultra Reflect,
Advanced Patience, Pyramid Patience.
Games that support ONLY Amiga mouse: Black Raven 1, Hexxagon, Indian Patience,
Magic Field, Mezi Vezemi 128 (cz), Sparrows, and Art Studio.
Spectrum Mouse - Other Mice
--------------------------Datel Genius Mouse
Early Datel mice (April-March 1987) had 3 buttons, all later mice had only 2
buttons. Very late Datel mouse interfaces (1989 or so) additionally included a
kempston joystick port. The interface (at least the latest version) contains
only a single 28pin SMD chip, plus some resistors and capacitors.
The used I/O addresses are still unknown, however, the interface with the SMD
chip connects to D0-D7, /IORQ, A5, A8-A10, +5V, and GND... so it might be
simply a clone of the Kempston Mouse interface? Although, Kempston Mouse and
Kempston Joystick both use A5=LOW, so, without checking A6/A7, it couldn't
separate between them...?
Joystick Mouse (supports only fixed speed motion)

Some mice (Commodore Mouse 1350, Noris Data Mouse M1, Boeder GEOS-Mouse, Elite
Mouse, Datalux SV-705) emulate a digital joystick. The advantage is that these
mice can be used with any games that support joystick input (provided that the
joystick port outputs +5V and GND pn Pin 7 and 8, ie. works only with standard
Kempston Joystick ports, not with standard Sinclair Joystick ports). The big
disadvantage that these mice can't separate between slow and fast motion.
RS232 Mouse on RS232 Port
Standard RS232 PC mice can be theoretically connected to Spectrum RS232 ports.
In practice it's difficult at both hardware and software side, and so it's
rarely supported. The first problem is that there are at least 16 Spectrum
RS232 interfaces from different companies. Next, some Spectrum RS232 ports have
non-standard pinouts (eg. Interface 1), simple Spectrum RS232 ports would
require to watch the incoming bitstream permanently by software (eg. Interface
1). So, to execute any other program code, one would need a RS232 interface
with built-in shift register and baudrate timer, and preferably also an
interrupt notification, or, even more preferably a FIFO that can hold at least
3 characters (so the 1200 baud mouse data would need to be processed only on
vblank interrupts).
AY-Mouse (C) V.M.G. (schematic in russian ZX Power digital magazine)
This is a (rather rarely supported) mouse interface. Similar to the Kempston
Mouse interface it contains two hardware counters and button inputs, intended
to be used with mice that have XA/XB/YA/YB signals (ie. any Amiga, Atari, AMX,
or Kempston mice) (of course, needing to recurse the different pinouts of that
mice).
The interface connects to PSG register 14, with the PSG being accessed via Port
FFFDh and BFFDh, ie. the Spectrum 128 style PSG addresses, but with PSG
register 14 being used to access the mouse (the real Spectrum 128 uses it as
RS232/Keypad port). The PSG register 14 bits are:
0-3 In Horizontal or Vertical 4bit Counter (as selected via bit6)
4
In Button 1 (0=Pressed, 1=Released) (presumably Left)
5
In Button 2 (0=Pressed, 1=Released) (presumably Right)
6
Out Select Counter to be mapped to bit0-3 (?=Horizontal, ?=Vertical)
7
?
Border ("for testing, and computer effects, type multicolor")
Changing bit6 (raising or falling edge?) does additionally reset the two 4bit
counters to a value of 8 each, so, the difference since last access is new-8
(or 8-new), rather than new-old.
Supported by Art Mouse (Art Studio), ZX Power 1-4, Lemmings (TRDOS version).
Nidd Valley - Digimouse (digital)
Nidd Valley - Anamouse (analog)
Saga Systems - Star Mouse
Individual Software - Keyboard Mouse
Tropic Informatica - TPX Mouse (for brazilian TK90X and TK95)
No idea how these devices work? They don't seem to be very popular.
Spectrum Light Guns
------------------Stack Light Rifle (Stack Computer Services Ltd) (1983)
connects to expansion port, accessed by reading from Port DFh:
bit1
= Trigger Button (0=Pressed, 1=Released)
bit4
= Light Sensor
(0=Light, 1=No Light)
other bits = Must be "1"
(the programs use compare FDh to test if bit1=0)
The vertical position is measured by counting time between vblank & light
sensor signal; none of the games seems to attempt to measure the horizontal
position; so there should be only one bright object per scanline).
The software timings are matched for PAL Spectrum 48K (and probably don't work
on other/newer spectrums due to different BIOS (irq handler), video (clks per
scanline), and cpu speed (waitstate) timings.
Magnum Light Phaser for Spectrum +2/+3 (Sinclair/Amstrad/Trojan) (1989)
Defender Light Gun for Spectrum 128/+2/+3 (Cheetah) (1989)
These two guns seem to be compatible with each other. Both are connected to
AUX/Keypad (aka PSG Register 0Eh):
bit4 = light sensor
(0=None, 1=Light)
bit5 = trigger button (0=Pressed, 1=Released)
Although the Spectrum 128 does have an AUX/Keypad socket, the Magnum manual
says that one should use the MIC-socket based gun on the Spectrum 128 (dunno
why).
Magnum Light Phaser for Spectrum 48K (Sinclair/Amstrad/Trojan) (1989)
Requires 9V battery, connects to MIC-output socket (which is misused as input
in this case). In the output direction, port FEh should be set to 00h
(accordingly, the 48K games cannot output sound while reading the gun) (mind
that CAS-IN, CAS-OUT, and SOUND-OUT are sharing the same ULA pin).
The trigger button is sensed as LONG pulse (Jungle Warfare reads 8Ch times, and
accepts trigger only if [FEh].Bit6=ZERO on all 8Ch reads). The light sensor is
sensed as EDGE (ie. 0-to-1 or 1-to-0 transitions on [FEh.Bit6]). Knowing that,

it seems that the trigger button and light sensor signals are XORed with each
other.
Defender Light Gun for Spectrum 48K (Cheetah) (1989)
Connects to Kempston Joystick interface. The Kempston Port 1Fh bits are:
Joystick UP
(bit3) = Trigger button
Joystick FIRE (bit4) = Light sensor
Other
(bit0-2,5-7) = Must be 0 (Jungle W. compares [1Fh] with 08h,10h,18h)
Works only with Kempston interfaces (other joystick interfaces don't seem to be
supported at software side, and, other interfaces usually don't provide the
required +5V supply voltage at hardware side).
Gunstick for Spectrum 48K/+/128 (MHT Ingenieros)
Connects to joystick interface. Requires four 1.5V batteries (and so, doesn't
require 5V/GND on joystick port).
Joystick FIRE = Trigger Button (LOW=Pressed, HIGH=Released)
Joystick DOWN = Light Sensor
(LOW=?)
Most games seem to support only Sinclair Joystick Interfaces (Port EFFEh or
F7FEh), although the hardware should work with all joystick interfaces.
Gunstick for Spectrum +2/+3 (MHT Ingenieros)
Same as the 48K version, but matched to the (distorted) pin-outs of the bizarre
Spectrum +2/+3 joystick ports.
Note on Defender "sliding autofire/function select switch"
Additionally to the trigger button, the Defender guns have a "sliding
autofire/function select switch", reportedly used to select one-shot or
machine-gun mode in some games, however, unknown how this switch is accessed by
software (there seem to be only two data bits used; the light sensor and
trigger button; so maybe it affects the length of the trigger button signal),
also unknown if that switch acts as a push button, sticky switch, or even as
potentiometer?
Existing Lightgun Games for the Spectrum
Stack Light Rifle Games:
Grouse Shoot
Stack Computer Services Ltd (compiled BASIC code)
Shooting Gallery
Stack Computer Services Ltd (compiled BASIC code)
High Noon
Stack Computer Services Ltd (compiled BASIC code)
Invasion Force
Micromania (real Z80 assembler code)
Defender Light Gun Games:
Advanced Pinball Simulator Code Masters Ltd
Billy the Kid
Code Masters Ltd
Bronx Street Cop
Code Masters Ltd
F-16 Fighting Falcon
Code Masters Ltd
Jungle Warfare
Code Masters Ltd
Super Car Trans Am
Code Masters Ltd
And... theoretically the AUX-based Magnum games should work, too?
Magnum Light Phaser Games:
Billy the Kid
Code Masters Ltd
Bronx Street Cop
Code Masters Ltd
Bullseye
Macsen Software
F-16 Fighting Falcon
Code Masters Ltd
Jungle Warfare
Code Masters Ltd
Living Daylights
Domark Ltd
Lord Bromley's Estate
Amstrad
Missile Ground Zero
Software Creations
Operation Wolf
Ocean Software Ltd
Q's Armoury
Amstrad
Robot Attack
Mastertronic Ltd
Rookie
Mastertronic Ltd
Solar Invasion
Mastertronic Ltd
Super Car Trans Am
Code Masters Ltd
Gunstick Games:
Acid Killer
New Frontier
Bestial Warrior
Dinamic Software
Cosmic Sheriff
Dinamic Software
El Equipo A (aka A-Team)
Zafiro Software Division
Guillermo Tell
Opera Soft S.A.
Hunting Mix
New Frontier
Mike Gunner
Dinamic Software
Shooting Range: Mix I
New Frontier
Solo
Opera Soft S.A.
Sootland
Zafiro Software Division
Space Smugglers
MHT Ingenieros S.L.
Target Plus
Dinamic Software
Trigger
Opera Soft S.A.
Note: In many cases there are two versions of each Magnum game: one hardcoded
to work with MIC port, another one hardcoded to work with AUX port. The Code
Masters titles do auto-detect if the Magnum (or Defender) is connected to MIC,
AUX, or Kempston joystick port.

Spectrum Printer Ports


---------------------Sinclair focused on selling their own 32-column printer (see ZX81 chapter), and
(until the Spectrum +2A/+3 were released) didn't support regular centronics
printers. The only official alternative to the 32-column thing was to use
(rather rare) RS232 printers connected to Interface 1 (see Serial port
chapter). Various other companies have released Centronics ports for the
spectrum (often included in disk interfaces), but without using any standarized
I/O addresses...
Centronics Ports
Type
Data
Busy
Strobe
Interface Bis
#1D
(#1D).7
auto
M'ody Technik 1986-12 #1F (inv) (#9F).4=0
(#9F).4=1
MB-02
#3F
(#5F).7=1
(#5F).1=0
YAMOD.8211
#0n58
(#0n59).7=0
(#0n5A).0=1
;n=0..1
Unipolbrit 2086
#xx7B
(#BB).?=1
(#BB).?=0
AERCo Centronics
#7F
(#7F).4=1
auto
MultiPrint
#BF
(#BB).6=1
(#BF)=X,(#BB)=X,(#BF)=X
Informik 1989-II
#E3
(#F3).4=0
(#F3).4=1
Sam FDD
#E8
(#E9).0
(#E9).0=1
Elwro 800 Jr
#DE
(#DD).7=1
(#DD).2=0
Scorpion
#DD
(#FE).7
auto(?)
AERCo FD-68
#E0DF ?
(#xx??).?
??
PlusD
#F7
(#F7).7
(#EF).6
DISCiPLE
#FB
(#1F).6
(#1F).6
ZX Lprint 3 & Pentagon #FB
(#FB).7=1
auto (?)
Centronics Microface
#FB
(#FB).7=1
auto
ZX Spectrum +3
#0FFD
(#0FFD).0=1
(#1FFD).4=0
GP500A PZ "APINA"
#xx??
(#xx??).?
??
Kempston S (Software) #E0BF
(#E2BF).0
E3BF.0 ;with SOFTWARE driver
Kempston E (EPROM)
#xx??
(#xx??).?
??
;with EPROM driver
DK'Tronics
#xx9B
(#xxBB).7
xxBB.1
INES Printerface
#xx??
(#xx??).?
??
Opus Discovery
(memory mapped PIA6821)
;BiDir.D0-D7,STB,READY,ACK
Rotronics Wafadrive
dd0Eh
0002h.5
000Ah/200Ah ;via IN (not OUT)
Indescomp
#FB
(#FB).0
(#7F).0
Watford
?
?
?
Fuller
?
?
?
VISMO ZP83 parallel interface
VTR Parallel Centronics Interface
Tasman Parallel Printer Interface
ADS Advanced Digital Systems Centronics Interface
Dorsch Centronics Interface
Technology Research S-Print
Cambridge Intelligent Printer Interface
Logitek Floppy/Printer Interface (centronics port and c64 floppy port)
Miracle ZX Printer Interface (rs232-to-centronics converter for Interface 1)
Morex Printer Interface (centronics, rs232, built-in word processor)
Romantic Robot Multiprint
Cambridge Microelectronics Polyprint Interface
Camel Products Print-SP
Ram Electronics RamPrint Interface (centronics, joystick, RamWrite in ROM)
Euroelectronics ZX Lprint (centronics)
Euroelectronics ZX Lprint III (centronics and rs232)
AMX Mouse (with 8bit centronics data split into two 4bit fragments)
Nidd Valley Digimouse Interface (professional version with Centronics port)
Cloned and/or Re-distributed Centronics interfaces
Hilderbay Interface (same as the Kempston S thing)
Datel Inter Printer (same as the DK'Tronics thing, distributed by datel)
Datel Ramprint
(same as the Ram Electronics thing, distributed by datel)
Pentagon
(russian spectrum clone, with built-in ZX Lprint 3)
Centronics Notes
Interface Bis
M'ody Technik 1986-12
MB-02
Unipolbrit 2086
Informik 1989-II
Elwro 800 Jr
YAMOD.8211
AERCo Centronics
MultiPrint
ZX Lprint 3 Pentagon

5 input lines for LapLink


8255 used: #DF=config; PA=data. All signals inverted.
8255 used; #7F=config; PB=data, PC2=/ACK,
PC3=/AUTOFEED, PC4=/ERROR, PC5=SELECT, PC6=PAPEROUT
8255 used; #FB=config; PA=data; only PA and PC0, PC1,
PC4, PC5 are in DB15 slot
8255 used: #FB=config; PA=data (PB switches memory
banks). All signals inverted.
8255, other bits reserved
PC LPT connected as YABUS.ZXISA
(#7F).5=0 - printer present
8kB ROM, 8kB RAM
2kB ROM

Centronics Microface
see files for documentation
ZX Lprint by Euro Electronics: The test for printer ready is IN A,(#E0): AND
#E0: CP #40. The ROM is paged into #0800..#0FFF. Looks like paged permanently.
ZX Lprint MK III: The ROM is paged into #0000..#07FF (with out to #FB - on, out
#7B - off). The code for selected printer is copied into printer buffer (at
#5B00).
Multiprint by Romantic Robot: Is NMI & debug interface with parallel port.
Basic Features
All cards should have STROBE and BUSY lines, and (at least) 7bit
one-directional DATA lines (most or all have probably 8bit?). Some cards
allow/require to control STROBE manually, others do generate it automatically
after writing to DATA.
Extended Features
A few parallel ports may have bi-directional DATA lines (namely those with 8255
chips) (also some, but not all, ISA parallel cards may have bi-directional
ports). Aside from STROBE and BUSY, some cards may have ACK, INIT, AUTOLF, etc.
Spectrum Serial Port
-------------------Interface 1
-> RS232/Network: Port F7h and EFh
Spectrum 128/+2/+2A/+3 -> RS232/Keypad: PSG Register 14
Rotronics Wafadrive
-> RS232:
Port ? (uses RX,TX,RTS,CTS)
Timex RS232 Interface
-> RS232:
Port ?
Indescomp
-> RS232:
Port FBh.R and 7Fh.W
Cobra RS232 Interface (1983)
Cole RS232 (100/300 baud RS232 output port) (1983)
Fuller RS232 Interface aka Fuller FD Printerface (1983)
Fuller Dual Interface (RS232 and Centronics)
Kempston RS232 Interface (1984)
Tasman RS232 Printer Interface (1984)
U-Microcomputers USP-232D (dual RS232 with Z80DART chip, 75..9600 baud)
Watford Centronics/RS232 Interface (1985)
Morex Printer Interface (centronics, rs232, built-in word processor)
Euroelectronics ZX Lprint III (centronics and rs232)
YAMOD.8250
"Most of ZX Spectrum + 128K is VERSION 6K (C) 1985. There's a VERSION 9G with
DB9 female slot for the RS232."
Network
Supported by Interface 1 (via Port F7h/EFh) and by Disciple (via Port 3Bh/1Fh).
Despite of the different I/O ports, the transmission protocol is the same, and
Interface 1 and Disciple can communicate with each other.
--> Spectrum Interface 1 (Microdrive, Network, RS232)
--> Spectrum Disc Disciple and Plus D
The network interfaces have two mono 3.5mm headphone sockets: One for the next,
and one for the previous computer in the network. Reportedly up to 64 computers
can be connected. On the first and last computer one socket is to be left
unconnected (no matter which one) (the sockets contain a switch which connects
the end of the data line via a terminator resistor to ground when no plug is
inserted).
Note: Another (incompatible) network-type is supported by the Opus Discovery
BIOS (which allows to use the Centronics port to transfer files to/from another
computer).
RS232 (Sinclair) (9pin DSUB female)
1
Not Connected.
___________
2 In TXD
| 5 4 3 2 1 |
3 Out RXD
\_9_8_7_6_/
4 In DTR ;should be high when ready
5 Out CTS ;should be high when ready
6
Not Connected.
7
GND
8
Not Connected.
9
+9V - Pull up. (DSR)
Although standard RS232 ports on PCs are using 9pin DSUB connectors too, the
pinouts are NOT compatible (PCs are using male connectors, and, DTR/CTS/GND are
at other locations).
AUX/Keypad and RS232/MIDI (PSG Register 14)
0 AUX/Keypad pin 2 (out)
1 AUX/Keypad pin 4 (out)
2 RS232/MIDI pin 5 (RS232: output to remote CTS) (MIDI: DATA OUT)
3 RS232/MIDI pin 3 (RS232: output to remote RXD) (MIDI: Not used)
4 AUX/Keypad pin 3 (in) (Lightgun: light sensor:
0=No Light, 1=Light)
5 AUX/Keypad pin 5 (in) (Lightgun: trigger button: 0=Pressed, 1=Released)
6 RS232/MIDI pin 4 (RS232: input from remote DTR) (MIDI: Not used)

7 RS232/MIDI pin 2 (RS232: input from remote TXD) (MIDI: Not used)
Using software control loops, the I/O lines could be driven as a second RS232
port (in the same way as the RS232/MIDI socket is driven using bits 2, 3, 6 and
7). Alternatively, the I/O lines could be used to drive, for example, a robot
or some other external device.
Pin
Function
1
GND
___________________________
2
OUTPUT BIT 0
__|
6
5
4
3
2
1
|
3
INPUT BIT 4
|__
### ### ### ### ### ### |
4
OUTPUT BIT 1
|___________________________|
5
INPUT BIT 5
6
+12V
AUX/Keypad socket
Pin
Function
1
GND
(MIDI: RETURN)
____________________
2
input from remote TXD (MIDI: not used)
__|
|
3
output to remote RXD
(MIDI: not used)
|__
6 5 4 3 2 1 |
4
input from remote DTR (MIDI: not used)
|____________________|
5
output to remote CTS
(MIDI: DATA OUT)
6
+12V
(MIDI: not used)
RS232/MIDI socket
Rather unconventional "BT 603A" sockets. As far as I understand, the plugs are
similar to RJ/Western plugs, but with the plastic clip at the left-side (next
to pin6), rather than at the top-side (above pin3/4).
Signal Naming
Spectrum RS232 pins are usually named according to the REMOTE side, eg. the
spectrums transmit output is named RXD (not TXD) meaning to be connected to the
remote receive input.
Spectrum Expansion Ports
-----------------------Expansion Ports (male cart-edge, 2x23 or 2x28 or 2x32 pins)
-------TS2068------- ------TC2068------ ----Spectrum----ZX80/ZX81/TS1x00Top
Bottom
Top/A
Bottom/B
GND 1 GND
/BE 1 /EXROM
Top
Bottom
EAR 2 SPKR/TAPE
A15 2 A14
A15 1 A14
A7R 3 +15V
A13 3 A12
A13 2 A12
Top
Bottom
D7 4 +5V
D7 4 +5V
D7 3 +5V
D7 1 5V
(DZ IN) 5 N.C.
N.C. 5 +9V
N.C. 4 +9V
/RAM CS 2 9V
(SLOT) 6 (SLOT)
(SLOT) 6 (SLOT)
(SLOT) 5 (SLOT)
(SLOT) 3 (SLOT)
D0 7 PWR GND
D0 7 0V
D0 6 0V
D0 4 0V
D1 8 PWR GND
D1 8 0V
D1 7 0V
D1 5 0V
D2 9 CPU CLK
D2 9 CPU CLK
D2 8 CPU CLK
D2 6 CPU CLK
D6 10 A0
D6 10 A0
D6 9 A0
D6 7 A0
D5 11 A1
D5 11 A1
D5 10 A1
D5 8 A1
D3 12 A2
D3 12 A2
D3 11 A2
D3 9 A2
D4 13 A3
D4 13 A3
D4 12 A3
D4 10 A3
/INT 14 A15'B
/INT 14
/INT 13 /IORQULA
/INT 11 A15
/NMI 15 A14'B
/NMI 15 0V
/NMI 14 0V
/NMI 12 A14
/HALT 16 A13'B
/HALT 16 VIDEO
/HALT 15 VIDEO
/HALT 13 A13
/MREQ'B 17 A12
/MREQ 17
/MREQ 16 /Y
/MREQ 14 A12
/IORQ'B 18 A11
/IOREQ 18
/IOREQ 17 V
/IORQ 15 A11
/RD'B 19 A10
/RD 19
/RD 18 U
/RD 16 A10
/WR'B 20 A9
/WR 20 /BUSREQ
/WR 19 /BUSREQ
/WR 17 A9
/BUSAK 21 A8
21 /RESET
-5V 20 /RESET
/BUSAK 18 A8
/WAIT 22 A7
/WAIT 22 A7
/WAIT 21 A7
/WAIT 19 A7
/BUSRQ 23 A6
23 A6
+12V 22 A6
/BUSRQ 20 A6
/RESET 24 A5
24 A5
-12V 23 A5
/RESET 21 A5
/M1 25 A4
/M1 25 A4
/M1 24 A4
/MI 22 A4
/RFSH'B 26 (DZ OUT)
/RFSH 26 /ROMCS
/RFSH 25 /ROMCS
/REFSH 23 /ROM CS
/EXROM 27 RGB-R
A8 27 /BUSACK
A8 26 /BUSACK
/ROSCS 28 RGB-G
A10 28 A9
A10 27 A9
/BE 29 RGB-B
N.C. 29 A11
N.C. 28 A11
(IO A5) 30 (BUSISO)
RED 30 CSYNC
SOUND 31 VIDEO
GREEN 31 BRIGHT
GND 32 GND
BLUE 32 GND
The Spectrum/TC20xx port (europe) is compatible only with the signals used by
the ZX81 printer, but not compatible with other ZX80/ZX81 hardware (for some
crazy reason, the /RESET pin is replaced by -12V, giving it a good chance to
vaporize any ZX80/ZX81 hardware). The TS2068 port (usa) is almost fully
backwards compatible with the ZX80/ZX81 and TS1000/TS1500 ports, but
incompatible with Spectrum/TC20xx ports.
On the Spectrum 48K, the /Y,U,V,VIDEO signals are passed through jumpers on the
mainboard, the Y,U,V jumpers are usually installed, but the VID jumper isn't
(so without adding that jumper, VIDEO isn't actually output on Pin15/Bottom).
Signal Notes
CPU CLK
normally 3.5MHz clock, but, PAUSED during waitstates
/ROMCS
BIOS chipselect (can be dragged to 5V to disable internal BIOS)

/IORQULA

ULA chipselect (can be dragged to 5V to disable ULA mirrors)

TS2068 Notes
(BUSISO),(IO A5),(DZ IN),(DZ OUT) are "not connected" (but are reserved for
something or so). "IO A5 (Bit5 of PSG Port A) available on edge-slot)" so it is
NOT not-connected...?
TC20xx
Although the TC2048/TC2068 are based on the US TS2068, their expansion port
pin-outs were converted back to the 2x28 pin Spectrum layout to match the
european market. During that backwards-conversion the /IORQULA pin got lost,
the TC devrs apparently didn't understand its purpose, in the first version of
the mainboard they have left it unconnected, in the next version it's
accidently connected to /IOREQ via a jumper, in the third version it's directly
wired to /IOREQ without any jumper.
Later Spectrums
Later Spectrums (eg. +3) don't use a +9V power supply, and thus leave the +9V
pin unconnected; also, later models changed the pin numbering from 1..28 to
1..27 (with the SLOT spacings not being counted as pins). Also, the +3 has
Pin4/comp = /ROM1OE, no -5V, no /BUSACK, no /IORQULA, no /ROMCS,
Pin28/comp=RESET, and VIDEO,/Y,V,U replaced by
/ROM2OE,/DISKRD,/DISKWR,/MOTORON.
Spectrum ROM Cartridges
----------------------Cartridge Slots (female cart-edge, 2x18 or 2x15 pins)
TS2068/TC2068 Cartridges (2x18 pin)
Interface 2 Cartridges (2x15 pin)
Solder Side
Component Side
Whatever Side
Other Side
1 A14'B
2 +5V
1A /ROMCS (+5V) 1B +5V
3..A12...........4..A13'B.....SLOT..
2A A12
2B A15 (/CS2)
5 D0
6 D7
3A A7
3B A13
7 D1
8 A0
4A A6
4B A8
9 D2
10 A1
5A (SLOT)
5B (SLOT)
11 D6
12 A2
6A A5
6B A9
13 D5
14 A3
7A A4
7B A11
15 D3
16 A15B
8A A3
8B /MREQ (/OE)
17 D4
18 /MREQ'B
9A A2
9B A10
19 /IORQ'B
20 A7R'B
10A A1
10B A14 (/CS1)
21 /RD'B
22 /M1
11A A0
11B D7
23 /WR'B
24 A8
12A D0
12B D6
25 A7
26 A9
13A D1
13B D5
27 A6
28 A10
14A D2
14B D4
29 A5
30 A11
15A GND
15B D3
31 A4
32 /RFSH'B or /ROMCS
33 /BE or ROMDIS 34 /EXROM
35 /ROSCS
36 GND
Timex TS2068/TC2068 Cartridges
The TS2068/TC2068 (but not the TC2048) contain a built-in cartridge slot.
The TC2068 cartridges are slightly bigger in height than TS2068 cartridges (so
the bigger TC2068 carts won't fit into the smaller TS2068 slot without
modifying the plastic case), and, the pinouts are slightly different for
TS2068/TC2068 (pin32 and pin33).
A7R'B=Refresh Address Bit7, /RFSH=Refresh (TS2068 only), /BE=Bank Enable
(TS2068 only), /EXROM (useless), /ROMCS (useless) (TC2068 only),
ROMDIS="disables both internal ROM and also forces high state on both /ROMCS
and /EXROM in the slot" (TC2068 only), /ROSCS=ROS Chip Select (Dock Bank
Enable), xx'B=buffered (not directly connected to corresponding xx pin on CPU).
Timex Cartridge Types
LROS --> Language ROM-Oriented Software
at 0000h (Z80 Code)
AROS --> Application ROM-Oriented Software at 8000h (BASIC or Z80 Code)
BASIC code isn't directly executed in ROM, instead, the current BASIC line is
copied to ARSBUF in RAM, and then executed from there. USR function does
address ROM. While PEEK/POKE address RAM?. User-Defined BASIC functions (DEF
FN) aren't supported.
Timex LROS Header
0000h Not used (should be F4h for Spectrum ROMs, see comment)
0001h Cartridge Type (01h=LROS)
0002h Entrypoint (16bit)
0004h Initial Value Port F4h (XORed by FFh)
0038h IRQ Handler
Note: [0004h].Bit3 should be set (otherwise the Machine Stack and Bank
Switching code gets replaced by ROM). Caution the LROS is started with IRQs
enabled (so the handler at 0038h might be called even before the Entrypoint
handler is executed). Accordingly, [0004h] must enable any ROM locations used
by the Entrypoint, and such used by the IRQ handler.

Comment: Some Spectrum games have JR FFF4h opcode as IM 2 interrupt handler at


FFFFh, the opcode consists of [FFFFh]=18h (in RAM), and [0000h]=F4h (ie.
initial DI opcode - or 1st byte of the LROS header) in BIOS ROM. Ie. an LROS
cartridge with Spectrum ROM and LROS header should contain the DI opcode at
0000h.
Timex AROS Header
8000h Language Type (01h=BASIC, 02h=Machine Code) (other=Error)
8001h Cartridge Type (02h=AROS) (other=no cartridge)
8002h Entrypoint (16bit) (ptr to first BASIC Line, or to first opcode)
8004h Initial Value Port F4h (not XORed) (Bit0-3 must be set for BIOS/VRAM)
8005h Autostart Flag
(0=No, 1=Autostart)
8006h Number of bytes of RAM reserved for Machine Code variables (16bit)
Bug: [8006h] must be set to "N+15h" to allocated "N" bytes.
Timex The Spectrum Emulator Cartridge:
"This cartridge made by Timex of Portugal, contains a ROM image of TC2048. I
think that this isn't a ROM cartridge, but a LROS cartridge, because it is
simply plugged to TC2068 and it starts automaticaly. Many American Timex
Sinclair 2068 users made a cartridge with a ROM chip of a ZX Spectrum and
because of this, they have to type the OUT 244,3 command."
Spectrum Interface 2 Cartridges
In the cartridge, /ROMCS is usually wired to +5V, completely disabling the
BIOS, and allowing to map 16K ROM to 0000h..3FFFh. There were only 10
cartridges manufactured, all of them only 16K in size, using ROM chips with two
/CS pins. For normal EPROMs, /CS1 and /CS2 would need to be ORed by external
logic (although /CS2 aka A15 could be left unconnected when not using the upper
32K of RAM). Bank switching for more than 16K ROM can be implemented by reading
from a specific memory region, and latching LSBs of the address as bank number;
observe that /MREQ gets low on /RD, /WR, and /RFSH; during refresh, the IR
register pair is output to the address bus, so the I register should be set to
a value that doesn't conflict with the bank switching addresses.
Timex TS1510 Command Cartridge Player (Pinouts unknown?)
An external cartridge adaptor for the TS1500. It can be also used with
TS1000/ZX81 with a 16K RAM upgrade (assuming that most or all cartridges do
require 16K RAM; there were only 4 carts manufactured).
The TS1500 BIOS starts cartridges automatically; it jumps to 2000h if the first
byte at [2000h] is 01h (ie. a LD BC,nnnn opcode). On a ZX81/TS1000, the
cartridge must be manually started (eg. by typing RAND USR 8192). Aside from
the cartridge connector, the TS1510 includes a RESET button.
The first 8K of ROM is obviosly mapped to 2000h. Carts with 16K or more ROM are
mapped to unknown (?) memory locations. According to the manual, such bigger
carts won't work on computers expanded to 32K RAM (which have extra RAM at
8000h..BFFFh) (so the extra ROM is probably mapped to that region).
The memory mapping logic seems to be built-in in the TS1510 (rather than in the
cartridge), looking at photo found in the internet, it seems to contain a
74LS00 chip, and another chip whose part number is unknown due to bad quality
of the photo.
The TS1510 was advertised to support up to 24K ROM.
Only four TS1510 cartridge titles were ever released:
07-9001 Supermath
07-9002 States and Capitals
07-9003 Chess
07-9004 Flight Simulator
Spectrum Chipset Pinouts
-----------------------Ferranti 6C001 (Spectrum 48K) - Uncommitted Logic Array (ULA):
Ferranti 7C001 (Spectrum 128K) - Uncommitted Logic Array (ULA):
1 /CAS 6 A1
11 A6
16 VIDEO V 21 D1
26 KB4
31 D7
2 /WR
7 A2
12 /INT
17 VIDEO /Y 22 D2
27 D4
32 CLOCK
3 /RD
8 A3
13 +5V
18 D0
23 KB2 28 SOUND 33 /IO-ULA
4 /WE
9 A4
14 +5V'
19 KB0
24 KB3 29 D5
34 /ROM CS
5 A0
10 A5 15 VIDEO U 20 KB1
25 D3
30 D6
35 /RAS
SOUND is the analog-I/O-line for beep, save and load.
CLK is the clock-source to the CPU including the inhibited T-states.
IO-ULA is "A0(CPU) OR /IORQ" for the I/O-port FEh.
OSC is the 14MHz-crystal, other side grounded through a capacitor.
One of the +5V is decoupled through a RC-low-pass.
TS2068 SCLD
1 A0
2 A1
3 A2
4 A3
5 A4
6 A5

11
12
13
14
15
16

/EXROM
/BE
OSC OUT
OSC IN
TAPE IN
TAPE OUT

21
22
23
24
25
26

MUX
MA7
MA3
MA4
MA2
GND

31
32
33
34
35
36

MA0
/ROSCS
/RAS1
VIDEO U
VIDEO V
VIDEO /Y

41
42
43
44
45
46

/CAS1
CLK CPU
+5V
A14
A15
VIDEO B

51
52
53
54
55
56

KB2
KB3
KB4
/RD'
D1
D2

36
37
38
39
40

61
62
63
64
65
66

A14
A15
/MREQ
OSC
GND

D4
D7
/RD
/IORQ
/WR
/MREQ

7 A6
8 A7
9 A13
10 CLK EXP

17
18
19
20

PSG BC1
PSG BDIR
PSG CLK
/TS

Gate Array +2A/+3


1 BUSY 14 MA3
2 EAR
15 GND1
3 A0
16 MA4
4 A1
17 MA5
5 A2
18 MA6
6 A3
19 MA7
7 A4
20 A8
8 A5
21 A9
9 A6
22 A10
10 A7
23 A11
11 MA0 24 A12
12 MA1 25 A13
13 MA2 26 A14

27
28
29
30
31
32
33
34
35
36
37
38
39

27
28
29
30

/ROMCS
MA6
MA1
MA5

A15
K0
K1
K2
K3
K4
/MTR
PRNT
/DRD
/DWR
VIDEO B
VIDEO R
VIDEO G

40
41
42
43
44
45
46
47
48
49
50
51
52

37
38
39
40
GND2
VCC1
BRIT
/SNC
FSC2
/RS
/CS
STRB
K5
K6
K7
K8
K9

/DRAMWE
A7R
/CAS3
/CAS2
53
54
55
56
57
58
59
60
61
62
63
64
65

K10
DV7
DV6
DV5
DV4
DV3
DV2
DV1
DV0
VA7
VA6
VA5
VA4

47
48
49
50

VIDEO G
VIDEO R
KB0
KB1

57
58
59
60

66
67
68
69
70
71
72
73
74
75
76
77
78

GND3
VA3
VA2
VA1
VA0
D7
D6
D5
D4
D3
D2
D1
D0

/RFS
/IRQ
/MRQ
/WR
/RD
/ROM2
/ROM1
RA14
/ZCK
/INT
/WAIT
GND4
VCC2

79
80
81
82
83
84
85
86
87
88
89
90
91

D0
D3
D5
D6

67 /INT
68 /RFSH

92 PSG CLK
93 PSG BC1
94 PSG BDIR
95 /VWE
96 /VCS
97 /VRS
98 MIC
99 /RS
100 OSC

AY-3-8912 Sound Chip (PSG)


1 SND C
5 SND A
9 P5
13 P1
17 A8 (+5V) 21 D7
25 D3
2 TEST,NC 6 GND
10 P4
14 P0
18 BDIR
22 D6
26 D2
3 +5V
7 P7
11 P3
15 CLK
19 BC2(+5V) 23 D5
27 D1
4 SND B
8 P6
12 P2
16 /RES 20 BC1
24 D4
28 D0
Timex TS2068 uses CLK=1.76475Mhz, Spectrum +3 uses CLK=1.7734MHz.
Spectrum Xboo
------------Step 1 - Connect Centronics Port and EPROM
GND ------------------- CNTR.24 GND
ULA.Pin28 ------|>o---- CNTR.10 ACK (SPKR)
EAR ------------------- CNTR.2 D0 (EAR)
KB1.Pin1 "0" ---|>|---- CNTR.3 D1 (CLK)
KB1.Pin2 "9" ---|>|---- CNTR.4 D2 (D0)
KB1.Pin3 "8" ---|>|---- CNTR.5 D3 (D1)
KB1.Pin4 "7" ---|>|---- CNTR.6 D4 (D2)
KB1.Pin5 "6" ---|>|---- CNTR.7 D5 (D3)
CPU.Pin26
----|>|---- CNTR.8 D6 (/RESET)
EPROM.Pin27 ----------- CNTR.9 D7 (ROM.A14)
EPROM.Pin27 ---/cut/--- /RD
EPROM.Pin27 ---[3k3]--- +5V
EPROM.Pin1 ----------- +5V
ACK must be amplified via a TTL inverter (eg. by using an unused NAND gate,
found on Pin1-3 of IC24 (74LS00) on Spectrum 48K Issue 2 mainboards; note that
the unused inputs are wired to 5V). Pass the reset and keyboard lines through
1N4148 diodes to prevent them to get stuck. Remove the ROM, and replace it by a
28pin socket for the EPROM, with 1:1 connection, except for pin1 (usually NC),
and pin27 (usually /RD), omitting the /RD line causes the EPROM to respond also
to writes and refresh, but that should be no problem.
Step 2 - Connect Joystick (Sinclair 1)
KB1.PIN1 "0" ---|>|--- DSUB.Pin6 Fire
KB1.PIN2 "9" ---|>|--- DSUB.Pin1 Up
KB1.PIN3 "8" ---|>|--- DSUB.Pin2 Down
KB1.PIN4 "7" ---|>|--- DSUB.Pin4 Right
KB1.PIN5 "6" ---|>|--- DSUB.Pin3 Left
KB2.PIN4 A12 ---|<|--- DSUB.Pin8 Common
Connect all joystick lines through 1N4148 diodes (the diode in A12 line facing
in opposite direction). The five joystick data diodes are required because the
joystick cable doesn't contain terminator resistors; without these diodes, the
xboo transmission won't work without the diodes when signals "bounce back" from
the end of the long joystick cable). Without the A12 diode, the Spectrum game
"Zynaps" would crash after 1-2 minutes (no idea why, there is already a diode
on the mainboard, so adding another diode should have little effect, but it
does fix the zynaps crash, maybe it just works as a resistor).
Step 3 - Connect AV-Cable
GND ----------------------------------------- Cinch GND
VID ----------------------------------------- Cinch V
MIC ----------------------------------------- Cinch A
Connect the Cinch sockets to the "VID" jumper, and to the "MIC" socket, the
cables don't need to be shielded, but, Cinch GND should be connected somewhere
close to the TV modulator (this gives a better picture).
Step 4 - Connect Supply from PC
There are two simple ways to replace the 9V supply by voltages from a PC power
supply. The straight way would be to use a 7809 to lower 12V to 9V, but the
7809 produces a lot of heat (and the internal 7805 produces further heat when

it lowers the 9V to 5V). So, my preferred way would be to use 5V:


Spectrum 5V ------------ PC 5V (red floppy cable)
Spectrum 5V -----||----- Spectrum GND
Spectrum 5V ----|>|----- Spectrum 9V
Inject 5V from the PC supply to 5V on the mainboard (there's no need to inject
GND, since that's passed through the centronics cable). Add a 470uF capacitor
between 5V and GND for better video quality. Pass 5V to 9V via a 1N4001 diode
(this feeds the internal +12V/-5V voltage generator which is usually driven at
9V, but it does also work at 5V, with 5V it's reaching only +10V instead of
+12V, but does still work; the voltages are required for DRAM and video signal
generation).
Basically 5V and 9V could be directly shortcut with each other, however, the
diode has two purposes: First, it prevents 9V being passed to 5V (in case
somebody connects a 9V supply). Second, it reduces noise from the voltage
generator on the 5V line (without the diode one might need a larger 2200uF
capactitor instead of 470uF one).
Caution - The 5V solution has two disadvantages: The TV modulator does no
longer work (not sure why, maybe it requires full 12V, or maybe the voltage
generator is producing too much noise when driven at 5V) (anyways, the AV cinch
output does work). And, it doesn't output 9V on the expansion port (which may
be required by some expansion hardware).
Step 5 - Connect Keyboard
The keyboard is connected via extremly fragile printed plastic wires, which
tend to break when fiddling with them (or just when they get old). The membrane
with the keyboard matrix consists of the same material, but the wires are the
most fragile part.
Desolder the keyboard connectors. Connect real metal wires to the connectors.
Cut the original plasitic wires close to the membrane. Carefully slide the
connectors on the remaining ends (best, put the ends on a solid surface, if
there's no good surfaces: put 1-2 layers of board under the ends, then firmly
push the ends onto that surface, and move the connector onto the cable; rather
than trying to move the cable into the connector. If needed, add some
tuner/contact spray, and move the cable end in and out a little. Finally, glue
the connectors to the case.
Software
The transmit function (for uploading .TAP files to the Spectrum) is found in
no$zx's "Utility" menu. The "Utility" menu also contains a function called
Create Patched BIOS Image, which creates a file called XMITSPEC.ROM, which is
to be stored in the EPROM; the ROM-image is 32K in size, containing two copies
(one original, and one patched) of the ZX Spectrum BIOS.
Note
Above Pin-numbers are for Spectrum 48K Issue 2 board (some may vary on other
boards). The transmit software currently works only with ZX Spectrum
16K/48K/Plus (not with Spectrum 128 and up).
Lambda 8300
----------The Lambda 8300 is a ZX81 clone (not an exact clone) made in china, and
distributed by various companies, in various countries, under various different
names...
Name___________Usage_______________
Lambda 8300
(Denmark, Sweden, Norway)
Power 3000
Creon Enterprises (Hongkong) (Denmark, Germany)
Marathon 32K
(Denmark)
Futura 8300
Unisonic (USA)
DEF 3000
(France)
Your Computer
IQ8300
(China?)
BASIC 2000
BASIC 3000
PC 2000
PC 8300
Text on mainboard
PC8300 BASIC
The BASIC syntax is more or less the same as on ZX81, so it accepts ZX81 BASIC
type-in listings in most cases, there is also (limited) support for loading
ZX81 cassette files. A few commands/functions are different: LOG (instead LN),
LET (can be optionally omitted), and the quad-quotes token ("") isn't supported
(ie. one cannot define double-quotes in strings). Additional commands are
TEMPO, MUSIC, SOUND, BEEP, NOBEEP (for internal speaker), and INK, PAPER,
BORDER (for external COLOR module).
PC8300 BIOS
The BIOS is apparently based on a disassembled and modified ZX81 BIOS. About
ALL procedures are moved to different addresses, so there's no compatibility
when CALLing BIOS functions. Only the INT and NMI handler are (more or less)

same as in ZX81 (the timings are slightly changed, the INT handler has same
function, but C and B registers are exchanged).
PC8300 RAM
Some entries in system area are modified. D_FILE is hardcoded at 407Dh, D_FILE
is always expanded (full 1+33*24 bytes). BASIC program is located after D_FILE
(ie. always at 4396h since D_FILE has fixed size). The BASIC program is
terminated by an FFh byte (ZX81 has no such end byte). The remaining memory
(VARS and up) is same as on ZX81.
The RAMTOP detection supports up to 32K RAM (unlike ZX81 which detects max
16K). The Lambda includes 2K RAM built-in (unlike 1K in ZX81). Note: despite of
its name, the Marathon 32K also has only 2K RAM built-in (not 32K).
PC8300 CHARSET
Six characters are different as on ZX81. The charset is located in the ULA chip
without using I register (the ZX81 has it in BIOS ROM, accessed via I=1Eh).
Accordingly, changing the I register doesn't affect video (so neither True
Hires nor Pseudo Hires will work, and any UDG/CHRs hardware expansions won't
work either). The CPU can read the charset via I/O ports (mainly required for
printers).
The video output is reportedly the inverse of ZX81, ie. white text on black
background with black screen border.
PC8300 PRINTERS
The BIOS supports the Sinclair Printer as well as an external Centronics
interface. The Centronics feature includes two modes: ZX chars converted to
ASCII, or ZX chars converted to bitmaps (via ESC codes, which must be supported
by the printer).
PC8300 KEYBOARD
42 Keys. The left 40 keys are same as on ZX81. The upper right key is wired to
/RESET causing a warmboot (pressing /RESET+ENTER forces a coldboot,
/RESET+L_KEY jumps to 2000h in external memory such like ROM, or COLOR RAM).
The lower right key is same as the left SHIFT key. Punctuation marks and
Cursor, Rubout, Edit, Graphics keys are at different location as than in ZX81.
Commands are entered letter-by-letter (eg. type L-O-A-D, unlike pressing J on
ZX81).
PC8300 SOUND
Contains a built-in speaker. The output level can be toggled HIGH/LOW by
reading from an I/O port. Allows to produce a single square wave at fixed
volume (though using PWM, one could eventually mix multiple channels at
variable volume). Since both sound and video require a lot of CPU load, it's
barely possible to output sound & video together. The BEEP (keyclick) is a very
remarkable feature: each key has a different tone assigned, resulting in a
funny melodic old-school SciFi typing effect.
PC8300 SOFTWARE
A few photos of cassettes do exist. As far as known there aren't any tape
images. Strange RAW <--> A83 conversion programs exists (purpose unknown).
PC8300 JOYSTICK
DSUB 9pin Atari-style joystick port (with only four directions and one fire
button implemented). Wired to keyboard matrix Bit3=Common, and
A11 = 2 = Up,
A10 = W = Down,
A12 = 9 = Left,
A9 = S = Right,
A13 = O = Fire
(according to Kai Fischer's schematic).
PC8300 FILES
Cassette files are SAVEd with circa 16000 leading sync pulses (though, this is
a fake, the LOAD function simply ignores them). Followed by a ZX81-style file:
Some silence, followed by the Filename terminated with bit7=1, followed by
memory at [4009h..[4014h]-1]. The memory content isn't ZX81 compatibile though
(different system area, different D_FILE location, different BASIC tokens). The
VERSN byte at 4009h is FFh (unlike 00h on ZX81).
Bits and bytes are encoded same as on ZX81 (0=four pulses, 1=nine pulses, with
same pulse/silence timings).
PC8300 SUPPORT FOR ZX81 FILES
The Lambda BIOS can load ZX81 files, but with several restrictions: The files
are converted to Lambda format (and cannot be converted back to ZX81 format).
Information in the system area (such like Autostart), and VARS and D_FILE
regions are discarded (only the raw BASIC code is accepted).
BUG: After loading a ZX81 file, the BIOS accidently jumps to 2000h, normally
this is a mirror of 0000h which produces a warmboot - however, it'll crash if a
Color RAM expansion is installed (workaround: POKE a RST0 opcode to 2000h), or
accidently start any expansion ROM at 2000h.

PC8300 COLOR EXPANSION


Colors are optionally supported via an external color module. The Lambda BIOS
contains built-in commands (INK/PAPER/BORDER) for it. The module connects to
expansion port, and also to the monochrome composite video output, deciphers
the "analogue" signal into TTL black/white and TTL sync/nosync signals.
Color attribtes are stored in 1K read/write-able RAM at 2000h..23FFh. During
drawing, the module takes the D_FILE address (usually 407Dh..4395h) ANDed with
3FFh as index in the RAM, and reads the color attribute for the current
character. The attributes associated with the HALT opcodes in D_FILE define the
current section of the screen border color. The attribute bytes are Bit0-2 =
INK, Bit4-6 = PAPER/BORDER, bit3,7 can be used as general purpose flags, but do
not affect the video output. The monochrome luminance level selects INK/PAPER,
but otherwise doesn't affect the outgoing signal (eg. PEN=3 and PAPER=3 do
produce exactly the same color & same brightness).
XXX does the border affect the COLOR BURST signal?
XXX and thus alter the colors in the picture region?
XXXXXX the 3bit color values allow to use 8 colors,
XXXXXX but it's unknown WHICH colors?
PC8300 TIMINGS
The INT handler (0038h) is made 1 cycle slower as than on ZX81, meaning that
the Lambda executes 208 clks/scanline (ZX81 only 207 clks).
The NMI handler is "improved" (the useless JP opcode removed, but the JR is
replaced by a JP, so there is no speedup gained, to the worst, there's a
bizarre NOP inserted making NMI handling 4 cycles slower than on ZX81, making
the SLOW mode even slower-than-slow.
PC8300 I/O PORTS
I/O:xxF5h.W ;select charset line number (00..07)
;\use only in FAST mode,
I/O:xxF6h.W ;select charset char number (00..3F)
;/or after HSYNC (NMI)
I/O:xxFBh.W ;printer control (sinclair pixel-style, or ASCII character)
I/O:xxFDh.W ;disable NMIs
I/O:xxFEh.W ;enable NMIs
I/O:xxFFh.W ;terminate retrace / CAS output
I/O:xxF5h.R ;toggle sound output level
I/O:xxF6h.R ;read selected charset data (8 pixels)
I/O:xxFBh.R ;printer status
I/O:NNFEh.R ;read keyboard (A8..A15=row) (and CAS.IN) (and JOYSTICK)
;(but no PAL/NTSC bit here, unlike ZX81)
I/O:FF7Eh.R ;read PAL/NTSC flag (A7=row) (via diode from A7 to KEYB.0)
MEM:00XXh dummy blink addr in write-protected BIOS ROM
MEM:2000h optional boot entryoint (in COLOR RAM, or TS1510-cartirdges)
MEM:2XXXh COLOR ATTRIBUTES (external color module)
MEM:3000h disable color ram (on any write to 3000-3FFE with A0=0)
MEM:3001h enable color ram (on any write to 3001-3FFF with A0=1)
PC8300 System Area
4000 2 unused
4002 2 err_sp
4004 2 ramtop
4006 1 prmode
4007 1 err_nr
4008 1 color
SAVE area...
4009 1 versn
400A 2 nxtlin
400C 2 program
400E 2 df_cc
4010 2 vars
4012 2 dest
4014 2 e_line
4016 2 ch_add
4018 2 x_ptr
401A 2 stkbot
401C 2 stkend
401E 1 flags
401F 2 mem
4021 1 munit
4022 1 df_sz
4023 2 s_top
4025 2 last_k
4027 1 bounce
4028 1 margin
4029 2 e_ppc
402B 2 oldppc
402D 1 flagx
402E 2 strlen
4030 2 t_addr
4032 2 seed

(unlike ZX81: ERR_NR, FLAGS) (not used)


(same as ZX81)
(same as ZX81, but, max 32K)
(unlike ZX81: MODE, cursor shape) (instead: printer mode)
(unlike ZX81: ppc.lsb)
(unlike ZX81: ppc.msb)
(same as ZX81)
(versn, and other temporary flags) (00h=ZX81, FFh=Lambda)
(unlike ZX81: e_ppc)
(unlike ZX81: d_file)
(same as ZX81)
(same as ZX81)
(same as ZX81)
(same as ZX81) (input/workspace buffer, end of SAVE area)
(same as ZX81)
(same as ZX81) (error/abort address)
(same as ZX81)
(same as ZX81) (increases on PUSHes)
(unlike ZX81: berg) (same as 4001h on ZX81)
(same as ZX81)
(unlike ZX81: unused) (tempo for music)
(same as ZX81)
(same as ZX81)
(same as ZX81)
(same as ZX81)
(same as ZX81) (but, derived from other I/O mechanism)
(unlike ZX81: nxtlin)
(same as ZX81)
(same as ZX81)
(same as ZX81)
(same as ZX81)
(same as ZX81)

4034 2 frames
(same as ZX81)
4036 2 ppc
(unlike ZX81: coords) (same as 4007h on ZX81)
4038 1 pr_cc
(same as ZX81)
4039 2 s_posn
(same as ZX81)
403B 1 cdflag
(additional bit4=graphics_cursor, bit5=beep_disable)
403C 33 prbuff
(same as ZX81)
405D 30 membot
(same as ZX81)
407B 2 blink
(unlike ZX81: blink address instead unused)
N/A 1 mode
(no [K],[L],[F] cursors, only [G] = flag in cdflag.bit4)
N/A 1 berg
(none such, memorized somehow elsewhere)
N/A 2 coords
(none such,isn't really used on ZX81 either)
4009
VERSN
Should be 00h to identify ZX81 cassette files
BUG: [400Ch] is NOT properly set after loading ZX81 files, so better use 4396h
than [400Ch].
PC8300 BIOS-MOD
There is also an alternate Lambda BIOS in the internet. It's source is unknown,
it seems to be an commercial or homebrewn BIOS replacement, intended to improve
ZX81 compatibility (called "replacement" because the BIOS doesn't match-up with
the Lambda keyboard, so it's unlikely that Lambda's were sold with that BIOS
built-in).
Patched TS1500 BIOS (around 1K modified, remaining 7K same as in original
BIOS). RAMTOP is hardcoded as 16K (won't work with less memory). Frame rate is
hardcoded as 60Hz. Keyboard layout is same as in ZX81 (cursor keys, punctuation
marks, and token-hotkeys don't match up with the Lambda keyboard). Doesn't
include charset in BIOS (uses the Lambda ULA charset, so, for video and printer
output, six chars are still different as on ZX81).
Fileformat and memory map are exactly same as in ZX81, so it's compatible with
machine code programs with hardcoded ZX81 memory addresses. System area is same
as ZX81, though with some extra bits in 403Bh (bit3=REM n Cursor Blink Enable,
bit4=STEP n Auto-Edit enable, bit5=BEEP n Keyclick Beep disable) and 407Bh
(16bit Cursor address for blink).
BASIC includes some new/modified commands/functions: BEEP n (n=1 enables
keyclick sounds, n=0 disables it), IN/OUT (executes IN/OUT opcode, the port
address is only 8bit wide, not 16bit), STEP n (usually suffix for FOR, but in
this BIOS it can be also as command to edit line "n" and all following/existing
lines), REM n (n=1 enables cursor blink, n=0 disables it).
Jupiter ACE
----------The ACE was manufactured by Jupiter Cantab from England in 1983. It was
designed by two ex-Sinclair Research employees, Steven Vickers and Richard
Altwasser, who earlier worked on the Sinclair ZX-80 and ZX-81, as well as the
Spectrum.
-->
-->
-->
-->
-->

Jupiter
Jupiter
Jupiter
Jupiter
Jupiter

FORTH
--> FORTH
--> FORTH
--> FORTH
--> FORTH
--> FORTH
--> FORTH

ACE
ACE
ACE
ACE
ACE

I/O Ports
Video
Dimensions and Timings
Memory Map and System Area
Files

Overview
Stack and Memory
Maths
Input/Output
...
Error Codes

Links
http://www.jupiter-ace.co.uk/
Jupiter ACE I/O Ports
--------------------Port FEh Read (or any Read with A0=0)
0-4 Keyboard Bits
5
Cassette Input (EAR/LOAD)
6-7 Not used
Any read from this port toggles the speaker "off".
Port FEh Write (or any Write with A0=0)
0-2 Not used
3
Cassette Output (MIC/SAVE)
4-7 Not used
Any write to this port toggles the speaker "on".
Jupiter ACE Video
-----------------

General
For VRAM Addressing & Timings, see:
--> Jupiter ACE Memory Map and System Area
--> Jupiter ACE Dimensions and Timings
Colors
The colors are 0=Black, 1=White, Border=Black (opposite of ZX81). Bit7 of the
character number can be used as invert-attribute.
BIOS charset at 1D7Bh..1FFBh
The ROM character set is slightly compressed (of the 8 character rows, blank
upper/lower rows are omitted for some characters):
Char
Rows
20h..3Eh 7
;1Fh chars (upper row blank) (lower row is used in $,;)
3Fh..5Eh 6
;20h chars (upper and lower row blank)
5Fh..7Eh 7
;20h chars (upper row blank) (lower row is used in _gjpqy)
7Fh
8
;01h char (no blank rows) (copyright symbol)
All character numbers ASCII (except 60h=pounds and 7Fh=copyright).
Video Capabilities
With only 1K Charset RAM, the Jupiter is more restrictive than a ZX Spectrum
(or HiRes ZX81) with 6K Bitmap RAM. On the other hand, there's more CPU load
available than on ZX81, so the Jupiter has some potential.
Possible would be games with not too detailed graphics (like racing games which
have relative featureless BG graphics, or shoot-em-ups without BG graphics,
etc.)
Another approach would be a medium-resolution Bitmap with 128x96 pixels (using
128 characters with 4x4 pixel "block graphics", and their inverses, giving 256
characters in total).
Jupiter ACE Dimensions and Timings
---------------------------------The Z80 CPU is clocked at 3.25MHz. Picture size is 256x192 pixels.
Horizontal Timings
Phase__________Dotclock_______________=_CPU Clock___________
Hsync
32 pixels (320..351) = 16 clks
Left Border
64 pixels (352..415) = 32 clks
Picture
256 pixels (0..255)
= 128 clks
Right Border
64 pixels (256..319) = 32 clks
Total
416 pixels (0..415)
= 208 clks
Vertical Timings
Phase__________50_Hz_version__________60_Hz_Version_______
Vsync
8 lines (248..255)
8 lines (224..231)
Upper Border
56 lines (256..311)
32 lines (232..263)
Picture
192 lines (0..191)
192 lines (0..191)
Lower Border
56 lines (192..247)
32 lines (192..223)
Total
312 lines (0..311)
264 lines (0..311)
Note: There are separate mainboards for 50Hz/60Hz (ie. the framerate isn't
software selectable).
VSYNC Interrupt
The default interrupt handler at 0038h isn't too useful, however, one can put a
custom IM2 interrupt handler in RAM. The Z80's /INT pin is wired directly to
/VSYNC. This implies two problems:
1) The /VSYNC signal is LOW for 8 scanlines (1664 cycles), so, the IRQ handler
should not re-enable IRQs during that period (otherwise the same interrupt
would be executed another time). If necessary include a 1664-cycle delay in the
IRQ handler, or return without enabling IRQs.
2) For flicker/waitstate-free drawing, it'd be ideal to access VRAM during
VBLANK, but since /INT is generated on VSYNC rather than VBLANK, one can use
only little more than half of the VBLANK periond.
Jupiter ACE Memory Map and System Area
-------------------------------------Jupiter ACE Memory Map
0000h-1FFFh R
BIOS ROM (8K) (FORTH Interpreter)
2000h-23FFh R/W VRAM BgMap/Pad with CPU priority (video DMA shows garbage)
2400h-27FFh R/W VRAM BgMap/Pad with DMA priority (CPU gets paused by /WAIT)
2800h-2BFFh W
VRAM Charset with CPU priority
(video DMA shows garbage)
2C00h-2FFFh W
VRAM Charset with DMA priority
(CPU gets paused by /WAIT)
3000h
R/W Unused (mirrors of 1K Work RAM)
3C00h
R/W Work RAM (1K)
4000h-FFFFh R/W Expansion RAM (or open-bus if none such)
The total amount of internal RAM is 3K (the CPU/DMA priority regions mirror to
a single 1K VRAM block).

Note: BgMap/Pad contains 300h bytes BgMap, followed by 100h bytes Pad (the Pad
is used to HOLD characters during formatted output, and to store filenames and
fileheaders during load/save).
Jupiter ACE System Area
FP_WS
3C00h 19 Workspace for floating point arithmetic
LISTWS 3C13h 5 Workspace for 'LIST' and 'EDIT'
RAMTOP 3C18h 2 Work RAM End Address (4000h=1K, 8000h=17K, 0000h=49K)
HLD
3C1Ah 2 VRAM PAD Address of the latest character held in the pad by
formatted output ('#', 'HOLD' and so on)
SCRPOS 3C1Ch 2 VRAM Output Address: location of next char to be printed
INSCRN 3C1Eh 2 VRAM InputBuf Address: start of current logical line
CURSOR 3C20h 2 VRAM InputBuf Address: cursor addresss in input buffer
ENDBUF 3C22h 2 VRAM InputBuf Address: end of current logical line
L_HALF 3C24h 2 VRAM InputBuf Address: input buffer start (ends at 26FFh)
KEYCOD 3C26h 1 Keyboard ASCII code of the last key pressed (00h=none)
KEYCNT 3C27h 1 Keyboard Debounce counter (key accept and repeat delay)
STATIN 3C28h 1 Keyboard Flags (0=newkey,1=caps,2=graph,3=invert,5=enter)
EXWRCH 3C29h 2 Address of print chr(A) routine (or 0000h=print to screen)
FRAMES 3C2Bh 4 Frames counter (number of /VSYNC interrupts since power-on)
XCOORD 3C2Fh 1 PLOT last used x-coordinate
YCOORD 3C30h 1 PLOT last used y-coordinate
CURRENT 3C31h 2 Vocabulary Address of CURRENT vocabulary
CONTEXT 3C33h 2 Vocabulary Address of CONTEXT vocabulary
VOCLNK 3C35h 2 Vocabulary Address of NEWEST vocabulary (plus 3)
STKBOT 3C37h 2 Work RAM Address of End of Dictionary / Start of Stack
DICT
3C39h 2 Work RAM Address of the (still undefined) length field of
the newest word in the dictionary (once when that length
field is correctly filled in then DICT may be 0000h)
SPARE
3C3Bh 2 Work RAM Address of first byte past top of the FORTH stack
ERR_NO 3C3Dh 1 Error code (FFh=no error) (ERROR shown on ABORT if bit7=0)
FLAGS
3C3Eh 1 Flags...
Bit2 incomplete definition at the end of the dictionary
Bit3 output is to be fed into the input buffer
Bit4 the Ace is in invisible mode
Bit6 the Ace is in compile (editing) mode
BASE
3C3Fh 1 The system number base (default is 0Ah=decimal)
3C40h 5 FORTH name string "FORTH"+80h
3C45h 2 FORTH disp to next word (or 0000h if no next)
3C47h 2 FORTH ptr to 1FFFh in ROM (links to ROM words)
3C49h 1 FORTH length of "FORTH" name at 3C40h (ie. =05h)
3C4Ah 2 FORTH ptr to 11B5h in ROM (vocabulary handler)
3C4Ch 2 FORTH ptr to next word in chain (or to 3C49h if none)
3C4Eh 1 FORTH unknown/unused (usually 00h)
3C4Fh 2 FORTH ptr to previous vocabulary (always 0000h=none)
3C51h .. user dictionary
Jupiter ACE Files
----------------Forth File Headers
Pre 1 Blocktype (00h=Header)
00h 1 Filetype (00h=Forth)
01h 10 Filename (ASCII, padded with spaces) (chr 00h = no name)
0Bh 2 Filesize (LEN=STKBOT-3C51h)
0Dh 2 Unused
(usually 3C51h, dictionary start address)
0Fh 2 Offset to newest word at end of file (relative to 3C51h)
11h 2 Unused
(usually 3C4Ch, CURRENT vocabulary)
13h 2 Unused
(usually 3C4Ch, CONTEXT vocabulary)
15h 2 Unused
(usually 3C4Fh, NEWEST vocabulary+3)
17h 2 Unused
(usually 3C51h+filesize, STKBOT)
Post 1 Chksum [00h..18h] XORed together (unlike Spectrum without Blocktype)
The file body is loaded to the begin of free memory (3C51h when memory is
empty). Addresses inside of the file body are relative to 3C51h (if the file is
loaded to a higher memory location, then the addresses are increased
accordingly).
Binary
Pre
00h
01h
0Bh
0Dh
0Fh
Post

File Header
1 Blocktype (00h=Header)
1 Filetype (20h=Binary)
10 Filename (ASCII, padded with spaces) (chr 00h = no name)
2 Filesize (LEN)
2 Fileaddr (Default target address, used when desired target=0)
10 Unused
(filled with spaces)
1 Chksum [00h..18h] XORed together (unlike Spectrum without Blocktype)

File Body
Pre 1
Blocktype (FFh=Body)
00h LEN Forth stuff (starting with 1st word name) / Binary Data
Post 1
Chksum [00h..LEN-1] XORed together (unlike Spectrum without Blktyp)

Cassette Signals
The overall format is nearly identical to ZX Spectrum. On the ACE, the Chksum
doesn't include the Blocktype byte. The bit-encoding and various pilot/data
pulse timings are identical as on spectrum (+/- 5 us or so, which can be
ignored). The number of Pilot pulses is slightly different (8192 for header,
1024 for data) (on Spectrum it's 8063 for Header, and 3223 for Data).
.TAP Images
Jupiter ACE cassette images are stored in .TAP files, using the same extension,
and (almost) the same format as ZX Spectrum .TAP files - the difference is that
Jupiter ACE images do not contain Blocktype bytes (software must insert the
missing byles: toggle between FFh or 00h on each second block). Most or all
.TAP images are starting with a header block, so the first 2 bytes in the file
should be 0019h for Jupiter ACE, and 0013h for ZX Spectrum.
Forth
Pos
-N
-4
-2
+0
+1
+3

Word Definitions
Len Content
.. word name in ASCII (terminated by bit7=1 in last char)
2
disp from current addr to NEXT <word name> (RAM words only, not ROM)
2
ptr to PREVIOUS word definition
1
length of word name (up to including the last char with bit7=1)
2
ptr to Z80 machine code handler for this word (usually to ROM)
.. whatever, probably TYPE and definition...
3C40h
3C45h
3C47h
3C49h
3C4Ah
3C4Ch

5
2
2
1
2
2

FORTH
FORTH
FORTH
FORTH
FORTH
FORTH

name string "FORTH"+80h


disp to next word (or 0000h if no next)
ptr to 1FFFh in ROM (links to ROM words)
length of "FORTH" name at 3C40h (ie. =05h)
ptr to 11B5h in ROM
ptr to next word in chain (or to 3C49h if none)

Starting files
There is no (intended) autostart mechanism provided. The normal way to load and
start ACE files is bizarre and usually requires detailed loading instructions:
One must know both the name of the file, and name of its "main" function, in
some cases one must also manually execute initialization functions. For example
Jupiter Cantab's "Worms" is - seriously - meant to be started like so:
LOAD worms GET graphics GO
If the names are unknown one can do: To discover file names: Type <LOAD dummy>,
watch the first filename listed on screen, rewind tape, type <LOAD filename>.
To discover function names: Type VLIST, watch the function/variable names
(watch quickly - before they get scrolled offscreen). Then try typing some of
the names, hoping that it's the main function (variables will produce errors,
subfunctions may act useless) (to start with: <FILENAME>, GO, RUN, PLAY, START,
MAIN, GAME, etc. would be possible candidates) (some programs may have multiple
main funtions, eg. PLAY/HELP, or PLAY_EASY/PLAY_DIFFICULT).
Empty Filenames
The BIOS doesn't allow to SAVE something without filenames, however, it can
LOAD such files (so, with suitable tools, one can create files with empty,
space-padded filenames). There is no "wildcard" to LOAD the first file on tape,
so - unless it's empty - the user must always type-in the filename.
Autostarting Files
There are two ways to autostart binary files by just typing "0 0 BLOAD" (or "0.
BLOAD"):
1) Load the entrypoint to EXWRCH in system area (EXWRCH gets executed almost
immediately after loading when the BIOS wants to display "OK"). This method is
best for machine code.
2) Load a commandline string into the Input Buffer in VRAM (ie. load <00h,"LOAD
filename mainfunction"> to address 22E0h). This method is best for FORTH
programs, and existing (older) files which originally didn't include autostart.
The VRAM method is used by Spacefighter (also loads a picture into VRAM
alongside with the commandline). The EXWRCH method is used by Magic Floor.
Autostarting works only with BLOAD, not with LOAD (the FORTH fileheader doesn't
include any useful entries; the relocation feature could be tweaked to add an
offset to whatever memory locations, but that offset is usually 0000h, so it'd
be useless).
FORTH Overview
-------------Stack
Stack Notation
c
flag
n
u
x

Cells
1
1
1
1
1

Description
Character (high byte ignored)
Boolean (0 = False, 1 = True)
Signed 16bit number
Unsigned 16bit number
Non-specific 16bit number

adr
1
Memory address (16bit)
d
2
Signed 32bit double number
ud
2
Unsigned 32bit double number
xd
2
Non-specific 32bit number
f
2
Floating point 32bit number
Each stack cell is 16bit wide, the cells do not contain type information, so
the programmer must take care to use the correct commands on each cell.
Word definitions
Defining a word (a procedure, variable, etc.) doesn't erase old words with the
same name, same applies when LOADing words from tape. So, it can happen that a
word is defined multiple times, of which, fortran will "see" the newest
definition; one can also make "newer" definitions of the predefined ROM words.
FORTH Stack and Memory
---------------------Stack Manipulation
x
(--> x)
f
(--> f)
DROP (x -->)
DUP
(x --> x x)
OVER (x2 x1 --> x2 x1 x2)
PICK (xn..x1 n --> xn..x1 xn)
SWAP (x2 x1 --> x1 x2)
ROT
(x3 x2 x1 --> x2 x1 x3)
ROLL (xn..x1 n --> xn-1..x1 xn)
?DUP (x --> x (x))
>R
(x -->) (R: --> x)
R>
(R: x -->) (--> x)
Memory
@
!
C@
C!

(adr --> x)
(x adr -->)
(adr --> c)
(c adr -->)

Store 16bit immediate on stack (eg. 1)


Store float immediate on stack (eg. 1.0)
Discard TOS (top of stack)
Copy 1st cell to top (Duplicate TOS)
Copy 2nd cell to top
Copy nth cell to top
Rotate 2nd cell to top
Rotate 3rd cell to top
Rotate nth cell to top
Conditional DUP, only if x = non-zero
Move TOS to Return Stack
Retrieve from Return Stack

Read x (2 bytes) from adr


Store x (2 bytes) to adr
Read c (1 byte) from adr
Store c (1 byte) to adr

FORTH Maths
----------Integer Arithmetic
+
(n1 n2 --> n3)
(n1 n2 --> n3)
*
(n1 n2 --> n3)
/
(n1 n2 --> n3)
MOD
(n1 n2 --> n3)
/MOD
(n1 n2 --> n3 n4)
*/
(n1 n2 n3 --> n4)
*/MOD
(n1 n2 n3 --> n4 n5)
1+
(n1 --> n2)
1(n1 --> n2)
2+
(n1 --> n2)
2(n1 --> n2)
ABS
(n --> u)
NEGATE (n1 --> n2)
U*
(u1 u2 --> ud)
U/MOD
(ud u1 --> u2 u3)
D+
(d1 d2 --> d3)
DNEGATE (d1 --> d2)

n3 = n1 + n2
n3 = n1 - n2
n3 = n1 * n2
n4 = n1 / n2
Remainder of n1 / n2 (sign of n1)
n3 = remainder of n1/n2, n4=n1/n2
n4 = n1*n2/n3
n4 = remainder of n1*n2/n3, n5=n1*n2/n3
n2 = n1 + 1
n2 = n1 - 1
n2 = n1 + 2
n2 = n1 - 2
u = |n| (absolute value)
n2 = -n1 (two's complement)
ud = u1 * u2
u2 = remainder of ud/u1, u3 = ud/u1
d3 = d1 + d2
d2 = -d1 (two's complement)

Floating Point Arithmetic


INT
(f --> n)
UFLOAT (u --> f)
F+
(f1 f2 --> f3)
F(f1 f2 --> f3)
F*
(f1 f2 --> f3)
F/
(f1 f2 --> f3)
FNEGATE (f1 --> f2)

Convert floating number to integer


Convert unsigned integer to float
f3 = f1 + f2
f3 = f1 - f2
f3 = f1 * f2
f3 = f1 / f2
f2 = -f1

Comparison
<
(n1 n2
=
(n1 n2
>
(n1 n2
0<
(n -->
0=
(n -->
0>
(n -->
U<
(u1 u2
D<
(d1 d2
MAX
(n1 n2
MIN
(n1 n2

True if n1 < n2
True if n1 = n2
True if n1 > n2
True if n < 0
True if n = 0
True if n > 0
True if u1 < u2
True if d1 < d2
Leave greater of two numbers
Leave lesser of two numbers

--> flag)
--> flag)
--> flag)
flag)
flag)
flag)
--> flag)
--> flag)
--> n3)
--> n3)

Logical
AND
OR
XOR

(x1 x2 --> x3)


(x1 x2 --> x3)
(x1 x2 --> x3)

Bitwise boolean AND


Bitwise boolean OR
Bitwise boolean XOR

FORTH Input/Output
-----------------Character Output
CR
(-->)
EMIT
(c -->)
SPACE
(-->)
SPACES
(n -->)
." ..."
(-->)
TYPE
(adr n -->)
Number Output
.
(n -->)
U.
(u -->)
F.
(f -->)

Print
Print
Print
Print
Print
Print

Formatted
<#
#
#S
HOLD
SIGN
#>

Print n with one trailing space


Print unsigned with one trailing space
Print float with one trailing space

Output
(-->)
(ud1 --> ud2)
(ud --> 0 0)
(c -->)
(n -->)
(ud --> adr n)

Initiate formatted output


Convert one digit from ud1 and HOLD it in the PAD
Convert and HOLD all remaining significant digits
Insert character into formatted string
HOLD minus sign if n < 0
Finish formatted output leaving address & length
of the resulting string

Conversion
BASE
(--> adr)
DECIMAL
(-->)
ASCII text (--> c)

1-byte variable containing system number base


Set base to decimal
ASCII code of first character in text

Character Input
QUERY
(-->)
WORD
(c --> adr)
RETYPE
INKEY

( --> )
(--> x)

carriage return and line feed


ASCII character c
one space
n spaces, if n > 0
string terminated by " (." 123 test")
n characters from adr

Accept entry at the input buffer


Take text from input buffer using c
as delimiter, leave adr of length byte
Allow input buffer editing, turning cursor to "?"
Read keyboard (0 = no key pressed)

Number Input
CONVERT (d1 adr1 --> d2 adr2)
NUMBER

(-->
(-->
(-->
(-->

x (adr))
n 4102)
f 4181)
0)

Convert string at adr1 to double number


and add into d1 leaving result d2
Get number from input buffer
Converted to integer
Converted to float
Conversion failed

Misc Screen Output


CLS
(-->)
Clear screen
AT
(n1 n2 -->)
Set print position to row n1 and column n2
PLOT (n1 n2 n3 -->) Plot X=n1,Y=n2,Mode=n3 (0=unplot,1=plot,2=move,3=change)
FORTH ....
---------Control Structures
IF
(flag -->)
ELSE
(-->)
THEN
(-->)
DO
(n1 n2 -->)
LOOP
(-->)
+LOOP
(n -->)
I
(--> n)
I'
(--> n)
J
(--> n)
LEAVE
(-->)
BEGIN
(-->)
UNTIL
(flag -->)
WHILE
(flag -->)
REPEAT (-->)
EXIT
( --> )
EXECUTE (adr -->)
CALL
(adr -->)
ABORT
(... -->)
QUIT
(-->)

Conditional structure IF..(ELSE)..THEN


False condition of an IF structure
End of an IF conditional structure
Counted loop structure DO...LOOP, (n2=start, n1=end)
Increment loop count, terminate if end
Add n to loop count, terminate if end
Get current loop count
Get current loop count limit
Get outer loop count
Force a DO...LOOP count to end
Begin a WHILE or UNTIL loop
Loop until flag = true (BEGIN..UNTIL)
Exit loop when flag = false (BEGIN..WHILE..REPEAT)
Jump back to BEGIN in a WHILE loop
Exit current word execution
Execute word with compilation adr
Call Z80 code (terminated with JP IY) (not by RET)
Quit program, clearing data stack
Quit program, not clearing data stack

Word Definition
: pname ... ;
VARIABLE vname
CONSTANT cname
CREATE aname
ALLOT
vname
aname
cname
pname
IMMEDIATE
DEFINER word
DOES>
COMPILER word
RUNS>
FIND word
LIST word
EDIT word
FORGET name
REDEFINE name
Vocabulary
VOCABULARY dname
dname
FORTH
DEFINITIONS
CONTEXT
CURRENT
VLIST

(-->)
(x -->)
(x -->)
(-->)
(n -->)
(--> adr)
(--> adr)
(--> x)
(-->)
(-->)
(-->)
(--> adr)
(n -->)
(--> adr)
(--> adr)
(-->)
(-->)
(-->)
(-->)

Compiler
,
C,
LITERAL
[ ... ]

(-->)
(-->)
(-->)
(-->)
(--> adr)
(--> adr)
(-->)

Define a procedure (terminated by semicolon)


Define a variable with initial value x
Define a constant with constant value x
Define an (empty) array (usually followed by ALLOT)
Allocate n bytes at end of newest word (see CREATE)
Get variable adr (eg. "vname @" to get its value)
Get array address
Get constant value
Call a procedure
Make newest word to execute even in compile mode
Start a defining word definition
Define the action routine of a defining word
Start a compiling word definition (and ALLOT n)
Defines the action routine of a compiling word
Find word compilation address (0 if not found)
List word definition
Edit word definition (doesn't delete old word)
Delete <name> as well as ALL newer words
Delete old <name> and replace it by newest word

(x -->)
(c -->)
(x -->)
(... -->)

Miscellaneous
( ...) (-->)
HERE
(--> adr)
PAD
(--> adr)
SLOW
(-->)
FAST
(-->)
?)
BEEP
(u1 u2 -->)
IN
(adr --> c)
OUT
(c adr -->)
INVIS (-->)
VIS
(-->)
LINE
(-->)

Define a new vocabulary


Set CONTEXT to the <dname> vocabulary
Set CONTEXT to the FORTH vocabulary
Set CURRENT vocabulary to CONTEXT
Get current word search vocabulary address ;3C33h
Get current word definition vocabulary addr ;3C31h
List dictionary to screen (press BREAK to stop it)
Compile x
Compile c
Compile x
Force ...

into dictionary (ALLOT 2 byte,


into dictionary (ALLOT 1 byte,
into edited procedure (preceed
to be interpreted (even during

set to x)
set to c)
by [ x ])
EDITing)

Start a comment, terminated by ")"


Next available dictionary location, ie. [STKBOT]
Scratch pad area address (2701h aka 9985)
Normal execution. Enable error checks
Faster execution. Disable error checks (and BREAK-key
Play tone, u1=1000000/(8*freq [Hz]), u2=duration [ms]
Read byte from Z80 input port adr
Write byte to Z80 output port adr
Disable copy-up mechanism and OK
Enable copy-up mechanism and OK
Interpret the input buffer as FORTH

Tape Files
LOAD name
(-->)
Load vocabulary
;\lists all filenames
VERIFY name
(-->)
Verify vocabulary
;/when no name typed
SAVE name
(-->)
Save vocabulary
BLOAD name
(adr u -->) Load u bytes to adr
;\use file header value(s)
BVERIFY name (adr u -->) Verify u bytes from adr ;/when adr=0 or u=0
BSAVE name
(adr u -->) Save u bytes from adr
filenames are case sensitive, length must be 1-10 characters, may not include
space characters.
CAUTION: The filenames are ALWAYS taken from the input buffer - that means one
cannot specify filenames inside of procedures (unless the procedure 'pokes' the
filename into the input buffer in VRAM before executing a cassette command).
FORTH Error Codes
----------------Error Codes
1 Not enough memory
2 Data Stack Underflow
3 BREAK pressed
4 Compile only word
5 Structure imbalance
6 Name size < 1 or > 64
7 PICK or ROLL operand = 0
8 Floating point overflow
9 AT or PLOT to the input buffer
10 Tape error
11 REDEFINE or FORGET error
12 Incomplete definition in dictionary

13 Word not found or is ROM or is FORTH


14 Word not Listable
Z80 Local Usage
--------------CPU and System Clock Overview
The ZX81 is equipped with a NEC D780C-1 CPU (fully compatible to Zilog Z80
CPUs, including for undocumented opcodes & flags). The CPU is operated at 3.25
MHz (generated by a 6.5MHz oscillator with very high tolerance - my ZX81
appears to be rather ticking at 3.33MHz even though the oscillator DOES have
the value 6.5 printed onto it) the available CPU time is reduced when the
display is enabled. The ZX81 produces a /WAIT signal for the duration while a
NMI is requested, otherwise the CPU runs free of waitstates.
Vectors, Registers and Memory Overview
The INT, NMI, and RST vectors are located in ROM and cannot be changed by
software. The AF' register (ie. EX AF,AF), the IX register, and IR register
(interrupt/refresh) are reserved for video and should be normally not used,
except in FAST mode. Attempting to execute program code stored at addresses
8000h-FFFFh is interpreted as video data (if the opcodes Bit 6 was set), if so,
a NOP opcode is forwarded to the CPU.
Using Machine Code
A machine code program is called by using the USR function, for example by
using the BASIC expression "LET N=USR <startaddress>", startaddress must be a
decimal number (hex numbers are not supported). If the machine code program
returns to BASIC, the content of the BC register is used as return value. For
info about storing binary data/machine code, see Memory chapter.
BASIC Interpreter
----------------The
-->
-->
-->
-->
-->
-->

BASIC
BASIC
BASIC
BASIC
BASIC
BASIC
BASIC

Interpreter
Editor
Commands
Functions
Error Codes
Programs and Variables (ZX81/Spectrum)
Programs and Variables (ZX80)

BASIC Editor
-----------This chapter explains ZX81 keyboard modes and key-combinations. The table with
all keywords/characters assigned to each key can be found here:
--> ZX80/ZX81 Keyboard Assignment
--> Spectrum Keyboard Assignment
Special Keys
Key
Name
Expl.
Equivalent/emulated PC Key
Ret
NEWLINE
Confirm Input
Enter
Space
BREAK
Stops the program!
Space
Shift+0
RUBOUT
Deletes a character
Backspace
Shift+1
EDIT
Edits [>] Cursor selected line
Shift+5/8 <CURSOR> Moves Cursor left/right in input buffer Cursor Keys
Shift+7/6 <CURSOR> Moves [>] Cursor up/down in listing
Cursor Keys
Shift+9
GRAPHICS Switches to [G] Graphics Cursor Mode
Alt
Shift+Ret FUNCTION Switches to [F] Function Cursor Mode
Control
Beside for these general special keys, all ZX81 keys are behaving kinda
special, depending on various input modes as shown below.
[K] Cursor - Keyword Mode (Expecting Keywords and/or Line Numbers)
This mode is automatically used at the beginning of each line (and after THEN).
At the beginning of line, a line number can be entered by using 0-9 keys.
Character keys are interpreted as command keywords (for example, P=PRINT). Some
commands must be entered as SHIFT combinations (for example, SHIFT+F=FAST).
Entering a line number without keyword deletes the specified line.
[L] Cursor - Letter Mode (Expecting Operands or Functions)
This mode is automatically selected after entering a keyword in [K] mode.
Allows to enter expressions, such like "HELLO" or 1234.5678. When SHIFT is held
down, functions/operators such like +,-,*,>=,OR,AND can be entered (for
example, SHIFT+W=OR), note that typing "OR" as characters by pressing "O", "R"
will result in syntax errors.
[F] Cursor - Function Mode (Expecting Functions) (ZX81 only)
This mode is entered by pressing SHIFT+ENTER from inside of [L] Mode, allowing
to enter functions such like L=USR, U=CHR$ which cannot be entered in [L] mode

directly.
[G] Cursor - Graphics Mode (Inverted Text and Block Graphics) (ZX81 only)
This mode is entered by pressing SHIFT+9 from inside of [L] Mode, allowing to
enter inverted characters (including inverted SPACE).
When keeping SHIFT held down, all combinations of Block Graphics can be entered
(for example, SHIFT+1=Dot-in-upper-left).
[>] Cursor/Symbol - Currently selected line
This cursor isn't part of the input line. Instead, it is displayed in the
program listing (if any) in the upper screen area. The cursor can be moved by
UP/DOWN key combinations (SHIFT+7/6), causing the listing to be scrolled if
necessary.
The EDIT key combination (SHIFT+1) copies the line that is currently selected
by the [>] Cursor to the input buffer (overwriting any old input).
[S] Symbol - Syntax Error
This is not actually a cursor, when entering an incorrect line, the [S] symbol
appears, indicating the fault position, and prompting the user to repair the
problem.
Note
The ZX80/ZX81 allows only one command per line. On the Spectrum, multiple
commands can be separated by ":" colons.
BASIC Commands
-------------BEEP n,n (Spectrum only)
Plays a sound via ULA port FEh. The 1st parameter
seconds (or fractions thereof, like 0.5), the 2nd
in semitones above middle C (or below thereof, if
software generated, so the program becomes paused

specifies the duration in


parameter specifies the pitch
negative). The waveform is
during beep.

BORDER n (Spectrum only)


Changes the screen border color (0..7).
CLEAR [n]
Erases all variables and frees up memory. The optional parameter changes RAMTOP
(supported on Spectrum only).
CIRCLE x,y,radius (Spectrum only)
Draws a circle.
CLS
Clears the screen.
CONT (called CONTINUE on ZX80/Spectrum)
Works much like GOTO, continues the program in the current line, or in the next
line if program has been halted by STOP.
COPY (ZX81/Spectrum only)
Sends a screen copy to the printer (if connected). Only topmost 32x22
characters are printed, ie. excluding bottommost 2 lines.
DATA item[,item[,item]] (Spectrum only)
Contains expressions (numbers, variables, or quoted strings) which may be
loaded into variables via READ command. DATA is just a data definition, not an
executable command (trying to execute DATA lines acts as REM lines).
DEF FN v(v1,v2,etc)=expression (Spectrum only)
Creates a user defined function. The function name must be a single letter
expression (like x or a$). For example, "DEF FN s(a)=a*a" would cause "FN s(n)"
to act identical as "n**2".
DELETE [n],[m] (Timex TS2068/TC2068 only)
Deletes BASIC line numbers n..m. Defaults to from 1st/to last line if n/m are
omitted. Note: To delete a single line, simply enter its line number and press
Enter.
DIM b(n1,...,nk) or DIM b$(n1,...,nk)
Defines dimensions for an array. All values (or strings) in the array are reset
to 0, (or SPACE-filled for strings/characters). The lastmost dimension of a
character array indicates the string length. For example, DIM A$(x,y,z) could
be accessed either as three-dimensional character array A$(x,y,z), or as
two-dimensional string array A$(x,y) with LENGTH=z.
The ZX80 supports only one-dimensional numeric arrays, ie. no multi-dimensional
arrays, and no string/character arrays.
DRAW x,y[,angle] (Spectrum only)

Draws a line (from most recent DRAW/PLOT/CIRCLE position) to x,y. The 3rd
parameter allows to draw curved lines (angle should be below +/-2*PI).
FAST (ZX81 only)
Switches to FAST mode, the CPU focuses on program execution only (approx. 4
times faster) and the display becomes black until end of program, or until
switching to SLOW mode. Also, the screen becomes temporarily enabled during
PAUSE or INPUT periods.
The ZX80 is always operating in 'FAST' mode.
FOR b=x TO y [STEP z]
Defines the begin and range of a FOR-NEXT loop, the default STEP is +1. The
ZX80 doesn't support the STEP operand.
GOSUB n (called GO SUB on ZX80/Spectrum)
Saves RETURN address on GOSUB stack, and jumps to the specified line number,
see GOTO for details.
GOTO n (called GO TO on ZX80/Spectrum)
Jumps to the specified line number. An immediate, a variable and/or other
expression may be used as line number, such like "GOTO A*10+230".
IF x THEN command
Executes command if x<>0 (eg. if an expression like "A=0" is true). The ZX does
not understand "THEN n" as alias for "THEN GOTO n".
INK/PAPER/FLASH/BRIGHT n (affects VRAM attributes) (Spectrum only)
INVERSE/OVER n (affects VRAM bitmap) (Spectrum only)
Changes parameters for following printing/drawing operations (like PRINT,
INPUT, PLOT, DRAW, CIRCLE).
INK/PAPER can be a color number in range 0..7, or 8=transparent, FLASH/BRIGHT
can be 0=off, 1=on, or 8=transparent, transparent means that the old attribute
value in VRAM is left unchanged. INVERSE/OVER can be 0=off, or 1=on. INVERSE
inverts the character data when printing, or causes pixels to become 0 when
drawing. OVER causes the new character/pixel data to be XORed with the old VRAM
bitmap content.
INK/PAPER/FLASH/BRIGHT/INVERSE/OVER can be used as "standalone" commands
(affecting all following printing/drawing commands) (eg. "INVERSE 1"), or as
"temporary" parameters inserted between a printing/drawing command and its
parameters (affecting only that command) (eg. "PLOT INVERSE 1;x,y" is
equivalent to UNPLOT x,y).
Note: Another way to use colors in printing is to use "hidden" tokens, like
typing PRINT"Hello {INK RED}Test", where {INK RED} is entered as EXT+SHIFT+2.
The {INK RED} token isn't displayed in text form when listing/editing the
program, it just causes the following characters to be drawn in red (this
method was supported only by the original 48K BASIC, and was discontinued in
128 BASIC).
INPUT ["text",] [LINE] v
Prompts the user to enter a value (or string) to be assigned to v. In FAST
mode, the display is temporarily re-enabled. Program is breaked if user enters
STOP as first character.
Strings must enclosed in quotes (otherwise any text input is treated as a
variable). Adding the LINE keyword allows to enter strings without quotes
(Spectrum only). "text" is an optional message displayed on the screen
(Spectrum only).
LET v=e
Assigns e to the variable v. The ZX does not understand "v=e" as alias for "LET
v=e". In case that v is a string-fragment, ie. A$(..TO..), the TO-length
remains unchanged, and truncated/space padded string is assigned to the
TO-area.
LIST [n]
Lists the program on the screen. The default starting line number is 0. Use
CONT to continue if program does not fit onto screen.
LLIST [n] (ZX81/Spectrum only)
Lists the program to the printer.
LOAD f
Loads a memory image from cassette. When specifying an empty filename, ie. LOAD
"", the first encountered file is loaded. Text display is suspended during
loading, white lines are shown on the screen when receiving cassette signals.
The program and all variables that are already in memory become overwritten.
The memory image contains all memory from 4009h up to (4014h), ie. most of the
system area, the actual BASIC program, the video memory, and any defined
variables. The program is automatically started, continuing at the next line
number, if it has been saved from <inside> of a running program.
The ZX80 does not support filenames, just type LOAD and hit NEWLINE.

LPRINT (ZX81/Spectrum only)


Works much like PRINT, but outputs to the printer. AT may be used to specify a
horizontal position inside of the currently printed line.
Bug: Numbers with more than one zero in their fractional portion aren't
displayed properly, for example, LPRINT 0.00001 does output "0.0XYZ1" (this bug
appears only with the ZX81/TS1000 BIOS, it's fixed in the TS1500, Lambda 8300,
and Spectrum BIOSes).
NEW
Restarts BASIC. The program, all variables, and all further memory up to RAMTOP
are erased. In the ZX80 this is equivalent to CALL 0.
NEXT b
Adjusts b as specified in the corresponding FOR command, and (if the target
condition has not been reached or exceeded) loops back to the line following to
the FOR command. The ZX does not understand "NEXT" as alias for "NEXT b".
ON ERR command (Timex TS2068/TC2068 only)
Defines error handling. command can be combined GOTO, CONT, or RESET.
OUT n,m (Spectrum only)
Writes a byte (m) to the specified 16bit I/O address (n).
PAUSE n (ZX81/Spectrum only)
Pauses the program for n/50 seconds (assuming 50Hz display refresh rate) or
until the user hits a key, and displays the screen for the duration of this
period (even if display was disabled by FAST mode). The highest allowed value
for n is 32767. Note that hitting the BREAK key (SPACE) stops the program
rather than continuing it. On the Spectrum, PAUSE 0 waits endless (until a key
is pressed).
PLAY string1[,string2[,string3]] (Spectrum 128/+2/+2A/+3 only)
Plays up to three sounds (on the three PSG sound channels). The strings are
composed of following characters:
c-b Play note within current octave
(c,d,e,f,g,a,b)
C-B Play note within next higher octave (C,D,E,F,G,A,B)
$
Flattens note following it (can be more flattened by $$ or $$$ etc.)
#
Sharpens note following it (can be more sharpened by ## or ### etc.)
&
Play silence (a pause of same length as normal c-b and C-B notes)
_
Tied notes (eg. "5_7c" = crotchet c and a minim c tied together)
On
Set current octave (0..8)
Tn
Set tempo (60..240)
n
Set length of notes (1..12) (use "Nn" if preceeded by other digits)
Nn
Separates two numbers (eg. octave=1,length=2 --> O1N2, instead of O12)
Vn
Set volume level (0..15) (0=Off, 15=Loudest)
Wn
Set volume envelope type (0..7) (bit0=ATTACK, bit1=HOLD, bit2=REPEAT)
Xn
Set volume envelope frequency (0..65535) (affects all 3 channels)
U
Turn on volume envelope in any string
(
Set loop start (if none specified: default is begin of string)
)
Jump to loop start (repeat 2x, multiple brackets can repeat 4x,8x,16x..)
))
Jump to loop starts (repeats endless if only ONE loop start was defined)
! ! Enclose a comment
H
Stop PLAY command (stops all 3 channels, including endless looping ones)
Mn
Configure PSG channels (bit0..2=Tone A..C, bit3..5=Noise A..C)
Yn
Turn on MIDI channel (1..16)
Zn
Send MIDI programming/configuration code (numbers depend on hardware)
Although the sounds are hardware generated, the program gets paused until the
PLAY command has finished, which is making the feature rather useless.
PLOT x,y (ZX81/Spectrum only)
ZX81: Draws a black dot (of 4x4 pixels, ie. one quarter of a 8x8 pixel
character) at the specified position by using graphics characters. Spectrum:
Draws a single pixel. For both ZX81/Spectrum: The origin (0,0) is at the lower
left of the screen, excluding the bottom-most two character lines.
POKE m,n
Writes the byte n at address m into memory, both must be decimal values (the ZX
does not recognize hexadecimal numbers).
PRINT ...
Displays the operand(s) - if any - on the screen. Possible operands are:
a) nothing
b) a numeric expression, displayed either as
normal decimal number (if in range 10^-5 .. 10^13)
otherwise as nnEmm indicating nn*10^mm
leading zeroes are displayed only if the first digit after
the "." is not zero, ie. 0.3 and .03 are displayed as such.
c) a string. undefined characters are displayed as question marks.
d) AT y,x; - moves the PRINT position to the specified screen

location, 0,0 is upper left.


e) TAB n; - moves the PRINT position to the specified horizontal
location. If this is to the left of the current location, then
the vertical position is incremented.
Operands may be separate by semicolon ";" (next operand displayed directly at
current position) or comma "," (next operand displayed at next TAB 0 or TAB 16
position).
Upon completion, the print position is moved to the begin of the next line
(unless expression was terminated by semicolon or comma).
An error may be generated if memory or screen is full, if so, CONT may be used
to clear the screen and to continue the program.
RAND [n] (called RANDOMISE on ZX80, and RANDOMIZE on Spectrum)
Initializes the random generators seed (n=1..65535). When n is zero (the
default), the current frame counter is used as seed.
READ v1[,v2[,v3]] (Spectrum only)
Loads expressions from DATA lines into the specified variable(s). See also:
RESTORE.
REM ...
Defines a remark, ignored by the program. The comment field may be also
mis-used to define binary machine code inside of a basic program.
However, the comment may not contain a NEWLINE character (76h) - ie. a HALT
instruction (opcode 76h) may not be used, as well as any other opcodes with 76h
as parameter byte, such like JP 4176h, or LD A,76h, etc.
RESET (Timex TS2068/TC2068 only)
Intended to reset connected peripherals. No idea if/which/how any peripherals
do actually support this command.
RESTORE [n] (Spectrum only)
Sets the first line number where following READ commands start searching for
DATA statements, the default is the begin of the program.
RETURN
Returns to the line following to the most recently executed GOSUB command.
RUN [n]
Clears all variables and jumps to the specified line number. The default is the
first line of the program. See GOTO for details.
SAVE f
Saves the system area, the program, the video memory, and any defined variables
to cassette. The filename f must be a 1-127 characters string, which may not
include inverted characters. The text display is suspended for the duration of
saving, white lines are displayed indicating the cassette signals.
When using SAVE from inside of the program, then the program is automatically
continued at the following line. Note that the GOSUB stack is not saved, so
that SAVE should not be used from inside of a sub-routine.
The ZX80 does not support filenames, just enter SAVE without parameter.
SCROLL (ZX81 only)
Moves the display upwards, and inserts a blank line at the bottom.
Note: The blank line is totally empty, in VRAM it is defined as a single HALT
opcode, without any SPACE characters.
SLOW (ZX81 only)
Switches to SLOW mode (approx. 4 times slower than FAST mode). The text screen
is displayed, and the program is executed during vertical blanking periods
only. The ZX81 is initially operating in SLOW mode.
The ZX80 does not support SLOW and FAST commands, and it is always operating in
FAST mode.
SOUND index,data [;index,data] [...] [;index,data] (Timex TS2068/TC2068 only)
Allows to write one or more values to the PSG sound registers. Unlike the
PLAY/BEEP commands, it does just start (or stop or change) sounds, but doesn't
pause program execution.
SPECTRUM (Spectrum 128/+2/+2A/+3 only)
Switches to Spectrum 48K backwards-compatible mode. Disables the new I/O ports,
disables the Extended System area, re-enables the old color codes like {INK
RED}, re-enables the hotkey mode like R=RUN, etc. The BASIC program (if any) is
kept in memory (eg. allows to load 48K program from Spectrum +3 disk drive, and
then run it in 48K mode).
STOP
Stops the program. User may enter CONT to continue in following line.
UNPLOT x,y (ZX81 only)

Same as PLOT, but drawing a white dot instead of a black dot.


Additional commands...
FORMAT (Spectrum only)
FORMAT LINE baudrate
;default=9600
FORMAT LPRINT target
;"R"=RS232, "C"=Centronics
FORMAT LPRINT tokenmode ;"E"=Expanded, "U"=Unexpanded tokens
COPY
- normal screen copy to printer
COPY EXP - expanded screen copy to printer (recurse BRIGHT attributes)
COPY EXP INVERSE - expanded inverse screen copy to printer
CAT (Spectrum only)
MOVE (Spectrum only)
ERASE (Spectrum only)
OPEN # (Spectrum only)
CLOSE # (Spectrum only)
MERGE (Spectrum only)
VERIFY (Spectrum only)
--> Spectrum Disc and Tape Commands
BASIC Functions
--------------Note that all ZX81 and Spectrum 48K functions must be entered in form of SHIFT
or FUNCTION mode key combinations. For example, type SHIFT+ENTER,B for the
INKEY$ keyword - attempting to enter I,N,K,E,Y,$ would result in a syntax
error. The same applies for multi-character operands such like ">=" and "**".
For the ZX80 and Spectrum 128/+2/+2A/+3 it is vice-versa, and all functions
must be entered character by character. Also, ZX80 function parameters must be
put into () brackets.
ABS n
Returns the unsigned value of n.
ATTR (y,x) (Spectrum only)
Returns the characters 8bit color attritbute stored in VRAM attribute area.
BIN n (Spectrum only)
Treats the following digits as binary number (max 16bit).
CHR$ n
Returns character n. (Converts a number into a single-character string.)
CODE string
Returns the character number of the first character (or 0 if string is empty).
Opposite of CHR$.
FN name(n,n,etc) (Spectrum only)
Executes a user defined function (which can be defined with DEF FN).
FREE (Timex TS2068/TC2068 only)
Returns amount of free memory in bytes.
IN n (Spectrum only)
Returns a byte read from the specified 16bit I/O address.
INKEY$ (ZX81/Spectrum only)
Returns the character of the currently pressed key, or "" if none pressed.
LEN string (ZX81/Spectrum only)
Returns the length of the string.
PEEK n
Returns a byte read from decimal (!) memory address n. The ZX does not
recognize hexadecimal numbers.
POINT (x,y) (Spectrum only)
Returns the pixel color (0 or 1) stored in VRAM bitmap area.
RND (for ZX80: RND n)
Returns a random number in range 0 to 0.99999... (ZX81/Spectrum), or 1 to n
(ZX80).
SCREEN$ (y,x) (Spectrum only) ;returns character at location x,y
Returns character that matches the 8x8 pixel cell in VRAM bitmap area.
SGN n (ZX81/Spectrum only)
Returns the sign (-1, 0, or +1) of n.
STICK n,m (Timex TS2068/TC2068 only)

Returns joystick status (via PSG register 14). n=1 returns 1bit button status,
n=2 returns 4bit direction status. m selects the joystick port (1 or 2).
STR$ n
Returns n converted into a string.
TL$ string (-ZX80- only)
Returns string with leftmost character truncated. Equivalent to the ZX81
expression 'string(2 TO)'.
USR n
Calls a machine program in memory at address n, and returns the value of the BC
register when (if) the machine code program returns. The ZX does not recognize
hexadecimal addresses.
VAL string (ZX81/Spectrum only)
Converts the string into a value, stops the program if failed.
VAL$ string (Spectrum only)
This is a subfunction of the VAL function, it removes bounding quotes from the
string, but without actually doing a string-to-value conversion. No idea if
it's useful for anything.
Floating Point related functions (ZX81/Spectrum only)
ACS n
Arcus Cosinus.
ASN n
Arcus Sinus.
ATN n
Arcus Tangens.
COS n
Cosinus.
EXP n
Exponent e^n.
INT n
Returns an integer value (rounded DOWN).
LN n
Logarhytmn of n (base e).
PI
3.14159265...
SIN n
Sinus.
SQR n
Square root.
TAN n
Tangens.
Numeric operations
Op.
Prio. Expl.
a+b
6
Addition
a-b
6
Subtraction
a*b
8
Multiplication
a/b
8
Division
-a
9
Invert sign
a**b 10
a^b
Logical operations (Returns 1 if true, 0 if false)
Op.
Prio. Expl.
a=b
5
Equal
a>b
5
Greater than
a<b
5
Less than
a<=b 5
Less or equal
a>=b 5
Greater or equal
a<>b 5
Not equal
Special Numeric/Logical operations
Op.
Prio. Expl.
a OR b
2
b<>0: Returns 1;
b=0: Returns a.
a[$] AND b 3
b<>0: Returns a (or a$); b=0: Returns 0 (or "").
NOT b
4
b<>0: Returns 0;
b=0: Returns 1.
Priority for indexing (DIM) and string-fragments (TO) is 12. Priority for all
functions is 12.
String ( [first] TO [last] ) Operand
Used to specify a fragement of a string from first character to last character.
The default values are: first=1, and last=LEN.
May be used either in source and destination of string operations, eg.:
LET A$(5 TO 7) = "***"
;overwrites 5th-7th character of A$
LET A$ = B$(TO 4)
;copies 1st-4th character of B$ to A$
BASIC Error Codes
----------------Commandline Errors
When entering a line incorrectly, the [S] symbol (Syntax Error) is displayed at
the fault location, prompting the user to correct the problem.
ZX81 Execution Errors
Otherwise, when errors occur during program execution, the following error
codes are displayed.
0 No Error, program terminated succesfully.
1 Encountered NEXT without FOR.
2 Undefined Variable.

3 DIM Index out of range. May also return error B if 16bit exceeded.
4 Memory full.
5 Screen full. Type CONT to continue with cleared screen.
6 Arithmetic Overflow, a value is greater than 10^38.
7 Encountered RETURN without GOSUB.
8 Attempted to use INPUT as command (without line number).
9 Program halted by STOP command, may continue by CONT.
A Function with bad argument.
B Integer out of range.
C Failed VAL function.
D Program aborted by BREAK (SPACE KEY), or entered STOP at begin of INPUT.
E Not used.
F Attempted to SAVE a file with empty "" name.
Errors are always displayed as ERR/LINE indicating the line number which caused
the error.
ZX80
0
1
2
3
4
5
6
7
8
9

Execution Errors
program completed (or breaked), no error
NEXT without FOR
variable not defined
dimension out of range (DIM)
memory or gosub stack full
(???)
integer overflow (value exceeds -32768..+32767)
RETURN without GOSUB
attempted INPUT but program isn't running
STOP command

BASIC Programs and Variables (ZX81/Spectrum)


-------------------------------------------BASIC Program Line Structure
Bytes Expl.
2
Line Number (MSB,LSB) (!)
2
Line Length (LSB,MSB)
LEN-1 Text
1
Newline
(ZX81=76h) (Spectrum=0Dh)
The following are used in the Text area: 00h-3Fh and 80h-BFh for normal and
inverted characters, C0h-FFh and 40h-42h for keywords, 7Eh for values, and 76h
indicates the end of the line. On the Spectrum, characters are in ASCII,
keywords are different, values are 0Eh, and end of line is 0Dh.
Values are duplicated in program lines: First, as normal text, ie. as entered
by the user (this field is ignored during execution, still it must exist, but
might be always set to "0" if desired). And second, invented by the code 7Eh,
as pre-calculated 5-byte FLOAT number.
An immediate thus occupies at least 7 bytes. However, there are some grindy
methods to save memory, such like: PI-PI defines 0 in only 3 bytes, VAL "9"
defines 9 in only 4 bytes, etc.
BASIC One-Letter Variables
Bytes Expl.
1
60h + Letter (5bit)
5
Floating point number (exponent/value)
BASIC Multi-Character Variables
Bytes Expl.
1
A0h + First Letter
(5bit)
NN
00h + Further Characters (6bit)
1
80h + Last Character
(6bit)
5
Floating point number (exponent/value)
BASIC Numeric Array
Bytes Expl.
1
80h + Letter (5bit)
2
Total Length of all following data
1
Number of Dimensions
D*2
Range of each of the Dimension(s)
N*5
Values
BASIC FOR-NEXT Counter
Bytes Expl.
1
E0h + Letter (5bit)
5
Current Value (float)
5
Target Value (float)
5
Step
2
Loop Linenumber (MSB,LSB) (!)
BASIC String
Bytes Expl.
1
40h + Letter

(5bit)

2
LEN

String Length
(0 if empty)
Character String (none if empty)

BASIC Character Array


Bytes Expl.
1
C0h + Letter
(5bit)
2
Total Length of all following data
1
Number of Dimensions
D*2
Range of each of the Dimension(s)
N*1
Characters
5-byte FLOAT numbers
1
Exponent 81h +/- location of most significant bit
4
Sign-Bit and Value excluding most significant bit
For example, the value 7FFFh would be defined as such: In this case the MSB is
Bit 14 (ie. 4000h) the exponent byte must be set to 14+81h (=8Fh). The sign bit
is zero (Bit 7 of first byte), and the remaining bits, in this case Bit 13-0
(3FFFh), are shifted to the left as much as possible (so that highest bit is
located in Bit 6 of first byte) the four bytes must be: 7F FE 00 00.
5-byte NON-FLOAT numbers with Exponent=00h (Spectrum only / not ZX81)
1
Exponent 00h (indicates that it is a non-float value)
1
Sign
(00h=Positive, FFh=Negative)
2
Integer (0000h..FFFFh) (or -0001h..-FFFFh when negative)
1
Unused (00h)
BUG: In some cases (not sure when?), -10000h is also stored as non-float, and,
in some further cases (not sure when?) that causes problems.
5-byte FLOAT bug
There's some inaccuracy when converting text strings (eg. user input) to float
numbers. For example, the correct value for 0.25 would be 7F 00 00 00 00,
however, the ZX81/TS1000 BIOSes do convert it to 7E 7F FF FF FF (accidently
rounded down), the TS1500 BIOS does unsuccessfully try to fix that problem by
converting it to 7F 00 00 00 01 (accidently rounded up). This is resulting in
incompatibility, for example,
10 FOR I = 0 TO 1 STEP .25
20 PRINT I
30 NEXT I
The ZX81/TS1000 does correctly stop at 1 being displayed as last number, whilst
the "improved" TS1500 does incorrectly stop at 0.75. Mind that immediates are
pre-compiled at time of entering the program code, so a program SAVEd on a
ZX81, may work exactly as on the ZX81 even when LOADing it on a TS1500 (unless
it contains conversions being done at runtime, like VAL ".25" or VAL A$).
1 IF VAL"0.25" < 1/4 THEN PRINT "TOO SMALL (ZX81 OR TS1000 OR SPECTRUM)"
2 IF VAL"0.25" > 1/4 THEN PRINT "TOO BIG (TS1500 OR LAMBDA)"
3 IF VAL"0.25" = 1/4 THEN PRINT "MATCH (WHOOPS)"
Typing IF VAL"0.25" forces conversion on runtime (typing IF 0.25 would be
converted when entering the program, and stay so even when SAVing it and
LOADing it on another computer). Interestingly, the TOO SMALL variants, do also
(incorrectly) display a MATCH in line 3.
BASIC Programs and Variables (ZX80)
----------------------------------BASIC Program Line Structure
Bytes Expl.
2
Line Number (MSB,LSB) (!)
...
Text
1
Newline
(76h)
The following are used in the Text area: 00-3F and 80-BF for normal and
inverted characters, D4-FF for keywords, and 76 indicates the end of the line.
A couple of 'special' characters such like ';()*+/-' are stored in form as
keywords rather than as normal character codes.
Function names and values in program lines are stored as normal text.
BASIC One-Letter Variables
Bytes Expl.
1
60h + Letter (5bit)
2
Signed Integer
BASIC Multi-Character Variables
Bytes Expl.
1
40h + First Letter
(5bit)
NN
00h + Further Characters (6bit)
1
80h + Last Character
(6bit)
2
Signed Integer
BASIC Numeric Array
Bytes
Expl.

1
1
(N+1)*2

A0h + Letter (5bit)


Range (Counted from 0 to N)
Signed Integers

BASIC FOR-NEXT Counter


Bytes Expl.
1
E0h + Letter (5bit)
2
Current Value
2
Target Value
2
Loop Linenumber (normal LSB,MSB for ZX80)
BASIC String
Bytes Expl.
1
80h + Letter
(5bit)
...
Character String (none if empty)
1
Ending Quotes
(01h)
BASIC Character/String Arrays
None such - ZX80 supports numeric arrays only.

Potrebbero piacerti anche