Phil's ZX Spectrum setup and what it would have been

The background

Many people know that my first computer (rather than one I merely tried out) was a Sinclair ZX Spectrum, that served me very well for seven years. Although expanded greatly, I personally could not afford to do much with it, nor could I persuade anyone to help me afford what I really wanted. Of course, I am not now likely to get it anyway due to the limited availability of equipment, but I am still hoping that one day I will be able to build an emulated version of my ideal Spectrum. I have made some good progress in recent months and have decided to write this web page about my experience. My chosen emulator, by the way, is FUSE.

Phil's Spectrum - final versus ideal
Item Final Ideal Progress
Spectrum 48K rubber keyed, having downgraded back from a Saga Lo-Profile keyboard which failed +2 (regular grey model) with a 48K held in reserve for situations needing it Both machines are well emulated
Mass storage Opus Discovery 1, single disk drive, online capacity 178KB, not 128 compatible version Beta 128, four disk drives, online capacity 2.5MB Emulated well by my usual emulator
Snapshot taker Multiface 1 Beta 128 has one built in Tested, and somewhat working.
Printer interface Opus Discovery 1 has a built-in one Undetermined - would have wanted one that would not need extra software loaded to make it work. Unlikely ever to be emulated. Not critical today.
Joysticks and interfaces Opus Discovery 1 and Multiface 1 both had a Kempston interface supporting a single-fire Atari-type joystick. Two Comcon plug-configured interfaces, with two dual-fire joysticks (e.g. QuickShot 2+2). Capability to common fire buttons, if not built into stick, could be provided via simple added leads that I can make. Also, leads to convert the wiring to SJS for the +2, and one that connects one joystick to both SJS ports to emulate the cursor layout. Potentially possible to manage with just one Comcon when using the +2. FUSE does not yet support arbitrary keys being operated by the joysticks, so support is limited to Fuller, Sinclair and Cursor. Kempston also possible but necessary to switch the interface off when using the Beta disks, due to port clash. Modern PC joysticks such as a Logitech Attack 3 support many fire buttons. Even old models support at least two.
Core business software The Last Word, later than version 2.1 Not yet available on World of Spectrum, and do not own a tape with it on.
Masterfile, version 9 Done. Was awkward but not impossible to adapt to Beta - see below.
Omnicalc 2 Done (easily), but known to require 48 mode to load on a 128 - see below.

One of my policies for software on disk would have been to put business software on its own disk, or one disk per user, and leisure software as multiple titles on the same disk, grouped by what machines it can run on and under what circumstances - the groups would have been, subject to finding anything to go in them, as in this table:

Memory required Machine restriction
16K 128 mode enhancements available - recommend 128 mode on a 128
128 compatible in any mode
128 compatible in 48 mode
Not 128 compatible - 48K machine maximum
48K 128 mode enhancements available - recommend 128 mode on a 128
128 compatible in any mode
128 compatible in 48 mode
Not 128 compatible - 48K machine only. Also for programs which give enhanced sound on a 128, but will not run from the same snapshot on a 48K
128K 128 only and not to be run in 48 mode. Also for programs which will run in 48 mode, if they give enhanced sound on a 128 but will not do so when a snapshot taken on a 48K machine is used

I have written a sequence to be put into a boot program to detect the presence of a minimum 48K of memory, and also to detect when running in 128 mode - both can be put in as needed, to display a message and halt the machine if the way being attempted is unsuitable. I would write similar for the other scenarios if I needed them. They will be clearly explained further down.

Converting Masterfile

Masterfile version 9 proved to be a little awkward to convert for Beta 128, because of its use of consecutive line numbers, called by the machine code of Masterfile itself, and the Beta disk system's requirement that any disk access commands are the last on a line. Fortunately it was not impossible but it did mean making some awkward changes to the BASIC of Masterfile.

