BUGS IN THE ROM

Some of the Spectrum's "undocumented features"

hbar

The Spectrum, as you may well know, is a machine of very many bugs. Some of these bugs crop up only in BASIC, some occur only in the use of machine code, while others are manifest all the time. Though the ROM (or ROMs, as there is more than one type of Spectrum) cannot be written to, and therefore the bugs cannot in general be cured, knowledge of their existence can certainly help us to avoid them, or get round them in some way.

This article is therefore a compilation of all the bugs that I know of which occur in the 16K and 48K Spectrums, the 128 and 128+2, and also the ZX Interface One which runs the microdrives.

It is almost impossible to classify bugs in any sensible manner. What I have done is to group them into fairly large and ambiguous clumps such as "PRINT errors", "CALCULATOR errors", and so forth. Where possible credit has been given, but no doubt other people will have made simultaneous discovery of these bugs - this is always the way.

I shall start off with three bugs which I couldn't fit into any category at all.

hbar

MISCELLANEOUS ERRORS

hbar

The CLOSE # Bug
(from Understanding Your Spectrum, by Martin Wren-Hilton)

The CLOSE # bug is present on all Spectrums unless a ZX Interface One is attached. If you attempt to close a stream which has not previously been opened by using the BASIC CLOSE statement then the system will almost invariably crash. More often than not causing a system reset. The presence of the ZX Interface One cures this bug by transferring control to its own ROM (the Shadow ROM) whenever the program counter reaches address 1708. The bug is caused by the table in the 48K ROM at address 1716 not being terminated by a 00 byte. It is interesting to note that Sinclair could have cured this bug in the Spectrum 128 - after all, they did make a few other alterations to the ROM - but alas they chose to leave the bug in place despite its serious consequences.

Neon Bar

The PLOT bug
(from ZX Computing Monthly - Toni Baker)

The BASIC PLOT statement suffers from the fact that it will accept negative co-ordinates. In fact the statement PLOT X, Y really turns out to mean PLOT ABS (X), ABS (Y). This is caused by a failure to test the D and E registers on return from the CALL_STK_TO_BC instruction at address 22DC.

Neon Bar

The SCREEN ONE bug
(from ZX Computing Monthly - Toni Baker)

