formats index
*** DiskPacked ZipCode (4 or 5 file version, 1!xxxxxx, 2!xxxxxx, etc)
** Document revision 1.1
This format works directly on D64 images only. It is a compressed form of
a 1541 disk (or a D64 file) and is typically comprised of 4 files for a 35
track disk. The 5-file version is for 40-track images, and is a Joe
Forster/STA extension of the standard. This form of the ZipCode format
can't be used to store disks with errors on them, as there are no
provisions for error bytes. It is strictly a compressed sector copy of a
disk.
The following chart shows the filenames, range of tracks and the total
sectors that each one contains:
FileName Track Range Block Count
-------- ----------- -----------
1!xxxxxx 1 - 8 168 sectors
2!xxxxxx 9 - 16 168 sectors
3!xxxxxx 17 - 25 172 sectors
4!xxxxxx 26 - 35 175 sectors
5!xxxxxx 36 - 40 85 sectors (valid only for 40 track disk images)
This format uses sector interleaving to read the disk. It reads each
sector using an interleave of -10 for even #'s sectors (0,2,4...) and +11
for odd numbered sectors (1,3,5...). The actual value for both interleaves
varies as we progress further into the disk. At track 18, it goes to -9 for
evens and +10 for odds, and at track 25 it changes to -8 for evens and +9
for odds. This is important to better understand the layout, as it means
the sectors are *not* stored in order (0,1,2...), but the changing
interleave makes reading/writing the sectors much faster. This also means
that in order to reconstruct each track, a buffer of memory the size of the
largest track (track 1, 21 sectors*256 bytes = 5.25 kbytes) must be set
aside, and the sector information copied into the appropriate area until
the whole track is assembled.
Here is a partial HEX dump of the first file and description of the layout.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
-----------------------------------------------
0000: FE 03 36 34 41 00 00 41 0B 00 41 01 00 41 0C 00
0010: 41 02 00 41 0D 00 41 03 00 41 0E 00 41 04 00 41
0020: 0F 00 41 05 00 41 10 00 41 06 00 81 11 33 02 00
0030: 2F 80 25 9D FA 66 AF 9B 6A 14 A0 E4 10 CA 18 90
0040: 7B 67 51 47 92 2B 4C 52 83 78 01 A9 58 D0 31 70
0050: 34 30 B7 85 2C D4 9F 1C 1F A9 EA EA EA 15 3E 02
0060: D0 00 41 07 00 41 12 00 41 08 00 41 13 00 41 09
Byte: $00-01: Load address, low/high byte. If the load address is $03FE
then we have the DISK ID following immediately after. If
it's $0400, then no DISK ID follows.
02-03: Disk ID, only if the load address is $0400.
From here on, the format can vary, depending on the contents of each
sector. The next two bytes contain the track/sector, but the track value
now includes the compression method, contained on the top two bits...
Bit: 76543210
xxyyyyyy
^^| |
| ------
| ^
| |
| |
| These are the track bits.
|
These are the compression flags
Since the track range is from 1-35, only the bottom 5 bit are used. This
leaves the top two empty, and usable. Here is their usage:
00 - No compression, the sector is stored in full. The next 256 bytes
contain the full sector information.
01 - Sector is filled with *one* character. The next character is the
fill byte. Repeat it 256 times, and fill the sector.
10 - Sector is compressed using RLE compression (see below for details)
11 - Unused
Lets look at each method of storing a sector with different compression
methods, using the above example...
00: This is the simplest method, as it entails no compression. All we
have is a track and sector value, and 256 bytes of data follow it.
01: At byte 04 we have 41 00 00. Breaking down $41 to binary we have
"01000001". The top two bits indicate we have type 01 compression
(fill sector), and the bottom 6 indicate we have track 1. The next
byte is the sector ($00), and the next byte is also a $00, indicating
this sector is completely filled with $00.
0000: .. .. .. .. 41 00 00 41 0B 00 41 01 00 41 0C 00
0010: 41 02 00 41 0D 00 41 03 00 41 0E 00 41 04 00 41
10: The RLE encoding takes some explanation. RLE stands for "Run Length
Encoding", and is simply a means of encoding a series of the same
numbers into a much smaller string (i.e. encoding the 1's in the
string "0456111111111645" into something much shorter).
Looking at the example below, when we encounter a "10" type, we have
track ($81, meaning track 1), sector ($11), the length of the encoded
string $33 (51 decimal) and a REP code, a unique byte used as a flag
to show when we encounter an encoded repeated string. The REP code is
a single byte whose value doesn't occur in the decoded sector. It is
typically the first unused value starting from 0, but in practice it
can be anything, it simply must be an unused value.
0020: .. .. .. .. .. .. .. .. .. .. .. 81 11 33 02 00
0030: 2F 80 25 9D FA 66 AF 9B 6A 14 A0 E4 10 CA 18 90
0040: 7B 67 51 47 92 2B 4C 52 83 78 01 A9 58 D0 31 70
0050: 34 30 B7 85 2C D4 9F 1C 1F A9 EA EA EA 15 3E 02
0060: D0 00 .. .. .. .. .. .. .. .. .. .. .. .. .. ..
We know with this example that the encoded data is 51 bytes long
($33), and with a REP code of $02, whenever we encounter a $02, we
have an encoded sequence. If we do not encounter a $02, we have
normal bytes. In the above sequence, we do not encounter a $02 until
$005F, so all the rest are normal bytes, which would go into the
sector starting at position $00.
Once we hit a $02, the next two bytes are encoded this way... repeat
count ($D0, decimal 208) and byte to repeat ($00). So we fill the
next 208 ($D0) bytes with $00's.
If you add up what we had before the $02, it was 48 bytes long, add
this to the 208 bytes and we have a full sector of 256 bytes. A
256-byte sector stored in 55 (51 + 4 byte header) bytes represents a
good savings.
Notice the byte sequence in the above example 'EA EA EA'. Why was
this not encoded? Simple. The encoding sequence (REP, LENGTH, CHAR)
takes three bytes. It would not make any sense to encode something
which is no shorter than the original string. ZipCode will only
encode a repeated string of 4 bytes or longer.
Now, lets break down the above sample into its encoded parts, to see
how its made...
0000: FE 03 - Load Address
0002: 36 34 - Disk ID
0004: 41 00 00 - T/S 1,00, fill $00
0007: 41 0B 00 - T/S 1,11, fill $00
000A: 41 01 00 - T/S 1,01, fill $00
000D: 41 0C 00 - T/S 1,12, fill $00
0010: 41 02 00 - T/S 1,02, fill $00
0013: 41 0D 00 - T/S 1,13, fill $00
0016: 41 03 00 - T/S 1,03, fill $00
0019: 41 0E 00 - T/S 1,14, fill $00
001C: 41 04 00 - T/S 1,04, fill $00
001F: 41 0F 00 - T/S 1,15, fill $00
0022: 41 05 00 - T/S 1,05, fill $00
0025: 41 10 00 - T/S 1,16, fill $00
0028: 41 06 00 - T/S 1,06, fill $00
002B: 81 11 33 02 - T/S 1,17, RLE, length 51 bytes, REP byte $02
00 2F 80 25 - Normal data
9D FA 66 AF
9B 6A 14 A0
E4 10 CA 18
90 7B 67 51
47 92 2B 4C
52 83 78 01
A9 58 D0 31
70 34 30 B7
85 2C D4 9F
1C 1F A9 EA
EA EA 15 3E
005F: 02 D0 00 - REP byte found, repeat 208, fill with $00
0062: 41 07 00 - T/S 1,07, fill $00
0065: 41 12 00 - T/S 1,18, fill $00
This listing is basically what you would see if you ran CheckZipCode from
inside 64COPY. It will dump out the ZipCode files into their constituent
parts, so you can see how the file is made, and if any errors exist.
The 4 and 5 file ZipCode format can't be used to store disks with errors
on them, as there are no provisions for error bytes. It is strictly a
compressed sector copy of a disk.
There is no benefit for using ZipCode as it is only used for making disks
easier to upload/download (for a BBS) or store. It is not a format that any
of the emulators use directly. You can find utilites for the PC to undo and
create the images, if you need to.
ÿ