Z80onDSK for the ZX Spectrum +3

Since getting a Gotek for my +3 it has been my go to machine. The biggest downside however is the lack of older games on disk format with pretty much everything 1986 and earlier missing. Although there are few compilations covering bits and pieces. I've been messing with a few of the utilities (tap2dsk, sna2dsk etc...) to transfer some of the older games to disk but haven't really found anything that is easy to use, can work with all snapshots or doesn't require a lot of tweaking to get it to work. I've probably missed an obvious utility that works amazing but I couldn't find it so I've therefore decided to write my own and have finally got it working.

I've called the utility Z80onDSK as it creates disk images from the popular Z80 snapshot format (v1, v2 or v3). The utility basically re-compresses the snapshots and adds a custom loader so it can be easily loaded on a +3. The custom loader uses the standard +3DOS ROM routines and RAM paging to load the entire snapshot from disk, including restoring all the registers as defined in the z80 snapshot. You can even add a different loading screen if you want. In addition to the +3 the converted files will also work on a +3e with hard disk although for hard disk use you are still probably better using the +3e inbuilt SPECTRUM command for all but those that require bank switching off or the Sinclair ROM.

To improve compatibility with older games you can turn off bank switching (good for Ultimate games), and also page in the original 48k Sinclair ROM if required. The later does have the downside that the upper memory will become contended though so best used on 16k games or ones that just don't work at all with the Amstrad ROM. There are plenty of other options to get most games working fine, see later on for details.

The created disks can contain single or multiple Z80 snapshots by using the inbuilt batch mode (see below). I've found that I can get between 5 & 6 48k games on one disk, obviously a few more if they are 16k ones and a few less if 128k. I use my LZF compressor to re-compress the snapshots, which is much better than Z80 compression shrinking the snapshots to around 70-80% of the original. For 48k snapshots, by default, it turns off bank switching to improve compatibility (you can also turn it back on if needed) and can patch in the original Sinclair ROM to improve compatibility further especially for 16k or very old games. For 128k snapshots it runs a quick analysis to determine if it can be stored as 48k only to save space or needs all the memory banks. Unfortunately in order to ensure all the memory is restored it does cause some screen corruption, much less on 48k snapshots and 128k with little data in bank/page 7.

+3DOS Menu

Bootstrap Menu

Example Loading

Version History

v1 was 48k only, v2 introduced 128k but with only partial memory restore and v3 had full memory restore which helps with compatibility. The advantage of the older versions is, even though they are limited, they can restore the snapshot with no screen corruption so I have offered v2.4 as a download. I don't recommend using this version for 128k snapshots unless you know it doesn't use bank/page 7. Also files created with v2.4 are not compatible with v3 or greater and vice versa.

As of version v3.2 I've included a more advanced loader with a nicer menu screen. This mimics the 128k menu just with a 64column font and catalogs the disk so you no longer need to pass in the filenames. However if you preferred the old way I've included a v3.1 download which is the last version with the old basic loader.

As of v3.3 I've added a fast bootstrap loader (track 0) which saves a few bytes as you no longer need the basic and loader code as +3DOS files. The only downside is it only works on floppy disk drive A:, so if you want to use drive B: or hard disks you will have to use the normal version. Option -l lets you pick the normal loader over the bootstrap.

v3.3a fixed a bug from earlier versions were I was switching off the disk motor by accident. This didn't show on testing as Gotek and most emulators don't care, however the more accurate RetroVirtual Machine picked it up. Big thanks to the author for helping me to find this.

v3.4 includes a bug fix when the second file is >64k, it no longer crashes.

v3.4a fixed an issue when the 128k Editor ROM was in place, this is now maintained instead of being switched to 48k ROM (Port 0x1FFD)

v3.4b fixed an issue with 48k v2 Z80 snapshots and an out of order page layout

v3.4c improved compression parser, faster and slightly better compression rate

v3.5a now works with 0x1ffd port if present & added option to replace the loading screen rather than just use a different one

Z80onDSK v3.5a

Windows (x86)

Z80onDSK v3.1

Mac & Windows

Z80onDSK v2.4

Mac & Windows

Basic Usage

In it's basic form to use the utility take any Z80 snapshot and type:

Z80onDSK snapshot.z80

