Commodore 64 Disk Tutorial - Written by Cyberonix in 1999
---------------------------------------------------------

A standard Commodore 64 disk (and .D64 image for that matter) contains 35
tracks.  These tracks run consecutively from the outside of the disk toward the
center.  Each track contains a fixed number of sectors.  The sectors are as
follows:

   Track: 01-17 Number of Sectors: 21 (0 - 20)
   Track: 18-24 Number of Sectors: 19 (0 - 18)
   Track: 25-30 Number of Sectors: 18 (0 - 17)
   Track: 31-35 Number of Sectors: 17 (0 - 16)

Notice the number of sectors decreases as the track number increases.  If you
imagine looking at a 5.25 inch disk you see that track 1 is on the outside of
the disk and has a much large circumference than track 35 which resides near the
hole in the center of the disk. All sectors are ZERO based which means if you
were going through the sectors on track 1 you would start with sector 0 up to
sector 20 (not 21) for a total of 21 sectors. Each sector contains 256 bytes so
let's do some math:

   Tracks  Bytes/Sector    # of Sectors   # of Tracks    Total
   01-17:      256      *     21        *     17      =  91392
   18-24:      256      *     19        *      7      =  34048
   25-30:      256      *     18        *      6      =  27648
   31-35:      256      *     17        *      5      =  21760
                                                        -------
                                                        174848 bytes

This is the total number of bytes for a Commodore disk and also the same number
of bytes of a standard .D64 disk image.

No that we know how many tracks and sectors a disk contains let get into the
good stuff.  We will start with a regular disk image and then discuss how zips
work.

Disk Image:
-----------

A disk image (or actual Commodore 64 disk) is nothing more than a series of
bytes strung together to form the disk.  The physical location of a byte on the
disk determines which track and sector it is in.  Track 18 is generally reserved
for holding file information.  This is the track that is read whenever you do a
LOAD"$",8.  It not only shows you which files are on the disk but also tells the
computer where to physically find those files on the disk. When you load a file
track 18 tells the computer "Go to this location on the disk and start loading
your file". This is a VERY simply overview and the only thing you really need to
remember is a disk is nothing more than a series of bytes strung together to
form tracks and sectors.  If you would like a more comprehensive understanding
of how disks work check out:
http://www.devili.iki.fi/Computers/Commodore/articles/Disk_Tricks/index.html

Zipcode Files
-------------

Zipcode files are files that contain all the information from a Commodore disk
but in a compressed format.  These file are denoted by a number and exclamation
mark. I.e. 1!... 2!... 3!... 4!...  In order to get from a disk image file to
zip files we need to understand a few things about the structure of zip files.

1.  Zip files contain the following information:
      1!Filename contains tracks 01-08.
      2!Filename contains tracks 09-16.
      3!Filename contains tracks 17-25.
      4!Filename contains tracks 26-35.

2.  Each zip file contain a sector by sector representation of the disk.

3.  The first 4 bytes of 1!Filename contains the header $343603FE.
    The first 2 bytes of 2!Filename contains the header $0400.
    The first 2 bytes of 3!Filename contains the header $0400.
    The first 2 bytes of 4!Filename contains the header $0400.
    All other bytes in the files contain the actual disk information.

4.  Each sector is stored in one of three ways depending on compression.
    Case 1: Some bytes repeat.  There are enough of the same bytes in a row to
            compress.  The sector is written as: Track/CompressionType | Sector |
            #BytesUntilNextSector | RepeatValue | Data.
    Case 2: All bytes are the same. The sector is written as: Track/Compression
            Type | Sector | Data.
    Case 3: All bytes are unique.  There are not enough of the same bytes in a
            row to compress.  The sector is written as: Track | Sector | Data.

5.  Compression types are determined as follows:
      if Track and 128 = 128 then we have some compression (Case 1).
      if Track and 64 = 64 then we have total compression (Case 2).
      else we have no compression (Case 3).

6.  The track number can be determined as follows:
      Track and 63 = actual track number regardless of compression type.

Confused yet?  You won't be with the following examples.

