Z80onMDR - ZX Spectrum Z80 to Microdrive Converter

With the growing popularity of the excellent vDrive and OqtaDrive I decided to adapt Z80onDSK to create Microdrive cartridges instead of disks from Z80 snapshots (now compatible with .SNA snapshots as of v2.5). Anybody that has tried to copy tapes to a Microdrive is aware of the challenges especially with the later custom loaders and the aim of this utility is to make it as easy as possible to get games onto cartridge, including the ability to create compilations with a nice menu etc...

Initially I was only going to make this 48k only as figured that would cover most users, however, I was quickly able to adapt it to cover all just in case somebody wanted to use a Microdrive on a Toastrack or early Amstrad +2 (light grey version).

Compared to Z80onDSK there are a few differences. For this utility I decided to stick to a basic loader rather than M/C as understanding the ROM routines wasn't as simple as for 3DOS, plus I found it easier to enable things like multi-Microdrive support. I also tweaked the menu system to take up a lot less space as Microdrive capacity is a lot lower than +3 disks. Finally I removed some of the memory tweaking options and the ability to switch ROMs as these don't really make sense on the machines that are compatible with an Interface 1. For 48k snapshots the utility also always turns off bank switching so the Ultimate Games (and others like Match Day) will work fine on a 128k machine.

As a special request I quickly converted the utility to create OPUS Discovery & MGT Plus D Disks, basically the same utility just different output.

I received a couple of requests for a utility to just create the program loader menu I've used in Z80onMDR for transfer to disk, so I've created MenuDSK to do this. It can handle up to 20 menu entries using the mock 128k menu style (shown below). It is wrapped in a basic loader and this can then be output to a variety of disk types (PlusD, OPUS, +3) plus also to tape for easy transfer to real drives.

And lastly Z80onTAP to complete the set and a shout out to Massimo Raffaele & Steve for their many suggestions and testing of this version which had a lot more attention than I expected given the abundance of TAP files out there :-)

The Dreaded Screen Corruption and the 4 Stage Loader Solution


The initial Z80onMDR utility had an in-screen launcher code copied from Z80onDSK but a lot smaller. Z80onDSK required a much more complex loader as 3DOS (used to load from disk) makes extensive use of bank 7. This meant the code needed to incorporate restoring page 7 as well as setting all the registers etc... This is not needed for the other Z80on utilities as the other disk, tape or microdrive loaders either use the normal 48k ROM or a swap in small shadow ROM that at most requires a little bit of memory under BASIC. This does push BASIC slightly higher in RAM, but not by much and nothing that needs as radical a restore as the +3 loader does. It is worth noting that 128k machines do also use bank 7 but use of this can be eliminated by loading the snapshot in USR 0 mode.

Even with a smaller m/c code block, putting the code in-screen is still probably the safest place as it is less likely to overwrite an important piece of code, outside of a few snapshots which store code or have the stack on the screen. It also gets around the other issue that you need the decompression code for the main memory outside of the main memory otherwise it would get overwritten. Without a custom loader (difficult with Microdrives) you cannot really load the full main memory in one as there is not enough room, also compressing the main memory means it loads faster. Running this decompression code from the screen gets around this issue, it does however have one big downside... screen corruption.

One solution is to put the decompression code in the printer buffer which sits just above the screen memory, and then only restore the main memory above this code. This works for some snapshots but unfortunately not that many as it seems the printer buffer is well used surprisingly. This lead me to look at a multi-stage launcher, one that would restore the contents of the printer buffer to improve compatibility. An obvious first choice would be to use a gap or same byte sequence in the main memory (usually a sequence of zeros), which may not be used by the snapshot. A big downside is this would be in the main memory which is compressed so only accessible after the decompression. So any code going here needs to be launched from either the screen or the printer buffer which would have the decompression code in it, defeating the objective. If the code in the gap can restore the printer buffer then this would improve compatibly & remove corruption. So the utility was adapted to find a gap, put the launcher & printer buffer restore code in the gap and then compress that with the rest of the main memory. The printer buffer is then needed to just house the decompression code and a jump into the "ingap" code. This worked much better than printer buffer alone but still had compatibility issues as it seems gaps are in fact used, who knew!

