*** 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.