You need to add or edit lines as follows (you need to use 48 BASIC for this, and do not disturb other lines):

   2 RANDOMIZE USR VAL "15619": REM : LOAD "MFPUtil"
   3 GO TO VAL "10"
   4 GO TO VAL "20"
   5 GO TO VAL "30"
  10 RANDOMIZE USR VAL "15619": REM : LOAD "MFPOvly"CODE
  11 GO TO R/R
  20 RANDOMIZE USR VAL "15619": REM : LOAD "MFmcode"CODE
  21 GO TO R/R
  30 RANDOMIZE USR VAL "15619": REM : SAVE "MFmcode"CODE VAL "57328",VAL "8208"
  31 GO TO R/R
  50 PRINT AT VAL "15",VAL "2";"(colour codes - leave alone)Cassette (0) or Disk (1-4)(colour codes - leave alone)"
  60 LET d=CODE INKEY$-VAL "48": IF d<R-R OR d>VAL "4" THEN GO TO VAL "60"
4025 LET N$=CHR$ (VAL "64"+d)+":"+C$( TO VAL "8"): RANDOMIZE USR VAL "15619": REM : SAVE N$ DATA f$()
4026 PRINT '"Verifying...": RANDOMIZE USR VAL "15619": REM : VERIFY N$ DATA f$()
4027 GO TO USR R
4032 LET N$=CHR$ (VAL "64"+d)+":"+C$( TO VAL "8"): RANDOMIZE USR VAL "15619": REM : SAVE N$ LINE VAL "4035"
4033 PRINT '"Verifying...": RANDOMIZE USR VAL "15619": REM : VERIFY N$
4034 GO TO USR R
4035 RANDOMIZE USR VAL "15619": REM : LOAD "MFmcode"CODE
4036 GO TO R/R
4055 LET N$=CHR$ (VAL "64"+d)+":"+C$( TO VAL "8"): RANDOMIZE USR VAL "15619": REM : LOAD N$ DATA f$()
4056 GO TO USR R
4201 GO SUB VAL "50": IF d THEN GO TO VAL "4203"
4203 LET N$=CHR$ (VAL "64"+d)+":"+N$( TO VAL "8"): RANDOMIZE USR VAL "15619": REM : LOAD N$ DATA P$()
4204 GO TO USR R

Resume Masterfile with GO TO 5, then key VF1 (assuming you are using drive A) and the filename to save the program and data to disk.

You should also clear the file (as per the Masterfile manual) and save this as a program, called EMPTY. You will also need a boot program. I suggest the one below (once again, use 48 BASIC for this):

10 LET r=PEEK VAL "23732"+VAL "256"*PEEK VAL "23733": IF r<>VAL "65535" THEN GO TO CODE "<"
20 CLEAR VAL "57327": PRINT "Choose option to load:"''"1. Example file"'"2. Blank file"
30 PAUSE NOT PI: LET i$=INKEY$: IF i$="1" THEN RANDOMIZE USR VAL "15619" : REM : LOAD "MF"
40 IF i$="2" THEN RANDOMIZE USR VAL "15619" : REM : LOAD "EMPTY"
50 GO TO VAL "30"
60 CLS : IF r<>VAL "32767" THEN GO TO CODE "P"
70 PRINT PAPER VAL "2"; INK VAL "7";"THIS PROGRAM REQUIRES A 48K OR"'"128K SPECTRUM"; PAPER VAL "7"; INK NOT PI''"It definitely won't work on a"'"16K. Please remove the disk,"'"power down and swap the attachedSpectrum for a model with more  memory.": GO TO CODE "Z"
80 PRINT PAPER VAL "2"; INK VAL "7";"THIS SPECTRUM HAS A MEMORY FAULT"; PAPER VAL "7"; INK NOT PI''"Please remove the disk, power"'"down and swap the attached"'"Spectrum for one with at least  48K working memory."
90 POKE USR "a",CODE " NEXT ": POKE USR "a"+SGN PI,CODE "v": RANDOMIZE USR USR "a"

(note: To key the NEXT in line 90, key THEN NEXT, then move the cursor left and delete the THEN)

To save the program, I recommend you do RANDOMIZE USR 15616, then SAVE "boot" LINE 10 - if there is already a boot program you will need to erase it before you can save.

On a 48K Spectrum with the autoboot switch on the Beta set to on, the boot program will load automatically. In any other scenario, do RANDOMIZE USR 15616, then RUN to start it. Masterfile is perfectly capable of running in 128 mode, but you don't get additional capabilities.

Programs not for 128 mode