Another place to put the code is just below the stack, assuming this is only normally used as an actual stack (not always the case, see later) and therefore safe, at least for a few bytes. To minimise the size of this code the printer buffer and ingap code were still used with the ingap code restoring the printer buffer and the stack code restoring the gap (simple djnz loop). This improved compatibility massively, although there were still some that didn't work.


One reason compatibility wasn't as high as hoped was the stack code was still relatively large at 67bytes and the ingap code even larger which often meant a suitable gap couldn't be found or the stack code overwrote an important part of the main code. Adding an extra stage helped reduce both of these code sizes and the best place for this 4th stage was within the BASIC loader.

The BASIC loader is overwritten when the main memory is decompressed, however, it can still set some of the registers which aren't used in the decompression code (i.e. the alt & ix/iy ones) and also complete some basic set-up including making sure the AY registers were correct which I avoided initially due to space issues. This change allowed the other three parts of code to be reduced in size significantly making the final byte difference between the original snapshot and the converted file a very small 28bytes under the stack. Compatibility was now very high.

  • Stage 1 - in the BASIC REM statement. Set register values for alt hl/bc/de/af, ix/iy, i and 16 AY, correct interrupt mode and sets up the main decompression
  • Stage 2 - in the printer buffer which is run after loading, this contains the main memory decompression from 0x5c36 onwards leaving the 54byte decompression in place
  • Stage 3 - in a continuous byte block in main memory and part of the main memory compression. As such this is only accessible after the main memory is decompression. This contains code to restore the printer buffer (simple ldir), the main memory decompression delta copy (another simple ldir) and a jump into stage 4. If no continuous block can be found this code is placed at the end of the ATTR region of the screen and when restored the best colour is picked to minimise corruption
  • Stage 4 - just under the stack and again compressed with the main memory (unless it was in the stack or printer buffer). This contains the rest of the launcher code and is used restore the gap block (a simple djnz loop copy of same byte) and to set the final registers hl,bc,de,af & r before enabling or disabling interrupts and jumping into the main code. Just 28bytes long.


Compatibility of this new 4 stage loader is high with very few snapshots failing to work. For those that do the original in-screen loader has been retained, and this has also reduced in size by using the new BASIC m/c routine.

Other additions include:

  • Ability to split the stack code if the PC (program counter) is also in the stack. This split left 2bytes (a single pop) under the stack and shifting the other 30bytes below the PC out of the way.
  • If the stack is in the screen (some loaders) it will check the m/c to see if the first m/c command is a LD SP command and if so puts the stage 4 loader there instead of in-screen.
  • Instead of using the stack for Stage 4 you can now use the screen. As the loader is small the corruption is minimal and contained within one pixel line. This does keep the 2bytes below the stack as it needs to do at least one pop command to restore registers af.
  • Combined the final code load with the main code load and adapted new BASIC m/c to move it into the correct place after loading. This will also restore the original screen if using a custom loading screen. If there is no space for the original screen the additional load will remain
  • Ability to add a pause after loading so you can admire the loading screen before either the snapshot launches or it is overwritten with the original screen if using a custom loading screen
  • Ability to force 48k snapshots i.e. don't keep the 128k memory banks. Useful for those incorrectly snapped
  • Ability to enter POKEs while creating the file. Useful for adding infinite lives etc...

Z80onMDR v3.1

Windows, MacM1 & Linux

Version History (latest & major changes only)

  • v1.3 initial release
  • v2.0 file interleaving to dramatically improving loading speed on OqtaDrive & vDrive
  • v3.0 4 Stage Loader with all the new features added
  • v3.1 bug fix for compressed v2+ Z80 snapshots

Z80onTAP v1.2

Windows & Linux (x86)

Version History

  • v1.0 in line with Z80onMDR v3.0 with all the latest features
  • v1.1 added new text loading screen option

Command Line Arguments