-----------------------------------------------------------------
First lets go from a zip file to a disk image file (zip -> .D64):
-----------------------------------------------------------------
  Lets pretend we opened the zip file 1!GameName in a hex editor and read 264
  bytes as follows: (Why 264 bytes and not 256 bytes like a sector contains?
  Because a zip file can contain more or less than 256 bytes depending on
  compression.  264 bytes is the number I counted until we reach the next track).

      FE03 3634 0100 4D53 A901 202E 03A9 028D
      0E18 78A9 1A8D 0218 A908 8D00 18A9 0185
      F9A0 0198 203E 0320 5204 20AA 04A9 828D
      0E18 5860 A000 A200 CAD0 FD88 D0FA 38E9
      01D0 F560 8480 8581 A900 857F 58A9 808D
      9802 2060 D478 A604 E001 D001 CAE0 0BD0
      1EA5 16A4 17CD EB04 D007 CCEC 04D0 10F0
      0ACD ED04 D009 CCEE 04D0 04A2 0186 04E0
      0060 A246 60BC 8005 8CEA 0418 7D00 05BC
      4005 F0EE D986 0490 0738 F986 04C8 D0F4
      48AD EA04 F01B C901 D00D ADEB 0485 12AD
      EC04 8513 4CBB 03AD ED04 8512 ADEE 0485
      1368 4C3E 03A9 088D 0018 868B A207 AD00
      1829 ED26 8B90 0209 028D 0018 4908 8D00
      1849 0826 8B2C 0018 10FB 8D00 1829 ED90
      0209 022C 0018 30FB 8D00 1849 088D 0018
      CAD0 DE49 082C 810B

  Notice the first four bytes $FE033634 are the header.  This is the same four
  bytes mentioned under number 3 but are written in Little Endian (byte
  swapped) format.  This is how the computer writes $343603FE to disk.  Removing
  those four bytes we are left with:

                0100 4D53 A901 202E 03A9 028D  01 = Track 00 = Sector 4D = Data
      0E18 78A9 1A8D 0218 A908 8D00 18A9 0185
      F9A0 0198 203E 0320 5204 20AA 04A9 828D
      0E18 5860 A000 A200 CAD0 FD88 D0FA 38E9
      01D0 F560 8480 8581 A900 857F 58A9 808D
      9802 2060 D478 A604 E001 D001 CAE0 0BD0
      1EA5 16A4 17CD EB04 D007 CCEC 04D0 10F0
      0ACD ED04 D009 CCEE 04D0 04A2 0186 04E0
      0060 A246 60BC 8005 8CEA 0418 7D00 05BC
      4005 F0EE D986 0490 0738 F986 04C8 D0F4
      48AD EA04 F01B C901 D00D ADEB 0485 12AD
      EC04 8513 4CBB 03AD ED04 8512 ADEE 0485
      1368 4C3E 03A9 088D 0018 868B A207 AD00
      1829 ED26 8B90 0209 028D 0018 4908 8D00
      1849 0826 8B2C 0018 10FB 8D00 1829 ED90
      0209 022C 0018 30FB 8D00 1849 088D 0018
      CAD0 DE49 082C 810B ....                 2C = End Data 810B = Next Sector

  Next we read the first byte.  This is the track number. First we find out if
  it is a valid track number by ANDing it with 63.

    Does $01 and 63 = 01?  Yes.  It is a valid track.  If not the zip file is
    corrupt.

  Second we find out if it has any compression by performing the following ANDs:

    Does $01 and 128 = 128? No.. we don't have PARTIAL compression.
    Does $01 and 64 = 64? No.. we don't have FULL compression either.
    Therefore $01 must be an uncompressed track.  Of course if you know you are
    reading track one and the actual byte is $01 then you probably already know
    this sector is not compressed just by looking at it.

  The next byte we read is $00.  This is the sector number.  If this number is
  ever greater than the maximum number of sector for that particular track then
  the zip file is corrupt.

  Since this is an uncompressed sector we know we must read 256 bytes of data
  (remember each sector contains 256 bytes).  This would be from $4D to $2C as
  shown above. Then take those bytes and write them to the image file.

  We have successfully read the first sector of track 1.  Let read the next.

      810B E706 0018 10FB 8D00 182C 0018 30FB  81 = Track 0B = Sector
      6020 E104 58AD 0018 10FB 78A9 008D 0018
      A208 A008 AD00 1830 FBA9 E018 6901 D0FB
      AD00 188C 0018 6A26 8BAD 0018 10FB A900
      8D00 18CA D0DE AD00 1830 FBA9 088D 0018
      20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
      01A2 0486 F9A9 0220 3E03 A000 A200 BD00
      07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
      0007 9980 05E8 C8D0 E560 0612 1500 0606
      1306 0612 0605 11A9 0485 F920 0D04 C9FF
      F01A 4820 0D04 A868 AA98 207F 0308 20BF
      0328 D0E3 A907 20D0 044C AA04 608D DA04
      A000 20E1 04BE 0010 20BF 03C8 D0F7 AD00
      1C49 088D 001C 6000 5041 574E 0006 05A0
      0020 FE01 A6DC 01AC E90E 00

  Reading the first byte we get $81.  Check for a valid track.
    Does $81 and 63 = 1? Yes.  It is a valid track.

  Now check for compression.

    Does $81 and 128 = 128? Yes.. This is a PARTIALLY compressed sector.  There
    is no need to perform any more ANDs for this sector.

  Reading the next byte gives us $0B (11 decimal) for the sector.  Why doesn't
  it read 01 when we just read sector 00?  Zip files alternate sectors.  Below
  is the breakdown of how a zip file packs a track and sectors:

    Track 01-17    Sectors: 0/11      Track 18-24    Sectors: 0/10
                            1/12                              1/11
                            2/13                              2/12
                            3/14                              3/13
                            4/15                              4/14
                            5/16                              5/15
                            6/17                              6/16
                            7/18                              7/17
                            8/19                              8/18
                            9/20                              9
                            10

    Track 25-30    Sectors: 0/9       Track 31-35    Sectors: 0/9
                            1/10                              1/10
                            2/11                              2/11
                            3/12                              3/12
                            4/13                              4/13
                            5/14                              5/14
                            6/15                              6/15
                            7/16                              7/16
                            8/17                              8

  So a zip track is laid out as: Track 1 Sector 0 Track 1 Sector 11 Track 1
  Sector 1 etc. This poses a little problem because disk files are laid out
  consecutively as: Track 1 Sector 0 Track 1 Sector 1 Track 1 Sector 2...  You
  have to actually write ahead in the disk image.  For example when I read
  Track 1 Sector 0 this gets written to the disk as the first 256 bytes.  Next
  when I read sector $0B (11 decimal) this means the data needs to be written
  256 bytes per sector * 11 sectors away = 2816 bytes later (and not at position
  257) in the file so you need a way to alternate between the lower and upper
  sectors. Review my code to see how to do this.

  Since this sector is partially compressed the next byte we read is the number
  of bytes until we reach the next sector.  In this case it is $E7 (231 decimal).
  There are 231 bytes until the next sector begins.

  The next sector read is $06.  This is a byte that wasn't present in the
  original disk file sector.  It is used to mark the start of a compressed series of
  bytes.

  The rest of the bytes are data but need to be read as follow:
    1. Read byte by byte until reaching the next sector (231 bytes in this case).
    2. If the byte just read doesn't equal the repeat marker ($06) then write it
       to the disk image file.
    3. If the byte does match the repeat marker then:
       A. Don't write that byte because it is only a marker, but instead read
          the next byte in the sector.  This byte is the number of times the
          data byte should be written.
       B. Read the next byte.  This is the actual byte to be written however
          many time as specified in A above.
    4. Repeat 1-3 until you reach the next sector.

  So lets run through this with a real example.  The output below is the same as
  above just reproduced so you don't have to keep moving to the top of the doc.

  First we read $81.  This is track 1 with some compression.  Next we read the
  sector of $0B.  We know we are working with track 1, sector 11.  Third, we
  read $E7 which is the number of bytes until the next sector.  Fourth, we read
  $06 which is the value to notify us of upcoming compressed bytes.  Now we start
  on the actual data.  The next byte is $00.  Not a repeating byte so write it
  to the disk image.  If you scan from 0018 until E560 there are no repeating
  bytes so you would write each one of these to the image.  After E560 we read
  $06.  This is our repeat notification.  Do not write this byte to the disk.
  Instead read the next byte which is $12 (18 decimal). Read the next byte which
  is $15.  This means we write the byte $15 18 times to the disk image.  Now
  read the next byte.  It is $00. Not a repeating byte so it gets written to the
  disk image.  The next byte is $06.  Follow the same procedure above to write
  the repeating number of byte.  Continue this way until you reach the end of
  the sector.  Simple huh?

      810B E706 0018 10FB 8D00 182C 0018 30FB  81 = Track 0B = Sector E7 = End Data
                                               06 = Repeat Notice
      6020 E104 58AD 0018 10FB 78A9 008D 0018
      A208 A008 AD00 1830 FBA9 E018 6901 D0FB
      AD00 188C 0018 6A26 8BAD 0018 10FB A900
      8D00 18CA D0DE AD00 1830 FBA9 088D 0018
      20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
      01A2 0486 F9A9 0220 3E03 A000 A200 BD00
      07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
      0007 9980 05E8 C8D0 E560 0612 1500 0606  06 = Repeating bytes ahead
      1306 0612 0605 11A9 0485 F920 0D04 C9FF
      F01A 4820 0D04 A868 AA98 207F 0308 20BF
      0328 D0E3 A907 20D0 044C AA04 608D DA04
      A000 20E1 04BE 0010 20BF 03C8 D0F7 AD00
      1C49 088D 001C 6000 5041 574E 0006 05A0
      0020 FE01 A6DC 01AC E90E 0041 0113 ....  0E00 = End Data 41 = Next Track

  Assume you have just read $E7 (231 decimal) bytes and reached the end of sector
  $0B.

  Reading the next byte gives us $41. Lets check for a valid track number:
    Does $41 AND 63 = 1 (remember we are still on track 1)? Yes.. it is a valid
    track.

  What type of compression does it have:
    Does $41 AND 128 = 128? No.. It isn't partially compressed.
    Does $41 AND 64 = 64? Yes.. We have total compression. There is no need to
    check for anything else.

  Looking above we read the next byte.  It is $01.  This is our sector number.

  Since we know this entire sector contains the same value the next byte we read
  is what we write 256 times.  In this case the value is $13.  This ends this
  sector and starts the next.  These are the three cases (types of compression)
  found in a zip file and how to read them.  If you aren't sure what I mean or
  you would like more practice simply open a zip file and follow it through for
  a while using the steps above.