Some programs, notably Omnicalc 2, will not work in 128 mode. Omnicalc 2 itself, with its add-on tape, was easy to convert to work with the Beta disk system, so I will not detail all of that here, but because it is incompatible with 128 mode, I designed a boot program to account for that. Here it is:

10 CLS : LET r=PEEK VAL "23732"+VAL "256"*PEEK VAL "23733": IF r<VAL "65535" THEN GO TO CODE "("
20 IF PEEK VAL "23388"<>VAL "16" THEN GO TO CODE "F"
30 PRINT PAPER VAL "2"; INK VAL "7";"THE PROGRAM ON THIS DISK WILL"'"NOT WORK IN 128 BASIC"; PAPER VAL "7"; INK NOT PI''"Reset the computer and select 48BASIC, then type RANDOMIZE (T)  USR (EXTEND MODE then L) 15616  and at the next prompt, RUN (R).": GO TO CODE "<"
40 IF r=VAL "32767" THEN PRINT PAPER VAL "2"; INK VAL "7";"THIS PROGRAM REQUIRES A 48K OR"'"128K SPECTRUM"; PAPER VAL "7"; INK NOT PI''"It definitely will not work on a16K. Please remove the disk,"'"power down and swap the attachedSpectrum for one with at least  48K of RAM. Remember, on a 128K you will need to use 48 BASIC toload this program.": GO TO CODE "<"
50 PRINT PAPER VAL "2"; INK VAL "7";"THIS SPECTRUM HAS A MEMORY FAULT"; PAPER VAL "7"; INK NOT PI''"Please remove the disk, power"'"down and swap the attached"'"Spectrum for one with at least  48K of working RAM. Remember, ona 128K you will need to use 48  BASIC to load this program."
60 POKE USR "a",CODE " NEXT ": POKE USR "a"+SGN PI,CODE "v": RANDOMIZE USR USR "a"
70 RANDOMIZE USR 15619: REM : LOAD "om2"

(note: the NEXT in line 60 is keyed as per the one in line 90 of Masterfile's boot program.)

Converting games

Whereas some games have tricky loaders, and can therefore only really be put on disk by using the NMI button, it is potentially advantageous to convert games that have simple loaders to load directly from disk.

As an example, here is how to convert the classic game "Stonkers".

  1. Use a tape header reader to read the headers of all the parts to the game. Note down whether the part is BASIC, and its start line (the first one will definitely be), bytes, in which case note start and length, or an array, in which case note its name.

    "Stonkers" has these 5:

    stonkers	BASIC	LINE 10
    screen		36864	6912
    stonk		24576	39900
    2		23728	2
    3		23672	3
    

    You should rename the last four parts "stonker1" to "stonker4" as you go, to prevent clashes with other games.

  2. Using 48 BASIC for best results, reset and MERGE "". This will give you access to the loader, which you will need to modify to meet the disk system's requirements. You will also need to specify the addresses for the last two parts as they load to the system variables NMIADD and FRAMES, and the game will not run if these are wrong.

    The version I use is as follows:

    10 CLEAR 24570: BEEP .5,1: BORDER 0: PAPER 0: INK 7: CLS: INK 0
    20 RANDOMIZE USR 15619: REM : LOAD "stonker1"SCREEN$
    30 RANDOMIZE USR 15619: REM : LOAD "stonker2"CODE
    40 RANDOMIZE USR 15619: REM : LOAD "stonker3"CODE 23728
    50 RANDOMIZE USR 15619: REM : LOAD "stonker4"CODE 23672
    60 PRINT USR 49348
    

    Do RANDOMIZE USR 15619: REM : SAVE "stonkers"LINE 10 to save this.

  3. Reset again, and CLEAR 24575. Then LOAD ""CODE : RANDOMIZE USR 15619 : REM : SAVE "stonker1"CODE 36864,6912. Next, LOAD ""CODE : RANDOMIZE USR 15619 : REM : SAVE "stonker2"CODE 24576,39900.

  4. The next two are slightly harder. LOAD ""CODE 32768 : RANDOMIZE USR 15619 : REM : SAVE "stonker3"CODE 32768,2. Then LOAD ""CODE 32768 : RANDOMIZE USR 15619 : REM : SAVE "stonker4"CODE 32768,3.

If you reset and RANDOMIZE USR 15619: REM : LOAD "stonkers" it should now work.