+-------------------------------------------------------------------------------
| Z80onMDR v3.0 (c) 2020 Tom Dalby
+-------------------------------------------------------------------------------
| Usage: Z80onMDR [global options] snapshot.z80 [snapshot settings]
|
| [global options]
|   -f NAME - specify Output Filename 
|   -m NAME - specify Microdrive Volume, length 10 alphanumeric only
|             Will truncate if >10 and remove non-alphanumeric chars
|             This will also be the Menu name in batch
|             <Default is take name from output filename (or 1st file)>
|   -s NUM  - # of sectors on Microdrive, min 170 (85kB), max/default 254 (127kB)
|   -o      - override estimated size check if showing Microdrive as oversized
|   -j      - just the snapshots, no run (or run menu) file included
|   -b      - just create a blank mdr, must be used with -m to name the
|             cartridge. If z80 filenames are specified after -b
|             then add a menu to the micordrive with those names but don't
|             include the snapshot. Note you need to put the .z80 after the
|             name and stick to 10 chars maximum or the program will truncate
|   -g NUM  - interleave sector gap: 0(vDrive), default 1(OqtaDrive), max 3
|             0 and 1 are special modes optimised for vDrive & OqtaDrive
|             using 2 & 3 just adds that many gaps between each written sector
|
| [snapshot settings]
|   -n NAME - specify filename, length 10 alphanumeric only.
|             Will truncate if >10 and remove non-alphanumeric chars.
|             <Default is take name from the z80 file>
|   -l FILE - add a custom loading screen. Screen must be in binary .scr format
|             and exactly 6912bytes long.
|   -L FILE  - as -l but doesn't overwrite with original screen at end
|   -c tmbp  - use alternate 2 stage launcher code within the screen/prtbuf,
|              (t)op, (m)iddle, (b)ottom of screen or (p)rtbuf
|   -48k     - force snapshot to 48k i.e. remove 128k pages, bank switching off
|   -b NUM   - override snapshot border colour with NUM, valid 0-7
|   -i NUM   - override loader paper/ink from border colour to NUM, valid 0-7
|   -t "N,V" - enter one or multiple POKEs, max 256. If more than one POKE
|              separate them with a colon. Example -t "23455,23:23456,37"
|   -p NUM   - add NUM 50th/sec PAUSE before final stage, max 999, 0 key press
|   -sos ROW - put the small 4th stage stack launcher on screen rather than
|              under the stack *note 2bytes will still be under the stack
|              ROW=pixel row on screen, 0 top, 191 bottom
|
| Batch Mode is activated if more than one z80 snapshot specified, example:
|
| Z80onMDR -m Games01 snapshot1.z80 -s screen1.scr snapshot2.z80 -n game1
|
| Which creates an MDR containing snapshot 1 & snapshot2. snapshot1 has an
| alternate loading screen, snapshot2 has the filenmae game1 and the output,
| menu & cartridge volume names are all Games01. Max 8 snapshots per cartridge
+-------------------------------------------------------------------------------

Older Versions for Other Systems

Z80onOPD v0.8c

Windows & Linux (x86)

Version History

  • v0.1 initial release
  • v0.2 added double density disk support (360kB) and added filename checks to stop same filename twice
  • v0.3 added double sided double density support (720kB)
  • v0.4 improved bootsector & ROM v2.22 or v2.31 Quick DOS.
  • v0.5 new option to suppress run file creation
  • v0.6 improved menu, v0.7 added joystick selector & bug fix
  • v0.8 special request to add tape output for transfer to real disk
  • v0.8a bug fix, v0.8b improved compression delta handling
  • v0.8c new backwards cost parser which increases compression

Z80onMGT v0.3

Windows & Linux (x86)

Version History

  • v0.1 initial release (this has all the functionality of v0.5 of Z80onOPD)
  • v0.2 improved menu
  • v0.2b bug fix, v0.2c another bug fix
  • v0.2d improved compression delta handling
  • v0.2e new backwards cost parser which increases compression
  • v0.3 fixed issue with files >20 and disk side 2

MenuDSK v0.4

Windows & Linux (x86)

Version History

  • v0.4 initial release

Worked Example


Quick example to show how to convert a .Z80 to MDR

