This section is broken into several parts: Channels & Streams, Hardware, ZX Interface I and Tape Data Structure. Each of these may have several sub-sections. Within each section, you may find links to additional information elsewhere in this FAQ, or to other reference documents. Commented ROM listings are available from Geoff Wearmouth, author of the SEA Change ROM.
Channels & Streams:
There are 5 subsections:
Introduction,
Opening and Closing,
Device Independence,
More Stream Commands and
Memory Formats.
offset len description 0 2 0x0008 (address of Spectrum error routine) 2 2 0x0008 (ditto) 4 1 A character describing the channel 5 2 Address of output routine in the shadow ROM 7 2 Address of input routine in the shadow ROM 9 2 Total length of channel information 11 * Any other data needed by the channelThe first two words being 8 denotes that the input and output routines are to be found in the shadow ROM. Either of them could be an ordinary number instead, in which case the shadow ROM will not be paged in and the word at offset 5 or 7 (as appropriate) could contain any data.
LD HL,(PROG) ; A new channel starts below PROG DEC HL ; LD BC,0x0005 ; Make space CALL 0x1655 ; INC HL ; HL points to 1st byte of new channel data LD A,0xfd ; LSB of output routine LD (HL),A ; INC HL ; PUSH HL ; Save address of 2nd byte of new channel data LD A,0xfd ; MSB of output routine LD (HL),A ; INC HL ; LD A,0xc4 ; LSB of input routine LD (HL),A ; INC HL ; LD A,0x15 ; MSB of input routine LD (HL),A ; INC HL ; LD A,0x55 ; Channel name 'U' LD (HL),A ; POP HL ; Get address of 2nd byte of output routine LD DE,(CHANS) ; Calculate the offset to the channel data AND A ; and store it in DE SBC HL,DE ; EX DE,HL ; LD HL,'STRMS' ; LD A,0x04 ; Stream to open, in this case #4. ADD A,0x03 ; Calculate the offset and store it in HL ADD A,A ; LD B,0x00 ; LD C,A ; ADD HL,BC ; LD (HL),E ; LSB of 2nd byte of new channel data INC HL ; LD (HL),D ; MSB of 2nd byte of new channel data RETThis routine will create a channel "U" (any ASCII character from 0 to 255 will be accepted by the standard ROM since it ignores this information). This channel has an output routine at 65021 and an input routine at 5572 (generates error report 'J'). A new entry is created in the STRMS table which points to the address of the second byte of new channel data. The stream number can be from -3 to 15, but it is best to stick to the range 4 to 15 and not modify the system streams (-3 to -1) or the standard streams (0 to 3).
Hardware:
At the hardware level, the Spectrum is a very simple machine. There's the 16K ROM which occupies the lowest part of the address space, and
48K of RAM which fills up the rest. An ULA which reads the lowest 6912 bytes of RAM to display
the screen, and contains the logic for just one I/O port completes the machine, from a software point of view at least.
There are 4 subsections available:
Port 0xfe,
48K Spectrum,
Contended Memory and
Contended Input/Output. Within each section, you may find links to additional information elsewhere in this FAQ, or to
reference documents located elsewhere.
Bit 7 6 5 4 3 2 1 0 +-------------------------------+ | | | | E | M | Border | +-------------------------------+
IN: Reads keys (bit 0 to bit 4 inclusive) 0xfefe SHIFT, Z, X, C, V 0xeffe 0, 9, 8, 7, 6 0xfdfe A, S, D, F, G 0xdffe P, O, I, U, Y 0xfbfe Q, W, E, R, T 0xbffe ENTER, L, K, J, H 0xf7fe 1, 2, 3, 4, 5 0x7ffe SPACE, SYM SHFT, M, N, B
10 OUT 254,BIN 11101111 20 PRINT IN 254 30 OUT 254,BIN 11111111 40 PRINT IN 254 50 GOTO 10For a correct test do not press any key while running, and have no EAR input.
Value output to bit: 4 3 | Iss 2 Iss 3 Iss 2 V Iss 3 V 1 1 | 1 1 3.79 3.70 1 0 | 1 1 3.66 3.56 0 1 | 1 0 0.73 0.66 0 0 | 0 0 0.39 0.34Iss 2 is value of bit 6 read by IN 254 after the appropriate OUT from an Issue 2, and Iss 3 is same for an Issue 3. Iss 2 V and Iss 3 V are voltage levels on pin 28 of the ULA chip after the OUT, with no input signal on the EAR socket.
ORG 45000 LD A,0x18 OR 0xf8 OUT (254),A LD A,0x08 OR 0xe8 OUT (254),A TIMING LD B,7 ;crucial value DL LD IX,0 DJNZ DL IN A,(254) ;query stateIn this case IN A,(254), or output of this value sometimes gives 255 and sometimes 191. If you make the constant in the TIMING line smaller then result will be always 255, if delay is longer then result will be always 191. Of course, the effect occurs only for Issue 3 machines.
ORG 50000 HALT ;synchronize with interrupts LD A,0x18 OUT (254),A HALT ;wait 20ms LD A,0x08 OUT (254),A LD B,107 ;crucial value DL LD IX,0 DJNZ DL IN A,(254)As you can see, after a longer high level duration, the delay is also much longer. The delay varies from approximately 180 T states (about 50 microsec) to 2800 T states (about 800 microsec), depending from duration of high level on port 254. The explanation for this delay is that there are capacitors connected between pin 28 of the ULA and the EAR and MIC connectors, but note that there is no delay when bit 4 changes from 0 to 1.
Cycle # Delay ------- ----- 14335 6 (until 14341) 14336 5 ( " " ) 14337 4 ( " " ) 14338 3 ( " " ) 14339 2 ( " " ) 14340 1 ( " " ) 14341 No delay 14342 No delay 14343 6 (until 14349) 14344 5 ( " " ) 14345 4 ( " " ) 14346 3 ( " " ) 14347 2 ( " " ) 14348 1 ( " " ) 14349 No delay 14350 No delayetc., until the cycle 14463 (always relative to the start of the interrupt), in which the electron beam reaches the border again for 96 more cycles. At cycle 14559 the same situation repeats. This is valid for all 192 lines of screen data. While the ULA is updating the border the delay does not happen at any time.
If 16384<=PC<=32767 then (Insert the delay corresponding to the current cycle, relative to the start of the frame) (according to the above table) (end if) Delay for 4 cycles (time after 'pc:'). If 16384<=HL<=32767 then (Insert the delay corresponding to the current cycle...) (end if) Store A into (HL) Delay for 3 cycles (time taken to store A)Example 1: if PC = 25000 and HL = 26000 and the instruction at address 25000 is LD (HL),A and we're in cycle 14335:
Instruction Breakdown ----------- --------- NOP pc:4 LD r,r' alo A,r INC/DEC r EXX EX AF,AF' EX DE,HL DAA CPL CCF SCF DI EI RLA RRA RLCA RRCA JP (HL) NOPD pc:4,pc+1:4 sro r BIT b,r SET b,r RES b,r NEG IM 0/1/2 LD A,I pc:4,pc+1:5 LD A,R LD I,A LD R,A INC/DEC dd pc:6 LD SP,HL ADD HL,dd pc:11 ADC HL,dd pc:4,pc+1:11 SBC HL,dd LD r,n pc:4,pc+1:3 alo A,n LD r,(ss) pc:4,ss:3 LD (ss),r alo A,(HL) pc:4,hl:3 LD r,(ii+n) pc:4,pc+1:4,pc+2:3,pc+2:1 x 5,ii+n:3 LD (ii+n),r alo A,(ii+n) BIT b,(HL) pc:4,pc+1:4,hl:3,hl:1 BIT b,(ii+n) pc+1:4,pc+2:3,pc+3:3,pc+3:1 x 2,ii+n:3,ii+n:1 LD dd,nn pc:4,pc+1:3,pc+2:3 JP nn JP cc,nn LD (HL),n pc:4,pc+1:3,hl:3 LD (ii+n),n pc:4,pc+1:4,pc+2:3,pc+3:3,pc+3:1 x 2,ii+n:3 LD A,(nn) pc:4,pc+1:3,pc+2:3,nn:3 LD (nn),A The following entry applies to the unprefixed version of these opcodes (22 and 2A) LD HL,(nn) pc:4,pc+1:3,pc+2:3,nn:3,nn+1:3 LD (nn),HL The following entry applies to the prefixed version of these opcodes (ED43, ED4B, ED53, ED5B, ED63, ED6B, ED73 and ED7B) LD dd,(nn) pc:4,pc+1:4,pc+2:3,pc+3:3,nn:3,nn+1:3 LD (nn),dd INC/DEC (HL) pc:4,hl:3,hl:1,hl(write):3 SET b,(HL) pc:4,pc+1:4,hl:3,hl:1,hl(write):3 RES b,(HL) sro (HL) INC/DEC (ii+n) pc:4,pc+1:4,pc+2:3,pc+2:1 x 5,ii+n:3,ii+n:1,ii+n(write):3 SET b,(ii+n) pc:4,pc+1:4,pc+2:3,pc+3:3,pc+3:1 x 2,ii+n:3,ii+n:1,ii+n(write):3 RES b,(ii+n) sro (ii+n) POP dd pc:4,sp:3,sp+1:3 RET RETI pc:4,pc+1:4,sp:3,sp+1:3 RETN RET cc pc:5,[sp:3,sp+1:3] PUSH dd pc:5,sp-1:3,sp-2:3 RST n CALL nn pc:4,pc+1:3,pc+2:3,[pc+2:1,sp-1:3,sp-2:3] CALL cc,nn JR n pc:4,pc+1:3,[pc+1:1 x 5] JR cc,n DJNZ n pc:5,pc+1:3,[pc+1:1 x 5] RLD pc:4,pc+1:4,hl:3,hl:1 x 4,hl(write):3 RRD IN A,(n) pc:4,pc+1:3,IO OUT (n),A IN r,(C) pc:4,pc+1:4,IO OUT (C),r EX (SP),HL pc:4,sp:3,sp+1:4,sp(write):3,sp+1(write):3,sp+1(write):1 x 2 LDI/LDIR pc:4,pc+1:4,hl:3,de:3,de:1 x 2,[de:1 x 5] LDD/LDDR CPI/CPIR pc:4,pc+1:4,hl:3,hl:1 x 5,[hl:1 x 5] CPD/CPDR INI/INIR pc:4,pc+1:5,IO,hl:3,[hl:1 x 5] IND/INDR OUTI/OTIR pc:4,pc+1:5,hl:3,IO,[hl:1 x 5] OUTD/OTDRThe above information is correct for the 48K ZX Spectrum - for the 128k/+2 models the contention sequence starts at cycle 14361.
High byte | | in 40 - 7F? | Low bit | Contention pattern ------------+---------+------------------- No | Reset | N:1, C:3 No | Set | N:4 Yes | Reset | C:1, C:3 Yes | Set | C:1, C:1, C:1, C:1The 'Contention pattern' column should be interpreted from left to right. An "N:n" entry means that no delay is applied at this cycle, and the Z80 continues uninterrupted for 'n' T states. A "C:n" entry means that the ULA halts the Z80; the delay is exactly the same as would occur for a contended memory access at this cycle (eg 6 T states at cycle 14335, 5 at 14336, etc on the 48K machine). After this delay, the Z80 then continues for 'n' cycles.
ZX Interface I:
The ZX Interface I uses three different I/O ports, and contains logic to page and unpage an 8K ROM if new commands are used.
The ROM is paged if the processor executes the instruction at ROM address 0x0008 or 0x1708, the error and close# routines.
It is inactivated when the Z80 executes the RET at address 0x0700.
Geoff Wearmouth provides complete assembly listings of version 1
and 2 (used after serial number 87315) of the ZX Interface I ROM at his web site.
You may find these helpful while reading this section.
There are 3 subsections available:
Port 0xe7,
Port 0xef and
Port 0xf7.
Bit 7 6 5 4 3 2 1 0 +---------------------------------------+ READ| | | |busy| dtr |gap| sync|write| | | | | | | | |prot.| |---+---+----+----+-----+---+-----+-----| WRITE| | |wait| cts|erase|r/w|comms|comms| | | | | | | | clk | data| +---------------------------------------+
Bit 7 6 5 4 3 2 1 0 +------------------------------------------+ READ|txdata| | | | | | | net | | | | | | | | | input | |------+---+---+---+---+---+---+-----------| WRITE| | | | | | | |net output/| | | | | | | | | rxdata | +------------------------------------------+
Tape Data Structure:
The SAVE command produces two blocks on tape: a 19 byte header block
and a variable length data block.
Each block has the following structure:
Notes:
Within each block, the data has the following structure:
The structure of the 17 byte tape header is as follows.
Byte Length Description --------------------------- 0 1 Type (0,1,2 or 3) 1 10 Filename (padded with blanks) 11 2 Length of data block 13 2 Parameter 1 15 2 Parameter 2
These 17 bytes are prefixed by the flag byte (0x00) and suffixed by the checksum byte to produce the 19 byte block seen on tape. The type is 0,1,2 or 3 for a PROGRAM, Number array, Character array or CODE file. A SCREEN$ file is regarded as a CODE file with start address 16384 and length 6912 decimal. If the file is a PROGRAM file, parameter 1 holds the autostart line number (or a number>=32768 if no LINE parameter was given) and parameter 2 holds the start of the variable area relative to the start of the program. If it's a CODE file, parameter 1 holds the start of the code block when saved, and parameter 2 holds 32768. For data files finally, the byte at position 14 decimal holds the variable name.
For example, SAVE "ROM" CODE 0,2 will produce the following data on tape (the vertical bar denotes the break between blocks):
00 03 52 4f 4d 7x20 02 00 00 00 00 80 f1 | ff f3 af a3 ^^ ................ flag byte ^^ ............. first byte of header, indicating a code block ^^^^^^^^^^^^^ file name header info ........^^^^^^^^^^^^^^^^^ checksum of header ...................^^ flag byte .................................^^ first two bytes of rom .......................^^^^^ checksum ...........................................^^