mirror of
https://github.com/problemkaputt/problemkaputt.github.io.git
synced 2024-05-13 10:09:21 -04:00
8675 lines
424 KiB
Plaintext
8675 lines
424 KiB
Plaintext
nocash sinclair ZX docs by martin korth
|
|
--------------------------------------
|
|
|
|
Computer Specs
|
|
--> ZX80/ZX81
|
|
--> ZX Spectrum
|
|
--> Lambda 8300
|
|
--> Jupiter ACE
|
|
|
|
Z80 CPU
|
|
--> Z80 CPU Specifications
|
|
|
|
The BASIC Interpreter
|
|
--> BASIC Interpreter
|
|
|
|
ZX80/ZX81
|
|
---------
|
|
|
|
ZX80/ZX81 Technical Information
|
|
--> ZX80/ZX81 Models
|
|
--> ZX80/ZX81 Keyboard Assignment
|
|
--> ZX80/ZX81 I/O Map
|
|
--> ZX80/ZX81 I/O Ports
|
|
--> ZX80/ZX81 Video Mode Text and Blockgraphics
|
|
--> ZX80/ZX81 Video Mode Pseudo Hi-Res Graphics
|
|
--> ZX80/ZX81 Video Mode True Hi-Res Graphics
|
|
--> ZX80/ZX81 Video Blanking and Retrace
|
|
--> ZX80/ZX81 Video Interrupts (INTs and NMIs)
|
|
--> ZX80/ZX81 Video Display Timings
|
|
--> ZX80/ZX81 Video Character Set
|
|
--> ZX81 Video Nonstandard UDG/CHRS Expansions
|
|
--> ZX81 Video Nonstandard HIRES Expansions
|
|
--> ZX81 Video Nonstandard Picture Size
|
|
--> ZX81 Video Nonstandard Color Expansions
|
|
--> ZX81 Joystick Expansions
|
|
--> ZX81 Sound Expansions
|
|
--> ZX80/ZX81 Memory Map and System Area
|
|
--> ZX80/ZX81 Memory Mirrors and Expansions
|
|
--> ZX80/ZX81 Memory Binary Data/Machine Code Programs
|
|
--> ZX80/ZX81 Cassette File Images
|
|
--> ZX80/ZX81 Cassette File Content
|
|
--> ZX80/ZX81 Cassette Signals
|
|
--> Hardware, Connectors, Upgrading
|
|
|
|
Z80 CPU
|
|
--> Z80 CPU Specifications
|
|
|
|
The BASIC Interpreter
|
|
--> BASIC Interpreter
|
|
|
|
ZX80/ZX81 Models
|
|
----------------
|
|
|
|
ZX81
|
|
CPU: NEC P1X108-144 D780C-1 (Z80 compatible) 3.25MHz
|
|
The clock frequency is gained from a high tolerance 6.5MHz
|
|
chewing gum, not exactly a quartz oscillator, in fact, my
|
|
oscilloscope tells me that my ZX81 is running at 3.33Mhz.
|
|
Effective CPU Speed in SLOW mode (when Display is enabled)
|
|
For 50Hz Display Refresh: 0.804600 MHz
|
|
For 60Hz Display Refresh: 0.536400 MHz
|
|
Custom: FERRANTI ULA 2C184E 8147
|
|
Combines the ZX80 video circuit in one chip, plus NMI-generator
|
|
Video Tech Data
|
|
Video: 32x24 Characters (256x192 pixels), 64x48 Dots Block Graphics
|
|
Characters: 64 Characters, defined in ROM area
|
|
Attributes: Normal and Inverted (separately for each char)
|
|
Memory
|
|
8 Kbytes ROM
|
|
1 KByte RAM built-in
|
|
Expanision RAM: 16KBytes (most popular) up to 56KBytes
|
|
|
|
ZX80
|
|
Memory: 4 KBytes ROM, 1 KByte RAM
|
|
Video: Same as ZX81, but without NMI-generator, ie. not supporting SLOW mode,
|
|
thus cannot display a picture while program is operating.
|
|
Sinclair also sold an upgrade kit for it: The 8K ZX81 ROM bundled with a
|
|
ZX81-style keyboard overlay (but still lacking the NMI-generator).
|
|
|
|
TS1000
|
|
A ZX81 clone, distributed in USA by a company called Timex. Includes 2 KBytes
|
|
RAM, and obviously 60Hz NTSC TV modulator, otherwise same as ZX81. The BIOS is
|
|
1:1 the same as in ZX81.
|
|
|
|
TS1500
|
|
Same as above TS1000, but with 16 KBytes of RAM built-in, with rubber keyboard,
|
|
and slightly modified BIOS.
|
|
|
|
Microdigital TKs (Brazil)
|
|
Reportedly brazilian ZX81 clones are called the "TKs".
|
|
TK80 ZX80 clone with 4K ROM, 1K RAM, TTL-chips, without NMI
|
|
TK82 ZX80 clone with 4K ROM, 2K RAM, TTL-chips, without NMI
|
|
TK82-C ZX81 clone with 8K ROM, 2K RAM, TTL-chips, with NMI on daughterboard
|
|
TK83 ZX81 clone with 8K ROM, 2K RAM, ULA-chip, with NMI,joystick,new case
|
|
TK85 ZX81 clone with 10K ROM, 16K RAM, psg-solder-points, rubber keyb,
|
|
and other extras...
|
|
TK83/TK85 have DIN joystick connector
|
|
The C in TK82-C is for "Cientifico", or Scientific in English.
|
|
|
|
____ ZX80 vs ZX81 Compatibility ____
|
|
|
|
Hardware
|
|
The ZX80 and ZX81 hardware is mostly the same, the same I/O address are used,
|
|
RAM is located at 4000h and up, and mirrored as VRAM at C000h and up. The only
|
|
relevant physical difference is that ZX81 includes an NMI generator, which is
|
|
(optionally) allowing to execute programs during vertical blanking periods.
|
|
|
|
Firmware
|
|
Compatibility ends at the firmware side, the revised ZX81 BIOS version dropped
|
|
any compatibility issues. The content of cassette files is different, some
|
|
characters in the character set have been exchanged, the system area is
|
|
different, the BASIC interpreter 'opcodes' have different meanings, variables
|
|
and immediates are stored as floating point numbers (ZX81) instead as integers
|
|
(ZX80), and any addresses in the BIOS ROM are different also.
|
|
|
|
Software
|
|
As described above, ZX80 and ZX81 cassette files are completely incompatible to
|
|
each other. However, the ZX81 BASIC syntax is mostly compatible to ZX80 syntax,
|
|
so that ZX80 software could be easily imported to ZX81 with little changes;
|
|
either by translation program that adjusts the file content, or by manually
|
|
entering the source code.
|
|
|
|
Performance
|
|
The main advantage of ZX81 hardware is the ability to execute program code and
|
|
to display a picture simultaneously in SLOW mode. As the name says, this fancy
|
|
feature is heavily slowing down effective CPU speed.
|
|
Otherwise ZX81 should be theoretically as fast as the trusty ZX80,
|
|
unfortunately the new BASIC interpreter uses floating point values rather than
|
|
integers, and thus ZX81 BASIC programs are ways slower even when using FAST
|
|
mode.
|
|
|
|
TS1500 BIOS
|
|
The inefficient RAM size detection function is removed, instead, the BIOS uses
|
|
a hardcoded RAM size of 16K, additionally it checks for "TS1510 Command
|
|
Cartridge Player" ROMs at location 2000h, and starts them if present (the first
|
|
opcode byte at 2000h must be 01h, ie. "ld bc,nnnn").
|
|
The TS1500 BIOS does fix the LPRINT bug, and it does (attempt) to increase
|
|
floating point conversion accurracy (the ZX81/TS1000 tends to round-down values
|
|
by accident, whilst the TS1500 tends to round-up values by accident, which
|
|
isn't any better, and in some cases it's even worse).
|
|
|
|
____ Sinclair ZX81 Personal Computer ____
|
|
|
|
Multimedia
|
|
The first step to modern decadency was done by releasing the ZX81, this
|
|
computer had the ability to operate in a so called SLOW mode, during which it
|
|
could both execute a program AND display a picture on the screen at the SAME
|
|
time, while its predecessor the ZX80 could do only either one at once. This
|
|
older computer has been restricted to FAST mode, offering high performance
|
|
execution time.
|
|
|
|
Energy
|
|
Anyways, a very amazing thing's been the keyboard heating. Even though the
|
|
computer's been operated at 5 Volts, it's been delivered with external 9V power
|
|
supply. The cooling plate of the 7805 voltage regulator's been located directly
|
|
under the keyboard, whereas cooling plate is a possibly misleading expression,
|
|
it's been heating up after a while, giving the keyboard an irritating feverish
|
|
temparature. If somebody'd claim that ZX81 are tough guys and that they'd never
|
|
get cold fingers - I could only confirm that.
|
|
|
|
Computers Today
|
|
Unfortunately, the rather ineffective new invention of animated pictures has
|
|
been adapted by newer computers, up to today!
|
|
As far as concerning power supplies, this has been another milestone in home
|
|
computer technology, and there's still nobody who stands up, takes his
|
|
ventilated heavy 200 Watts supply, and smashes it into the face of the guy who
|
|
has mass-manufactured it.
|
|
|
|
ZX80/ZX81 Keyboard Assignment
|
|
-----------------------------
|
|
|
|
Here's the ZX81 keyboard assignment. The Graphics column is meant to be
|
|
Shift+Graphics (Graphic without Shift just returns inverted 'normal'
|
|
characters).
|
|
The two columns to the right are for the ZX80, as there's no Function mode,
|
|
ZX80 function names (such like CHR$) can be (and must be) typed by hand as
|
|
single characters.
|
|
<-key-> <------------- ZX81 -----------> <------ZX80------>
|
|
NORMAL COMMAND SHIFT FUNCTION GRAPHICS ZX80/CMD ZX80/SHFT
|
|
1 1 <edit> -- 1000 1 NOT
|
|
2 2 AND -- 0100 2 AND
|
|
3 3 THEN -- 0001 3 THEN
|
|
4 4 TO -- 0010 4 TO
|
|
5 5 <left> -- 0101 5 <left>
|
|
6 6 <down> -- 0011 6 <down>
|
|
7 7 <up> -- 1100 7 <up>
|
|
8 8 <right> -- 0101 8 <right>
|
|
9 9 <graphics> -- -- 9 <hide???>
|
|
0 0 <rubout> -- -- 0 <rubout>
|
|
Q PLOT "" SIN 0111 NEW 1010
|
|
W UNPLOT OR COS 1011 LOAD 0011
|
|
E REM STEP TAN 1110 SAVE 1000
|
|
R RUN <= INT 1101 RUN 0100
|
|
T RAND <> RND 0110 " " 0022
|
|
Y RETURN >= STR$ 1001 REM "
|
|
U IF $ CHR$ -- IF $
|
|
I INPUT ( CODE -- INPUT (
|
|
O POKE ) PEEK -- PRINT )
|
|
P PRINT " TAB -- "?" *
|
|
A NEW STOP ARCSIN 2222 LIST 2222
|
|
S SAVE LPRINT ARCCOS 2200 STOP 0110
|
|
D DIM SLOW ARCTAN 0022 DIM 0010
|
|
F FOR FAST SGN 2211 FOR 0001
|
|
G GOTO LLIST ABS 1122 GO TO 2200
|
|
H GOSUB ** SQR 2222 POKE **
|
|
J LOAD - VAL -- RANDOMISE -
|
|
K LIST + LEN -- LET +
|
|
L LET = USR -- "?" =
|
|
ENTER newline function -- newline <edit>
|
|
SHIFT -- -- -- -- -- --
|
|
Z COPY : LN -- "?" :
|
|
X CLEAR ; EXP -- CLEAR ;
|
|
C CONT ? AT -- CLS ?
|
|
V CLS / -- -- GO SUB /
|
|
B SCROLL * INKEY$ -- RETURN OR
|
|
N NEXT < NOT -- NEXT <
|
|
M PAUSE > PI -- "?" >
|
|
. , -- -- "." ,
|
|
SPACE BREAK pound -- 1111 BREAK pound
|
|
|
|
40-key ZX80/ZX81 Keyboard
|
|
| 1 2 3 4 5 6 7 8 9 0 |
|
|
| Q W E R T Y U I O P |
|
|
| A S D F G H J K L ENTER|
|
|
|SHF Z X C V B N M . SPACE|
|
|
|
|
Keyboard Translation
|
|
When the keyboard translation option is used, special characters such like
|
|
comma, quotes, plus, etc. are mapped to the respective PC keys. In result, the
|
|
meaning of the ZX key combinations SHIFT+1..4 changes also. The respective
|
|
functions are remapped to the following PC-keys:
|
|
ZX81 ZX80 PC
|
|
EDIT NOT !
|
|
AND AND &
|
|
THEN THEN #
|
|
TO TO %
|
|
Some other remapped keys are Cursor=Cursor, Rubout=Backspace, Graphics=Alt,
|
|
Function/Symbol=Ctrl, Break=End.
|
|
|
|
ZX80/ZX81 I/O Map
|
|
-----------------
|
|
|
|
I/O Ports
|
|
xx0Fh.W PSG data (Bi-Pak ZON-X81 Sound)
|
|
xx1Dh.R Zebra Joystick adapter
|
|
xx2Fh.R Memopak I/F Centronics Interface status (IN status,[dd3Fh]);dd=data
|
|
xx3Fh.R Memopak I/F Centronics Interface finish (IN dummy,[dd3Fh]) ;dd=data
|
|
FF7Eh.R Lambda - read PAL/NTSC flag (A7=row) (via diode from A7 to KEYB.0)
|
|
xx9Fh.W PSG index (Timedata ZXM Sound Box)
|
|
xxBFh.R PSG data (Timedata ZXM Sound Box/Joystick Read)
|
|
xxDFh.W PSG index (Bi-Pak ZON-X81 Sound) (default address) (sometimes CFh)
|
|
xxDFh.W PSG data (Timedata ZXM Sound Box)
|
|
xxDFh.R Mikro-Gen digital joystick
|
|
xxDFh.R AGB - JOYSTICK II (port A) (or B ?)
|
|
xxEFh.R AGB - JOYSTICK II (port B) (or A ?)
|
|
xxF5h.R Lambda - toggle sound output level
|
|
xxF5h.W Lambda - select charset line number (00..07)
|
|
xxF6h.R Lambda - read selected charset data (8 pixels)
|
|
xxF6h.W Lambda - select charset char number (00..3F)
|
|
xxFBh.R Sinclair Printer Status
|
|
xxFBh.W Sinclair Printer Output
|
|
xxFDh.W Disable NMI (ZX81 only)
|
|
xxFEh.W Enable NMI (ZX81 only)
|
|
NNFEh.R Keyboard read, when NMI=Off: also enter VSYNC and set CAS.OUT=Low
|
|
xxFFh.W Terminate Vsync and restart LINECNTR and set CAS.OUT=High
|
|
|
|
Accidently Used I/O Port Mirrors
|
|
0Eh.R Faulty mirror of FEh.R (used by a GRAND-PRIX game)
|
|
CFh.W PSG index (Bi-Pak ZON-X81 Sound) (used accidently in Bi-Pak manual)
|
|
CFh.W PSG index (Bi-Pak ZON-X81 Sound) (used by Lunar 10)
|
|
FEh.W Faulty mirror of FFh.W (used by animated Space Invaders for ZX80)
|
|
|
|
Memory Mapped Ports
|
|
3E80h.R/W Mikro-Gen analog joystick A/D board
|
|
7FFFh.W PSG index (Quicksilva QS Sound board)
|
|
7FFEh.R/W PSG data (Quicksilva QS Sound board)
|
|
|
|
IR Register
|
|
I=00h Pseudo HiRes (Madjump II)
|
|
I=08h Pseudo HiRes (Bipods, Micromouse)
|
|
I=0Ch Pseudo HiRes (Rock Crush, Dans Revenge, etc.)
|
|
I=1Eh ZX81 ROM Charset (or QS CHRS board RAM)
|
|
I=2xh dk'tronics UDG ROM (or unknown UDG RAM)
|
|
I=3xh dk'tronics UDG RAM
|
|
I=40h Xtricator IM2 vector at [40FFh] (with databus assumed to be FFh)
|
|
IR=x True hires bitmap address
|
|
R=x Interrupt counter for "compressed" text output (INT wired to A6)
|
|
R=x+EI Interrupt execution forces HSYNC (on ZX81: also resets NMI counter)
|
|
|
|
ZX80/ZX81 I/O Ports
|
|
-------------------
|
|
|
|
Output to Port FFh (or ANY other port)
|
|
Writing any data to any port terminates the Vertical Retrace period, and
|
|
restarts the LINECNTR counter. The retrace signal is also output to the
|
|
cassette (ie. the Cassette Output becomes High).
|
|
|
|
Input from Port FEh (or any other port with A0 zero)
|
|
Reading from this port initiates the Vertical Retrace period (and accordingly,
|
|
Cassette Output becomes Low), and resets the LINECNTR register to zero,
|
|
LINECNTR remains stopped/zero until user terminates retrace - In the ZX81, all
|
|
of the above happens only if NMIs are disabled.
|
|
Bit Expl.
|
|
0-4 Keyboard column bits (0=Pressed)
|
|
5 Not used (1)
|
|
6 Display Refresh Rate (0=60Hz, 1=50Hz)
|
|
7 Cassette input (0=Normal, 1=Pulse)
|
|
When reading from the keyboard, one of the upper bits (A8-A15) of the I/O
|
|
address must be "0" to select the desired keyboard row (0-7).
|
|
(When using IN A,(nn), the old value of the A register is output as upper
|
|
address bits and <nn> as lower bits. Otherwise, ie. when using IN r,(C) or INI
|
|
or IND, the BC register is output to the address bus.)
|
|
The ZX81/ZX80 Keyboard Matrix
|
|
Port____Line____Bit__0____1____2____3____4__
|
|
FEFEh 0 (A8) SHIFT Z X C V
|
|
FDFEh 1 (A9) A S D F G
|
|
FBFEh 2 (A10) Q W E R T
|
|
F7FEh 3 (A11) 1 2 3 4 5
|
|
EFFEh 4 (A12) 0 9 8 7 6
|
|
DFFEh 5 (A13) P O I U Y
|
|
BFFEh 6 (A14) ENTER L K J H
|
|
7FFEh 7 (A15) SPC . M N B
|
|
|
|
Port FDh Write (ZX81 only)
|
|
Writing any data to this port disables the NMI generator.
|
|
|
|
Port FEh Write (ZX81 only)
|
|
Writing any data to this port enables the NMI generator.
|
|
NMIs (Non maskable interrupts) are used during SLOW mode vertical blanking
|
|
periods to count the number of drawn blank scanlines.
|
|
|
|
ZX81 Printer
|
|
Below ports are for the printer. Both ZX80 and ZX81 aren't actually include any
|
|
printer connector or hardware, but the ZX81 BIOS supports three BASIC
|
|
instructions (LPRINT, LLIST, COPY) which access external printer hardware by
|
|
these I/O addresses.
|
|
Port FBh Read - Printer Status
|
|
Bit Expl.
|
|
0 Data Request (0=Busy, 1=Ready/DRQ)
|
|
1-5 Not used
|
|
6 Printer Detect (0=Okay, 1=None)
|
|
7 Newline (0=Nope, 1=Begin of new line)
|
|
Port FBh Write - Printer Output
|
|
Bit Expl.
|
|
0 Not used
|
|
1 Undoc/Speed? (0=Normal, 1=used to slow-down last 2 scanlines)
|
|
2 Motor (0=Start, 1=Stop)
|
|
3-6 Not used
|
|
7 Pixel Output (0=White/Silver, 1=Black)
|
|
That serial 1-bit / 1-pixel protocol isn't compatible with normal character
|
|
based printers.
|
|
Uses thermal paper rolls with 100 (or 110 ?) mm width, max 25 meters length.
|
|
Horizontal resolution is 256 pixels (32 characters).
|
|
|
|
Note
|
|
Beside for the actual I/O ports, the IR register, the most significant bit of
|
|
the program counter, and (if that bit was set) the opcodes on the databus are
|
|
also relevant for video output. For details refer to chapters about Video.
|
|
|
|
ZX80/ZX81 Video Mode Text and Blockgraphics
|
|
-------------------------------------------
|
|
|
|
Overview
|
|
This is the ZX standard video mode. The display area consists of 32x24
|
|
characters of 8x8 pixels each. The user cannot set single pixels though, only
|
|
64 predefined characters can be used. However, some of these characters are
|
|
split into 2x2 blocks (4x4 pixel each), allowing to display 64x48 block low
|
|
resolution graphics.
|
|
|
|
Video Memory
|
|
Video memory is addressed by the D_FILE pointer (400Ch) in ZX80/81 system area.
|
|
The first byte in VRAM is a HALT opcode (76h), followed by the data (one byte
|
|
per character) for each of the 24 lines, each line is terminated by a HALT
|
|
opcode also. In case that a line contains less than 32 characters, the HALT
|
|
opcode blanks (white) the rest of the line up to the right screen border. (Thus
|
|
left-aligned text will take up less memory than centered or right-aligned
|
|
text.)
|
|
|
|
Character Data, VRAM Size
|
|
Character data in range 00h..3Fh displays the 64 characters, normally black on
|
|
white. Characters may be inverted by setting Bit 7, ie. C0h..FFh represents the
|
|
same as above displayed white on black.
|
|
The fully expanded VRAM size is 793 bytes (32x24 + 25 HALTs, almost occupying
|
|
the whole 1Kbyte of internal RAM), an empty fully collapsed screen occupies
|
|
only 25 bytes (HALTs).
|
|
|
|
Character Set
|
|
The character set is addressed by the I register multiplied by 100h. In the
|
|
ZX81 this is 1Eh for 1E00h..1FFFh, in ZX80 0Eh for 0E00h..0FFFh. Setting
|
|
I=40h..7Fh in attempt to define a custom charset in RAM rather than ROM does
|
|
not work.
|
|
|
|
Display procedure Tech Details
|
|
The display data is more or less 'executed' by the CPU. When displaying a line,
|
|
the BIOS takes the address of the first character, eg. 4123h, sets Bit 15, ie.
|
|
C123h, and then jumps to that address.
|
|
|
|
The hardware now senses A15=HIGH and /M1=LOW (signalizing opcode read), upon
|
|
this condition memory is mirrored from C000-FFFF to 4000-7FFF. The 'opcode' is
|
|
presented to the databus as usually, the display circuit interpretes it as
|
|
character data, and (if Bit 6 is zero) forces the databus to zero before the
|
|
CPU realizes what is going on, causing a NOP opcode (00h) to be executed. Bit 7
|
|
of the stolen opcode is used as invert attribute, Bit 0-5 address one of the 64
|
|
characters in ROM at (I*100h+char*8+linecntr), the byte at that address is
|
|
loaded into a shift register, and bits are shifted to the display at a rate of
|
|
6.5MHz (ie. 8 pixels within 4 CPU cycles).
|
|
|
|
However, when encountering an opcode with Bit 6 set, then the video circuit
|
|
rejects the opcode (displays white, regardless of Bit 7 and 0-5), and the CPU
|
|
executes the opcode as normal. Usually this would be the HALT opcode - before
|
|
displaying a line, BIOS enables INTs and initializes the R register, which will
|
|
produce an interrupt when Bit 6 of R becomes zero.
|
|
In this special case R is incremented at a fixed rate of 4 CPU cycles (video
|
|
data executed as NOPs, followed by repeated HALT), so that line display is
|
|
suspended at a fixed time, regardless of the collapsed or expanded length of
|
|
the line.
|
|
|
|
As mentioned above, an additional register called linecntr is used to address
|
|
the vertical position (0..7) whithin a character line. This register is reset
|
|
during vertical retrace, and then incremented once per scanline. The BIOS thus
|
|
needs to 'execute' each character line eight times, before starting to
|
|
'execute' the next character line.
|
|
|
|
ZX80/ZX81 Video Mode Pseudo Hi-Res Graphics
|
|
-------------------------------------------
|
|
|
|
This method is used to display 256x192 pixels graphics, limited to max 128
|
|
combinations within each row of 8 pixels though. Even though not supported by
|
|
the BIOS, a couple of games are using this video mode: Rock Crush, Dans
|
|
Revenge, Rocketman, Forty Niner, Madjump II, Bipods, Micromouse, and possibly
|
|
others.
|
|
|
|
Basically it is working much like Text video mode, the character height is
|
|
reduced to a single scanline, so each tile consists of 8x1 pixels rather than
|
|
8x8 pixels. And the screen consists of 32x192 of these 'flat' characters, each
|
|
line usually terminated by a RET opcode (C9h), thus occupying 6176 bytes of
|
|
memory.
|
|
|
|
A special display procedure is required which forces the linecntr register to
|
|
zero by issuing a very short 'vertical retrace' signal each scanline
|
|
(preferably simultaneously to the hardware generated horizontal retrace
|
|
signal). In result, only the topmost row of each character will be displayed,
|
|
as the topmost row of most of the normal characters is just blank, it'd be
|
|
recommended to change the characterset pointer in the I register to another
|
|
address in ROM.
|
|
|
|
For example, setting I=0Ch would select the area 0C00h..0DFFh (in steps of
|
|
eight: topmost rows of chars #0, #1, #2 at C00h, C08h, C10h, etc). The machine
|
|
code bytes in this memory region are then used as 'randomly' predefined pixel
|
|
rows, which may or may not match the programmers requirements. Each of the 64
|
|
rows may be inverted as normal text characters, so theoretical a total of 128
|
|
different 8-pixel rows can be used, practically less because most likely a
|
|
couple of rows will be duplicated.
|
|
|
|
As the interrupt based BIOS display procedure at 0038h does not support above,
|
|
a raw software based handler is used in most cases, that's why each line is
|
|
terminated by a RET rather than HALT opcode.
|
|
|
|
Observe that the TS1500 BIOS version contains some patched opcodes, so graphics
|
|
may appear different as with original ZX81/TS1000 BIOS (the most commonly used
|
|
region, with I=0Ch, is same in both BIOS versions).
|
|
|
|
ZX80/ZX81 Video Mode True Hi-Res Graphics
|
|
-----------------------------------------
|
|
|
|
This mode produces a 256x192 pix graphics screen, and, unlike Pseudo Hi-Res, it
|
|
allows to set each pixel separately. The downside is that it does not work with
|
|
most external RAM Paks (memory expansions can be quite easily upgraded by using
|
|
two diodes and a resistor though, see chapter Hardware Modifications for
|
|
details).
|
|
|
|
However, it does work with internal RAM and with modified RAM Paks.
|
|
When using internal RAM, take care about these two limitiations: Only a small
|
|
picture will fit into 1K memory (so the display procedure must increase
|
|
horizontal and/or vertical blanking times), and external RAM must be
|
|
disconnected (as it'd otherwise disable internal RAM).
|
|
|
|
The true hi-res technique is used by the games Guus Flater, Starfight, and by
|
|
some demos such like WRX1K.
|
|
|
|
The general idea is to move the character set into RAM at 4000h..7FFFh by
|
|
setting I to 40..7Fh. Now this does NOT work as expected, ie. as
|
|
(I*100h+char*8+linecntr) as for text mode. Both the executed opcode (character
|
|
number) and the linecntr value are ignored. Instead, pixels are directly read
|
|
from memory at (IR). Each eight bits of each byte represent eight pixels. The
|
|
picture is defined in form of a common monochrome bitmap.
|
|
|
|
The bitmap data can be located anywhere in RAM, and as it is not 'executed' as
|
|
in other display modes, only raw data is required (ie. and no HALT or RET
|
|
opcodes need to be attached to each line). Note that only the lower seven bits
|
|
of the R register are incremented by the CPU; care should be taken that it does
|
|
not overflow within a line. For example, a bitmap of 256 pixels width (32
|
|
bytes) should be aligned to 32 in memory.
|
|
|
|
The main display procedure should load the MSB of the current bitmap line into
|
|
the I register, and the LSB into the A register, then jump to a dummy D_FILE
|
|
display procedure in memory with A15=HIGH. This dummy procedure should copy the
|
|
LSB from A into R register, and then execute a stream of 32 NOP opcodes (00h:
|
|
Bit 7 indicates not inverted output, Bit 6 disables blanking, data is directly
|
|
read from (IR), so that the character number in Bit 0-5 is ignored), and return
|
|
to the main procedure - which'd then issue some delays, prepare new address in
|
|
I and A and start over with the next line (using the same dummy procedure
|
|
again), until the whole screen has been displayed.
|
|
|
|
ZX80/ZX81 Video Blanking and Retrace
|
|
------------------------------------
|
|
|
|
Display becomes white during blanking time. That is: when Bit 15 of the program
|
|
counter (PC) is "0", and/or when Bit 6 of the current opcode is "1".
|
|
Theoretically the CPU could execute whatever program code during blanking -
|
|
however, as there is only limited interrupt feedback, this time is usually
|
|
spent on HALT opcodes or other delay loops, required to keep the CPU
|
|
synchronized to visible display output.
|
|
|
|
Vertical Blanking
|
|
Upper and lower screen borders are displayed above/below of the actual picture,
|
|
the height of these borders depends on the display refresh rate. The BIOS
|
|
permanently reads out the preferred refresh rate (50Hz or 60Hz) when checking
|
|
for keystrokes, and uses this to re-calculate the desired border height for
|
|
each frame - allowing to export the ZX to other countries without having to
|
|
reboot it ;-)
|
|
|
|
ZX80 Vertical Blanking ("PAUSE")
|
|
The ZX80 points to a HALT opcode in the D_FILE area, which is repeatedly
|
|
executed to display blank upper and lower screen borders (much like empty lines
|
|
in a collapsed screen). The CPU thus wastes all its energies just on drawing
|
|
blank lines (and on decreasing a remaining lines counter).
|
|
|
|
ZX81 Vertical Blanking ("SLOW")
|
|
Even though the ZX81 supports the above method either, it'd usually use NMI
|
|
based blanking which allows program code to be executed during blanking time.
|
|
NMIs (non maskable interrupts) are enabled by I/O, the NMI handler is then
|
|
called each scanline. The handler increases a counter and (if the counter does
|
|
not overflow) returns to the user program, otherwise it executes a HALT opcode
|
|
to synchronize the CPU to the display at one-cycle resolution and terminates
|
|
the blanking procedure.
|
|
|
|
Horizontal Blanking
|
|
In both ZX80 and ZX81, the CPU cannot be used to execute user programs during
|
|
horizontal blanking periods - it is required to execute delays to be kept
|
|
synchronized to video hardware. This could be gained by a hardcoded delay.
|
|
However, ZX video is required to support variable length blanking when using
|
|
collapsed screens, in that case the width of the right screen border must be
|
|
increased when drawing an empty (or incomplete) line. This is gained by loading
|
|
a counter value into the R register (before drawing the line), and terminating
|
|
the line by a HALT opcode which is kept executed until Bit 6 of R becomes zero.
|
|
|
|
Retrace
|
|
The cathode ray is moved back to the begin of the scanline / top of display
|
|
during horizontal / vertical retrace periods.
|
|
Horizontal retrace is generated by the video hardware, so care should be taken
|
|
to keep the display procedure synchronized to retrace signals.
|
|
Vertical retrace must be manually initiated and terminated by I/O, a fixed
|
|
length delay should be issued during v-retrace in order to produce a stable
|
|
display.
|
|
|
|
ZX80/ZX81 Video Interrupts (INTs and NMIs)
|
|
------------------------------------------
|
|
|
|
INTs
|
|
Maskable Interrupts (INTs) are generated when Bit 6 of the R (refresh) register
|
|
becomes zero. As the R register is incremented once for each opcode (twice for
|
|
prefixed opcodes), there is no linear relationship between clock cycles and
|
|
refresh cycles.
|
|
In the ZX, INTs are used to terminate scanline drawing, the display data is
|
|
'executed' identical as NOP instructions, followed by a HALT opcode (which is
|
|
identical as repeated NOPs), so that in this special case (as both HALTs and
|
|
NOPs increment R once per 4 clock cycles) INTs can be used to produce a regular
|
|
interval.
|
|
The above INT/HALT combination is used as variable length delay, which is
|
|
required for variable length scanlines (ie. mixed collapsed and expanded
|
|
scanlines) only. Fixed length scanlines could be terminated by hardcoded
|
|
delays.
|
|
In IM 1 (default), the INT handler is located at 0038h in BIOS ROM. INTs are
|
|
enabled by EI instruction, and are automatically disabled upon execution (or
|
|
when issuing DI instruction).
|
|
|
|
NMIs (ZX81 only)
|
|
Non maskable interrupts (NMIs) are requested during horizontal retrace time
|
|
(ie. at the end of each scanline), the CPU is forced into WAIT state for the
|
|
duration of NMI request (unless when executing a HALT opcode which is allowed
|
|
to complete without WAIT states).
|
|
NMIs are used to count the number of drawn scanlines during vertical blanking
|
|
periods. This is allowing the user program to be executed in SLOW mode while
|
|
drawing upper and lower screen borders, and to pass control back to the
|
|
display/retrace procedure once the NMI handler decides to terminate the
|
|
blanking period.
|
|
The NMI handler is located at 0066h in BIOS ROM (independently of IM interrupt
|
|
mode). NMIs are enabled/disabled by I/O instructions - the CPU cannot disable
|
|
NMIs (ie. DI/EI has no effect on NMIs).
|
|
|
|
ZX80/ZX81 Video Display Timings
|
|
-------------------------------
|
|
|
|
Horizontal Scanline Timings
|
|
Horizontal Display 128 cycles (32 characters, 256 pixels)
|
|
Horizontal Blanking 64 cycles (left and right screen border)
|
|
Horizontal Retrace 15 cycles
|
|
Total Scanline Time 207 cycles
|
|
Horizontal retrace rate and duration are fixed. The display procedure might
|
|
increase or decrease the width of the display area (by respectively adjusting
|
|
the blanking time) even though larger screens might exceed the visible
|
|
dimensions of the attached TV set or monitor.
|
|
|
|
Vertical Timings (50Hz)
|
|
Upper Blanking 11592 cycles 56 scanlines (7 charlines)
|
|
Display Area 39744 cycles 192 scanlines (24 charlines)
|
|
Lower Blanking ca.11592 cycles ca. 56 scanlines (or a bit less)
|
|
Vertical Retrace 1235 cycles ca. 6 scanlines
|
|
|
|
Vertical Timings (60Hz)
|
|
Upper Blanking 6624 cycles 32 scanlines (4 charlines)
|
|
Display Area 39744 cycles 192 scanlines (24 charlines)
|
|
Lower Blanking ca. 6624 cycles ca. 32 scanlines (or a bit less)
|
|
Vertical Retrace 1235 cycles ca. 6 scanlines
|
|
|
|
User Available Blank Lines
|
|
Even though upper screen border consists of 56 scanlines (32 in 60Hz mode),
|
|
only 54 scanlines (60Hz: 30 scanlines) are available for user program
|
|
execution. The first of the remaining scanlines is occupied by a HALT opcode
|
|
(which is suspended by a NMI; providing exact retrace synchronisation), and the
|
|
next scanline is spent on a collapsed D_FILE row. Lower screen borders are
|
|
idientical as above, except that no collapsed D_FILE line is drawn at the
|
|
bottom. Instead, some cycles are spent upon incrementing the FRAMES counter.
|
|
|
|
User Available Blanking Time
|
|
The total of 207 cycles per scanline isn't available for user program, even
|
|
during blanking periods: An NMI is generated each line, including some
|
|
NMI-waitstates, the CALL 66h execution, and the execution of the NMI handler
|
|
(which is counting the number of drawn scanlines).
|
|
Item Original ZX81 Tuned ZX81
|
|
Total scanline time 207 cycles 207 cycles
|
|
NMI WAIT - 14 cycles - 0 cycles (WAITMOD by Wilf Rigter)
|
|
NMI CALL 66h - 12 cycles - 12 cycles
|
|
NMI handler - 32 cycles - 29 cycles (NMIPATCH by Nocash)
|
|
Remaining user time = 149 cycles = 166 cycles
|
|
Recursing both upper and lower border, 54*2 scanlines per frame are available
|
|
for user programs in 50Hz mode; only 30*2 in 60Hz mode.
|
|
|
|
Resulting User Available CPU Time
|
|
SLOW, 50Hz Effective Speed 0.804600 MHz (54*2*149 cycles, 50 frames) (ori)
|
|
SLOW, 50Hz Effective Speed 0.896400 MHz (54*2*166 cycles, 50 frames) (tuned)
|
|
SLOW, 60Hz Effective Speed 0.536400 MHz (30*2*149 cycles, 60 frames) (ori)
|
|
SLOW, 60Hz Effective Speed 0.597600 MHz (30*2*166 cycles, 60 frames) (tuned)
|
|
FAST, Total CPU Speed 3.250000 MHz (display disabled)
|
|
ZX80/PAUSE/INPUT 0.0 MHz (user program stopped)
|
|
For more info on tuning, see:
|
|
--> HW Making the ZX81 Faster
|
|
|
|
ZX80/ZX81 Video Character Set
|
|
-----------------------------
|
|
|
|
First, here's the ZX81 character set (64 characters)
|
|
____0___1___2___3___4___5___6___7___8___9___A___B___C___D___E___F____
|
|
00 SPC [' ][ '][''][. ][: ][.'][:']{::}{..}{''} " GBP $ : ? 0F
|
|
10 ( ) > < = + - * / ; , . 0 1 2 3 1F
|
|
20 4 5 6 7 8 9 A B C D E F G H I J 2F
|
|
30 K L M N O P Q R S T U V W X Y Z 3F
|
|
For the ZX80, some characters are located at other positions:
|
|
____0___1___2___3___4___5___6___7___8___9___A___B___C___D___E___F____
|
|
00 SPC " [: ][..][' ][ '][. ][ .][.']{::}{..}{''}GBP $ : ? 0F
|
|
10 ( ) - + * / = > < ; , . 0 1 2 3 1F
|
|
20 4 5 6 7 8 9 A B C D E F G H I J 2F
|
|
30 K L M N O P Q R S T U V W X Y Z 3F
|
|
For both ZX80 and ZX81, all characters can be displayed normal (Bit 7 cleared)
|
|
or inverted (Bit 7 set). For SPC and GRA see below, GBP means the 'pounds'
|
|
currency symbol.
|
|
|
|
Block Graphics
|
|
For [solid] symbols, all 16 combinations of block graphics (with any number of
|
|
4x4 pixel dots at any position within a 8x8 pixel character) can be produced by
|
|
using the invert-attribute bit. Only limited combinations are possible for
|
|
{dithered} symbols.
|
|
|
|
ZX81 charset is stored at 1E00h-1FFFh in BIOS ROM (I register I=1Eh), ZX80
|
|
charset at 0E00h-0FFFh (I=0Eh).
|
|
|
|
The lower 9 bits (A8-A0) of the characterset are addressed by the 'display
|
|
controller' (overriding the CPU supplied address signals, which outputs the
|
|
whole IR register to the address bus) - the special address bits are output to
|
|
the ROM chip only (but not to RAM, nor to Expansion Port), so neither internal,
|
|
not external RAM can be used to store character data.
|
|
|
|
ZX81 Video Nonstandard UDG/CHRS Expansions
|
|
------------------------------------------
|
|
|
|
UDG/CHRS boards (User Defined Graphics / Character Set expansions)
|
|
|
|
Internal Expansions
|
|
The ZX80/ZX81 has two variants of A0-A8 address lines: The normal A0-A8 are
|
|
from the CPU, and are wired to RAM and Expansion Port. For character set
|
|
addressing A0'-A8' are generated by the ULA, and wired to the BIOS ROM.
|
|
The dk'tronics/kayde expansions are mounted as internal daughterboard, plugged
|
|
to the BIOS ROM chip. That method allows to use the A0'-A8' lines.
|
|
|
|
External Expansions
|
|
The QS expansion connects to expansion port. Accordingly, it must externally
|
|
reproduce some of the ULA functionality (latch the character number & increment
|
|
the LINECTR) in order to generate its own A0'-A8' signals. The QS also takes
|
|
the inverse flag as character MSB (aka A9'), allowing to use 128 different
|
|
symbols rather than only 64.
|
|
|
|
dk'tronics 4K Graphics ROM (plus optional RAM)
|
|
Contains a 4K EPROM, mapped to 2000h-2FFFh, with seven new character sets (of
|
|
64 symbols each), the region at 2E00h-2FFFh is mainly FFh-filled, and contains
|
|
only a few USR functions for selecting the new character sets (each one: "LD
|
|
A,20h+N*2, LD I,A, RET", except N=7: selects the default ZX81 charset with
|
|
I=1Eh). As an upgrade option, the board can be fitted with 1K or 2K SRAM, or 4K
|
|
EPROM (mapped to 3000h-3xFFh). dk'tronics offered 6 programs for use with the
|
|
hardware:
|
|
Asteroids
|
|
Centipede
|
|
Defender
|
|
Meteor Storm
|
|
Space Invaders
|
|
Character Development System (aka UDG, User Defined Graphics editor)
|
|
The pre-defined ROM symbols are possibly useful for some games, but useless for
|
|
others. Only 64 symbols can be used at once, for example one cannot
|
|
simultaneously display lower-case letters and numeric digits. Many symbols
|
|
(like A-Z) are duplicated in several 64-character banks, so one gets far less
|
|
than 512 <different> characters.
|
|
Note: Of the above 6 programs, only Space Invaders and UDG are found in the
|
|
internet. There's also a Centipede version, but it doesn't support the hardware
|
|
(it can be somewhat tweaked by typing "RAND USR 11904" before "RUN", but this
|
|
causes its text screens to become distorted, only its game screen looks more or
|
|
less as it should).
|
|
|
|
Kayde 4K ROM (plus optional RAM)
|
|
This is a (probably unlicensed) clone of the dk'tronics 4K character board.
|
|
Locations 000h..7FFh and A00h..FFFh in the ROM are 1:1 byte-identical to the
|
|
dk'tronics ROM. Locations 800h..9FFh are modified: Containing inverse symbols
|
|
in dk'tronics ROM, and Pac-Man symbols in Kayde ROM. Kayde advertised three
|
|
games that support their hardware:
|
|
Centipede
|
|
Peckman (this one probably requires the Kayde-ROM with Pac-Man symbols)
|
|
Space Invaders
|
|
The circuit with three logic chips & three ROM/RAM sockets looks identical to
|
|
the dk'tronics board (aside from some cosmetic differences: top/bottom layers
|
|
exchanged, and Kayde text instead of dk'tronics text on the PCB). Even the
|
|
advert seems to be a shameless copy of the dk'tronics one (though with slight
|
|
mis-spellings in the 1st advert: saying it "fits nearly" instead of "fits
|
|
neatly"). dk'tronics had adverts in Sinclair User issues 1..8, Kayde had
|
|
adverts in the same magazine, issues 4..8.
|
|
Note: One or two years later, Kayde also (illegally) cloned Compusounds
|
|
patented "Telesound 84" (an add-on for amplifying the Spectrum's ULA sound via
|
|
TV).
|
|
|
|
QuickSilva QS CHRS board
|
|
Maps 1K RAM to 8400h-87FFh, allows to define and display 128 characters (64
|
|
normal, and, independently thereof, 64 inverted characters) (for example, the
|
|
inverse ones can be assigned as lowercase letters).
|
|
On power-up, the RAM is uninitialized, so garbage would be displayed.
|
|
Quicksilva has "solved" this problem by providing a mechanical switch, where
|
|
the user can (must) manually enable/disable the CHRS feature (there is no I/O
|
|
port to do this by software). Moreover, the board has 4 DIP switches,
|
|
presumably for adjusting HSYNC or so (should be all off for ZX81 in SLOW mode,
|
|
or switch 3,4 on for ZX80 and ZX81 in FAST mode) (whereas "FAST" mode is
|
|
probably meant to mean PAUSE/INPUT, accordingly software should avoid to switch
|
|
between SLOW mode and PAUSE/INPUT).
|
|
Depending on the invert bit, the first or second 512 bytes are mirrored to
|
|
1E00h on ULA access (however, the CPU is still able to read ROM from 1E00h;
|
|
though, eventually, ROM-reading MIGHT work only when the enable switch is off?)
|
|
Emulating the QS CHRS board with its original crude manual enable switch is
|
|
easy, but automatically detecting and enabling it is more difficult, possible
|
|
ways are: Detect the original driver (won't work with custom drivers), or,
|
|
detect if 8400h..87FFh contains data whilst all other RAM at 8000h and up is
|
|
zero-filled (or filled with whatever values you stored there on power-up).
|
|
|
|
Haven Hardware chrs board
|
|
Another character thing. Seems to be able to map RAM (or ROM?) to 1E00h-1FFFh
|
|
and 3E00h-3FFFh. Low-level details are unknown? (sounds similar to the QS
|
|
board)
|
|
|
|
AGB UDG graphic card
|
|
Whatever. Reportedly mirrors 512 byte RAM to 1E00h.
|
|
|
|
Memotech UDG Interface
|
|
Whatever - if it does exist at all. It is mentioned only on one single webpage.
|
|
|
|
Unknown UDG Type
|
|
There is a game called "FROGGER-HR" by "E LANTING". It sets I=20h and uses
|
|
character RAM at 2000h (similar to dk'tronics/kayde, but having RAM at that
|
|
location, not ROM). Unknown which hardware does support this (if any - it's
|
|
also possible that the game is homebrewn and works only with emulators).
|
|
|
|
ZX81 Video Nonstandard HIRES Expansions
|
|
---------------------------------------
|
|
|
|
QuickSilva QS HI-RES screen board
|
|
Maps 2K ROM to 2800h-2FAFh (errr, more likely: 2800h..2FFFh or so), and 6K RAM
|
|
to A800h-BFFFh. Low-level details are unknown?
|
|
|
|
Memotech HRG
|
|
Maps 2K EPROM to 2000h-27FFh. The EPROM contains USR function for
|
|
high-resolution PLOT and LINE drawing functions. Supported resolution is
|
|
248x192. Seems to require a separate RAM expansion for use as video RAM. Aside
|
|
from the EPROM, it does contain an overkill of five 74LSxx chips, and two PAL
|
|
chips. Low-level details are unknown?
|
|
|
|
G007 Graphic Card
|
|
Whatever.
|
|
|
|
HRG-MS (Matthias Swatosch)
|
|
Technically same as Wilf Ritger's hires, but doesn't work unless first loading
|
|
an additional software driver from cassette, before loading the actual program.
|
|
The driver contains some USR functions for drawing LINEs from within BASIC - in
|
|
the BASIC era it would have been revolutionary, nowadays... it isn't. The
|
|
driver loading is more than uncomfortable, and BASIC is crap anyways.
|
|
|
|
ZX81 Video Nonstandard Picture Size
|
|
-----------------------------------
|
|
|
|
The official picture size is 32x24 tiles (256x192 pixels) with huge borders.
|
|
However, on a PAL screen, the ZX81 can display 40x34 tiles (320x272 pixels).
|
|
|
|
34-lines Quicksilva Defender
|
|
Displays 31x32 tiles (the advert claims 34 lines, but it's actually only 32
|
|
lines). There's some glitch in the blanking/retrace that causes the topmost
|
|
lines to become ultra-bright and horizontally unstable (at least on my Philips
|
|
TV Set). Moreover, the framerate is only 43Hz (that part works fine on my TV
|
|
Set).
|
|
Note: The game was also announced for ZX80 and works without NMI (even the ZX81
|
|
version doesn't use NMIs).
|
|
|
|
Wilf Ritger's WRX1K
|
|
A variant of Wilf Ritger's WRX hires. WRX1K works on an unexpanded ZX81 with 1K
|
|
RAM, accordingly, the picture/bitmap is tiny.
|
|
|
|
MAXDEMO
|
|
Displays 40x32 tiles text and 320x256 pixels hires. There seems to be a
|
|
vertical centering glitch: No upper border visible, but 16 lines lower border
|
|
visible.
|
|
|
|
Mixed Video Modes
|
|
Highres Chess (192 hires lines, plus 1-2 text lines)
|
|
Maxdemo (splits hires/text regions)
|
|
|
|
ZX81 Video Nonstandard Color Expansions
|
|
---------------------------------------
|
|
|
|
Lambda Color Module
|
|
External Color Module designed for the Lambda 8300. Contains 1K Color RAM (with
|
|
color attributes similar as on ZX Spectrum). Supports 8 colors, but the palette
|
|
is still unknown.
|
|
It should also work with ZX81, though with some restrictions: The normal ZX81
|
|
BIOS doesn't initialize the color attributes on power-up (upon power-on the
|
|
module is disabled, displaying a "white-on-white?" picture; to activate color
|
|
RAM one needs to init the RAM at 2000h-2FFFh and then enable it via write to
|
|
3001h) (the unit isn't re-disabled on warmboot via /RESET, only on power-on),
|
|
and the ZX81 doesn't have a composite video output (so one would need some
|
|
soldering to extract the monochrome video signal), and, compared to Lambda, the
|
|
ZX81 has black/white inverted, so ink/paper will be exchanged.
|
|
See Lambda 8300 for details.
|
|
|
|
Interface 8 x Couleurs / Carte Couleur (PCB: "DISTR.(C) par S.A.M. 001")
|
|
A french add-on for the ZX81. Sold by EREL Boutique.
|
|
The interface doesn't contain any RAM for storing color attributes. Instead, it
|
|
seems to watch the character numbers being read from D_FILE, and applies one of
|
|
the 8 colors when seeing CHR numbers 86h..8Dh (aka inverse [A]..[H] symbols).
|
|
The palette is unknown. Also unknown if it changes the foreground and/or
|
|
background color. Also unknown if the [A]..[H] symbols are displayed, or if
|
|
they are masked.
|
|
Video Output: Outputs UHF (SECAM) and Peritel (SCART, ie. probably RGB). UHF
|
|
output is done using ZX81's internal UHF modulator (requires some soldering)
|
|
(the signal can be adjusted by potentiometers on the interface, so colors might
|
|
be "user-selectable" rather than having a constant palette?). Peritel requires
|
|
a special cable that connects to a spare DIL socket on the interface (the
|
|
pin-outs of the socket are unknown, so without the original cable, one could
|
|
only guess which pins a R,G,B).
|
|
|
|
Carte couleur
|
|
Reportedly made by (provider: DIRECO International).
|
|
Claimed to support 16 colors with SCART.
|
|
Claimed to use ASCII... uh, ASCII, on a ZX81?
|
|
Said to be Chr $ 161 is the first color (pink).
|
|
|
|
the peripheral color (catalan translation)
|
|
As the highest town, the play calling this peripherique tour and see the iron
|
|
because Souder Souder had a cable on the peripheral of the anode of diode D9
|
|
ordinateur, fortunately, a printed circuit board with the plan had branchement
|
|
delivered with the peripheral.
|
|
The curseurs colored bands disappeared and became each other: the F curseur
|
|
became a green hand, the K a white band, G one side magenta and yellow L a
|
|
band. You could play with a palette of 16 colors:
|
|
White plays 4 or CHR invested $ 160
|
|
Yellow key 5 or CHR $ 161
|
|
Light Blue plays 6 or CHR $ 162
|
|
Green light touch 7 or CHR $ 163
|
|
Fusch plays 8 or CHR $ 164
|
|
Red key 9 or CHR $ 165
|
|
Keyboard has blue or CHR $ 166
|
|
Dark gray or key B CHR $ 167
|
|
CHR turn gray or C $ 168
|
|
Kaki plays D or CHR $ 169
|
|
Cyan play E or CHR $ 170
|
|
Green plays or F CHR $ 171
|
|
Magenta G plays or CHR $ 172
|
|
Carmin playing H or CHR $ 173
|
|
And navy blue key or CHR $ 174
|
|
Black J key or CHR $ 175
|
|
Example:
|
|
10 PRINT CHR $ 173
|
|
20 PRINT "THREE"
|
|
carmine dye gave the word THREE. So then each word you wanted color.
|
|
|
|
ZX81 Joystick Expansions
|
|
------------------------
|
|
|
|
Joystick Ports and Data Bits (U=Up, D=Down, L=Left, R=Right, F=Fire)
|
|
Port_Joystick_Type___________________________7_6_5_4_3_2_1_0___Data Bits___
|
|
EFFE Nocash A12 joystick (keys 6,7,8,9,0) - - - D U R L F (0=Pressed)
|
|
EFFE AGF (cursor mode, A12, keys 6,7,8,0) - - - D U R - F (0=Pressed)
|
|
F7FE AGF (cursor mode, A11, key 5) - - - L - - - - (0=Pressed)
|
|
DFFE AGF (2nd Joystick, A13, keys Y,U,I,P) - - - D U R - F (0=Pressed)
|
|
FBFE AGF (2nd Joystick, A10, key T) - - - L - - - - (0=Pressed)
|
|
nnFE PC8300 (ZX81 clone using A9..A13, bit3) - - - - x - - - (0=Pressed)
|
|
xx1D Zebra Joystick - - - F R L D U (0=Pressed)
|
|
xxBF Timedata ZXM Sound Box, PSG Reg 14 0 F U D L R y x (0=Pressed)
|
|
xxDF Mikro-Gen (Digital joystick)(Frogs) - - - F L R D U (0=Pressed)
|
|
MEM Mikro-Gen (Analog joystick) F a a a a a a a (analog)
|
|
MEM Quicksilva Sound Board, PSG Reg 15 ? ? ? ? ? ? ? ? (?=Pressed)
|
|
???? Microdigital TK83/TK85 (DIN socket) ? ? ? ? ? ? ? ? (?)
|
|
|
|
Quicksilva "Joystick" Games
|
|
As far as known, Quicksilva has NOT manufactured a joystick interface. However,
|
|
at least one Quicksilva game (Asteroids) allows to use PSG reg 15 (of the QS
|
|
Sound board) as joystick port (where the user needs to wire the joystick to the
|
|
16bit I/O port).
|
|
|
|
Micro Gen - for Micro Gen's "Space Raider" game (maybe also for "Bomber")
|
|
For several Micro Gen games. Requires their 4-channel A/D converter board. Can
|
|
be used with 2 joysticks - that is, apparently ANALOGUE joysticks.
|
|
Note: The company name is written with "c" or "k": Micro Gen (adverts and
|
|
catalog), or Mikro Gen (cassette inlays).
|
|
IN (xxDFh) -- bits 1,2 // lunar: bit2,3,4
|
|
xx == select something ?
|
|
scramble: LD A,(3E80h) others: LD HL,3E80h (3E80h is 16000 decimal)
|
|
scramble uses ONLY 3E80 (not DF), and supports up/dn/rt/fire
|
|
|
|
Mikro-Gen Analog Joystick (Memory 3E80h)
|
|
Memory mapped to address 3E80h (=16000 decimal). Write to 3E80h:
|
|
00h Axis 0 (request vertical position, and bit7=not used)
|
|
01h Axis 1 (request horizontal position, and bit7=Fire button 1=Pressed)
|
|
??h Axis 2,3 (for second joystick) (not used by any games)
|
|
There must be a delay after writing (ld b,96h, djnz $). Thereafer, reading from
|
|
3E80h:
|
|
returns 7bit analog for selected axis (and bit7=fire, if any)
|
|
vertical: 00h..7Fh = up..down
|
|
horizontal: 00h..7Fh = left..right
|
|
Supported by several Mikro-Gen games (and one Quicksilva game):
|
|
Space Invaders (Mikro-Gen) (uses analog value as screen position)
|
|
Scramble (Mikro-Gen) (converts analog value to digital move/no move)
|
|
Bomber (Mikro-Gen) (supports both digital and analog joysticks)
|
|
Croaka Crawler (aka Hopper) (Quicksilva)
|
|
|
|
Mikro-Gen Digital Joystick (Port DFh)
|
|
This is the "inofficial" digital joystick used in several Mikro-Gen games.
|
|
Lunar Rescue (Mikro-Gen)
|
|
Frogs (Mikro-Gen)
|
|
Bomber (Mikro-Gen) (supports both digital and analog joysticks)
|
|
Tempest (also does a single read from 3E80h, but otherwise supports DFh only)
|
|
Inofficial meaning that Mikro-Gen doesn't ever seem to have advertised the
|
|
digital joystick (either they did silently replace their analog joystick by the
|
|
digital one, or above games are homebrewn patches).
|
|
|
|
Thurnall Electronics - see advert from them
|
|
Spectrum Version advertised as "The Winners Joystick". Supports Cursor+Rubout
|
|
keys, and Q-A-Z-X keys.
|
|
|
|
AGF Joystick (from AGF Hardware)
|
|
Available for ZX81 and Spectrum. Both versions work as so:
|
|
5-6-7-8-0 Joystick 1 (Cursor keys & rubout)
|
|
T-Y-U-I-P Joystick 2 (same data bits as above, but other address lines)
|
|
The joystick interface connects to expansion port. For some reason, only the
|
|
keyboard OR joystick can be operated at a time - there is a switch to select
|
|
between keyboard and joystick mode.
|
|
|
|
AGB - JOYSTICK II : [driver in the P_Tools directory]
|
|
Reportedly: Use the $DF & $EF IN IRQ Port.
|
|
Port A: Press "5" LEFT "6" DOWN "7" UP "8" RIGHT "New/Line" FIRE
|
|
Port B: Press "A" LEFT "S" DOWN "W" UP "D" RIGHT "F" FIRE
|
|
|
|
Timedata ZXM Sound Box - includes joystick port (PSG reg 14)
|
|
No known software supporting this.
|
|
|
|
Zebra Joystick (US) (Port 1Dh)
|
|
Supported by a homebrewn Hires Space Invaders game. Zebra also released some
|
|
patches for a handful of third-party games.
|
|
hrinvaders --> zebra joystick, port 1Dh
|
|
0 up (0=Pressed)
|
|
1 down (0=Pressed)
|
|
2 left (0=Pressed)
|
|
3 right (0=Pressed)
|
|
4 fire (0=Pressed)
|
|
5-7
|
|
zebra listing
|
|
1 REM 123456789
|
|
2 POKE 16514,219 DB ;\IN A,[1Dh]
|
|
3 POKE 16515,29 1D ;/
|
|
4 POKE 16516,47 2F ;-CPL
|
|
5 POKE 16517,230 E6 ;\AND A,1Fh
|
|
6 POKE 16518,31 1F ;/
|
|
7 POKE 16519,6 06 ;\LD B,0
|
|
8 POKE 16520,0 00 ;/
|
|
9 POKE 16521,79 4F ;-LD C,A
|
|
10 POKE 16522,201 C9 ;-RET
|
|
20 PRINT USR 16514;
|
|
|
|
ZX81 Sound Expansions
|
|
---------------------
|
|
|
|
ZON-X81 Sound (Bi-Pak)
|
|
Contains a PSG sound chip, built-in speaker with manual volume control. There
|
|
seems to be no user I/O port.
|
|
F = 1625000 Hz / 16 / nnn
|
|
Parameters are poke'd to RAM, and then forwarded via USR call.
|
|
Uses "1 REM YYPEEK TO YYPEEK ?TAN"
|
|
OUT (CFh or DFh),A ;index
|
|
OUT (0Fh),A ;data (w)
|
|
The manual is unclear about the "index" port:
|
|
BASIC example suggests "TO" token = port DFh.
|
|
But ASM example suggests port CFh.
|
|
Maybe both are working. Anyways, the recommended address would be DFh (assuming
|
|
that the manual was mainly addressed to BASIC programmers, and the ASM example
|
|
being only a confused side note). The technical specs in the french "Interface
|
|
Sonore" manual uses DFh, too).
|
|
Note: The Spectrum version uses ports FFh and 7Fh, maybe these do work on ZX81,
|
|
too (though under BASIC, 7Fh cannot be entered via keyboard, which may explain
|
|
why the manual used other values)
|
|
Supported by
|
|
Cosmic (brazilian magazine Revista Micro Sistemas, Oct/1986)
|
|
Lunar 10 (brazilian magazine Revista Micro Sistemas, Nov/1986)
|
|
|
|
ZXM Sound Box (Timedata) (OUT 159/223)
|
|
For ZX81 and Spectrum.
|
|
Contains a 8912 PSG sound chip, built-in speaker with manual volume control,
|
|
can be optionally connected to external amplifier. There is a 9pin DSUB
|
|
atari/commodore joystick port; can be also used as 7bit user I/O port.
|
|
F = 100000 Hz / nnn ;approximately, according to manual
|
|
the above 100kHz is probably meant to be 3.25MHz/32.
|
|
OUT (159),A ;9F index ;\same addresses for ZX81 and Spectrum, ZX81
|
|
OUT (223),A ;DF data (w) ; accesses via POKE+USR, Spectrum via OUT token
|
|
IN A,(191) ;BF data (r) ;/ <--- for joystick port
|
|
DSUB 9pin male Pin-outs
|
|
Pin Bit
|
|
1 PSG.PortA.Bit5 up / forward
|
|
2 PSG.PortA.Bit4 down / back
|
|
3 PSG.PortA.Bit3 left
|
|
4 PSG.PortA.Bit2 right
|
|
5 PSG.PortA.Bit1 general purpose (usually 1) (C64: Pot Y)
|
|
6 PSG.PortA.Bit6 Fire
|
|
7 +5V
|
|
8 GND
|
|
9 PSG.PortA.Bit0 general purpose (usually 1) (C64: Pot X)
|
|
According to manual, PSG.PortA.Bit7 is always zero.
|
|
Supported by:
|
|
Sound Box Super Editor (Timedata) (zxm demo tape & type-in listing in manual)
|
|
|
|
QS Sound Board (QuickSilva)
|
|
AY-3-8910. Two 8bit I/O ports. Reportedly memory mapped to 7FFEh..7FFFh (see
|
|
Sinclair User, Issue 2, May 1982, Page 24).
|
|
7FFFh index (W)
|
|
7FFEh data (R/W)
|
|
Supported by:
|
|
Cosmic Guerilla (Quicksilva)
|
|
Croaka (aka Hopper) (Quicksilva)
|
|
Defenda (Quicksilva)
|
|
Space Invaders
|
|
Asteroids (Quicksilva) (also supports PSG reg 15 as alternate joystick)
|
|
Scramble (Quicksilva)
|
|
PSG reg 15: used by asteroids (as OUTPUT, probably as pull-up)
|
|
|
|
William Stuart Systems ZX80/ZX81 Music Synthesiser
|
|
Three-part music and sound effects. 16-line control port for home security,
|
|
robot control, etc. Can be used with the "Composer" music program.
|
|
|
|
Telesound 82 (ZX80/ZX81 version) - stops flicker (is THAT sound related?)
|
|
3-channel Sound with 16bit I/O port (Bolton Electronics)
|
|
Motherboard plus Sound-Card (Watford)
|
|
|
|
Interface Sonore
|
|
(assumed to be from Mageco Electronic)
|
|
(actually, seems to be same as the Bi-Pak thing)
|
|
AY-3-8912
|
|
Manual page 3 contains (distorted) instructions for "1 REM Y1PEEK TO Y2 ?TAB"
|
|
which would mean "LD A,index; OUT [DF],A; LD A,data; OUT [0F],A; RET"
|
|
But...
|
|
Manual page 79-80 contains "Carte Sonore QS" 7FFEh,7FFFh stuff.
|
|
These pages probably refer to a DIFFERENT and MEMORY MAPPED sound interface.
|
|
Namely, to the QS Sound Board (see above).
|
|
|
|
ZXS Speech Synthesiser (Timedata)
|
|
DCP Microdevelopments Speech Pack (1982) for ZX81
|
|
Speech hardware. Both DCP and Timedata also released versions for ZX Spectrum.
|
|
ZXS might be allophone based (?), DCP isn't allophone based (it uses a fixed
|
|
digitized vocabulary stored in ROM).
|
|
|
|
Lambda 8300
|
|
ZX81 clone with built-in speaker. The speaker is software controlled (toggled
|
|
HIGH/LOW via IN A,[F5h]).
|
|
|
|
ZX80/ZX81 Memory Map and System Area
|
|
--------------------------
|
|
|
|
Overview
|
|
0000-1FFF BIOS ROM (8KBytes)
|
|
2000-3FFF not used
|
|
4000-43FF Internal RAM (1 KByte)
|
|
4000-7FFF External RAM (16 KBytes)
|
|
Internal RAM is disabled (and cannot be accessed) when external RAM is
|
|
installed.
|
|
|
|
ZX81 RAM Map
|
|
4000 System Area (see below)
|
|
407D BASIC Program
|
|
D_FILE Video Memory (BG Map)
|
|
VARS BASIC Variables
|
|
E_LINE-1 Byte 80h
|
|
E_LINE Input Buffer/Workspace
|
|
STKBOT BASIC Calculator Stack
|
|
STKEND Machine Stack/Free Memory
|
|
SP Machine Stack/In Use (SP is meant to be the CPUs SP register)
|
|
ERR_SP GOSUB Stack
|
|
RAMTOP USR Programs (Begin of unused/reserved memory)
|
|
|
|
ZX81 System Area
|
|
Addr. Name Expl
|
|
4000 ERR_NR Errorcode-1
|
|
4001 FLAGS Various BASIC Control flags
|
|
Bit0=used (purpose unknown)
|
|
Bit1=Redirect Output to printer
|
|
Bit2=used (purpose unknown)
|
|
Bit3-5=not used
|
|
Bit6=used (purpose unknown)
|
|
Bit7=used (purpose unknown)
|
|
4002 ERR_SP Pointer to top of Machine Stack / Bottom of GOSUB Stack
|
|
4004 RAMTOP Pointer to unused/free memory (Changes realized
|
|
at next NEW or CLS)
|
|
4006 MODE Selects [K], [L], [F], or [G] Cursor
|
|
4007 PPC Line Number of most recently executed BASIC line
|
|
---Begin of Save Area---
|
|
4009 VERSN Should be 00h to identify ZX81 cassette files (FFh=Lambda)
|
|
400A E_PPC Line Number of currently selected line [>] Cursor
|
|
400C D_File Pointer to Video Memory (BG Map) / End of Basic Program
|
|
400E DF_CC Pointer to VRAM Address for PRINT
|
|
4010 VARS Pointer to BASIC Variables Area
|
|
4012 DEST Pointer to Variable when assigning a value to it
|
|
4014 E_LINE Pointer to Input Buffer/Workspace, and to --End of Save Area--
|
|
4016 CH_ADD Pointer to next interpreted character
|
|
4018 X_PTR Pointer to character prior to [S] Symbol (=Syntax Error) (or
|
|
ptr to aborted/breaked line)
|
|
401A STKBOT Pointer to BASIC Calculator Stack / End of
|
|
Input Buffer/Workspace
|
|
401C STKEND Pointer to bottom of Machine Stack / End of Calculator Stack
|
|
401E BERG Calculator B-Register
|
|
401F MEM Pointer to Calculator Memory (usually same as MEMBOT)
|
|
4021 - Not used
|
|
4022 DF_SZ Number of lines in lower display section (including 1 blank
|
|
line)
|
|
4023 S_TOP Line Number of first line for automatic LISTing
|
|
4025 LAST_K Keyboard - Recently pressed key (4025=row, 4026=shift/column)
|
|
4027 DEBOUN Keyboard - Debounce State (key release delay)
|
|
4028 MARGIN Vertical Border Height (55 lines at top/bottom for 50Hz,
|
|
31 for 60Hz)
|
|
4029 NXTLIN Address of next BASIC line which is to be executed,
|
|
pointing to a byte >=40h when stopped, indicates
|
|
autostart address in cassette files.
|
|
402B OLDPPC Line Number for CONT
|
|
402D FLAGX 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
|
|
402E STRLEN Length of string during assignment
|
|
4030 T_ADDR Pointer to next item in Syntax Table (or INPUT's old S_POSN)
|
|
4032 SEED Random Number Seed
|
|
4034 FRAMES Decrementing Video Frame Counter (Bit15: 0=PAUSE, ie.
|
|
display ON, program PAUSEd)
|
|
4036 COORDS X-Coordinate of last PLOT, Y-Coordinate of last PLOT
|
|
4038 PR_CC Least significant byte of PRBUFF printer buffer pointer
|
|
4039 S_POSN X-Coordinate for PRINT, Y-Coordinate for PRINT
|
|
403B CDFLAG 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)
|
|
403C PRBUFF Printer Buffer 32 characters + NEWLINE (76h)
|
|
405D MEMBOT Default workspace for BASIC Calculator
|
|
407B - Not used (2 bytes)
|
|
|
|
ZX80 Memory Map
|
|
4000..4027 System Area
|
|
4028..(4008)-1 Basic Program
|
|
(4008)..(4004 or 400A)-1 VARS
|
|
(4004 or 400A)..(400C)-1 Input Buffer, and probably something else ???
|
|
(400C)... VRAM
|
|
...
|
|
|
|
ZX80 System Area
|
|
4000 ERR_NR Error Number (one less than report code)
|
|
4001 FLAGS Various Flags to control BASIC System
|
|
7 1-Syntax off 0-Syntax on
|
|
6 1-Numeric result 0-String result
|
|
5 1-Evaluating function (not used)
|
|
3 1-K cursor 0-L cursor
|
|
2 1-K mode 0-L mode
|
|
0 1-No leading space 0-Leading space
|
|
4002 PPC Line number which is to be executed next (bit15: 1=stopped)
|
|
4004 P_PTR Position in RAM of [K] or [L] cursor
|
|
4006 E_PPC Line Number of current line with [>] cursor (for LIST)
|
|
4008 VARS Address of start of variables area (end of BASIC Program)
|
|
400A E_LINE Address of start of Edit Line (end of VARS) (-save area end-)
|
|
400C D_FILE Start of Display File (VRAM) (end of Edit Line/Input Buffer)
|
|
400E DF_EA Address of the start of lower screen
|
|
4010 DF_END Display File End
|
|
4012 DF_SZ Number of lines in lower screen
|
|
4013 S_TOP The number of first line on screen
|
|
4015 X_PTR Address of the character preceding the [S] marker
|
|
4017 OLDPPC Line number to which CONTINUE jumps
|
|
4019 FLAGX More flags.
|
|
7 1-K mode 0-L mode
|
|
6 1-Numeric result 0-String result
|
|
5 1-Inputting 0-Editing
|
|
401A T_ADDR Address of next item in syntax table
|
|
401C SEED The seed for the random number
|
|
401E FRAMES Count of frames shown since start-up (incrementing)
|
|
4020 DEST Address of variable in statement
|
|
---Active/Basic:
|
|
4022 RESULT Value of the last expression
|
|
4024 S_POSN_X Column number for print position
|
|
4025 S_POSN_Y Line number for print position
|
|
4026 CH_ADD BASIC program pointer (address of next char/token)
|
|
---Pause/Input:
|
|
4022 - Keyboard debounce
|
|
4023 MARGIN Screen border height
|
|
4024 ?
|
|
4026 LAST_K Keyboard last key pressed (4026=row, 4027=column)
|
|
|
|
ZX80/ZX81 Memory Mirrors and Expansions
|
|
---------------------------------------
|
|
|
|
Memory Overview
|
|
RAM is originated at 4000h, for 1K RAM: at 4000h-43FFh; 48K: at 4000h-FFFFh,
|
|
the area below 4000h is used only when more than 48K are installed.
|
|
In the ZX world, memory accesses can be split into three categories: data read,
|
|
data write, and opcode read. Opcode read is sensed by the CPUs /M1 signal, and
|
|
behaves different than normal data read in case that A15 is HIGH, ie. for
|
|
addresses in range from 8000h-FFFFh.
|
|
address code read write
|
|
0000..1FFF ROM ROM --- ;all ZX81's
|
|
2000..3FFF RAM4 RAM4 RAM4 ;ZX81 with 56K only
|
|
4000..7FFF RAM1 RAM1 RAM1 ;ZX81 with 16K or more RAM
|
|
8000..BFFF VRAM2 RAM2 RAM2 ;ZX81 with 32K or more RAM
|
|
C000..FFFF VRAM1 RAM3 RAM3 ;ZX81 with 48K or more RAM (*)
|
|
(*) That, for the RAM3 part, VRAM1 is of course found in all ZX with 16K
|
|
The memory region 8000h-FFFFh cannot be used to execute machine code programs;
|
|
any opcodes in that region with Bit 6 cleared are treated as video output (and
|
|
are executed as NOPs).
|
|
Opcodes/video data at C000-FFFFh are read from memory at 4000h-7FFFh - the
|
|
software should usually write video data into memory at 4000h-7FFF, and
|
|
'execute' the data in the mirrored region at C000-FFFF.
|
|
|
|
1K RAM
|
|
Default ZX81 includes only 1K RAM at 4000h-43FFh. However, the default RAM and
|
|
ROM select signals are mirroring ROM across 0000h-3FFFh and 8000h-BFFFh, and
|
|
RAM at 4000h-7FFFh and (including 'data read' accesses) at C000h-FFFFh.
|
|
The ZX81 mainboard provides space for either two 1K x 4bit SRAM chips, or one
|
|
1K x 8bit SRAM chip (with L1 jumper closed).
|
|
|
|
2K RAM
|
|
The american 'ZX81' (Timex TS1000) appears to have been delivered with 2K
|
|
internal memory. The socket for 1K x 8bit SRAM on the ZX81 mainboard may be
|
|
used (by closing L2 jumper) for a 2K x 8bit SRAM chip.
|
|
|
|
16K RAM
|
|
Even though above described 1K RAM signals are providing memory space for up to
|
|
16K RAM, the Memotech expansions (not sure about Sinclair or other expansions)
|
|
are supplying their own RAM and ROM select signals; ROM is then located at
|
|
0000-1FFF only, and RAM at 4000-7FFFh only, all other areas are unused,
|
|
typically 'FFh filled'. Except that, video memory opcode reads (but not data
|
|
reads) from C000h-FFFFh are mirrored to 4000h-7FFFh as usually.
|
|
Timex TS1500 has been delivered with 16K built-in RAM.
|
|
|
|
The 16K RAM configuration may be more or less treated as standard configuration
|
|
- programmers should recurse that below expansions of 32K or more RAM haven't
|
|
been very popular - thus any programs that require more than 16K memory won't
|
|
work on most ZX computers.
|
|
|
|
32K RAM
|
|
RAM is located at 4000h-BFFFh, whereas the upper half may be used to store data
|
|
and/or to 'execute' video code, but not for normal machine code program code.
|
|
Note that the BIOS memory detection ends at 8000h, the BIOS will detect only a
|
|
maximum of 16K RAM - and the stack pointer will be then initiated at 8000h.
|
|
Thus, loading large cassette files will overwrite the stack. When using more
|
|
than 16K RAM, the RAMTOP identifier in the system area must be changed manually
|
|
by POKE instructions, and then applied by a NEW instruction (or by a short
|
|
program that moves stack data and stack pointers to the new addresses).
|
|
Care should be taken that video memory may not cross the 7FFFh/8000h boundary;
|
|
Video data at 7FFFh is executed by addressing FFFFh, and thus the next address
|
|
will be 0000h instead 8000h! Ie. video memory may be located in either one of
|
|
the two 16K blocks, not in both.
|
|
|
|
48K RAM
|
|
RAM is located at 4000h-FFFFh, same restrictions as for 32K RAM apply. The
|
|
memory at C000h-FFFFh can be used as data storage only, but not for machine
|
|
code execution, and not for video data 'execution'.
|
|
When patching the RAMTOP value use the maximum of FFFFh (indicating 48K minus
|
|
one byte), as video memory must be below C000h, BASIC program code is
|
|
restricted to less than 32K as well, BASIC variables may use the additional
|
|
memory though.
|
|
Some 16K expansions can be combined with 32K expansions to gain a total of 48K
|
|
RAM.
|
|
|
|
64K RAM
|
|
Even though called "64K" expansions, most or all of these expansions do not
|
|
seem to support bank switching which'd allow to switch RAM into the 8K BIOS ROM
|
|
area at 0000h-1FFFh, so only 56K of RAM at 2000h-FFFFh can be used.
|
|
As for 48K RAM, the highest RAMTOP value would be FFFFh, the 'RAMBASE' is fixed
|
|
at 4000h, so that the additional memory at 2000h-3FFFh cannot be used by the
|
|
BIOS/BASIC interpreter.
|
|
|
|
ZX80/ZX81 Memory Binary Data/Machine Code Programs
|
|
--------------------------------------------------
|
|
|
|
Depositing Binary Data/Program in Memory
|
|
The ZX81 does not directly support loading binary files from cassette, when
|
|
using LOAD, a memory image is loaded which contains the BIOS system variables,
|
|
the BASIC program, the video memory, and the BASIC variables.
|
|
The following are places that can be used as reserved area for binary code.
|
|
|
|
Using a REM instruction (in the program area)
|
|
Preferably locate the REM in the first line number (ensuring that it is located
|
|
at a fixed memory address), the length of the comment must provide enough space
|
|
for the program, then use POKE or else to fill the program code into it.
|
|
RESTRICTION: The comment may not contain the value 76h (the NEWLINE character).
|
|
Thus, the assembler program should not contain a "HALT" instruction (opcode
|
|
76h), or any other opcodes with operand 76h such like LD A,76h or JP 4276h
|
|
etc., or any data definitions such like "DB 76h".
|
|
|
|
Using a string (in the variables area)
|
|
Define a string such like A$ and fill it by binary character numbers. Note that
|
|
all variables are saved by SAVE command, it is not necessary that the program
|
|
itself contains the LET A$=... definition.
|
|
RESTRICTION: The position of the string in memory may change when (re-)defining
|
|
other variables, when modifying the BASIC program, or when altering video
|
|
memory contents.
|
|
|
|
Using memory above RAMTOP (outside of the known memory)
|
|
By default, RAMTOP (4004h) points to the address following to the detected RAM
|
|
area (4400h for 1KByte RAM). The user can alter this address by using POKE,
|
|
then type NEW to let the BIOS realize the new value, all memory above RAMTOP
|
|
may now be used for whatever purposes.
|
|
RESTRICTION: The (standard) SAVE instruction does not save this area to
|
|
cassette.
|
|
|
|
ZX80/ZX81 Cassette File Images
|
|
------------------------------
|
|
|
|
.81 and .80 Files
|
|
These are 1:1 copies of the content of real ZX81 and ZX80 cassette files.
|
|
ZX81 files are copies of the memory area 4009h up to E_LINE-1, the filename
|
|
(which is usually part of ZX81 files) is not included in the file.
|
|
ZX80 files are copies of the memory area 4000h up to E_LINE-1, the filename is
|
|
obviously not included as real ZX80 files do not have names.
|
|
|
|
.P and .O Files
|
|
Basically, these are identical as .81 (.P) and .80 (.O) files, except that an
|
|
unpredictable amount of garbage is meant to be attached to each file.
|
|
Older versions of the Xtender emulator seem to have attached 1 byte of garbage.
|
|
The current Xtender version apparently dropped this behaviour, and saves
|
|
correct length. Files at ftp.nvg randomly contain between 28-38 bytes of
|
|
garbage, probably caused by a cassette-to-disk transfer program. And some files
|
|
appear to have went through a CP/M filesystem, which caused the length to be
|
|
rounded up to multiples of 128 bytes.
|
|
Programs that deal with these files should determine the correct length (by
|
|
examining the header/system area), and truncate the extra bytes.
|
|
|
|
.P Files with Filename
|
|
Some .P files contain the original "FILENAME.P" (in ZX81 charset) at 003Fh
|
|
(within the PRBUFF area) (the purpose is probably to "preserve" long filenames
|
|
in MSDOS) (the preceeding bytes at 003Ch are usually 00-1A-1C, or in
|
|
FROGGER-HR: 00-1C-1C (unknown purpose)).
|
|
|
|
.TZX Files
|
|
This format was originally designed for the Spectrum, mainly intended to encode
|
|
nonstandard formats (copy-protections / turbo loaders). It can be also used
|
|
(via ID 19h) for ZX80/ZX81 programs. The format is quite complicated - it's
|
|
advantage is that it can contain more than one file (a feature required for
|
|
games that are split into two or more files).
|
|
--> Spectrum Cassette TZX Format
|
|
|
|
.C and .S and .V and .B or else
|
|
These are not actually real ZX files, programs that include such files won't
|
|
work on real ZX81 or ZX80, nor in no$zx. The Xtender emulator includes several
|
|
custom functions, allowing the user to create or delete directories on the
|
|
harddisk, probably as well as to format it, and to save these kind of files.
|
|
|
|
ZX80/ZX81 Cassette File Content
|
|
-------------------------------
|
|
|
|
ZX81 Data Field (excluding filename)
|
|
The data field is loaded to address 4009h, and it contains the system area
|
|
(excluding the first 9 bytes), the basic program, the video memory, and VARS
|
|
area.
|
|
The system area should contain proper data. Some entries are of special
|
|
interest:
|
|
4014h defines the end address (used to calculate the file length)
|
|
4029h points to the next executed (autostarted) BASIC line
|
|
403Bh indicates if program runs in SLOW or FAST mode (bit 6)
|
|
Memory at 403Ch and up may be misused for whatever purpose, video memory is
|
|
required to contain 25 HALT opcodes if the file was saved in SLOW mode.
|
|
|
|
ZX80 Data Field
|
|
The data field is loaded to address 4000h, and it contains the whole system
|
|
area, the basic program, and VARS area. Video memory is NOT included in ZX80
|
|
files.
|
|
The system area should contain proper data. The entry at 400Ah defines the end
|
|
address (used to calculate the file length). Memory at 4028h and up may be
|
|
misused for whatever purpose.
|
|
Normally, ZX80 files cannot be autostarted - except via "nocash LD H,L trick":
|
|
;nocash LD H,L trick for autostarting ZX80 files, 9/2009 by martin korth
|
|
4000h 8 x 00h ;System area: Zerofilled stuff
|
|
4008h 402Ch ;System area: Pointer to VARS
|
|
400Ah nn3Dh ;System area: Pointer to End of file
|
|
400Ch 1Ch x 00h ;System area: Zerofilled stuff
|
|
4028h 00h,01h,65h,76h ;BASIC program: Line 0001, LD H,L opcode, NEWLINE
|
|
402Ch 80h ;VARS area: End code
|
|
402Dh 13h x 00h ;Unused/padding (for entryoint 4040h)
|
|
4040h ... ;Machine code (entrypoint at 4040h)
|
|
xxxxh (xx3Dh-$) x 00h ;Unused/padding (for end address xx3Dh)
|
|
xx3Dh ;End of file (must be at xx3Dh)
|
|
After loading, the BASIC line is LISTed on the screen. The ZX80 BIOS doesn't
|
|
replace invalid tokens in range of 40h..7Fh by question marks, so Token 65h is
|
|
written as-is to VRAM (ie. as LD H,L opcode). The file must end at xx3Dh, so
|
|
the first character line starts at xx40h, which is (normally) excecuted 8 times
|
|
via JP HL from inside of the IRQ handler. After first execution, the LD H,L
|
|
opcode changes HL=xx40h to HL=4040h, so the next IRQ jumps to the autostart
|
|
entryoint at 4040h. That is still done with IRQs enabled, so the first opcode
|
|
at 4040h should be a DI.
|
|
Note: Emulators that do not handle opcodes in VRAM should reproduce autostart
|
|
as "IF [402Ah]=7665h THEN JP 4040h" after loading the file (that, preferably
|
|
with registers and memory initialized as on real hardware).
|
|
|
|
Maximum File Length
|
|
Files should usually not exceed 16 KBytes. The memory detection procedure in
|
|
both ZX80 and ZX81 BIOS stops after 16 KBytes (at 8000h), and initializes the
|
|
stack pointer at that address, even if more memory is installed. Thus loading
|
|
files of 16K or more would destroy the stack area (unless a separate loader has
|
|
previously moved the stack area to another location).
|
|
However, most ZXes don't have more than 16K RAM, so bigger files won't work on
|
|
most computers anyways.
|
|
|
|
ZX80/ZX81 Cassette Signals
|
|
--------------------------
|
|
|
|
ZX81 Cassette File Structure
|
|
x seconds your voice, saying "filename" (optional)
|
|
x seconds video noise
|
|
5 seconds silence (only some clock cycles required for ZX81)
|
|
1-127 bytes filename (bit7 set in last char)
|
|
LEN bytes data, loaded to address 4009h, LEN=(4014h)-4009h.
|
|
1 pulse video retrace signal (only if display was enabled)
|
|
x seconds silence / video noise
|
|
The data field contains the system area, the basic program, the video memory,
|
|
and VARS area.
|
|
|
|
ZX80 Cassette File Structure
|
|
x seconds your voice, saying "filename" (optional)
|
|
x seconds video noise
|
|
5 seconds silence (at least 0.5 seconds REQUIRED for ZX80)
|
|
LEN bytes data, loaded to address 4000h, LEN=(400Ah)-4000h.
|
|
x seconds silence / video noise
|
|
ZX80 files do not have filenames, and video memory is not included in the file.
|
|
|
|
File End
|
|
For both ZX80 and ZX81 the fileend is calculated as shown above. In either
|
|
case, the last byte of a (clean) file should be 80h (ie. the last byte of the
|
|
VARS area), not followed by any further signals except eventually video noise.
|
|
|
|
Bits and Bytes
|
|
Each byte consists of 8 bits (MSB first) without any start and stop bits,
|
|
directly followed by the next byte. A "0" bit consists of four high pulses, a
|
|
"1" bit of nine pulses, either one followed by a silence period.
|
|
0: /\/\/\/\________
|
|
1: /\/\/\/\/\/\/\/\/\________
|
|
Each pulse is split into a 150us High period, and 150us Low period. The
|
|
duration of the silence between each bit is 1300us. The baud rate is thus 400
|
|
bps (for a "0" filled area) downto 250 bps (for a "1" filled area). Average
|
|
medium transfer rate is approx. 307 bps (38 bytes/sec) for files that contain
|
|
50% of "0" and "1" bits each.
|
|
|
|
Hardware, Connectors, Upgrading
|
|
-------------------------------
|
|
|
|
Hardware Plugs'n'Pins
|
|
--> HW External Connectors
|
|
--> HW Internal Pins
|
|
|
|
Hardware Modifications
|
|
Below are some ideas of how to attack ZX hardware just by using a few
|
|
resistors, diodes and/or some wires. Ie. it's all very simple stuff, not
|
|
requiring special hardware or etched circuit boards, but nethertheless quite
|
|
useful and effective.
|
|
|
|
--> HW Replacing the ZX81 ROM by an EPROM
|
|
--> HW 56K RAM Upgrade
|
|
--> HW Connecting a Joystick
|
|
--> HW Making the ZX81 Faster
|
|
--> HW Upgrading RamPaks for True Hi-Res Graphics
|
|
--> HW Connecting a Monitor
|
|
--> HW Getting rid of the 9V DC Power Supply
|
|
--> HW Uploading Programs from the PC to the ZX81
|
|
|
|
HW External Connectors
|
|
----------------------
|
|
|
|
TV - Video Output - UHF Channel 36 (Cinch, female)
|
|
Ring: Shield
|
|
Tip: TV Signal
|
|
Note that modern TV sets (such manufactured after 1981, especially such with
|
|
automatic channel-detection) might have problems to detect/handle the signal.
|
|
If necessary, adjust the contrast/brightness, and (as far as supported) adjust
|
|
the channel manually.
|
|
|
|
EAR - Cassette Input (from recorder earphone socket to ZX81)
|
|
Ring: Ground
|
|
Tip: Cassette Input
|
|
|
|
MIC - Cassette Output (from ZX81 to recorder microphone socket)
|
|
Ring: Ground
|
|
Tip: Cassette Output
|
|
This is in fact the video signal, output through resistor and capaciator,
|
|
causing black and white stripes to be displayed during cassette output.
|
|
|
|
9V DC - Power Supply
|
|
Ring: Ground
|
|
Tip: 9V DC
|
|
Even though using the official 9V ZX power supply, the voltage is rather 11V
|
|
than 9V in my computer. Internally, the ZX81 is operated at 5V, generated from
|
|
a 7805 voltage regulator, so the input voltage could be anything in range from
|
|
7V up to I think 24V. However, a higher voltage would heat up the regulator
|
|
even more, and be aware that it is output to the expansion port, possibly
|
|
damaging attached hardware if it is too high.
|
|
|
|
Power Consumption
|
|
Internal 5V, 0.31A, ie. 1.55W, without 16K RAM
|
|
Internal 5V, 0.39A, ie. 1.95W, with Memotech Mempak 16KB
|
|
|
|
Expansion Port (46 Pin Cartridge Slot, male)
|
|
Only 44 pins are actually used, the two ---SLOT--- marked pins are cut-out,
|
|
used as polarisation mark. When attaching a 46pin female plug, note that you
|
|
must cut off the plastic at the left and right ends, preferably before doing
|
|
any soldering work.
|
|
Upper Side Lower Side
|
|
1A D7 1B 5V DC
|
|
2A /RAM CS 2B 9V DC
|
|
3A ---SLOT--- 3B ---SLOT---
|
|
4A D0 4B 0V
|
|
5A D1 5B 0V
|
|
6A D2 6B CLK
|
|
7A D6 7B A0
|
|
8A D5 8B A1
|
|
9A D3 9B A2
|
|
10A D4 10B A3
|
|
11A /INT 11B A15
|
|
12A /NMI 12B A14
|
|
13A /HALT 13B A13
|
|
14A /MREQ 14B A12
|
|
15A /IORQ 15B A11
|
|
16A /RD 16B A10
|
|
17A /WR 17B A9
|
|
18A /BUSAK 18B A8
|
|
19A /WAIT 19B A7
|
|
20A /BUSRQ 20B A6
|
|
21A /RESET 21B A5
|
|
22A /M1 22B A4
|
|
23A /REFSH 23B /ROM CS
|
|
Expansion cartridges should have a male connector at the rear side - allowing
|
|
to connect further cartridge(s) - one to each other.
|
|
|
|
HW Internal Pins
|
|
----------------
|
|
|
|
ZX81 Keyboard Connector
|
|
Pin 1-8: A15, A14, A8, A13, A9, A12, A10, A11.
|
|
Pin 9-13: KBD0, KBD1, KBD2, KBD3, KBD4.
|
|
|
|
Video Signal
|
|
The video output consists of a /SYNC signal (low during horizontal and vertical
|
|
retrace), and the actual VIDEO signal (low=black, high=white). In the ZX81 both
|
|
signals are internally mixed into a single signal, and then output as shown
|
|
below at Pin 16 of the Ferranti chip.
|
|
Reportedly these voltages are output on Pin 16 (no idea if/when that happens in
|
|
reality, maybe on US versions with VHF-modulator):
|
|
0V sync
|
|
2.5V black
|
|
5V white
|
|
On my own ZX81 with UHF modulator (ie. without the VHF pulldown resistors):
|
|
2.5V sync
|
|
3.7V black
|
|
5.0V white
|
|
When connecting Pin16 directly to the AV-input of my television set:
|
|
0.0V sync
|
|
0.5V black
|
|
1.0V white
|
|
|
|
50Hz/60Hz Refresh Rate Jumper
|
|
Even though the display refresh rate is actually software based, the BIOS
|
|
determines the local desired rate by reading from I/O port FEh. In the ZX81,
|
|
the setting depends on whether Pin 22 of the Ferranti chip is shortcut to
|
|
ground or not.
|
|
When it is grounded, by a 0 Ohm "resistor" called R 30, then vertical blanking
|
|
time is reduced for 60Hz timing - note that this heavily reduces the
|
|
user-available CPU time in SLOW mode.
|
|
|
|
ZX81 Ferranti ULA
|
|
1 A7'
|
|
2 A8'
|
|
3 A2'
|
|
4 A1'
|
|
5 A0'
|
|
6 /RD
|
|
7 /IORQ
|
|
8 /WR
|
|
9 /MREQ
|
|
10 M1
|
|
11 A14
|
|
12 /RAMCS
|
|
13 /ROMCS
|
|
14 OSC (EXPANSION)
|
|
15 /NMI
|
|
16 TV/TAPE
|
|
17 /HALT
|
|
18 A15
|
|
19 D7
|
|
20 TAPE.IN
|
|
21 D6
|
|
22 /NTSC
|
|
23 D5
|
|
24 D4
|
|
25 KDB4
|
|
26 D3
|
|
27 KDB3
|
|
28 D2
|
|
29 KDB2
|
|
30 D1
|
|
31 KDB1
|
|
32 D0
|
|
33 KBD0
|
|
34 GND
|
|
35 OSC (CERAM)
|
|
36 A3'
|
|
37 A4'
|
|
38 A5'
|
|
39 A6'
|
|
40 +5V
|
|
|
|
HW Replacing the ZX81 ROM by an EPROM
|
|
-------------------------------------
|
|
|
|
Even though the ZX81 includes a 24 pin 8K ROM, it should be usually delivered
|
|
with a 28 pin socket - matching for an 28 pin 8K EPROM. However, a few pins
|
|
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. Pin 14 is lower left.)
|
|
Caution:
|
|
Best use a 2764 EPROM, CMOS chips (27C64) don't seem to work very well -
|
|
probably they are too fast and/or outputs aren't amplified enough.
|
|
|
|
HW 56K RAM Upgrade
|
|
------------------
|
|
|
|
Upgrading to 56K RAM by krbaker
|
|
ROM is enabled at 0000h-1FFFh (8K), RAM at 2000h-FFFFh. /MREQ is for normal
|
|
memory access, /RFSH is for character pattern & hires bitmap memory fetches.
|
|
/M1 mirrors 0000h-7FFFh to 8000h-FFFFh on opcode fetches (aka BG map), in
|
|
result, memory at 8000h-FFFFh can be used for data storage only, machine code
|
|
cannot be executed in that area.
|
|
____ __________________________________
|
|
/M1 ----|AND \__|__ ____ ____ RAM A15
|
|
A15 ----|____/ |OR \______|INV \_____ ____
|
|
A14 ----|OR \_____|____/ | |____/ ___|OR \___ /RAMCS
|
|
A13 ----|____/ | | |____/
|
|
/MREQ --|AND \_____________ | ________|___|OR \___ /ROMCS
|
|
/RFSH --|____/ |_____________|____/
|
|
|
|
Parts List: 7404 hex inverter, 7408 quad 2-input AND gate, 7432 quad 2-input OR
|
|
gate, and 128Kx8bit static RAM. Notes: Remove the resistors in the /ROMCS and
|
|
/RAMCS lines on the board, connect RAM A16 to VCC or GND. Circuit tested &
|
|
working with either 74LSxx or 74HCxx chips.
|
|
|
|
Caution: Mapping RAM to address 2000h works only with ZX80 and ZX81/TS1000
|
|
BIOSes (the TS1500 BIOS checks for [2000h]=01h, and if so, treats it as
|
|
expansion ROM).
|
|
|
|
Compatibility Problem: Memopak expansions do allow d_file at 4000h-BFFFh (eg.
|
|
30K BASIC programs, followed by d_file at Bxxxh), but, above circuit supports
|
|
only 4000h-7FFFh. To fix this, RAM A15 should be also HIGH whenever A15=1 AND
|
|
A14=0.
|
|
|
|
HW Connecting a Joystick
|
|
------------------------
|
|
|
|
As far as I know, there isn't any (in-)official standard for sticks, nor do any
|
|
games support a standard keyboard/joystick control scheme. Anyways, a digital
|
|
four direction/one button joystick could be easily connected to one of the
|
|
keyboard rows.
|
|
|
|
I'd personally vote for row 4, Bits 0-4 used as Fire, Left, Right, Up, Down,
|
|
and the A12-diode as /Select. Using this method, the Keys for Right, Up, Down,
|
|
comply with ZX cursor controls (Shift+8,7,6). As used for my 'Starfight' game.
|
|
|
|
Caution: When having a PC data transfer cable connected to the keyboard lines
|
|
as well, the joystick cable may disturb the data transfer. If so, insert diodes
|
|
(1N4148 or else) into each of the four direction lines, ring pointing to the
|
|
joystick side (nocash upload data lines), and if necessary for fire button also
|
|
(nocash upload clock line).
|
|
|
|
HW Making the ZX81 Faster
|
|
-------------------------
|
|
|
|
Wilf Rigter's WAITMOD (7/2005) speedup 9%
|
|
The ZX81 generates a 14-cycle WAIT along with every NMI. However, the WAIT is
|
|
actually required only after the HALT opcode at 0079h (ie. on the final NMI at
|
|
the end of the upper/lower blanking period). Rewiring the R1 resistor, and
|
|
adding another 10K resistor and a PNP transistor (eg. BC557) causes the WAIT to
|
|
be generated only after HALT opcodes, and thus saves 14-cycles on all other
|
|
NMIs.
|
|
Before:
|
|
------- R1 ---------------- /HALT CPU.18
|
|
After:
|
|
----+-- R1 ------+--/cut/-- /HALT CPU.18
|
|
| ___ |
|
|
+-----|C | +--------- GND
|
|
| B|_____________
|
|
VCC--10K--|E__| /WAIT CPU.24
|
|
All basic/machine code software with video output enabled will run 9% faster,
|
|
there should be no compatibility problems, except, eventually with a few
|
|
unstable (bugged) programs.
|
|
|
|
Nocash NMI Patch (5/2010) speedup 2%
|
|
Removing the useless 10-cycle "JP @@blah" causes the 7-cycle "JR @@zero" to be
|
|
executed instead, thus saving 3-cycles per NMI. After the HALT, a final NMI is
|
|
executed, and in this case, the 10-cycle "JP @@blah" is required as delay, this
|
|
is solved by moving the JP @@blah after the HALT opcode.
|
|
<---- Original NMI Handler ----> <----- Tuned NMI Handler ----->
|
|
0066 08 ex af,af 0066 08 ex af,af
|
|
0067 3C inc a 0067 3C inc a
|
|
0068 FA 6D 00 jp m,@@blah 0068 28 02 jr z,@@zero
|
|
006B 28 02 jr z,@@zero 006A 08 ex af,af
|
|
@@blah: 006B C9 ret
|
|
006D 08 ex af,af @@zero:
|
|
006E C9 ret 006C 08 ex af,af
|
|
@@zero: 006D F5 push af
|
|
006F 08 ex af,af 006E C5 push bc
|
|
0070 F5 push af 006F D5 push de
|
|
0071 C5 push bc 0070 E5 push hl
|
|
0072 D5 push de 0071 2A 0C 40 ld hl,[400Ch]
|
|
0073 E5 push hl 0074 CB FC set 7,h
|
|
0074 2A 0C 40 ld hl,[400Ch] 0076 76 halt
|
|
0077 CB FC set 7,h 0077 C3 7A 00 jp @@blah
|
|
0079 76 halt @@blah:
|
|
007A D3 FD out [0FDh],a 007A D3 FD out [0FDh],a
|
|
007C DD E9 jp ix 007C DD E9 jp ix
|
|
All basic/machine code software with video output enabled will run 2% faster,
|
|
there should be no compatibility problems, with a few exceptions: buggy
|
|
programs (with unstable timings), programs that jump to addresses 0068..0079,
|
|
and, pseudo-hires programs that use I=0 (only Madjump II does do that).
|
|
|
|
Nocash Increased Blanking Time - speedup around 50% possible
|
|
Finally, the CPU speed can be (greatly) improved by increasing the number of
|
|
blank lines. There are three ways to do this:
|
|
1) Decrease Vertical Picture Size, increase upper/lower blanking accordingly
|
|
2) Decrease Vertical Retrace Time, increase upper blanking accordingly
|
|
3) Decrease Frame Rate by increasing upper/lower blanking
|
|
Method 1) is perfectly legal and can be about 250% faster - but works only with
|
|
small pictures. Methods 2) and 3) can be around 50% faster, but might cause
|
|
problems with some TV sets, so, using them should be made optional. If desired,
|
|
Method 3) can be also implemented at BIOS level (increase the byte at 02E2h) -
|
|
that patch will speedup all BASIC programs & most machine code programs.
|
|
|
|
HW Upgrading RamPaks for True Hi-Res Graphics
|
|
---------------------------------------------
|
|
|
|
When using "True Hi-Res" software, pixel data is read from RAM rather than ROM
|
|
area. Pixel data is requested by a /RFSH (refresh) signal, rather than by a
|
|
normal /RD (read) signal. So, RAM is required to output data whenever when /RD
|
|
or /RFSH are low.
|
|
|
|
Internal RAM does support the above combination, but external RAM usually
|
|
generates its own read signal - which senses /RD only. Below example for fixing
|
|
this problem is taken from Wilf Ritgers ZX81VID.TXT document:
|
|
|
|
ZX81.+5V --------------------+-----+---- RAMPACK.+5V
|
|
| |
|
|
ZX81./RFSH ----|<|---+--[4K7]--+ +---- RAMPACK./RFSH ;ALWAYS HIGH
|
|
|
|
|
ZX81./RD ----|<|---+-------------------- RAMPACK./RD ;/RD AND /RFSH
|
|
|
|
The RAMPACK is modified to enable the data output at RFSH time by cutting the
|
|
RD and RFSH lines at the edge connector and installing 2 only 1N34A Germanium
|
|
diodes and a 4.7K pullup resistor.
|
|
|
|
Note: ZX hardware often uses a couple of small RAM chips (instead of a single
|
|
28 pin SRAM chip), anyways these are SRAM chips either (so cutting the RFSH
|
|
signal shouldn't cause problems). Ie. you can be quite sure that no DRAM is
|
|
used because the refresh register is used as interrupt counter.
|
|
|
|
HW Connecting a Monitor
|
|
-----------------------
|
|
|
|
Internally the ZX81 is producing a more or less crystal clear video signal,
|
|
which is normally converted into a TV signal by the UHF modulator in the
|
|
computer, and then re-decoded by the de-modulator in the TV Set, most likey
|
|
resulting in a more than bad display quality.
|
|
|
|
Anyways, the 'raw' video signal can be found at pin 16 of the ZX81 Ferranti
|
|
chip, that is: 0V=Sync, 2.5V=black, 5V=white, which might or might not work
|
|
with various types of computer displays. Some displays might not understand the
|
|
refresh rates, and others might require other voltages - which might be
|
|
adjusted by one or more resistors.
|
|
|
|
I've currently only tried to connect a GT65 Green Monitor (for
|
|
Amstrad/Schneider CPC homecomputers): Connect Ground as such, and connect the
|
|
Video signal to both /Sync, and (preferably through a 1kOHm resistor) to
|
|
Luminance. The voltage is apparently much too high (not actually blowing the
|
|
display, but the picture appears very bright), the resistor is more or less
|
|
healing this.
|
|
|
|
HW Getting rid of the 9V DC Power Supply
|
|
----------------------------------------
|
|
|
|
When connecting the ZX81 to the PC, the external ZX 9V power supply becomes
|
|
more or less useless, and it might be recommended to use the PC supply instead.
|
|
Two possible methods are:
|
|
|
|
Using 12V DC (Yellow cable in PCs)
|
|
The official ZX so-called-9V-supply actually outputs about 11V, thus the
|
|
slightly higher voltage wouldn't cause much more overheat, but keep in mind
|
|
that the voltage is forwarded to any connected hardware expansions, if
|
|
necessary lower the voltage to approx. 11V by inserting a 1N4004 diode into the
|
|
12V line.
|
|
|
|
Using 5V DC (Red cable in PCs)
|
|
The ZX81 is internally operated at 5V only, the additional volts are just blown
|
|
into heat by the 7805 voltage regulator. So, connecting 5V directly to the 7805
|
|
output does work (and prevents the keyboard from heating up). However, the "9V"
|
|
voltage is output to the expansion port, and some hardware expansions
|
|
(including 16K Memotech RAM Paks) actually require this voltage.
|
|
|
|
A separate ground signal isn't forcefully required if the ZX is connected to
|
|
the PCs parallel port, as the existing ground/shield connection could be badly
|
|
mis-used as ground.
|
|
|
|
HW Uploading Programs from the PC to the ZX81
|
|
---------------------------------------------
|
|
|
|
The Transmit function in no$zx Utility menu supports three different transfer
|
|
methods, each using the PCs parallel port to output data to the ZX (only into
|
|
that direction, not vice versa):
|
|
|
|
1) Nocash Highspeed (transmission time 100-1300ms)
|
|
This is a very simple six-diodes-network. The transmission rate is approx.
|
|
12500 bytes/sec (about 300 times faster than 38 bytes/sec cassette loading).
|
|
The ZX is automatically reset and immediately switched into read-mode, even a
|
|
huge 16K file is transferred in less than 1.5 seconds - ways faster than the
|
|
unpatched ZX81/16K CLS boot procedure.
|
|
However, this method requires a patched BIOS ROM, and it's thus restricted to
|
|
more or less serious users only. Data is transferred in units of 4 Bits,
|
|
synchronized by a separate clock signal, thus making the timing rather
|
|
uncritical, even when using a multitasking operating system.
|
|
|
|
2) Mixed (transmission time 3-4 seconds)
|
|
This method combines the above/below protocols, but works well without patched
|
|
BIOS ROM. Before transmission, you'll have to type LOAD "" manually on remote
|
|
side, a small loader will be then transferred by using the slow transfer method
|
|
(approx 3 seconds), followed by the actual file using highspeed transfer
|
|
(approx 0-1 second).
|
|
|
|
3) ZXTAPE (transmission time up to 7 minutes)
|
|
This protocol is transferring data at original cassette speed (38 bytes per
|
|
second), similar to Wilf Ritger's ZXTAPE program. A possible advantage is that
|
|
you won't need to open the ZX81, and won't need to install any diodes, just
|
|
connect parallel port pin 2 and ground to the ZX EAR socket, and ignore further
|
|
instructions below.
|
|
Note that this method won't work very well with multi-tasking operating
|
|
systems.
|
|
|
|
You need:
|
|
1 PC with Parallel Port, and a normal Centronics Printer Cable
|
|
1 Centronics plug (36 pins, female)
|
|
1 EPROM (2764 non-CMOS) and EPROM burner (optional)
|
|
6 Diodes (for example 1N4148, ie. the most cheapest standard ones)
|
|
and some short isolated wires
|
|
|
|
Schematic
|
|
ZX Mainboard Side Centronics Side
|
|
Cassette Input (EAR) ------------- Centr.Pin2 (D0)
|
|
Keyb Col0/Pin9 (CLK) -----|>|----- Centr.Pin3 (D1)
|
|
Keyb Col1/Pin10 (D0) -----|>|----- Centr.Pin4 (D2)
|
|
Keyb Col2/Pin11 (D1) -----|>|----- Centr.Pin5 (D3)
|
|
Keyb Col3/Pin12 (D2) -----|>|----- Centr.Pin6 (D4)
|
|
Keyb Col4/Pin13 (D3) -----|>|----- Centr.Pin7 (D5)
|
|
Expansion 21A (RESET) -----|>|----- Centr.Pin8 (D6)
|
|
ROM Pin26 (A13) ------------- Centr.Pin9 (D7) (LO=ZX80, HI=ZX81)
|
|
VCC ----[10K]---- Centr.Pin9 (D7)
|
|
Expansion 4B/5B (GND) ------------- Centr.Pin24 (GND)
|
|
_______
|
|
CPU.Pin36 (A6) --|D1 Q1|-- Centr.Pin10 (ACK)
|
|
CPU.Pin20 (/IORQ) --|CK1 |
|
|
CPU.Pin26 (/RESET) --|SET1 | 74LS74 FlipFlop
|
|
VCC ---------------------|RES1 |
|
|
|_______|
|
|
|
|
Step 1 - The Diodes
|
|
Connect the diodes to Pin 3-8 of the Centronics plug. The end with the black
|
|
ring (or other color) must point to the plug, the other end will be connected
|
|
to the ZX81 mainboard. The diodes are required because otherwise the strong PC
|
|
LPT port pulls up the ZX81 address signals when pressing a key. (Even though
|
|
bi-directional LPT ports might be able to avoid that.)
|
|
|
|
Step 2 - Connecting the Data Lines.
|
|
When looking on top of the ZX81 board, you will see the keyboard connector in
|
|
lower right. Counted from the right end, pin 1-8 are A8-A15 signals (in no
|
|
specific order) - ignore these. Pin 9-13 are Keyboard Columns 0-4 (in exactly
|
|
that order) - connect these to the diodes at Pin 3-7 of the Centronics plug.
|
|
|
|
Step 3 - Connecting Ground, Reset and Cassette.
|
|
Connect Ground (found at Pin 4B and 5B of the expansion port) to Pin 24 or else
|
|
of the Centronics plug. Connect Reset (Pin 21A of expansion port) to the diode
|
|
at Pin 8 of Centronics plug (the reset signal isn't actually required, but it's
|
|
quite comfortable if the transmission program can reset the ZX81). Finally,
|
|
connect the Cassette Input (EAR) to Pin 2 of the Centronics plug (this is
|
|
required only if you are not using patched BIOS).
|
|
|
|
Step 4 - Connecting the ACK Flipflop (NEW, added 2010)
|
|
Connect the 74LS74 flipflop as shown above. This is allowing to send feedback
|
|
info and EPROM version string to the PC. It's making the circuit a little bit
|
|
more complicated than necessary, but it's rather useful to solve connection
|
|
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 Models
|
|
--> Spectrum I/O Map
|
|
--> Spectrum Memory Maps
|
|
--> Spectrum System Variables
|
|
--> Spectrum ULA
|
|
--> Spectrum VRAM
|
|
--> Spectrum Video Connectors
|
|
--> Spectrum Timings
|
|
--> Spectrum Sound
|
|
--> Spectrum Disc and Tape Drives
|
|
--> Spectrum Interrupts
|
|
--> Spectrum Keyboards
|
|
--> Spectrum Joystick Ports
|
|
--> Spectrum Mouse Ports
|
|
--> Spectrum Light Guns
|
|
--> Spectrum Printer Ports
|
|
--> Spectrum Serial Port
|
|
--> Spectrum Expansion Ports
|
|
--> Spectrum ROM Cartridges
|
|
--> Spectrum Chipset Pinouts
|
|
--> Spectrum 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 Spectrum 128 - 128K-RAM,PSG,MIDI,RS232,RGB,32K-ROM
|
|
1986 Amstrad +2 (typewriter keyboard, built-in cas drive, two joy ports)
|
|
1987 Amstrad +2A (manufactured in Taiwan) (+3 style mainboard, Centronics)
|
|
1987 Amstrad +2B (same as +2A but manufactured in China instead of Taiwan)
|
|
1987 Amstrad +3 (more ROM, RAM map-able at 0000h for CP/M, built-in disk)
|
|
|
|
Timex (licensed Spectrum clones)
|
|
1983 TS2068 special video modes, timex bios, PSG, 48K RAM, NTSC (USA)
|
|
1984 TC2068 special video modes, timex bios, PSG, 48K RAM, PAL (Portugal)
|
|
1984 TC2048 special video modes, spectrum bios, no PSG, 16K RAM, PAL (Portu.)
|
|
|
|
Unlicensed Spectrum Clones
|
|
There are about 50 unlicensed spectrum clones: Mass-produced clones (like
|
|
russian pentagon and scorpion), as well as homebrew modifications.
|
|
|
|
Spectrum I/O Map
|
|
----------------
|
|
|
|
The original spectrum did use only one I/O address (the ULA at port FEh). And
|
|
only one pre-assigned expansion I/O address (the ZX printer at port FDh).
|
|
Although that original design was very simple, the lack of further pre-assigned
|
|
addresses resulted in a mess. For example, there are at least 5 different
|
|
"standards" for connecting joysticks, 3 for PSG sound chips (probably more),
|
|
many dozens of floppy and centronics standards, etc.
|
|
|
|
Spectrum I/O Ports (accessed via IN/OUT opcodes)
|
|
Port Binary Address Dir Description
|
|
xxFF ................ R Spectrum Current VRAM Data (dirt effect)
|
|
xxFE nnnnnnnn.......0 R Spectrum ULA (Keyboard, and CAS Input)
|
|
xxFE ...............0 W Spectrum ULA (Border Color, Speaker/CAS Output)
|
|
F7FE ....0..........0 R Spectrum +2/+2A/+3 Joystick 2
|
|
EFFE ...0...........0 R Spectrum +2/+2A/+3 Joystick 1
|
|
F7FE ...10..........0 R Interface 2 Joystick 2
|
|
EFFE ...01..........0 R Interface 2 Joystick 1
|
|
FFFD 11............0. W Spectrum 128K/+2/+2A/+3 PSG index register
|
|
FFFD 11............0. R Spectrum 128K/+2/+2A/+3 PSG data read (and RS232)
|
|
BFFD 10............0. W Spectrum 128K/+2/+2A/+3 PSG data write (and RS232)
|
|
7FFD 0.............0. W Spectrum 128K/+2 Memory Control
|
|
BFFD 10............0. R Spectrum +2A/+3 Mirror of Port FFFDh (+2A/+3 only)
|
|
7FFD 01............0. W Spectrum +2A/+3 Memory Control A
|
|
1FFD 0001..........0. W Spectrum +2A/+3 Memory Control B and Disk Motor
|
|
0FFD 0000..........0. Spectrum +2A/+3 Centronics
|
|
3FFD 0011..........0. R/W Spectrum +3 Floppy FDC NEC uPD765 data
|
|
2FFD 0010..........0. R Spectrum +3 Floppy FDC NEC uPD765 status
|
|
xxFB .............0.. R/W ZX Printer
|
|
xxF7 ...........10... R/W Interface 1 RS232/Network Data (1bit send/receive)
|
|
xxEF ...........01... R/W Interface 1 Microdrive/RS232/Network Control
|
|
xxE7 ...........00... R/W Interface 1 Microdrive Data (8bit send/receive)
|
|
xx1F ........000..... R Kempston joystick
|
|
|
|
Timex I/O Ports
|
|
xxFF ........11111111 Timex Display Mode
|
|
xxFE nnnnnnnn11111110 R Timex ULA (Keyboard, and CAS Input)
|
|
xxFE ........11111110 W Timex ULA (Border Color, Speaker/CAS Output)
|
|
xxF4 ........11110100 Timex Memory Mapping
|
|
xxF6 ........11110110 R/W Timex TS2068/TC2068 PSG data R/W (sound registers)
|
|
x1F6 .......111110110 R/W Timex TS2068/TC2068 PSG data R/W (and joystick 1)
|
|
x2F6 ......1.11110110 R/W Timex TS2068/TC2068 PSG data R/W (and joystick 2)
|
|
xxF5 ........11110101 W Timex TS2068/TC2068 PSG index
|
|
xxFB ........11111011 R/W Timex Printer (TS2040 or Alphacom 32)
|
|
xx1F ..........0..... R Timex TC2048 joystick (kempston-style, A5-only)
|
|
xxEF ........???0???? R/W Timex FDD Interface (for FDD or FDD-3000 drive)
|
|
|
|
Expansion I/O Stuff (Audio related)
|
|
0007 W Cheetah Sweet Talker - Speech Output (halts CPU)
|
|
007F 0 W DK'Tronics Speech Synthesiser - Speech Output
|
|
007F 0 R DK'Tronics Speech Synthesiser - Speech Status
|
|
xx7F ........011 R Fuller Box - Joystick port
|
|
xx3F ........00 W Fuller Box - PSG index (also DK'Tronics PSG)
|
|
xx3F ........00 R Fuller Box - PSG data read (maybe also DK'Tronics?)
|
|
xx5F ........010 W Fuller Box - PSG data write (also DK'Tronics PSG)
|
|
xx9F ........ 00 W Fuller Orator / Box Master Unit - Speech Output
|
|
xxBF ........ 01 R Fuller Orator / Box Master Unit - Speech Status
|
|
xx9F ........ 00 W William Stuart Systems Music Synthesiser PSG index
|
|
xxDF ........ 10 W William Stuart Systems Music Synthesiser PSG data
|
|
xxFF ........1..11111 W Bi-Pak ZON X Soundbox PSG index
|
|
xx7F ........0..11111 W Bi-Pak ZON X Soundbox PSG data write
|
|
0038 0000000000111000 R Currah uSpeech enable/disable BIOS (mirror)
|
|
|
|
Expansion I/O Stuff (Storage, Centronics, etc.)
|
|
xx7F ........01111111 Aerco Centronics Interface
|
|
xx8F ........10001111 JLO status/command
|
|
xx9F ........10011111 JLO track
|
|
xxAF ........10101111 JLO sector
|
|
xxBF ........10111111 JLO data
|
|
xxB7 ........10110111 JLO select
|
|
xxFB ........1....0.. ZX LPrint III Enable ROM, and Write=Data, Read=Busy
|
|
xx7B ........0....0.. ZX LPrint III Disable ROM
|
|
E3BF 0 W Kempston Centronics Ctrl (b0=0=Strobe)(0Eh,0Fh,81h)
|
|
E2BF 0 R Kempston Centronics Status (b0=1=Busy)
|
|
E0BF 0 W Kempston Centronics Data Output
|
|
xxBB ........ R DK'Tronics Centronics Status (b7=1=Busy)
|
|
xxBB ........ W DK'Tronics Centronics Ctrl (b1=0=Strobe) (02h,00h)
|
|
xx9B ........ W DK'Tronics Centronics Data
|
|
xxDB ........ W DK'Tronics Centronics Config 1 (set to 3Fh)
|
|
xxFB ........ W DK'Tronics Centronics Config 2 (set to FFh,80h)
|
|
dd0E dddddddd R Wafadrive Centronics Data Out ;via "IN A,(dd0Eh)"
|
|
x00A s R Wafadrive Centronics Strobe Out;via "IN A,(s00Ah)"
|
|
0002 R Wafadrive Centronics Busy In ;returned in bit5
|
|
xxFB ........ W Indescomp Centronics Data
|
|
xxFB ........ R Indescomp Status (b0=Busy,b1=Rs232Busy,b2=RxD)
|
|
xx7F ........ W Indescomp Control (b0=Strobe,b1=TxD,b2=CTS)
|
|
xx1B ........ 0 W Disciple FDC Command
|
|
xx1B ........ 0 R Disciple FDC Status
|
|
xx5B ........ 0 R/W Disciple FDC Track
|
|
xx9B ........ 0 R/W Disciple FDC Sector
|
|
xxDB ........ 0 R/W Disciple FDC Data
|
|
xx1F ........ W Disciple Control Register
|
|
xx1F ........ R Disciple Joystick/Printer/Network
|
|
xx3B ........ 0 ? Disciple Network Wait
|
|
F7FE 0 0 R Disciple Disciple Joystick
|
|
EFFE 0 0 R Disciple Disciple Joystick
|
|
xxBB ........ 0 R Disciple Enable Internal ROM/RAM
|
|
xxBB ........ 0 W Disciple Disable Internal ROM/RAM
|
|
xxFB ........ 0 W Disciple Centronics Data
|
|
xx7B ........ 0 R Disciple Map ROM=0000h, RAM=2000h
|
|
xx7B ........ 0 W Disciple Map ROM=2000h, RAM=0000h
|
|
xxE3 ........ 000 W PlusD FDC Command
|
|
xxE3 ........ 000 R PlusD FDC Status
|
|
xxE7 ........ 001 R PlusD Enable Internal ROM/RAM
|
|
xxE7 ........ 001 W PlusD Disable Internal ROM/RAM
|
|
xxEB ........ 010 R/W PlusD FDC Track
|
|
xxEF ........ 011 W PlusD Control Register
|
|
xxF3 ........ 100 R/W PlusD FDC Sector
|
|
xxF7 ........ 101 W PlusD Centronics Data
|
|
xxF7 ........ 101 R PlusD Centronics Busy
|
|
xxFB ........ 110 R/W PlusD FDC Data
|
|
xx1F ........ W Beta Disk FDC Command
|
|
xx1F ........ R Beta Disk FDC Status
|
|
xx3F ........ R/W Beta Disk FDC Track
|
|
xx5F ........ R/W Beta Disk FDC Sector
|
|
xx7F ........ R/W Beta Disk FDC Data
|
|
xxFF ........ R Beta Disk Status
|
|
xxFF ........ W? Beta Disk Control
|
|
And many more. See Floppy Disc and Centronics chapters for details on some
|
|
various further expansion ports.
|
|
|
|
Other
|
|
xx9F ........ Multiface I In
|
|
xx1F ........ Multiface I Out
|
|
xxBF ........ Multiface 128 In
|
|
xx9F ........ Multiface 128 In v2 (Disciple) (uh/what?)
|
|
xx3F ........ Multiface 128 Out
|
|
xx3F ........ Multiface III Button
|
|
xx3F ........ Multiface III In
|
|
xxBF ........ Multiface III Out
|
|
7F3F Multiface III P7FFD (uh?)
|
|
1F3F Multiface III P1FFD (uh?)
|
|
FF3F British Micro Grafpad Pen up/down
|
|
FFBF British Micro Grafpad Pen position X coordinate
|
|
FF7F British Micro Grafpad Pen position Y coordinate
|
|
FADF ......?0..0....? Kempston Mouse Buttons (b0=Right,b1=Left,b2=Mid)
|
|
FBDF .....0?1..0....? Kempston Mouse X
|
|
FFDF .....1?1..0....? Kempston Mouse Y
|
|
xx1F ........000..... R/W AMX Mouse Z80PIO Data A: X, CentronicsLSBs/Strobe
|
|
xx3F ........001..... R/W AMX Mouse Z80PIO Data B: Y, CentronicsMSBs/Busy
|
|
xx5F ........010..... AMX Mouse Z80PIO Ctrl A: X, CentronicsLSBs/Strobe
|
|
xx7F ........011..... AMX Mouse Z80PIO Ctrl B: Y, CentronicsMSBs/Busy
|
|
xxDF ........110..... R AMX Mouse 74LSXX Logic: Mouse Buttons (R)
|
|
xxDF ........ 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) (with waitstates)
|
|
8000h-FFFFh N/A
|
|
|
|
Spectrum 48K/Spectrum + Memory Map
|
|
0000h-3FFFh ROM (BASIC)
|
|
4000h-7FFFh RAM (Work RAM and VRAM) (with waitstates)
|
|
8000h-FFFFh Additional RAM
|
|
|
|
Spectrum 128K/+2 Memory Map
|
|
0000h-3FFFh ROM0 (EDITOR) or ROM1 (BASIC) (see Port 7FFDh.Bit4)
|
|
4000h-7FFFh RAM Page 5 (VRAM) (with waitstates)
|
|
8000h-BFFFh RAM Page 2 (Work RAM)
|
|
C000h-FFFFh RAM Page 0..7 (see Port 7FFDh.Bit0-2) (Page1,3,5,7=waitstates)
|
|
|
|
Spectrum +2A/+3 Memory Map (in normal mode)
|
|
0000h-3FFFh ROM0..ROM3 (see Port 7FFDh.Bit4 and 1FFDh.Bit2)
|
|
4000h-7FFFh RAM Page 5 (VRAM) (with waitstates)
|
|
8000h-BFFFh RAM Page 2 (Work RAM)
|
|
C000h-FFFFh RAM Page 0..7 (see Port 7FFDh.Bit0-2) (Page 4-7 with waitstates)
|
|
|
|
Spectrum +2A/+3 Memory Map (in special mode) (with RAM at 0000h for CP/M)
|
|
0000h-3FFFh RAM Page 0, 4, 4, or 4 (see Port 1FFDh.Bit0-2)
|
|
4000h-7FFFh RAM Page 1, 5, 5, or 7 (see Port 1FFDh.Bit0-2)
|
|
8000h-BFFFh RAM Page 2, 6, 6, or 6 (see Port 1FFDh.Bit0-2)
|
|
C000h-FFFFh RAM Page 3, 7, 3, or 3 (see Port 1FFDh.Bit0-2)
|
|
|
|
Timex TC2048 Memory Map (see Port F4h, and Port FFh)
|
|
Address HOME EX-ROM DOCK
|
|
0000h-1FFFh BIOS Expansion Bank 0 N/A
|
|
2000h-3FFFh BIOS Expansion Bank 1 N/A
|
|
4000h-5FFFh VRAM (Screen 0) Expansion Bank 2 N/A
|
|
6000h-7FFFh VRAM (Screen 1) Expansion Bank 3 N/A
|
|
8000h-9FFFh N/A Expansion Bank 4 N/A
|
|
A000h-BFFFh N/A Expansion Bank 5 N/A
|
|
C000h-DFFFh N/A Expansion Bank 6 N/A
|
|
E000h-FFFFh N/A Expansion Bank 7 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
|
|
function (if one is being evaluated), otherwise 0.
|
|
5C0Dh l K_DATA Stores 2nd byte of colour controls entered from keyboard.
|
|
5C0Eh 2 TVDATA Stores bytes of colour, AT and TAB controls going to TV.
|
|
5C10h 38 STRMS Addresses of channels attached to streams.
|
|
(16bit pointers for Stream FDh..FFh, and 00..0Fh)
|
|
5C36h 2 CHARS 256 less than address of character set
|
|
(which starts with space and carries
|
|
on to (C)). Normally in ROM, but you
|
|
can set up your down in RAM and make
|
|
CHARS point to it.
|
|
5C38h 1 RASP Length of warning buzz.
|
|
5C39h 1 PIP Length of keyboard click.
|
|
5C3Ah 1 ERRNR 1 less than the report code. Starts
|
|
off at 255 (for -1) so 'PEEK 23610' gives 255.
|
|
5C3Bh 1 FLAGS Various flags to control the BASIC system.
|
|
5C3Ch 1 TVFLAG Flags associated with the TV.
|
|
5C3Dh 2 ERRSP Address of item on machine stack to be used as error return
|
|
5C3Fh 2 LISTSP Address of return address from automatic listing.
|
|
5C41h 1 MODE Specifies 'K', 'L', 'C', 'E' or 'G' cursor.
|
|
5C42h 2 NEWPPC Line to be jumped to.
|
|
5C44h 1 NSPPC Statement number in line to be jumped to. Poking first
|
|
NEWPPC and then NSPPC forces a jump to a specified
|
|
statement in a line.
|
|
5C45h 2 PPC Line number of statement currently being executed.
|
|
5C47h 1 SUBPPC Number within line of statement currently being executed.
|
|
5C48h 1 BORDCR Border colour multiplied by 8; also
|
|
contains the attributes normally used
|
|
for the lower half of the screen.
|
|
5C49h 2 E_PPC Number of current line (with program cursor).
|
|
5C4Bh 2 VARS Address of variables. (End of BASIC Program)
|
|
5C4Dh 2 DEST Address of variable in assignment.
|
|
5C4Fh 2 CHANS Address of channel data (usually 5CB6h)
|
|
5C51h 2 CURCHL Address of current I/O channel (CHANS+n)
|
|
5C53h 2 PROG Address of BASIC program. (End of CHANS)
|
|
5C55h 2 NXTLIN Address of next line in program. (PROG+n, or 0000h=None)
|
|
5C57h 2 DATADD Address of terminator of last DATA item. (initially PROG-1)
|
|
5C59h 2 E_LINE Address of input buffer (aka line editor) (End of VARS)
|
|
5C5Bh 2 K_CUR Address of cursor in input buffer (E_LINE+n)
|
|
5C5Dh 2 CH_ADD Address of the next character to be interpreted
|
|
(the character after the argument of PEEK,
|
|
or the NEWLINE at the end of a POKE statement)
|
|
5C5Fh 2 X_PTR Address of the character after the [] marker. (or 00D7h?)
|
|
5C61h 2 WORKSP Address of temporary work space.
|
|
5C63h 2 STKBOT Address of bottom of calculator stack.
|
|
5C65h 2 STKEND Address of start of spare space.
|
|
5C67h 1 BREG Calculator's B register.
|
|
5C68h 2 MEM Address of area used for calculator's memory
|
|
(usually MEMBOT, but not always).
|
|
5C6Ah 1 FLAGS2 More flags. (Bit3 set when CAPS SHIFT or CAPS LOCK is on.)
|
|
5C6Bh 1 DF_SZ Number of lines in lower part of screen (including one
|
|
blank line)
|
|
5C6Ch 2 S_TOP The number of the top program line in automatic listings.
|
|
5C6Eh 2 OLDPPC Line number to which CONTINUE jumps.
|
|
5C70h 1 OSPPC Number within line of statement to which CONTINUE jumps.
|
|
5C71h 1 FLAGX Various flags.
|
|
5C72h 2 STRLEN Length of string type destination in assignment.
|
|
5C74h 2 T_ADDR Address of next item in syntax table.
|
|
5C76h 2 SEED The seed for RND. This is set by RANDOMIZE.
|
|
5C78h 3 FRAMES Frame counter incremented at 50Hz (or 60Hz) (24bit)
|
|
5C7Bh 2 UDG Address of first user-defined graphic (usually FF58h)
|
|
5C7Dh 2 COORDS X,Y coordinates of last point plotted.
|
|
5C7Fh 1 P_POSN 33-column number of printer position.
|
|
5C80h 2 PRCC Address of Current Column in PRBUFF (5B00h..5B1Fh)
|
|
[Not used in 128K mode or when certain peripherals
|
|
are attached]
|
|
5C82h 2 ECHO_E 33-column number and 24-line number
|
|
(in lower half) of end of input buffer.
|
|
5C84h 2 DF_CC Address in display file of PRINT position.
|
|
5C86h 2 DF_CCL Like DF_CC for lower part of screen.
|
|
5C88h 1 S_POSN 33-column number for PRINT position.
|
|
5C89h 1 24-line number for PRINT position.
|
|
5C8Ah 2 SPOSNL Like S_POSN for lower part.
|
|
5C8Ch 1 SCR_CT Counts scrolls - it is always 1 more
|
|
than the number of scrolls that will
|
|
be done before stopping with
|
|
'scroll?'. If you keep poking this
|
|
with a number bigger than 1 (say 255),
|
|
the screen will scroll on and on
|
|
without asking you.
|
|
5C8Dh 1 ATTR_P Permanent current colours, etc., (as
|
|
set up by colour statements).
|
|
5C8Eh 1 MASK_P Used for transparent colours, etc. Any
|
|
bit that is 1 shows that the
|
|
corresponding attribute bit is taken
|
|
not from ATTR_P, but from what is
|
|
already on the screen.
|
|
5C8Fh 1 ATTR_T Temporary current colours, etc., (as
|
|
set up by colour items).
|
|
5C90h 1 MASK_T Like MASK_P, but temporary.
|
|
5C91h 1 P_FLAG More flags.
|
|
5C92h 30 MEMBOT Calculator's memory area - used to
|
|
store numbers that cannot conveniently
|
|
be put on the calculator stack.
|
|
5CB0h 2 NMIADD Holds the address of the users NMI service routine.
|
|
NOTE - On previous machines, this did
|
|
not work correctly and these two bytes
|
|
were documented as 'Not used.'
|
|
Programs that used these two bytes for
|
|
passing values may need to be
|
|
modified.
|
|
5CB2h 2 RAMTOP Address of last byte of BASIC system area.(usually FF57h)
|
|
5CB4h 2 P_RAMT Address of last byte of physical RAM. (usually FFFFh)
|
|
|
|
Timex 2068 - Extended System Area
|
|
5CB6h 2 ERRLN Line number to GOTO on error
|
|
5CB8h 2 ERRLN Line number in which error occurred
|
|
5CBAh 1 ERRS Statement number within line in which error occurred
|
|
5CBBh 1 ERRT Error number (Report Code)
|
|
5CBCh 2 SYSCON Pointer to System Configuration Table
|
|
5CBEh 1 MAXBNK Number of Expansion Banks in System
|
|
5CBFh 1 CURCBN Current Channel Bank Number
|
|
5CC0h 2 MSTBOT Address of location above machine stack
|
|
5CC2h 1 VIDMOD Video Mode (non-zero if 2nd display file is used)
|
|
5CC3h 1 <undocumented/unused byte> ?
|
|
5CC4h 7 "Various variables used for BASIC cartridges" ...details?
|
|
5CCBh 1 STRMNM Current Stream number
|
|
5CCCh 334h - Not used (except, some stuff at 5EF3h..5EF6h is used?)
|
|
|
|
Spectrum 128/+2/+2A/+3 - Extended System Area (formerly Printer buffer)
|
|
Addr Siz Name Expl.
|
|
Below is for Spectrum 128/+2:
|
|
5B00h 20 SWAP Paging subroutine.
|
|
5B14h 9 YOUNGER Paging subroutine.
|
|
5B1Dh 18 ONERR Paging subroutine.
|
|
5B2Fh 5 PIN
|
|
5B34h 22 POUT
|
|
5B4Ah 14 POUT2
|
|
Below is for Spectrum +3:
|
|
5B00h 16 SWAP Paging subroutine.
|
|
5B10h 17 STOO Paging subroutine. Entered with IRQs disabled, AF,BC pushed
|
|
5B21h 9 YOUNGER Paging subroutine.
|
|
5B2Ah 16 REGNUOY Paging subroutine.
|
|
5B3Ah 24 ONERR Paging subroutine.
|
|
5B52h 2 OLDHL Temporary register store while switching ROMs.
|
|
5B54h 2 OLDBC Temporary register store while switching ROMs.
|
|
5B56h 2 OLDAF Temporary register store while switching ROMs.
|
|
Below is for both Spectrum 128 and +3:
|
|
5B58h 2 TARGET Subroutine address in ROM 3.
|
|
5B5Ah 2 RETADDR Return address in ROM 1.
|
|
5B5Ch 1 BANKM Copy of last byte output to I/O port 7FFDh.
|
|
5B5Dh 1 RAMRST RST 8 instruction. Used by ROM 1 to
|
|
report old errors to ROM 3.
|
|
5B5Eh 1 RAMERR Error number passed from ROM 1 to ROM
|
|
3. Also used by SAVE/LOAD as temporary drive store.
|
|
5B5Fh 2 BAUD RS232 bit period in T states/26. Set by FORMAT LINE.
|
|
5B61h 2 SERFL Second-character-received-flag, and data.
|
|
5B63h 1 COL Current column from 1 to width.
|
|
5B64h 1 WIDTH Paper column width. Defaults to 80. (on +3 at least)
|
|
5B65h 1 TVPARS Number of inline parameters expected by RS232.
|
|
5B66h 1 FLAGS3 Various flags. Bits 0, 1, 6 and 7
|
|
unlikely to be useful. Bit 2 is set
|
|
when tokens are to be expanded on
|
|
printing. Bit 3 is set if print output
|
|
is RS232. The default (at reset) is
|
|
Centronics (on +3) and whatever? (on 128/+2).
|
|
Bit 4 is set if a disk
|
|
interface is present. Bit 5 is set if
|
|
drive B: is present.
|
|
Below is for Spectrum 128/+2:
|
|
5B67h 10 NSTR1
|
|
5B71h 1 HD00
|
|
5B72h 2 HD0B
|
|
5B74h 2 HD0D
|
|
5B76h 2 HD0F
|
|
5B78h 2 HD11
|
|
5B7Ah 1 SC00
|
|
5B7Bh 2 SC08
|
|
5B7Dh 2 SC0D
|
|
5B7Fh 2 SC0F
|
|
5B81h 2 OLDSP
|
|
5B83h 2 SFNEXT
|
|
5B85h 3 SPSPACE
|
|
5B88h 1 ROW01
|
|
5B89h 1 ROW23
|
|
5B8Ah 1 ROW45
|
|
5B8Bh 2 SYNRET
|
|
5B8Dh 5 LASTV
|
|
5B92h 2 RNLINE
|
|
5B94h 2 RNFIRST
|
|
5B96h 2 RNSTEP
|
|
5B98h 8 STRIP1
|
|
5BA0h 8 STRIP2
|
|
5BA8h 87 TSTACK
|
|
5BFFh 1 N/A
|
|
Below is for Spectrum +3:
|
|
5B67h 1 BANK678 Copy of last byte output to I/O port 1FFDh.
|
|
5B68h 1 XLOC Holds X location when using the unexpanded COPY command.
|
|
5B69h 1 YLOC Holds Y location when using the unexpanded COPY command.
|
|
5B6Ah 2 OLDSP Old SP (stack pointer) when TSTACK is in use.
|
|
5B6Ch 2 SYNRET Return address for ONERR.
|
|
5B6Eh 5 LASTV Last value printed by calculator.
|
|
5B73h 2 RCLINE Current line being renumbered.
|
|
5B75h 2 RCSTART Starting line number for renumbering. The default is 10.
|
|
5B77h 2 RCSTEP Incremental value for renumbering. The default is 10.
|
|
5B79h 1 LODDRV Holds 'T' if LOAD, VERIFY, MERGE are
|
|
from tape, otherwise 'A', 'B' or 'M'.
|
|
5B7Ah 1 SAVDRV Holds 'T' if SAVE is to tape, otherwise 'A', 'B' or 'M'.
|
|
5B7Bh 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.
|
|
5B7Ch 8 STRIP1 Stripe one bitmap. ;\allowed to be destroyed by
|
|
5B84h 8 STRIP2 Stripe two bitmap. ;/Temporary stack
|
|
5B8Ch 115 TSTACK Temporary stack (when RAM7 is mapped to C000h-FFFFh)
|
|
5BFFh 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 (0..7) (always with Bright=off)
|
|
3 MIC Output (CAS SAVE) (0=On, 1=Off)
|
|
4 Beep Output (ULA Sound) (0=Off, 1=On)
|
|
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 . 7 6 .
|
|
4 /Composite Sync (TTL) | 3 8 1 |
|
|
5 +12V ' 5 4 '
|
|
6 Green (Analogue 1.67V p-p) \ 2 /
|
|
7 Red (Analogue 1.67V p-p) '---'
|
|
8 Blue (Analogue 1.67V p-p)
|
|
|
|
TS2068: If the RGB output is used, BRIGHT is ignored.
|
|
|
|
Spectrum Timings
|
|
----------------
|
|
|
|
Maker Spectrum Spectrum Spectrum Timex Timex
|
|
Version 16K/48K/+ 128/+2 +2A/+3 TC2048/2068 TS2068
|
|
CPU Osc 14.000MHz 17.73447MHz ? ? 14.112MHz
|
|
Color Osc 4.4336MHz CPU Osc/4 CPU Osc/n ? 3.579545MHz
|
|
CPU Clock 3.500000MHz 3.54690MHz 3.54690MHz 3.50000MHz 3.52800MHz
|
|
PSG Clock N/A 1.7734MHz 1.7734MHz ? (if any) 1.764(75)?
|
|
HorizontalTotal 224 clks 228 clks 228 clks ? 224 clks
|
|
HorizontalDraw 128 clks 128 clks 128 clks 128 clks 128 clks
|
|
HorizontalBlank 96 clks 100 clks 100 clks ? ?
|
|
Vertical Total 312 lines 311 lines ? ? 262 lines
|
|
Screen 192 lines 192 lines 192 lines 192 lines 192 lines
|
|
Upper Border 64 lines 63 lines ? ? ?
|
|
Lower Border 56 lines 56 lines ? ? ?
|
|
Frame Rate 50.08Hz/PAL 50.01Hz/PAL 50.?Hz/PAL 50.?Hz/PAL 60.11Hz/NTSC
|
|
Flash Rate 50/32=1.6Hz 50/32=1.6Hz 50/32=1.6Hz 50/32=1.6Hz 60/32=1.9Hz
|
|
First Delay at 14335 clks ? 14361 clks ? ?
|
|
Delay Pattern 6..1,0,0 ? 1,0,7..2 ? ?
|
|
Port FEh Delay Yes Yes No Yes Yes
|
|
VRAM Delay at 4000h-7FFFh RAM1,3,5,7 RAM4,5,6,7 4000h-7FFFh 4000h-7FFFh
|
|
Snow Effect Yes Yes/Crash ? No? Yes/No?
|
|
|
|
Some Clones
|
|
The russian Scorpion seems to have same timings as Spectrum 48K. The russian
|
|
Pentagon has 320 lines total (64+192+48+16), and, it generates INT at begin of
|
|
its 16-lines Vsync period (all other computers have INT at end of Vsync, aka
|
|
begin of upper border). Horizontal total is 224 clks on both Pentagon and
|
|
Scorpion, but hsync position is slightly different on each. Both Scorpion and
|
|
Pentagon do not have slow (contended) memory.
|
|
|
|
VRAM Waitstates (aka "contended memory" waitstates)
|
|
Within each 8 cycles, the ULA reads 2 bitmap bytes and 2 attribute bytes via
|
|
video DMA (which takes up 4 clks), followed by 4 cycles where bus is free for
|
|
the CPU. Although there are 4 free cycles, the ULA allows the CPU to invoke a
|
|
RAM access (or a Port FEh access) only during 2 of that 4 cycles:
|
|
UUUUUUccUUUUUUccUUUUUUcc.. ;<--- U=Blocked by ULA, c=Free for CPU access
|
|
654321006543210065432100.. ;<--- Number of waitstates (0=none)
|
|
For whatever reason, the access pattern is different on the +2A/+3:
|
|
UcUUUUUUUcUUUUUUUcUUUUUU.. ;<--- U=Blocked by ULA, c=Free for CPU access
|
|
107654321076543210765432.. ;<--- Number of waitstates (0=none)
|
|
Waitstates occur only during drawing, ie. not during Vblank and Hblank. The
|
|
first ULA access appears 14335 (or 14361) cycles after the Vsync IRQ (or
|
|
unknown number of cycles on NTSC and others). The above access pattern is then
|
|
repeated throughout the 128 cycles drawing time, and pauses throughout the 96
|
|
(or 100) cycles hblank time.
|
|
Although a screen with attributes consists of only 6.75Kbytes, the waitstates
|
|
apply on any access to memory chips that are connected to the ULA (ie. the
|
|
whole 16K at 4000h..7FFFh) (or one half of RAM on 128K machines, either in
|
|
banks 1,3,5,7 on Spectrum 128/+2, or in banks 4,5,6,7 on Spectrum +2A/+3).
|
|
Other portions of RAM (and ROM) can be accessed without waitstates.
|
|
|
|
Details on VRAM-DMA Access Timings
|
|
As said above, within each 8 cycles, the ULA reads 2 bitmap bytes and 2
|
|
attribute bytes, the LSBs of the bitmap address are the same as of the
|
|
attribute address, so two bytes (1x bitmap, and 1x attr) can be fetched with a
|
|
single long /RAS signal (1.5 clks low) and two short /CAS signals (0.5 clks
|
|
low):
|
|
|-----8 clks----||-----8 clks----|-----H/V-Blank...------
|
|
/RAS (RAM.Pin4) -___-___---------___-___--------------------------------
|
|
/CAS (RAM.Pin15) -_-_-_-_---------_-_-_-_--------------------------------
|
|
During drawing, the ULA outputs all /RAS addresses in range 00h..7Fh (though
|
|
not in linear order) to the memory, so the above /RAS signals do also serve as
|
|
refresh signals.
|
|
|
|
Details on CPU Access Timings
|
|
CPU memory accesses are slower than video DMA (the CPU outputs /CAS and /RAS
|
|
low for 1.5 clks, while DMA uses only 0.5 clks for /CAS). Normally, the CPU
|
|
does also output a "dummy" /RAS for refresh (1.0 clks low), so a stream of NOP
|
|
opcodes would look like so:
|
|
|-----8 clks----||-----8 clks----|
|
|
/RAS (RAM.Pin4) -___-__--___-__--___-__--___-__- ;four NOP opcodes
|
|
/CAS (RAM.Pin15) -___-----___-----___-----___----
|
|
When accessing "contended" memory, the ULA takes care of refresh, so the CPU's
|
|
refresh signal can be suppressed, and a stream of NOP opcodes would look like
|
|
so (assuming that no VRAM-DMA is taking place, eg. during Hblank):
|
|
|-----8 clks----||-----8 clks----|
|
|
/RAS (RAM.Pin4) -___-----___-----___-----___---- ;four NOP opcodes
|
|
/CAS (RAM.Pin15) -___-----___-----___-----___----
|
|
|
|
Scanline Effects
|
|
The Spectrum doesn't have a Scanline interrupt, so changing video attributes in
|
|
specfic scanlines (for using more than 2 colors per 8x8 pixels), or changing
|
|
the horizontal resolution in a given scanline (on Timex machines) can be
|
|
implemented only by waiting so-and-so-many clock cycles after the Vsync
|
|
interrupt has occurred. That method wastes a lot of CPU load, and its difficult
|
|
to get it compatible with all computers (due to different horizontal and
|
|
vertical timings, and different waitstates).
|
|
Another approach would be reading from Port FFh (or other unused ports), and to
|
|
wait until contains a specific color attribute, that method is more flexible
|
|
than hardcoded delays, but, it doesn't work on all computers (see Port FFh info
|
|
in ULA chapter for details).
|
|
|
|
Refresh and Snow
|
|
The Z80 CPU generates refresh signals used for the non-contended RAM only.
|
|
The contended VRAM uses a different refresh signal generated from the ULA.
|
|
Although contended VRAM doesn't use CPU refresh signal, the ULA can get
|
|
"confused" when the CPU refresh occurs with the address bus containing a
|
|
contended memory address (ie. when the IR register pair points to 4000h..7FFFh;
|
|
aka when the I register is 40h..7Fh), in that case the ULA thinks that the CPU
|
|
wants to access memory, causing the ULA not to load new data from VRAM (and to
|
|
re-use old data), which results in "snow" on the screen. On Spectrum 128K/+2,
|
|
the snow effect does exist, but it does reportedly "crash the machine shortly
|
|
after I is set to point to contended memory".
|
|
Hmmm.......... assuming that the effect doesn't just block VRAM reads, but also
|
|
VRAM refresh.... then it actually CRASH programs (and BIOS code) that have
|
|
code/data located in the "contended" memory regions.... eg. the 16K spectrum
|
|
has ONLY contended memory, so the program would survive on a few seconds or
|
|
so.... the reported crash on 128K/+2 might have the same reason (but could be
|
|
simply avoided by using only uncontended memory)...?
|
|
|
|
Spectrum Sound
|
|
--------------
|
|
|
|
Standard ULA Beeper
|
|
--> Spectrum Sound ULA
|
|
--> Spectrum Sound Speaker/Amplifier/Modulator
|
|
|
|
Programmable Sound Generator
|
|
The 3-channel PSG is used in the Spectrum 128/+2/+2A/+3 (and occassionally
|
|
supported by newer games).
|
|
--> Spectrum Sound PSG (Programmable Sound Generator)
|
|
The same PSG chip is also used in Timex TS2068/TC2068 computers and in various
|
|
expansion boxes (but at different I/O addresses, and rarely supported by any
|
|
games).
|
|
|
|
Speech Hardware
|
|
--> Spectrum Sound Speech Overview
|
|
--> Spectrum Sound Speech I/O Ports
|
|
--> Spectrum Sound Speech SP0256 Voice Generator
|
|
--> Spectrum Sound Speech SP0256 Instruction Set
|
|
--> Spectrum Sound Speech SP0256 Allophones/Words
|
|
--> Spectrum Sound Speech SP0256 Pin-Outs
|
|
|
|
Digital Sound (Playback/Recording)
|
|
--> Spectrum Sound Digital Playback/Sampling
|
|
|
|
MIDI Interfaces
|
|
Cheetah MIDI Interface (Cheetah)
|
|
EMR MIDI Interface (Electro Music Research)
|
|
MIDISYNC (Icon Design Ltd.)
|
|
MIDI Sync Boxes (XRI Systems)
|
|
Siel MIDI Interface (Siel UK Ltd)
|
|
Upstream MIDI Interface (Upstream Computer Systems Ltd)
|
|
XRI Micon MIDI Interface (XRI Systems)
|
|
ZX Spectrum 128 +2 to MIDI Lead (Cheetah)
|
|
Music Machine (see Digial Sound chapter for details)
|
|
|
|
Spectrum Sound ULA
|
|
------------------
|
|
|
|
Sound Frequency vs Video Waitstates
|
|
Observe that video waitstates occur when drawing the bitmap area (but not
|
|
during Hblank and Vblank), so the presence/absence of waitstates can have some
|
|
nasty effects on software generated sound frequencies.
|
|
Basically, do not use code/data in RAM at 4000h..7FFFh when generating sounds.
|
|
Waitstates do also occur on accessing Port FEh, which may become a problem with
|
|
high-frequency PWM sounds, a workaround would be to access Port FEh only within
|
|
multiples of 8 clock cycles (so it runs in sync with video DMA).
|
|
Aside from waitstates, it may be also good to disable IRQs to prevent the sound
|
|
to get paused during IRQ handling (or at least to use a custom fast IRQ
|
|
handler).
|
|
|
|
Sound Volume via Bit3 (not recommended / unstable results)
|
|
The ULA has two separate control bits for Sound and Cassette output:
|
|
Port FEh.Bit4 = Audio Output (0 = 0.3 Volts, 1 = 3.7 Volts)
|
|
Port FEh.Bit3 = Cassette Output (0 = 0.3 Volts, 1 = 0.7 Volts)
|
|
However, it does output both signals on the same pin.
|
|
Port FEh = 18h --> 3.7V
|
|
Port FEh = 10h --> 3.6V
|
|
Port FEh = 08h --> 0.7V
|
|
Port FEh = 00h --> 0.3V
|
|
Below are examples for a Spectrum 48K with Issue 2 mainboard; one column shows
|
|
results for the internal speaker, the other column shows results for the MIC
|
|
output passed to an external amplifier (eg. to the Audio Input of a TV set).
|
|
Furthermore, results may differ on other mainboards (after issue 2, Sinclair
|
|
seem to have added a transistor as internal amplifier).
|
|
Toggle between Internal Speaker External Amplifier
|
|
00h and 10h Volume = ##### Volume = ##### ;normal
|
|
00h and 08h Volume = ..... Volume = ##... ;unpredictable
|
|
10h and 18h Volume = ##... Volume = #.... ;unpredictable
|
|
Normally, sound should be generated by toggling bit4 of Port FEh. As shown
|
|
above, messing with bit3 has rather unpredictable results; toggling between 00h
|
|
and 08h has a good voltage difference which is audible on external amplifiers,
|
|
but not enough amperes to drive the internal speaker; for toggling between 10h
|
|
and 18h it's vice versa, the voltage difference is smaller, but there are more
|
|
amperes (it becomes audible on internal speaker, but the volume drops with
|
|
external amplifier).
|
|
|
|
Spectrum Sound Speaker/Amplifier/Modulator
|
|
------------------------------------------
|
|
|
|
Internal Speaker (Spectrum 16K/48K/Plus and Timex TS/TC20xx)
|
|
Older Spectrums with 16K/48K RAM are containing an internal speaker, used to
|
|
output the ULA sound (and PSG sound in case of the Timex 2068). The dimensions
|
|
(and volume) of the internal speaker would be more suitable for headphones. The
|
|
TV modulator generates a raw video signal (so the TV speaker is not used).
|
|
|
|
Internal Audio UHF Modulator (Spectrum 128/+2/+2A/+3)
|
|
Newer Spectrums with 128K RAM don't include an internal speaker, instead, the
|
|
ULA sound (and PSG sound) is passed to the TV set via the UHF modulator.
|
|
|
|
External Speakers/Amplifiers and Modulators
|
|
To "boost" the volume, several companies offered external amplifiers with
|
|
bigger external speakers. Most external PSG/Speech devices do also mix and
|
|
amplify the ULA sound with the PSG/Speech sound.
|
|
For using the TV speakers, several companies have offered internal and external
|
|
UHF modulators which mixed the audio signal with the video signal (for modern
|
|
TVs with A/V inputs sets it'd be easier/cheaper to pass MIC/VID to A/V input of
|
|
the TV set, which'd also give better picture quality than UHF).
|
|
|
|
External Sound Connectors
|
|
In general, sound can be obtained from the MIC port (or anywhere from the
|
|
mainboard). The Timex TS2068 does also output PSG/ULA on the expansion port.
|
|
The Spectrum expansion Port doesn't have a sound output (however, external
|
|
hardware could easily reconstruct ULA sound by latching D4 upon /IORQULA and
|
|
/WR). The analogue RGB output on the Spectrum +2A/+3 does also include an audio
|
|
pin (unlike the TTL RGB output on the Spectrum 128).
|
|
|
|
Mono/Stereo Sound
|
|
The standard spectrum hardware supports only mono sound output. Some of the
|
|
external PSG devices allow to produce stereo sounds by passing one PSG channel
|
|
to left, one to right, and the third channel to both left and right speakers;
|
|
but, external PSG devices are rarely supported by any games, and there's no
|
|
real standard which channel is passed to which speaker.
|
|
|
|
Spectrum Sound PSG (Programmable Sound Generator)
|
|
-------------------------------------------------
|
|
|
|
I/O Ports of known PSG devices
|
|
Model Index.W Data.W Data.R Chip Year
|
|
Spectrum 128/+2/+2A/+3 FFFDh BFFDh FFFDh 8912 1985
|
|
Didaktik Melodik (spectrum 128 style) FFFDh BFFDh FFFDh 891x 19xx
|
|
Timex TS2068 (NTSC) xxF5h xxF6h xxF6h 8912 1983
|
|
Timex TC2068 (PAL) xxF5h xxF6h xxF6h 8912 1984
|
|
Fuller Box xx3Fh xx5Fh xx3Fh 8912 1983
|
|
Fuller Box Master Unit (with Orator) xx3Fh xx5Fh xx3Fh 8912 1983
|
|
DK'Tronics 3 Channel Sound Synthesiser xx3Fh xx5Fh ? 8912 1984
|
|
Timedata ZXM Soundbox (ZX81) xx9Fh xxDFh xxBFh 8912 198x
|
|
Timedata ZXM Soundbox (Spectrum) xx9Fh xxDFh xxBFh 8912 198x
|
|
William Stuart Systems Music Synthesiser xx9Fh xxDFh ? 891x 1983
|
|
Bi-Pak ZON X81 Soundbox (ZX81) xxDFh xx0Fh N/A? 891x 198x
|
|
Bi-Pak ZON X Soundbox (Spectrum) xxFFh xx7Fh N/A 8912 1982
|
|
Ricoll RISG Sound Generator ? ? ? 8910 1983
|
|
Ricoll RIFG Sound Generator with filters ? ? ? 8910 1983
|
|
Petron Trichord (includes PROM) ? ? ? 8910 1983
|
|
Signpoint Sound Synthesiser Plus ? ? ? 8910 1984
|
|
Datel 3 Channel Sound Synthesiser ? ? ? ? 1989
|
|
Investronica INAXEL Sound & Joystick ? ? ? ? ?
|
|
|
|
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 = Tone Frequency channel A, low (0-255)
|
|
01h = Tone Frequency channel A, high (0-15)
|
|
02h = Tone Frequency channel B, low (0-255)
|
|
03h = Tone Frequency channel B, high (0-15)
|
|
04h = Tone Frequency channel C, low (0-255)
|
|
05h = Tone Frequency channel C, high (0-15)
|
|
The actual listened frequency in Hertz is calculated as follows:
|
|
F = 3.5xxMHz / 32 / nn ;with nn in range 1..4095 (nn=0 acts as nn=1)
|
|
|
|
06h = Noise Frequency (0-31)
|
|
The actual noise frequency in Hertz is calculated as follows:
|
|
F = 3.5xxMHz / 32 / nn ;with nn in range 1..31 (nn=0 acts as nn=1)
|
|
Noise can be output on all 3 channels, but there is only one noise generator
|
|
(so all channels share the same noise frequency). The noise generator consists
|
|
of 17bit shift register, and a 1bit noise level (0=LOW or 1=HIGH). These are
|
|
updated at the selected frequency as follows:
|
|
noise_level = noise_level XOR shiftreg.bit0
|
|
newbit = shiftreg.bit0 XOR shiftreg.bit3
|
|
shiftreg = (shiftreg SHR 1) + (newbit SHL 16)
|
|
Note that level isn't set equal to bit0, instead, it toggles when bit0=1.
|
|
|
|
07h = Mixer Control
|
|
Bit Expl.
|
|
0 Channel A tone enable (0=Enable, 1=Disable)
|
|
1 Channel B tone enable (0=Enable, 1=Disable)
|
|
2 Channel C tone enable (0=Enable, 1=Disable)
|
|
3 Channel A noise enable (0=Enable, 1=Disable)
|
|
4 Channel B noise enable (0=Enable, 1=Disable)
|
|
5 Channel C noise enable (0=Enable, 1=Disable)
|
|
6 I/O port A mode (0=Input, 1=Output)
|
|
7 I/O port B mode (0=Input, 1=Output)
|
|
If both Tone and Noise are disabled on a channel, then a constant HIGH level is
|
|
output (useful for digitized speech). If both Tone and Noise are enabled on the
|
|
same channel, then the signals are ANDed (the signals aren't ADDed) (ie. HIGH
|
|
is output only if both are HIGH).
|
|
|
|
08h = Volume channel A (0-15, 16=Envelope)
|
|
09h = Volume channel B (0-15, 16=Envelope)
|
|
0Ah = Volume channel C (0-15, 16=Envelope)
|
|
Defines the volume, 0=off, 15=max. If bit4=1, then the volume is taken from the
|
|
envelope generator. The volume is non-linear:
|
|
amplitude = max / sqrt(2)^(15-nn) ;(according to datasheet)
|
|
eg. 15 --> max/1, 14 --> max/1.414, 13 --> max/2, etc.
|
|
The volume affects only HIGH levels. LOW levels are always NULL. Ie. sound
|
|
output toggles between +VOL and NULL (not between +VOL and -VOL).
|
|
Digitized samples can be written to the volume registers (mind that volume is
|
|
non-linear). When doing that, it's best to switch the channel to constant HIGH
|
|
level (by disabling both Tone and Noise). Another method would be to set tone
|
|
frequency to 000h or 001h (the resulting frequency is too high to be audible,
|
|
so the HIGH/LOW levels sound like a constant HALF level).
|
|
|
|
0Bh = Volume Envelope Frequency, low (0-255)
|
|
0Ch = Volume Envelope Frequency, high (0-255)
|
|
Envelope step frequency (tone or noise) calculated as follows:
|
|
F = 3.5xxMHz / 32 / nn ;with nn in range 0..65535 (nn=0 acts as nn=1)
|
|
Depending on the envelope shape, the volume is incremented from 0 to 15, or
|
|
decremented from 15 to 0. In either case it takes 16 steps to complete, the
|
|
completion time for 16 steps is therefore:
|
|
T = nn*512 / 3.5xxMHz ;with nn in range 1..65535 (0 .. ca. 9.5 seconds)
|
|
|
|
0Dh = Volume Envelope shape (0-15)
|
|
Writing to this register (re-)starts the envelope. Additionally, the written
|
|
value specifies the envelope shape, the four bits have the following meaning:
|
|
CONT ATT ALT HLD
|
|
0 0 X X \_________ 0-3 (same as 9)
|
|
0 1 X X /_________ 4-7 (same as F)
|
|
1 0 0 0 \\\\\\\\\\ 8 (Repeating)
|
|
1 0 0 1 \_________ 9
|
|
1 0 1 0 \/\/\/\/\/ A (Repeating)
|
|
1 0 1 1 \""""""""" B
|
|
1 1 0 0 ////////// C (Repeating)
|
|
1 1 0 1 /""""""""" D
|
|
1 1 1 0 /\/\/\/\/\ E (Repeating)
|
|
1 1 1 1 /_________ F
|
|
|
|
0Eh = I/O port A (with external pinouts on AY-3-8910 and AY-3-8912)
|
|
0Fh = I/O port B (with external pinouts on AY-3-8910 only)
|
|
These are two general purpose 8bit I/O ports (direction can be set via register
|
|
7). Port A exists on both AY-3-8910 and AY-3-8912 chips. Port B exists on
|
|
AY-3-8910 only (or actually, it does internally exist even on the smaller
|
|
AY-3-8912, but it doesn't have external pinouts).
|
|
Model Port A Port B
|
|
Timex TC2068 and TS2068 Joysticks (*) N/A (uses 8912 chip)
|
|
Spectrum 128/+2/+2A/+3 RS232/Keypad N/A (uses 8912 chip)
|
|
Fuller Box ? N/A (uses 8912 chip)
|
|
DK'Tronics Unused? N/A (uses 8912 chip)
|
|
Timedata ZXM Soundbox Joystick/User Port N/A (uses 8912 chip)
|
|
Signpoint ioport ioport
|
|
Other expansions...? ? ? (some do use 8910 chip)
|
|
(*) Timex also passes Bit5 of Port A to Expansion Port Pin 30 on upper side.
|
|
|
|
Spectrum 128/+2/+2A/+3 PSG Software
|
|
Some newer games (made after the Spectrum 128 was released in 1985) do support
|
|
its PSG hardware (eg. Cybernoid, Exolon, Into the Eagles Nest, Head Over
|
|
Heels), but many other newer games don't do so.
|
|
|
|
Fuller Box and DK'Tronics PSG Software (compatible with each other)
|
|
Fuller Box Demonstration Program (Fuller)
|
|
Sound Designer (DK'Tronics)
|
|
Invasion of the Body Snatchas
|
|
Aside from the Fuller Box and DK'Tronics demonstration tapes, there seems to be
|
|
almost no other software that supports these PSGs (even DK'Tronics didn't
|
|
support their own hardware in their own games).
|
|
|
|
William Stuart Systems Music Synthesiser Software
|
|
Composer (William Stuart Systems)
|
|
|
|
Timex 2068 Software
|
|
The TS2068 (USA) wasn't very popular, and the TC2068 (Portugal/Poland) was
|
|
mainly used with 'normal' european Spectrum 48K software - so there are
|
|
probably not too many (if any?) commercial games that support the PSG in Timex
|
|
computers.
|
|
|
|
Spectrum Sound Speech Overview
|
|
------------------------------
|
|
|
|
Known "General Instrument SP0256-AL2 Narrator" Speech devices
|
|
Currah MicroSpeech (1983) - uses SP0256-AL2 speech processor, output via TV
|
|
Fuller Orator - Speech Synthesis (1984) - uses G1-SP0256 AL voice chip
|
|
Fuller Box Master Unit (PSG and Orator)
|
|
Cheetah Sweet Talker (1983) (crude thing that HALTs the CPU during speech)
|
|
DK'Tronics Speech Synthesiser (1985) - uses the SLO/256 chip
|
|
The Currah MicroSpeech (aka Currah uSpeech) seems to be the most popular speech
|
|
device, possibly because of it's easy to use BIOS extension, although that
|
|
extension causes very serious compatibility problems with other software.
|
|
|
|
Other known Speech devices
|
|
Spirit Instruments - Spectrum Speech Synthesiser (1983)
|
|
SS1 Speech Synthesiser (1983)
|
|
VTR Vocal Synthesizer (1985)
|
|
Timedata ZXS Speech Synthesiser (1983)
|
|
William Stuart Systems Chatterbox (1983)
|
|
William Stuart Systems Chatterbox II (1985) (with intonation)
|
|
Zebra Talker Speech Synthesiser (for Timex)
|
|
Datel Vox Box (1984) (allophone)
|
|
DCP Microdevelopments S-Pack (1983) - vocabulary of 71 words (upgradeable)
|
|
DCP Microdevelopments Speech Pack (1982) for ZX81
|
|
There isn't much known about these devices, most are probably containing
|
|
SP0256-AL2 chips, too. One exception are the devices from DCP, which contain
|
|
Digitalker chips from National Semiconductor, and which use a fixed vocabulary
|
|
instead of allophones. Not too sure if Datel has actually manfactured any
|
|
hardware (possibly they've just renamed and redistributed hardware from other
|
|
companies).
|
|
|
|
Cheetah Sweet Talker Software
|
|
Chatbox (Demonstration Program by Cheetah Marketing Ltd.)
|
|
|
|
Fuller Orator / Master Unit Speech Software
|
|
Spectrum Voice Chess (Fuller Box version; ie. NOT the ULA version) (Artic)
|
|
|
|
DK'Tronics Speech Software
|
|
Speech Software (Demonstration Program by DK'Tronics Ltd.)
|
|
|
|
Currah MicroSpeech Software
|
|
Title Publisher
|
|
3-D Monster Chase Romik Software
|
|
All or Nothing Abbex Electronics
|
|
Arrow of Death Part 1 Digital Fantasia
|
|
Arrow of Death Part 2 Digital Fantasia
|
|
Atic Atac Ultimate Play The Game
|
|
Auf Wiedersehen Pet Tynesoft
|
|
Bingo Tynesoft
|
|
Birds and the Bees, The Bug-Byte Software Ltd
|
|
Blade Alley PSS
|
|
Blastermind! Martech Games Ltd
|
|
Blob, The 16/48 Tape Magazine
|
|
Bongo Anirog Software
|
|
Cagara Players Software
|
|
Colour Clash Romik Software
|
|
Connect 4 John Westhead
|
|
Covenant, The PSS
|
|
Crazy Golf Mr. Micro Ltd
|
|
Currah MicroSpeech Currah Computer Components Ltd
|
|
Currah MicroSpeech Software Cecomsa
|
|
Evil Dead, The Palace Software
|
|
Fruit Snapper LiveWire Software
|
|
Giant's Revenge Thor Computer Software
|
|
Golden Baton Digital Fantasia
|
|
Grand Prix Driver Britannia Software Ltd
|
|
Gremlins Thor Computer Software
|
|
Harlequin Mr. Micro Ltd
|
|
Hunchback Ocean Software Ltd
|
|
Insult Generator Greg Fox
|
|
Island, The Crystal Computing
|
|
Jack and the Beanstalk Thor Computer Software
|
|
Learn with Ted Playground Software
|
|
Lunar Jetman Ultimate Play The Game
|
|
Lunar Rescue Lyversoft
|
|
Max Headroom Quicksilva Ltd
|
|
Maze of Terror Kevin Hillyer
|
|
Maziacs DK'Tronics Ltd
|
|
Mega Fruit Thor Computer Software
|
|
Mined-Out Quicksilva Ltd
|
|
Moon Alert Ocean Software Ltd
|
|
Mr. Wimpy Ocean Software Ltd
|
|
Mystic Tower Aardvark Software
|
|
Night Stalker Thor Computer Software
|
|
Pi-Balled Automata UK Ltd
|
|
Pogo Ocean Software Ltd
|
|
Pontoon Oxford Computer Publishing
|
|
Psi-Spy Postern Ltd
|
|
Punchy Mr. Micro Ltd
|
|
Rainy Day CCS
|
|
Rockfall Crash
|
|
Rockfall II Crash
|
|
Roulette Oxford Computer Publishing
|
|
Sexy Black Jack Load 'n' Run [Ita]
|
|
Shark Attack Romik Software
|
|
Skelby - The Schizophrenic Droid Q Bit
|
|
Spectrum Voice Chess Artic Computing Ltd
|
|
Spiders Web Thor Computer Software
|
|
Sport of Kings Mastertronic Added Dimension
|
|
Spyship SOS Dynamic Software
|
|
Starbike The Edge Software
|
|
Steve Davis Snooker CDS Microsystems
|
|
Terrahawks CRL Group PLC
|
|
Timebomb CDS Microsystems
|
|
Time Machine, The Digital Fantasia
|
|
Titanic R&R Software Ltd
|
|
Twin Kingdom Valley Bug-Byte Software Ltd
|
|
War of the Worlds, The CRL Group PLC
|
|
Xavior PSS
|
|
Zepherus National Software Library
|
|
Zig Zag DK'Tronics Ltd
|
|
Not verified if the above list is correct (Spectrum Voice Chess seems to be
|
|
wrong, versions that support ULA and Fuller speech do exist, but there seems to
|
|
be no Currah version).
|
|
|
|
Spectrum Sound Speech I/O Ports
|
|
-------------------------------
|
|
|
|
xx9Fh - Fuller Orator / Fuller Box Master Unit - Speech Output (W)
|
|
0-5 SP0256-AL2 Allophone number
|
|
6-7 Unknown
|
|
|
|
xxBFh - Fuller Orator / Fuller Box Master Unit - Speech Status (R)
|
|
0-6 Unknown
|
|
7 Load Request (LRQ) (0=Buffer full, 1=Ready to receive data)
|
|
|
|
007Fh - DK'Tronics Speech Synthesiser - Speech Output (W)
|
|
0-5 SP0256-AL2 Allophone number
|
|
6-7 Unknown
|
|
|
|
007Fh - DK'Tronics Speech Synthesiser - Speech Status (R)
|
|
0-6 Unknown
|
|
7 Load Request (LRQ) (0=Ready to receive data, 1=Not ready)
|
|
|
|
DK'Tronics Speech Synthesiser - Software Driver
|
|
The DK'Tronics hardware doesn't include a BIOS/BASIC extension ROM, but, the
|
|
BASIC demonstration program includes a machine code driver, which allows the
|
|
LPRINT command with backslash to be used to output speech, eg.:
|
|
LPRINT "\d k tronics"
|
|
LPRINT "print this\speak this"
|
|
the DK'Tronics driver does attempt to properly pronounce words automatically,
|
|
without needing to use special codes like (aa) (dth) as used by Currah.
|
|
|
|
0007h - Cheetah Sweet Talker - Speech Output (halts CPU) (W)
|
|
0-5 SP0256-AL2 Allophone number
|
|
6-7 Unknown
|
|
This poor piece of hardware doesn't seem to have a status register that
|
|
indicates when new data can be sent, instead, it does simply HALT the CPU when
|
|
speech is busy. Not sure if halting is bound to the SBY or /LRQ pin (?) (in the
|
|
latter case one could still execute some program code when implementing complex
|
|
timings in software).
|
|
|
|
Read from Memory Address 0038h - Enable/Disable Currah uSpeech BIOS
|
|
Reading from this memory address enables/disables the 2K uSpeech BIOS (and
|
|
probably also the uSpeech command/status register), ie. on each second read it
|
|
gets enabled (at 0000h..07FFh), on each other read it gets disabled.
|
|
0-7 Data/Opcode from the (newly) activated ROM
|
|
Usually the enable takes place when the CPU jumps to the vblank IRQ handler at
|
|
0038h, which is then redirected to the uSpeech BIOS, which does then do it's
|
|
job, and jumps to 0038h, which re-enables the Spectrum BIOS and executes the
|
|
normal IRQ handler.
|
|
There are no further BIOS hooks; initialization (upon reset) is also done from
|
|
inside of the hooked IRQ handler.
|
|
|
|
Read from Memory Address 1000h - Currah uSpeech Status (R)
|
|
This port is probably accessible only when enabled via address 0038h.
|
|
0 Load Request (LRQ) (1=Buffer full, 0=Ready to receive data)
|
|
1-7 Unknown/unused
|
|
Bit0 seems to be the /LRQ pin of the SP0256 chip. Unknown if the SBY pin
|
|
(indicating when all data is finished) is also found in this register?
|
|
The size of the buffer is unknown, maybe it can only hold only a single value
|
|
(additionally to the sound being currently played)...?
|
|
|
|
Write to Memory Address 1000h - Currah uSpeech Output (W)
|
|
This port is probably accessible only when enabled via address 0038h.
|
|
0-5 SP0256-AL2 Allophone Number (00h..3Fh)
|
|
6 Intonation (0=Decrease Pitch, 1=Increase Pitch)
|
|
7 Unknown/unused (should be zero)
|
|
Data can be written to this register when the Status.Bit0 indicates ready (not
|
|
sure happens when it doesn't). The last allophone should be followed by a pause
|
|
(eg. 00h=Pause10ms), otherwise the SP0256 does reportedly gets stuck repeating
|
|
the last allophone (not sure what gets repeated exactly, maybe it repeats only
|
|
the end of the last allophone, ie. "shhhhhhh" for "sh", or maybe the whole last
|
|
allophone, ie. "shshshsh"?)
|
|
The intonation bit seems to be a special feature of the Currah hardware (not a
|
|
feature of the SP0256 voice chip itself). Unknown how it is implemented... it
|
|
might modify the CLK passed to the SP0256... so, aside from the frequency, this
|
|
would also alter the durations, ie. the length of a "100ms" pause would vary...
|
|
or it might modify whatever kind of external low-pass and/or high-pass
|
|
filter...? The intonation does increase step-by-step (rather than changing
|
|
abruptly from low to high)... the stepping rate, and the max/min values are
|
|
unknown?
|
|
|
|
Currah uSpeech Mirrors of 0038h and 1000h and ROM
|
|
Reads from memory address 0038h are also mirrored to reads from I/O address
|
|
0038h (used by Rockfall to detect the uSpeech), apparently the port is decoded
|
|
by checking only A0..A15 and /RD.
|
|
For address 1000h it's still unknown if there are mirrors, possibly, only /RD,
|
|
/WR, A12, A14, A15 are decoded (probably together with the uSpeech BIOS enable
|
|
flag which gets set/cleared via 0038h); if so, mirrors would occur at
|
|
1000h-1FFFh and 3000h-3FFFh in both memory and I/O region? If so, using the I/O
|
|
mirrors would be not too recommended since they could conflict with other
|
|
internal/external I/O ports.
|
|
For the ROM it's unknown if it's mirrored, too. Might be mirrored to 800h..FFFh
|
|
and 2000h-2FFFh?
|
|
|
|
Currah uSpeech BIOS/BASIC extension
|
|
Unlike most or all other speech devices, the Currah hardware includes a BIOS
|
|
extension. Currah related BASIC commands are:
|
|
LET keys=0 ;disable spoken keystrokes (recommended for LOAD/SAVE)
|
|
LET keys=1 ;enable spoken keystrokes (default)
|
|
LET s$="he(ll)(oo)" ;say hello (normal lowercase)
|
|
LET s$="hE(ll)(oO)" ;say hello (with raised intonation on "e" and "(oo)")
|
|
PAUSE 1 ;wait for Vblank IRQ (where s$ is processed)
|
|
CLEAR n ;change RAMTOP (speech buffer is between RAMTOP and UDG)
|
|
IF PEEK(65364)=81 ;buffer pointer LSB, [FF54h]=51h=buffer_empty (on 48K)
|
|
IF s$(TO 1)="*" ;check if s$ was processed (copied to speech buffer)
|
|
IF s$(TO 1)="?" ;check if s$ was rejected (contained invalid characters)
|
|
IF s$(TO 1)=other ;check if s$ was not yet processed (or buffer full)
|
|
On power up, the Currah BIOS allocates 256 bytes between RAMTOP and UDG,
|
|
containing a 6-byte "header", and a 250-byte buffer; which contains allophone
|
|
numbers (and intonation flag in bit6), in the format as written to address to
|
|
1000h (ie. not in ASCII format as used in the BASIC s$ variable). On the
|
|
Spectrum this region is at FFxxh (on Spectrum 16K it's at 7Fxxh):
|
|
FF57h - Flag byte
|
|
FF56h - Spare (unused general purpose byte; NOT reserved for anything)
|
|
FF55h - Hi byte of buffer pointer ;\contains FF51h when empty
|
|
FF54h - Lo byte of buffer pointer ;/
|
|
FF53h - Spare (unused general purpose byte; NOT reserved for anything)
|
|
FF52h - Spare (unused general purpose byte; NOT reserved for anything)
|
|
FF51h..FE58h - Speech buffer (default size=250) [FF51h]=next allophone
|
|
In BASIC, the spoken keystrokes and s$ strings are good for a first "oh it does
|
|
really speak" impression, although after soon, the keystroke feature may become
|
|
annoying, and the automatic modification of the first character in s$ may cause
|
|
compatibility problems with various BASIC programs that do use s$ for other
|
|
purposes.
|
|
Moreover, allocating 256 bytes between RAMTOP and UDG may cause problems with
|
|
many machine code programs. And, hooking the IRQ handler changes Vblank
|
|
handling timings which may also cause problems with a few programs.
|
|
|
|
Spectrum Sound Speech SP0256 Voice Generator
|
|
--------------------------------------------
|
|
|
|
Voice Generator
|
|
The voice generator relies on the Amplitude, Pitch, F0..F5, and B0..B5
|
|
registers, which are processed like so:
|
|
Amplitude --> F0 --> F1 --> F2 --> F3 --> F4 --> F5 --> PWM --> External
|
|
Pitch/Noise B0 B1 B2 B3 B4 B5 5kHz Filter
|
|
Another important register is the Repeat counter, which indicates when the next
|
|
opcode shall be executed (and which may then load new values into the above
|
|
registers).
|
|
|
|
Sample Rate and Repeat Timings
|
|
The SP0256 is (usually) driven by a 3.12MHz oscillator, and it uses 7bit PWM
|
|
output, which is clocked at 3.12MHz/2. To obtain a 10kHz sample rate, the chip
|
|
issues some dummy steps with constant LOW level additionally to the 128 steps
|
|
needed for 7bit PWM, making it a total number of 156 steps per sample.
|
|
Sample Rate = 3.12MHz/2/156 = 10.0kHz ;100us per sample
|
|
Which means one sample is 100us long, that value multiplied by 64 or 91 gives
|
|
the following timings per repeat:
|
|
6.4ms per repeat (noise and pause), or
|
|
9.1ms per repeat (tone with pitch=91)
|
|
Note: Some speech interfaces have the chip overclocked to 4MHz, resulting in
|
|
higher pitch & sample rate, and shorter timings as with the normal 3.12MHz.
|
|
|
|
Amplitude/Pitch/Repeat
|
|
The 8bit amplitude register defines the volume in floating point form,
|
|
Amplitude = lower5bit SHL upper3bit
|
|
The pitch defines the frequency, counted in numbers of samples per period.
|
|
For pitch=91, one HIGH sample (amplitude) is output, followed by 90 zero
|
|
samples (null). That pattern is repeated as many times as specified in the
|
|
repeat count, for example, with repeat=3:
|
|
__ Amplitude level (+)
|
|
| | |
|
|
|________|________|________ __ Zero level PITCH
|
|
|
|
<-Pitch-> __ Amplitude level (-)
|
|
<--------repeat=3--------->
|
|
As shown above, the generated waveform is NOT a square wave (which would have
|
|
50% high, and 50% low). After applying filters, the final waveform may look
|
|
somewhat like so:
|
|
__ Amplitude level (+)
|
|
| | |
|
|
|_|_.____|_|_.____|_|_.____ __ Zero level PITCH+FILTERS
|
|
| | | | | |
|
|
| | | __ Amplitude level (-)
|
|
Note that (aside from noise) the AL2 ROM uses only one pitch value: 5Bh aka 91
|
|
decimal (meaning that all vowels are using the same base frequency, and they
|
|
differ only by using different filter settings).
|
|
|
|
Amplitude/Noise/Repeat
|
|
Noise is activated when setting pitch=0. The timings are then same as when
|
|
pitch=64, but instead of outputting HIGH and NULL levels, the hardware does now
|
|
randomly output HIGH or LOW levels, for example, pitch=0 and repeat=5:
|
|
__ Amplitude level (+)
|
|
||| || | | | || | || ||| |
|
|
|||_|| |__|_|__||_|___|| |||_| __ Zero level NOISE
|
|
| | || | || | ||| | |
|
|
<-64->| || | || | ||| | | __ Amplitude level (-)
|
|
<----------repeat=5---------->
|
|
The exact random algorithm is unknown (probably some shift/xor stuff?), the
|
|
random levels seem to be output on each sample (not only on the first sample of
|
|
a repeat). Like normal pitch, the noise is passed to the 6 filters.
|
|
|
|
Pause/Repeat
|
|
The pause command sets amplitude=0. The timings are then same as when pitch=64,
|
|
but the output is always NULL, for example, pause and repeat=5:
|
|
__ Amplitude level (+)
|
|
|
|
______________________________ __ Zero level PAUSE (SILENCE)
|
|
|
|
<-64-> __ Amplitude level (-)
|
|
<----------repeat=5---------->
|
|
Pause does reset the filters to 0, so the silence is not affected by filters.
|
|
|
|
Digital Filters
|
|
As shown above, the amplitude/pitch/noise output is passed through six digital
|
|
filter stages (using the F0..F5 and B0..B5 registers), each stage looks like
|
|
so:
|
|
_____ _____
|
|
------------------>| |------------------->| |-----+----->
|
|
_____ | SUB | ______ | SUB | |
|
|
+--->| *B |--->|_____| +--->| *2*F |-->|_____| |
|
|
| |_____| _____ | |______| _____ |
|
|
+---------------|OLDER|<---+---------------| OLD |<----+
|
|
|_____| |_____|
|
|
Ie. the incoming samples are adjusted like so:
|
|
for i=0 to 5 ;filter number
|
|
sample = sample - quant_table[F.i] * OLD.i * 2 ;F0..F5 registers
|
|
sample = sample - quant_table[B.i] * OLDER.i ;B0..B5 registers
|
|
OLDER.i = OLD.i
|
|
OLD.i = sample
|
|
next i
|
|
Whereas, quant_table is a non-linear translation table that translates the
|
|
signed 8bit registers to signed 10bit factors (with 9bit fractional part, ie.
|
|
511 means 0.99), with following entries:
|
|
0 ,9 ,17 ,25 ,33 ,41 ,49 ,57 ,65 ,73 ,81 ,89 ,97 ,105,113,121
|
|
129,137,145,153,161,169,177,185,193,201,209,217,225,233,241,249
|
|
257,265,273,281,289,297,301,305,309,313,317,321,325,329,333,337
|
|
341,345,349,353,357,361,365,369,373,377,381,385,389,393,397,401
|
|
405,409,413,417,421,425,427,429,431,433,435,437,439,441,443,445
|
|
447,449,451,453,455,457,459,461,463,465,467,469,471,473,475,477
|
|
479,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495
|
|
496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511
|
|
Above shows only positive values for index 0..127. Values for index -1..-128
|
|
should be 0..-511, or maybe -9..-512.
|
|
|
|
Spectrum Sound Speech SP0256 Instruction Set
|
|
--------------------------------------------
|
|
|
|
Memory
|
|
The SP0256 can address 60Kbytes (480Kbits) of internal or external ROM,
|
|
however, usally the ROMs are only 2Kbytes (16Kbit). The ROM contains plain
|
|
program code, without any kind of data arrays.
|
|
The upper 4bit of the program counter cannot be zero, so the memory starts at
|
|
byte-address 1000h, and ends at FFFFh. The first 512 bytes are entrypoints,
|
|
usually containing JUMP opcodes for up to 256 allophones or words.
|
|
The opcodes and their parameters are transferred serially, LSB first (except,
|
|
for some reason, the JUMP/CALL/SETPAGE "Target" values are MSB first).
|
|
The JUMP/CALL/RET opcodes can address only byte-aligned addresses, however,
|
|
opcodes aren't always multiples of 8bits in size, so following opcodes may
|
|
begin on any bit boundary.
|
|
|
|
Opcode Summary
|
|
0000b SETPAGE/RET Set Page for JUMP/CALL, or Return from CALL
|
|
0001b SETMODE Set the MODE bits and Repeat MSBs
|
|
0010b LOAD_23 Load Pitch, Amplitude, 2-3 Coefficients
|
|
0011b LOAD_56 Load Pitch, Amplitude, 5-6 Coefficients
|
|
0100b LOAD_56D Load Pitch, Amplitude, 5-6 Coefficients, Delta
|
|
0101b SETMSB_3 Load Amplitude, MSBs of 3 Coefficients
|
|
0110b SETMSB_23 Load Amplitude, MSBs of 2 or 3 Coeffcients
|
|
0111b LOAD_PA Load Pitch, Amplitude
|
|
1000b LOAD_ALL Load All Parameters (at full 8bit precision)
|
|
1001b DELTA_56 Add Delta to Amplitude, Pitch, 5 or 6 Coefficients
|
|
1010b SETMSB_3P Load Amplitude, MSBs of 3 Coefficients, Pitch
|
|
1011b DELTA_23 Add Delta to Amplitude, Pitch, 2 or 3 Coefficients
|
|
1100b SETMSB_3D Load Amplitude, MSBs of 3 Coefficients, Delta
|
|
1101b CALL Jump to Subroutine (12-bit PAGE-Relative Address)
|
|
1110b JUMP Jump to 12-bit PAGE-Relative Address
|
|
1111b PAUSE Silent Pause
|
|
Each opcode starts with a 4bit parameter field, followed by the 4bit opcode
|
|
number, eventually followed by further Nbit parameter(s).
|
|
|
|
Opcode 1110b - JUMP - Jump to 12-bit PAGE-Relative Address
|
|
Opcode 1101b - CALL - Jump to Subroutine (12-bit PAGE-Relative Address)
|
|
4 Target bit8-11 (in reversed bit-order!)
|
|
4 Opcode (must be 1110b or 1101b)
|
|
8 Target bit0-7 (in reversed bit-order!)
|
|
0..7 Byte-alignment for next opcode (should be padded with 0 bits)
|
|
Jumps to the specified memory address, Target bit12-15 are taken from the PAGE
|
|
register (which is usually 01h, set like so on power up, but can be set to
|
|
other values in range 01h..0Fh via SETPAGE).
|
|
CALL pushes the 16bit byte-aligned return address onto stack, and marks the
|
|
stack as not empty. The previous contents of the stack are lost (the stack is
|
|
only one entry deep).
|
|
|
|
Opcode 0000b with Zero-Operand - RET - Return from Subroutine (or HALT)
|
|
4 Zero for RET (00h=Return)
|
|
4 Opcode (must be 0000b)
|
|
0..7 Byte-alignment for next opcode (should be padded with 0 bits)
|
|
If the stack was not empty: Jumps to the pushed return address (ie. to the next
|
|
byte after the most recent CALL opcode), and marks the stack as empty.
|
|
If the stack was already empty: Enters HALT state until/unless new data is/was
|
|
input via /ALD pin. As soon as new data is available, it jumps to 1000h+data*2.
|
|
Note: HALT state stops program execution, but does not stop the sound generator
|
|
- to obtain silence, issue a short PAUSE (or another opcode that sets
|
|
amplitude=0).
|
|
|
|
Opcode 0000b with Nonzero-Operand - SETPAGE - Set the PAGE register
|
|
4 Target bit12-15 (in reversed bit-order!) (01h..0Fh=Page)
|
|
The above target bits are used for ALL following JUMP/CALL opcodes
|
|
4 Opcode (must be 0000b)
|
|
The PAGE register retains its setting until the next SETPAGE is encountered.
|
|
(Note that address loads via ALD appear to ignore PAGE, and set the four MSBs
|
|
to $1000. They do not modify the PAGE register, so subsequent JUMP/CALL
|
|
instructions will jump relative to the current value in PAGE.)
|
|
|
|
Opcode 0001b - SETMODE - Set the MODE bits and Repeat MSBs
|
|
2 Repeat Count bit4-5 (expands the next ONE opcode that uses 4bit repeat)
|
|
1 WIDTH for ALL following opcodes (0=Smaller, 1=Bigger bit-width)
|
|
1 EXTRA for ALL following opcodes (0=Exclude, 1=Include optional params)
|
|
4 Opcode (must be 0001b)
|
|
Some opcodes have coefficient parameters of variable width (for example "3/6"
|
|
means 3bit or 6bit), the smaller width is used when WIDTH=0, the bigger when
|
|
WIDTH=1.
|
|
Some opcodes have optional parameters (for example "(8)" means an optional 8bit
|
|
parameter), which is included in the opcode only when EXTRA=1.
|
|
|
|
Opcode 1111b - PAUSE - Silent Pause
|
|
4 Repeat Count
|
|
4 Opcode (must be 1111b)
|
|
Provides a silent pause of varying length. The pause behaves identially to a
|
|
pitch with Amplitude=0 and Period=64. All coefficients are cleared, as well.
|
|
|
|
Opcode 0111b - LOAD_PA - Load Pitch, Amplitude
|
|
4 Repeat Count
|
|
4 Opcode (must be 0111b)
|
|
6 Amplitude MSBs (upper 3bit are exponent)
|
|
8 Pitch (00h=Noise)
|
|
|
|
Opcode 1000b - LOAD_ALL - Load All Parameters (at full 8bit precision)
|
|
4 Repeat Count
|
|
4 Opcode (must be 1000b)
|
|
8 Amplitude unsigned (upper 3bit are exponent)
|
|
8 Pitch unsigned (00h=Noise)
|
|
8 Coeff B0 signed ;\coeff pair 0
|
|
8 Coeff F0 signed ;/
|
|
8 Coeff B1 signed ;\coeff pair 1
|
|
8 Coeff F1 signed ;/
|
|
8 Coeff B2 signed ;\coeff pair 2
|
|
8 Coeff F2 signed ;/
|
|
8 Coeff B3 signed ;\coeff pair 3
|
|
8 Coeff F3 signed ;/
|
|
8 Coeff B4 signed ;\coeff pair 4
|
|
8 Coeff F4 signed ;/
|
|
8 Coeff B5 signed ;\coeff pair 5
|
|
8 Coeff F5 signed ;/
|
|
(8) Amplitude Interpolation, signed ;\when EXTRA=1 only
|
|
(8) Pitch Interpolation, signed ;/
|
|
Notes: The pitch and amplitude deltas that are available when EXTRA=1 are
|
|
applied every pitch period, not just once. Wraparound may occur. If the Pitch
|
|
goes to zero, the periodic excitation switches to noise.
|
|
|
|
Opcode 0010b - LOAD_23 - Load Pitch, Amplitude, 2-3 Coefficients
|
|
Opcode 0011b - LOAD_56 - Load Pitch, Amplitude, 5-6 Coefficients
|
|
Opcode 0100b - LOAD_56D - Load Pitch, Amplitude, 5-6 Coefficients, Delta
|
|
4 Repeat Count
|
|
4 Opcode (must be 0010b or 0011b or 0100b)
|
|
6 Amplitude MSBs (upper 3bit are exponent)
|
|
8 Pitch (00h=Noise)
|
|
3/6 Coeff B0 Bit4/1..6 unsigned ;\coeff pair 0 ;\
|
|
5/6 Coeff F0 Bit3/2..7 signed ;/ ;
|
|
3/6 Coeff B1 Bit4/1..6 unsigned ;\coeff pair 1 ; opcode LOAD_56D,
|
|
5/6 Coeff F1 Bit3/2..7 signed ;/ ; and LOAD_56 only
|
|
3/6 Coeff B2 Bit4/1..6 unsigned ;\coeff pair 2 ;
|
|
5/6 Coeff F2 Bit3/2..7 signed ;/ ;/
|
|
4/6 Coeff B3 Bit3/1..6 unsigned ;\coeff pair 3
|
|
6/7 Coeff F3 Bit2/1..7 signed ;/
|
|
7/8 Coeff B4 Bit1/0..7 signed ;\coeff pair 4
|
|
6/8 Coeff F4 Bit2/0..7 signed ;/
|
|
(8) Coeff B5 Bit0..7 signed ;\coeff pair 5 ;\when EXTRA=1 only
|
|
(8) Coeff F5 Bit0..7 signed ;/ ;/
|
|
5 Amplitude Interpolation LSBs, unsigned ;\opcode LOAD_56D only
|
|
5 Pitch Interpolation LSBs, unsigned ;/
|
|
Sets the unspecified coefficients to 0. The "unsigned" B0,B1,B2,B3 values are
|
|
zero-expanded from N bits to (N+1) bits, and are then copied to the upper (N+1)
|
|
bits of the register.
|
|
|
|
Opcode 0110b - SETMSB_23 - Load Amplitude, MSBs of 2 or 3 Coeffcients
|
|
Opcode 0101b - SETMSB_3 - Load Amplitude, MSBs of 3 Coefficients
|
|
Opcode 1010b - SETMSB_3P - Load Amplitude, MSBs of 3 Coefficients, Pitch
|
|
Opcode 1100b - SETMSB_3D - Load Amplitude, MSBs of 3 Coefficients, Delta
|
|
4 Repeat Count
|
|
4 Opcode (must be 0101b or 0110b or 1010b or 1100b)
|
|
6 Amplitude MSBs (upper 3bit are exponent)
|
|
[8] Pitch (00h=Noise) ;-Opcode SETMSB_3P only
|
|
5/6 New F0 MSBs signed ;\
|
|
5/6 New F1 MSBs signed ; Opcode SETMSB_3/3P/3D only
|
|
5/6 New F2 MSBs signed ;/
|
|
6/7 New F3 MSBs signed ;\
|
|
6/8 New F4 MSBs signed ; Opcode SETMSB_23 only
|
|
(8) New F5 MSBs signed (when EXTRA=1 only) ;/
|
|
(0) Set F5=0 and B5=0 (when EXTRA=0 only)
|
|
[5] Amplitude Interpolation LSBs, unsigned ;\Opcode SETMSB_3D only
|
|
[5] Pitch Interpolation LSBs, unsigned ;/
|
|
All other coefficient bits are unaffected (ie. all coefficients that aren't
|
|
accessed by the specific opcode, as well as LSBs of accessed coefficients).
|
|
|
|
Opcode 1001b - DELTA_56 - Add Delta to Amplitude, Pitch, 5 or 6 Coefficients
|
|
Opcode 1011b - DELTA_23 - Add Delta to Amplitude, Pitch, 2 or 3 Coefficients
|
|
4 Repeat Count
|
|
4 Opcode (must be 1001b or 1011b)
|
|
4 Amplitude Interpolation 6 MSBs signed
|
|
5 Pitch Interpolation LSBs signed
|
|
3/4 B0 4,7 MSBs signed ;\ ;\
|
|
3/4 F0 5,6 MSBs signed ;/ ;
|
|
3/4 B1 4,7 MSBs signed ;\ ; opcode DELTA_56 only
|
|
3/4 F1 5,6 MSBs signed ;/ ;
|
|
3/4 B2 4,7 MSBs signed ;\ ;
|
|
3/4 F2 5,6 MSBs signed ;/ ;/
|
|
3/4 B3 5,7 MSBs signed ;\
|
|
4/5 F3 6,7 MSBs signed ;/
|
|
4/5 B4 x,8 MSBs signed ;\ <---- DELTA_56: x=6, and DELTA_23: x=7 (?)
|
|
4/5 F4 6,8 MSBs signed ;/
|
|
(5) B5 (8) MSBs signed ;\ ;\when EXTRA=1 only
|
|
(5) F5 (8) MSBs signed ;/ ;/
|
|
Performs a delta update, adding small 2s complement numbers to a series of
|
|
coefficients. The 2s complement updates for the various filter coefficients
|
|
only update some of the MSBs -- the LSBs are unaffected. The exact bits which
|
|
are updated are noted above.
|
|
Normal 2s complement arithmetic is performed, and no protection is provided
|
|
against overflow. Adding 1 to the largest value for a bit field wraps around to
|
|
the smallest value for that bitfield.
|
|
Notes: The delta update is applied only once (even if the repeat count is
|
|
bigger than 1).
|
|
The delta updates are applied to the 8-bit encoded forms of the coefficients,
|
|
not the 10-bit decoded forms.
|
|
The update to the amplitude register is a normal 2s complement update to the
|
|
entire register. This means that any carry/borrow from the mantissa will change
|
|
the value of the exponent. The update doesn't know anything about the format of
|
|
that register.
|
|
|
|
Program Counter and Stack Note
|
|
As seen in the datasheets for external speech ROMs, the Program Counter & Stack
|
|
seem to be part of the ROM (not of the microprocessor). So, when using external
|
|
ROMs, one would theoretically have separate stacks for each ROM. NB. this
|
|
explains why the Target values are reversed; apparently the ROMs use different
|
|
bit-order (for memory addresses) than the microprocessor does for its own
|
|
values (ie. the opcodes and voice-parameters).
|
|
|
|
Credits
|
|
The SP0256 opcodes were reverse engineered by Joe Zbiciak and Frank Palazzolo.
|
|
|
|
Repeat Count = 0
|
|
According to Joe and Frank, a repeat count of zero "causes the instruction to
|
|
not execute" (and not to fetch any of its following paramters, so the opcode
|
|
becomes only 8bits long; or to fetch, but not apply them?), however, they've
|
|
also mentioned that "conflicting documentation suggests there's more going on".
|
|
|
|
XXX...
|
|
Bit fields narrower than 8 bits are MSB justified unless specified otherwise,
|
|
meaning that the least significant bits are the ones that are missing. These
|
|
LSBs are filled with zeros.
|
|
|
|
When updating filter coefficients with a delta-update, the microsequencer
|
|
performs plain 2s-complement arithmetic on the 8-bit value in the coefficient
|
|
register file. No attention is paid to the format of the register.
|
|
|
|
Spectrum Sound Speech SP0256 Allophones/Words
|
|
---------------------------------------------
|
|
|
|
SP0256-AL2 Allophone List
|
|
Num Name Example Funny Actual Num Name Example Funny Actual
|
|
00h PA1 PAUSE 10ms 6.4ms 20h /AW/ Out 370ms 254.8ms
|
|
01h PA2 PAUSE 30ms 25.6ms 21h /DD2/ Do 160ms 72.1ms
|
|
02h PA3 PAUSE 50ms 44.8ms 22h /GG3/ Wig 140ms 110.5ms
|
|
03h PA4 PAUSE 100ms 96.0ms 23h /VV/ Vest 190ms 127.4ms
|
|
04h PA5 PAUSE 200ms 198.4ms 24h /GG1/ Got 80ms 72.1ms
|
|
05h /OY/ Boy 420ms 291.2ms 25h /SH/ Ship 160ms 198.4ms
|
|
06h /AY/ Sky 260ms 172.9ms 26h /ZH/ Azure 190ms 134.1ms
|
|
07h /EH/ End 70ms 54.6ms 27h /RR2/ Brain 120ms 81.9ms
|
|
08h /KK3/ Comb 120ms 76.8ms 28h /FF/ Food 150ms 108.8ms
|
|
09h /PP/ Pow 210ms 147.2ms 29h /KK2/ Sky 190ms 134.4ms
|
|
0Ah /JH/ Dodge 140ms 98.4ms 2Ah /KK1/ Can't 160ms 115.2ms
|
|
0Bh /NN1/ Thin 140ms 172.9ms 2Bh /ZZ/ Zoo 210ms 148.6ms
|
|
0Ch /IH/ Sit 70ms 45.5ms 2Ch /NG/ Anchor 220ms 200.2ms
|
|
0Dh /TT2/ To 140ms 96.0ms 2Dh /LL/ Lake 110ms 81.9ms
|
|
0Eh /RR1/ Rural 170ms 127.4ms 2Eh /WW/ Wool 180ms 145.6ms
|
|
0Fh /AX/ Succeed 70ms 54.6ms 2Fh /XR/ Repair 360ms 245.7ms
|
|
10h /MM/ Milk 180ms 182.0ms 30h /WH/ Whig 200ms 145.2ms
|
|
11h /TT1/ Part 100ms 76.8ms 31h /YY1/ Yes 130ms 91.0ms
|
|
12h /DH1/ They 290ms 136.5ms 32h /CH/ Church 190ms 147.2ms
|
|
13h /IY/ See 250ms 172.9ms 33h /ER1/ Letter 160ms 109.2ms
|
|
14h /EY/ Beige 280ms 200.2ms 34h /ER2/ Fir 300ms 209.3ms
|
|
15h /DD1/ Could 70ms 45.5ms 35h /OW/ Beau 240ms 172.9ms
|
|
16h /UW1/ To 100ms 63.7ms 36h /DH2/ Bath 240ms 182.0ms
|
|
17h /AO/ Aught 100ms 72.8ms 37h /SS/ Vest 90ms 64.0ms
|
|
18h /AA/ Hot 100ms 63.7ms 38h /NN2/ No 190ms 136.5ms
|
|
19h /YY2/ Yes 180ms 127.4ms 39h /HH2/ Hoe 180ms 126.0ms
|
|
1Ah /AE/ Hat 120ms 81.9ms 3Ah /OR/ Store 330ms 236.6ms
|
|
1Bh /HH1/ He 130ms 89.6ms 3Bh /AR/ Alarm 290ms 200.2ms
|
|
1Ch /BB1/ Business 80ms 36.4ms 3Ch /YR/ Clear 350ms 245.7ms
|
|
1Dh /TH/ Thin 180ms 128.0ms 3Dh /GG2/ Guest 40ms 69.4ms
|
|
1Eh /UH/ Book 100ms 72.8ms 3Eh /EL/ Saddle 190ms 136.5ms
|
|
1Fh /UW2/ Food 260ms 172.9ms 3Fh /BB2/ Business 50ms 50.2ms
|
|
Mind that completion of an allophone doesn't mute the voice generator (it'll
|
|
keep repeating the end of the allophone until receiving a new allophone). To
|
|
mute the voice generator, output a short pause (eg. PA1) after your last
|
|
allophone.
|
|
The "Funny" timings are from the SP0256-AL2 data sheet (these values are
|
|
totally wrong). The "Actual" timings are calculated from the pitch/repeat
|
|
values in the AL2 ROM (these values should be 100% correct, when clocked at
|
|
3.12MHz).
|
|
<--------------- Currah Codes --------------->
|
|
Num ASCII Num ASCII Num ASCII Num ASCII
|
|
18h a 27h r 14h (aa)/(ay) 29h (ck)
|
|
1Ch b 37h s 13h (ee) 3Ch (ear)
|
|
08h c 11h t 06h (ii) 1Ah (eh)
|
|
15h d 0Fh u 35h (oo)/(eau) 33h (er)
|
|
07h e 23h v 3Fh (bb) 34h (err)
|
|
28h f 2Eh w 21h (dd) 2Ch (ng)
|
|
24h g - x "ks" 3Dh (gg) 3Ah (or)
|
|
1Bh h 31h y 22h (ggg) 16h (ou)
|
|
0Ch i 2Bh z 39h (hh) 1Fh (ouu)
|
|
0Ah j 3Eh (ii) 20h (ow)
|
|
2Ah k 36h N/A 38h (nn) 05h (oy)
|
|
2Dh l 00h EOL 0Eh (rr) 25h (sh)
|
|
10h m 01h ' 0Dh (tt) 1Dh (th)
|
|
0Bh n 02h N/A 19h (yy) 12h (dth)
|
|
17h o 03h SPACE 3Bh (ar) 1Eh (uh)
|
|
09h p 04h , 2Fh (aer) 30h (wh)
|
|
- q "kw" 04hx2 . 32h (ch) 21h (zh)
|
|
|
|
Other Allophone/Word Sets
|
|
For curiosity, below are some other SP0256-xx variants (none of the known
|
|
Spectrum devices is using that variants though).
|
|
|
|
SP0256-012 Word List
|
|
This chip is used in the "Intellivoice" expansion module for Mattel's
|
|
Intellivision.
|
|
00h (SPB640 08h One 14h Thirteen 20h Seventy
|
|
Speech 09h Two 15h Fourteen 21h Eighty
|
|
FIFO) 0Ah Three 16h Fifteen 22h Ninety
|
|
01h pause4 0Bh Four 17h Sixteen 23h Hundred
|
|
02h pause3 0Ch Five 18h Seventeen 24h Thousand
|
|
03h pause2 0Dh Six 19h Eighteen 25h -teen
|
|
04h pause1 0Eh Seven 1Ah Nineteen 26h -ty
|
|
05h pause0 0Fh Eight 1Bh Twenty 27h Press
|
|
06h "Mattel 10h Nine 1Ch Thirty 28h Enter
|
|
Electronics 11h Ten 1Dh Fourty 29h Or
|
|
Presents" 12h Eleven 1Eh Fifty 2Ah And
|
|
07h Zero 13h Twelve 1Fh Sixty
|
|
There isn't much known about the SPB640 FIFO, as far as I understand, it does
|
|
have three functions: It can hold up to 64 word/allophone numbers (to be
|
|
injected to A1..A8 pins of the SP0256), it can hold opcodes/parameters (to be
|
|
injected to SER IN pin of the SP0256), and it includes a general purpose I/O
|
|
port.
|
|
|
|
SP0256-017 Word List
|
|
00h Oh 09h Nine 12h Eighteen 1Bh Hour
|
|
01h One 0Ah Ten 13h Nineteen 1Ch Minute
|
|
02h Two 0Bh Eleven 14h Twenty 1Dh Hundred Hour
|
|
03h Three 0Ch Twelve 15h Thirty 1Eh Good Morning
|
|
04h Four 0Dh Thirteen 16h Forty 1Fh Attention Please
|
|
05h Five 0Eh Fourteen 17h Fifty 20h Please Hurry
|
|
06h Six 0Fh Fifteen 18h It is 21h Melody A
|
|
07h Seven 10h Sixteen 19h A.M. 22h Melody B
|
|
08h Eight 11h Seventeen 1Ah P.M. 23h Melody C
|
|
|
|
SP0256-019 (or rather SP0256B-019) Allophone/Word/Phrase List
|
|
This chip is used in "The Voice", an expansion module for the Odyssey 2. The
|
|
chip contains the following allophones and words:
|
|
80h..BFh Allophones (same as 00h..3Fh on SP0256-AL2) C0h "Enemy"
|
|
C1h "All clear" C2h "Please" C3h "Get off" C4h "Open fire"
|
|
C5h "Watch out" C6h "Mercy" C7h "Hit it" C8h "You blew it"
|
|
C9h "Do it again" CAh "Incredible" FAh "U.F.O." FBh "Monster!"
|
|
Not sure why bit7 is set in the codes (it should be written like so to the O2
|
|
I/O ports, but maybe the bit isn't actually passed to the SP0256 chip)?
|
|
Additionally, the expansion module contains 3 built-in speech ROMs with sound
|
|
effects and various words/phrases like "Amazing", "Come on", "Outch", etc.
|
|
Moreover, Odyssey 2 game cartridges can contain up to 5 external speech ROMs.
|
|
For details see "Odyssey 2 Technical Specs" from Daniel Boris.
|
|
|
|
Spectrum Sound Speech SP0256 Pin-Outs
|
|
-------------------------------------
|
|
|
|
SP0256 - Speech chip
|
|
1 GND
|
|
2 /RESET
|
|
3 ROM DISABLE
|
|
4 C1
|
|
5 C2
|
|
6 C3
|
|
7 VCC1
|
|
8 SBY
|
|
9 /LRQ
|
|
10 A8
|
|
11 A7
|
|
12 SER OUT
|
|
13 A6
|
|
14 A5
|
|
15 A4
|
|
16 A3
|
|
17 A2
|
|
18 A1
|
|
19 SE
|
|
20 /ALD
|
|
21 SER IN
|
|
22 TEST
|
|
23 VCC2
|
|
24 PWM OUT
|
|
25 /SBY RESET
|
|
26 ROM CLK
|
|
27 OSC1
|
|
28 OSC2
|
|
The oscillator should be 3.12MHz
|
|
Allows to output sounds up to 5kHz (ie. the output is updated at 10kHz rate).
|
|
The SP0256 is reportedly expandable to "491 K of ROM" (probably bullshit).
|
|
The SP0256B is reportedly expandable to "480 K of ROM" (probably K=Kbits).
|
|
The TEST pin of the SP0256 chip can be used (among others) to dump its internal
|
|
ROM. Note: Details on TEST are found in the "SP0256B" datasheet - but not in
|
|
the "SP0256" datasheet - not sure if the pin works identical for both chip
|
|
types, nor if there's a difference between them at all.
|
|
|
|
SPR16 (16kbit) and SPR32 (32kbit) - External Serial-bus Speech ROM
|
|
1 GND
|
|
2 C3
|
|
3 NC
|
|
4 ROM CLK
|
|
5..6 NC
|
|
7 CS1
|
|
8 /CS2
|
|
9 /ROM ENABLE
|
|
10 SERIAL OUT
|
|
11 VCC
|
|
12..13 NC
|
|
14 SERIAL IN
|
|
15 C1
|
|
16 C2
|
|
|
|
SPR128 (128kbit) - External Serial-bus Speech ROM
|
|
1 GND
|
|
2 C3
|
|
3 NC
|
|
4 ROM CLK
|
|
5..10 NC
|
|
11 CS1
|
|
12 /CS2
|
|
13 /ROM ENABLE
|
|
14 SERIAL OUT
|
|
15 VCC
|
|
16..21 NC
|
|
22 SERIAL IN
|
|
23 C1
|
|
24 C2
|
|
|
|
Spectrum Sound Digital Playback/Sampling
|
|
----------------------------------------
|
|
|
|
Cheetah Specdrum (Playback)
|
|
OUT DFh ;output unsigned sample data (80h=silence)
|
|
Advertised as Drum machine, although hardware-wise it's simply a general
|
|
purpose D/A playback device. Supported by the included SpecDrum software, and
|
|
by additional Afro Kit, Electro Kit, Latin Kit tapes. Functionally same as the
|
|
Cheetah Sound Sampler's playback, but using a different port address.
|
|
|
|
Latin/Electro/Afro-KitSideB --> OUTs to DF,FF,9F,BF
|
|
|
|
Cheetah - Sound Sampler (Playback/Recording)
|
|
OUT 7Fh ;write any data to start sampling (to be followed by delay)
|
|
IN BFh ;read sampled data (after OUT 7Fh)
|
|
OUT BFh ;output (unsigned?) sample data (write twice?)
|
|
Supported only by the included software. Functionally same as Datel's sampler,
|
|
but with port addresses BFh and 7Fh exchanged.
|
|
|
|
Datel - Digital Sound Sampler (Playback/Recording)
|
|
OUT BFh ;write any data to start sampling (to be followed by delay)
|
|
IN 7Fh ;read sampled data (after OUT BFh)
|
|
OUT 7Fh ;output (unsigned?) sample data (output)
|
|
Supported only by the included software. Functionally same as Cheetah's
|
|
sampler, but with port addresses BFh and 7Fh exchanged.
|
|
|
|
RAM Electronics - Music Machine (Playback/Recording/MIDI)
|
|
IN DFh ;dummy read to start sampling (followed by delay, and then IN BFh)
|
|
IN BFh ;read sampled data (unsigned, 80h=silence) (after IN DFh)
|
|
OUT 9Fh ;output 8bit unsigned sample data (80h=silence)
|
|
OUT 5Fh ;maybe MIDI (used 4 times with values 00h,01h) ;-INTERRUPT?
|
|
OUT FC7Fh ;maybe MIDI (used 5 times with values 03h,91h,31h,11h) ;\
|
|
OUT FD7Fh ;maybe MIDI (used 1 time with variable value) ; ACIA?
|
|
-- FE7Fh ;maybe MIDI (not used by existing software?) ;
|
|
IN FF7Fh ;maybe MIDI (used 1 time) ;/
|
|
Note: The Amstrad CPC version has these MIDI ports:
|
|
&F8E8(Write only) INTERUPT SEL Writing 01 to this port disables internal
|
|
Amstrad interrupts and replaces the IRQ signal from ACIA.
|
|
Writing 00 restores normality.
|
|
&F8EC(Write only) ACIA Control See 6850 ACIA chip for details
|
|
&F8ED(Write only) ACIA Data write See 6850 ACIA chip for details
|
|
&F8EE(Read only) ACIA Status See 6850 ACIA chip for details
|
|
&F8EF(Read only) ACIA Data read See 6850 ACIA chip for details
|
|
Supported only by the included software.
|
|
|
|
Spectrum Disc and Tape Drives
|
|
-----------------------------
|
|
|
|
Disc and Tape Overviews
|
|
--> Spectrum Disc and Tape Drive Summary
|
|
--> Spectrum Disc and Tape Commands
|
|
|
|
Standard Audio Cassette Drives
|
|
--> Spectrum Cassette
|
|
--> Spectrum Cassette TZX Format
|
|
|
|
Some other more or less popular Disc and Tape drives
|
|
--> Spectrum Interface 1 (Microdrive, Network, RS232)
|
|
--> Spectrum Disc Spectrum +3 Disc Controller (NEC uPD765)
|
|
--> Spectrum Disc Opus Discovery
|
|
--> Spectrum Disc Disciple and Plus D
|
|
--> Spectrum Disc Beta/BetaPlus/Beta128 Disk Interface (TRDOS)
|
|
XXX
|
|
x--> Spectrum Disc I/O Ports
|
|
x--> Spectrum Disc Formats
|
|
|
|
Disc Controllers
|
|
--> Spectrum Disc Controller (Western Digital WD177x)
|
|
--> Spectrum Disc Spectrum +3 Disc Controller (NEC uPD765)
|
|
--> Spectrum Disc Controller (Other)
|
|
|
|
Timex FDD Interface
|
|
The interface uses a logic circuit to page in the 4KB FDD ROM whenever there is
|
|
a call to 0x0000 or 0x0008 and page it out again whenever there is a call to
|
|
0x0604. When it is needed the FDD ROM is paged in at 0x0000 and 0x1000 and the
|
|
area 0x2000-0x3fff holds eight copies of 1K of RAM or four copies of 2K of RAM.
|
|
The disk drive is controlled by port 0xef
|
|
|
|
NMI Snapshot Button
|
|
Many disk interfaces have a NMI button, allowing to save a snapshot of the RAM
|
|
and CPU registers to disk. Since most spectrum programs are sold on cassettes,
|
|
this is a useful feature; allowing to "copy" the program to disk, it can be
|
|
also useful for saving game postition on disks in games that don't support
|
|
saving (or that only support saving to cassette).
|
|
|
|
Floppy I/O Ports
|
|
Interface Chip Type Cmd/Stat Track Sector Data Misc
|
|
MFT PlusD 1772 IO E3h EBh F3h FBh EFh,E7h,F7h
|
|
MFT Disciple 1772 IO 1Bh 5Bh 9Bh DBh 1Fh,3Bh,7Bh,BBh,FBh
|
|
Beta Disk 1793 IO 1Fh 3Fh 5Fh 7Fh FFh
|
|
Didaktik D80 ? IO 81h 83h 85h 87h 89h
|
|
JLO ? IO 8Fh 9Fh AFh BFh B7h
|
|
Putnik 1991 1772 IO F1h F3h F5h F7h DFh/1Fh
|
|
Putnik 1998 1772 IO 73h F3h 77h F7h DFh/1Fh
|
|
Opus Discovery 1770 MEM 2800h 2801h 2802h 2803h 3000h-3003h, IO:1Fh
|
|
Spectrum +3 765 IO N/A N/A N/A 3FFDh 2FFDh,1FFDh
|
|
IO: Accessed via IN/OUT opcodes, MEM: Accessed via LD opcodes (memory mapped).
|
|
The first 4 ports are used to access the disc controller.
|
|
The "Misc" port(s) can have various (non-standarized) purposes: Reading the
|
|
controllers DRQ or IRQ signal (not supported by all interfaces), outputting
|
|
Drive Select signals (or Drive Number), Motor enable (done automatically by
|
|
WD1770/WD1772), Side Select, and/or non-disk related add-ons like joysticks,
|
|
centronics ports, etc.
|
|
|
|
Stepping Compatible MotorOn Pin20
|
|
WD179x Slow No
|
|
WD1770 Slow Yes(Pin20) MO
|
|
WD1772 Faster Yes(Pin20) MO
|
|
WD1773 Slow WD1793 No END/RDY
|
|
The newer WD177x chips contain a digital data separator and write
|
|
precompensation circuitry (meaning that they require less external components
|
|
than the older WD179x chips).
|
|
|
|
28pin 177x Pinouts
|
|
1 /CS 28 INTRQ ->
|
|
2 R/W 27 DRQ ->
|
|
3 A0 26 /DDEN <- Double Density Enable
|
|
4 A1 25 /WRPT <-
|
|
5 D0 24 /IP <- Index Hole
|
|
6 D1 23 /TR00 <-
|
|
7 D2 22 WD Write Data ->
|
|
8 D3 21 WG Write Gate ->
|
|
9 D4 20 MO Motor On ->
|
|
10 D5 19 /RD Read Data <-
|
|
11 D6 18 CLK 8MHz <-
|
|
12 D7 17 SD Step-Direction ->
|
|
13 /RES 16 STEP Step ->
|
|
14 GND 15 +5V
|
|
|
|
40pin 179x Pinouts
|
|
...?
|
|
|
|
Putnik Port 1Fh/DFh (decoded via A5)
|
|
0-4 Kempston Joystick
|
|
5 Not used (always 0)
|
|
6 INTRQ (from FDC chip)
|
|
7 DRQ (from FDC chip)
|
|
The interface contains a manual side select switch. The interface doesn't
|
|
include a ROM, maybe it's intended to be used with a patched BASIC ROM, or
|
|
additional ROM cartridge, or with a boot cassette.
|
|
(Note: There's also a "Putnik RomSwitch" circuit, which uses Port A9h, probably
|
|
that's intended to be used in combination with the floppy circuit.)
|
|
|
|
IDE Interface I/O Ports
|
|
Type divIDE Vehmaa Vehmaa 1-Chip Putnik Putnik Putnik Putnik SAfri
|
|
ZXCF ZXATASP 8bitv1 8bitv2 16bitv1 16bitv2 16bit
|
|
Data &xxA3 &00BF &039F? &00EF &xx2B &00BF &xx69 &xx2B &xx59
|
|
Error &xxA7 &01BF &039F? &01EF &xx2F &01BF &xx79 &xx2F &xx5B
|
|
Count &xxAB &02BF &039F? &10EF &xx6B &10BF &xx6B &xx6B &xx5D
|
|
Sector &xxAF &03BF &039F? &11EF &xx6F &11BF &xx7B &xx6F &xx5F
|
|
CylinderLo &xxB3 &04BF &039F? &20EF &xxAB &20BF &xx6D &xxAB &xx79
|
|
CylinderHi &xxB7 &05BF &039F? &21EF &xxAF &21BF &xx7D &xxAF &xx7B
|
|
Drive &xxBB &06BF &039F? &30EF &xxEB &30BF &xx6F &xxEB &xx7D
|
|
Command &xxBF &07BF &039F? &31EF &xxEF &31BF &xx7F &xxEF &xx7F
|
|
DataLo &08BF &009F?
|
|
DataHi &09BF &019F?
|
|
Error &0EBF
|
|
AltStatus &0FBF
|
|
Control &xxE3
|
|
|
|
ROM selection
|
|
Type Vehmaa Vehmaa Putnik JGH Sinclair
|
|
ZXCF ZXATSP RomSwitch ROMBox Spectrum128
|
|
Range &00-&3F &00-&3F &00-&03 &00-&F0 &00-&10
|
|
Page ROM &10BF,n &029F,n &xxA9,n &xxFD,16*n &7FFD,16*n
|
|
ZX ROM &10BF,&80+x &xxFD,&10 &7FFD,&10
|
|
RESET ROM &00 &00 &03 &00 &00
|
|
|
|
|
|
Spectrum Disc and Tape Drive Summary
|
|
------------------------------------
|
|
|
|
The standard media for Spectrum software are regular Audio Cassettes. Instead
|
|
of supporting disk drives, Sinclair has focused on selling Microdrive
|
|
Cartridges as alternative media, until, finally Amstrad released an "official"
|
|
disk drive in the Spectrum +3. However, at that time third-party companies have
|
|
had already produced various disk drives, all incompatible with each other,
|
|
using different controllers, I/O ports, BIOSes, file systems, and different
|
|
physical dimensions (2.8", 3", 3.5", and 5.25").
|
|
|
|
Standard Audio Cassette Drives
|
|
Any standard data or audio Cassette Recorder connected to MIC/EAR sockets
|
|
Spectrum +2/+2A with internal cassette recorder
|
|
Challenge Research Ltd: Challenge Sprint (quad-speed "audio" cassette drive)
|
|
Challenge Research Ltd: Challenge Sprint Mk II (new: Interface 1 compatible)
|
|
Evesham Micro Centre: Doubler (external tape input for tape-to-tape copy)
|
|
Evesham Micro Centre: Doubler Mk II (new: more compatible with more tape decks)
|
|
|
|
Sequential Disk/Tape Drives
|
|
Sinclair Microdrive (endless tape drive) (85K..100K) (requires Interface 1)
|
|
Rotronics Wafadrive (endless tape drive) (16K, 64K, 128K)
|
|
Crescent Quick Disk (2.8" disk, with single spiral-track, 128K or 256K)
|
|
Triton Quick Disk (2.8" disk, with single spiral-track, 100K)
|
|
|
|
Floppy Disk Drives/Interfaces
|
|
Opus: Discovery (1985) (centronics, video out, kempston stick, intern 3.5" drv)
|
|
Opus: Spectra Disc Interface (1984) (centronics, external 3.5" or 5.25" drive)
|
|
Miles Gordon Technology: MGT Plus D Interface (for MGT Lifetime Drive) (1988)
|
|
Miles Gordon Technology/Rockford Products: Disciple (1987)
|
|
Spectrum +3 (internal 3" disk drive) (1987)
|
|
Technology Research: Beta Disk Interface (1984)
|
|
Technology Research: Beta Plus Disk Interface (1985) (magic button)
|
|
Technology Research: Beta 128 Disk Interface (1986)
|
|
Timex FDD and FDD-3000 Disk Drives (with external Z80 CPU)
|
|
Omnitronix Ltd: Pacer Disk Interface
|
|
John Oliger Company: JLO TS2068 Disk System
|
|
Ramex Millenia K disk interface (SPDOS, or alternately LKDOS)
|
|
Acme Electric Robot Company: AERCO FD-68 (for TS2068) (Aerco DOS, or LKDOS)
|
|
LarKen: Disk Interface and LKDOS cartridge (for TS2068)
|
|
Kempston: Disc Interface (KDOS)
|
|
Logitek: Disc Interface (connect a Commodore 1541 drive to spectrum)
|
|
Sixword Ltd.: Swift Disc
|
|
Circuit Design: CS-DISK Interface
|
|
Haytech: Cyborg Disk Drive with Spectrum Personality Module
|
|
Statacom: Datafax Disk System
|
|
Cumana Ltd: Double Density Disk Interface
|
|
Dove Microtronix Ltd: Dove Disk Interface
|
|
8BC: MB-02+ Disk Interface
|
|
Morex Peripherals Ltd: Morex Floppy Disk System
|
|
Saga Systems Ltd: Saga Disk Interface
|
|
Saga Systems Ltd: Saga Disk Interface II (with printer port)
|
|
Thurnall Electronics Ltd: Thurnall Disk System (MCD-1)
|
|
Interactive Instruments Ltd: Viscount Disk Drive System
|
|
ITL & Tyrell Systems: Byte Drive 500
|
|
Ergo Systems Ltd/Video Vault Ltd: Clive Drive
|
|
Didaktik D40
|
|
Didaktik D80
|
|
Putnik 1991 (homebrew schematic) (uses A1, incompatible with Spectrum 128)
|
|
Putnik 1998 (homebrew schematic) (uses A7, now compatible with Spectrum 128)
|
|
|
|
Compact Disc Interface
|
|
Code Masters CD Games Pack (load games from Audio CD via joystick port)
|
|
|
|
Other Interfaces
|
|
Additonally, there are a number of newer harddisk and compact flash interfaces,
|
|
though they are probably rather rarely used.
|
|
|
|
Spectrum Disc and Tape Commands
|
|
-------------------------------
|
|
|
|
General Spectrum Load/Save commands (cas/disk)
|
|
LOAD "" ;load basic program (by wildcard)
|
|
LOAD <filename> ;load basic program (by name)
|
|
LOAD "picture.bin" CODE ;load binary to original addr
|
|
LOAD "picture.bin" CODE dest(,len_verify) ;load binary to other addr
|
|
LOAD "picture.bin" CODE SCREEN$ ;load binary to VRAM
|
|
LOAD <filename> DATA a () ;load numeric array
|
|
LOAD <filename> DATA a$ () ;load character array
|
|
SAVE <filename> ;save basic program
|
|
SAVE <filename> LINE <linenumber> ;save basic program with autostart
|
|
SAVE "picture.bin" CODE SCREEN$ ;save binary file (VRAM at 4000h)
|
|
SAVE "picture.bin" CODE 16384,6912 ;save binary file (same as SCREEN$)
|
|
SAVE "picture.bin" CODE start,length ;save binary file (custom area)
|
|
SAVE <filename> DATA a () ;save numeric array
|
|
SAVE <filename> DATA a$ () ;save character array
|
|
VERIFY <filename> ;compare file with program in in RAM
|
|
MERGE <filename> ;merge file with program in in RAM
|
|
|
|
Disk commands (Spectrum +3)
|
|
filename="DISK" ;default name for "loader" option in +3 BIOS menu
|
|
filename="filename.ext" ;max 8.3 characters (for CP/M-style filesystem)
|
|
MOVE oldname newname ;rename (or move to other drive)
|
|
MOVE oldname TO attr ;change attr "+p" "+s" "+a" or "-p" "-s" "-a"
|
|
COPY oldname newname ;copy
|
|
COPY textfile TO SCREEN$
|
|
COPY textfile TO LPRINT
|
|
COPY binfile TO SPECTRUM FORMAT ;creates binfile.HED (with binary HEaDer)
|
|
LOAD "d:" ;set default load drive (a:disk1, b:disk2, m:ramdisk, t:tape)
|
|
SAVE "d:" ;set default save drive (a:disk1, b:disk2, m:ramdisk, t:tape)
|
|
CAT (#stream),"filename" ;show directory (on stream #n)
|
|
ERASE filename ;delete
|
|
FORMAT drive
|
|
FORMAT LINE baudrate ;set RS232 baudrate
|
|
FORMAT LPRINT "r" ;redirect printer ("p") to RS232 ("r") stream
|
|
Streams:
|
|
OPEN #n,"k" ;keyboard (default=#1)
|
|
OPEN #n,"s" ;screen (default=#2)
|
|
OPEN #n,"p" ;printer (default=#3)
|
|
|
|
RAM-Disk (Spectrum 128/+2/+2A/+3)
|
|
On the Spectrum 128/+2/+2A/+3, 64Kbytes of RAM are used as RAM-Disk, which can
|
|
be accessed by appending an exclamation mark to cassette commands,
|
|
LOAD! SAVE! MERGE! CAT! ERASE! --> access RAM disk
|
|
On the Spectrum +2A/+3, one can additionally/alternately access the RAM-Disk by
|
|
specifying drive letter M as part of the filename, eg. LOAD "m:filename".
|
|
|
|
Microdrive (Sinclair Interface I)
|
|
LOAD * "m" ;1; "filename"
|
|
SAVE * "m" ;1; "filename"
|
|
FORMAT "m" ;1; "filename"
|
|
CAT 1
|
|
The microdrive syntax is also used by the Opus Discovery.
|
|
|
|
Rotronics Wavadrive
|
|
CAT * ;directory for default drive
|
|
CAT * "a:" ;directory for drive A
|
|
CAT # "a:" ;set A as default drive and load (but do not show) directory
|
|
POKE 23767,n ;set default drive (0=A, 1=B)
|
|
SAVE * "a:name" ;save on drive A
|
|
SAVE * "name" ;save on default drive
|
|
The thing also has a one-directional centronics port (stream "c"), and a RS232
|
|
port with RXD,TXD,RTS,CTS lines (stream "r").
|
|
Extended System Area occupies 102 bytes of RAM (starting at 23734), read/write
|
|
buffer occupies 1026 bytes (at 23836), directory A and B occupy 582 bytes each
|
|
(at 24862 and 25444).
|
|
|
|
Opus Discovery
|
|
Uses microdrive-style syntax. Additional commands are:
|
|
FORMAT "j";1 ;enable kempston joystick port in opus discovery
|
|
FORMAT "j";0 ;disable kempston joystick port in opus discovery
|
|
Includes a kempston joystick port (which must be enabled as described above),
|
|
and a centronics port. The centronics port can be also use as network
|
|
interface, via LOAD/SAVE/VERIFY * "b".
|
|
|
|
Technology Research - Beta Disk Interface (TRDOS)
|
|
In BASIC:
|
|
LET DOS=15360 ;=3C00h ;for Beta and Beta Plus (TRDOSv1 or TRDOSv4)
|
|
LET DOS=15616 ;=3D00h ;for Beta 128 (TRDOSv5)
|
|
RANDOMIZE USR DOS+3:REM:LOAD"D:FILENAME" ;load from drive D
|
|
RANDOMIZE USR DOS+0 ;switch from BASIC to TRDOS
|
|
In TRDOS:
|
|
LIST (K-key) ;show directory ;<B>=bootable
|
|
LOAD (J-key) or RUN (R-key) ;load a file
|
|
USR ;set disk password
|
|
RETURN (Y-key) ;switch from TRDOS to BASIC
|
|
|
|
Kempston Disk Interface (K-DOS)
|
|
Uses a rather strange syntax where disk-commands are preceeded by "PRINT #4:",
|
|
and in some cases followed by ":PRINT parameter(s)", eg:
|
|
PRINT #4:LOAD"filename"
|
|
PRINT #4:CAT:PRINT d ;d=drive number (1..4)
|
|
|
|
Larken (LARKEN DOS aka LKDOS)
|
|
Uses similar syntax as Kempston, but must be first initialized as:
|
|
RANDOMIZE USR 100: OPEN# 4, "dd"
|
|
Thereafter, "PRINT #4:" can be used to preceed disk-commands, eg.
|
|
PRINT #4:LOAD"filename"
|
|
The built-in joystick port is accessed via IN 31 (kempston style).
|
|
There are also LKDOS versions for use with Ramex and Aerco disk interfaces.
|
|
|
|
Spectrum Cassette
|
|
-----------------
|
|
|
|
The cassette is accessed via bits in ULA Port FEh (see ULA chapter). Cassette
|
|
input is received from EAR port, output is passed to MIC port. For the bizarre
|
|
part, the MIC and EAR leads cannot be simultaneously connected, so one of the
|
|
leads must be disconnected/reconnected for loading/saving. There is no Motor On
|
|
signal, so PLAY/STOP must be pressed manually.
|
|
|
|
Spectrum Cassette Blocks
|
|
Silence (low level)
|
|
8063 (Header) or 3223 (Data) Pilot Pulses (2168 clks/pulse) (619us/pulse)
|
|
1st Sync Pulse (667 clks/pulse) (190us/pulse)
|
|
2nd Sync Pulse (735 clks/pulse) (210us/pulse)
|
|
Blocktype Byte (00h=Header, FFh=Data)
|
|
Data Byte(s) (two 855 or 1710 clks/pulse per bit) (244 or 488 us/pulse)
|
|
Checksum Byte (above Blocktype and Data Bytes XORed with each other)
|
|
End pulse (opposite level of last pulse)
|
|
Silence (low level)
|
|
|
|
Spectrum Pilot/Sync/Bits/Bytes
|
|
/"""\__/ Sync Pulses (1st=667, 2nd=735 clks/pulse)
|
|
/""""\____/ "0"-Bit (two pulses, 855 clks/pulse)
|
|
/"""""""""\_________/ "1"-Bit (two pulses, 1710 clks/pulse)
|
|
/""""""""""""\____________/ etc. Pilot Pulses (2168 clks/pulse)
|
|
Bytes are transferred MSB (Bit7) first. Signals may be inverted.
|
|
|
|
Spectrum Header Block
|
|
Pre 1 Blocktype (aka Flag Byte) (must be 00h for Header blocks)
|
|
0 1 Filetype (0..3, see below)
|
|
1 10 Filename (padded with blanks, ie. chr(20h))
|
|
11 2 Length of following Data Block (LEN)
|
|
13 4 Parameters (depends on Filetype, see below)
|
|
Post 1 Checksum (above 18 bytes XORed with each other)
|
|
|
|
Spectrum Data Block
|
|
Pre 1 Blocktype (aka Flag Byte) (must be FFh for Data Blocks)
|
|
0 LEN Data
|
|
Post 1 Checksum (above LEN+1 bytes XORed with each other)
|
|
|
|
Spectrum Filetypes/Parameters (Bytes 13..16 of Header Blocks)
|
|
For Filetype=00h / BASIC Program File (Program and Variables):
|
|
13 2 Autostart LINE Number (or 8000h..FFFFh if no autostart)
|
|
15 2 Size of the PROG area aka start of the VARS area
|
|
For Filetype=01h / BASIC Number Array, or Filetype=02h / BASIC Character Array:
|
|
13 1 Unknown
|
|
14 1 Name of the variable
|
|
15 2 Unknown
|
|
For Filetype=03h / Binary CODE File (or SCREEN$ file):
|
|
13 2 Memory Address
|
|
15 2 Unused (Should be 8000h)
|
|
A SCREEN$ file is a CODE file with Memory Address 4000h and LEN=1B00h.
|
|
|
|
.TAP Files (Standard Cassette-Image for normal unprotected files)
|
|
A .TAP file can contain one or more spectrum file(s). Each file should usually
|
|
consist of two blocks (header and data). Each block is preceeded by a 16bit
|
|
length value (eg. 0013h for Header blocks), followed by "length" bytes which
|
|
contain the same information as stored on real cassettes (including the leading
|
|
Blocktype byte, and ending Checksum byte).
|
|
TAP files do not contain pilot/sync pulses, nor baudrate information, so they
|
|
can be used only for standard files (as used by the BIOS functions), not for
|
|
copyprotected software.
|
|
|
|
.TZX Files (Standard Cassette-Image for copy-protected files)
|
|
--> Spectrum Cassette TZX Format
|
|
|
|
Spectrum Cassette TZX Format
|
|
----------------------------
|
|
|
|
For some general definitions, see:
|
|
--> Spectrum Cassette TZX Notes
|
|
|
|
TZX Header (length: 0Ah bytes)
|
|
00h 8 TZX signature ("ZXTape!",1Ah)
|
|
08h 1 TZX major revision number (currently 01h, for v1.20)
|
|
09h 1 TZX minor revision number (currently 1Ah, for v1.20)
|
|
|
|
ID 10h - Standard Speed Data Block (length: [02h..03h]+4)
|
|
This block must be replayed with the standard Spectrum BIOS timings - see the
|
|
values in curly {} brackets in block ID 11h.
|
|
00h 2 Pause after this block (ms) (0=none) {1000}
|
|
02h 2 Length of data that follow (N)
|
|
04h N Data as in .TAP files (first byte implies number of pilot pulses)
|
|
The pilot tone consists of 8063 pulses if the first data byte (flag byte) (aka
|
|
block_type) is < 128, or 3223 pulses otherwise. This block can be used for the
|
|
BIOS loading routines AND for custom loading routines that use the same timings
|
|
as BIOS ones do.
|
|
|
|
ID 11h - Turbo Speed Data Block (length: [0Fh..11h]+12h)
|
|
00h 2 Length of PILOT pulse {2168} ;-occurs P times at begin
|
|
02h 2 Length of SYNC first pulse {667} ;-occurs ONCE after above
|
|
04h 2 Length of SYNC second pulse {735} ;-occurs ONCE after above
|
|
06h 2 Length of ZERO bit pulse {855} ;-occurs TWICE per bit
|
|
08h 2 Length of ONE bit pulse {1710} ;-occurs TWICE per bit
|
|
0Ah 2 Number of PILOT pulses (P) {8063 for header, 3223 for data)
|
|
0Ch 1 Number of used bits in the last byte {8}
|
|
(e.g. if this is 6, then the bits used (x) in the last byte are:
|
|
xxxxxx00, where MSb is the leftmost bit, LSb is the rightmost bit)
|
|
0Dh 2 Pause after this block (ms) (0=none) {1000}
|
|
0Fh 3 Length of data that follow (N)
|
|
12h N Data as in .TAP files {block_type, data[N-2], chksum}
|
|
This block is very similar to the normal TAP block but with some additional
|
|
info on the timings and other important differences. The same tape encoding is
|
|
used as for the standard speed data block. If a block should use some
|
|
non-standard sync or pilot tones (i.e. all sorts of protection schemes) then
|
|
use the next three blocks to describe it.
|
|
|
|
ID 12h - Pure Tone (length: 04h)
|
|
00h 2 Length of one pulse in T-states
|
|
02h 2 Number of pulses
|
|
This will produce a tone which is basically the same as the pilot tone in the
|
|
ID 10h, ID 11h blocks. You can define how long the pulse is and how many pulses
|
|
are in the tone.
|
|
|
|
ID 13h - Pulse sequence (length: [00h]*2+1)
|
|
00h 1 Number of pulses (N)
|
|
01h 2*N Pulse lengths (16bit each)
|
|
This will produce N pulses, each having its own timing. Up to 255 pulses can be
|
|
stored in this block; this is useful for non-standard sync tones used by some
|
|
protection schemes.
|
|
|
|
ID 14h - Pure Data Block (length: [07h..09h]+0Ah)
|
|
00h 2 Length of ZERO bit pulse
|
|
02h 2 Length of ONE bit pulse
|
|
04h 1 Used bits in last byte (other bits should be 0)
|
|
(e.g. if this is 6, then the bits used (x) in the last byte are:
|
|
xxxxxx00, where MSb is the leftmost bit, LSb is the rightmost bit)
|
|
05h 2 Pause after this block (ms) (0=none)
|
|
07h 3 Length of data that follow (N)
|
|
0Ah N Data as in .TAP files
|
|
Same as in the turbo loading data block, but without pilot and sync pulses.
|
|
|
|
ID 15h - Direct Recording (length: [05h..07h]+08h)
|
|
00h 2 Number of T-states per sample-bit (usually 158 or 79)
|
|
02h 2 Pause after this block (ms) (0=none)
|
|
04h 1 Used bits (samples) in last byte of data (1..8)
|
|
(eg. 2 means only first two samples of the last byte will be played)
|
|
05h 3 Length of sample data in bytes (N)
|
|
08h N Sample data. Each bit represents a state on the EAR port
|
|
(i.e. one sample). MSb is played first.
|
|
This block is used for tapes which have some parts in a format such that the
|
|
turbo loader block cannot be used. This is not like a VOC file, since the
|
|
information is much more compact. Each sample value is represented by one bit
|
|
only (0 for low, 1 for high) which means that the block will be at most 1/8 the
|
|
size of the equivalent VOC.
|
|
The preferred sampling frequencies are 22050 or 44100 Hz (158 or 79
|
|
T-states/sample), this will ensure correct playback when using PC's soundcards.
|
|
Please, if you can, don't use other sampling frequencies.
|
|
Please use this block only if you cannot use any other block.
|
|
|
|
ID 16h - C64 BIOS Type Data Block (length: [00h..03h]+0 or 4?) (v1.13 only)
|
|
ID 17h - C64 Turbo Tape Data Block (length: [00h..03h]+0 or 4?) (v1.13 only)
|
|
These two blocks were defined (although rarely/never used) in TZX version v1.13
|
|
only, intended to support Commodore 64 files.
|
|
Bug: Blocks invented after v1.10 are stated to have a length of "[00h..03h]+4"
|
|
bytes, while the C64 blocks invented in v1.13 were ALSO stated by "[00h..03h]"
|
|
in length, so it's somewhat unclear how to the C64 blocks. Anyways, they should
|
|
never show up in Spectrum files, and as far as I know the format wasn't
|
|
actually used in the C64 world either.
|
|
|
|
ID 18h - CSW Recording (length: [00h..03h]+4) (v1.20 and up)
|
|
00h 4 Block length (without these four bytes) (10h+N)
|
|
04h 2 Pause after this block (ms) (0=none)
|
|
06h 3 Sampling rate
|
|
09h 1 Compression type (01h=RLE, 02h=Z-RLE)
|
|
0Ah 4 Number of stored pulses (after decompression, for validation purposes)
|
|
0Eh N CSW data, encoded according to the CSW file format specification.
|
|
This block contains a sequence of raw pulses encoded in Ramsoft's CSW format v2
|
|
(Compressed Square Wave). The encoding of the RLE and Z-RLE data is
|
|
undocumented. It can reportedly compress a 12MB 44kHz VOC file to 1MB, which is
|
|
still very bloated, so better don't use the CSW stuff.
|
|
|
|
ID 19h - Generalized Data Block (length: [00h..03h]+4) (v1.20 and up)
|
|
This block has been specifically developed to represent an extremely wide range
|
|
of data encoding techniques.
|
|
--> Spectrum Cassette TZX Format ID 19h
|
|
|
|
ID 20h - Pause (silence) or 'Stop the Tape' command (length: 2)
|
|
00h 2 Pause after this block (ms) (or 0=stop tape, ie. infinite pause)
|
|
This will make a silence for a given time in milliseconds. If the value is 0
|
|
then the emulator or utility should (in effect) STOP THE TAPE, ie. it should
|
|
make a pause of infinite length (until the user or emulator requests to restart
|
|
the tape motor). As usually, the first 1 ms of the pause must be opposite of
|
|
the old level, the remaining milliseconds must be low level.
|
|
|
|
ID 21h - Group start (length: [00h]+1)
|
|
00 1 Length of the group name string (L)
|
|
01 L Group name in ASCII format (please keep it under 30 characters long)
|
|
This block marks the start of a group of blocks which are to be treated as one
|
|
single (composite) block. This is very handy for tapes that use lots of
|
|
subblocks like Bleepload (which may well have over 160 custom loading blocks).
|
|
You can also give the group a name (example 'Bleepload Block 1').
|
|
For each group start block, there must be a group end block. Nesting of groups
|
|
is not allowed.
|
|
|
|
ID 22h - Group end (length: 0)
|
|
This indicates the end of a group. This block has no body.
|
|
|
|
ID 23h - Jump to block (length: 2)
|
|
00h 2 Relative jump value (number of blocks, from current block)
|
|
This block will enable you to jump from one block to another within the file.
|
|
Some examples:
|
|
Jump +0 = Loop Forever ;this should never happen
|
|
Jump +1 = Go to the next block ;acts as a NOP in assembler
|
|
Jump +2 = Skip one block
|
|
Jump -1 = Go to the previous block
|
|
All blocks are included in the block count!
|
|
|
|
ID 24h - Loop start (length: 2) (v1.10 and up)
|
|
00h 2 Number of repetitions (greater than 1)
|
|
If you have a sequence of identical blocks, or of identical groups of blocks,
|
|
you can use this block to tell how many times they should be repeated. This
|
|
block is the same as the FOR statement in BASIC.
|
|
For simplicity reasons don't nest loop blocks!
|
|
|
|
ID 25h - Loop end (length: 0) (v1.10 and up)
|
|
This is the same as BASIC's NEXT statement. It means that the utility should
|
|
jump back to the start of the loop if it hasn't been run for the specified
|
|
number of times. This block has no body.
|
|
|
|
ID 26h - Call sequence (length: [00h..01h]*2+2) (v1.10 and up)
|
|
00h 1 Number of calls to be made (N)
|
|
02h 2*N Array of call block numbers (relative-signed 16bit offsets)
|
|
This block is an analogue of the CALL Subroutine statement. It basically
|
|
executes a sequence of blocks that are somewhere else and then goes back to the
|
|
next block. Because more than one call can be normally used you can include a
|
|
list of sequences to be called. The 'nesting' of call blocks is also not
|
|
allowed for the simplicity reasons. You can, of course, use the CALL blocks in
|
|
the LOOP sequences and vice versa. The value is relative for the obvious
|
|
reasons - so that you can add some blocks in the beginning of the file without
|
|
disturbing the call values. Please take a look at 'Jump To Block' for reference
|
|
on the values.
|
|
|
|
ID 27h - Return from sequence (length: 0) (v1.10 and up)
|
|
This block indicates the end of the Called Sequence. The next block played will
|
|
be the block after the last CALL block (or the next Call, if the Call block had
|
|
multiple calls). This block has no body.
|
|
|
|
ID 28h - Select block (length: [00h..01h]+2) (v1.10 and up)
|
|
00h 2 Length of the whole block (without these two bytes)
|
|
02h 1 Number of selections (N)
|
|
03h .. List of selections
|
|
Each selection has the following format:
|
|
00 2 Relative Offset (16bit)
|
|
02 1 Length of description text (L)
|
|
03 L Description text in ASCII (please use single line and max 30 chars)
|
|
This block is useful when the tape consists of two or more separately-loadable
|
|
parts. With this block, you are able to select one of the parts and the
|
|
utility/emulator will start loading from that block. For example you can use it
|
|
when the game has a separate Trainer or when it is a multiload. Of course, to
|
|
make some use of it the emulator/utility has to show a menu with the selections
|
|
when it encounters such a block. All offsets are relative signed words.
|
|
|
|
ID 2Ah - Stop the tape if in 48K mode (length: 4) (v1.xx? and up)
|
|
00h 4 Length of the block without these four bytes (=0)
|
|
When this block is encountered, the tape will stop ONLY if the machine is an
|
|
48K Spectrum. This block is to be used for multiloading games that load one
|
|
level at a time in 48K mode, but load the entire tape at once if in 128K mode.
|
|
This block has no body of its own, but follows the extension rule.
|
|
|
|
ID 2Bh - Set signal level (length: 5) (v1.20 and up)
|
|
00h 4 Block length (without these four bytes) (=1)
|
|
04h 1 Signal level (0=low, 1=high)
|
|
This block sets the current signal level to the specified value (high or low).
|
|
It should be used whenever it is necessary to avoid any ambiguities, e.g. with
|
|
custom loaders which are level-sensitive.
|
|
|
|
ID 30h - Text description (length: [00h]+1)
|
|
00h 1 Length of the text description (N)
|
|
01h N Text description in ASCII format
|
|
This is meant to identify parts of the tape, so you know where level 1 starts,
|
|
where to rewind to when the game ends, etc. This description is not guaranteed
|
|
to be shown while the tape is playing, but can be read while browsing the tape
|
|
or changing the tape pointer.
|
|
The description can be up to 255 characters long but please keep it down to
|
|
about 30 so the programs can show it in one line (where this is appropriate).
|
|
Please use 'Archive Info' block for title, authors, publisher, etc.
|
|
|
|
ID 31h - Message block (length: [01h]+2)
|
|
00h 1 Time (in seconds) for which the message should be displayed
|
|
01h 1 Length of the text message (N)
|
|
02h N Message that should be displayed in ASCII format
|
|
This will enable the emulators to display a message for a given time. This
|
|
should not stop the tape and it should not make silence. If the time is 0 then
|
|
the emulator should wait for the user to press a key.
|
|
The text message should:
|
|
stick to a maximum of 30 chars per line;
|
|
use single 0x0D (13 decimal) to separate lines;
|
|
stick to a maximum of 8 lines.
|
|
If you do not obey these rules, emulators may display your message in any way
|
|
they like.
|
|
|
|
ID 32h - Archive info (length: [00h..01h]+2)
|
|
00h 2 Length of the whole block (without these two bytes)
|
|
02h 1 Number of text strings (N)
|
|
03h N List of Text Structures
|
|
Text Structure format:
|
|
00h 1 Text identification byte (see list below)
|
|
01h 1 Length of text string (L)
|
|
02h L Text string in ASCII format
|
|
Text identification byte values:
|
|
00h Full title
|
|
01h Software house/publisher
|
|
02h Author(s)
|
|
03h Year of publication (eg. 1982) (in ASCII, too)
|
|
04h Language (v1.10 and up) (eg. English) (=default)
|
|
05h Game/utility type (v1.12 and up) (eg. arcade adventure, puzzle)
|
|
06h Price with currency (v1.12 and up) (eg. GBP 5.99, or chr(A3h)=GBP)
|
|
07h Protection scheme/loader (v1.12 and up) (eg. Speedlock 1, Alkatraz)
|
|
08h Origin (v1.12 and up) (eg. Original, Budget re-release)
|
|
FFh Comment(s)
|
|
xxh Reserved for future (decoders should skip any unknown entries)
|
|
When using this block, store it at the beginning of the tape. The information
|
|
about what hardware the tape uses is in the 'Hardware Type' block, so no need
|
|
for it here. According to the tzx format release notes, v1.10 and up allows
|
|
multiple lines in the 'Archive info' (ID 32h) block.
|
|
|
|
ID 33h - Hardware type (length: [00h]*3+1)
|
|
00h 1 Number of machines and hardware types for which info is supplied (N)
|
|
01h 3*N List of machines and hardware
|
|
This blocks contains information about the hardware that the programs on this
|
|
tape use. For details, see:
|
|
--> Spectrum Cassette TZX Format HW
|
|
This feature is (theoretically) the main advantage of the TZX format over the
|
|
TAP format, however, in practice, most (or all) existing TZX files don't use
|
|
this feature. So, for that matter, one could as well keep using normal TAP
|
|
files.
|
|
|
|
ID 34h - Emulation info (length: 8) (up to v1.13 only)
|
|
This block was defined (although rarely used) in TZX versions up to v1.13 only.
|
|
00h 2 General emulation flags:
|
|
bit 0 : R-register emulation [1]
|
|
bit 1 : LDIR emulation [1]
|
|
bit 2 : high resolution colour emulation with true interrupt freq. [1]
|
|
bit 3,4 : video synchronisation (1=high, 3=low, 0,2=normal) [0]
|
|
bit 5 : fast loading when BIOS load routine is used [1]
|
|
bit 6 : border emulation [1]
|
|
bit 7 : screen refresh mode (0=off, 1=on) [1]
|
|
bit 8 : start playing the tape immediately (0=no, 1=yes) [0]
|
|
bit 9 : auto type LOAD"" or press ENTER when in 128k mode [0]
|
|
02h 1 Update screen every N frames (1..255) (used only when flags.bit7=1)
|
|
03h 2 Interrupt Frequency in Hertz (0..999)
|
|
05h 3 Reserved for future expansion
|
|
This is a special block that would normally be generated only by emulators.
|
|
Those bits that are not used by the emulator that stored the info, should be
|
|
left at their [default] values.
|
|
|
|
ID 35h - Custom info block (length: [10h..13h]+14h) (works in v1.01 and up)
|
|
00h 16 Identification string (in ASCII) (usually padded with spaces)
|
|
10h 1 Length of the custom info (L)
|
|
14h L Custom info
|
|
This block can be used to save any information you want. For example, it might
|
|
contain some information written by a utility, extra settings required by a
|
|
particular emulator, or even poke data.
|
|
--> Spectrum Cassette TZX Format Custom
|
|
Note: The Length of the ID string was accidently documented as 15 bytes in
|
|
v1.00 (although it should have been 16), this has been fixed in v1.01.
|
|
|
|
ID 40h - Snapshot block (length: [01h..03h]+4) (v1.10..v1.13 only)
|
|
This block was defined (although rarely used) in tzx versions v1.10..v1.13
|
|
only.
|
|
00h 1 Snapshot type (00h=.Z80 format, 01h=.SNA format)
|
|
01h 3 Snapshot length (L)
|
|
04h L The Snapshot itself
|
|
Allows to snapshot the game at the start and still have all the tape blocks
|
|
(level data, etc.) in the same file. The emulator should take care of that the
|
|
snapshot is not taken while the actual Tape loading is taking place. When an
|
|
emulator encounters the snapshot block it should load it and then continue with
|
|
the next block.
|
|
|
|
ID 5Ah (aka "Z") - Glue block (length: 09h)
|
|
00h 9 ZXTape Header (excluding the "Z", ie. "XTape!",1Ah,MajR,MinR)
|
|
This block is generated when you merge two ZX Tape files together. It is here
|
|
so that you can easily copy the files together and use them. Of course, this
|
|
means that resulting file would be 10 bytes longer than if this block was not
|
|
used. If you can avoid using this block for this purpose, then do so; it is
|
|
preferable to use a utility to join the two files and ensure that they are both
|
|
of the higher version number.
|
|
|
|
ID xxh - Reserved (length [00h..03h]+4)
|
|
00h 4 Block length (32bit) (without these four bytes)
|
|
04h .. Reserved
|
|
Reserved for future. As shown above, all new blocks added after v1.10 should
|
|
begin with a 32bit Block length entry in the first 4 bytes; the length value
|
|
should exclude that first 4 bytes). With that definition, decoders may skip
|
|
unknown blocks - and may still work (if the blocks contain only comments or
|
|
so).
|
|
A special case are the C64 blocks (ID 16h and ID 17h) where the TZX format does
|
|
"clearly" define BOTH to include AND to exclude first 4 bytes in the length
|
|
entry (that blocks should never show up in Spectrum files, so it should be no
|
|
problem, as far as I know they even weren't ever actually used for the C64).
|
|
|
|
Spectrum Cassette TZX Format HW
|
|
-------------------------------
|
|
|
|
ID 33h - Hardware type (length: [00h]*3+1)
|
|
00h 1 Number of machines and hardware types for which info is supplied (N)
|
|
01h 3*N List of machines and hardware (HWINFO)
|
|
HWINFO structure format:
|
|
00h 1 Hardware type (00h..10h; see the headlines of the ID lists)
|
|
01h 1 Hardware ID (00h..xxh; see the ID list entries)
|
|
02h 1 Hardware information (00h..03h; see the small table below)
|
|
This blocks contains information about the hardware that the programs on this
|
|
tape use. Please include only machines and hardware for which you are 100% sure
|
|
that it either runs (or doesn't run) on or with, or you know it uses (or
|
|
doesn't use) the hardware or special features of that machine.
|
|
If the tape runs only on the ZX81 (and TS1000, etc.) then it clearly won't work
|
|
on any Spectrum or Spectrum variant, so there's no need to list this
|
|
information.
|
|
If you are not sure or you haven't tested a tape on some particular
|
|
machine/hardware combination then do not include it in the list.
|
|
The list of hardware types and IDs is somewhat large, and may be found at the
|
|
end of the format description.
|
|
|
|
Hardware information (3rd byte)
|
|
00h The tape RUNS on this hardware (and may or may not use its features)
|
|
01h The tape RUNS and DOES use the special features of the hardware
|
|
02h The tape RUNS but DOES-NOT use the special features of the hardware
|
|
03h The tape DOES-NOT-WORK on this hardware
|
|
|
|
Hardware information reference
|
|
This is the list of all hardware types and hardware identification ID's that
|
|
are used in the 'Hardware info' block. Please send any additions you might have
|
|
to the TZX maintainers so that they can be included.
|
|
By default you don't have to write any of the information if the game is made
|
|
for the ZX Spectrum and complies with the following:
|
|
- runs on ZX Spectrum 48K
|
|
- runs on, but doesn't use any of the special hardware of ZX Spectrum 128K
|
|
- doesn't run on ZX Spectrum 16K
|
|
If, for example, game works on BOTH ZX 48K and 128K, and uses the hardware of
|
|
the 128K Spectrum, then you would just include the 128K Spectrum in the list
|
|
(because by default it has to work on 48K too).
|
|
If the game is 128K ONLY then you would include two entries: The game works on
|
|
AND uses the hardware of a 128K Spectrum AND the game DOESN'T work on a 48K
|
|
Spectrum.
|
|
If the game works on both 48K and 128K Spectrum, but it only uses the sound
|
|
chip (AY) of the 128K Spectrum and none of its extra memory then you would only
|
|
include the entry that says that the game uses the 'Classic AY hardware
|
|
(Spectrum 128 compatible sound device)'.
|
|
These were only some examples of the usage of this block.
|
|
|
|
Computer Types (first byte = 00h)
|
|
00h ZX Spectrum 16k
|
|
01h ZX Spectrum 48k, Plus
|
|
02h ZX Spectrum 48k ISSUE 1
|
|
03h ZX Spectrum 128k + (Sinclair)
|
|
04h ZX Spectrum 128k +2 (grey case)
|
|
05h ZX Spectrum 128k +2A, +3
|
|
06h Timex Sinclair TC-2048
|
|
07h Timex Sinclair TS-2068
|
|
08h Pentagon 128
|
|
09h Sam Coupe
|
|
0Ah Didaktik M
|
|
0Bh Didaktik Gama
|
|
0Ch ZX-80 (via ID 19h, generalized data block, supported in v1.20 and up)
|
|
0Dh ZX-81 (via ID 19h, generalized data block, supported in v1.20 and up)
|
|
0Eh ZX Spectrum 128k, Spanish version
|
|
0Fh ZX Spectrum, Arabic version
|
|
10h Microdigital TK 90-X
|
|
11h Microdigital TK 95
|
|
12h Byte
|
|
13h Elwro 800-3
|
|
14h ZS Scorpion 256
|
|
Below in v1.02 and up (For Amstrad, use extension .CDT instead of .TZX)
|
|
15h Amstrad CPC 464
|
|
16h Amstrad CPC 664
|
|
17h Amstrad CPC 6128
|
|
18h Amstrad CPC 464+
|
|
19h Amstrad CPC 6128+
|
|
Below in v1.12 and up
|
|
1Ah Jupiter ACE
|
|
1Bh Enterprise
|
|
Below in v1.13 only
|
|
1Ch (was intended for Commodore 64)
|
|
1Dh (was intended for Commodore 128)
|
|
Below in v1.20 and up
|
|
1Eh Inves Spectrum+
|
|
1Fh Profi
|
|
20h GrandRomMax
|
|
21h Kay 1024
|
|
22h Ice Felix HC 91
|
|
23h Ice Felix HC 2000
|
|
24h Amaterske RADIO Mistrum
|
|
25h Quorum 128
|
|
26h MicroART ATM
|
|
27h MicroART ATM Turbo 2
|
|
28h Chrome
|
|
29h ZX Badaloc
|
|
2Ah TS-1500
|
|
2Bh Lambda
|
|
2Ch TK-65
|
|
2Dh ZX-97
|
|
|
|
External storage types (first byte = 01h)
|
|
00h ZX Microdrive
|
|
01h Opus Discovery
|
|
02h MGT Disciple
|
|
03h MGT Plus-D
|
|
04h Rotronics Wafadrive
|
|
05h TR-DOS (BetaDisk)
|
|
06h Byte Drive
|
|
07h Watsford
|
|
08h FIZ
|
|
09h Radofin
|
|
0Ah Didaktik disk drives
|
|
0Bh BS-DOS (MB-02)
|
|
0Ch ZX Spectrum +3 disk drive
|
|
0Dh JLO (Oliger) disk interface
|
|
0Eh Timex FDD3000
|
|
0Fh Zebra disk drive
|
|
10h Ramex Millenia
|
|
11h Larken
|
|
Below in v1.20 and up
|
|
12h Kempston disk interface
|
|
13h Sandy
|
|
14h ZX Spectrum +3e hard disk
|
|
15h ZXATASP
|
|
16h DivIDE
|
|
17h ZXCF
|
|
|
|
ROM/RAM type add-ons (first byte = 02h)
|
|
00h Sam Ram
|
|
01h Multiface ONE
|
|
02h Multiface 128k
|
|
03h Multiface +3
|
|
04h MultiPrint
|
|
05h MB-02 ROM/RAM expansion
|
|
Below in v1.20 and up
|
|
06h SoftROM
|
|
07h 1k
|
|
08h 16k
|
|
09h 48k
|
|
0Ah Memory in 8-16k used
|
|
|
|
Sound devices (first byte = 03h)
|
|
00h Classic AY hardware (compatible with 128k ZXs)
|
|
01h Fuller Box AY sound hardware
|
|
02h Currah microSpeech
|
|
03h SpecDrum
|
|
04h AY ACB stereo (A+C=left, B+C=right); Melodik
|
|
05h AY ABC stereo (A+B=left, B+C=right)
|
|
Below in v1.20 and up
|
|
06h RAM Music Machine
|
|
07h Covox
|
|
08h General Sound
|
|
09h Intec Electronics Digital Interface B8001
|
|
0Ah Zon-X AY
|
|
0Bh QuickSilva AY
|
|
0Ch Jupiter ACE
|
|
|
|
Joysticks (first byte = 04h)
|
|
00h Kempston
|
|
01h Cursor, Protek, AGF
|
|
02h Sinclair 2 Left (12345)
|
|
03h Sinclair 1 Right (67890)
|
|
04h Fuller
|
|
|
|
Mice (first byte = 05h)
|
|
00h AMX mouse
|
|
01h Kempston mouse
|
|
|
|
Other controllers (first byte = 06h)
|
|
00h Trickstick
|
|
01h ZX Light Gun
|
|
02h Zebra Graphics Tablet
|
|
Below in v1.20 and up
|
|
03h Defender Light Gun
|
|
|
|
Serial ports (first byte = 07h)
|
|
00h ZX Interface 1
|
|
01h ZX Spectrum 128k
|
|
|
|
Parallel ports (first byte = 08h)
|
|
00h Kempston S
|
|
01h Kempston E
|
|
02h ZX Spectrum +3
|
|
03h Tasman
|
|
04h DK'Tronics
|
|
05h Hilderbay
|
|
06h INES Printerface
|
|
07h ZX LPrint Interface 3
|
|
08h MultiPrint
|
|
09h Opus Discovery
|
|
0Ah Standard 8255 chip with ports 31,63,95
|
|
|
|
Printers (first byte = 09h)
|
|
00h ZX Printer, Alphacom 32 & compatibles
|
|
01h Generic printer
|
|
02h EPSON compatible
|
|
|
|
Modems (first byte = 0Ah)
|
|
00h Prism VTX 5000
|
|
01h T/S 2050 or Westridge 2050
|
|
|
|
Digitizers (first byte = 0Bh)
|
|
00h RD Digital Tracer
|
|
01h DK'Tronics Light Pen
|
|
02h British MicroGraph Pad
|
|
Below in v1.20 and up
|
|
03h Romantic Robot Videoface
|
|
|
|
Network adapters (first byte = 0Ch)
|
|
00h ZX Interface 1
|
|
|
|
Keyboards & keypads (first byte = 0Dh)
|
|
00h Keypad for ZX Spectrum 128k
|
|
|
|
AD/DA converters (first byte = 0Eh)
|
|
00h Harley Systems ADC 8.2
|
|
01h Blackboard Electronics
|
|
|
|
EPROM programmers (first byte = 0Fh)
|
|
00h Orme Electronics
|
|
|
|
Graphics (first byte = 10h)
|
|
Below in v1.20 and up
|
|
00h WRX Hi-Res
|
|
01h G007
|
|
02h Memotech
|
|
03h Lambda Colour
|
|
|
|
Spectrum Cassette TZX Format ID 19h
|
|
-----------------------------------
|
|
|
|
ID 19h - Generalized Data Block (length: [00h..03h]+4) (v1.20 and up)
|
|
00h 4 Block length (without these four bytes)
|
|
04h 2 Pause after this block (ms) (0=none)
|
|
06h 4 Total number of symbols in pilot/sync block (can be 0) (TOTP) ;\pilot
|
|
0Ah 1 Maximum number of pulses per pilot/sync symbol (NPP) ; hdr
|
|
0Bh 1 Number of pilot/sync symbols in alphabet table (0=256) (ASP) ;/
|
|
0Ch 4 Total number of symbols in data stream (can be 0) (TOTD) ;\data
|
|
10h 1 Maximum number of pulses per data symbol (NPD) ; hdr
|
|
11h 1 Number of data symbols in the alphabet table (0=256) (ASD) ;/
|
|
12h .. Pilot/Sync symbols definition table (only if TOTP>0) ;\pilot
|
|
.. .. Pilot/Sync RLE-compressed stream (PRLE) (only if TOTP>0) ;/stream
|
|
.. .. Data symbols definition table (only if TOTD>0) ;\data
|
|
.. .. Data stream (as in .TAP files) (only if TOTD>0) ;/stream
|
|
Can be used to encode nonstandard copy-protected files. Also used for ZX81
|
|
files.
|
|
|
|
Symbol Definition Table entry format (for both Pilot/Sync and Data)
|
|
00h 1 Symbol flags (b0-b1: starting symbol polarity)
|
|
0: opposite to current level (make an edge, as usual) - default
|
|
1: same as current level (no edge - prolongs previous pulse)
|
|
2: force low level
|
|
3: force high level
|
|
01h 2*MAXP Pulse lengths (16bit) (padded with 0000h if less than MAXP used)
|
|
The number of table entries is ASP or ASD. The size per entry is 1+2*MAXP,
|
|
where MAXP is NPP or NPD.
|
|
|
|
Run-Length Encoded Pilot/Sync Stream format (PRLE)
|
|
00h 1 Symbol to be output (eg. a symbol that defines the Pilot pulse)
|
|
01h 2 Number of repetitions (eg. number of Pilot pulses)
|
|
The number of entries is TOTP, each entry is 3 bytes in size.
|
|
|
|
Data Stream format
|
|
Most commonly, 2 symbols are used, so the 1st symbol is in bit7 of 1st byte.
|
|
If 3 or 4 symbols are used, then the 1st symbol is in bit7-6 of 1st byte.
|
|
|
|
Example (Standard Spectrum Block)
|
|
00h 0000xxxxh ;Total block length (28h+LEN)
|
|
04h 03E8h ;Pause after this block (ms)
|
|
06h 00000002h ;Total number of pilot/sync symbols TOTP;\
|
|
0Ah 02h ;Max pulses per symbol NPP ; pilot header
|
|
0Bh 02h ;Number of symbols in pilot/sync alphabet ASP ;/
|
|
0Ch LEN*8 ;Total number of data symbols TOTD;\
|
|
10h 02h ;Max pulses per data symbol NPD ; data header
|
|
11h 02h ;Number of symbols in data alphabet ASD ;/
|
|
12h 00h,02168,00000 ;Pilot Symbol 0 (single pilot pulse)
|
|
17h 00h,00667,00735 ;Pilot Symbol 1 (two sync pulses)
|
|
1Ch 00h,08063 ;PRLE: take Pilot-Symbol 0, and repeat it 8063 times
|
|
1Fh 01h,00001 ;PRLE: take Pilot-Symbol 1, and repeat it 1 times
|
|
22h 00h,00855,00855 ;Data Symbol 0
|
|
27h 00h,01710,01710 ;Data Symbol 1
|
|
2Ch Data (LEN bytes: block_type, data[LEN-2], chksum)
|
|
|
|
Example (Standard ZX81 Block)
|
|
00h 0000xxxxh ;Total block length (58h+LEN)
|
|
04h 03E8h ;Pause after this block (ms)
|
|
06h 00000000h ;Total number of pilot/sync records TOTP;\no pilot
|
|
0Ah 00h ;Max pulses per symbol NPP ; for zx81
|
|
0Bh 00h ;Number of symbols in pilot/sync alphabet ASP ;/
|
|
0Ch LEN*8 ;Total number of data symbols TOTD;\
|
|
10h 12h ;Max pulses per data symbol NPD ; data header
|
|
11h 02h ;Number of symbols in data alphabet ASD ;/
|
|
12h 3,530,520,530,520,530,520,530 ;\Data Symbol 0
|
|
4689,0,0,0,0,0,0,0,0,0,0 ;/
|
|
37h 3,530,520,530,520,530,520,530 ;\Data Symbol 1
|
|
520,530,520,530,520,530,520,530,520,530,4689 ;/
|
|
5Ch Data (LEN bytes: ZX81 filename, followed by memory [4009h..E_LINE-1])
|
|
Note: As usually, data symbol definitions are referred to spectrum-style 3.5MHz
|
|
clock frequency (ie. not to ZX81-style 3.25MHz).
|
|
|
|
ZX80/ZX81 Filetype Detection
|
|
ZX80/ZX81 files SHOULD have a Hardware Info block (ID 33h) that identifies them
|
|
as ZX80/ZX81 file. Unfortunately, in practice, they usually do NOT contain that
|
|
information. So, to detect a ZX80/ZX81 file, one would need to check if the
|
|
first data block has ID 19h, and if so, if it contains the above Symbols. To
|
|
separate between ZX80 and ZX81 one may need to examine the presence of the ZX81
|
|
filename, and the values in the System Area.
|
|
|
|
ZX80/ZX81 Leading Silence
|
|
ZX80/ZX81 files are preceeded by leading silence (instead of a pilot tone). For
|
|
the ZX80 this leading silence is REQUIRED (must be at least around 500ms). For
|
|
ZX81, it can be shorter, and it is required only if the signal is preceeded by
|
|
noise (if loading starts at the exact time when the 1st pulse is output, then
|
|
the ZX81 BIOS doesn't need the silence).
|
|
The ID 19h block itself doesn't support leading silence, so ZX80 files MUST
|
|
have it preceeded by Pause block (ID 20h) - one could almost expect that people
|
|
will violate that rule, if so, software must automatically insert the leading
|
|
pause.
|
|
|
|
Spectrum Cassette TZX Format Custom
|
|
-----------------------------------
|
|
|
|
Custom Info Blocks...
|
|
Some of the most common uses of the Custom info block (ID 35h) have become
|
|
standardized in the past revisions, although now they are deprecated:
|
|
|
|
POKEs block (v1.10..v1.13 only)
|
|
The purpose of this custom block is to hold any amount of different trainers
|
|
for the game.
|
|
00h 16 Custom block ID ("POKEs" + 11 spaces)
|
|
10h 4 Length of data that follow
|
|
14h 1 General description length (L)
|
|
15h L General description in ASCII format
|
|
15h+L 1 Number of trainer definitions (N)
|
|
15h+L+1 .. Trainer definitions
|
|
Each trainer can have its own description and any number of POKEs.
|
|
TRAINER structure format
|
|
00h 1 Trainer description length (L)
|
|
01h L Trainer description in ASCII format
|
|
01h+L 1 Number of poke definitions in this trainer (N)
|
|
01h+L+1 .. POKEs definitions
|
|
For each POKE entry you can supply the memory page number and/or the original
|
|
value of the address (if you want to restore it some way through the game).
|
|
Normally you would enter these pokes with the help of some freezer-type tool
|
|
like Multiface, but hopefully in the future the emulators will support this
|
|
block directly, in which case you could use the 'User inserts the POKE value'
|
|
feature. You can specify the point at which to insert the POKEs in the 'General
|
|
description' field.
|
|
NOTE: All ASCII Descriptions can use more than one line. Please use only up to
|
|
30 characters per line and separate the lines by one CR (13 decimal).
|
|
POKE structure format
|
|
00h 1 POKE type:
|
|
bit 0-2 : memory page number
|
|
bit 3 : ignore memory page number
|
|
bit 4 : user inserts the POKE value
|
|
bit 5 : unknown original value
|
|
01h 2 POKE address
|
|
03h 1 POKE value (leave 0 if 'user inserts' bit set)
|
|
04h 1 POKE original value (leave 0 if 'unknown' bit set)
|
|
|
|
Instructions block (v1.10..v1.13 only)
|
|
This block can hold any general .TXT file, with the main purpose of storing the
|
|
instructions to the program or game that is in the tape.
|
|
To ensure consistency with all other ASCII texts in this format please use a
|
|
single CR character (13 decimal, 0Dh) to separate lines; also please use only
|
|
up to 80 characters per line.
|
|
00h 16 Custom block ID ("Instructions" + 4 spaces)
|
|
10h 4 Length of the following data (L)
|
|
14h L Instructions text in ASCII format
|
|
|
|
Spectrum screen block (v1.10..v1.13 only)
|
|
If the game on the tape is not an original and lacks the original loading
|
|
screen then you can supply it separately within this block. This is also very
|
|
handy when you want the loading screen stored separately because the original
|
|
is either encrypted (like with the 'Speedlock' or 'Alkatraz' loaders) or it is
|
|
corrupted by some on-screen info (like the 'Bleepload' loader). Of course not
|
|
only loading screens can be stored here... you can use it to store maps or any
|
|
other picture that is in Spectrum Video format (that's why the Description is
|
|
there for), but because the Loading Screen will be the most common you can just
|
|
set the description length field to 0 when you use it for that. Also the border
|
|
colour can be specified.
|
|
00h 16 Custom block ID ("Spectrum Screen" + 1 space)
|
|
10h 4 Length of data that follow
|
|
14h 1 Description length (L) (if 0 then handle it as 'Loading Screen')
|
|
15h L Description of the picture in ASCII format
|
|
15h+L 1 BORDER Colour in Spectrum colour format (0=black, 1=blue, ...)
|
|
15h+L+1 6912 Screen in standard Spectrum video format
|
|
|
|
ZX-Edit document block (v1.12..v1.13 only)
|
|
This block can hold files created with the new utility called ZX-Editor. This
|
|
utility gives documents the look and feel of ZX-Spectrum and its documents can
|
|
contain text, graphics (with Spectrum attributes), different type faces,
|
|
colours, etc. Normally these files use extension .ZED. Also the description is
|
|
added, in case you want to use it for something else than 'Instructions' - you
|
|
can use it for MAPs, etc.
|
|
00h 16 Custom block ID ("ZX-Edit document")
|
|
10h 4 Length of data that follow
|
|
14h 1 Description length (L) (if 0 then handle it as 'Instructions')
|
|
15h L Description of the document in ASCII format
|
|
15h+L .. The ZX-Editor document (.ZED file)
|
|
|
|
Picture block (v1.12..v1.13 only)
|
|
Finally you can include any picture (in supported formats) in the TZX file too.
|
|
So cover pictures, maps, etc. can now be included in full colour (or whatever
|
|
the formats supports). The best way for utilities to use this block is to spawn
|
|
an external viewer, or the authors can write their own viewers (yeah, right ;)
|
|
). For inlay cards and other pictures that have zillions of colours use the
|
|
JPEG format, for more simple pictures (drawing, maps, etc.) use the GIF format.
|
|
00h 16 Custom block ID ("Picture" + 9 spaces)
|
|
10h 4 Length of data that follow
|
|
14h 1 Picture format (00h=GIF, 1=JPEG)
|
|
15h 1 Description length (L) (if 0 then handle it as 'Inlay Card')
|
|
16h L Description of the document in ASCII format
|
|
16h+L .. The picture itself
|
|
|
|
Spectrum Cassette TZX Notes
|
|
---------------------------
|
|
|
|
Format revision: v1.20, 19 Dec 2006
|
|
|
|
Introduction
|
|
TZX is a file format designed to preserve all (hopefully) of the tapes with
|
|
turbo or custom loading routines. Even though some of the newer and 'smarter'
|
|
emulators can find most of the info about the loader from the code itself, this
|
|
isn't possible if you want to save the file to tape, or to a real Spectrum. And
|
|
with all this information in the file, the emulators don't have to bother with
|
|
finding out the timings and other things.
|
|
This file format is explicitly targeted to the ZX Spectrum compatible computers
|
|
only. Specialized versions of the TZX format have been defined for other
|
|
machines too, e.g. the Amstrad CPC and C64, but they are now available as
|
|
distinct file formats with other filename extensions.
|
|
At the end of this document you can find a description of encoding differences
|
|
between these machines and a table which displays timings used by their
|
|
respective BIOS loading routines (some of them are not official). If you know
|
|
of any other machines that have similar encoding that could be represented with
|
|
this file format then let us know.
|
|
|
|
If you're looking for TZX files, you can find an extensive collection at
|
|
Martijn van der Heide's 'World of Spectrum'.
|
|
|
|
The format was first started off by Tomaz Kac who was maintainer until revision
|
|
1.13, and then passed to Martijn v.d. Heide. After that, Ramsoft were the
|
|
maintainers for a brief period during which the v1.20 revision was put
|
|
together. If you have any questions about the format, visit the forums at World
|
|
of Spectrum and ask.
|
|
|
|
The default format file extension is "TZX" and hopefully this won't have to
|
|
change in the future; for RISC OS, the current TAP file type will be used.
|
|
Amstrad CPC files should use the extension "CDT" to distinguish them from the
|
|
ZX Spectrum files, otherwise the inner structure is totally the same.
|
|
|
|
Rules and definitions
|
|
- All values are stored in little endian format (i.e. LSB first)
|
|
- All unused bits should be set to zero
|
|
- All timings are given in 3.5MHz clock cycles (unless otherwise stated)
|
|
- All ASCII texts use the ISO 8859-1 (Latin 1) encoding
|
|
- Some ASCII texts can have several lines, to be separated by chr(0Dh)
|
|
- MSB = most significant byte, LSB = least significant byte
|
|
- MSb = most significant bit, LSb = least significant bit
|
|
- The values in curly brackets {} are the default values as used by BIOS
|
|
|
|
High and low levels
|
|
This document refers to 'high' and 'low' pulse levels. Whether this is
|
|
implemented as ear=1 and ear=0 respectively or the other way around is not
|
|
important, as long as it is done consistently.
|
|
Zeros and ones in 'Direct recording' blocks mean low and high pulse levels
|
|
respectively. The 'current pulse level' after playing a Direct Recording block
|
|
of CSW recording block is the last level played.
|
|
The 'current pulse level' after playing the blocks ID 10h,11h,12h,13h,14h or
|
|
19h is the opposite of the last pulse level played, so that a subsequent pulse
|
|
will produce an edge.
|
|
An emulator should put the 'current pulse level' to 'low' when starting to play
|
|
a TZX file, either from the start or from a certain position. The writer of a
|
|
TZX file should ensure that the 'current pulse level' is well-defined in every
|
|
sequence of blocks where this is important, i.e. in any sequence that includes
|
|
a 'Direct recording' block, or that depends on edges generated by 'Pause'
|
|
blocks. The recommended way of doing this is to include a Pause after each
|
|
sequence of blocks.
|
|
|
|
Silence (pause, stop, end of tzx file)
|
|
Some blocks allow to define a pause of N milliseconds (ms) duration. If the old
|
|
level was low, then the first 1 ms of that pause should be high (required to
|
|
terminate the last pulse), and the remaining N-1 ms should be low. If the old
|
|
level was high, then the full N ms should be low.
|
|
The same requirement applies also when stopping the tape (on stop command, or
|
|
at end of tzx file): if the old level was low, then output 1ms high before
|
|
stopping the motor (required because some files do not include a pause after
|
|
the last data block which would imply the 1ms thing)
|
|
Pause of 0 ms duration is completely ignored, so the 'current pulse level' will
|
|
NOT change in this case. If there is no pause between two data blocks then the
|
|
second one should follow immediately; not even so much as one T state between
|
|
them.
|
|
|
|
Machine specific information
|
|
Currently supported machines are: ZX Spectrum, Amstrad CPC, SAM Coupe, ZX-81
|
|
Jupiter ACE and Enterprise. Only ZX-81 (or the old Timex 1000) and Jupiter ACE
|
|
use different tape encoding than the others.
|
|
|
|
Jupiter ACE encoding
|
|
See a dedicated site.
|
|
|
|
ZX Spectrum, Amstrad CPC, SAM Coupe & Enterprise tape encoding
|
|
These computers share the same tape encoding, which is normal frequency type
|
|
encoding. Each bit is represented by one 'wave' of different duration for bit 0
|
|
and bit 1. Normally bit 1 is twice as big as bit 0. In the blocks, the timings
|
|
are presented with Z80 T-states (cycles) per pulse. One wave is made from two
|
|
pulses.
|
|
The standard data blocks have always the same structure: first there is the
|
|
PILOT tone, then the two SYNC pulses (one wave) and after that the actual DATA
|
|
(which can include a FLAG byte at the beginning and a CHECKSUM byte at the
|
|
end).
|
|
Here is a table showing the pulse timings for each part of the standard BIOS
|
|
load/save routine for each of these machines. If you have more accurate
|
|
information then we would be glad to include it here. Enterprise has two
|
|
loading speeds so timings for both are included.
|
|
Machine Pilot pulse Length Sync1 Sync2 Bit 0 Bit 1
|
|
ZX Spectrum 2168 (1) 667 735 855 1710
|
|
SAM Coupe' 58+19*W 6000 58+9*W 113+9*W 10+8*W 42+15*W (*)
|
|
Amstrad CPC Bit 1 4096 Bit 0 Bit 0 (2) (2)
|
|
Enterprise (fast) 742 ? 1280 1280 882 602 (**)
|
|
Enterprise (slow) 1750 ? 2800 2800 1982 1400 (**)
|
|
Notes:
|
|
(1) The Spectrum uses different pilot lengths for header and data blocks.
|
|
Header blocks have 8063 and data blocks have 3223 pilot pulses.
|
|
(2) Amstrad CPC BIOS load/save routine can use variable speed for loading,
|
|
so the bit 1 pulse must be read from the pilot tone and bit 0 can be
|
|
read from the sync pulses, and is always half the size of bit 1. The
|
|
checksum is also different than the other two machines. The speed can
|
|
vary from 1000 to 2000 baud.
|
|
(*) The SAM Coupe' timings can be user selected by a system variable. The
|
|
standard value is 112, which is VERY close to ZX Spectrum loading
|
|
speed, and therefore the 'Standard Speed Data' block can be used for
|
|
those blocks. However if this system variable is changed then the
|
|
timings will change accordingly. In the above table the value of this
|
|
variable is given as 'W', the 'H' value is 'W/2'. Of course the best
|
|
way to determine it is to calculate it from the timings you get when
|
|
sampling the Pilot tone. The values in the table could be by a
|
|
fraction of the real ones, but it should not matter. Note: All timings
|
|
are written in 3.5MHz clock. Also, there might be some junk bits
|
|
(usually 7 or 8) AFTER the checksum (XOR) byte at the end of the
|
|
block, but they can just be ignored.
|
|
(**) The Enterprise stores data in a different way than all other computers
|
|
do. It stores the LSb first, but the data blocks require the data to
|
|
be MSb first. This might lead to some confusion, but if the same
|
|
mechanism is used to replay data for all machines then there will be
|
|
no problem. Just store the data as MSb first, but if you want to view
|
|
the raw data in the TZX file then you will have to mirror each byte to
|
|
get the correct values.
|
|
IMPORTANT: The ZXTape format has ALL timings written according to a 3.5MHz
|
|
clock (the standard Spectrum 16/48K clock), so if the tape should be used on an
|
|
Amstrad CPC with 4MHz clock then you should multiply ALL timings with 4/3.5
|
|
when you use that tape (this should be trivial). Similarly goes for SAM Coupe,
|
|
that uses a 6MHz clock and Jupiter ACE that uses 3.2448 MHz and Enterprise that
|
|
uses 4 MHz!
|
|
|
|
Spectrum Interface 1 (Microdrive, Network, RS232)
|
|
-------------------------------------------------
|
|
|
|
Sinclair Interface 1 Features
|
|
Allows to connect up to 8 Microdrives (endless tape drives), allows to set up a
|
|
network with up to 64 computers, allows to connect a RS232 printer.
|
|
|
|
Memory Mapped Ports
|
|
0008h,1708h - Interface 1 - Enable external ROM (8K) (error and close#)
|
|
0700h - Interface 1 - Disable external ROM (8K) (ret)
|
|
|
|
Port E7h (R/W)
|
|
0-7 Microdrive Data (send/receive)
|
|
Accessing this port will HALT the Z80 until the Interface I has collected 8
|
|
bits from the microdrive head; therefore, if the microdrive motor isn't
|
|
running, or there is no formatted cartridge in the microdrive, the Spectrum
|
|
hangs. This is the famous 'IN 0 crash'.
|
|
|
|
Port EFh (R)
|
|
0 Microdrive Write Protected
|
|
1 Microdrive Sync
|
|
2 Microdrive Gap
|
|
3 RS232 DTR
|
|
4 Busy (what busy?)
|
|
5-7 Not used
|
|
|
|
Port EFh (W)
|
|
0 Microdrive Comms Data (and Mode for Write to PortF7.Bit0)
|
|
1 Microdrive Comms Clk
|
|
2 Microdrive R/W
|
|
3 Microdrive Erase
|
|
4 RS232 CTS
|
|
5 Network Wait (used to synchronize)
|
|
6-7 Not used
|
|
|
|
Port F7h (R)
|
|
0 Network Input
|
|
1-6 Not used
|
|
7 RS232 TXDATA
|
|
|
|
Port F7h (W)
|
|
0 Network Output or RS232 RXDATA (depending on Port EFh.Bit0.Write)
|
|
1-7 Not used
|
|
If the microdrive is not being used, the COMMS DATA output selects the function
|
|
of bit0 of out-port F7h.
|
|
|
|
Spectrum Disc Spectrum +3 Disc Controller (NEC uPD765)
|
|
------------------------------------------------------
|
|
|
|
The Spectrum +3 uses Plus3DOS (which is based on AMSDOS for Amstrad CPC), like
|
|
the CPC it's using a NEC uPD765 floppy disk controller.
|
|
|
|
Port 1FFDh - Spectrum +2A/+3 Memory Control B and Disk Motor (W)
|
|
Port 2FFDh - Spectrum +3 Floppy FDC NEC uPD765 status (R)
|
|
Port 3FFDh - Spectrum +3 Floppy FDC NEC uPD765 data (R/W)
|
|
|
|
Accessing the FDC 765
|
|
The Data Register (Port 3FFDh) is used to write Commands and Parameters, to
|
|
read/write data bytes, and to receive result bytes. These three operations are
|
|
called Command-, Execution-, and Result-Phase. The Main Status Register
|
|
signalizes when the FDC is ready to send/receive the next byte through the Data
|
|
Register.
|
|
|
|
Command Phase
|
|
A command consists of a command byte (eventually including the MF, MK, SK
|
|
bits), and up to eight parameter bytes.
|
|
|
|
Execution Phase
|
|
During this phase, the actual data is transferred (if any). Usually that are
|
|
the data bytes for the read/written sector(s), except for the Format Track
|
|
Command, in that case four bytes for each sector are transferred.
|
|
|
|
Result Phase
|
|
Returns up to seven result bytes (depending on the command) that are containing
|
|
status information. The Recalibrate and Seek Track commands do not return
|
|
result bytes directly, instead the program must wait until the Main Status
|
|
Register signalizes that the command has been completed, and then it must (!)
|
|
send a Sense Interrupt State command to 'terminate' the Seek/Recalibrate
|
|
command.
|
|
|
|
FDC Command Table
|
|
Command Parameters Exm Result Description
|
|
02+MF+SK HU TR HD ?? SZ NM GP SL <R> S0 S1 S2 TR HD NM SZ read track
|
|
03 XX YY - specify spd/dma
|
|
04 HU - S3 sense drive state
|
|
05+MT+MF HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ write sector(s)
|
|
06+MT+MF+SK HU TR HD SC SZ LS GP SL <R> S0 S1 S2 TR HD LS SZ read sector(s)
|
|
07 HU - recalib.seek TP=0
|
|
08 - - S0 TP sense int.state
|
|
09+MT+MF HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ wr deleted sec(s)
|
|
0A+MF HU - S0 S1 S2 TR HD LS SZ read ID
|
|
0C+MT+MF+SK HU TR HD SC SZ LS GP SL <R> S0 S1 S2 TR HD LS SZ rd deleted sec(s)
|
|
0D+MF HU SZ NM GP FB <W> S0 S1 S2 TR HD LS SZ format track
|
|
0F HU TP - seek track n
|
|
11+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan equal
|
|
19+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan low or equal
|
|
1D+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan high or eq.
|
|
|
|
Parameter bits that can be specified in some Command Bytes are:
|
|
MT Bit7 Multi Track (continue multi-sector-function on other head)
|
|
MF Bit6 MFM-Mode-Bit (Default 1=Double Density)
|
|
SK Bit5 Skip-Bit (set if secs with deleted DAM shall be skipped)
|
|
|
|
Parameter/Result bytes are:
|
|
HU b0,1=Unit/Drive Number, b2=Physical Head Number, other bits zero
|
|
TP Physical Track Number
|
|
TR Track-ID (usually same value as TP)
|
|
HD Head-ID
|
|
SC First Sector-ID (sector you want to read)
|
|
SZ Sector Size (80h shl n) (default=02h for 200h bytes)
|
|
LS Last Sector-ID (should be same as SC when reading a single sector)
|
|
GP Gap (default=2Ah except command 0D: default=52h)
|
|
SL Sectorlen if SZ=0 (default=FFh)
|
|
Sn Status Register 0..3
|
|
FB Fillbyte (for the sector data areas) (default=E5h)
|
|
NM Number of Sectors (default=09h)
|
|
XX b0..3=headunload n*32ms (8" only), b4..7=steprate (16-n)*2ms
|
|
YY b0=DMA_disable, b1-7=headload n*4ms (8" only)
|
|
|
|
Format Track: output TR,HD,SC,SZ for each sector during execution phase
|
|
Read Track: reads NM sectors (starting with first sec past index hole)
|
|
Read ID: read ID bytes for current sec, repeated/undelayed read lists all IDs
|
|
Recalib: walks up to 77 tracks, 80tr-drives may need second recalib if failed
|
|
Seek/Recalib: All read/write commands will be disabled until succesful senseint
|
|
Senseint: Set's IC if unsuccesful (no int has occured) (until IC=0)
|
|
|
|
FDC Status Registers
|
|
The Main Status register can be always read through Port 2FFDh. The other four
|
|
Status Registers cannot be read directly, instead they are returned through the
|
|
data register as result bytes in response to specific commands.
|
|
|
|
Main Status Register (Port 2FFDh)
|
|
b0..3 DB FDD0..3 Busy (seek/recalib active, until succesful sense intstat)
|
|
b4 CB FDC Busy (still in command-, execution- or result-phase)
|
|
b5 EXM Execution Mode (still in execution-phase, non_DMA_only)
|
|
b6 DIO Data Input/Output (0=CPU->FDC, 1=FDC->CPU) (see b7)
|
|
b7 RQM Request For Master (1=ready for next byte) (see b6 for direction)
|
|
Status Register 0
|
|
b0,1 US Unit Select (driveno during interrupt)
|
|
b2 HD Head Adress (head during interrupt)
|
|
b3 NR Not Ready (drive not ready or non-existing 2nd head selected)
|
|
b4 EC Equipment Check (drive failure or recalibrate failed (retry))
|
|
b5 SE Seek End (Set if seek-command completed)
|
|
b6,7 IC Interrupt Code (0=OK, 1=aborted:readfail/OK if EN, 2=unknown cmd
|
|
or senseint with no int occured, 3=aborted:disc removed etc.)
|
|
Status Register 1
|
|
b0 MA Missing Adress Mark (Sector_ID or DAM not found)
|
|
b1 NW Not Writeable (tried to write/format disc with wprot_tab=on)
|
|
b2 ND No Data (Sector_ID not found, CRC fail in ID_field)
|
|
b3,6 0 Not used
|
|
b4 OR Over Run (CPU too slow in execution-phase (ca. 26us/Byte))
|
|
b5 DE Data Error (CRC-fail in ID- or Data-Field)
|
|
b7 EN End of Track (set past most read/write commands) (see IC)
|
|
Status Register 2
|
|
b0 MD Missing Address Mark in Data Field (DAM not found)
|
|
b1 BC Bad Cylinder (read/programmed track-ID different and read-ID = FF)
|
|
b2 SN Scan Not Satisfied (no fitting sector found)
|
|
b3 SH Scan Equal Hit (equal)
|
|
b4 WC Wrong Cylinder (read/programmed track-ID different) (see b1)
|
|
b5 DD Data Error in Data Field (CRC-fail in data-field)
|
|
b6 CM Control Mark (read/scan command found sector with deleted DAM)
|
|
b7 0 Not Used
|
|
Status Register 3
|
|
b0,1 US Unit Select (pin 28,29 of FDC)
|
|
b2 HD Head Address (pin 27 of FDC)
|
|
b3 TS Two Side (0=yes, 1=no (!))
|
|
b4 T0 Track 0 (on track 0 we are)
|
|
b5 RY Ready (drive ready signal)
|
|
b6 WP Write Protected (write protected)
|
|
b7 FT Fault (if supported: 1=Drive failure)
|
|
|
|
Motor On/Off Flipflop
|
|
The motor is controlled via a bit in Port 1FFDh (see ULA chapter), the bit
|
|
controls motors for ALL drive(s), it is not possible to turn on/off the motor
|
|
of a specific drive separately.
|
|
|
|
Notes:
|
|
Before accessing a disk you should first Recalibrate the drive, that'll move
|
|
the head backwards until it reaches Track 0 (that's required to initialize the
|
|
FDCs track counter). On a 80 track drive you may need to repeat that in case
|
|
that the first recalibration attempt wasn't successful (that's because the FDC
|
|
stops searching after 77 steps).
|
|
|
|
Now if you want to format, read or write a sector on a specific track you must
|
|
first Seek that track (command 0Fh). That'll move the read/write head to the
|
|
physical track number. If you don't do that, then the FDC will attempt to
|
|
read/write data to/from the current physical track, independendly of the
|
|
specified logical Track-ID.
|
|
|
|
The Track-, Sector-, and Head-IDs are logical IDs only. These logical IDs are
|
|
defined when formatting the disk, and aren't required to be identical to the
|
|
physical Track, Sector, or Head numbers. However, when reading or writing a
|
|
sector you must specify the same IDs that have been used during formatting.
|
|
|
|
Despite of the confusing name, a sector with a "Deleted Data Address Mark"
|
|
(DAM) is not deleted. The DAM-flag is just another ID-bit, and (if that ID-bit
|
|
is specified correctly in the command) it can be read/written like normal data
|
|
sectors.
|
|
|
|
At the end of a successful read/write command, the program should send a
|
|
Terminal Count (TC) signal to the FDC. However, in the CPC (and probably also
|
|
in the Spectrum) the TC pin isn't connected to the I/O bus, making it
|
|
impossible for the program to confirm a correct operation. For that reason, the
|
|
FDC will assume that the command has failed, and it'll return both Bit 6 in
|
|
Status Register 0 and Bit 7 in Status Register 1 set. The program should ignore
|
|
this errormessage.
|
|
|
|
The CPC doesn't support floppy DMA transfers, and the FDCs Interrupt signal
|
|
isn't used in the CPC also.
|
|
|
|
Usually single sided 40 Track 3" disk drives are used in CPCs, whereas 40
|
|
tracks is the official specification, practically 42 tracks could be used. The
|
|
FDC controller can be used to control 80 tracks, and/or double sided drives
|
|
also, even though AMSDOS isn't supporting such formats. AMSDOS is supporting a
|
|
maximum of two disk drives only.
|
|
|
|
Spectrum Disc Opus Discovery
|
|
----------------------------
|
|
|
|
MEM:0008h,0048h,1708h - Discovery - Enable external ROM/RAM/WD/PIA
|
|
MEM:1748h - Discovery - Disable external ROM/RAM/WD/PIA
|
|
Opcode fetches from these addresses enable/disable the Discovery hardware, when
|
|
enabled, the following is mapped to first 16K of memory:
|
|
0000-1FFF ROM (8K)
|
|
2000-27FF RAM (2K)
|
|
2800-2803 WD 1770 Ports (floppy controller)
|
|
3000-3003 PIA 6821 Ports (drive/side select, centronics etc.)
|
|
|
|
DRQ (Data Request)
|
|
The DRQ output from WD 1770 is inverted and connected to /NMI input (unlike as
|
|
most other drives which map DRQ to a status register bit, and which use /NMI as
|
|
snapshot button).
|
|
|
|
MEM:2800h - FDC Command (W)
|
|
MEM:2800h - FDC Status (R)
|
|
MEM:2801h - FDC Track (R/W)
|
|
MEM:2802h - FDC Sector (R/W)
|
|
MEM:2803h - FDC Data (R/W)
|
|
--> Spectrum Disc Controller (Western Digital WD177x)
|
|
|
|
MEM:3000h when CRA.Bit2=1 - PIA Peripheral Interface A (PA0..7)
|
|
MEM:3000h when CRA.Bit2=0 - PIA Data Direction Reg. A (0=Input, 1=Output)
|
|
MEM:3001h - PIA Control Register A (CRA)
|
|
MEM:3002h when CRB.Bit2=1 - PIA Peripheral Interface B (PA0..7)
|
|
MEM:3002h when CRB.Bit2=0 - PIA Data Direction Reg. B (0=Input, 1=Output)
|
|
MEM:3003h - PIA Control Register B (CRB)
|
|
The PIA 6821 lines are connected as such:
|
|
PA0 drive 2 select (and enable motors for both drives)
|
|
PA1 drive 1 select (and enable motors for both drives)
|
|
PA4 side select
|
|
PA5 double density enable
|
|
PA6 centronics busy (input)
|
|
PA7 enable kempston joystick port on A5=0 (from BASIC: type FORMAT "j";1)
|
|
PB0..7 centronics data
|
|
CA2 centronics ack
|
|
CB2 centronics strobe
|
|
The PA2,PA3,CA1,CB1,/IRQA,/IRQB pins are not used.
|
|
|
|
PIA Control Register A (CRA)
|
|
0 CA1 Input Control (0..3)
|
|
0 = Set IRQA1 when CA1=Negative, but do not trigger /IRQA
|
|
1 = Set IRQA1 when CA1=Negative, and do trigger /IRQA
|
|
2 = Set IRQA1 when CA1=Positive, but do not trigger /IRQA
|
|
3 = Set IRQA1 when CA1=Positive, and do trigger /IRQA
|
|
2 DDRA Access (0=Data Direction Register A, 1=Data Register A)
|
|
3-5 CA2 Input/Output Control (0..7)
|
|
0 = Set IRQA2 when CA2=Negative, but do not trigger /IRQA
|
|
1 = Set IRQA2 when CA2=Negative, and do trigger /IRQA
|
|
2 = Set IRQA2 when CA2=Positive, but do not trigger /IRQA
|
|
3 = Set IRQA2 when CA2=Positive, and do trigger /IRQA
|
|
4 = Handshake Output Mode (CA2=High on CA1, CA2=Low on "Read A Data")
|
|
5 = Pulse Output Mode (CA2=Low for 1 clk after "Read A Data")
|
|
6 = Manual Output, set CA2=Low
|
|
7 = Manual Output, set CA2=High
|
|
6 IRQA2 Flag (CA2 input)
|
|
7 IRQA1 Flag (CA1 input)
|
|
|
|
PIA Control Register B (CRB)
|
|
Same as CRA, but using Port B, CB1, CB2, IRQB, etc. And, CRB handshake/pulse
|
|
modes are bound to "Write B Data" instead of "Read A Data" conditions.
|
|
|
|
IO:1Fh - Discovery Joystick Port (uses A5 only, eg. mirrored to DFh)
|
|
0-4 Kempston Joystick (disabled by default)
|
|
5-7 Not used
|
|
Unlike normal kempston joystick ports this port is disabled by default
|
|
(presumably for best compatibility with other hardware that uses Port 1Fh, or
|
|
mirrors like DFh, for something else). The port can be enabled via PA7 bit, or
|
|
by typing FORMAT "j";1 in BASIC (type ;0 to disable it again).
|
|
|
|
PIA 6821 Pin-Outs
|
|
1 VSS 6 PA4 11 PB1 16 PB6 21 R/W 26 D7 31 D2 36 RS1(A1)
|
|
2 PA0 7 PA5 12 PB2 17 PB7 22 CS0 27 D6 32 D1 37 /IRQB
|
|
3 PA1 8 PA6 13 PB3 18 CB1 23 /CS2 28 D5 33 D0 38 /IRQA
|
|
4 PA2 9 PA7 14 PB4 19 CB2 24 CS1 29 D4 34 /RES 39 CA2
|
|
5 PA3 10 PB0 15 PB5 20 VCC 25 PHI2 30 D3 35 RS0(A0) 40 CA1
|
|
|
|
DOS Replacement for Opus Discovery
|
|
The MegaSoft QuickDOS package consists of a disc, manual, and replacement ROM
|
|
which contains faster load/save routines than the original Opus ROM.
|
|
|
|
Spectrum Disc Disciple and Plus D
|
|
---------------------------------
|
|
|
|
The Disciple and PlusD are both developed by Miles Gordon Technology, both
|
|
contain 16K ROM, 8K RAM, a Snapshot/NMI button (works only when SHIFT held
|
|
down?), a Western Digital disk controller, and a centronics port (although
|
|
using different I/O addresses).
|
|
The older Disciple (1987) does additionally contain Joystick and Network ports,
|
|
and a feature to swap ROM and RAM addresses, and a Inhibit button (to lock out
|
|
the interface). The newer PlusD (1988) does not include these extras (so the
|
|
"Plus D" is actually a "Disciple Minus Extras").
|
|
|
|
1Bh/E3h Disciple/PlusD - FDC Command (W)
|
|
1Bh/E3h Disciple/PlusD - FDC Status (R)
|
|
5Bh/EBh Disciple/PlusD - FDC Track (R/W)
|
|
9Bh/F3h Disciple/PlusD - FDC Sector (R/W)
|
|
DBh/FBh Disciple/PlusD - FDC Data (R/W)
|
|
--> Spectrum Disc Controller (Western Digital WD177x)
|
|
|
|
EFh PlusD only - PlusD Control Register (W)
|
|
0 Drive A Select
|
|
1 Drive B Select
|
|
2 Single/double density
|
|
3 ROM bank select (first/second 8K of total 16K ROM)
|
|
4 Not used
|
|
5 Ext. select (?)
|
|
6 Centronics Strobe
|
|
7 Side select
|
|
|
|
1Fh Disciple only - Disciple Control Register (W)
|
|
0 Drive select
|
|
1 Side select
|
|
2 Single/double density
|
|
3 ROM bank select (first/second 8K of total 16K ROM)
|
|
4 Inhibit switch control
|
|
5 Ext. select (?)
|
|
6 Centronics Strobe
|
|
7 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 Year TRDOS Description
|
|
Beta 1984 v1 original version
|
|
Beta Plus 1985 v4 auto-boot, drive-detect, magic-button, seq/rnd access
|
|
Beta 128 1986 v5.0x changed USR addresses, auto-boot-disable-switch
|
|
Pentagon 1989 v5.0x russian spectrum clone with beta 128 disk interface
|
|
|
|
Features
|
|
The Interface is quite simple, it consists of the TRDOS ROM, the FDC chip, and
|
|
eventually a Magic button and/or Reset button. It doesn't include RAM, nor any
|
|
extras like Centronics or Joystick ports.
|
|
Since there's no built-in RAM, it allocates 70h bytes at 5CB6h (or at higher
|
|
address if other hardware like Interface 1 has already allocated memory).
|
|
Additionally, it does temporarily allocate a 100h bytes as sector buffer while
|
|
accessing the disk.
|
|
|
|
MEM:3C00h..3CFFh - Enable ROM & I/O Ports (Beta/TRDOSv1 and BetaPlus/TRDOSv4)
|
|
MEM:3D00h..3DFFh - Enable ROM & I/O Ports (Beta128/TRDOSv5.0x)
|
|
The enable region was originally at 3Cxxh (which is FFh-filled in Spectrum
|
|
16K/48K/Plus BIOSes), and was invoked via RANDOMIZE USR 15360 and 15363 from
|
|
BASIC. For compatibility with the Spectrum 128 (which contains BIOS code in
|
|
that region), the region was moved to 3Dxxh (which contains only character set
|
|
data, but no program code) and is now invoked via USR 15616 and 15619. The
|
|
first address is used to enter TRDOS,
|
|
RANDOMIZE USR 15360 or 15616 --> switch from BASIC to TRDOS ;3C00h/3D00h
|
|
RETURN (aka Y-key) --> switch from TRDOS to BASIC
|
|
The second address is used as prefix to normal BASIC commands, eg.:
|
|
RANDOMIZE USR 15363 or 15619:REM:LOAD"filename" ;3C03h/3D03h
|
|
|
|
MEM:4000h..FFFFh - Disable ROM & I/O Ports (all versions)
|
|
Opcode fetches outside of the ROM region (ie. at 4000h..FFFFh) do automatically
|
|
disable the TRDOS ROM and I/O ports.
|
|
|
|
MEM:0000h? - Enable ROM & I/O Ports (BetaPlus/TRDOSv4 and Beta128/TRDOSv5.0x)
|
|
The Beta Plus and Beta 128 have an Auto-Boot feature that automatically enters
|
|
TRDOS instead of BASIC on power-up. Unknown which opcode address activates
|
|
TRDOS... probably 0000h.
|
|
The Auto-Boot feature works only on Spectrum 48K/Plus, but isn't compatible
|
|
with the Spectrum 128 (the Beta 128 includes a "system switch" that allows to
|
|
disable auto-boot for Spectrum 128 compatibility, ie. on the Spectrum 128 TRDOS
|
|
can be started only manually via RANDOMIZE USR 15616).
|
|
|
|
MEM:0066h? - Enable ROM & I/O Ports (BetaPlus/TRDOSv4 and Beta128/TRDOSv5.0x)
|
|
The Beta Plus and Beta 128 have a Magic button, presumably triggering an /NMI
|
|
and thus needing to enable ROM on address 0066h (?) although in poor quality
|
|
schematics it looks more like /RESET than /NMI. The button does usually allow
|
|
to save snapshots (except, on the Scorpion, it launches a Service-Monitor
|
|
program).
|
|
|
|
I/O Port Activation
|
|
Below I/O ports are enabled only while the ROM is enabled, too. Ie. when
|
|
disabled, there's no conflict with Kempston Joysticks (Port 1Fh) or with the
|
|
VRAM Garbage effect (Port FFh). Mind that ROM and I/O ports are automatically
|
|
disabled when accessing opcodes at 4000h..FFFFh (so the I/O ports can be
|
|
accessed ONLY from inside of the TRDOS ROM).
|
|
|
|
1Fh - Beta Disk FDC Command (W)
|
|
1Fh - Beta Disk FDC Status (R)
|
|
3Fh - Beta Disk FDC Track (R/W)
|
|
5Fh - Beta Disk FDC Sector (R/W)
|
|
7Fh - Beta Disk FDC Data (R/W)
|
|
--> Spectrum Disc Controller (Western Digital WD177x)
|
|
According to some untitled schematics, the interface uses a FD1793-02 chip
|
|
(which is maybe correct), according to Sinclair User magazine it uses a 1771
|
|
chip (such a thing probably doesn't exist at all), according to russian source
|
|
it uses a KR1818VG93 aka VG93 chip (which is probably a 1793 clone).
|
|
|
|
FFh - Beta Disk Status (R)
|
|
0-5 Unused?
|
|
6 DRQ (data request)
|
|
7 INTRQ (command completion)
|
|
|
|
FFh - Beta Disk Control (W?)
|
|
0-1 Drive select (0..3 = Drive A..D)
|
|
2 Hardware microcontroller reset (0=reset, 1=normal)
|
|
3 Blocks signal HLT of microcontroller (=disk controller?) (1=normal)
|
|
4 Head select (0=First/bottom, 1=Second/Top)
|
|
5 Density select (0=FM, 1=MFM)
|
|
6-7 Unused
|
|
|
|
Spectrum Disc Controller (Western Digital WD177x)
|
|
-------------------------------------------------
|
|
|
|
Command description
|
|
Commands should only be loaded in the Command Register when the Busy status bit
|
|
is off (Status bit 0). The one exception is the Force Interrupt command.
|
|
Whenever a command is being executed, the Busy status bit is set.
|
|
At the completion of every command an INTRQ is generated. INTRQ is reset by
|
|
either reading the status register or by loading the command register with a
|
|
new command. In addition, INTRQ is generated if a Force Interrupt command
|
|
condition is met.
|
|
When a command is completed, an interrupt is generated and the busy status bit
|
|
is reset. The Status Register indicates whether the completed command
|
|
encountered an error or was fault free.
|
|
|
|
Command Summary (models 1791, 1792, 1793, 1794) (and 1770,1772,1773)
|
|
Type Command b7 b6 b5 b4 b3 b2 b1 b0
|
|
I Restore 0 0 0 0 h/M V r1 r0
|
|
I Seek 0 0 0 1 h/M V r1 r0
|
|
I Step 0 0 1 T h/M V r1 r0
|
|
I Step-In 0 1 0 T h/M V r1 r0
|
|
I Step-Out 0 1 1 T h/M V r1 r0
|
|
II Read Sector 1 0 0 m S/M E C/0 0
|
|
II Write Sector 1 0 1 m S/M E C/P a0
|
|
III Read Address 1 1 0 0 0/M E 0 0
|
|
III Read Track 1 1 1 0 0/M E 0 0
|
|
III Write Track 1 1 1 1 0/M E 0/P 0
|
|
IV Force Interrupt 1 1 0 1 i3 i2 i1 i0
|
|
|
|
Flag Summary
|
|
r1,r0 Stepping Motor Rate (0..3 = 6ms,12ms,20ms,30ms) (WD179X,WD1770/WD1773)
|
|
r1,r0 Stepping Motor Rate (0..3 = 2ms,3ms,5ms,6ms) (WD1772 Preliminary docs)
|
|
r1,r0 Stepping Motor Rate (0..3 = 6ms,12ms,2ms,3ms) (WD1772 Other docs... ?)
|
|
V Track Number Verify Flag (0: no verify, 1: verify on dest track)
|
|
h Head Load Flag (1: load head at beginning, 0: unload head) (WD179X)
|
|
T Track Update Flag (0: no update, 1: update Track Register)
|
|
a0 Data Address Mark (0: FB, 1: F8 (deleted DAM))
|
|
C Side Compare Flag (0: disable, 1: enable) (WD179X only) (and WD1773?)
|
|
E 15 ms delay (0: no 15ms delay, 1: 15 ms delay)
|
|
S Side Compare Flag (0: compare for side 0, 1: compare for side 1)
|
|
m Multiple Record Flag (0: single record, 1: multiple records)
|
|
P Write Precompensation (0=On, 1=Off) (WD1770/WD1772 only) (and WD1773?)
|
|
M Motor On (0=on, 1=off) (WD1770/WD1772 only)
|
|
Interrupt Condition Flags
|
|
i3-i0 0 = Terminate with no interrupt (INTRQ)
|
|
i3 1 = Immediate interrupt, requires a reset
|
|
i2 1 = Index pulse
|
|
i1 1 = Ready to not ready transition (Not used on WD1770/WD1772)
|
|
i0 1 = Not ready to ready transition (Not used on WD1770/WD1772)
|
|
|
|
Type I commands (Restore, Seek, Step-Out, Step-In, Step)
|
|
Used to move the read/write head. The stepping motor rate should be usally set
|
|
to 6ms (r1 and r0 bits set to zero) for a 3.5-inch floppy disk drive. An
|
|
optional verification of head position can be performed by setting bit 2 (V=1)
|
|
in the command word.
|
|
|
|
When V=1: When the seek is completed, the drive automatically goes into read
|
|
mode, the track number from the first encountered Sector ID Field is then
|
|
compared against the contents of the Track Register (or Data Register?), if the
|
|
track numbers compare (and the ID Field CRC is correct) the verify operation is
|
|
complete and an INTRQ is generated with no errors. If these track numbers do
|
|
not match, the Seek Error bit of the status register is set.
|
|
|
|
When V=0: When the seek is completed, the track position is not verified (this
|
|
mode is required for unformatted disks). The command ends once the last step
|
|
pulse is output. Since the result is that there is not enough time for step
|
|
stability, the host system must use its software to make the floppy disk wait a
|
|
certain period before reading or writing the track just arrived at.
|
|
|
|
When the seek command is complete, the interrupt request is set and at the same
|
|
time, the Busy bit in the status register is set to 0. When the CPU reads the
|
|
status register, it resets the interrupt request signal.
|
|
|
|
Restore (Seek Track 0)
|
|
If TR00 is not active, stepping pulses are issued until the TR00 input is
|
|
activated. The Track Register is set to zero, and an interrupt is generated
|
|
when track 0 has been reached.
|
|
|
|
Seek
|
|
This command assumes that the Track Register contains the <current> position of
|
|
the head, and that the Data Register contains the <desired> destination track
|
|
number. The FD179X will update the Track Register and issue stepping pulses in
|
|
the appropriate direction until the contents of the Track and Data Register are
|
|
equal to each other. An interrupt is generated at the completion of the
|
|
command.
|
|
|
|
Step-Out, Step-In, Step
|
|
Issues one stepping pulse to the disk drive. Step-Out: towards track 0.
|
|
Step-In: towards track 76 (that feature is not useful for 80-track drives).
|
|
Step: same direction as for previous step command. The track register is
|
|
updated (ie. incremented or decremented) only if the "T" bit has been set in
|
|
the command word. An interrupt is generated at the end of each command.
|
|
|
|
Type II commands (Read Sector, Write Sector)
|
|
Prior to loading the Type II command into the Command Register, the computer
|
|
must load the Sector Register with the desired sector number. Upon receipt of
|
|
the Type II command, the busy status bit is set. The FD179X must find an ID
|
|
field with a matching Track number and Sector number, otherwise the Record not
|
|
found status bit is set and the command is terminated with an interrupt.
|
|
Each of the Type II commands contains an m flag which determines if multiple
|
|
records (sectors) are to be read or written. If m=0, a single sector is read or
|
|
written and an interrupt is generated at the completion of the command. If m=1,
|
|
multiple records are read or written with the sector register internally
|
|
updated so that an address verification can occur on the next record. The
|
|
FD179X will continue to read or write multiple records and update the sector
|
|
register in numerical ascending sequence until the sector register exceeds the
|
|
number of sectors on the track or until the Force Interrupt command is loaded
|
|
into the Command Register.
|
|
The Type II commands for 1791-94 also contain side select compare flags. When
|
|
C=0 (bit 1), no comparison is made. When C=1, the LSB of the side number is
|
|
read off the ID Field of the disk and compared with the contents of the S flag.
|
|
|
|
Read Sector
|
|
Upon receipt of the command, the head is loaded, the busy status bit set and
|
|
when an ID field is encountered that has the correct track number, correct
|
|
sector number, correct side number, and correct CRC, the data field is
|
|
presented to the computer.
|
|
An DRQ is generated each time when the CPU must read a byte from the data
|
|
register, the Lost Data bit is set if the CPU didn't read data in time, and the
|
|
Read operation continues until the end of sector is reached.
|
|
At the end of the Read operation, the type of Data Address Mark encountered in
|
|
the data field is recorded in the Status Register (bit 5).
|
|
|
|
Write Sector
|
|
Upon receipt of the command, the head is loaded, the busy status bit set and
|
|
when an ID field is encountered that has the correct track number, correct
|
|
sector number, correct side number, and correct CRC, a DRQ is generated.
|
|
The FD179X counts off 22 bytes (in double density) from the CRC field and the
|
|
Write Gate output is made active if the DRQ is serviced (ie. the DR has been
|
|
loaded by the computer). If DRQ has not been serviced, the command is
|
|
terminated and the Lost Data status bit is set. If the DRQ has been serviced,
|
|
12 bytes of zeroes (in double density) are written to the disk, then the Data
|
|
Address Mark as determined by the a0 field of the command.
|
|
The FD179X then writes the data field and generates DRQ's to the computer. If
|
|
the DRQ is not serviced in time for continuous writing the Lost Data Status bit
|
|
is set and a byte of zeroes is written on the disk and the command continues
|
|
until the last byte of the sector is reached.
|
|
After the last data byte has been written on the disk, the two-byte CRC is
|
|
computed internally and written on the disk followed by one byte of logic ones.
|
|
|
|
Type III commands
|
|
|
|
Read Address
|
|
Upon receipt of the Read Address command, the head is loaded and the Busy
|
|
Status bit is set. The next encountered ID field is then read in from the disk,
|
|
and the six data bytes of the ID field are assembled and transferred to the DR,
|
|
and a DRQ is generated for each byte. The six bytes of the ID field are : Track
|
|
address, Side number, Sector address, Sector Length, CRC1, CRC2. Although the
|
|
CRC bytes are transferred to the computer, the FD179X checks for validity and
|
|
the CRC error status bit is set if there is a CRC error. The track address of
|
|
the ID field is written into the sector register so that a comparison can be
|
|
made by the user. At the end of the operation, an interrupt is generated and
|
|
the Busy status bit is reset.
|
|
|
|
Read Track
|
|
Upon receipt of the Read Track command, the head is loaded, and the busy status
|
|
bit is set. Reading starts with the leading edge of the first encountered index
|
|
pulse and continues until the next index pulse. All gap, header, and data bytes
|
|
are assembled and transferred to the data register and DRQ's are generated for
|
|
each byte. The accumulation of bytes is synchronized to each address mark
|
|
encountered. An interrupt is generated at the completion of the command. The ID
|
|
Address Mark, ID field, ID CRC bytes, DAM, Data and Data CRC bytes for each
|
|
sector will be correct. The gap bytes may be read incorrectly during
|
|
write-splice time because of synchronization.
|
|
|
|
Write Track (formatting a track)
|
|
Upon receipt of the Write Track command, the head is loaded and the Busy Status
|
|
bit is set. Writing starts with the leading edge of the first encountered index
|
|
pulse and continues until the next index pulse, at which time the interrupt is
|
|
activated. The Data Request is activated immediately upon receiving the
|
|
command, but writing will not start until after the first byte has been loaded
|
|
into the DR. If the DR has not been loaded by the time the index pulse is
|
|
encountered, the operation is terminated making the device Not Busy, the Lost
|
|
Data status bit is set, and the interrupt is activated. If a byte is not
|
|
present in the DR when needed, a byte of zeroes is substituted. This sequence
|
|
continues from one index mark to the next index mark.
|
|
Normally, whatever data pattern appears in the data register is written on the
|
|
disk with a normal clock pattern. However, if the FD179X detects a data pattern
|
|
of F5 thru FE in the data register, this is interpreted as data address marks
|
|
with missing clocks or CRC generation. The CRC generator is initialized when an
|
|
F5 data byte is about to be transferred (in MFM). An F7 pattern will generate
|
|
two CRC bytes. As a consequence, the patterns F5 thru FE must not appear in the
|
|
gaps, data fiels, or ID fiels. Tracks may be formatted with sector lengths of
|
|
128, 256, 512 or 1024 bytes. See "Formatting" below for more info and example.
|
|
|
|
Type IV command (Force Interrupt)
|
|
The Forced Interrupt command is generally used to terminate a multiple sector
|
|
read or write command or insure Type I status register. This command can be
|
|
loaded into the command register at any time. If there is a current command
|
|
under execution (busy status bit set), the command will be terminated and the
|
|
busy status bit reset.
|
|
|
|
Status Register
|
|
Upon receipt of any command, except the Force Interrupt command, the Busy
|
|
Status bit is set and the rest of the status bits are updated or cleared for
|
|
the new command.
|
|
The user has the option of reading the status register through program control
|
|
or using the DRQ line with DMA or interrupt methods. When the DR is read the
|
|
DRQ bit in the Status register and the DRQ line are automatically reset. A
|
|
write to the DR also causes both DRQ's to reset. The busy bit in the status may
|
|
be monitored with a user program to determine when a command is complete, in
|
|
lieu of using the INTRQ line. When using the INTRQ, a busy status check is not
|
|
recommended because a read of the status register to determine the condition of
|
|
busy will reset the INTRQ line.
|
|
|
|
Status for Type I commands
|
|
Bit Expl.
|
|
0 Busy (1=Command is in progress)
|
|
1 Index (1=Index mark detected from drive)
|
|
2 Track 0 (1=Read/Write head is positioned to Track 0)
|
|
3 CRC Error (1=CRC encountered in ID field)
|
|
4 Seek Error (1=Desired track was not verified) (reset 0 when updated)
|
|
5 Head Loaded (1=Head loaded an engaged) (WD1770/WD1772: Spin-up ready)
|
|
6 Protected (1=Disk write protected)
|
|
7 Not Ready (1=Drive not ready) (WD1770/WD1772: Motor On)
|
|
|
|
Status for type II & III commands
|
|
Bit Expl.
|
|
0 Busy (1=Command is under execution)
|
|
1 Data Request (1=CPU must read/write next data byte) (DRQ)
|
|
2 Lost Data (1=CPU did not respond to DRQ in one byte time)
|
|
3-4 Error Code (1=Bad Data CRC, 2=Sector not found, 3=Bad ID Field CRC)
|
|
5 Fault/Type (Any Write:1=Write Fault, Read Sector:1=Deleted Data Mark)
|
|
6 Protected (Any Write:1=Write Protect, Any Read:Not used)
|
|
7 Not Ready (1=Drive not ready) (WD1770/WD1772: Motor On)
|
|
Notes: Bit 1-6 are reset when updated. Bit 3-4 not used for read/write track.
|
|
|
|
Status for type IV command
|
|
If the Force Interrupt command is received while a command is under execution,
|
|
the Busy status bit is reset and the rest of the status bits are unchanged.
|
|
If the Force Interrupt command is received when there is no command under
|
|
execution, the Busy Status bit is reset and the rest of the status bits are
|
|
updated or cleared. In this case, Status reflects the Type I commands.
|
|
|
|
External Circuit
|
|
The floppy disk controller itself cannot select the drive number, side, disk
|
|
density, and it cannot turn on/off the drive motor(s). These settings must be
|
|
set up by an external circuit, which are (as far as they aren't set to a fixed
|
|
setting) controlled through separate I/O addresses. For details have a look at
|
|
the MSX FDC I/O addresses.
|
|
|
|
Note that the FDC contains only one track register which is used for all
|
|
drives. The current track position for each drive should be backed up in
|
|
memory, and the track register should be updated each time when changing the
|
|
current drive number.
|
|
|
|
The external circuit might also use the INTRQ and DRQ lines to handle FDC
|
|
operations by DMA transfers, and/or to produce interrupts upon completion. In
|
|
the MSX these methods are not used, however, most MSX adapters allow to read
|
|
out the state of INTRQ and DRQ from a custom I/O address (this isn't actually
|
|
required because INTRQ is just a inverted copy of the Status Busy bit, and DRQ
|
|
can be read out from the normal Status register either.
|
|
|
|
Formatting
|
|
This table shows DATA PATTERNs and their FD179X interpretation in MFM.
|
|
00-F4 Write 00 thru F4
|
|
F5 Write A1, preset CRC
|
|
F6 Write C2
|
|
F7 Generate 2 CRC bytes
|
|
F8-FF Write F8 thru FF
|
|
|
|
Formatting Example
|
|
The example below shows the data stream that must be presented to the Write
|
|
Track command for the "IBM system 34 format" (256 bytes/sector), note that the
|
|
MSX usually uses 512 bytes/sector. The left values in the tables below identify
|
|
the write-repeat count (in decimal) for the values to the right. First the
|
|
Track Header must be written, followed by Sector ID and Sector Data Fields (for
|
|
each sector). Finally 4E bytes must be written until the command has completed.
|
|
|
|
Track Header
|
|
80 x 4E
|
|
12 x 00
|
|
3 x F6 (writes C2)
|
|
1 x FC (index mark)
|
|
50 x 4E
|
|
1st Sector ID Field
|
|
12 x 00
|
|
3 x F5 (writes A1, preset CRC)
|
|
1 x FE (ID address mark)
|
|
1 x Track number
|
|
1 x Side number
|
|
1 x Sector number
|
|
1 x 01 (sector length=256)
|
|
1 x F7 (write 2 CRC bytes)
|
|
22 x 4E
|
|
1st Sector Data Field
|
|
12 x 00
|
|
3 x F5 (writes A1, preset CRC)
|
|
1 x FB (data address mark)
|
|
256 x DATA
|
|
1 x F7 (write 2 CRC bytes)
|
|
54 x 4E
|
|
2nd Sector ID Field (as above)
|
|
2nd Sector Data Field (as above)
|
|
etc.
|
|
Track End (Fill unused bytes)
|
|
.. x 4E (padding until index hole interrupt)
|
|
|
|
Spectrum Disc Controller (Other)
|
|
--------------------------------
|
|
|
|
Challenge Research Ltd: Challenge Sprint and Sprint Mk II
|
|
This is a quad-speed "audio" cassette drive, it connects to the expansion port,
|
|
apparently spins faster than normal cassette drives, and works with existing
|
|
cassette software (that was recorded at slow speed). The included BIOS replaces
|
|
the normal cassette functions by faster functions, works only with software
|
|
that uses the BIOS functions, eg. not with copyprotected games.
|
|
|
|
Evesham Micro Centre: Doubler Mk I / Double Mk II
|
|
External input for 2nd tape drive, for tape-to-tape transfers. The included
|
|
software executes an endless loop that forwards input from the Double I/O port
|
|
to the normal ULA cassette port.
|
|
Version Hardware Software
|
|
Mk I : Port BFh, Bit0 I.R.Lavell (quite efficently coded)
|
|
Mk II : Port 1Fh, Bit3 Draysoft (less efficiently coded)
|
|
The Mk II version is advertised to be more compatible with different tape
|
|
decks.
|
|
|
|
Sinclair: Microdrive (endless tape drive)
|
|
Rotronics Wafadrive (endless tape drive) (not Microdrive compatible)
|
|
These are tape-drives, so, obviously, they don't use standard floppy disk
|
|
controllers.
|
|
Unlike normal cassette recorders, these drives can seek files (or free space)
|
|
automatically (without needing to press any play/stop/forward buttons), ie.
|
|
they do have a disk-like filesystem, however, they must wind the tape until it
|
|
reaches the desired location, so the seek-time is relative slow. Wafadrive
|
|
cartridges are manufactured with 16K, 64K, 128K capacity (of which 16K has the
|
|
shortest tape, and therefore fastest seek-time).
|
|
|
|
Crescent Quick Disk (2.8" disk, with single spiral-track, 128K or 256K)
|
|
Triton Quick Disk (2.8" disk, with single spiral-track, 100K)
|
|
Quick Disks (also used by Nintendo's Famicom Disk System) have only a single
|
|
spiral-shaped track (like CDROMs and music records), so, obviously, they don't
|
|
use standard floppy disk controllers.
|
|
Note: Quick Disk drives don't have a stepping motor for random access, instead
|
|
the head is following the spiral windings in sequential access fashion (giving
|
|
it a relative slow seek-time; similar to endless tape drives).
|
|
|
|
Timex FDD and FDD-3000
|
|
These drives are using standard a Western Digital controller, but, the
|
|
controller is connected to a separate Z80 CPU. So the spectrum is communicating
|
|
with that external Z80 CPU rather than directly with the WD chip.
|
|
|
|
Logitek: Disc Interface (connect a Commodore 1541 drive to spectrum)
|
|
An adaptor for communicating with Commodore 1541 drive (the standard disk drive
|
|
for the C64) via serial data cable. The 1541 doesn't contain any standard disk
|
|
controller (it consists of a 6502 CPU and a bunch of TTL logic). Although the
|
|
drive uses standard 5.25" disks, the sector encoding isn't compatible with that
|
|
used by Western Digital WD177x and NEC uPD765 disk controllers.
|
|
|
|
Spectrum CD Games Pack (Code Masters) (1989)
|
|
The pack consists of a Audio CD with about 30 spectrum games (each one recorded
|
|
twice), and a connection cable (cd player's 3.5mm (or 6.3mm via adapter) stereo
|
|
headphone socket to spectrum 9pin DSUB joystick port) (for Spectrum 128/+2/+3
|
|
or 48K with Kempston interface), and loading software on tape, once when a game
|
|
is loaded one can press Q,U,I,T on keyboard to load a new game (without needing
|
|
to load tape loader again).
|
|
No info if/how the stereo signal is used (maybe one channel used as CLOCK, and
|
|
the other channel as DATA...?) The cable does reportedly contain a 1bit A/D
|
|
converter, which is probably a single transistor or so (so it's mono, not
|
|
stereo?). The CD capacity is said to be "12 Megs" (presumably meaning 12
|
|
Megabit = 60 tracks with 25Kbytes each).
|
|
|
|
Unknown Controllers
|
|
For most spectrum disk interfaces it is still unknown if they do contain a
|
|
standard disk controller chip, and if so, which one (the WD177x chips seem to
|
|
be quite popular in the spectrum world, so many of the unknown interfaces are
|
|
probably using that chips, too).
|
|
|
|
Spectrum Interrupts
|
|
------------------
|
|
|
|
The IRQ is triggered on each vsync.
|
|
With IM1 opcode, the interrupt handler is at 0038h in BIOS ROM.
|
|
With IM2 opcode, the interrupt handler is at [I*100h+databus].
|
|
|
|
IRQ (IM1)
|
|
The normal IM1 handler does solely execute in ROM (without redirecting to a RAM
|
|
vector), so, since ROM is read-only, the IM1 vector cannot be hooked (unless by
|
|
external hardware that replaces the BIOS by other data, as done in the Currah
|
|
uSpeech).
|
|
To wait for an interrupt, one can use the HALT opcode, and/or check if the
|
|
FRAMES system variable has changed.
|
|
|
|
IRQ (IM2)
|
|
This mode allows to use a custom IRQ handler at [I*100h+databus]. Because of
|
|
the Display Snow bug, the table may not be at 4000h..7FFFh.
|
|
Normally [I*100h+databus] would be table in RAM at 8000h..FFFFh, however, some
|
|
games have it in ROM: Spectrum 48K has [3B00h..3C00h]=FFh, and Spectrum 128 and
|
|
up have [3BFFh..3C00h]=FFh filled, the handler is then at FFFFh, which would be
|
|
usually set to 18h (a JR opcode) whose parameter byte is read from address
|
|
0000h in BIOS, which is F3h (a DI opcode), thus forming a JR FFF4h opcode.
|
|
Assuming that the databus contains a "random" number in range of 00h..FFh upon
|
|
IRQs, it requires a table with 101h bytes at [I*100h+0..100h]. On the Spectrum
|
|
128 and up the databus seems to be stable FFh, needing only a 2 bytes at
|
|
[I*100h+FFh..100h].
|
|
|
|
External IRQ
|
|
The /IRQ signal is available on the expansion port, eventually allowing
|
|
external hardware to sense when vblanks occur, or allowing external hardware to
|
|
inject additional IRQs (done by the AMX Mouse in IM2), though it's problematic
|
|
to distingush external IRQs from normal vblank IRQs, especially if they occur
|
|
simultaneously.
|
|
|
|
External NMI
|
|
The NMI handler is at 0066h in BIOS. On the Spectrum 16K/48K/+/128/+2, and on
|
|
Timex TC2048/TC2068/TS2068, the BIOS handler does (accidently) do this:
|
|
IF [5CB0h]=0000h then JMP [5CB0h] ;ie. jump to 0000h (bullshit)
|
|
On the Spectrum +2A/+3, the bug was fixed, and it does:
|
|
IF [5CB0h]<>0000h then JMP [5CB0h]
|
|
A couple of disk-interfaces are hooking address 0066h (or address 0000h, which
|
|
can be easier decoded and which works too, due to the bug, except in the
|
|
bug-fixed Spectrum +2A/+3 versions), the most common use is a Snapshot
|
|
function, allowing to load/save the entire RAM to/from disk (useful because
|
|
most spectrum programs support only cassette loading/saving). Some disk
|
|
interfaces are using NMI to handle data requests (not so useful as that could
|
|
be also done without NMIs).
|
|
|
|
Spectrum Keyboards
|
|
------------------
|
|
|
|
--> Spectrum Keyboard Assignment
|
|
|
|
Keyboard Matrix
|
|
Port Bit4 Bit3 Bit2 Bit1 Bit0
|
|
FEFEh A8 V C X Z SHIFT
|
|
FDFEh A9 G F D S A
|
|
FBFEh A10 T R E W Q
|
|
F7FEh A11 5 4 3 2 1
|
|
EFFEh A12 6 7 8 9 0
|
|
DFFEh A13 Y U I O P
|
|
BFFEh A14 H J K L ENTER
|
|
7FFEh A15 B N M SYM 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 SHIFT CMD SYMBOL EXT EXT+SYM EXT+SHIFT GRAPH GRAPH+SHFT
|
|
1 EDIT 1 ! P=BLUE DEF FN I=BLUE [ '] [:.]
|
|
2 CAPS 2 @ P=RED FN I=RED [' ] [.:]
|
|
3 TRUE_V 3 # P=MAGENT.LINE I=MAGENT. [''] [..]
|
|
4 INV_V 4 $ P=GREEN OPEN# I=GREEN [ .] [:']
|
|
5 LEFT 5 % P=CYAN CLOSE# I=CYAN [ :] [: ]
|
|
6 DOWN 6 & P=YELLOW MOVE I=YELLOW ['.] [.']
|
|
7 UP 7 ' P=WHITE ERASE I=WHITE [':] [. ]
|
|
8 RIGHT 8 ( (BRIGHT) POINT FLASH=OFF [ ] [::]
|
|
9 GRAPH 9 ) (DARK) CAT FLASH=ON GRA=OFF GRA=OFF
|
|
0 DELETE 0 _ P=BLACK FORMAT I=BLACK DELETE DELETE
|
|
q Q PLOT <= SIN ASN ASN USR.Q USR.Q
|
|
w W DRAW <> COS ACS ACS INKEY$ INKEY$
|
|
e E REM >= TAN ATN ATN USR.E USR.E
|
|
r R RUN < INT VERIFY VERIFY USR.R USR.R
|
|
t T RAND > RND MERGE MERGE USR.T USR.T
|
|
y Y RETURN AND STR$ [ [ FN FN
|
|
u U IF OR CHR$ ] ] USR.U USR.U
|
|
i I INPUT AT CODE IN IN USR.I USR.I
|
|
o O POKE ; PEEK OUT OUT USR.O USR.O
|
|
p P PRINT " TAB RESET (C) RESET (C) USR.P USR.P
|
|
a A NEW STOP READ FREE ~ FREE ~ USR.A USR.A
|
|
s S SAVE NOT RESTORE STICK | STICK | USR.S USR.S
|
|
d D DIM STEP DATA \ \ \ \ USR.D USR.D
|
|
f F FOR TO SGN ON_ERR { ON_ERR { USR.F USR.F
|
|
g G GOTO THEN ABS SOUND } SOUND } USR.G USR.G
|
|
h H GOSUB ^ SQR CIRCLE CIRCLE USR.H USR.H
|
|
j J LOAD - VAL VAL$ VAL$ USR.J USR.J
|
|
k K LIST + LEN SCREEN$ SCREEN$ USR.K USR.K
|
|
l L LET = USR ATTR ATTR USR.L USR.L
|
|
ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER
|
|
SHIFT SHIFT SHIFT EXT=ON SHIFT EXT=OFF SHIFT SHIFT SHIFT
|
|
z Z COPY : LN BEEP BEEP POINT POINT
|
|
x X CLEAR pound EXP INK INK PI PI
|
|
c C CONT ? LPRINT PAPER PAPER USR.C USR.C
|
|
v V CLS / LLIST FLASH FLASH RND RND
|
|
b B BORDER * BIN BRIGHT BRIGHT USR.B USR.B
|
|
n N NEXT , INKEY$ OVER OVER USR.N USR.N
|
|
m M PAUSE . PI INVERSE INVERSE USR.M USR.M
|
|
SYMBOL EXT=ON SYMBOL SYMBOL SYMBOL SYMBOL EXT=OFF SHIFT EXT=ON
|
|
SPACE SPACE SPACE SPACE SPACE SPACE SPACE SPACE SPACE
|
|
|
|
Timex TS2068 and TC2068
|
|
The DELETE, RESET, FREE, STICK, ON_ERR, SOUND keywords exist on Timex TS2068
|
|
and TC2068 only. FREE/STICK are premanently mapped (not allowing to use "~" and
|
|
"|" on these computers). The other four commands are mapped only when the [K]
|
|
cursor is shown (to use the backspace function with [K] cursor: Keep Shift+1
|
|
held down for 2-3 seconds, the key-repeat does then act as backspace instead of
|
|
repeatedly showing up the DELETE keyword).
|
|
|
|
Spectrum 128/+2/+2A/+3
|
|
On the Spectrum 128/+2/+2A/+3 all keywords must be entered letter-by-letter
|
|
(ie. type P,L,O,T instead of pressing Q), letters and punctuation marks are
|
|
kept at the same locations as in the above table, the EDIT key shows the
|
|
options menu (which includes a RENUMBER function).
|
|
|
|
Spectrum Joystick Ports
|
|
-----------------------
|
|
|
|
Joystick Ports and Data Bits (U=Up, D=Down, L=Left, R=Right, F=Fire)
|
|
Port_Joystick_Type___________________________7_6_5_4_3_2_1_0___Data Bits___
|
|
xx1F Kempston (and Timex TC2048) ? ? ? F U D L R (1=Pressed)
|
|
xx7F Fuller Box F ? ? ? R L D U (0=Pressed)
|
|
EFFE Protek (cursor mode, A12, keys 6,7,8,0) - - - D U R - F (0=Pressed)
|
|
F7FE Protek (cursor mode, A11, key 5) - - - L - - - - (0=Pressed)
|
|
DFFE AGF (2nd Joystick, A13, keys Y,U,I,P) - - - D U R - F (0=Pressed)
|
|
FBFE AGF (2nd Joystick, A10, key T) - - - L - - - - (0=Pressed)
|
|
EFFE Sinclair Port 1 (keys 6,7,8,9,0) - - - L R D U F (0=Pressed)
|
|
F7FE Sinclair Port 2 (keys 5,4,3,2,1) - - - F U D R L (0=Pressed)
|
|
E7FE Sinclair Garbage or Nothing - - - x x x x x (0=Pressed)
|
|
01F6 Timex TS2068/TC2068 PSG Reg 14, Port 1 F ? ? ? R L D U (0=Pressed)
|
|
02F6 Timex TS2068/TC2068 PSG Reg 14, Port 2 F ? ? ? R L D U (0=Pressed)
|
|
03F6 Timex TS2068/TC2068 PSG Reg 14, Both F ? ? ? R L D U (0=Pressed)
|
|
xxBF Timedata ZXM Sound Box, PSG Reg 14 0 F U D L R y x (0=Pressed)
|
|
? Rotronics Wafadrive Joystick Adaptor ? ? ? ? ? ? ? ? (?=Select)
|
|
|
|
Recommended Controls
|
|
When making Spectrum software, best support ALL of the following controls:
|
|
6,7,8,9,0 --> Interprete as Sinclair Joystick Port 1
|
|
SHIFT+5,6,7,8,SPACE --> Interprete as Cursor Keys (for use in emulators)
|
|
Q,A,O,P,SPACE --> Interprete as Keyboard Keys
|
|
Port 1Fh --> Interprete as Kempston Joystick Port
|
|
|
|
Kempston Port Notes
|
|
This is a quite popular standard, and should be supported by most games. There
|
|
are a lot of homebrew clones, including some released in magazines, many
|
|
variants are decoding only A5=0, ignoring A6 and A7. Some variants are using
|
|
the upper data bits (D5-D7) as centronics busy input, or as floppy interrupt or
|
|
data requests.
|
|
|
|
Sinclair Port Notes
|
|
Sinclair ports are supported by the Interface 2 adaptor, by the Disciple disk
|
|
interface, and are built-in in Spectrum +2/+3. The Sinclair joysticks are
|
|
equivalent to keyboard keys 1,2,3,4,5 (port2) and 6,7,8,9,0 (port1), both
|
|
keyboard groups are arranged as L,R,D,U,F (that keyboard arrangement is why the
|
|
data bits are in opposite order for port1 and port2) (note: the arrangement
|
|
does NOT comply with the cursor keys on keys 5,6,7,8). Reading both ports at
|
|
once doesn't work well: Interface 2 doesn't respond to reads from Port E7FEh,
|
|
Spectrum +2/+3 does respond to it (but, due to the reversed data bit
|
|
arrangement, it returns rather useless garbage, eg. Up1 ANDed with Fire2).
|
|
|
|
Protek Port Notes
|
|
The original Protek supports only cursor mode, newer variants can be reportedly
|
|
switched to three modes (probably cursor, kempston, and sinclair or so).
|
|
AGF and Thurnall support Cursor+Rubout, too. AGF additionally supports
|
|
T-Y-U-I-P as second joystick. Thurnall additionally supports Q-A-Z-X for
|
|
whatever usage.
|
|
|
|
Timex TS2068/TC2068 Port Notes
|
|
Timex Ports are using PSG register 14, which must be configured properly: Clear
|
|
Bit6 of PSG Register 7 (input direction), write FFh or 8Fh or so to PSG
|
|
register 14 (output HIGH levels), and set PSG index to 14. For details see
|
|
PSG/sound specs.
|
|
|
|
Rotronics Wafadrive Joystick Adaptor
|
|
According to the Rotronics Wafadrive manual, one can connect a joystick to the
|
|
centronics port of the Wafadrive via an adaptor. There's no info on how to
|
|
build that adaptor, but the manual says it is sold separately (if that adaptor
|
|
was actually ever produced, then it didn't became very popular). Because the
|
|
Wafadrive centronics port is one-directonal, it is probably using the joystick
|
|
switches in reversed direction (ie. outputting LOW levels to L,R,U,D,F via some
|
|
of the Data lines, and reading the result from the common pin via the Busy
|
|
input).
|
|
|
|
Joystick Port Pin-outs
|
|
The five switches are connected to Pin8 as a common pin, in the Atari standard
|
|
that'd be GND, but in some variants it is a /SELECT signal that goes low when
|
|
reading from the joystick port (that method works with joystick that consists
|
|
of raw switches; but won't work with sticks that contain autofire functions or
|
|
other logic that requires +5V/GND supply at Pin7/Pin8).
|
|
Kempston Homebrew TS2068/TC2068 Interface2 Spectrum+2 Protek
|
|
Pin Joy1 Joy1 Joy1 Joy2 Joy1 Joy2 Joy1 Joy2 Joy1
|
|
1 Up Up Up Up Up Up N/A? N/A? Up
|
|
2 Down Down Down Down Down Down MA3 MA4 Down
|
|
3 Left Left Left Left Left Left N/A? N/A? Left
|
|
4 Right Right Right Right Right Right Fire Fire Right
|
|
5 N/A N/A N/A N/A N/A N/A Up Up ?
|
|
6 Fire Fire Fire Fire Fire Fire Right Right Fire
|
|
7 +5V (Fire 2) +5V +5V N/A N/A Left Left ?
|
|
8 GND +5V /A8 /A9 GND GND MA3 MA4 ?
|
|
9 N/A N/A GND GND N/A N/A Down Down ?
|
|
Amstrad's Spectrum +2 uses standard DSUB-9 ports, but with nonstandard pinouts
|
|
(so it works only when re-wiring the connection on the mainboard, using an
|
|
external adaptor, or buying an original "SJS1" joystick from Amstrad) (the
|
|
MA3/MA4 lines are DRAM row/column address bits; essentially same as A11/A12 at
|
|
time when reading the ports).
|
|
|
|
Spectrum Mouse Ports
|
|
--------------------
|
|
|
|
Kempston Mouse (hardware counters)
|
|
This is probably the most popular, best working, and most often supported mouse
|
|
interface.
|
|
--> Spectrum Mouse - Kempston Mouse
|
|
The original package consists of a Kempston Mouse and Kempston Mouse Interface,
|
|
there are also compatible interfaces that can be used with Amiga, PS/2, or USB
|
|
mice, and maybe also some for RS232, Atari, or even analog mice.
|
|
|
|
AMX Mouse (IM2 interrupts)
|
|
This is almost as powerful as the Kempston Mouse, but conflicts with various
|
|
other hardware expansions, the AMX Mouse is rarely supported by any programs.
|
|
--> Spectrum Mouse - AMX Mouse (Advanced Memory Systems)
|
|
The I/O addresses conflict with various other expansions like Kempston
|
|
Joysticks (Port 1Fh), Beta Disk, Fuller Box, etc.
|
|
|
|
Amiga/Atari Mice (software counters)
|
|
Amiga/Atari mice can be connected directly to Kempston Joystick ports (which
|
|
have +5V and GND), without needing any mouse interface. Although it's simple at
|
|
hardware side, it's supported only by a dozen of programs.
|
|
--> Spectrum Mouse - Amiga Mouse or Atari Mouse in Kempston Joystick port
|
|
The problem is that the mickeys must be counted by software, meaning that the
|
|
software must check Port 1Fh more than 500 times per second, ie. much more
|
|
often than it could be done via the 50Hz vblank interrupt.
|
|
|
|
Other Mice
|
|
Some other less popular and/or less powerful solutions are:
|
|
--> Spectrum Mouse - Other Mice
|
|
|
|
Double Speed Threshold
|
|
Don't forget to implement Threshold in software, ie. if you have received more
|
|
than so-and-so-many mickeys per frame, multiply that value by two.
|
|
|
|
Spectrum Mouse - Kempston Mouse
|
|
-------------------------------
|
|
|
|
FADFh - Kempston Mouse Buttons (R)
|
|
0 Right Button (0=Pressed, 1=Released)
|
|
1 Left Button (0=Pressed, 1=Released)
|
|
2 Middle Button (not supported in original Kempston Mouse interface)
|
|
3 Not used
|
|
4-7 Mouse Wheel Counter (supported in some russian interfaces only)
|
|
The wheel "Counter is 4-bit and its value increases with the movement of wheels
|
|
down, decrases the movement up." Whatever that means...? normally the wheel
|
|
turns away from, or towards to user (where "away from user" should look
|
|
UP-wards in a document; which means the screen scrolls DOWN-wards).
|
|
|
|
FBDFh - Kempston Mouse X (R)
|
|
FFDFh - Kempston Mouse Y (R)
|
|
0-7 Counter (mickeys)
|
|
"8bit reverse counters" whatever that means... increasing or decreasing when
|
|
moving towards where? The counters aren't reset after reading, and may wrap
|
|
from FFh to 00h, or vice versa, when exceeding the 8bit range. To get mickeys
|
|
since last read, subtract old/new value.
|
|
|
|
Notes
|
|
Usually deconds A5, A7, A8, A10, /RD, /IORQ, sometimes also /RD, A9, and/or A0.
|
|
Uh, why A0...?
|
|
There is port conflict with incompletely implemented Kempston Joystick ports
|
|
that decode only A5 (eg. Timex TC2048).
|
|
|
|
Spectrum Mouse - AMX Mouse (Advanced Memory Systems)
|
|
----------------------------------------------------
|
|
|
|
1Fh - AMX Mouse - Z80PIO Data Reg A, Mouse X, Centronics LSBs/Strobe (R/W)
|
|
0 Mouse X Direction (XB input from mouse) (?=Left, ?=Right)
|
|
1-2 Not used
|
|
3 Centronics Strobe (should be usually output in Mode 3)
|
|
4-7 Centronics Data LSBs (should be usually output in Mode 3)
|
|
|
|
3Fh - AMX Mouse - Z80PIO Data Reg B, Mouse Y, Centronics MSBs/Busy (R/W)
|
|
0 Mouse Y Direction (YB input from mouse) (?=Up, ?=Down)
|
|
1-2 Not used
|
|
3 Centronics Busy (should be usually input in Mode 3)
|
|
4-7 Centronics Data MSBs (should be usually output in Mode 3)
|
|
|
|
5Fh - AMX Mouse - Z80PIO Control Register A, Horizontal Control (W)
|
|
Used to configure Port A and Interrupt A by writing 1 or 2 byte(s) to this
|
|
register, the meaning depends on the LSBs of the 1st byte:
|
|
1stByte 2ndByte Function
|
|
vvvvvvv0 N/A Set Interrupt Vector
|
|
exxx0011 N/A Set Interrupt Enable
|
|
eah00111 N/A Set Interrupt Enable/Control (for Mode 3 only)
|
|
eah10111 mmmmmmmm Set Interrupt Enable/Control/Mask (for Mode 3 only)
|
|
00xx1111 N/A Set Mode 0 (all 8 data bits = Output)
|
|
01xx1111 N/A Set Mode 1 (all 8 data bits = Input)
|
|
10xx1111 N/A Set Mode 2 (all 8 data bits = Bidirectional) (Port A only)
|
|
11xx1111 dddddddd Set Mode 3 and Direction bits (0=Out, 1=In)
|
|
Whereas,
|
|
vvvvvvv Interrupt Vector (Bit0=0, Bit1-7=vvvvvvv, Bit8..15="I"-Register)
|
|
e Interrupt Enable (0=Disable, 1=Enable; trigger on each mickey)
|
|
a Interrupt AND/OR (for Mode3 only)
|
|
h Interrupt HI/LO (for Mode3 only)
|
|
mmmmmmmm Interrupt Mask (for Mode3 only) (0=Monitor, 1=Mask)
|
|
dddddddd Data Direction bits 0-7 (0=Output, 1=Input)
|
|
|
|
7Fh - AMX Mouse - Z80PIO Control Register B, Vertical Control (W)
|
|
Same as Control Register A (see there), but for Port B accordingly.
|
|
|
|
DFh - AMX Mouse - 74LSXX Logic, Mouse Buttons (R)
|
|
0-4 Not used
|
|
5 Right Button
|
|
6 Middle Button
|
|
7 Left Button
|
|
Buttons are handled via separate 74LSxx chips. Although, theoretically, they
|
|
could be mapped to bit1-2 of the Z80PIO data ports; maybe the whole 8bit data
|
|
ports are latched on interrupts; which would freeze the state of bit1-2.
|
|
|
|
Interrupts
|
|
The AMX mouse triggers an interrupt and outputs an IM2 interrupt vector on the
|
|
databus on each mickey, the CPU should be in IM2, and the CPUs I-register
|
|
should contain MSB of the interrupt table, the Z80 does then do am indirect
|
|
"CALL [I*100h+databus]" on interrupts. Mind that trying to set I=40h..7Fh
|
|
results in ULA Snow bug.
|
|
The two Z80PIO interrupt vectors should point to the address of X and Y motion
|
|
handler; which should read the X or Y direction bit, and inrease/decrease the
|
|
mickey counter accordingly. If both X and Y mickeys occor simultaneously, then
|
|
the Z80PIO would first produce vector A, and then vector B (after vector A was
|
|
processed).
|
|
The normal Vblank interrupt doesn't output anything on databus, so databus
|
|
should be (hopefully) FFh, causing a "CALL [I*100h+FFh]" on vblank. If mickeys
|
|
occur simulaneously with vblank, then the vblank interrupt is probably lost...?
|
|
which would be bad for general animation synchronizations, keyboard handling,
|
|
as well as for mouse specific threshold calculations.
|
|
|
|
Notes
|
|
The Z80PIO is reset on power-up (when raising VCC) only, but NOT on /RESET.
|
|
The AMX Mouse is supported by Minesweeper (new version - EN), and Artist II.
|
|
|
|
Spectrum Mouse - Amiga Mouse or Atari Mouse in Kempston Joystick port
|
|
---------------------------------------------------------------------
|
|
|
|
Pinouts
|
|
Pin Amiga Mouse Atari Mouse Kempston Joystick Kempston Mouse
|
|
1 YA XB Joystick up +5V
|
|
2 XA XA Joystick down XA
|
|
3 YB YA Joystick left YB
|
|
4 XB YB Joystick right Left Button
|
|
5 Middle Button Not connected Not connected Right Button
|
|
6 Left Button Left Button Fire button GND
|
|
7 +5V +5V +5V Not connected
|
|
8 GND GND GND YA
|
|
9 Right Button Right Button Not connected XB
|
|
As shown in 1st/2nd column, Amiga and Atari have XA/XB/YA/YB arranged
|
|
differently. 3rd column shows how the signals are mapped on the joystick port.
|
|
The 4th column is just for curiosity, it shows the connection between Kempston
|
|
Mouse and Kempston Mouse Interface (aside from the different pinouts it's much
|
|
the same as Amiga/Atari mice, the big difference is that the Kempston Mouse
|
|
Interface contains hardware counters, without needing to count mickeys by
|
|
software).
|
|
|
|
Motion Signals
|
|
The XA/XB indicate horizontal motion (and YA/YB vertical motion), like so:
|
|
One Direction Opposite Direction
|
|
XA _______----____ _____----______
|
|
XB _____----______ _______----____
|
|
The signal timings depend on how fast the mouse is moved (ie. if the mouse is
|
|
not moved, then it may stop anywhere in the above diagram, eg. while XA and XB
|
|
are both high, both low, or one high and one low).
|
|
The simpliest approach is to wait for raising edge on XA, and then to check XB
|
|
(either XB is already high, or XB is still low) and increase/decrease the
|
|
software's mickey counter accordingly. In situations where the direction
|
|
changes, it may be also recommended to handle "half mickeys" on falling edges
|
|
on XA, eg.:
|
|
One Direction Stop Opposite Direction
|
|
XA _______---------------------------______
|
|
XB _____-------------------------------____
|
|
In the above case, checking only raising XA would miss the direction change on
|
|
falling XA (if that happens repeatedly, then the mouse would disappear towards
|
|
the screen border, eg. if the mouse is in an unstable position, without
|
|
actually being moved).
|
|
|
|
Notes
|
|
Mind that the Kempston Joystick port inverts all signals (that is don't care
|
|
for XA,XB,YA,XB, but the button bit may be opposite as expected). And, of
|
|
course, a Kempston Joystick port does have only one Fire button (so only the
|
|
Left mouse button can be read).
|
|
Games that support BOTH Amiga and Atari mouse: Godzilla, Ultra Reflect,
|
|
Advanced Patience, Pyramid Patience.
|
|
Games that support ONLY Amiga mouse: Black Raven 1, Hexxagon, Indian Patience,
|
|
Magic Field, Mezi Vezemi 128 (cz), Sparrows, and Art Studio.
|
|
|
|
Spectrum Mouse - Other Mice
|
|
---------------------------
|
|
|
|
Datel Genius Mouse
|
|
Early Datel mice (April-March 1987) had 3 buttons, all later mice had only 2
|
|
buttons. Very late Datel mouse interfaces (1989 or so) additionally included a
|
|
kempston joystick port. The interface (at least the latest version) contains
|
|
only a single 28pin SMD chip, plus some resistors and capacitors.
|
|
The used I/O addresses are still unknown, however, the interface with the SMD
|
|
chip connects to D0-D7, /IORQ, A5, A8-A10, +5V, and GND... so it might be
|
|
simply a clone of the Kempston Mouse interface? Although, Kempston Mouse and
|
|
Kempston Joystick both use A5=LOW, so, without checking A6/A7, it couldn't
|
|
separate between them...?
|
|
|
|
Joystick Mouse (supports only fixed speed motion)
|
|
Some mice (Commodore Mouse 1350, Noris Data Mouse M1, Boeder GEOS-Mouse, Elite
|
|
Mouse, Datalux SV-705) emulate a digital joystick. The advantage is that these
|
|
mice can be used with any games that support joystick input (provided that the
|
|
joystick port outputs +5V and GND pn Pin 7 and 8, ie. works only with standard
|
|
Kempston Joystick ports, not with standard Sinclair Joystick ports). The big
|
|
disadvantage that these mice can't separate between slow and fast motion.
|
|
|
|
RS232 Mouse on RS232 Port
|
|
Standard RS232 PC mice can be theoretically connected to Spectrum RS232 ports.
|
|
In practice it's difficult at both hardware and software side, and so it's
|
|
rarely supported. The first problem is that there are at least 16 Spectrum
|
|
RS232 interfaces from different companies. Next, some Spectrum RS232 ports have
|
|
non-standard pinouts (eg. Interface 1), simple Spectrum RS232 ports would
|
|
require to watch the incoming bitstream permanently by software (eg. Interface
|
|
1). So, to execute any other program code, one would need a RS232 interface
|
|
with built-in shift register and baudrate timer, and preferably also an
|
|
interrupt notification, or, even more preferably a FIFO that can hold at least
|
|
3 characters (so the 1200 baud mouse data would need to be processed only on
|
|
vblank interrupts).
|
|
|
|
AY-Mouse (C) V.M.G. (schematic in russian ZX Power digital magazine)
|
|
This is a (rather rarely supported) mouse interface. Similar to the Kempston
|
|
Mouse interface it contains two hardware counters and button inputs, intended
|
|
to be used with mice that have XA/XB/YA/YB signals (ie. any Amiga, Atari, AMX,
|
|
or Kempston mice) (of course, needing to recurse the different pinouts of that
|
|
mice).
|
|
The interface connects to PSG register 14, with the PSG being accessed via Port
|
|
FFFDh and BFFDh, ie. the Spectrum 128 style PSG addresses, but with PSG
|
|
register 14 being used to access the mouse (the real Spectrum 128 uses it as
|
|
RS232/Keypad port). The PSG register 14 bits are:
|
|
0-3 In Horizontal or Vertical 4bit Counter (as selected via bit6)
|
|
4 In Button 1 (0=Pressed, 1=Released) (presumably Left)
|
|
5 In Button 2 (0=Pressed, 1=Released) (presumably Right)
|
|
6 Out Select Counter to be mapped to bit0-3 (?=Horizontal, ?=Vertical)
|
|
7 ? Border ("for testing, and computer effects, type multicolor")
|
|
Changing bit6 (raising or falling edge?) does additionally reset the two 4bit
|
|
counters to a value of 8 each, so, the difference since last access is new-8
|
|
(or 8-new), rather than new-old.
|
|
Supported by Art Mouse (Art Studio), ZX Power 1-4, Lemmings (TRDOS version).
|
|
|
|
Nidd Valley - Digimouse (digital)
|
|
Nidd Valley - Anamouse (analog)
|
|
Saga Systems - Star Mouse
|
|
Individual Software - Keyboard Mouse
|
|
Tropic Informatica - TPX Mouse (for brazilian TK90X and TK95)
|
|
No idea how these devices work? They don't seem to be very popular.
|
|
|
|
Spectrum Light Guns
|
|
-------------------
|
|
|
|
Stack Light Rifle (Stack Computer Services Ltd) (1983)
|
|
connects to expansion port, accessed by reading from Port DFh:
|
|
bit1 = Trigger Button (0=Pressed, 1=Released)
|
|
bit4 = Light Sensor (0=Light, 1=No Light)
|
|
other bits = Must be "1" (the programs use compare FDh to test if bit1=0)
|
|
The vertical position is measured by counting time between vblank & light
|
|
sensor signal; none of the games seems to attempt to measure the horizontal
|
|
position; so there should be only one bright object per scanline).
|
|
The software timings are matched for PAL Spectrum 48K (and probably don't work
|
|
on other/newer spectrums due to different BIOS (irq handler), video (clks per
|
|
scanline), and cpu speed (waitstate) timings.
|
|
|
|
Magnum Light Phaser for Spectrum +2/+3 (Sinclair/Amstrad/Trojan) (1989)
|
|
Defender Light Gun for Spectrum 128/+2/+3 (Cheetah) (1989)
|
|
These two guns seem to be compatible with each other. Both are connected to
|
|
AUX/Keypad (aka PSG Register 0Eh):
|
|
bit4 = light sensor (0=None, 1=Light)
|
|
bit5 = trigger button (0=Pressed, 1=Released)
|
|
Although the Spectrum 128 does have an AUX/Keypad socket, the Magnum manual
|
|
says that one should use the MIC-socket based gun on the Spectrum 128 (dunno
|
|
why).
|
|
|
|
Magnum Light Phaser for Spectrum 48K (Sinclair/Amstrad/Trojan) (1989)
|
|
Requires 9V battery, connects to MIC-output socket (which is misused as input
|
|
in this case). In the output direction, port FEh should be set to 00h
|
|
(accordingly, the 48K games cannot output sound while reading the gun) (mind
|
|
that CAS-IN, CAS-OUT, and SOUND-OUT are sharing the same ULA pin).
|
|
The trigger button is sensed as LONG pulse (Jungle Warfare reads 8Ch times, and
|
|
accepts trigger only if [FEh].Bit6=ZERO on all 8Ch reads). The light sensor is
|
|
sensed as EDGE (ie. 0-to-1 or 1-to-0 transitions on [FEh.Bit6]). Knowing that,
|
|
it seems that the trigger button and light sensor signals are XORed with each
|
|
other.
|
|
|
|
Defender Light Gun for Spectrum 48K (Cheetah) (1989)
|
|
Connects to Kempston Joystick interface. The Kempston Port 1Fh bits are:
|
|
Joystick UP (bit3) = Trigger button
|
|
Joystick FIRE (bit4) = Light sensor
|
|
Other (bit0-2,5-7) = Must be 0 (Jungle W. compares [1Fh] with 08h,10h,18h)
|
|
Works only with Kempston interfaces (other joystick interfaces don't seem to be
|
|
supported at software side, and, other interfaces usually don't provide the
|
|
required +5V supply voltage at hardware side).
|
|
|
|
Gunstick for Spectrum 48K/+/128 (MHT Ingenieros)
|
|
Connects to joystick interface. Requires four 1.5V batteries (and so, doesn't
|
|
require 5V/GND on joystick port).
|
|
Joystick FIRE = Trigger Button (LOW=Pressed, HIGH=Released)
|
|
Joystick DOWN = Light Sensor (LOW=?)
|
|
Most games seem to support only Sinclair Joystick Interfaces (Port EFFEh or
|
|
F7FEh), although the hardware should work with all joystick interfaces.
|
|
|
|
Gunstick for Spectrum +2/+3 (MHT Ingenieros)
|
|
Same as the 48K version, but matched to the (distorted) pin-outs of the bizarre
|
|
Spectrum +2/+3 joystick ports.
|
|
|
|
Note on Defender "sliding autofire/function select switch"
|
|
Additionally to the trigger button, the Defender guns have a "sliding
|
|
autofire/function select switch", reportedly used to select one-shot or
|
|
machine-gun mode in some games, however, unknown how this switch is accessed by
|
|
software (there seem to be only two data bits used; the light sensor and
|
|
trigger button; so maybe it affects the length of the trigger button signal),
|
|
also unknown if that switch acts as a push button, sticky switch, or even as
|
|
potentiometer?
|
|
|
|
Existing Lightgun Games for the Spectrum
|
|
Stack Light Rifle Games:
|
|
Grouse Shoot Stack Computer Services Ltd (compiled BASIC code)
|
|
Shooting Gallery Stack Computer Services Ltd (compiled BASIC code)
|
|
High Noon Stack Computer Services Ltd (compiled BASIC code)
|
|
Invasion Force Micromania (real Z80 assembler code)
|
|
Defender Light Gun Games:
|
|
Advanced Pinball Simulator Code Masters Ltd
|
|
Billy the Kid Code Masters Ltd
|
|
Bronx Street Cop Code Masters Ltd
|
|
F-16 Fighting Falcon Code Masters Ltd
|
|
Jungle Warfare Code Masters Ltd
|
|
Super Car Trans Am Code Masters Ltd
|
|
And... theoretically the AUX-based Magnum games should work, too?
|
|
Magnum Light Phaser Games:
|
|
Billy the Kid Code Masters Ltd
|
|
Bronx Street Cop Code Masters Ltd
|
|
Bullseye Macsen Software
|
|
F-16 Fighting Falcon Code Masters Ltd
|
|
Jungle Warfare Code Masters Ltd
|
|
Living Daylights Domark Ltd
|
|
Lord Bromley's Estate Amstrad
|
|
Missile Ground Zero Software Creations
|
|
Operation Wolf Ocean Software Ltd
|
|
Q's Armoury Amstrad
|
|
Robot Attack Mastertronic Ltd
|
|
Rookie Mastertronic Ltd
|
|
Solar Invasion Mastertronic Ltd
|
|
Super Car Trans Am Code Masters Ltd
|
|
Gunstick Games:
|
|
Acid Killer New Frontier
|
|
Bestial Warrior Dinamic Software
|
|
Cosmic Sheriff Dinamic Software
|
|
El Equipo A (aka A-Team) Zafiro Software Division
|
|
Guillermo Tell Opera Soft S.A.
|
|
Hunting Mix New Frontier
|
|
Mike Gunner Dinamic Software
|
|
Shooting Range: Mix I New Frontier
|
|
Solo Opera Soft S.A.
|
|
Sootland Zafiro Software Division
|
|
Space Smugglers MHT Ingenieros S.L.
|
|
Target Plus Dinamic Software
|
|
Trigger Opera Soft S.A.
|
|
Note: In many cases there are two versions of each Magnum game: one hardcoded
|
|
to work with MIC port, another one hardcoded to work with AUX port. The Code
|
|
Masters titles do auto-detect if the Magnum (or Defender) is connected to MIC,
|
|
AUX, or Kempston joystick port.
|
|
|
|
Spectrum Printer Ports
|
|
----------------------
|
|
|
|
Sinclair focused on selling their own 32-column printer (see ZX81 chapter), and
|
|
(until the Spectrum +2A/+3 were released) didn't support regular centronics
|
|
printers. The only official alternative to the 32-column thing was to use
|
|
(rather rare) RS232 printers connected to Interface 1 (see Serial port
|
|
chapter). Various other companies have released Centronics ports for the
|
|
spectrum (often included in disk interfaces), but without using any standarized
|
|
I/O addresses...
|
|
|
|
Centronics Ports
|
|
Type Data Busy Strobe
|
|
Interface Bis #1D (#1D).7 auto
|
|
M'ody Technik 1986-12 #1F (inv) (#9F).4=0 (#9F).4=1
|
|
MB-02 #3F (#5F).7=1 (#5F).1=0
|
|
YAMOD.8211 #0n58 (#0n59).7=0 (#0n5A).0=1 ;n=0..1
|
|
Unipolbrit 2086 #xx7B (#BB).?=1 (#BB).?=0
|
|
AERCo Centronics #7F (#7F).4=1 auto
|
|
MultiPrint #BF (#BB).6=1 (#BF)=X,(#BB)=X,(#BF)=X
|
|
Informik 1989-II #E3 (#F3).4=0 (#F3).4=1
|
|
Sam FDD #E8 (#E9).0 (#E9).0=1
|
|
Elwro 800 Jr #DE (#DD).7=1 (#DD).2=0
|
|
Scorpion #DD (#FE).7 auto(?)
|
|
AERCo FD-68 #E0DF ? (#xx??).? ??
|
|
PlusD #F7 (#F7).7 (#EF).6
|
|
DISCiPLE #FB (#1F).6 (#1F).6
|
|
ZX Lprint 3 & Pentagon #FB (#FB).7=1 auto (?)
|
|
Centronics Microface #FB (#FB).7=1 auto
|
|
ZX Spectrum +3 #0FFD (#0FFD).0=1 (#1FFD).4=0
|
|
GP500A PZ "APINA" #xx?? (#xx??).? ??
|
|
Kempston S (Software) #E0BF (#E2BF).0 E3BF.0 ;with SOFTWARE driver
|
|
Kempston E (EPROM) #xx?? (#xx??).? ?? ;with EPROM driver
|
|
DK'Tronics #xx9B (#xxBB).7 xxBB.1
|
|
INES Printerface #xx?? (#xx??).? ??
|
|
Opus Discovery (memory mapped PIA6821) ;BiDir.D0-D7,STB,READY,ACK
|
|
Rotronics Wafadrive dd0Eh 0002h.5 000Ah/200Ah ;via IN (not OUT)
|
|
Indescomp #FB (#FB).0 (#7F).0
|
|
Watford ? ? ?
|
|
Fuller ? ? ?
|
|
VISMO ZP83 parallel interface
|
|
VTR Parallel Centronics Interface
|
|
Tasman Parallel Printer Interface
|
|
ADS Advanced Digital Systems Centronics Interface
|
|
Dorsch Centronics Interface
|
|
Technology Research S-Print
|
|
Cambridge Intelligent Printer Interface
|
|
Logitek Floppy/Printer Interface (centronics port and c64 floppy port)
|
|
Miracle ZX Printer Interface (rs232-to-centronics converter for Interface 1)
|
|
Morex Printer Interface (centronics, rs232, built-in word processor)
|
|
Romantic Robot Multiprint
|
|
Cambridge Microelectronics Polyprint Interface
|
|
Camel Products Print-SP
|
|
Ram Electronics RamPrint Interface (centronics, joystick, RamWrite in ROM)
|
|
Euroelectronics ZX Lprint (centronics)
|
|
Euroelectronics ZX Lprint III (centronics and rs232)
|
|
AMX Mouse (with 8bit centronics data split into two 4bit fragments)
|
|
Nidd Valley Digimouse Interface (professional version with Centronics port)
|
|
|
|
Cloned and/or Re-distributed Centronics interfaces
|
|
Hilderbay Interface (same as the Kempston S thing)
|
|
Datel Inter Printer (same as the DK'Tronics thing, distributed by datel)
|
|
Datel Ramprint (same as the Ram Electronics thing, distributed by datel)
|
|
Pentagon (russian spectrum clone, with built-in ZX Lprint 3)
|
|
|
|
Centronics Notes
|
|
Interface Bis 5 input lines for LapLink
|
|
M'ody Technik 1986-12 8255 used: #DF=config; PA=data. All signals inverted.
|
|
MB-02 8255 used; #7F=config; PB=data, PC2=/ACK,
|
|
PC3=/AUTOFEED, PC4=/ERROR, PC5=SELECT, PC6=PAPEROUT
|
|
Unipolbrit 2086 8255 used; #FB=config; PA=data; only PA and PC0, PC1,
|
|
PC4, PC5 are in DB15 slot
|
|
Informik 1989-II 8255 used: #FB=config; PA=data (PB switches memory
|
|
banks). All signals inverted.
|
|
Elwro 800 Jr 8255, other bits reserved
|
|
YAMOD.8211 PC LPT connected as YABUS.ZXISA
|
|
AERCo Centronics (#7F).5=0 - printer present
|
|
MultiPrint 8kB ROM, 8kB RAM
|
|
ZX Lprint 3 Pentagon 2kB ROM
|
|
Centronics Microface see files for documentation
|
|
ZX Lprint by Euro Electronics: The test for printer ready is IN A,(#E0): AND
|
|
#E0: CP #40. The ROM is paged into #0800..#0FFF. Looks like paged permanently.
|
|
ZX Lprint MK III: The ROM is paged into #0000..#07FF (with out to #FB - on, out
|
|
#7B - off). The code for selected printer is copied into printer buffer (at
|
|
#5B00).
|
|
Multiprint by Romantic Robot: Is NMI & debug interface with parallel port.
|
|
|
|
Basic Features
|
|
All cards should have STROBE and BUSY lines, and (at least) 7bit
|
|
one-directional DATA lines (most or all have probably 8bit?). Some cards
|
|
allow/require to control STROBE manually, others do generate it automatically
|
|
after writing to DATA.
|
|
|
|
Extended Features
|
|
A few parallel ports may have bi-directional DATA lines (namely those with 8255
|
|
chips) (also some, but not all, ISA parallel cards may have bi-directional
|
|
ports). Aside from STROBE and BUSY, some cards may have ACK, INIT, AUTOLF, etc.
|
|
|
|
Spectrum Serial Port
|
|
--------------------
|
|
|
|
Interface 1 -> RS232/Network: Port F7h and EFh
|
|
Spectrum 128/+2/+2A/+3 -> RS232/Keypad: PSG Register 14
|
|
Rotronics Wafadrive -> RS232: Port ? (uses RX,TX,RTS,CTS)
|
|
Timex RS232 Interface -> RS232: Port ?
|
|
Indescomp -> RS232: Port FBh.R and 7Fh.W
|
|
Cobra RS232 Interface (1983)
|
|
Cole RS232 (100/300 baud RS232 output port) (1983)
|
|
Fuller RS232 Interface aka Fuller FD Printerface (1983)
|
|
Fuller Dual Interface (RS232 and Centronics)
|
|
Kempston RS232 Interface (1984)
|
|
Tasman RS232 Printer Interface (1984)
|
|
U-Microcomputers USP-232D (dual RS232 with Z80DART chip, 75..9600 baud)
|
|
Watford Centronics/RS232 Interface (1985)
|
|
Morex Printer Interface (centronics, rs232, built-in word processor)
|
|
Euroelectronics ZX Lprint III (centronics and rs232)
|
|
YAMOD.8250
|
|
|
|
"Most of ZX Spectrum + 128K is VERSION 6K (C) 1985. There's a VERSION 9G with
|
|
DB9 female slot for the RS232."
|
|
|
|
Network
|
|
Supported by Interface 1 (via Port F7h/EFh) and by Disciple (via Port 3Bh/1Fh).
|
|
Despite of the different I/O ports, the transmission protocol is the same, and
|
|
Interface 1 and Disciple can communicate with each other.
|
|
--> Spectrum Interface 1 (Microdrive, Network, RS232)
|
|
--> Spectrum Disc Disciple and Plus D
|
|
The network interfaces have two mono 3.5mm headphone sockets: One for the next,
|
|
and one for the previous computer in the network. Reportedly up to 64 computers
|
|
can be connected. On the first and last computer one socket is to be left
|
|
unconnected (no matter which one) (the sockets contain a switch which connects
|
|
the end of the data line via a terminator resistor to ground when no plug is
|
|
inserted).
|
|
Note: Another (incompatible) network-type is supported by the Opus Discovery
|
|
BIOS (which allows to use the Centronics port to transfer files to/from another
|
|
computer).
|
|
|
|
RS232 (Sinclair) (9pin DSUB female)
|
|
1 Not Connected. ___________
|
|
2 In TXD | 5 4 3 2 1 |
|
|
3 Out RXD \_9_8_7_6_/
|
|
4 In DTR ;should be high when ready
|
|
5 Out CTS ;should be high when ready
|
|
6 Not Connected.
|
|
7 GND
|
|
8 Not Connected.
|
|
9 +9V - Pull up. (DSR)
|
|
Although standard RS232 ports on PCs are using 9pin DSUB connectors too, the
|
|
pinouts are NOT compatible (PCs are using male connectors, and, DTR/CTS/GND are
|
|
at other locations).
|
|
|
|
AUX/Keypad and RS232/MIDI (PSG Register 14)
|
|
0 AUX/Keypad pin 2 (out)
|
|
1 AUX/Keypad pin 4 (out)
|
|
2 RS232/MIDI pin 5 (RS232: output to remote CTS) (MIDI: DATA OUT)
|
|
3 RS232/MIDI pin 3 (RS232: output to remote RXD) (MIDI: Not used)
|
|
4 AUX/Keypad pin 3 (in) (Lightgun: light sensor: 0=No Light, 1=Light)
|
|
5 AUX/Keypad pin 5 (in) (Lightgun: trigger button: 0=Pressed, 1=Released)
|
|
6 RS232/MIDI pin 4 (RS232: input from remote DTR) (MIDI: Not used)
|
|
7 RS232/MIDI pin 2 (RS232: input from remote TXD) (MIDI: Not used)
|
|
Using software control loops, the I/O lines could be driven as a second RS232
|
|
port (in the same way as the RS232/MIDI socket is driven using bits 2, 3, 6 and
|
|
7). Alternatively, the I/O lines could be used to drive, for example, a robot
|
|
or some other external device.
|
|
Pin Function
|
|
1 GND ___________________________
|
|
2 OUTPUT BIT 0 __| 6 5 4 3 2 1 |
|
|
3 INPUT BIT 4 |__ ### ### ### ### ### ### |
|
|
4 OUTPUT BIT 1 |___________________________|
|
|
5 INPUT BIT 5
|
|
6 +12V AUX/Keypad socket
|
|
|
|
Pin Function
|
|
1 GND (MIDI: RETURN) ____________________
|
|
2 input from remote TXD (MIDI: not used) __| |
|
|
3 output to remote RXD (MIDI: not used) |__ 6 5 4 3 2 1 |
|
|
4 input from remote DTR (MIDI: not used) |____________________|
|
|
5 output to remote CTS (MIDI: DATA OUT)
|
|
6 +12V (MIDI: not used) RS232/MIDI socket
|
|
Rather unconventional "BT 603A" sockets. As far as I understand, the plugs are
|
|
similar to RJ/Western plugs, but with the plastic clip at the left-side (next
|
|
to pin6), rather than at the top-side (above pin3/4).
|
|
|
|
Signal Naming
|
|
Spectrum RS232 pins are usually named according to the REMOTE side, eg. the
|
|
spectrums transmit output is named RXD (not TXD) meaning to be connected to the
|
|
remote receive input.
|
|
|
|
Spectrum Expansion Ports
|
|
------------------------
|
|
|
|
Expansion Ports (male cart-edge, 2x23 or 2x28 or 2x32 pins)
|
|
-------TS2068------- ------TC2068------ ----Spectrum---- -ZX80/ZX81/TS1x00-
|
|
Top Bottom Top/A Bottom/B
|
|
GND 1 GND /BE 1 /EXROM Top Bottom
|
|
EAR 2 SPKR/TAPE A15 2 A14 A15 1 A14
|
|
A7R 3 +15V A13 3 A12 A13 2 A12 Top Bottom
|
|
D7 4 +5V D7 4 +5V D7 3 +5V D7 1 5V
|
|
(DZ IN) 5 N.C. N.C. 5 +9V N.C. 4 +9V /RAM CS 2 9V
|
|
(SLOT) 6 (SLOT) (SLOT) 6 (SLOT) (SLOT) 5 (SLOT) (SLOT) 3 (SLOT)
|
|
D0 7 PWR GND D0 7 0V D0 6 0V D0 4 0V
|
|
D1 8 PWR GND D1 8 0V D1 7 0V D1 5 0V
|
|
D2 9 CPU CLK D2 9 CPU CLK D2 8 CPU CLK D2 6 CPU CLK
|
|
D6 10 A0 D6 10 A0 D6 9 A0 D6 7 A0
|
|
D5 11 A1 D5 11 A1 D5 10 A1 D5 8 A1
|
|
D3 12 A2 D3 12 A2 D3 11 A2 D3 9 A2
|
|
D4 13 A3 D4 13 A3 D4 12 A3 D4 10 A3
|
|
/INT 14 A15'B /INT 14 /INT 13 /IORQULA /INT 11 A15
|
|
/NMI 15 A14'B /NMI 15 0V /NMI 14 0V /NMI 12 A14
|
|
/HALT 16 A13'B /HALT 16 VIDEO /HALT 15 VIDEO /HALT 13 A13
|
|
/MREQ'B 17 A12 /MREQ 17 /MREQ 16 /Y /MREQ 14 A12
|
|
/IORQ'B 18 A11 /IOREQ 18 /IOREQ 17 V /IORQ 15 A11
|
|
/RD'B 19 A10 /RD 19 /RD 18 U /RD 16 A10
|
|
/WR'B 20 A9 /WR 20 /BUSREQ /WR 19 /BUSREQ /WR 17 A9
|
|
/BUSAK 21 A8 21 /RESET -5V 20 /RESET /BUSAK 18 A8
|
|
/WAIT 22 A7 /WAIT 22 A7 /WAIT 21 A7 /WAIT 19 A7
|
|
/BUSRQ 23 A6 23 A6 +12V 22 A6 /BUSRQ 20 A6
|
|
/RESET 24 A5 24 A5 -12V 23 A5 /RESET 21 A5
|
|
/M1 25 A4 /M1 25 A4 /M1 24 A4 /MI 22 A4
|
|
/RFSH'B 26 (DZ OUT) /RFSH 26 /ROMCS /RFSH 25 /ROMCS /REFSH 23 /ROM CS
|
|
/EXROM 27 RGB-R A8 27 /BUSACK A8 26 /BUSACK
|
|
/ROSCS 28 RGB-G A10 28 A9 A10 27 A9
|
|
/BE 29 RGB-B N.C. 29 A11 N.C. 28 A11
|
|
(IO A5) 30 (BUSISO) RED 30 CSYNC
|
|
SOUND 31 VIDEO GREEN 31 BRIGHT
|
|
GND 32 GND BLUE 32 GND
|
|
The Spectrum/TC20xx port (europe) is compatible only with the signals used by
|
|
the ZX81 printer, but not compatible with other ZX80/ZX81 hardware (for some
|
|
crazy reason, the /RESET pin is replaced by -12V, giving it a good chance to
|
|
vaporize any ZX80/ZX81 hardware). The TS2068 port (usa) is almost fully
|
|
backwards compatible with the ZX80/ZX81 and TS1000/TS1500 ports, but
|
|
incompatible with Spectrum/TC20xx ports.
|
|
On the Spectrum 48K, the /Y,U,V,VIDEO signals are passed through jumpers on the
|
|
mainboard, the Y,U,V jumpers are usually installed, but the VID jumper isn't
|
|
(so without adding that jumper, VIDEO isn't actually output on Pin15/Bottom).
|
|
|
|
Signal Notes
|
|
CPU CLK normally 3.5MHz clock, but, PAUSED during waitstates
|
|
/ROMCS BIOS chipselect (can be dragged to 5V to disable internal BIOS)
|
|
/IORQULA ULA chipselect (can be dragged to 5V to disable ULA mirrors)
|
|
|
|
TS2068 Notes
|
|
(BUSISO),(IO A5),(DZ IN),(DZ OUT) are "not connected" (but are reserved for
|
|
something or so). "IO A5 (Bit5 of PSG Port A) available on edge-slot)" so it is
|
|
NOT not-connected...?
|
|
|
|
TC20xx
|
|
Although the TC2048/TC2068 are based on the US TS2068, their expansion port
|
|
pin-outs were converted back to the 2x28 pin Spectrum layout to match the
|
|
european market. During that backwards-conversion the /IORQULA pin got lost,
|
|
the TC devrs apparently didn't understand its purpose, in the first version of
|
|
the mainboard they have left it unconnected, in the next version it's
|
|
accidently connected to /IOREQ via a jumper, in the third version it's directly
|
|
wired to /IOREQ without any jumper.
|
|
|
|
Later Spectrums
|
|
Later Spectrums (eg. +3) don't use a +9V power supply, and thus leave the +9V
|
|
pin unconnected; also, later models changed the pin numbering from 1..28 to
|
|
1..27 (with the SLOT spacings not being counted as pins). Also, the +3 has
|
|
Pin4/comp = /ROM1OE, no -5V, no /BUSACK, no /IORQULA, no /ROMCS,
|
|
Pin28/comp=RESET, and VIDEO,/Y,V,U replaced by
|
|
/ROM2OE,/DISKRD,/DISKWR,/MOTORON.
|
|
|
|
Spectrum ROM Cartridges
|
|
-----------------------
|
|
|
|
Cartridge Slots (female cart-edge, 2x18 or 2x15 pins)
|
|
TS2068/TC2068 Cartridges (2x18 pin) Interface 2 Cartridges (2x15 pin)
|
|
Solder Side Component Side Whatever Side Other Side
|
|
1 A14'B 2 +5V 1A /ROMCS (+5V) 1B +5V
|
|
3..A12...........4..A13'B.....SLOT.. 2A A12 2B A15 (/CS2)
|
|
5 D0 6 D7 3A A7 3B A13
|
|
7 D1 8 A0 4A A6 4B A8
|
|
9 D2 10 A1 5A (SLOT) 5B (SLOT)
|
|
11 D6 12 A2 6A A5 6B A9
|
|
13 D5 14 A3 7A A4 7B A11
|
|
15 D3 16 A15B 8A A3 8B /MREQ (/OE)
|
|
17 D4 18 /MREQ'B 9A A2 9B A10
|
|
19 /IORQ'B 20 A7R'B 10A A1 10B A14 (/CS1)
|
|
21 /RD'B 22 /M1 11A A0 11B D7
|
|
23 /WR'B 24 A8 12A D0 12B D6
|
|
25 A7 26 A9 13A D1 13B D5
|
|
27 A6 28 A10 14A D2 14B D4
|
|
29 A5 30 A11 15A GND 15B D3
|
|
31 A4 32 /RFSH'B or /ROMCS
|
|
33 /BE or ROMDIS 34 /EXROM
|
|
35 /ROSCS 36 GND
|
|
|
|
Timex TS2068/TC2068 Cartridges
|
|
The TS2068/TC2068 (but not the TC2048) contain a built-in cartridge slot.
|
|
The TC2068 cartridges are slightly bigger in height than TS2068 cartridges (so
|
|
the bigger TC2068 carts won't fit into the smaller TS2068 slot without
|
|
modifying the plastic case), and, the pinouts are slightly different for
|
|
TS2068/TC2068 (pin32 and pin33).
|
|
A7R'B=Refresh Address Bit7, /RFSH=Refresh (TS2068 only), /BE=Bank Enable
|
|
(TS2068 only), /EXROM (useless), /ROMCS (useless) (TC2068 only),
|
|
ROMDIS="disables both internal ROM and also forces high state on both /ROMCS
|
|
and /EXROM in the slot" (TC2068 only), /ROSCS=ROS Chip Select (Dock Bank
|
|
Enable), xx'B=buffered (not directly connected to corresponding xx pin on CPU).
|
|
|
|
Timex Cartridge Types
|
|
LROS --> Language ROM-Oriented Software at 0000h (Z80 Code)
|
|
AROS --> Application ROM-Oriented Software at 8000h (BASIC or Z80 Code)
|
|
BASIC code isn't directly executed in ROM, instead, the current BASIC line is
|
|
copied to ARSBUF in RAM, and then executed from there. USR function does
|
|
address ROM. While PEEK/POKE address RAM?. User-Defined BASIC functions (DEF
|
|
FN) aren't supported.
|
|
|
|
Timex LROS Header
|
|
0000h Not used (should be F4h for Spectrum ROMs, see comment)
|
|
0001h Cartridge Type (01h=LROS)
|
|
0002h Entrypoint (16bit)
|
|
0004h Initial Value Port F4h (XORed by FFh)
|
|
0038h IRQ Handler
|
|
Note: [0004h].Bit3 should be set (otherwise the Machine Stack and Bank
|
|
Switching code gets replaced by ROM). Caution the LROS is started with IRQs
|
|
enabled (so the handler at 0038h might be called even before the Entrypoint
|
|
handler is executed). Accordingly, [0004h] must enable any ROM locations used
|
|
by the Entrypoint, and such used by the IRQ handler.
|
|
Comment: Some Spectrum games have JR FFF4h opcode as IM 2 interrupt handler at
|
|
FFFFh, the opcode consists of [FFFFh]=18h (in RAM), and [0000h]=F4h (ie.
|
|
initial DI opcode - or 1st byte of the LROS header) in BIOS ROM. Ie. an LROS
|
|
cartridge with Spectrum ROM and LROS header should contain the DI opcode at
|
|
0000h.
|
|
|
|
Timex AROS Header
|
|
8000h Language Type (01h=BASIC, 02h=Machine Code) (other=Error)
|
|
8001h Cartridge Type (02h=AROS) (other=no cartridge)
|
|
8002h Entrypoint (16bit) (ptr to first BASIC Line, or to first opcode)
|
|
8004h Initial Value Port F4h (not XORed) (Bit0-3 must be set for BIOS/VRAM)
|
|
8005h Autostart Flag (0=No, 1=Autostart)
|
|
8006h Number of bytes of RAM reserved for Machine Code variables (16bit)
|
|
Bug: [8006h] must be set to "N+15h" to allocated "N" bytes.
|
|
|
|
Timex The Spectrum Emulator Cartridge:
|
|
"This cartridge made by Timex of Portugal, contains a ROM image of TC2048. I
|
|
think that this isn't a ROM cartridge, but a LROS cartridge, because it is
|
|
simply plugged to TC2068 and it starts automaticaly. Many American Timex
|
|
Sinclair 2068 users made a cartridge with a ROM chip of a ZX Spectrum and
|
|
because of this, they have to type the OUT 244,3 command."
|
|
|
|
Spectrum Interface 2 Cartridges
|
|
In the cartridge, /ROMCS is usually wired to +5V, completely disabling the
|
|
BIOS, and allowing to map 16K ROM to 0000h..3FFFh. There were only 10
|
|
cartridges manufactured, all of them only 16K in size, using ROM chips with two
|
|
/CS pins. For normal EPROMs, /CS1 and /CS2 would need to be ORed by external
|
|
logic (although /CS2 aka A15 could be left unconnected when not using the upper
|
|
32K of RAM). Bank switching for more than 16K ROM can be implemented by reading
|
|
from a specific memory region, and latching LSBs of the address as bank number;
|
|
observe that /MREQ gets low on /RD, /WR, and /RFSH; during refresh, the IR
|
|
register pair is output to the address bus, so the I register should be set to
|
|
a value that doesn't conflict with the bank switching addresses.
|
|
|
|
Timex TS1510 Command Cartridge Player (Pinouts unknown?)
|
|
An external cartridge adaptor for the TS1500. It can be also used with
|
|
TS1000/ZX81 with a 16K RAM upgrade (assuming that most or all cartridges do
|
|
require 16K RAM; there were only 4 carts manufactured).
|
|
The TS1500 BIOS starts cartridges automatically; it jumps to 2000h if the first
|
|
byte at [2000h] is 01h (ie. a LD BC,nnnn opcode). On a ZX81/TS1000, the
|
|
cartridge must be manually started (eg. by typing RAND USR 8192). Aside from
|
|
the cartridge connector, the TS1510 includes a RESET button.
|
|
The first 8K of ROM is obviosly mapped to 2000h. Carts with 16K or more ROM are
|
|
mapped to unknown (?) memory locations. According to the manual, such bigger
|
|
carts won't work on computers expanded to 32K RAM (which have extra RAM at
|
|
8000h..BFFFh) (so the extra ROM is probably mapped to that region).
|
|
The memory mapping logic seems to be built-in in the TS1510 (rather than in the
|
|
cartridge), looking at photo found in the internet, it seems to contain a
|
|
74LS00 chip, and another chip whose part number is unknown due to bad quality
|
|
of the photo.
|
|
The TS1510 was advertised to support up to 24K ROM.
|
|
Only four TS1510 cartridge titles were ever released:
|
|
07-9001 Supermath
|
|
07-9002 States and Capitals
|
|
07-9003 Chess
|
|
07-9004 Flight Simulator
|
|
|
|
Spectrum Chipset Pinouts
|
|
------------------------
|
|
|
|
Ferranti 6C001 (Spectrum 48K) - Uncommitted Logic Array (ULA):
|
|
Ferranti 7C001 (Spectrum 128K) - Uncommitted Logic Array (ULA):
|
|
1 /CAS 6 A1 11 A6 16 VIDEO V 21 D1 26 KB4 31 D7 36 A14
|
|
2 /WR 7 A2 12 /INT 17 VIDEO /Y 22 D2 27 D4 32 CLOCK 37 A15
|
|
3 /RD 8 A3 13 +5V 18 D0 23 KB2 28 SOUND 33 /IO-ULA 38 /MREQ
|
|
4 /WE 9 A4 14 +5V' 19 KB0 24 KB3 29 D5 34 /ROM CS 39 OSC
|
|
5 A0 10 A5 15 VIDEO U 20 KB1 25 D3 30 D6 35 /RAS 40 GND
|
|
SOUND is the analog-I/O-line for beep, save and load.
|
|
CLK is the clock-source to the CPU including the inhibited T-states.
|
|
IO-ULA is "A0(CPU) OR /IORQ" for the I/O-port FEh.
|
|
OSC is the 14MHz-crystal, other side grounded through a capacitor.
|
|
One of the +5V is decoupled through a RC-low-pass.
|
|
|
|
TS2068 SCLD
|
|
1 A0 11 /EXROM 21 MUX 31 MA0 41 /CAS1 51 KB2 61 D4
|
|
2 A1 12 /BE 22 MA7 32 /ROSCS 42 CLK CPU 52 KB3 62 D7
|
|
3 A2 13 OSC OUT 23 MA3 33 /RAS1 43 +5V 53 KB4 63 /RD
|
|
4 A3 14 OSC IN 24 MA4 34 VIDEO U 44 A14 54 /RD' 64 /IORQ
|
|
5 A4 15 TAPE IN 25 MA2 35 VIDEO V 45 A15 55 D1 65 /WR
|
|
6 A5 16 TAPE OUT 26 GND 36 VIDEO /Y 46 VIDEO B 56 D2 66 /MREQ
|
|
7 A6 17 PSG BC1 27 /ROMCS 37 /DRAMWE 47 VIDEO G 57 D0 67 /INT
|
|
8 A7 18 PSG BDIR 28 MA6 38 A7R 48 VIDEO R 58 D3 68 /RFSH
|
|
9 A13 19 PSG CLK 29 MA1 39 /CAS3 49 KB0 59 D5
|
|
10 CLK EXP 20 /TS 30 MA5 40 /CAS2 50 KB1 60 D6
|
|
|
|
Gate Array +2A/+3
|
|
1 BUSY 14 MA3 27 A15 40 GND2 53 K10 66 GND3 79 /RFS 92 PSG CLK
|
|
2 EAR 15 GND1 28 K0 41 VCC1 54 DV7 67 VA3 80 /IRQ 93 PSG BC1
|
|
3 A0 16 MA4 29 K1 42 BRIT 55 DV6 68 VA2 81 /MRQ 94 PSG BDIR
|
|
4 A1 17 MA5 30 K2 43 /SNC 56 DV5 69 VA1 82 /WR 95 /VWE
|
|
5 A2 18 MA6 31 K3 44 FSC2 57 DV4 70 VA0 83 /RD 96 /VCS
|
|
6 A3 19 MA7 32 K4 45 /RS 58 DV3 71 D7 84 /ROM2 97 /VRS
|
|
7 A4 20 A8 33 /MTR 46 /CS 59 DV2 72 D6 85 /ROM1 98 MIC
|
|
8 A5 21 A9 34 PRNT 47 STRB 60 DV1 73 D5 86 RA14 99 /RS
|
|
9 A6 22 A10 35 /DRD 48 K5 61 DV0 74 D4 87 /ZCK 100 OSC
|
|
10 A7 23 A11 36 /DWR 49 K6 62 VA7 75 D3 88 /INT
|
|
11 MA0 24 A12 37 VIDEO B 50 K7 63 VA6 76 D2 89 /WAIT
|
|
12 MA1 25 A13 38 VIDEO R 51 K8 64 VA5 77 D1 90 GND4
|
|
13 MA2 26 A14 39 VIDEO G 52 K9 65 VA4 78 D0 91 VCC2
|
|
|
|
AY-3-8912 Sound Chip (PSG)
|
|
1 SND C 5 SND A 9 P5 13 P1 17 A8 (+5V) 21 D7 25 D3
|
|
2 TEST,NC 6 GND 10 P4 14 P0 18 BDIR 22 D6 26 D2
|
|
3 +5V 7 P7 11 P3 15 CLK 19 BC2(+5V) 23 D5 27 D1
|
|
4 SND B 8 P6 12 P2 16 /RES 20 BC1 24 D4 28 D0
|
|
Timex TS2068 uses CLK=1.76475Mhz, Spectrum +3 uses CLK=1.7734MHz.
|
|
|
|
Spectrum Xboo
|
|
-------------
|
|
|
|
Step 1 - Connect Centronics Port and EPROM
|
|
GND ------------------- CNTR.24 GND
|
|
ULA.Pin28 ------|>o---- CNTR.10 ACK (SPKR)
|
|
EAR ------------------- CNTR.2 D0 (EAR)
|
|
KB1.Pin1 "0" ---|>|---- CNTR.3 D1 (CLK)
|
|
KB1.Pin2 "9" ---|>|---- CNTR.4 D2 (D0)
|
|
KB1.Pin3 "8" ---|>|---- CNTR.5 D3 (D1)
|
|
KB1.Pin4 "7" ---|>|---- CNTR.6 D4 (D2)
|
|
KB1.Pin5 "6" ---|>|---- CNTR.7 D5 (D3)
|
|
CPU.Pin26 ----|>|---- CNTR.8 D6 (/RESET)
|
|
EPROM.Pin27 ----------- CNTR.9 D7 (ROM.A14)
|
|
EPROM.Pin27 ---/cut/--- /RD
|
|
EPROM.Pin27 ---[3k3]--- +5V
|
|
EPROM.Pin1 ----------- +5V
|
|
ACK must be amplified via a TTL inverter (eg. by using an unused NAND gate,
|
|
found on Pin1-3 of IC24 (74LS00) on Spectrum 48K Issue 2 mainboards; note that
|
|
the unused inputs are wired to 5V). Pass the reset and keyboard lines through
|
|
1N4148 diodes to prevent them to get stuck. Remove the ROM, and replace it by a
|
|
28pin socket for the EPROM, with 1:1 connection, except for pin1 (usually NC),
|
|
and pin27 (usually /RD), omitting the /RD line causes the EPROM to respond also
|
|
to writes and refresh, but that should be no problem.
|
|
|
|
Step 2 - Connect Joystick (Sinclair 1)
|
|
KB1.PIN1 "0" ---|>|--- DSUB.Pin6 Fire
|
|
KB1.PIN2 "9" ---|>|--- DSUB.Pin1 Up
|
|
KB1.PIN3 "8" ---|>|--- DSUB.Pin2 Down
|
|
KB1.PIN4 "7" ---|>|--- DSUB.Pin4 Right
|
|
KB1.PIN5 "6" ---|>|--- DSUB.Pin3 Left
|
|
KB2.PIN4 A12 ---|<|--- DSUB.Pin8 Common
|
|
Connect all joystick lines through 1N4148 diodes (the diode in A12 line facing
|
|
in opposite direction). The five joystick data diodes are required because the
|
|
joystick cable doesn't contain terminator resistors; without these diodes, the
|
|
xboo transmission won't work without the diodes when signals "bounce back" from
|
|
the end of the long joystick cable). Without the A12 diode, the Spectrum game
|
|
"Zynaps" would crash after 1-2 minutes (no idea why, there is already a diode
|
|
on the mainboard, so adding another diode should have little effect, but it
|
|
does fix the zynaps crash, maybe it just works as a resistor).
|
|
|
|
Step 3 - Connect AV-Cable
|
|
GND ----------------------------------------- Cinch GND
|
|
VID ----------------------------------------- Cinch V
|
|
MIC ----------------------------------------- Cinch A
|
|
Connect the Cinch sockets to the "VID" jumper, and to the "MIC" socket, the
|
|
cables don't need to be shielded, but, Cinch GND should be connected somewhere
|
|
close to the TV modulator (this gives a better picture).
|
|
|
|
Step 4 - Connect Supply from PC
|
|
There are two simple ways to replace the 9V supply by voltages from a PC power
|
|
supply. The straight way would be to use a 7809 to lower 12V to 9V, but the
|
|
7809 produces a lot of heat (and the internal 7805 produces further heat when
|
|
it lowers the 9V to 5V). So, my preferred way would be to use 5V:
|
|
Spectrum 5V ------------ PC 5V (red floppy cable)
|
|
Spectrum 5V -----||----- Spectrum GND
|
|
Spectrum 5V ----|>|----- Spectrum 9V
|
|
Inject 5V from the PC supply to 5V on the mainboard (there's no need to inject
|
|
GND, since that's passed through the centronics cable). Add a 470uF capacitor
|
|
between 5V and GND for better video quality. Pass 5V to 9V via a 1N4001 diode
|
|
(this feeds the internal +12V/-5V voltage generator which is usually driven at
|
|
9V, but it does also work at 5V, with 5V it's reaching only +10V instead of
|
|
+12V, but does still work; the voltages are required for DRAM and video signal
|
|
generation).
|
|
Basically 5V and 9V could be directly shortcut with each other, however, the
|
|
diode has two purposes: First, it prevents 9V being passed to 5V (in case
|
|
somebody connects a 9V supply). Second, it reduces noise from the voltage
|
|
generator on the 5V line (without the diode one might need a larger 2200uF
|
|
capactitor instead of 470uF one).
|
|
Caution - The 5V solution has two disadvantages: The TV modulator does no
|
|
longer work (not sure why, maybe it requires full 12V, or maybe the voltage
|
|
generator is producing too much noise when driven at 5V) (anyways, the AV cinch
|
|
output does work). And, it doesn't output 9V on the expansion port (which may
|
|
be required by some expansion hardware).
|
|
|
|
Step 5 - Connect Keyboard
|
|
The keyboard is connected via extremly fragile printed plastic wires, which
|
|
tend to break when fiddling with them (or just when they get old). The membrane
|
|
with the keyboard matrix consists of the same material, but the wires are the
|
|
most fragile part.
|
|
Desolder the keyboard connectors. Connect real metal wires to the connectors.
|
|
Cut the original plasitic wires close to the membrane. Carefully slide the
|
|
connectors on the remaining ends (best, put the ends on a solid surface, if
|
|
there's no good surfaces: put 1-2 layers of board under the ends, then firmly
|
|
push the ends onto that surface, and move the connector onto the cable; rather
|
|
than trying to move the cable into the connector. If needed, add some
|
|
tuner/contact spray, and move the cable end in and out a little. Finally, glue
|
|
the connectors to the case.
|
|
|
|
Software
|
|
The transmit function (for uploading .TAP files to the Spectrum) is found in
|
|
no$zx's "Utility" menu. The "Utility" menu also contains a function called
|
|
Create Patched BIOS Image, which creates a file called XMITSPEC.ROM, which is
|
|
to be stored in the EPROM; the ROM-image is 32K in size, containing two copies
|
|
(one original, and one patched) of the ZX Spectrum BIOS.
|
|
|
|
Note
|
|
Above Pin-numbers are for Spectrum 48K Issue 2 board (some may vary on other
|
|
boards). The transmit software currently works only with ZX Spectrum
|
|
16K/48K/Plus (not with Spectrum 128 and up).
|
|
|
|
Lambda 8300
|
|
-----------
|
|
|
|
The Lambda 8300 is a ZX81 clone (not an exact clone) made in china, and
|
|
distributed by various companies, in various countries, under various different
|
|
names...
|
|
Name___________Usage_______________
|
|
Lambda 8300 (Denmark, Sweden, Norway)
|
|
Power 3000 Creon Enterprises (Hongkong) (Denmark, Germany)
|
|
Marathon 32K (Denmark)
|
|
Futura 8300 Unisonic (USA)
|
|
DEF 3000 (France)
|
|
Your Computer
|
|
IQ8300 (China?)
|
|
BASIC 2000
|
|
BASIC 3000
|
|
PC 2000
|
|
PC 8300 Text on mainboard
|
|
|
|
PC8300 BASIC
|
|
The BASIC syntax is more or less the same as on ZX81, so it accepts ZX81 BASIC
|
|
type-in listings in most cases, there is also (limited) support for loading
|
|
ZX81 cassette files. A few commands/functions are different: LOG (instead LN),
|
|
LET (can be optionally omitted), and the quad-quotes token ("") isn't supported
|
|
(ie. one cannot define double-quotes in strings). Additional commands are
|
|
TEMPO, MUSIC, SOUND, BEEP, NOBEEP (for internal speaker), and INK, PAPER,
|
|
BORDER (for external COLOR module).
|
|
|
|
PC8300 BIOS
|
|
The BIOS is apparently based on a disassembled and modified ZX81 BIOS. About
|
|
ALL procedures are moved to different addresses, so there's no compatibility
|
|
when CALLing BIOS functions. Only the INT and NMI handler are (more or less)
|
|
same as in ZX81 (the timings are slightly changed, the INT handler has same
|
|
function, but C and B registers are exchanged).
|
|
|
|
PC8300 RAM
|
|
Some entries in system area are modified. D_FILE is hardcoded at 407Dh, D_FILE
|
|
is always expanded (full 1+33*24 bytes). BASIC program is located after D_FILE
|
|
(ie. always at 4396h since D_FILE has fixed size). The BASIC program is
|
|
terminated by an FFh byte (ZX81 has no such end byte). The remaining memory
|
|
(VARS and up) is same as on ZX81.
|
|
The RAMTOP detection supports up to 32K RAM (unlike ZX81 which detects max
|
|
16K). The Lambda includes 2K RAM built-in (unlike 1K in ZX81). Note: despite of
|
|
its name, the Marathon 32K also has only 2K RAM built-in (not 32K).
|
|
|
|
PC8300 CHARSET
|
|
Six characters are different as on ZX81. The charset is located in the ULA chip
|
|
without using I register (the ZX81 has it in BIOS ROM, accessed via I=1Eh).
|
|
Accordingly, changing the I register doesn't affect video (so neither True
|
|
Hires nor Pseudo Hires will work, and any UDG/CHRs hardware expansions won't
|
|
work either). The CPU can read the charset via I/O ports (mainly required for
|
|
printers).
|
|
The video output is reportedly the inverse of ZX81, ie. white text on black
|
|
background with black screen border.
|
|
|
|
PC8300 PRINTERS
|
|
The BIOS supports the Sinclair Printer as well as an external Centronics
|
|
interface. The Centronics feature includes two modes: ZX chars converted to
|
|
ASCII, or ZX chars converted to bitmaps (via ESC codes, which must be supported
|
|
by the printer).
|
|
|
|
PC8300 KEYBOARD
|
|
42 Keys. The left 40 keys are same as on ZX81. The upper right key is wired to
|
|
/RESET causing a warmboot (pressing /RESET+ENTER forces a coldboot,
|
|
/RESET+L_KEY jumps to 2000h in external memory such like ROM, or COLOR RAM).
|
|
The lower right key is same as the left SHIFT key. Punctuation marks and
|
|
Cursor, Rubout, Edit, Graphics keys are at different location as than in ZX81.
|
|
Commands are entered letter-by-letter (eg. type L-O-A-D, unlike pressing J on
|
|
ZX81).
|
|
|
|
PC8300 SOUND
|
|
Contains a built-in speaker. The output level can be toggled HIGH/LOW by
|
|
reading from an I/O port. Allows to produce a single square wave at fixed
|
|
volume (though using PWM, one could eventually mix multiple channels at
|
|
variable volume). Since both sound and video require a lot of CPU load, it's
|
|
barely possible to output sound & video together. The BEEP (keyclick) is a very
|
|
remarkable feature: each key has a different tone assigned, resulting in a
|
|
funny melodic old-school SciFi typing effect.
|
|
|
|
PC8300 SOFTWARE
|
|
A few photos of cassettes do exist. As far as known there aren't any tape
|
|
images. Strange RAW <--> A83 conversion programs exists (purpose unknown).
|
|
|
|
PC8300 JOYSTICK
|
|
DSUB 9pin Atari-style joystick port (with only four directions and one fire
|
|
button implemented). Wired to keyboard matrix Bit3=Common, and
|
|
A11 = 2 = Up,
|
|
A10 = W = Down,
|
|
A12 = 9 = Left,
|
|
A9 = S = Right,
|
|
A13 = O = Fire
|
|
(according to Kai Fischer's schematic).
|
|
|
|
PC8300 FILES
|
|
Cassette files are SAVEd with circa 16000 leading sync pulses (though, this is
|
|
a fake, the LOAD function simply ignores them). Followed by a ZX81-style file:
|
|
Some silence, followed by the Filename terminated with bit7=1, followed by
|
|
memory at [4009h..[4014h]-1]. The memory content isn't ZX81 compatibile though
|
|
(different system area, different D_FILE location, different BASIC tokens). The
|
|
VERSN byte at 4009h is FFh (unlike 00h on ZX81).
|
|
Bits and bytes are encoded same as on ZX81 (0=four pulses, 1=nine pulses, with
|
|
same pulse/silence timings).
|
|
|
|
PC8300 SUPPORT FOR ZX81 FILES
|
|
The Lambda BIOS can load ZX81 files, but with several restrictions: The files
|
|
are converted to Lambda format (and cannot be converted back to ZX81 format).
|
|
Information in the system area (such like Autostart), and VARS and D_FILE
|
|
regions are discarded (only the raw BASIC code is accepted).
|
|
BUG: After loading a ZX81 file, the BIOS accidently jumps to 2000h, normally
|
|
this is a mirror of 0000h which produces a warmboot - however, it'll crash if a
|
|
Color RAM expansion is installed (workaround: POKE a RST0 opcode to 2000h), or
|
|
accidently start any expansion ROM at 2000h.
|
|
|
|
PC8300 COLOR EXPANSION
|
|
Colors are optionally supported via an external color module. The Lambda BIOS
|
|
contains built-in commands (INK/PAPER/BORDER) for it. The module connects to
|
|
expansion port, and also to the monochrome composite video output, deciphers
|
|
the "analogue" signal into TTL black/white and TTL sync/nosync signals.
|
|
Color attribtes are stored in 1K read/write-able RAM at 2000h..23FFh. During
|
|
drawing, the module takes the D_FILE address (usually 407Dh..4395h) ANDed with
|
|
3FFh as index in the RAM, and reads the color attribute for the current
|
|
character. The attributes associated with the HALT opcodes in D_FILE define the
|
|
current section of the screen border color. The attribute bytes are Bit0-2 =
|
|
INK, Bit4-6 = PAPER/BORDER, bit3,7 can be used as general purpose flags, but do
|
|
not affect the video output. The monochrome luminance level selects INK/PAPER,
|
|
but otherwise doesn't affect the outgoing signal (eg. PEN=3 and PAPER=3 do
|
|
produce exactly the same color & same brightness).
|
|
XXX does the border affect the COLOR BURST signal?
|
|
XXX and thus alter the colors in the picture region?
|
|
XXXXXX the 3bit color values allow to use 8 colors,
|
|
XXXXXX but it's unknown WHICH colors?
|
|
|
|
PC8300 TIMINGS
|
|
The INT handler (0038h) is made 1 cycle slower as than on ZX81, meaning that
|
|
the Lambda executes 208 clks/scanline (ZX81 only 207 clks).
|
|
The NMI handler is "improved" (the useless JP opcode removed, but the JR is
|
|
replaced by a JP, so there is no speedup gained, to the worst, there's a
|
|
bizarre NOP inserted making NMI handling 4 cycles slower than on ZX81, making
|
|
the SLOW mode even slower-than-slow.
|
|
|
|
PC8300 I/O PORTS
|
|
I/O:xxF5h.W ;select charset line number (00..07) ;\use only in FAST mode,
|
|
I/O:xxF6h.W ;select charset char number (00..3F) ;/or after HSYNC (NMI)
|
|
I/O:xxFBh.W ;printer control (sinclair pixel-style, or ASCII character)
|
|
I/O:xxFDh.W ;disable NMIs
|
|
I/O:xxFEh.W ;enable NMIs
|
|
I/O:xxFFh.W ;terminate retrace / CAS output
|
|
I/O:xxF5h.R ;toggle sound output level
|
|
I/O:xxF6h.R ;read selected charset data (8 pixels)
|
|
I/O:xxFBh.R ;printer status
|
|
I/O:NNFEh.R ;read keyboard (A8..A15=row) (and CAS.IN) (and JOYSTICK)
|
|
;(but no PAL/NTSC bit here, unlike ZX81)
|
|
I/O:FF7Eh.R ;read PAL/NTSC flag (A7=row) (via diode from A7 to KEYB.0)
|
|
MEM:00XXh dummy blink addr in write-protected BIOS ROM
|
|
MEM:2000h optional boot entryoint (in COLOR RAM, or TS1510-cartirdges)
|
|
MEM:2XXXh COLOR ATTRIBUTES (external color module)
|
|
MEM:3000h disable color ram (on any write to 3000-3FFE with A0=0)
|
|
MEM:3001h enable color ram (on any write to 3001-3FFF with A0=1)
|
|
|
|
PC8300 System Area
|
|
4000 2 unused (unlike ZX81: ERR_NR, FLAGS) (not used)
|
|
4002 2 err_sp (same as ZX81)
|
|
4004 2 ramtop (same as ZX81, but, max 32K)
|
|
4006 1 prmode (unlike ZX81: MODE, cursor shape) (instead: printer mode)
|
|
4007 1 err_nr (unlike ZX81: ppc.lsb)
|
|
4008 1 color (unlike ZX81: ppc.msb)
|
|
SAVE area... (same as ZX81)
|
|
4009 1 versn (versn, and other temporary flags) (00h=ZX81, FFh=Lambda)
|
|
400A 2 nxtlin (unlike ZX81: e_ppc)
|
|
400C 2 program (unlike ZX81: d_file)
|
|
400E 2 df_cc (same as ZX81)
|
|
4010 2 vars (same as ZX81)
|
|
4012 2 dest (same as ZX81)
|
|
4014 2 e_line (same as ZX81) (input/workspace buffer, end of SAVE area)
|
|
4016 2 ch_add (same as ZX81)
|
|
4018 2 x_ptr (same as ZX81) (error/abort address)
|
|
401A 2 stkbot (same as ZX81)
|
|
401C 2 stkend (same as ZX81) (increases on PUSHes)
|
|
401E 1 flags (unlike ZX81: berg) (same as 4001h on ZX81)
|
|
401F 2 mem (same as ZX81)
|
|
4021 1 munit (unlike ZX81: unused) (tempo for music)
|
|
4022 1 df_sz (same as ZX81)
|
|
4023 2 s_top (same as ZX81)
|
|
4025 2 last_k (same as ZX81)
|
|
4027 1 bounce (same as ZX81)
|
|
4028 1 margin (same as ZX81) (but, derived from other I/O mechanism)
|
|
4029 2 e_ppc (unlike ZX81: nxtlin)
|
|
402B 2 oldppc (same as ZX81)
|
|
402D 1 flagx (same as ZX81)
|
|
402E 2 strlen (same as ZX81)
|
|
4030 2 t_addr (same as ZX81)
|
|
4032 2 seed (same as ZX81)
|
|
4034 2 frames (same as ZX81)
|
|
4036 2 ppc (unlike ZX81: coords) (same as 4007h on ZX81)
|
|
4038 1 pr_cc (same as ZX81)
|
|
4039 2 s_posn (same as ZX81)
|
|
403B 1 cdflag (additional bit4=graphics_cursor, bit5=beep_disable)
|
|
403C 33 prbuff (same as ZX81)
|
|
405D 30 membot (same as ZX81)
|
|
407B 2 blink (unlike ZX81: blink address instead unused)
|
|
N/A 1 mode (no [K],[L],[F] cursors, only [G] = flag in cdflag.bit4)
|
|
N/A 1 berg (none such, memorized somehow elsewhere)
|
|
N/A 2 coords (none such,isn't really used on ZX81 either)
|
|
4009 VERSN Should be 00h to identify ZX81 cassette files
|
|
BUG: [400Ch] is NOT properly set after loading ZX81 files, so better use 4396h
|
|
than [400Ch].
|
|
|
|
PC8300 BIOS-MOD
|
|
There is also an alternate Lambda BIOS in the internet. It's source is unknown,
|
|
it seems to be an commercial or homebrewn BIOS replacement, intended to improve
|
|
ZX81 compatibility (called "replacement" because the BIOS doesn't match-up with
|
|
the Lambda keyboard, so it's unlikely that Lambda's were sold with that BIOS
|
|
built-in).
|
|
Patched TS1500 BIOS (around 1K modified, remaining 7K same as in original
|
|
BIOS). RAMTOP is hardcoded as 16K (won't work with less memory). Frame rate is
|
|
hardcoded as 60Hz. Keyboard layout is same as in ZX81 (cursor keys, punctuation
|
|
marks, and token-hotkeys don't match up with the Lambda keyboard). Doesn't
|
|
include charset in BIOS (uses the Lambda ULA charset, so, for video and printer
|
|
output, six chars are still different as on ZX81).
|
|
Fileformat and memory map are exactly same as in ZX81, so it's compatible with
|
|
machine code programs with hardcoded ZX81 memory addresses. System area is same
|
|
as ZX81, though with some extra bits in 403Bh (bit3=REM n Cursor Blink Enable,
|
|
bit4=STEP n Auto-Edit enable, bit5=BEEP n Keyclick Beep disable) and 407Bh
|
|
(16bit Cursor address for blink).
|
|
BASIC includes some new/modified commands/functions: BEEP n (n=1 enables
|
|
keyclick sounds, n=0 disables it), IN/OUT (executes IN/OUT opcode, the port
|
|
address is only 8bit wide, not 16bit), STEP n (usually suffix for FOR, but in
|
|
this BIOS it can be also as command to edit line "n" and all following/existing
|
|
lines), REM n (n=1 enables cursor blink, n=0 disables it).
|
|
|
|
Jupiter ACE
|
|
-----------
|
|
|
|
The ACE was manufactured by Jupiter Cantab from England in 1983. It was
|
|
designed by two ex-Sinclair Research employees, Steven Vickers and Richard
|
|
Altwasser, who earlier worked on the Sinclair ZX-80 and ZX-81, as well as the
|
|
Spectrum.
|
|
|
|
--> Jupiter ACE I/O Ports
|
|
--> Jupiter ACE Video
|
|
--> Jupiter ACE Dimensions and Timings
|
|
--> Jupiter ACE Memory Map and System Area
|
|
--> Jupiter ACE Files
|
|
|
|
FORTH
|
|
--> FORTH Overview
|
|
--> FORTH Stack and Memory
|
|
--> FORTH Maths
|
|
--> FORTH Input/Output
|
|
--> FORTH ...
|
|
--> FORTH 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 File Header
|
|
Pre 1 Blocktype (00h=Header)
|
|
00h 1 Filetype (20h=Binary)
|
|
01h 10 Filename (ASCII, padded with spaces) (chr 00h = no name)
|
|
0Bh 2 Filesize (LEN)
|
|
0Dh 2 Fileaddr (Default target address, used when desired target=0)
|
|
0Fh 10 Unused (filled with spaces)
|
|
Post 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 Word Definitions
|
|
Pos Len Content
|
|
-N .. word name in ASCII (terminated by bit7=1 in last char)
|
|
-4 2 disp from current addr to NEXT <word name> (RAM words only, not ROM)
|
|
-2 2 ptr to PREVIOUS word definition
|
|
+0 1 length of word name (up to including the last char with bit7=1)
|
|
+1 2 ptr to Z80 machine code handler for this word (usually to ROM)
|
|
+3 .. whatever, probably TYPE and definition...
|
|
|
|
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
|
|
3C4Ch 2 FORTH ptr to next word in chain (or to 3C49h if none)
|
|
|
|
Starting files
|
|
There is no (intended) autostart mechanism provided. The normal way to load and
|
|
start ACE files is bizarre and usually requires detailed loading instructions:
|
|
One must know both the name of the file, and name of its "main" function, in
|
|
some cases one must also manually execute initialization functions. For example
|
|
Jupiter Cantab's "Worms" is - seriously - meant to be started like so:
|
|
LOAD worms GET graphics GO
|
|
If the names are unknown one can do: To discover file names: Type <LOAD dummy>,
|
|
watch the first filename listed on screen, rewind tape, type <LOAD filename>.
|
|
To discover function names: Type VLIST, watch the function/variable names
|
|
(watch quickly - before they get scrolled offscreen). Then try typing some of
|
|
the names, hoping that it's the main function (variables will produce errors,
|
|
subfunctions may act useless) (to start with: <FILENAME>, GO, RUN, PLAY, START,
|
|
MAIN, GAME, etc. would be possible candidates) (some programs may have multiple
|
|
main funtions, eg. PLAY/HELP, or PLAY_EASY/PLAY_DIFFICULT).
|
|
|
|
Empty Filenames
|
|
The BIOS doesn't allow to SAVE something without filenames, however, it can
|
|
LOAD such files (so, with suitable tools, one can create files with empty,
|
|
space-padded filenames). There is no "wildcard" to LOAD the first file on tape,
|
|
so - unless it's empty - the user must always type-in the filename.
|
|
|
|
Autostarting Files
|
|
There are two ways to autostart binary files by just typing "0 0 BLOAD" (or "0.
|
|
BLOAD"):
|
|
1) Load the entrypoint to EXWRCH in system area (EXWRCH gets executed almost
|
|
immediately after loading when the BIOS wants to display "OK"). This method is
|
|
best for machine code.
|
|
2) Load a commandline string into the Input Buffer in VRAM (ie. load <00h,"LOAD
|
|
filename mainfunction"> to address 22E0h). This method is best for FORTH
|
|
programs, and existing (older) files which originally didn't include autostart.
|
|
The VRAM method is used by Spacefighter (also loads a picture into VRAM
|
|
alongside with the commandline). The EXWRCH method is used by Magic Floor.
|
|
Autostarting works only with BLOAD, not with LOAD (the FORTH fileheader doesn't
|
|
include any useful entries; the relocation feature could be tweaked to add an
|
|
offset to whatever memory locations, but that offset is usually 0000h, so it'd
|
|
be useless).
|
|
|
|
FORTH Overview
|
|
--------------
|
|
|
|
Stack
|
|
Stack Notation Cells Description
|
|
c 1 Character (high byte ignored)
|
|
flag 1 Boolean (0 = False, 1 = True)
|
|
n 1 Signed 16bit number
|
|
u 1 Unsigned 16bit number
|
|
x 1 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) Store 16bit immediate on stack (eg. 1)
|
|
f (--> f) Store float immediate on stack (eg. 1.0)
|
|
DROP (x -->) Discard TOS (top of stack)
|
|
DUP (x --> x x) Copy 1st cell to top (Duplicate TOS)
|
|
OVER (x2 x1 --> x2 x1 x2) Copy 2nd cell to top
|
|
PICK (xn..x1 n --> xn..x1 xn) Copy nth cell to top
|
|
SWAP (x2 x1 --> x1 x2) Rotate 2nd cell to top
|
|
ROT (x3 x2 x1 --> x2 x1 x3) Rotate 3rd cell to top
|
|
ROLL (xn..x1 n --> xn-1..x1 xn) Rotate nth cell to top
|
|
?DUP (x --> x (x)) Conditional DUP, only if x = non-zero
|
|
>R (x -->) (R: --> x) Move TOS to Return Stack
|
|
R> (R: x -->) (--> x) Retrieve from Return Stack
|
|
|
|
Memory
|
|
@ (adr --> x) Read x (2 bytes) from adr
|
|
! (x adr -->) Store x (2 bytes) to adr
|
|
C@ (adr --> c) Read c (1 byte) from adr
|
|
C! (c adr -->) Store c (1 byte) to adr
|
|
|
|
FORTH Maths
|
|
-----------
|
|
|
|
Integer Arithmetic
|
|
+ (n1 n2 --> n3) n3 = n1 + n2
|
|
- (n1 n2 --> n3) n3 = n1 - n2
|
|
* (n1 n2 --> n3) n3 = n1 * n2
|
|
/ (n1 n2 --> n3) n4 = n1 / n2
|
|
MOD (n1 n2 --> n3) Remainder of n1 / n2 (sign of n1)
|
|
/MOD (n1 n2 --> n3 n4) n3 = remainder of n1/n2, n4=n1/n2
|
|
*/ (n1 n2 n3 --> n4) n4 = n1*n2/n3
|
|
*/MOD (n1 n2 n3 --> n4 n5) n4 = remainder of n1*n2/n3, n5=n1*n2/n3
|
|
1+ (n1 --> n2) n2 = n1 + 1
|
|
1- (n1 --> n2) n2 = n1 - 1
|
|
2+ (n1 --> n2) n2 = n1 + 2
|
|
2- (n1 --> n2) n2 = n1 - 2
|
|
ABS (n --> u) u = |n| (absolute value)
|
|
NEGATE (n1 --> n2) n2 = -n1 (two's complement)
|
|
U* (u1 u2 --> ud) ud = u1 * u2
|
|
U/MOD (ud u1 --> u2 u3) u2 = remainder of ud/u1, u3 = ud/u1
|
|
D+ (d1 d2 --> d3) d3 = d1 + d2
|
|
DNEGATE (d1 --> d2) d2 = -d1 (two's complement)
|
|
|
|
Floating Point Arithmetic
|
|
INT (f --> n) Convert floating number to integer
|
|
UFLOAT (u --> f) Convert unsigned integer to float
|
|
F+ (f1 f2 --> f3) f3 = f1 + f2
|
|
F- (f1 f2 --> f3) f3 = f1 - f2
|
|
F* (f1 f2 --> f3) f3 = f1 * f2
|
|
F/ (f1 f2 --> f3) f3 = f1 / f2
|
|
FNEGATE (f1 --> f2) f2 = -f1
|
|
|
|
Comparison
|
|
< (n1 n2 --> flag) True if n1 < n2
|
|
= (n1 n2 --> flag) True if n1 = n2
|
|
> (n1 n2 --> flag) True if n1 > n2
|
|
0< (n --> flag) True if n < 0
|
|
0= (n --> flag) True if n = 0
|
|
0> (n --> flag) True if n > 0
|
|
U< (u1 u2 --> flag) True if u1 < u2
|
|
D< (d1 d2 --> flag) True if d1 < d2
|
|
MAX (n1 n2 --> n3) Leave greater of two numbers
|
|
MIN (n1 n2 --> n3) Leave lesser of two numbers
|
|
|
|
Logical
|
|
AND (x1 x2 --> x3) Bitwise boolean AND
|
|
OR (x1 x2 --> x3) Bitwise boolean OR
|
|
XOR (x1 x2 --> x3) Bitwise boolean XOR
|
|
|
|
FORTH Input/Output
|
|
------------------
|
|
|
|
Character Output
|
|
CR (-->) Print carriage return and line feed
|
|
EMIT (c -->) Print ASCII character c
|
|
SPACE (-->) Print one space
|
|
SPACES (n -->) Print n spaces, if n > 0
|
|
." ..." (-->) Print string terminated by " (." 123 test")
|
|
TYPE (adr n -->) Print n characters from adr
|
|
|
|
Number Output
|
|
. (n -->) Print n with one trailing space
|
|
U. (u -->) Print unsigned with one trailing space
|
|
F. (f -->) Print float with one trailing space
|
|
|
|
Formatted Output
|
|
<# (-->) Initiate formatted output
|
|
# (ud1 --> ud2) Convert one digit from ud1 and HOLD it in the PAD
|
|
#S (ud --> 0 0) Convert and HOLD all remaining significant digits
|
|
HOLD (c -->) Insert character into formatted string
|
|
SIGN (n -->) HOLD minus sign if n < 0
|
|
#> (ud --> adr n) Finish formatted output leaving address & length
|
|
of the resulting string
|
|
|
|
Conversion
|
|
BASE (--> adr) 1-byte variable containing system number base
|
|
DECIMAL (-->) Set base to decimal
|
|
ASCII text (--> c) ASCII code of first character in text
|
|
|
|
Character Input
|
|
QUERY (-->) Accept entry at the input buffer
|
|
WORD (c --> adr) Take text from input buffer using c
|
|
as delimiter, leave adr of length byte
|
|
RETYPE ( --> ) Allow input buffer editing, turning cursor to "?"
|
|
INKEY (--> x) Read keyboard (0 = no key pressed)
|
|
|
|
Number Input
|
|
|
|
CONVERT (d1 adr1 --> d2 adr2) Convert string at adr1 to double number
|
|
and add into d1 leaving result d2
|
|
NUMBER (--> x (adr)) Get number from input buffer
|
|
(--> n 4102) Converted to integer
|
|
(--> f 4181) Converted to float
|
|
(--> 0) Conversion failed
|
|
|
|
Misc Screen Output
|
|
CLS (-->) Clear screen
|
|
AT (n1 n2 -->) Set print position to row n1 and column n2
|
|
PLOT (n1 n2 n3 -->) Plot X=n1,Y=n2,Mode=n3 (0=unplot,1=plot,2=move,3=change)
|
|
|
|
FORTH ....
|
|
----------
|
|
|
|
Control Structures
|
|
IF (flag -->) Conditional structure IF..(ELSE)..THEN
|
|
ELSE (-->) False condition of an IF structure
|
|
THEN (-->) End of an IF conditional structure
|
|
DO (n1 n2 -->) Counted loop structure DO...LOOP, (n2=start, n1=end)
|
|
LOOP (-->) Increment loop count, terminate if end
|
|
+LOOP (n -->) Add n to loop count, terminate if end
|
|
I (--> n) Get current loop count
|
|
I' (--> n) Get current loop count limit
|
|
J (--> n) Get outer loop count
|
|
LEAVE (-->) Force a DO...LOOP count to end
|
|
BEGIN (-->) Begin a WHILE or UNTIL loop
|
|
UNTIL (flag -->) Loop until flag = true (BEGIN..UNTIL)
|
|
WHILE (flag -->) Exit loop when flag = false (BEGIN..WHILE..REPEAT)
|
|
REPEAT (-->) Jump back to BEGIN in a WHILE loop
|
|
EXIT ( --> ) Exit current word execution
|
|
EXECUTE (adr -->) Execute word with compilation adr
|
|
CALL (adr -->) Call Z80 code (terminated with JP IY) (not by RET)
|
|
ABORT (... -->) Quit program, clearing data stack
|
|
QUIT (-->) Quit program, not clearing data stack
|
|
|
|
Word Definition
|
|
: pname ... ; (-->) Define a procedure (terminated by semicolon)
|
|
VARIABLE vname (x -->) Define a variable with initial value x
|
|
CONSTANT cname (x -->) Define a constant with constant value x
|
|
CREATE aname (-->) Define an (empty) array (usually followed by ALLOT)
|
|
ALLOT (n -->) Allocate n bytes at end of newest word (see CREATE)
|
|
vname (--> adr) Get variable adr (eg. "vname @" to get its value)
|
|
aname (--> adr) Get array address
|
|
cname (--> x) Get constant value
|
|
pname (-->) Call a procedure
|
|
IMMEDIATE (-->) Make newest word to execute even in compile mode
|
|
DEFINER word (-->) Start a defining word definition
|
|
DOES> (--> adr) Define the action routine of a defining word
|
|
COMPILER word (n -->) Start a compiling word definition (and ALLOT n)
|
|
RUNS> (--> adr) Defines the action routine of a compiling word
|
|
FIND word (--> adr) Find word compilation address (0 if not found)
|
|
LIST word (-->) List word definition
|
|
EDIT word (-->) Edit word definition (doesn't delete old word)
|
|
FORGET name (-->) Delete <name> as well as ALL newer words
|
|
REDEFINE name (-->) Delete old <name> and replace it by newest word
|
|
|
|
Vocabulary
|
|
VOCABULARY dname (-->) Define a new vocabulary
|
|
dname (-->) Set CONTEXT to the <dname> vocabulary
|
|
FORTH (-->) Set CONTEXT to the FORTH vocabulary
|
|
DEFINITIONS (-->) Set CURRENT vocabulary to CONTEXT
|
|
CONTEXT (--> adr) Get current word search vocabulary address ;3C33h
|
|
CURRENT (--> adr) Get current word definition vocabulary addr ;3C31h
|
|
VLIST (-->) List dictionary to screen (press BREAK to stop it)
|
|
|
|
Compiler
|
|
, (x -->) Compile x into dictionary (ALLOT 2 byte, set to x)
|
|
C, (c -->) Compile c into dictionary (ALLOT 1 byte, set to c)
|
|
LITERAL (x -->) Compile x into edited procedure (preceed by [ x ])
|
|
[ ... ] (... -->) Force ... to be interpreted (even during EDITing)
|
|
|
|
Miscellaneous
|
|
( ...) (-->) Start a comment, terminated by ")"
|
|
HERE (--> adr) Next available dictionary location, ie. [STKBOT]
|
|
PAD (--> adr) Scratch pad area address (2701h aka 9985)
|
|
SLOW (-->) Normal execution. Enable error checks
|
|
FAST (-->) Faster execution. Disable error checks (and BREAK-key
|
|
?)
|
|
BEEP (u1 u2 -->) Play tone, u1=1000000/(8*freq [Hz]), u2=duration [ms]
|
|
IN (adr --> c) Read byte from Z80 input port adr
|
|
OUT (c adr -->) Write byte to Z80 output port adr
|
|
INVIS (-->) Disable copy-up mechanism and OK
|
|
VIS (-->) Enable copy-up mechanism and OK
|
|
LINE (-->) Interpret the input buffer as FORTH
|
|
|
|
Tape Files
|
|
LOAD name (-->) Load vocabulary ;\lists all filenames
|
|
VERIFY name (-->) Verify vocabulary ;/when no name typed
|
|
SAVE name (-->) Save vocabulary
|
|
BLOAD name (adr u -->) Load u bytes to adr ;\use file header value(s)
|
|
BVERIFY name (adr u -->) Verify u bytes from adr ;/when adr=0 or u=0
|
|
BSAVE name (adr u -->) Save u bytes from adr
|
|
filenames are case sensitive, length must be 1-10 characters, may not include
|
|
space characters.
|
|
CAUTION: The filenames are ALWAYS taken from the input buffer - that means one
|
|
cannot specify filenames inside of procedures (unless the procedure 'pokes' the
|
|
filename into the input buffer in VRAM before executing a cassette command).
|
|
|
|
FORTH Error Codes
|
|
-----------------
|
|
|
|
Error Codes
|
|
1 Not enough memory
|
|
2 Data Stack Underflow
|
|
3 BREAK pressed
|
|
4 Compile only word
|
|
5 Structure imbalance
|
|
6 Name size < 1 or > 64
|
|
7 PICK or ROLL operand = 0
|
|
8 Floating point overflow
|
|
9 AT or PLOT to the input buffer
|
|
10 Tape error
|
|
11 REDEFINE or FORGET error
|
|
12 Incomplete definition in dictionary
|
|
13 Word not found or is ROM or is FORTH
|
|
14 Word not Listable
|
|
|
|
|
|
Z80 Local Usage
|
|
---------------
|
|
|
|
CPU and System Clock Overview
|
|
The ZX81 is equipped with a NEC D780C-1 CPU (fully compatible to Zilog Z80
|
|
CPUs, including for undocumented opcodes & flags). The CPU is operated at 3.25
|
|
MHz (generated by a 6.5MHz oscillator with very high tolerance - my ZX81
|
|
appears to be rather ticking at 3.33MHz even though the oscillator DOES have
|
|
the value 6.5 printed onto it) the available CPU time is reduced when the
|
|
display is enabled. The ZX81 produces a /WAIT signal for the duration while a
|
|
NMI is requested, otherwise the CPU runs free of waitstates.
|
|
|
|
Vectors, Registers and Memory Overview
|
|
The INT, NMI, and RST vectors are located in ROM and cannot be changed by
|
|
software. The AF' register (ie. EX AF,AF), the IX register, and IR register
|
|
(interrupt/refresh) are reserved for video and should be normally not used,
|
|
except in FAST mode. Attempting to execute program code stored at addresses
|
|
8000h-FFFFh is interpreted as video data (if the opcodes Bit 6 was set), if so,
|
|
a NOP opcode is forwarded to the CPU.
|
|
|
|
Using Machine Code
|
|
A machine code program is called by using the USR function, for example by
|
|
using the BASIC expression "LET N=USR <startaddress>", startaddress must be a
|
|
decimal number (hex numbers are not supported). If the machine code program
|
|
returns to BASIC, the content of the BC register is used as return value. For
|
|
info about storing binary data/machine code, see Memory chapter.
|
|
|
|
BASIC Interpreter
|
|
-----------------
|
|
|
|
The BASIC Interpreter
|
|
--> BASIC Editor
|
|
--> BASIC Commands
|
|
--> BASIC Functions
|
|
--> BASIC Error Codes
|
|
--> BASIC Programs and Variables (ZX81/Spectrum)
|
|
--> BASIC 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 specifies the duration in
|
|
seconds (or fractions thereof, like 0.5), the 2nd parameter specifies the pitch
|
|
in semitones above middle C (or below thereof, if negative). The waveform is
|
|
software generated, so the program becomes paused during beep.
|
|
|
|
BORDER n (Spectrum only)
|
|
Changes the screen border color (0..7).
|
|
|
|
CLEAR [n]
|
|
Erases all variables and frees up memory. The optional parameter changes RAMTOP
|
|
(supported on Spectrum only).
|
|
|
|
CIRCLE x,y,radius (Spectrum only)
|
|
Draws a circle.
|
|
|
|
CLS
|
|
Clears the screen.
|
|
|
|
CONT (called CONTINUE on ZX80/Spectrum)
|
|
Works much like GOTO, continues the program in the current line, or in the next
|
|
line if program has been halted by STOP.
|
|
|
|
COPY (ZX81/Spectrum only)
|
|
Sends a screen copy to the printer (if connected). Only topmost 32x22
|
|
characters are printed, ie. excluding bottommost 2 lines.
|
|
|
|
DATA item[,item[,item]] (Spectrum only)
|
|
Contains expressions (numbers, variables, or quoted strings) which may be
|
|
loaded into variables via READ command. DATA is just a data definition, not an
|
|
executable command (trying to execute DATA lines acts as REM lines).
|
|
|
|
DEF FN v(v1,v2,etc)=expression (Spectrum only)
|
|
Creates a user defined function. The function name must be a single letter
|
|
expression (like x or a$). For example, "DEF FN s(a)=a*a" would cause "FN s(n)"
|
|
to act identical as "n**2".
|
|
|
|
DELETE [n],[m] (Timex TS2068/TC2068 only)
|
|
Deletes BASIC line numbers n..m. Defaults to from 1st/to last line if n/m are
|
|
omitted. Note: To delete a single line, simply enter its line number and press
|
|
Enter.
|
|
|
|
DIM b(n1,...,nk) or DIM b$(n1,...,nk)
|
|
Defines dimensions for an array. All values (or strings) in the array are reset
|
|
to 0, (or SPACE-filled for strings/characters). The lastmost dimension of a
|
|
character array indicates the string length. For example, DIM A$(x,y,z) could
|
|
be accessed either as three-dimensional character array A$(x,y,z), or as
|
|
two-dimensional string array A$(x,y) with LENGTH=z.
|
|
The ZX80 supports only one-dimensional numeric arrays, ie. no multi-dimensional
|
|
arrays, and no string/character arrays.
|
|
|
|
DRAW x,y[,angle] (Spectrum only)
|
|
Draws a line (from most recent DRAW/PLOT/CIRCLE position) to x,y. The 3rd
|
|
parameter allows to draw curved lines (angle should be below +/-2*PI).
|
|
|
|
FAST (ZX81 only)
|
|
Switches to FAST mode, the CPU focuses on program execution only (approx. 4
|
|
times faster) and the display becomes black until end of program, or until
|
|
switching to SLOW mode. Also, the screen becomes temporarily enabled during
|
|
PAUSE or INPUT periods.
|
|
The ZX80 is always operating in 'FAST' mode.
|
|
|
|
FOR b=x TO y [STEP z]
|
|
Defines the begin and range of a FOR-NEXT loop, the default STEP is +1. The
|
|
ZX80 doesn't support the STEP operand.
|
|
|
|
GOSUB n (called GO SUB on ZX80/Spectrum)
|
|
Saves RETURN address on GOSUB stack, and jumps to the specified line number,
|
|
see GOTO for details.
|
|
|
|
GOTO n (called GO TO on ZX80/Spectrum)
|
|
Jumps to the specified line number. An immediate, a variable and/or other
|
|
expression may be used as line number, such like "GOTO A*10+230".
|
|
|
|
IF x THEN command
|
|
Executes command if x<>0 (eg. if an expression like "A=0" is true). The ZX does
|
|
not understand "THEN n" as alias for "THEN GOTO n".
|
|
|
|
INK/PAPER/FLASH/BRIGHT n (affects VRAM attributes) (Spectrum only)
|
|
INVERSE/OVER n (affects VRAM bitmap) (Spectrum only)
|
|
Changes parameters for following printing/drawing operations (like PRINT,
|
|
INPUT, PLOT, DRAW, CIRCLE).
|
|
INK/PAPER can be a color number in range 0..7, or 8=transparent, FLASH/BRIGHT
|
|
can be 0=off, 1=on, or 8=transparent, transparent means that the old attribute
|
|
value in VRAM is left unchanged. INVERSE/OVER can be 0=off, or 1=on. INVERSE
|
|
inverts the character data when printing, or causes pixels to become 0 when
|
|
drawing. OVER causes the new character/pixel data to be XORed with the old VRAM
|
|
bitmap content.
|
|
INK/PAPER/FLASH/BRIGHT/INVERSE/OVER can be used as "standalone" commands
|
|
(affecting all following printing/drawing commands) (eg. "INVERSE 1"), or as
|
|
"temporary" parameters inserted between a printing/drawing command and its
|
|
parameters (affecting only that command) (eg. "PLOT INVERSE 1;x,y" is
|
|
equivalent to UNPLOT x,y).
|
|
Note: Another way to use colors in printing is to use "hidden" tokens, like
|
|
typing PRINT"Hello {INK RED}Test", where {INK RED} is entered as EXT+SHIFT+2.
|
|
The {INK RED} token isn't displayed in text form when listing/editing the
|
|
program, it just causes the following characters to be drawn in red (this
|
|
method was supported only by the original 48K BASIC, and was discontinued in
|
|
128 BASIC).
|
|
|
|
INPUT ["text",] [LINE] v
|
|
Prompts the user to enter a value (or string) to be assigned to v. In FAST
|
|
mode, the display is temporarily re-enabled. Program is breaked if user enters
|
|
STOP as first character.
|
|
Strings must enclosed in quotes (otherwise any text input is treated as a
|
|
variable). Adding the LINE keyword allows to enter strings without quotes
|
|
(Spectrum only). "text" is an optional message displayed on the screen
|
|
(Spectrum only).
|
|
|
|
LET v=e
|
|
Assigns e to the variable v. The ZX does not understand "v=e" as alias for "LET
|
|
v=e". In case that v is a string-fragment, ie. A$(..TO..), the TO-length
|
|
remains unchanged, and truncated/space padded string is assigned to the
|
|
TO-area.
|
|
|
|
LIST [n]
|
|
Lists the program on the screen. The default starting line number is 0. Use
|
|
CONT to continue if program does not fit onto screen.
|
|
|
|
LLIST [n] (ZX81/Spectrum only)
|
|
Lists the program to the printer.
|
|
|
|
LOAD f
|
|
Loads a memory image from cassette. When specifying an empty filename, ie. LOAD
|
|
"", the first encountered file is loaded. Text display is suspended during
|
|
loading, white lines are shown on the screen when receiving cassette signals.
|
|
The program and all variables that are already in memory become overwritten.
|
|
The memory image contains all memory from 4009h up to (4014h), ie. most of the
|
|
system area, the actual BASIC program, the video memory, and any defined
|
|
variables. The program is automatically started, continuing at the next line
|
|
number, if it has been saved from <inside> of a running program.
|
|
The ZX80 does not support filenames, just type LOAD and hit NEWLINE.
|
|
|
|
LPRINT (ZX81/Spectrum only)
|
|
Works much like PRINT, but outputs to the printer. AT may be used to specify a
|
|
horizontal position inside of the currently printed line.
|
|
Bug: Numbers with more than one zero in their fractional portion aren't
|
|
displayed properly, for example, LPRINT 0.00001 does output "0.0XYZ1" (this bug
|
|
appears only with the ZX81/TS1000 BIOS, it's fixed in the TS1500, Lambda 8300,
|
|
and Spectrum BIOSes).
|
|
|
|
NEW
|
|
Restarts BASIC. The program, all variables, and all further memory up to RAMTOP
|
|
are erased. In the ZX80 this is equivalent to CALL 0.
|
|
|
|
NEXT b
|
|
Adjusts b as specified in the corresponding FOR command, and (if the target
|
|
condition has not been reached or exceeded) loops back to the line following to
|
|
the FOR command. The ZX does not understand "NEXT" as alias for "NEXT b".
|
|
|
|
ON ERR command (Timex TS2068/TC2068 only)
|
|
Defines error handling. command can be combined GOTO, CONT, or RESET.
|
|
|
|
OUT n,m (Spectrum only)
|
|
Writes a byte (m) to the specified 16bit I/O address (n).
|
|
|
|
PAUSE n (ZX81/Spectrum only)
|
|
Pauses the program for n/50 seconds (assuming 50Hz display refresh rate) or
|
|
until the user hits a key, and displays the screen for the duration of this
|
|
period (even if display was disabled by FAST mode). The highest allowed value
|
|
for n is 32767. Note that hitting the BREAK key (SPACE) stops the program
|
|
rather than continuing it. On the Spectrum, PAUSE 0 waits endless (until a key
|
|
is pressed).
|
|
|
|
PLAY string1[,string2[,string3]] (Spectrum 128/+2/+2A/+3 only)
|
|
Plays up to three sounds (on the three PSG sound channels). The strings are
|
|
composed of following characters:
|
|
c-b Play note within current octave (c,d,e,f,g,a,b)
|
|
C-B Play note within next higher octave (C,D,E,F,G,A,B)
|
|
$ Flattens note following it (can be more flattened by $$ or $$$ etc.)
|
|
# Sharpens note following it (can be more sharpened by ## or ### etc.)
|
|
& Play silence (a pause of same length as normal c-b and C-B notes)
|
|
_ Tied notes (eg. "5_7c" = crotchet c and a minim c tied together)
|
|
On Set current octave (0..8)
|
|
Tn Set tempo (60..240)
|
|
n Set length of notes (1..12) (use "Nn" if preceeded by other digits)
|
|
Nn Separates two numbers (eg. octave=1,length=2 --> O1N2, instead of O12)
|
|
Vn Set volume level (0..15) (0=Off, 15=Loudest)
|
|
Wn Set volume envelope type (0..7) (bit0=ATTACK, bit1=HOLD, bit2=REPEAT)
|
|
Xn Set volume envelope frequency (0..65535) (affects all 3 channels)
|
|
U Turn on volume envelope in any string
|
|
( Set loop start (if none specified: default is begin of string)
|
|
) Jump to loop start (repeat 2x, multiple brackets can repeat 4x,8x,16x..)
|
|
)) Jump to loop starts (repeats endless if only ONE loop start was defined)
|
|
! ! Enclose a comment
|
|
H Stop PLAY command (stops all 3 channels, including endless looping ones)
|
|
Mn Configure PSG channels (bit0..2=Tone A..C, bit3..5=Noise A..C)
|
|
Yn Turn on MIDI channel (1..16)
|
|
Zn Send MIDI programming/configuration code (numbers depend on hardware)
|
|
Although the sounds are hardware generated, the program gets paused until the
|
|
PLAY command has finished, which is making the feature rather useless.
|
|
|
|
PLOT x,y (ZX81/Spectrum only)
|
|
ZX81: Draws a black dot (of 4x4 pixels, ie. one quarter of a 8x8 pixel
|
|
character) at the specified position by using graphics characters. Spectrum:
|
|
Draws a single pixel. For both ZX81/Spectrum: The origin (0,0) is at the lower
|
|
left of the screen, excluding the bottom-most two character lines.
|
|
|
|
POKE m,n
|
|
Writes the byte n at address m into memory, both must be decimal values (the ZX
|
|
does not recognize hexadecimal numbers).
|
|
|
|
PRINT ...
|
|
Displays the operand(s) - if any - on the screen. Possible operands are:
|
|
a) nothing
|
|
b) a numeric expression, displayed either as
|
|
normal decimal number (if in range 10^-5 .. 10^13)
|
|
otherwise as nnEmm indicating nn*10^mm
|
|
leading zeroes are displayed only if the first digit after
|
|
the "." is not zero, ie. 0.3 and .03 are displayed as such.
|
|
c) a string. undefined characters are displayed as question marks.
|
|
d) AT y,x; - moves the PRINT position to the specified screen
|
|
location, 0,0 is upper left.
|
|
e) TAB n; - moves the PRINT position to the specified horizontal
|
|
location. If this is to the left of the current location, then
|
|
the vertical position is incremented.
|
|
Operands may be separate by semicolon ";" (next operand displayed directly at
|
|
current position) or comma "," (next operand displayed at next TAB 0 or TAB 16
|
|
position).
|
|
Upon completion, the print position is moved to the begin of the next line
|
|
(unless expression was terminated by semicolon or comma).
|
|
An error may be generated if memory or screen is full, if so, CONT may be used
|
|
to clear the screen and to continue the program.
|
|
|
|
RAND [n] (called RANDOMISE on ZX80, and RANDOMIZE on Spectrum)
|
|
Initializes the random generators seed (n=1..65535). When n is zero (the
|
|
default), the current frame counter is used as seed.
|
|
|
|
READ v1[,v2[,v3]] (Spectrum only)
|
|
Loads expressions from DATA lines into the specified variable(s). See also:
|
|
RESTORE.
|
|
|
|
REM ...
|
|
Defines a remark, ignored by the program. The comment field may be also
|
|
mis-used to define binary machine code inside of a basic program.
|
|
However, the comment may not contain a NEWLINE character (76h) - ie. a HALT
|
|
instruction (opcode 76h) may not be used, as well as any other opcodes with 76h
|
|
as parameter byte, such like JP 4176h, or LD A,76h, etc.
|
|
|
|
RESET (Timex TS2068/TC2068 only)
|
|
Intended to reset connected peripherals. No idea if/which/how any peripherals
|
|
do actually support this command.
|
|
|
|
RESTORE [n] (Spectrum only)
|
|
Sets the first line number where following READ commands start searching for
|
|
DATA statements, the default is the begin of the program.
|
|
|
|
RETURN
|
|
Returns to the line following to the most recently executed GOSUB command.
|
|
|
|
RUN [n]
|
|
Clears all variables and jumps to the specified line number. The default is the
|
|
first line of the program. See GOTO for details.
|
|
|
|
SAVE f
|
|
Saves the system area, the program, the video memory, and any defined variables
|
|
to cassette. The filename f must be a 1-127 characters string, which may not
|
|
include inverted characters. The text display is suspended for the duration of
|
|
saving, white lines are displayed indicating the cassette signals.
|
|
When using SAVE from inside of the program, then the program is automatically
|
|
continued at the following line. Note that the GOSUB stack is not saved, so
|
|
that SAVE should not be used from inside of a sub-routine.
|
|
The ZX80 does not support filenames, just enter SAVE without parameter.
|
|
|
|
SCROLL (ZX81 only)
|
|
Moves the display upwards, and inserts a blank line at the bottom.
|
|
Note: The blank line is totally empty, in VRAM it is defined as a single HALT
|
|
opcode, without any SPACE characters.
|
|
|
|
SLOW (ZX81 only)
|
|
Switches to SLOW mode (approx. 4 times slower than FAST mode). The text screen
|
|
is displayed, and the program is executed during vertical blanking periods
|
|
only. The ZX81 is initially operating in SLOW mode.
|
|
The ZX80 does not support SLOW and FAST commands, and it is always operating in
|
|
FAST mode.
|
|
|
|
SOUND index,data [;index,data] [...] [;index,data] (Timex TS2068/TC2068 only)
|
|
Allows to write one or more values to the PSG sound registers. Unlike the
|
|
PLAY/BEEP commands, it does just start (or stop or change) sounds, but doesn't
|
|
pause program execution.
|
|
|
|
SPECTRUM (Spectrum 128/+2/+2A/+3 only)
|
|
Switches to Spectrum 48K backwards-compatible mode. Disables the new I/O ports,
|
|
disables the Extended System area, re-enables the old color codes like {INK
|
|
RED}, re-enables the hotkey mode like R=RUN, etc. The BASIC program (if any) is
|
|
kept in memory (eg. allows to load 48K program from Spectrum +3 disk drive, and
|
|
then run it in 48K mode).
|
|
|
|
STOP
|
|
Stops the program. User may enter CONT to continue in following line.
|
|
|
|
UNPLOT x,y (ZX81 only)
|
|
Same as PLOT, but drawing a white dot instead of a black dot.
|
|
|
|
Additional commands...
|
|
|
|
FORMAT (Spectrum only)
|
|
FORMAT LINE baudrate ;default=9600
|
|
FORMAT LPRINT target ;"R"=RS232, "C"=Centronics
|
|
FORMAT LPRINT tokenmode ;"E"=Expanded, "U"=Unexpanded tokens
|
|
COPY - normal screen copy to printer
|
|
COPY EXP - expanded screen copy to printer (recurse BRIGHT attributes)
|
|
COPY EXP INVERSE - expanded inverse screen copy to printer
|
|
CAT (Spectrum only)
|
|
MOVE (Spectrum only)
|
|
ERASE (Spectrum only)
|
|
OPEN # (Spectrum only)
|
|
CLOSE # (Spectrum only)
|
|
MERGE (Spectrum only)
|
|
VERIFY (Spectrum only)
|
|
--> Spectrum Disc and Tape Commands
|
|
|
|
BASIC Functions
|
|
---------------
|
|
|
|
Note that all ZX81 and Spectrum 48K functions must be entered in form of SHIFT
|
|
or FUNCTION mode key combinations. For example, type SHIFT+ENTER,B for the
|
|
INKEY$ keyword - attempting to enter I,N,K,E,Y,$ would result in a syntax
|
|
error. The same applies for multi-character operands such like ">=" and "**".
|
|
For the ZX80 and Spectrum 128/+2/+2A/+3 it is vice-versa, and all functions
|
|
must be entered character by character. Also, ZX80 function parameters must be
|
|
put into () brackets.
|
|
|
|
ABS n
|
|
Returns the unsigned value of n.
|
|
|
|
ATTR (y,x) (Spectrum only)
|
|
Returns the characters 8bit color attritbute stored in VRAM attribute area.
|
|
|
|
BIN n (Spectrum only)
|
|
Treats the following digits as binary number (max 16bit).
|
|
|
|
CHR$ n
|
|
Returns character n. (Converts a number into a single-character string.)
|
|
|
|
CODE string
|
|
Returns the character number of the first character (or 0 if string is empty).
|
|
Opposite of CHR$.
|
|
|
|
FN name(n,n,etc) (Spectrum only)
|
|
Executes a user defined function (which can be defined with DEF FN).
|
|
|
|
FREE (Timex TS2068/TC2068 only)
|
|
Returns amount of free memory in bytes.
|
|
|
|
IN n (Spectrum only)
|
|
Returns a byte read from the specified 16bit I/O address.
|
|
|
|
INKEY$ (ZX81/Spectrum only)
|
|
Returns the character of the currently pressed key, or "" if none pressed.
|
|
|
|
LEN string (ZX81/Spectrum only)
|
|
Returns the length of the string.
|
|
|
|
PEEK n
|
|
Returns a byte read from decimal (!) memory address n. The ZX does not
|
|
recognize hexadecimal numbers.
|
|
|
|
POINT (x,y) (Spectrum only)
|
|
Returns the pixel color (0 or 1) stored in VRAM bitmap area.
|
|
|
|
RND (for ZX80: RND n)
|
|
Returns a random number in range 0 to 0.99999... (ZX81/Spectrum), or 1 to n
|
|
(ZX80).
|
|
|
|
SCREEN$ (y,x) (Spectrum only) ;returns character at location x,y
|
|
Returns character that matches the 8x8 pixel cell in VRAM bitmap area.
|
|
|
|
SGN n (ZX81/Spectrum only)
|
|
Returns the sign (-1, 0, or +1) of n.
|
|
|
|
STICK n,m (Timex TS2068/TC2068 only)
|
|
Returns joystick status (via PSG register 14). n=1 returns 1bit button status,
|
|
n=2 returns 4bit direction status. m selects the joystick port (1 or 2).
|
|
|
|
STR$ n
|
|
Returns n converted into a string.
|
|
|
|
TL$ string (-ZX80- only)
|
|
Returns string with leftmost character truncated. Equivalent to the ZX81
|
|
expression 'string(2 TO)'.
|
|
|
|
USR n
|
|
Calls a machine program in memory at address n, and returns the value of the BC
|
|
register when (if) the machine code program returns. The ZX does not recognize
|
|
hexadecimal addresses.
|
|
|
|
VAL string (ZX81/Spectrum only)
|
|
Converts the string into a value, stops the program if failed.
|
|
|
|
VAL$ string (Spectrum only)
|
|
This is a subfunction of the VAL function, it removes bounding quotes from the
|
|
string, but without actually doing a string-to-value conversion. No idea if
|
|
it's useful for anything.
|
|
|
|
Floating Point related functions (ZX81/Spectrum only)
|
|
ACS n Arcus Cosinus.
|
|
ASN n Arcus Sinus.
|
|
ATN n Arcus Tangens.
|
|
COS n Cosinus.
|
|
EXP n Exponent e^n.
|
|
INT n Returns an integer value (rounded DOWN).
|
|
LN n Logarhytmn of n (base e).
|
|
PI 3.14159265...
|
|
SIN n Sinus.
|
|
SQR n Square root.
|
|
TAN n Tangens.
|
|
|
|
Numeric operations
|
|
Op. Prio. Expl.
|
|
a+b 6 Addition
|
|
a-b 6 Subtraction
|
|
a*b 8 Multiplication
|
|
a/b 8 Division
|
|
-a 9 Invert sign
|
|
a**b 10 a^b
|
|
Logical operations (Returns 1 if true, 0 if false)
|
|
Op. Prio. Expl.
|
|
a=b 5 Equal
|
|
a>b 5 Greater than
|
|
a<b 5 Less than
|
|
a<=b 5 Less or equal
|
|
a>=b 5 Greater or equal
|
|
a<>b 5 Not equal
|
|
Special Numeric/Logical operations
|
|
Op. Prio. Expl.
|
|
a OR b 2 b<>0: Returns 1; b=0: Returns a.
|
|
a[$] AND b 3 b<>0: Returns a (or a$); b=0: Returns 0 (or "").
|
|
NOT b 4 b<>0: Returns 0; b=0: Returns 1.
|
|
Priority for indexing (DIM) and string-fragments (TO) is 12. Priority for all
|
|
functions is 12.
|
|
|
|
String ( [first] TO [last] ) Operand
|
|
Used to specify a fragement of a string from first character to last character.
|
|
The default values are: first=1, and last=LEN.
|
|
May be used either in source and destination of string operations, eg.:
|
|
LET A$(5 TO 7) = "***" ;overwrites 5th-7th character of A$
|
|
LET A$ = B$(TO 4) ;copies 1st-4th character of B$ to A$
|
|
|
|
BASIC Error Codes
|
|
-----------------
|
|
|
|
Commandline Errors
|
|
When entering a line incorrectly, the [S] symbol (Syntax Error) is displayed at
|
|
the fault location, prompting the user to correct the problem.
|
|
|
|
ZX81 Execution Errors
|
|
Otherwise, when errors occur during program execution, the following error
|
|
codes are displayed.
|
|
0 No Error, program terminated succesfully.
|
|
1 Encountered NEXT without FOR.
|
|
2 Undefined Variable.
|
|
3 DIM Index out of range. May also return error B if 16bit exceeded.
|
|
4 Memory full.
|
|
5 Screen full. Type CONT to continue with cleared screen.
|
|
6 Arithmetic Overflow, a value is greater than 10^38.
|
|
7 Encountered RETURN without GOSUB.
|
|
8 Attempted to use INPUT as command (without line number).
|
|
9 Program halted by STOP command, may continue by CONT.
|
|
A Function with bad argument.
|
|
B Integer out of range.
|
|
C Failed VAL function.
|
|
D Program aborted by BREAK (SPACE KEY), or entered STOP at begin of INPUT.
|
|
E Not used.
|
|
F Attempted to SAVE a file with empty "" name.
|
|
Errors are always displayed as ERR/LINE indicating the line number which caused
|
|
the error.
|
|
|
|
ZX80 Execution Errors
|
|
0 program completed (or breaked), no error
|
|
1 NEXT without FOR
|
|
2 variable not defined
|
|
3 dimension out of range (DIM)
|
|
4 memory or gosub stack full
|
|
5 (???)
|
|
6 integer overflow (value exceeds -32768..+32767)
|
|
7 RETURN without GOSUB
|
|
8 attempted INPUT but program isn't running
|
|
9 STOP command
|
|
|
|
BASIC Programs and Variables (ZX81/Spectrum)
|
|
--------------------------------------------
|
|
|
|
BASIC Program Line Structure
|
|
Bytes Expl.
|
|
2 Line Number (MSB,LSB) (!)
|
|
2 Line Length (LSB,MSB)
|
|
LEN-1 Text
|
|
1 Newline (ZX81=76h) (Spectrum=0Dh)
|
|
The following are used in the Text area: 00h-3Fh and 80h-BFh for normal and
|
|
inverted characters, C0h-FFh and 40h-42h for keywords, 7Eh for values, and 76h
|
|
indicates the end of the line. On the Spectrum, characters are in ASCII,
|
|
keywords are different, values are 0Eh, and end of line is 0Dh.
|
|
Values are duplicated in program lines: First, as normal text, ie. as entered
|
|
by the user (this field is ignored during execution, still it must exist, but
|
|
might be always set to "0" if desired). And second, invented by the code 7Eh,
|
|
as pre-calculated 5-byte FLOAT number.
|
|
An immediate thus occupies at least 7 bytes. However, there are some grindy
|
|
methods to save memory, such like: PI-PI defines 0 in only 3 bytes, VAL "9"
|
|
defines 9 in only 4 bytes, etc.
|
|
|
|
BASIC One-Letter Variables
|
|
Bytes Expl.
|
|
1 60h + Letter (5bit)
|
|
5 Floating point number (exponent/value)
|
|
|
|
BASIC Multi-Character Variables
|
|
Bytes Expl.
|
|
1 A0h + First Letter (5bit)
|
|
NN 00h + Further Characters (6bit)
|
|
1 80h + Last Character (6bit)
|
|
5 Floating point number (exponent/value)
|
|
|
|
BASIC Numeric Array
|
|
Bytes Expl.
|
|
1 80h + Letter (5bit)
|
|
2 Total Length of all following data
|
|
1 Number of Dimensions
|
|
D*2 Range of each of the Dimension(s)
|
|
N*5 Values
|
|
|
|
BASIC FOR-NEXT Counter
|
|
Bytes Expl.
|
|
1 E0h + Letter (5bit)
|
|
5 Current Value (float)
|
|
5 Target Value (float)
|
|
5 Step
|
|
2 Loop Linenumber (MSB,LSB) (!)
|
|
|
|
BASIC String
|
|
Bytes Expl.
|
|
1 40h + Letter (5bit)
|
|
2 String Length (0 if empty)
|
|
LEN Character String (none if empty)
|
|
|
|
BASIC Character Array
|
|
Bytes Expl.
|
|
1 C0h + Letter (5bit)
|
|
2 Total Length of all following data
|
|
1 Number of Dimensions
|
|
D*2 Range of each of the Dimension(s)
|
|
N*1 Characters
|
|
|
|
5-byte FLOAT numbers
|
|
1 Exponent 81h +/- location of most significant bit
|
|
4 Sign-Bit and Value excluding most significant bit
|
|
For example, the value 7FFFh would be defined as such: In this case the MSB is
|
|
Bit 14 (ie. 4000h) the exponent byte must be set to 14+81h (=8Fh). The sign bit
|
|
is zero (Bit 7 of first byte), and the remaining bits, in this case Bit 13-0
|
|
(3FFFh), are shifted to the left as much as possible (so that highest bit is
|
|
located in Bit 6 of first byte) the four bytes must be: 7F FE 00 00.
|
|
|
|
5-byte NON-FLOAT numbers with Exponent=00h (Spectrum only / not ZX81)
|
|
1 Exponent 00h (indicates that it is a non-float value)
|
|
1 Sign (00h=Positive, FFh=Negative)
|
|
2 Integer (0000h..FFFFh) (or -0001h..-FFFFh when negative)
|
|
1 Unused (00h)
|
|
BUG: In some cases (not sure when?), -10000h is also stored as non-float, and,
|
|
in some further cases (not sure when?) that causes problems.
|
|
|
|
5-byte FLOAT bug
|
|
There's some inaccuracy when converting text strings (eg. user input) to float
|
|
numbers. For example, the correct value for 0.25 would be 7F 00 00 00 00,
|
|
however, the ZX81/TS1000 BIOSes do convert it to 7E 7F FF FF FF (accidently
|
|
rounded down), the TS1500 BIOS does unsuccessfully try to fix that problem by
|
|
converting it to 7F 00 00 00 01 (accidently rounded up). This is resulting in
|
|
incompatibility, for example,
|
|
10 FOR I = 0 TO 1 STEP .25
|
|
20 PRINT I
|
|
30 NEXT I
|
|
The ZX81/TS1000 does correctly stop at 1 being displayed as last number, whilst
|
|
the "improved" TS1500 does incorrectly stop at 0.75. Mind that immediates are
|
|
pre-compiled at time of entering the program code, so a program SAVEd on a
|
|
ZX81, may work exactly as on the ZX81 even when LOADing it on a TS1500 (unless
|
|
it contains conversions being done at runtime, like VAL ".25" or VAL A$).
|
|
1 IF VAL"0.25" < 1/4 THEN PRINT "TOO SMALL (ZX81 OR TS1000 OR SPECTRUM)"
|
|
2 IF VAL"0.25" > 1/4 THEN PRINT "TOO BIG (TS1500 OR LAMBDA)"
|
|
3 IF VAL"0.25" = 1/4 THEN PRINT "MATCH (WHOOPS)"
|
|
Typing IF VAL"0.25" forces conversion on runtime (typing IF 0.25 would be
|
|
converted when entering the program, and stay so even when SAVing it and
|
|
LOADing it on another computer). Interestingly, the TOO SMALL variants, do also
|
|
(incorrectly) display a MATCH in line 3.
|
|
|
|
|
|
BASIC Programs and Variables (ZX80)
|
|
-----------------------------------
|
|
|
|
BASIC Program Line Structure
|
|
Bytes Expl.
|
|
2 Line Number (MSB,LSB) (!)
|
|
... Text
|
|
1 Newline (76h)
|
|
The following are used in the Text area: 00-3F and 80-BF for normal and
|
|
inverted characters, D4-FF for keywords, and 76 indicates the end of the line.
|
|
A couple of 'special' characters such like ';()*+/-' are stored in form as
|
|
keywords rather than as normal character codes.
|
|
Function names and values in program lines are stored as normal text.
|
|
|
|
BASIC One-Letter Variables
|
|
Bytes Expl.
|
|
1 60h + Letter (5bit)
|
|
2 Signed Integer
|
|
|
|
BASIC Multi-Character Variables
|
|
Bytes Expl.
|
|
1 40h + First Letter (5bit)
|
|
NN 00h + Further Characters (6bit)
|
|
1 80h + Last Character (6bit)
|
|
2 Signed Integer
|
|
|
|
BASIC Numeric Array
|
|
Bytes Expl.
|
|
1 A0h + Letter (5bit)
|
|
1 Range (Counted from 0 to N)
|
|
(N+1)*2 Signed Integers
|
|
|
|
BASIC FOR-NEXT Counter
|
|
Bytes Expl.
|
|
1 E0h + Letter (5bit)
|
|
2 Current Value
|
|
2 Target Value
|
|
2 Loop Linenumber (normal LSB,MSB for ZX80)
|
|
|
|
BASIC String
|
|
Bytes Expl.
|
|
1 80h + Letter (5bit)
|
|
... Character String (none if empty)
|
|
1 Ending Quotes (01h)
|
|
|
|
BASIC Character/String Arrays
|
|
None such - ZX80 supports numeric arrays only.
|