To convert Three Weeks in Paradise type:

z80onmdr "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).z80"

This will create a MDR file with the following output:

+-------------------------------------------------------------------------------
| Z80onMDR v1.3 (c) 2020 Tom Dalby
+-------------------------------------------------------------------------------
| Single Snapshot Mode: "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).z80"
| Microdrive Cartridge Name: "ThreeWeeks" -> Size 127kB [S:0xfe]
| Single Snapshot to transfer, no menu required
| - Writing File: "run       " (BASIC A:10 L:38) #Sectors Used:1
+-------------------------------------------------------------------------------
| Processing: "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).z80"
| - Options -> Screen:Default, Filename:Default, LaunchPos:Default(Top)
| - Z80 Size: 42142bytes
| Z80 Snapshot Decode: [v1-48k-C]
+-----------------+---------------+---------------+---------------+-------------
| a=0x3b          | f=0x08        | bc=0x311a     | hl=0xf72d     | pc=0x0038
| sp=0xfff8       | i=0x3f        | r=0x0e        | bcol=0        | de=0x1113
| bc'=0x8900      | de'=0x0000    | hl'=0x3264    | a'=0x00       | f'=0x45
| iy=$5c3a        | ix=$5bd8      | di            | im 1
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 5(10056) 2(15705) 0(16347)
| - Full Memory-Screen Compressed to: [D3]32098bytes
|   - Copying 3bytes from end of code to end of launcher
| Adding Files to Microdrive Image:
| - Writing File: "ThreeWeeks" (BASIC A:10 L:119) #Sectors Used:1
| - Writing File: "ThreeWee.0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "ThreeWee.1" (CODE S:33438 L:32098) #Sectors Used:63
| - Writing File: "ThreeWee.2" (CODE S:16384 L:137) #Sectors Used:1
| Total bytes written 39266 vs. 42142 ->  7% Saved [#Sectors Left:173]
+-------------------------------------------------------------------------------
| Writing Out "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).mdr"
+-------------------------------------------------------------------------------

The utility creates 5 files on the Cartridge. The first is run which allows you to load the game straight from a reboot by typing RUN and enter. The second is ThreeWeeks which is the basic loader and then 3 code files which are the loading screen, the compressed main code and the final one the launcher code which is put into screen memory as there is nowhere else for it to go.

This Z80 snapshot doesn't come with a loading screen, more the screen is the game screen. In order to have something nicer to look at while loading you can add a custom screen using the -l option:

z80onmdr "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).z80" -l 3weeks.scr

This will create a MDR file with the following output:

+-------------------------------------------------------------------------------
| Z80onMDR v1.3 (c) 2020 Tom Dalby
+-------------------------------------------------------------------------------
| Single Snapshot Mode: "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).z80"
| Microdrive Cartridge Name: "ThreeWeeks" -> Size 127kB [S:0xfe]
| Single Snapshot to transfer, no menu required
| - Writing File: "run       " (BASIC A:10 L:38) #Sectors Used:1
+-------------------------------------------------------------------------------
| Processing: "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).z80"
| - Options -> Screen:"3weeks.scr", Filename:Default, LaunchPos:Default(Top)
| - Z80 Size: 42142bytes (+Additional Screen 6912bytes)
| Z80 Snapshot Decode: [v1-48k-C]
+-----------------+---------------+---------------+---------------+-------------
| a=0x3b          | f=0x08        | bc=0x311a     | hl=0xf72d     | pc=0x0038
| sp=0xfff8       | i=0x3f        | r=0x0e        | bcol=0        | de=0x1113
| bc'=0x8900      | de'=0x0000    | hl'=0x3264    | a'=0x00       | f'=0x45
| iy=$5c3a        | ix=$5bd8      | di            | im 1
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 5(10056) 2(15705) 0(16347)
| - Full Memory-Screen Compressed to: [D3]32098bytes
|   - Copying 3bytes from end of code to end of launcher
| Adding Files to Microdrive Image:
| - Writing File: "ThreeWeeks" (BASIC A:10 L:119) #Sectors Used:1
| - Writing File: "ThreeWee.0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "ThreeWee.1" (CODE S:33438 L:32098) #Sectors Used:63
| - Writing File: "ThreeWee.2" (CODE S:16384 L:6912) #Sectors Used:14
| Total bytes written 46041 vs. 49054 ->  6% Saved [#Sectors Left:160]
+-------------------------------------------------------------------------------
| Writing Out "Three Weeks in Paradise (1986)(Mikro-Gen)(48K-128K).mdr"
+-------------------------------------------------------------------------------

Notice the final file written is now 6912bytes long, this is the game screen with the launcher imbedded already. The previous example was only 137bytes long as it just required the launcher code.

For 128k snapshots the process is the same, the utility will just create a few more files to cover the additional memory banks.

Let us try Chase HQ 128k. Again type:

z80onmdr "Chase H.Q. (1989)(Ocean)(128K)[a].z80" -n ChaseHQ

You will notice I added a new option -n. This simply renames the files on the Cartridge to ChaseHQ instead of taking it from the input which would've been ChaseHQ198 which isn't as nice. The output is now:

+-------------------------------------------------------------------------------
| Z80onMDR v1.3 (c) 2020 Tom Dalby
+-------------------------------------------------------------------------------
| Single Snapshot Mode: "Chase H.Q. (1989)(Ocean)(128K)[a].z80"
| Microdrive Cartridge Name: "ChaseHQ198" -> Size 127kB [S:0xfe]
| Single Snapshot to transfer, no menu required
| - Writing File: "run       " (BASIC A:10 L:38) #Sectors Used:1
+-------------------------------------------------------------------------------
| Processing: "Chase H.Q. (1989)(Ocean)(128K)[a].z80"
| - Options -> Screen:Default, Filename:"ChaseHQ   ", LaunchPos:Default(Top)
| - Z80 Size: 109247bytes
| Z80 Snapshot Decode: [v3(54)-128k]
+-----------------+---------------+---------------+---------------+-------------
| a=0x00          | f=0x54        | bc=0x0000     | hl=0x5d0a     | pc=0x1f3d
| sp=0x61a2       | i=0x3f        | r=0x2e        | bcol=0        | de=0x5d0f
| bc'=0x1721      | de'=0x369b    | hl'=0xf8ad    | a'=0x00       | f'=0x44
| iy=$5c3a        | ix=$03d4      | ei            | im 1          | 0x7ffd=0x10
+-----------------+---------------+---------------+---------------+-------------
| AY Chip Registers Set-up        | 0xfffd=0x08   | ay1=0x00      | ay2=0x00
| ay3=0x00        | ay4=0x00      | ay5=0x00      | ay6=0x00      | ay7=0x00
| ay8=0xff        | ay9=0x00      | ay10=0x00     | ay11=0x00     | ay12=0x00
| ay13=0x00       | ay14=0x00     | ay15=0xff     | ay16=0x00
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 0(8314) 1(13548) 2(16384) 3(15870) 4(14291) 5(13848) 6(13673) 7(13209)
| - Full Memory-Screen Compressed to: [D3]33503bytes
|   - Copying 3bytes from end of code to end of launcher
| - Additional 128k Memory Compression:
|   - Page 1 Compressed to: 11223bytes + 77 for unpack code
|   - Page 3 Compressed to: 12162bytes
|   - Page 4 Compressed to: 11556bytes
|   - Page 6 Compressed to: 11000bytes
|   - Page 7 Compressed to: 10480bytes
| Adding Files to Microdrive Image:
| - Writing File: "ChaseHQ   " (BASIC A:10 L:211) #Sectors Used:1
| - Writing File: "ChaseHQ .0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "ChaseHQ .1" (CODE S:32179 L:11300) #Sectors Used:23
| - Writing File: "ChaseHQ .2" (CODE S:32255 L:12162) #Sectors Used:24
| - Writing File: "ChaseHQ .3" (CODE S:32255 L:11556) #Sectors Used:23
| - Writing File: "ChaseHQ .4" (CODE S:32255 L:11000) #Sectors Used:22
| - Writing File: "ChaseHQ .5" (CODE S:32255 L:10480) #Sectors Used:21
| - Writing File: "ChaseHQ .6" (CODE S:32033 L:33503) #Sectors Used:66
| - Writing File: "ChaseHQ .7" (CODE S:16384 L:137) #Sectors Used:1
| Total bytes written 97261 vs. 109247 -> 11% Saved [#Sectors Left:57]
+-------------------------------------------------------------------------------
| Writing Out "Chase H.Q. (1989)(Ocean)(128K)[a].mdr"
+-------------------------------------------------------------------------------

Finally the utility can create compilations with a nice menu screen, see right.

To do this you just need to put the .Z80 names in the command line one after each other. The following example creates a compilation Cartridge called UPtG 01 with a few well known games on it

To create the compilation type:

./z80onmdr -m "UPtG 01" "Cookie (1983)(Ultimate Play The Game)(16K).z80" -n Cookie "Jetpac (1983)(Ultimate Play The Game)(16K).z80" -n JetPac "Pssst (1983)(Ultimate Play The Game)(16K).z80" -n PSSST "Tranz Am (1983)(Ultimate Play The Game)(16K).z80" -n TranzAm

+-------------------------------------------------------------------------------
| Z80onMDR v1.3 (c) 2020 Tom Dalby
+-------------------------------------------------------------------------------
| Entering Batch Mode:
| 1) "Cookie (1983)(Ultimate Play The Game)(16K).z80" [49182bytes]
| 2) "Jetpac (1983)(Ultimate Play The Game)(16K).z80" [14636bytes]
| 3) "Pssst (1983)(Ultimate Play The Game)(16K).z80" [15318bytes]
| 4) "Tranz Am (1983)(Ultimate Play The Game)(16K).z80" [14205bytes]
+-------------------------------------------------------------------------------
| Microdrive Cartridge Name: "UPtG 01   " -> Size 127kB [S:0xfe]
| 4 Snapshots to transfer, building menu
| - Writing File: "run       " (BASIC A:10 L:476) #Sectors Used:1
+-------------------------------------------------------------------------------
| Batch #1 -->
| Processing: "Cookie (1983)(Ultimate Play The Game)(16K).z80"
| - Options -> Screen:Default, Filename:"Cookie    ", LaunchPos:Default(Top)
| - Z80 Size: 49182bytes
| Z80 Snapshot Decode: [v1-48k-U]
+-----------------+---------------+---------------+---------------+-------------
| a=0x50          | f=0x4c        | bc=0x0700     | hl=0x408e     | pc=0x749a
| sp=0x5ef8       | i=0x3f        | r=0x00        | bcol=0        | de=0x6373
| bc'=0x0080      | de'=0x635f    | hl'=0x588e    | a'=0x80       | f'=0x47
| iy=$5c3a        | ix=$5c7a      | di            | im 1
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 5(16384) 2(16384) 0(16384)
| - Full Memory-Screen Compressed to: [D3]7520bytes
|   - Copying 3bytes from end of code to end of launcher
| Adding Files to Microdrive Image:
| - Writing File: "Cookie    " (BASIC A:10 L:119) #Sectors Used:1
| - Writing File: "Cookie  .0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "Cookie  .1" (CODE S:58016 L:7520) #Sectors Used:15
| - Writing File: "Cookie  .2" (CODE S:16384 L:137) #Sectors Used:1
| Total bytes written 14688 vs. 49182 -> 70% Saved [#Sectors Left:221]
+-------------------------------------------------------------------------------
| Batch #2 -->
| Processing: "Jetpac (1983)(Ultimate Play The Game)(16K).z80"
| - Options -> Screen:Default, Filename:"JetPac    ", LaunchPos:Default(Top)
| - Z80 Size: 14636bytes
| Z80 Snapshot Decode: [v1-48k-C]
+-----------------+---------------+---------------+---------------+-------------
| a=0x00          | f=0xdc        | bc=0x0000     | hl=0x5e6a     | pc=0x0038
| sp=0x5ff8       | i=0x3f        | r=0x36(b7)    | bcol=0        | de=0x5e6f
| bc'=0x1021      | de'=0x369b    | hl'=0x0000    | a'=0xff       | f'=0x01
| iy=$5c3a        | ix=$5b8e      | di            | im 1
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 5(13834) 2(ovf:16576)(261) 0(507)
| - Full Memory-Screen Compressed to: [D3]8020bytes
|   - Copying 3bytes from end of code to end of launcher
| Adding Files to Microdrive Image:
| - Writing File: "JetPac    " (BASIC A:10 L:119) #Sectors Used:1
| - Writing File: "JetPac  .0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "JetPac  .1" (CODE S:57516 L:8020) #Sectors Used:16
| - Writing File: "JetPac  .2" (CODE S:16384 L:137) #Sectors Used:1
| Total bytes written 15188 vs. 14636 ->  4% Larger [#Sectors Left:189]
+-------------------------------------------------------------------------------
| Batch #3 -->
| Processing: "Pssst (1983)(Ultimate Play The Game)(16K).z80"
| - Options -> Screen:Default, Filename:"PSSST     ", LaunchPos:Default(Top)
| - Z80 Size: 15318bytes
| Z80 Snapshot Decode: [v1-48k-C]
+-----------------+---------------+---------------+---------------+-------------
| a=0x00          | f=0xdc        | bc=0x0000     | hl=0x5dbc     | pc=0x0038
| sp=0x5ee4       | i=0x3f        | r=0x1c(b7)    | bcol=7        | de=0x5dc1
| bc'=0x0821      | de'=0x369b    | hl'=0x0000    | a'=0xff       | f'=0x01
| iy=$5c3a        | ix=$5c7a      | di            | im 1
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 5(ovf:16635)(14531) 2(ovf:16571)(256) 0(497)
| - Full Memory-Screen Compressed to: [D3]8399bytes
|   - Copying 3bytes from end of code to end of launcher
| Adding Files to Microdrive Image:
| - Writing File: "PSSST     " (BASIC A:10 L:119) #Sectors Used:1
| - Writing File: "PSSST   .0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "PSSST   .1" (CODE S:57137 L:8399) #Sectors Used:17
| - Writing File: "PSSST   .2" (CODE S:16384 L:137) #Sectors Used:1
| Total bytes written 15567 vs. 15318 ->  2% Larger [#Sectors Left:156]
+-------------------------------------------------------------------------------
| Batch #4 -->
| Processing: "Tranz Am (1983)(Ultimate Play The Game)(16K).z80"
| - Options -> Screen:Default, Filename:"TranzAm   ", LaunchPos:Default(Top)
| - Z80 Size: 14205bytes
| Z80 Snapshot Decode: [v1-48k-C]
+-----------------+---------------+---------------+---------------+-------------
| a=0x00          | f=0xdc        | bc=0x0000     | hl=0x5da6     | pc=0x0038
| sp=0x5ef8       | i=0x3f        | r=0x0c(b7)    | bcol=0        | de=0x5dab
| bc'=0x0f21      | de'=0x369b    | hl'=0x0000    | a'=0xff       | f'=0x01
| iy=$5c3a        | ix=$5c7a      | di            | im 1
+-----------------+---------------+---------------+---------------+-------------
| Extracting Pages from Z80:
| - 5(13416) 2(ovf:16575)(260) 0(495)
| - Full Memory-Screen Compressed to: [D3]8577bytes
|   - Copying 3bytes from end of code to end of launcher
| Adding Files to Microdrive Image:
| - Writing File: "TranzAm   " (BASIC A:10 L:119) #Sectors Used:1
| - Writing File: "TranzAm .0" (CODE S:16384 L:6912) #Sectors Used:14
| - Writing File: "TranzAm .1" (CODE S:56959 L:8577) #Sectors Used:17
| - Writing File: "TranzAm .2" (CODE S:16384 L:137) #Sectors Used:1
| Total bytes written 15745 vs. 14205 -> 11% Larger [#Sectors Left:123]
+-------------------------------------------------------------------------------
| Writing Out "UPtG01.mdr"
+-------------------------------------------------------------------------------