This will de-compress the Z80 snapshot, re-order, re-compress (using my own modified LZF compressor) and create a Spectrum +3 disk image called "snapshot.dsk". As well as the Z80 snapshot the disk, s default, contains a bootstrap loader which catalogs the disk allowing you to select which snapshot to load. If there is only one snapshot on the disk it will auto load it. If you choose not to use the bootstrap version of the loader there will be an additional two files on the disk. One is the autorun basic routine called DISK, the other the loader machine code called LOADER. These work the same as the bootstrap but are +3DOS friendly so you can run them from other disks such as B: drive or a hard disk, you just need to switch devices beforehand with LOAD "b:". If the loader fails at any point it will just crash so no real error trapping. In addition to disks you can also create a tape file or just dump the compression files to your PCs hard disk so you can copy to a HDF file or similar (for use with +3e ROMs)

If you want the disk to be called something else, say Disk001, you just put:

Z80onDSK snapshot.z80 Disk001

Other settings are shown below.


Transfering to Real 3" Disks

Although predominately designed for use with Goteks you can also transfer the resultant disks to real media either using an Amstrad FD-1 connected to a PC or by using a utility called DSK2TAP. This utility converts a DSK image to a TAP file which, when run on a Spectrum +3, recreates the original disk. Just use a PC or APP to load the TAP file into your +3.


Batch Mode

To use batch mode simply list the snapshots you want to convert onto a single disk on the same command line. For example to create a disk called compilation1.dsk with two snapshots included put:

Z80onDSK snapshot1.z80 snapshot2.z80 compilation1

Each snapshot can have its own set of settings and you can include a maximum of 16 on each disk as long as there is space.


Snapshot Settings

These are applied only to the snapshot they proceed:

Alternate Loading Screen (-s screen.scr)
As default the loader uses the z80 snapshot screen ($4000-$5b00) as a loading screen. This is often fine as many z80 snapshots have a pause screen after loading which just so happens to be the loading screen. Some however don't, or you might not like the one in the snapshot, so you have the option to replace it with another compressed screen with the original loaded in right before run time. This obviously adds to the total snapshot size.

Alter SPECTRUM filename for the snapshot -o <name>
Normally the SPECTRUM disk name is taken from the snapshot name truncated to 8 chars with non-alphanumeric & spaces removed to ensure PLUS3DOS compatibility. This option can be used to change that.

Clear AY register settings (-a)
Sometimes 48k snapshots have erroneous data in the AY registers which cause unwanted noise when running on the +3. This option will clear all the AY registers instead of using snapshot settings to prevent this.

Override Border Colour (-b1,2,3,4,5,6 or 7)
Sometimes snapshots have incorrect border colour so you can use this option to override the snapshot setting with the correct colour 0 - 7

Force machine type (-f1,2,3,4 or 5)
The original snapshot may have been captured on an incorrect machine or you may want to ensure bank switching is still turned on. With this option you can force the machine type. For example 16k snapshots are often taken on 48k machines and junk may appear in the upper memory. You can force the utility to wipe the upper mem and reduce the snapshot size, it will also patch in the Sinclair ROM to improve compatibility. You can also tell the utility to force 48k with or without bank switching and also if you want to patch in the original Sinclair ROM. Finally the utility will attempt to auto convert 128k snapshots to 48k if only 48k banks are used, f5 options will prevent this from happening.


Global Options

These are applied to all snapshots and outputs

Output to Tape (-t)
As well as creating a disk this option will enable tape support. Only the loader code and snapshots are put onto the tape.

Quiet Mode (-q)
As it implies no text output from the utility other than error messages

Dump z80 banks (-m)
Mostly used for debugging but I left it in just in case. Basically dumps the memory banks and final compression out to files which are named after the SPECTRUM filename

Dump compression data files only (-d)
Dump compression data files only & suppress disk production. Useful if you want to copy the images to a disk or hdf manually using one of the many utilities. As for -m the files are named after the SPECTRUM filename

Alter Menu Name (-n <name>)
Change the default menu name (Z80onDSK) with a custom 8 character name. This has to be alphanumeric and will be converted to uppercase.

Use Standard Loader (-l)
Use standard +3DOS compatible loader, with basic autorun routine, instead of embedded disk bootstrap


Q&A

(Q) Snapshot doesn't work
(A) If the game is old (16k or 48k from 1982/83) then it might require the Sinclair ROM try option -f4