----------------------------------------------------------
Now lets go from a disk image to a zip file (.D64 -> zip):
----------------------------------------------------------
  This is just a little more complicated than going from a zip to a disk.
  Remember the track/sector layout is the same as above.  Just keep this in
  mind as we write the sector.

  1. Remember if you are starting to write the zip file don't forget to include
     the header.  $343603FE for 1!... and $0400 for files 2!.. 3!.. 4!..
  2. After opening the .D64 file read the first 256 bytes (1 sector).
  3. Scan those bytes for any equal values that run consecutively.
     There are two things to look for in compression:
       A. A series of 6 or more bytes means the sector can be compressed.
       B. If you don't have at least one series of 6 or more bytes but you do
          have two or three series of 4 or 5 bytes then you can still compress.

     There reason for this is simple.  A partially compressed sector is written
     as follows (how the bytes are stored):

       Track/Compression | Sector | #BytesUntilNextSector | RepeatNotice |...Data.

     In the actual data a compressed section is stored as:

       RepeatNotice | HowManyTimeToRepeat | ValueToBeRepeated.

     So you can see we have 2 extra bytes to store in the zip file:
     (#BytesUntilNextSector | RepeatNotice).  A standard uncompressed track is
     only (Track | Sector |...Data).
     If we have 6 of the same bytes in order, when compressed this number saves
     us more bytes than the 2 needed to setup a compressed sector so it is worth
     it to compress the series.  Example: suppose we write the sector without
     compression.  Then this series of 6 bytes take up 6 bytes in the zip file.
     This is nothing mystical.  If we compress it lets see what happens.  Right
     off the bat it take 2 extra bytes to setup a compressed sector.  Now we
     know all repeating sets of bytes can be compressed into 3 bytes.  2 bytes
     for the setup + 3 bytes after compression = 5 bytes written to the zip
     file.  We just saved a byte. Now lets lets take that same example but lets
     use 5 bytes instead of 6. If we write the bytes as uncompressed data we add
     5 bytes to the zip file.  If we compress it then we get 2 bytes for the
     setup + 3 bytes after compression = 5 bytes.  We have no savings.  However
     if later on in the sector we come across another set of 4 we get 2 bytes
     for the setup + 3 bytes after first set is compressed + 3 bytes after the
     second set is compressed = 8 bytes written where as two uncompressed
     sections of 4 or 5 bytes would be written as 9 bytes.  This is how 3B above
     works.  So if you don't find anything 6 or greater why do you check for 4
     or 5 bytes in a row but not 3 in a row? Simple... How many bytes does a
     series of similar bytes get compressed into? 3.  How many bytes are we
     trying to compress? 3.  Why waste your time?  Also the original Commodore
     Zipcode program ignores anything less than 4 bytes.

  4. Look through the sector trying to find a byte that doesn't exist. This is a
     repeat notifier.
  5. Compress the sector while keeping track of how much data you actually
     write.

  Let's follow up with examples of all three types of sectors.  Reading in the
  first 256 bytes of GameName.D64 we get:

     4D53 A901 202E 03A9 028D 0E18 78A9 1A8D
     0218 A908 8D00 18A9 0185 F9A0 0198 203E
     0320 5204 20AA 04A9 828D 0E18 5860 A000
     A200 CAD0 FD88 D0FA 38E9 01D0 F560 8480
     8581 A900 857F 58A9 808D 9802 2060 D478
     A604 E001 D001 CAE0 0BD0 1EA5 16A4 17CD
     EB04 D007 CCEC 04D0 10F0 0ACD ED04 D009
     CCEE 04D0 04A2 0186 04E0 0060 A246 60BC
     8005 8CEA 0418 7D00 05BC 4005 F0EE D986
     0490 0738 F986 04C8 D0F4 48AD EA04 F01B
     C901 D00D ADEB 0485 12AD EC04 8513 4CBB
     03AD ED04 8512 ADEE 0485 1368 4C3E 03A9
     088D 0018 868B A207 AD00 1829 ED26 8B90
     0209 028D 0018 4908 8D00 1849 0826 8B2C
     0018 10FB 8D00 1829 ED90 0209 022C 0018
     30FB 8D00 1849 088D 0018 CAD0 DE49 082C

  If you look byte after byte we find no matching values in succession.  This
  sector can't be compressed so it is written as (Case 3 from above):
     Track | Sector | 256 Bytes of Data

  Read the next sector.  Remember zip files do not store sectors in order.  The
  next sector we read is $0B (11 decimal) so we need to move forward 2816 bytes
  in the disk image. 11 sectors * 256 bytes per sector = 2816 bytes.

     0018 10FB 8D00 182C 0018 30FB 6020 E104
     58AD 0018 10FB 78A9 008D 0018 A208 A008
     AD00 1830 FBA9 E018 6901 D0FB AD00 188C
     0018 6A26 8BAD 0018 10FB A900 8D00 18CA
     D0DE AD00 1830 FBA9 088D 0018 20E1 04A5
     8B60 A000 9899 0005 C8D0 FAA0 01A2 0486
     F9A9 0220 3E03 A000 A200 BD00 07F0 1699
     4005 E8BD 0007 9900 05E8 E8BD 0007 9980  $E8E8 = Repeats but not enough
     05E8 C8D0 E560 1515 1515 1515 1515 1515  $15 Repeats 18 times
     1515 1515 1515 1515 0013 1313 1313 1312  $13 Repeats 6 times $12 6 times
     1212 1212 1211 1111 1111 A904 85F9 200D  $11 Repeats 5 times
     04C9 FFF0 1A48 200D 04A8 68AA 9820 7F03
     0820 BF03 28D0 E3A9 0720 D004 4CAA 0460
     8DDA 04A0 0020 E104 BE00 1020 BF03 C8D0
     F7AD 001C 4908 8D00 1C60 0050 4157 4E00
     A0A0 A0A0 A000 20FE 01A6 DC01 ACE9 0E00  $A0 Repeats 5 times

  Scanning through this sector we see it meets the criteria for number 3 above
  and needs to be compressed.  We used AND above to extract the compression type
  so we need to use OR to add the compression type.  First write the
  track/compression type:
    Track 01 OR 128 (128 = partial compression remember?) = 129 so we write
    129 ($81 in hex) as the track.
  Now write the sector which is $0B. The output starts to look like this: 810B

  Now we scan through the data until we find a byte that isn't present.  If you
  start at $00 and work your way up you will find $06 is the first available
  non-used byte.  The next value to be written is actually the number of bytes
  until we reach the next sector but we don't know that yet since we haven't
  actually compressed anything so let's skip ahead in the zip file by one
  and write our repeat byte.  Now we have: 810B xx06

  Here's were we write the actual data.  You can see the bytes can't be
  compressed until we reach the string of $15s so we write all bytes until then.
  Now we have:

    810B xx06 0018 10FB 8D00 182C 0018 30FB
    6020 E104 58AD 0018 10FB 78A9 008D 0018
    A208 A008 AD00 1830 FBA9 E018 6901 D0FB
    AD00 188C 0018 6A26 8BAD 0018 10FB A900
    8D00 18CA D0DE AD00 1830 FBA9 088D 0018
    20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
    01A2 0486 F9A9 0220 3E03 A000 A200 BD00
    07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
    0007 9980 05E8 C8D0 E560

  Now compress the section of $15.  It repeats 18 ($12 in hex) times so we write
  it as RepeatNotifier | HowManyTimesToRepeat | ValueToRepeat.  This comes out
  to be: 0612 15
  Now we have:

    810B xx06 0018 10FB 8D00 182C 0018 30FB
    6020 E104 58AD 0018 10FB 78A9 008D 0018
    A208 A008 AD00 1830 FBA9 E018 6901 D0FB
    AD00 188C 0018 6A26 8BAD 0018 10FB A900
    8D00 18CA D0DE AD00 1830 FBA9 088D 0018
    20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
    01A2 0486 F9A9 0220 3E03 A000 A200 BD00
    07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
    0007 9980 05E8 C8D0 E560 0612 15

  The next set of bytes is a repeating $13 for 6 times.  It is written as:
  0606 13
  Now we have:

    810B xx06 0018 10FB 8D00 182C 0018 30FB
    6020 E104 58AD 0018 10FB 78A9 008D 0018
    A208 A008 AD00 1830 FBA9 E018 6901 D0FB
    AD00 188C 0018 6A26 8BAD 0018 10FB A900
    8D00 18CA D0DE AD00 1830 FBA9 088D 0018
    20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
    01A2 0486 F9A9 0220 3E03 A000 A200 BD00
    07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
    0007 9980 05E8 C8D0 E560 0612 1506 0613

  Continue to do this until the end of the sector is reached compressing as
  necessary.  When you do it will look like this:

    810B xx06 0018 10FB 8D00 182C 0018 30FB
    6020 E104 58AD 0018 10FB 78A9 008D 0018
    A208 A008 AD00 1830 FBA9 E018 6901 D0FB
    AD00 188C 0018 6A26 8BAD 0018 10FB A900
    8D00 18CA D0DE AD00 1830 FBA9 088D 0018
    20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
    01A2 0486 F9A9 0220 3E03 A000 A200 BD00
    07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
    0007 9980 05E8 C8D0 E560 0612 1500 0606
    1306 0612 0605 11A9 0485 F920 0D04 C9FF
    F01A 4820 0D04 A868 AA98 207F 0308 20BF
    0328 D0E3 A907 20D0 044C AA04 608D DA04
    A000 20E1 04BE 0010 20BF 03C8 D0F7 AD00
    1C49 088D 001C 6000 5041 574E 0006 05A0
    0020 FE01 A6DC 01AC E90E 00

  Lastly we need to count how many bytes were written after the xx above.
  There are 231 bytes ($E7 in hex) until the next sector.  Replace xx with $E7.

    810B E706 0018 10FB 8D00 182C 0018 30FB
    6020 E104 58AD 0018 10FB 78A9 008D 0018
    A208 A008 AD00 1830 FBA9 E018 6901 D0FB
    AD00 188C 0018 6A26 8BAD 0018 10FB A900
    8D00 18CA D0DE AD00 1830 FBA9 088D 0018
    20E1 04A5 8B60 A000 9899 0005 C8D0 FAA0
    01A2 0486 F9A9 0220 3E03 A000 A200 BD00
    07F0 1699 4005 E8BD 0007 9900 05E8 E8BD
    0007 9980 05E8 C8D0 E560 0612 1500 0606
    1306 0612 0605 11A9 0485 F920 0D04 C9FF
    F01A 4820 0D04 A868 AA98 207F 0308 20BF
    0328 D0E3 A907 20D0 044C AA04 608D DA04
    A000 20E1 04BE 0010 20BF 03C8 D0F7 AD00
    1C49 088D 001C 6000 5041 574E 0006 05A0
    0020 FE01 A6DC 01AC E90E 00

  Just for kicks look back at the example showing us reading sector $0B of
  1!GameName in the disk image section.  Those bytes are the same as these
  bytes.  That's because we went from reading Track 1 Sector 11 ($0B) from a
  compressed state, then uncompressed it, and then compressed it again.

  Finally the third type of compression is full.  Shown below is a fully
  compressible track:

    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF

  After running through the sector we see all bytes are the same.  We write it
  as Track/Compression | Sector | Value.  For this example let's assume it is
  sector 01.  Since full compression uses the value of 64 we must OR it with the
  track.  01 OR 64 = 65 ($41 in hex).
  It is written as 4101 FF.

This concludes the tutorial.  I hope you found it useful.  You may want to
compare it to the source code provided to get a better feel of how it works.  If
you have any questions or are unsure about anything discussed here please feel
free to send me e-mail at cyberonix@hotmail.com

Please DO NOT change this text in any way.  If you find an error please let me
know and I will update the text. Please do not distribute this text without the
accompanying source and readme files.

Thanks,
Jason