The Spectrum 128 offers a choice of two different areas of memory which may be used to hold the television picture. These are called SCREEN ZERO (the normal one, at address 4000) and SCREEN ONE (the alternative, at address 7C00). The instruction POKE 23388, 24 will activate screen one, whereas POKE 23388, 16 will activate screen zero. The bug occurs in the rare circumstances of the silicon disc area becoming full (in which case files may collide with the screen) or if more than 217 files, however small, are SAVE!d (in which case the catalogue collides with the screen. The bug is caused by the complete failure of the RAMdisc system to recognise the existence of screen one. The following BASIC program demonstrates this bug and is fun to watch.

10 POKE 23388, 24: REM activate screen one
20 FOR I = 1 TO 562
30 SAVE! "F" + STR$ I CODE 0, 1
40 NEXT I
50 PAUSE 0
60 POKE 23388, 16: REM activate screen zero

hbar

PRINT ERRORS

hbar

The CHR$ 9 error
(from Understanding Your Spectrum, by Dr. Ian Logan)

CHR$ 9 is supposed to print as "forwardspace" (the opposite of backspace). In other words the effect of PRINT CHR$ 9 is supposed to be that the print position is moved rightward by one character square without altering the contents of the screen. Sadly, this does not work. Not only does the print position not move at all, but the character at the current print position is accidentally recoloured with the current colours. The first of these faults is due to the fact that the cursor right subroutine at address 0A3D ends with RET, instead of with JP 0ADC, PO_STORE, however the second fault is due to sloppy thinking as the system variable MASK_T should have been assigned with FF and then restored.

Neon Bar

The CHR$ 8 error
(from Understanding Your Spectrum, by Dr. Frank O'Hara)

CHR$ 8 prints as "backspace" - that is - when printed it will move the print position leftward by one character square. However - if the current print position is AT 1, 0; then backspace will not work. Furthermore, it is possible to backspace from position AT 0, 0; (which should not be possible) and this can produce some interesting results. The bug is caused by the cursor-left subroutine at address 0A23 testing for line one instead of line zero. The byte at address 0A33 should be 19h instead of 18h.

Neon Bar

The STR$ error
(from Understanding Your Spectrum, by Tony Stratton)

This is a bug which manifests itself in both BASIC and machine code. In BASIC the statement PRINT "BUG"+STR$ 0. 5 will simply print "0.5". In machine code the bug manifests itself in the PRINT_FP subroutine at address 2DE3, whose purpose is to print the floating point number at the top of the calculator stack to the current channel. This subroutine is called by the STR$ routine and in this way the bug also appears in BASIC. The bug occurs whenever the number at the top of the calculator stack (or the argument of STR$) lies between -1 and +1 exclusive (excluding zero). In such a case an erroneous zero is left at the top of the calculator stack, and it is this which causes all the problems. In BASIC the bug can be avoided by using temporary variables - e.g. LET A$=STR$ 0.5: PRINT "BUG"+A$ will work. In machine code it is advisable to use the following subroutine in place of PRINT_FP, as this takes the bug into account.

     2A655C
 
PRINT_FP_OK
 
LD HL, (STKEND)
 
:HL points to end of calculator stack.
     225F5C
LD (X_PTR), HL
Store in system variable.
     CDE32D
CALL 2DE3, PRINT_FP
Print the floating point number.
     2A5F5C
LD HL, (X_PTR)
:HL points to end of calculator stack +5.
     11FBFF
LD DE, FFFE
:DE = -5.
     19
ADD HL, DE
:HL points to end of calculator stack.
     22655C
LD (STKEND), HL
Restore (STKEND) to its correct value.
     FD362600
LD (X_PTR) hi, 00
Cancel error pointer.
     C9
RET
Return.

Neon Bar

The COLOUR COMMANDS error
(from Master Your ZX Microdrive, by Andrew Pennell)

If any channel other than the screen or the keyboard is selected as the current channel (i.e. if the last thing PRINTed was to a channel other than "K" or "S") then the permanent colour commands will erroneously transmit the colour control codes to the last channel used. The bug is caused by the failure to select channel "S" at the start of the subroutine CO_TEMP_1 at address 21E1. It is possible to get round the problem by preceding each permanent colour command by a PRINT statement (e.g. PRINT;: INK 4).

Neon Bar

The COLOUR CONTROLS error
(from ZX Computing Monthly - Toni Baker)

If any non-standard channel (e.g. a user-defined channel) is selected as the current channel then the colour statements such as PAPER 4 (etc.) will produce report C; Nonsense in BASIC if the channel output subroutine returns with the carry flag set. This bug is only visible in machine code. To cure the problem it is necessary to ensure that all channel output routines return with the carry reset, at least for control codes 10h to 15h and their second parameter.

Neon Bar

The RS232 COLOUR COMMANDS error
(from ZX Computing Monthly - Toni Baker)

This is for users of 128K machines only. On both the Spectrum 128 and the Plus2 the command LPRINT INK 4 will produce error report C; Nonsense in BASIC. There are two reasons for this. Firstly, the new channel "P" (the built in RS232 socket) erroneously expects the colour controls to be followed by two parameters instead of just one, and secondly the ROM routine sets the carry flag (oops! see previous error). Sinclair may like to know that the byte at 086D (128) or 088C (128+2) should be 01 instead of 02, and, further, that the byte at 087C (128) or 089B (128+2) which currently reads CCF should be replaced by two bytes SCF/CCF.

hbar

CALCULATOR ERRORS

hbar

The DIVISION error
(from Understanding Your Spectrum, by Dr. Frank O'Hara)

The BASIC statement IF 1/2<>0. 5 THEN PRINT "BUG" is sufficient to show that there is a bug somewhere in the works. The bug is in the division routine, which fails to register the thirty-fourth bit of a division. The JR displacement at address 3200 directs control to the label DIV_START instead of DIV_34TH. This means that numbers may not be correctly rounded up. You can avoid any major problems by using IF ABS (X-Y<2. 15E+9) instead of IF X=Y.

Neon Bar

The -65536 error
(from Understanding Your Spectrum, by Dr. Ian Logan)

The ROM is inconsistent about the calculator five-byte form of the number -65536. Some parts of the ROM assume that only numbers in the range -65535 to +65535 may be treated as integers, whereas other parts of the ROM allow an integer from -65536 (as opposed to a full loading point form). This error can be demonstrated by the now famous statement PRINT INT -65536 which gives -1.

Neon Bar

The SCREEN$ error
(from Understanding Your Spectrum, by Stephen Kelly and others.)

The BASIC routine for calculating SCREEN$ accidentally leaves a duplicate entry of the string result at the top of the calculator stack. This means that the BASIC statement IF "X"=SCREEN$ (0,0) THEN PRINT "BUG" will invariably print "BUG" no matter what happens to be on the screen at the time. The bug is fortunately not present in machine code, and calling the subroutine S_SCRN$_S will evaluate SCREEN$ correctly, leaving the stack correct. As with the STR$ error the best way to avoid it in BASIC is to use temporary variables, e.g.

LET A$=SCREEN$ (0,0) : IF "X"=A$ THE PRINT "BUG" will work correctly.

Neon Bar

The MOD. DIV error
(from ZX Computing Monthly - Toni Baker)

Calculate code 32 (initiated by RST 28) is supposed to remove two items from the calculator stack - X and Y, say, and replace them by the quantities X MOD Y, X DIV Y in that order. [Note: X MOD Y means X - Y * INT (X/Y), whereas X DIV Y means INT (X/Y) ]. Unfortunately, it fails to take into account the fact that the INT subroutine corrupts calculator memory zero whenever its argument is negative. This means that the quantity X MOD Y will be incorrect whenever X/Y is negative. The bug could have been cured had Sinclair ensured that the MOD. DIV subroutine at address 36A0 utilised memory one instead of memory zero.

Neon Bar

The E-TO-FP error
(from ZX Computing Monthly - Toni Baker)

Calculator code 3C (initiated by RST 28) is supposed to multiply the item at the top of the calculator stack by the factor 10^A. Unfortunately, unlike the B register, the A register is not preserved by RST 28, and so by the time the byte 3C is reached the A register will have already been corrupted. The only way out of this problem is to use endcalc/LD A, XX/CALL 2D4F, E_TO_FP/RST 28 instead of the byte 3C in your code.

Neon Bar

The INKEY$# 0 error
(from ZX Computing Monthly - Toni Baker)

Normally, stream zero represents the keyboard, so we would expect INKEY$# 0 to be similar in operation to INKEY$ (without a stream number). This, however, is not the case, and INKEY$# 0 almost invariably produces an empty string, making it completely useless. Note also that calculator code 1A evaluates INKEY$#X (where X is the item at the top of the calculator stack) and this too will be useless whenever stream X represents the keyboard. The bug is in the subroutine at address 1634 which makes channel "K" the current channel. The instruction RES 5, (FLAGS) at address 1638 erroneously cancels out any key press which would otherwise have been detected. The bug could have been cured in the READ_IN subroutine at address 3645 by preserving the value of (FLAGS) during the call of CHAN_OPEN.

Neon Bar

The FN error
(from ZX Computing Monthly - Toni Baker)

When a user-defined function is evaluated the value of the system variable (CH_ADD) which stores the address of the next character to be interpreted, is saved on the machine stack instead of in one of the dynamic variables such as (X_PTR) during the evaluation of the function. This means that any user-defined function which causes the BASIC program area to move up or down in memory will cause error report C; Nonsense in BASIC. This is not normally possible, but exceptions can occur if the DEF FN statement contains the function USR, and could also conceivably happen with the function INKEY#X. To avoid this bug you must ensure that any machine code subroutine which is called by a DEF FN statement does not disturb the BASIC program area (e.g. it is impossible to define a function FN D (X,Y) which would delete BASIC lines X to Y inclusive without also manipulating the machine stack).

Neon Bar

The USR error
(from ZX Computing Monthly - Toni Baker)

Machine code programmers will be so familiar with this one that they don't even think of it as a bug any more. The problem is that the HL' register, whose value is required by the RST 28 sequence at address 2756, is not preserved by the USR subroutine at address 34B3. This means that any machine code subroutine which disturbs the value of HL' (it should contain 2758) will crash the system upon return. To avoid this bug simply ensure that HL' contains 2758 upon execution of the final RET statement of any machine code subroutine called by USR.

hbar

EDITING ERRORS

hbar

The SCROLL? error
(from Understanding Your Spectrum, by Dr. Ian Logan)

Whenever a prompt message such as "scroll?" Or the cassette messages appear, the Spectrum waits for you to press a key. The problem is that if you press the wrong key, things go wrong. Pressing TRUE VIDEO, INV VIDEO, CAPS LOCK, GRAPHIC or EXTEND MODE causes the previous edit line to appear at the bottom of the screen, with the 48K flashing cursor (even on 128K machines). This is because the KEY_INPUT subroutine at address 10A8 is designed to deal with CAPS LOCK, mode changing, and colour control parameters, however this is inappropriate for prompt messages.

Neon Bar

The CURRENT LINE CURSOR error
(from Understanding Your Spectrum, by Paul Harrison)

This bug is applicable only on the 16K and 48K Spectrums. 128s don't have this problem because the EDIT key doesn't do quite the same thing. Type 9000 PRINT/9001/EDIT (note that "/" stands for ENTER) and, provided there are no lines greater than 9000, you'll see the problem - a GREATER-THAN symbol appears in the edit line. The bug occurs in the OUT_LINE routine at address 1855. The bug could have been avoided if the subroutine had refused to print the GREATER-THAN cursor whenever bit four of (FLAGS2) were set.

Neon Bar

The LEADING SPACE error
(from Understanding Your Spectrum, by Dr. Ian Logan)

Bit zero of (FLAGS) is supposed to be set whenever a leading space is not required for a keyword token. Unfortunately, the ROM is not consistent about its use, as the one-line program

CLS: FOR I=1 TO 5: PRINT CHR$ 244: NEXT I

will prove. The problem would be solved if the flag were to be set every time CLS were executed, or whenever a control character 00 to 1F were printed.

Neon Bar

The K-MODE error
(from Understanding Your Spectrum, by Chris Thornton)

This is another one for 16K and 48K Spectrums only. If, when editing program line, the cursor is a flashing "K" then the editor is said to be in K-mode. This means that the next key you press will be interpreted as a keyword, so that if you press "P" for instance, then you'll get PRINT. The problem is that if you hold a key down so that it repeats then K-mode remains in force. This means that you could end up with a line like "NEXT NEXT" instead of "NEXT N". The bug is caused by the K_REPEAT routine at address 0310. To work properly the routine would have to subtract hex A5 from the key value whenever this was greater than hex E5. This would replace keywords with capital letters.

Neon Bar

The SYNTAX CHECK error
(from Master Your ZX Microdrive, by Andrew Pennell)

On the 16K and 48K Spectrums the four keywords ERASE, MOVE, FORMAT and CAT have incorrect syntaxes. The statements ERASE (string) : MOVE (string), (string) : FORMAT (string) : CAT will be accepted as program lines, but will give error messages if you try to run them. On the 128K Spectrums the statement MOVE (string), (string) will be accepted as a program line, but treated as a REM statement on running. The bug in the 48K machine is due to the fact that the syntaxes of these Interface One commands were incorrectly anticipated. On the 128 a wholly new syntax routine is included, and the commands ERASE and CAT have been taken over for use with the silicon disc system, whilst FORMAT has been taken over for use with the RS232. MOVE, however, is not used at all, and the original false syntax has been reproduced in an entirely new syntax routine in the new ROM.

hbar

HOOK CODE ERRORS

hbar

Hook codes are used to call subroutines in the Interface One's Shadow ROM. There are two errors in these:

The READ-N error
(from Master Your ZX Microdrive, by Andrew Pennell)

Hook code 2F (READ_N) was intended to read a block of data from the "N" channel (the local area Network). The carry flag is assigned to indicate success or failure, but unfortunately the carry flag is subsequently destroyed by a call to the border restore routine.

Neon Bar

The SET-T-MCH error
(from Master Your ZX Microdrive, by Andrew Pennell)

On version one issues of the Interface One, hook code 2B (SET_T_MCH) accidentally calls the OPEN_M routine instead of SET_T_MCH, making it identical in operation to hook code 22. The bug has been cured in later editions of the Interface One, and in these later editions it correctly performs its task of creating a temporary "M" channel in the channel information area.

hbar

INTERRUPT ERRORS

hbar

The MONOPOLISING OF IY error
(from ZX Computing Monthly - Toni Baker)

Though not strictly an "error" as such it is worth noting that the Spectrum's interrupt routine contains the instruction INC (IY+40), which is intended to increment the high byte of the (FRAMES) variable (when necessary), however to do this IY must have a value of 5C3A at all times while interrupts are enabled (unless of course you define your own interrupt routines). Unfortunately, IY is not temporarily assigned with this value within the interrupt routine itself. The effect of this misdemeanour is that the value contained by IY must never be changed (unless interrupts are disabled or an alternative interrupt routine supplied). This restricts us, because it means that a machine code register which could have been available to us now must not be touched. It is possible to cure this condition by using the following program as an interrupt routine.

     FDE5
 
INT_ROUTINE
 
PUSH IY
 
Preserve the IY register.
     FD213A5C
LD IY, 5C3A
:IY contains value required by normal interrupt routine.
     FF
RST 38
Execute normal interrupt routine.
     FDE1
POP IY
Restore IY register.
     C9
RET
Return.

Neon Bar

The SWAP error
(from ZX Computing Monthly - Toni Baker)

The SWAP routine which switches between the two ROMs of the 128K Spectrum invariably enables interrupts, which may not always be desired. Fortunately, this error may be cured by the following program:

     ORG 5B00
     C3????
 
SWAP JP
 
SWAP_OK
 
Redirect control to revised routine.
 
     ORG ????
     F5
SWAP_OK
PUSH AF
Stack A and F.
     C3
PUSH BC
Stack B and C.
     ED5F
LD A, R
:P/V flag = interrupt status.
     F5
PUSH AF
Stack interrupt status.
     01FD7F
LD BC, 7FFD
:BC= port number required for paging.
     3A5C5B
LD A, (BANK_M)
:A= current pages.
     EE10
XOR 10
Complement 'ROM' bit.
     F3
DI
Disable interrupts (in case an interrupt occurs between the next two instructions.
     325C5B
LD (BANK_M), A
Store revised pages.
     ED79
OUT (C), A
Actually change ROM.
     F1
POP AF
:P/V flag= former interrupt status.
     E2????
JP PO, SWAP_OK_2
Jump if interrupts previously disabled.
     FB
EI
Re-enable interrupts.
     C1
SWAP_OK_2
POP BC
Restore B and C.
     F1
POP AF
Restore A and F.
     C9
RET
Return.

Simply write the instruction JP SWAP_OK to location 5B00, where SWAP_OK is the address of the program.

Neon Bar

The PLAY error
(from ZX Computing Monthly - Toni Baker)

At address 09CD in the 128, or 09EC in the 128+2, the STK_FETCH subroutine is called from the old ROM. At this point interrupts are disabled and IY is now being used as a pointer to the master PLAY information block. Unfortunately, because of the two bugs listed above, interrupts are enabled during the STK_FETCH call, leaving IY containing the wrong value. This means that if an interrupt were to occur during execution of the subroutine then there would be a one in 65536 chance that (IY+40) will be corrupted - this corresponds to the volume setting for music channel A. In practice this circumstance is very rare indeed. Rewriting the SWAP routine as above will cure this bug.

hbar

ERROR ERRORS

hbar

This group of errors are bugs in the Spectrum's own error handling routines!

The INVALID FILENAME error
(from Master Your ZX Microdrive, by Andrew Pennell)

If the Interface One is attached then the error message "Invalid filename" is replaced by the message "Nonsense in BASIC", which is not particularly helpful.

Neon Bar

The INVALID DEVICE EXPRESSION error
(from ZX Computing Monthly - Toni Baker)

Most ironic of all is the curious error which only occurs with the combination of ZX Interface One and Spectrum 128 or 128+2. If you have a BASIC line such as 1000 OPEN 4, "X" (the line number must be greater than 999) then you should by rights get the error message "Invalid device expression, 1000:1" - indeed, true to form, the Spectrum does indeed attempt to produce this message for us. Unfortunately, the message is just too long to fit on a line! The thirty three characters in the error message will not fit on a line of only thirty two squares. The Spectrum 128's marvellous little full screen editor only allows for a lower screen of two lines (including one blank line above the error message), but this particular error message takes three lines, not two! If you're using only the lower two lines as the editor then the effects of the bug aren't too bad: you merely get a few spurious things happening at the bottom of the screen. If you're using the whole screen as an editor however then the bug is FATAL, causing an unavoidable system reset in 48K mode! A shame really - the poor thing was only trying to tell you about a bug in your BASIC. Never mind - after all nobody is perfect.

hbar

NEW ERRORS

hbar

These errors have been reported after the original article was published.

The CLEAR PRINTER BUFFER Bug (48K mode only)

This routine should really start by checking bit 1 of FLAGS to see if stream 3 is in use. As a consequence of ignoring this the printer buffer is needlessly cleared after the COPY command and also when the COPY command is interrupted by pressing BREAK. Even worse, if stream 2 is in use, i.e. COPY, then the DF CC system variable is loaded with the address of the start of the printer buffer as the CLEAR-PRB routine exits to PO-STORE via CLS-SET. This will lead to an "Out of screen" error if subsequent PRINT commands do not include an AT clause. e.g.

PRINT : COPY : PRINT

The rest of the ROM is so well developed that this check must once have been in place. Instead there's a half-baked attempt to circumvent the use of 23681.

Neon Bar

The PR CC Error (48K mode only)

This is more a bug in the manual although the ROM code is untidy (see above). The manual says that 23681 is unused whereas it is the high byte of PR CC and should never be altered. At one time the printer buffer followed the system variables as it did on the ZX81. With a few more system variables for network and RS232 the high byte could increment as characters were printed. When the printer buffer was moved to it's current location an attempt was made to set the low byte of the system variable directly within the CLEAR-PRB routine. However this instruction is superfluous and the variable is updated in full by PO-STORE. This can be demonstrated with

10 POKE 23681,64 : LLIST

This uses the first 256 bytes of the screen as a printer buffer and if you look carefully at the screen, you may be able to make out the listing.

Neon Bar

The NEW COMMAND Bug (128K mode only)

The initialisation routine of the 128K ROMs (Sinclair 128K, Amstrad +2, Amstrad +3, and possibly +2A) intentionally set main memory to the following values
60435,0
65316,0
65317,236
This is very hard to detect as the only non-zero byte is immediately below the machine stack and soon overwritten. The NEW command unfortunately also sets these locations even if they are above RAMTOP. Consequently utilities which are designed to survive NEW don't.
Examples are Zeus assembler, Devpac, Basic extensions and other languages.

Neon Bar

MAIN-4, (48 ROM-1303h)

There are two problems with the MAIN-4 routine. First if it is called with interrupts disabled it will crash because of the HALT instruction. Second it is missing a SET 1(IY+1) instruction (which tells the Spectrum to use the printer instead of the screen). The result is that typing LPRINT "bug";: PRINT, pressing enter and then typing PRINT will generate an Out of screen error.

Neon Bar

KEYCLICK, (128 ROM-26F1h)
(Ian Collier)

On the +3, the 128 (and presumably the +2) also has the wrong memory location to check the length of the keyclick. This is why it sounds deeper in 128 Basic.

Neon Bar

LOWER SCREEN EDITING, (128 ROM-2DA1)
(Ian Collier)

Also spotted on the +3, replicated at this address on the 128 (and somewhere else on the +2).

Neon Bar

128 MENU (128 ROM)

Not exactly a bug. The menu is centred over the copyright message on the 128 but on later machines it no longer looks centred because of the length of the copyright message. Amstrad only needed to change four bytes to centre it on the screen!

Neon Bar

WRITE TO ROM (48 ROM-33FEh)

Not so much a bug as poor coding. The ROM tries to write four bytes starting at 0000h. On a real Spectrum there is usually no effect because you can't actually write to the ROM, but if a copy of the ROM is really in RAM (to give better compatibility on a +3 or +2A for instance), the 'ROM' could be overwritten.

Neon Bar

The SCROLL? error (48 ROM)

Not only does this affect the 'Scroll?' prompt, but also the 'Start tape and press any key.' prompt. Pressing 'any' key will not always work!

Neon Bar

The RAM test (48 ROM-11CEh)

Again, not a bug as such. The RAM test had a secondary function on the original Spectrum of detecting if it was a 48K or 16K machine but as it only tests the first 48K of RAM serves no purpose on 128 machines and could have been replaced with a more efficient memory wipe routine.

Neon Bar

The EDIT key bug (48 ROM-1860h)

If you enter a line 9000 REM bug. Then enter 9001 and then press EDIT the '>' cursor appears in the line.

Neon Bar

The DRAW commands (48 ROM)

The PLOT, DRAW, CIRCLE and POINT commands are limited to the normal printable area (32x22 characters). There was no reason to stop users using the lower two lines of the screen.

Neon Bar

The GOTO bug (48 ROM)

The result you get of attempting to GOTO a non-existent line depends on whether it is above or below 16384. It appears the ROM originally supported line numbers up to 16383 and the only logical reason for limiting it to 9999 is the problem of error messages going off the screen.

Neon Bar

The RESTORE bug (48 ROM)

Basically, typing RESTORE 61250 will put the machine in a continual loop, effectively crashing it.

Neon Bar

The CHR$ 27 bug (48 ROM-09F7h, only affects 128)
(Andrew Owen)

The Spectrum character set is just like normal ASCII (except for the POUND and COPYRIGHT symbols) from code 32 to 127. But, codes lower than those are used for setting colour and position and so on, while some are not used at all. The upshot of which is, 128 machines cannot generate special printer codes (using code 27) from BASIC. Changing one byte from 20h to 18h would allow the use of codes 24-31, and while they would print garbage on the screen, they would be able to control a printer connected to the RS232 port (or parallel on the +3/+2A).

Neon Bar

Channel P (ZX Printer) does not restore permanent attributes.
(Daniel Nagy)

Trigger: 10 LPRINT INVERSE 1;"BUG!": LLIST After running the above, the listing will also be inverted.

Cause: A jump to TEMP is missing from the end of CHAN_P.

Fix (combined with another minor fix):

162d 4b 06                     L162D:  DEFB    'K', CHAN_K-$-1
162f 53 11                      DEFB     'S', CHAN_S-$-1
1631 50 1a                     DEFB     'P', CHAN_P-$-1
1633 00                          DEFB      $00                          ; end marker.
1634 21 3c 5c                CHAN_K: LD  HL,TV_FLAG
1637 cb c6                     SET     0,(HL)                          ; signal lower
1639 cb 9e                     RES    3,(HL)                          ; disable echo
163b fd cb 30 e6           SET     4,(IY+$30)                   ; update FLAGS2
163f 18 04                      JR                   CHAN_S1       ; jump forward
1641 fd cb 02 86           CHAN_S: RES 0,(IY+$02)    ; signal upper
1645 fd cb 01 8e           CHAN_S1: RES 1,(IY+$01)  ; no printer
1649 c3 4d 0d               CHAN_S2: JP L0D4D           ; TEMPS
164c fd cb 01 ce           CHAN_P: SET 1,(IY+$01)      ; signal printer
1650 18 f7                     JR CHAN_S2                           ; indirect exit

This fix also makes the call at $1FD5 redundant; removing it will marginally speed up the PRINT command, when printing to TV (K and S channels).

hbar
My thanks to Geoff Wearmouth, Ian Collier, Daniel Nagy and Andrew Owen for expanding my original list and for their continued work on the Spectrums previously undocumented features.
hbar

Go To eZine X Page Go To Contents Page