(Q) Still doesn't work
(A) Some 48k games require bank switch on or some require it off. Try options f2 and f3 to see if that helps

(Q) Still doesn't work
(A) It might be a bad snapshot, does it work on an Emulator? Try loading the tape/tzx version into an Emulator (correct machine selected) and saving a new snapshot. Also if it is 128k try saving the snapshot after the loading screen as this may avoid any setup/memory swapping routines which may not work on a +3. If taking a new snapshot use FUSE and debugger option br ev tape:stop to capture the snapshot just as the game has loaded.

(Q) Nope still not working should I give up
(A) Some games just don't work on the Spectrum +3, however it might be worth trying different releases of the game (for example Hit Squad) which may have fixes. Also try Alessandro Grussu's website to see if there is a fixed version on there

(Q)The snapshot size for a 16k game is very large
(A)Often 16k games where captured on a 48k machine which may have junk in the top 32k. Try option -f1 or if you can re-load via tape & re-capture the snapshot using an Emulator with 16k machine selected you should then get a nice small snapshot


Technical Details

For either loader (bootstrap or normal) just press enter at the main menu and a selector menu will appear. The bootstrap loader is located in track 0 so you cannot access it from +3DOS (at least without the low-level DD routines). The normal loader is just files on the disk and uses a small basic routine to load (called DISK so it autoruns). Both routines are located at 24388 so a CLEAR 24387 is required to run correctly. To enter the normal loader enter RANDOMIZE USR 25012. The basic loader for this version is simply:

10 CLEAR 24387
20 LOAD "loader"CODE
30 RANDOMIZE USR 25012

If using v3.1 or earlier the loader works slightly differently as you have to POKE the filename of the snapshot to a certain location. This isn't as slick but is more adaptable if you want to use your own menu. I'd recommend using v3.1 if this is what you want as it restores all the 128k memory. The basic loader is as follows for that version:

10 CLEAR 24414
20 BORDER 7:PAPER 7:INK 0:CLS
30 LET a$="URIDIUM "
40 FOR i = 1 TO LEN(a$):POKE 24414+i,CODE(a$(i)):NEXT i:POKE 24414+i,255
50 BORDER 0:PAPER 0:INK 7:CLS
60 LOAD "loader"CODE
70 RANDOMIZE USR 24424

This loads the snapshot URIDIUM which is poked to memory location 24415-24423 which is then picked up by the loader.

For 48k the unpacking strategy is:

  1. Loader code placed at 24388 (new) or 24415 (old) which includes a small 256byte buffer
  2. Disable disk cache and RAM drive
  3. If -f1 or -f4 option used then Patch 48k ROM and copy into page/bank 4
  4. Open File
  5. Decompress loading screen to page/bank 5
  6. Decompress page/bank 0 to page/bank 0, if -f4 then 3
  7. Decompress page/bank 2 to page/bank 2, if -f4 then 6
  8. Decompress page/bank 5 (0x6200 to 0x7fff) to page/bank 5
  9. Decompress page/bank 5 (0x5b00 to 0x61ff) to page/bank 7 @ 0xec00
  10. If required decompress original screen to page/bank 5 (0x4000 to 0x5aff)
  11. Copy run-time code to top of page/bank 5 (0x4000)
  12. Turn off 3DOS (close file, turn off motor & disable interrupts)
  13. Jump to run code at 0x4000
  14. Copy code at 0xec00 to 0x5b00-0x61ff
  15. Set-up registers to match snapshot and jump to PC

and for 128k which uses two files to ensure file size isn't > 65536bytes:

  1. Loader code placed at 24388 (new) or 24415 (old) which includes a small 256byte buffer
  2. Disable disk cache and RAM drive
  3. Open file 1
  4. Decompress loading screen to page/bank 5
  5. Decompress page/bank 0 to page/bank 0
  6. Decompress page/bank 1 to page/bank 1
  7. Decompress page/bank 2 to page/bank 2
  8. Decompress page/bank 7 shadow screen to page/bank 7 (0xc000 to 0xdb00)
  9. Close file 1 & open file 2
  10. Decompress page/bank 3 to page/bank 3
  11. Decompress page/bank 4 to page/bank 4
  12. Decompress page/bank 6 to page/bank 6
  13. Decompress page/bank 7 (0xec00 to 0xffff) to page/bank 7 which includes
  14. compressed bank/page 5 (0x5b00-0x61ff)
  15. If required decompress original screen to page/bank 5 (0x4000 to 0x5aff)
  16. Copy run-time code & compressed bank/page 7 (0xdb00 to 0xec00+len of 13)
  17. to top of page/bank 5 (0x4000)
  18. Turn off 3DOS (close file 2, turn off motor & disable interrupts)
  19. Jump to run code at 0x4000
  20. Decompress code at 0xec00 to 0x5b00-0x61ff
  21. Decompress code in run-time to 0xdb00-0xec00+len of 13
  22. Set-up registers to match snapshot and jump to PC

