Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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).
cycles
cycles
cycles
cycles
56
192
ca. 56
ca. 6
scanlines (7 charlines)
scanlines (24 charlines)
scanlines (or a bit less)
scanlines
cycles
cycles
cycles
cycles
32
192
ca. 32
ca. 6
scanlines (4 charlines)
scanlines (24 charlines)
scanlines (or a bit less)
scanlines
MHz
MHz
MHz
MHz
MHz
(ori)
(tuned)
(ori)
(tuned)
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)
System Area
Basic Program
VARS
Input Buffer, and probably something else ???
VRAM
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.
HW
HW
HW
HW
HW
HW
HW
HW
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,
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
--------------------+-----+---- 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.
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
|
|_______|
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.
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
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)
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)
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
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
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
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
/
'---'
/
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).
Speech
Speech
Speech
Speech
Speech
Speech
Overview
I/O Ports
SP0256 Voice Generator
SP0256 Instruction Set
SP0256 Allophones/Words
SP0256 Pin-Outs
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
(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
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
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
Opcode
4
4
8
8
8
8
8
8
8
8
8
8
8
8
8
8
(8)
(8)
Notes:
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)
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
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
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
->
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
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)
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
ID 15h 00h 2
02h 2
04h 1
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
26h
27h
28h
29h
2Ah
2Bh
2Ch
2Dh
MicroART ATM
MicroART ATM Turbo 2
Chrome
ZX Badaloc
TS-1500
Lambda
TK-65
ZX-97
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
Write Protected
Sync
Gap
busy?)
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
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
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
Command (W)
Status (R)
Track (R/W)
Sector (R/W)
Data (R/W)
(Western Digital WD177x)
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).
FFh 0-1
2
3
4
5
6-7
(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.
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
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
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
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
3Fh 0
1-2
3
4-7
output in Mode 3)
output in Mode 3)
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.
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
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.
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
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
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.
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
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 -->)
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)
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
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
#>
Output
(-->)
(ud1 --> ud2)
(ud --> 0 0)
(c -->)
(n -->)
(ud --> adr n)
Conversion
BASE
(--> adr)
DECIMAL
(-->)
ASCII text (--> c)
Character Input
QUERY
(-->)
WORD
(c --> adr)
RETYPE
INKEY
( --> )
(--> x)
Number Input
CONVERT (d1 adr1 --> d2 adr2)
NUMBER
(-->
(-->
(-->
(-->
x (adr))
n 4102)
f 4181)
0)
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)
(-->)
(x -->)
(c -->)
(x -->)
(... -->)
Miscellaneous
( ...) (-->)
HERE
(--> adr)
PAD
(--> adr)
SLOW
(-->)
FAST
(-->)
?)
BEEP
(u1 u2 -->)
IN
(adr --> c)
OUT
(c adr -->)
INVIS (-->)
VIS
(-->)
LINE
(-->)
set to x)
set to c)
by [ x ])
EDITing)
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
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
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.
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
(5bit)
2
LEN
String Length
(0 if empty)
Character String (none if empty)
1
1
(N+1)*2