This will recover 100% of the Spectrum +3s memory other than part of the screen area which is used for storing the run-time code and part of page/bank 7 for 128k.

My test 128k Z80 snapshots were Daley Thompson's Supertest 128k and Three Weeks in Paradise 128k. My initial design was to have one big file on the disk as +3DOS can stop and start as required. This worked fine for Three Weeks and it loaded fine. For Daley the resultant compressed file was over 64kB which although doable caused some strange results so I decided to split 128k snapshots into 2 files so they can never go over 64kB. Once I did this Daley loaded fine as well.

I've tested a few other snapshots and it has a good success rate. If using the TOSEC or similar collection it may require that you re-do some of the snapshots.


╔═══════════════════════════════════════════════════════════════════════════════
║ Z80onDSK v3.3 for WINDOWS or OSX (c) 2019 Tom Dalby
╠═══════════════════════════════════════════════════════════════════════════════
║ Usage: Z80onDSK [global options] <snapshot>.z80 [snapshot settings] <name>

║ <name>: output filename, if nothing specified z80 snapshot filename used

║ [global options]
║ -t: output to tape as well as disk
║ -q: quiet mode, turn off all text output (other than error messages)
║ -m: dump memory banks and full compression to binary files. These will be
║ named after the SPECTRUM filename
║ -l: Use standard +3DOS compatible loader (with basic) instead of bootstrap.
║ -n <name>: Add an 8 char name to the loader menu, alphanumeric only.
║ -d: dump compression data files only & suppress disk production. Useful if
║ you want to copy the images to a disk or hdf manually. As for -m the
║ files are named after the SPECTRUM filename

║ [snapshot settings]
║ -o <name>: define SPECTRUM filename, if nothing is specified snapshot
║ filename used. Truncated to 8 chars with non-alphanumeric
║ & spaces removed to ensure PLUS3DOS compatibility
║ -s <name>.scr: use an alternate loading screen. Must be a .scr 6912bytes
║ -a: clear all AY registers instead of using snapshot settings
║ -bN: override snapshot border colour (0-7)
║ -fN: force machine type
║ 1: force 16k. Clears top 2 memory banks to remove erroneous data in upper
║ memory for 16k games. Helps reduce snapshot compressed size. If stack
║ or PC are in upper mem (>0x7fff) utility will exit with error.
║ 2: force 48k + paging. Works on 128k & 48k snapshots. Only banks 5,0 & 2
║ are stored, retains paging & Amstrad ROM.
║ 3: force 48k no paging. For 128k snapshots as this is default for 48k.
║ Only banks 5,0 & 2 are stored, paging off & Amstrad ROM in place.
║ 4: force 48k old skool. Only banks 5,0 & 2 stored, paging off &
║ original Sinclair ROM patched in. Note this causes upper mem to be
║ contended which may cause issues with some games.
║ 5: force 128k. Prevent automatic conversion to 48k if data not found
║ outside of the page 7 buffers.

║ Batch Mode is activated if more than one z80 snapshot specified, example:

║ Z80onDSK snapshot1.z80 snapshot2.z80 compilation1
║ where "compilation1" is the filename of the resultant disk/tape file
║ (if nothing specified the first snapshot name is used as above)

║ each snapshot can have its own settings but options are global, example:

║ Z80onDSK -q snapshot1.z80 -s screen1.scr snapshot2.z80 compilation1
║ which runs in quiet mode, snapshot 1 has an alternate loading screen,
║ snapshot 2 standard and all outputted to "compliation1.dsk"

║ max 16 snapshots per disk/tape
╚═══════════════════════════════════════════════════════════════════════════════