Compilation of information on most archival image types for the commodore.


*** Introduction to the various Emulator File Formats
***  Compiled by:    Peter Schepers ***      Started:   August 24, 1996 *** Last updated: December 10, 2009

There are always questions asked regarding the various file formats which are commonly used on either the emulators or the real C64. Most  often  the question involves conversion... "What do I do with LNX files?" or "How do I make these files work on the C64s emulator?". These  documents  attempt  to explain their internal structure, what to do with them, and some  of  their respective strengths and weaknesses. These documents were compiled and written in an attempt to unify all  the other smaller files dealing with Commodore file  types  that  are  floating about the net, or that exist with other programs.  They  are  by  no  means exhaustive (even though they look like it), but attempts will  be  made  to keep them up-to-date, and correct anything which  is  wrong.  If  you  spot something that needs correcting please make sure to  email  the  author  so that corrections  can  be  made  for future  releases...  the  address  is contained later in this document. Some of the information contained in these documents may not be  accurate as it could have  been  taken  from  inaccurate  sources,  and  I  have  no first-hand experience with said  format.  However,  use  these,  pass  them around, upload them, whatever. Just be sure to  leave  them  INTACT,  don't remove bits. I have attempted to categorize the filetypes involved using  three  basic categories: IMAGES, ARCHIVES and CONTAINERS. The definitions  for  each  of these categories can be found at the bottom of this document. Also, plenty of good information can be  gleaned  from  the  source  code contained in the archive CBMConvert, which is on the FTP.FUNET.FI FTP site. Contained in it are the sources for UnZipCode, UnLNX, Ark, some  LHA  info, etc. It is an invaluable set of utilities put together by both Marko Makela and Paul Doherty. So far, this document covers the following files:
* D64 images (1541 disks and some variants)
* X64 images (for the X64/Vice emulator)
* T64 containers (for the C64s emulator)
* T64 .FRZ (FRoZen Files, saved emulator sessions for C64s)
* PC64 containers (P/S/U/Rxx)
* PC64 .C64 (saved emulator sessions for PC64)
* D71 images (1571 disks)
* D81 images (1581 disks)
* D80 (8050) & D82 (8250) floppy images
* G64 images (GCR copy of a 1541 disk)
* D2M images (FD2000 disks)
* DNP images (CMD hard disk native partitions)
* F64 (not an image file, but a companion file to D64's)
* N64 (64NET's custom files)
* L64 (64LAN's custom files)
* C64 (PCLINK's custom files)
* CRT images (CCS64 ROM cartridges)
* 64x (PC64 ROM files)
* TAP images (for CCS64, sampled cassette tapes)
* VSF VICE snapshots (saved-emulator sessions for VICE)
* WAV Audio RIFF files for the PC

...as well as the following native C64 types,  some  of  which  are  also supported on the various emulators:
* Extensive disk file layout (how files are stored on 1541/71/81 disks)
* 4-file diskpacked ZipCode archives (or .Z64, 4 or 5 files, #!xxxxx)
* 6-file SixPack ZipCode images (or .Z64, #!!xxxx)
* Filepacked ZipCode archives (or .Z64, x files, x!xxxxx)
* LNX containers (LyNX)
* ARK containers & SRK archives (ARKive & compressed ARKive)
* LHA & LZH archives (header description only)
* SFX archives (SelF-eXtracting LHA/LZH)
* SDA archives (Self-Dissolving Archive)
* ARC archives (ARChive)
* ZIP archives (PKZIP)
* CKIT archives (Compression KIT)
* CPK containers
* WRA & WR3 archives (Wraptor, version 1 to 3)
* LBR containers (LiBRary, C64 only, not the C128 CP/M .LBR files)
* GEOS VLIR files (Variable Length Index Record)
* REL files (RELative)
* CVT files (GEOS ConVerT)
* SPY containers (SPYne)
* C128 Boot Sector layout
* Binary & PRG (PRoGram, with load address)
 
Also included is a very basic look at some C64 graphic bitmap formats (in BITMAP.TXT), and the  saved  session  layout  of  the  Macintosh-based  C64 emulator "Power64" (in POWER64.TXT). Thanks to Peter Weighill for the above
info. Joe Forster/STA has written up a description of how the various Commodore drives (1541/1571/1581) allocate sectors and directory entries when  saving files (under normal mode and under GEOS). It is included as DISK.TXT Right now there are several good utilities available to work with most of the mentioned formats. The first is 64COPY, my own conversion program.  The second is Star Commander, by Joe Forster/STA. Included with his program are
many smaller utilities such as Star ARK, Star LHA and Star ZIP, which  will convert specific formats to D64 images.

                                           Peter Schepers, University of Waterloo.

                                               Email: schepers@ist.uwaterloo.ca

Most recent changes:
Oct  1/07 - Updated VICE_FRZ.TXT with info about the bogus ".S64"  snapshot file extension from the UnQuill package.
          - Updated D81.TXT doc
          - Updated D71.TXT doc
          - Updated G64.TXT doc
          - Updated CVT.TXT doc

Feb 19/08 - Updated G64.TXT, removed erroneous odd/even tail gap info.
          - Updated D64.TXT with other SpeedDOS clone names

 Nov 7/08 - Updated D64, D71, D81  &  D80/D82  with  extra  explanation  of oversize directory track images, which contain more files  than normal.

Jul 21/09 - Updated CRT.TXT, correcting many incorrect  entries  for  EXROM and GAME under the cartridge samples. Added section on  Ultimax mode, changed all EXROM  and  GAME  references  to  /EXROM  and /GAME, explaining these lines are active-low.

Dec 10/09 - Updated CRT.TXT again with changes to Simons  Basic  and  Ocean Type 1 regions.

*** Terms and acronyms
Many strange terms have come along with computers in general, and I  will not attempt to explain them all, but some of the ones in this document  may not be entirely clear. I will attempt to make things  a  little  easier  by
explaining some of the more common ones.

<CR> - Short form for a Carriage Return ($0D) symbol.

<LF> - Short form for a Line Feed ($0A) symbol.

ARCHIVE - A  file  format  which  contains  other  files,  and  in  which compression is an integral part of the design.  Some  examples are ZIP, SRK, SDA, ARC, LHA, WRA.

ASCII - This is an acronym for "American Standard  Code  for  Information Interchange". The standard  is  a  7-bit code  covering  control codes, punctuation, alphanumeric (A to Z, 0 to 9) as well as math and a few other symbols. Since it is a 7-bit code, it ranges from $00 to $7F (0-127). This leaves the top 128-255 definable by  the vendor. The PC world has corrupted this standard making it 8-bit.

BAM - An acronym for "Block Availability Map". Here  is  where  the  disk operating system keeps track of  what sectors  are  allocated  (or available) for each track.

BLOCK - This refers to sectors which  on  a  logical  level  are  grouped together. On a 1541 disk, it could be a series of sectors  linked together in a file, or a partition on a  1581  disk.  In  the  PC world it represents a "cluster"  of sectors.  Generally  if  I'm referring to a grouping of sectors thats *not* 256  bytes  large, then I talk in blocks.

BYTE - A group of 8 bits, the contents of a memory location.

CHAIN - A series of sectors linked  together.  One  sector  will  have  a pointer to another, and that sector will point to another,  until the chain has no more forward pointers. A file stored on  a  1541 disk would be considered a chain of sectors, but it  also  has  a directory entry explaining what the chain is for.

CONTAINER - A file format which  simply  contains  other  files,  and  no compression takes place. Some examples are  T64,  P00,  SPY,  ARK, LNX.

FILETYPE - In the Commodore world, this would be the kind of file, be  it SEQ, REL, PRG, USR, GEOS etc. In the  DOS  world,  this  would possibly be the file extension, be it EXE, TXT, DOC. It  tells the user what file it is, making usage easier.

GCR - An acronym for "Group Code Recording". This is the encoding  method Commodore uses to physically store the information on most  of  the 5.25" disks (i.e. 1541). It encodes an  8  bit  sequence  (2  4-bit nybbles) into a 10 bit sequence (2  5-bit  nybbles)  so  that  long repeated sequences of 1's or 0's are avoided. These must be avoided so that the timing of reading/writing to the disk won't become "out of sync". As a user, you would not normally see the GCR information since the drive does all the conversion to normal HEX  data  before it gives it to you.

HIGH/LOW - The bytes here are stored backwards compared to  the  LOW/HIGH method. See LOW/HIGH for more information.

IMAGE - A file format which is a PC equivalent of  a  physical  Commodore media. Some examples are D64 (1541), D71 (1571), D81 (1581),  D2M (FD2000), X64.

LINK - This is the track/sector values, stored in the first two bytes  of a sector, which point to (or "link" to) the t/s location  of  the next sector. A  series  of  these  links  comprise  a  "chain"  of sectors.

LOW/HIGH - This is how values are stored when they  exceed  one  byte.  A good example of this is the sector count of  a  D64  file.  To calculate the actual value, take the second value, multiply it by 256 and add the low  value.  You  will  now  get  the  real decimal value. i.e. (HIGH*256)+LOW=result. If you look at is as a HEX value, swap the bytes  around  and put them together for the 16-bit HEX value. i.e. $FE $03 would be $03FE as a 16-bit HEX value.

LSB/MSB - See LOW/HIGH.

LSU - This is my own acronym meaning "last  sector  useage".  It  is  the value stored in byte position $01 (the "sector" value  of  the  t/s link) of the last sector of a file. This value is the offset  into the sector where the last byte is stored. It  also  represents  the byte count + 1, since a value of 255 would actually mean  only  254 bytes of file data exists (full sector less the  2  bytes  for  t/s chain). Without reasonable knowledge of the disk layout, this  byte can be confusing, and hard to explain.

NYBBLE - A grouping of 4 bits (half a byte), either the first or  last  4 bits of an 8-bit binary number,  or  one  half  of  a  two-digit hexadecimal number. Typically, a byte will be broken down into two parts, the top  4 bits and the bottom 4 bits. These are referred to as  the  upper and lower  nybble  respectively,  and  are  represented  by  two hexadecimal digits in base 16.

PETASCII - (or PETSCII) This is Commodore's version  of  ASCII  (the  PET part of the name comes from the  first  computer  to  use  the code, the PET or Personal Electronic Transactor). Most of the codes from 0-127 are the same as ASCII, but  there are differences, especially  noticible  when  converting  text from a C64  to  a  DOS  machine.  Where  ASCII  has  uppercase characters, PETASCII has lower  case  ones,  and  vice  versa.  Also, the top 128 characters (128 to 255) are quite  different from the PC "standard".

RLE - An acronym for "Run Length Encoding". This is a simple  compression method, employed by most compression programs,  and  also  used  by some file formats (ZipCode, CPK). It encodes sequences (or  "runs", hence the name "RUN length...") of the same byte (i.e. 00 00 00  00 00 00) into a smaller string using a shorter code sequence,  making the resultant file smaller than the original. This is the  simplest form of file compression.

SECTOR - It is best described as the method that the drive uses to  store the smallest group of bytes physically on the disk. On the  1541 this refers to a group of 256 bytes stored together in a  single sector. On a PC disk, this is typically 512 bytes.

SIGNATURE - A group of bytes, usually near or at the front of  the  file, which are used to identify the type of file. i.e. a PC64 file will always have the signature string "C64file" contained  at the beginning of the file.

TAR - An acronym for "Tape ARchiver", a UNIX application, and  method  of backing up information.


 

*** L64 (64LAN container files)  *** Document revision: 1.3  *** Last updated: March 11, 2004

*** Compiler/Editor: Peter Schepers  *** Contributors/sources: Markus Mehring.

64LAN gives your C64 access to files on your PC  hard  disk  (similar  to 64NET). It uses a custom file format extension "L64",  which  contains  the original C64 filename and attributes.

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
-----------------------------------------------   ----------------
0000: 36 34 4C 41 4E 20 49 44 42 4C 4F 43 4B 20 0D 0A   64LAN�IDBLOCK���
0010: 73 64 66 67 73 66 20 20 20 20 20 20 20 20 20 20   sdfgsf����������
0020: 0D 0A 30 38 30 31 2C 44 33 45 42 0D 0A 20 20 20   ��0801,D3EB�����
0030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20   ����������������
0040: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20   ����������������
0050: 20 20 20 20 0D 0A 20 20 20 20 20 20 20 20 20 20   ����������������
0060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20   ����������������
0070: 20 20 20 20 20 20 20 20 20 20 20 20 20 0D 0A 1A   ����������������
0080: 09 65 FF FF FF FF FF 01 00 00 00 00 00 00 00 00   �e��������������
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0100: 0E 08 E9 03 9E 20 28 32 30 36 34 29 00 00 00 78   ������(2064)���x

Bytes: $00-0F: 64LAN file signature ("64LAN IDBLOCK ", with <CR><LF>)
10-21: 16-byte filename of contained C64  file,  with  <CR><LF>.
Filename padded with $20 (spaces!)
22-2C: Starting and ending HEX load addresses, with <CR><LF>
2D-55: 39-byte comment #1, with <CR><LF>
56-7E: 39-byte comment #2, with <CR><LF>
7F: EOF marker, for text viewing
80-81: Version number of  file  (high/low  byte  format),  Above
example provides a version of 09.65
82-86: 5-byte CRC
87: Origin of file:
0 - Real C64
1 - C64s emulator
88-FF: Reserved for future use
100-: File data starts here, without the original load address

All the strings in the beginning of the file, from 00-7F  are  in  ASCII, and delimited with <CR> and <LF> markers. This block ends  in  a  text-mode EOF marker. This is to help with the viewing of the contents of these files using the DOS "TYPE" command.


 

*** N64 (64NET container files) *** Document revision: 1.3 *** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers *** Contributors/sources: Markus Mehring

64NET links your C64  and  PC  together  through  a  special  cable,  and provides the C64 access to many image and native files stored  on  your  PC hard disk. Early versions only provided access to 64NET's  custom  filetype "N64", which is explained here, but newer versions also support many of the common files (LNX, T64, D64, etc).

The following is a dump of an N64 file:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
-----------------------------------------------   ----------------
00: 43 36 34 01 82 01 08 C4 0C 00 00 00 00 00 00 00   C64�������������
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 31   ���������������1
20: 35 58 58 20 2D 3E 20 36 34 4E 45 54 00 00 00 00   5XX�->�64NET����
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .. ..   ��������������..

Bytes:  $00-02: 64NET file signature ("C64")
03: File version ($01)
04: C64 filetype. Valid types are: $x0=DEL  $x1=SEQ  $x2=PRG  $x3=SEQ  $x4=REL $x5=DIR (not really implemented)  $x6=VOL (not really implemented)
Bit 0-3: The actual filetype 000 (0) - DEL  001 (1) - SEQ  010 (2) - PRG  011 (3) - USR  100 (4) - REL Values 5-15  are  illegal,  but  if  used  will produce  very  strange  results.  The  1541  is inconsistent in how it treats these bits.  Some routines use all 4 bits, others ignore  bit  3, resulting in values from 0-7.
Bit 4: Not used
Bit 5: Used only during SAVE-@ replacement
Bit 6: Locked flag (Set produces ">" locked files)
Bit 7: Closed flag (Not set produces "*",  or  "splat" files)
05-06: Load address of contained file in low/high format.  Some versions do not contain this address, so use the one  at the beginning of the file data.
07-0A: File size (in bytes,  low/med1/med2/high  format).  This provides  access  to  *very*  large  files,  up   to   2 Gigabytes!
0B: Network security level $00 - None 01 - Visitor 02 - Low 03 - High 04 - Master
0C-1E: Reserved for future use
IF-2E: 16-byte C64 filename in PETASCII, padded with $00
2F: Set to $00
30-FD: Reserved for future use
FE-: Start of file data (including original load address)

Some versions of these files are longer than what  the  header  and  file size total up to. It is safe to ignore this inconsistency and only read the amount of data dictated by the "file size".


 

*** ARC (compressed ARChive) *** Document revision: 1.4 *** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers *** Contributors/sources: Chris Smeets (source code)

The name is likely a shortened version  of  "ARChive".  It  is  a  direct relative of SDA, as SDA's are simply self-dissolving ARC  files.  ARC  does not contain the dissolving code on the front of the file.  Do  not  confuse
these ARC files with C64 ARKive files (made with the  ARKIVE  program),  or with PC .ARC files, as they are all completely different. Below is  a  dump of the first 48 bytes of an ARC file...

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
-----------------------------------------------   ----------------
0000: 02 01 20 9D 47 01 00 01 00 50 01 41 FE 3A 21 FE   ..��G.�.�P.A�:!�
0010: 00 01 FE 00 02 FE 03 02 A9 00 20 90 FF A9 02 A6   �.��.�..������.�
0020: BA A0 01 20 BA FF A9 04 A2 35 A0 02 20 BD FF A2   ��.����.�5�.����

Byte:   $00 - ARChive version $01 = original 02 = extended header
01 - Compression mode $00 - Stored 01 - Packed 02 - Squeezed 03 - Crunched (ARC version 2 only)
04 - Squeezed and packed (ARC version 2 only) 05 - Crunched in 1 pass (ARC version 2 only)
02-03 - Checksum (low/high format) 04-06 - Original file size  in  bytes  (low/med/high  format).
This value is not valid if the compression mode  (from above) is 5, a one pass crunch)
07-08 - Number of blocks compressed file takes (low/high,  254 bytes/block)
09 - Filetype ("P", "S",  "U",  "R",  uppercase  in  ASCII, lowercase in PETASCII )
0A - Filename length 0B-0B+length - Filename (in PETASCII, no longer than  16  characters)
0B+length+1 - Relative file record length (only for ARC version 2)
0B+length+2 - Date (2 bytes, in MSDOS format, only in ARC vers. 2)

The header can also have some extra fields, depending on what version the archive is. Version 1 archives do not  have  the  RECORD  length  and  DATE fields, meaning they cannot contain REL files. The RECORD  length  is  only
used when the filetype is REL.

Immediately following the filename (for version 1 archives)  is  the  RLE control byte, and then follows the LZ table and compressed data.

Watch out for "extra" data at the end of the file, typically many  $00's. Some files which exist have this, and it makes reading the  contained  file list more difficult.

64COPY can unpack ARC files easily, and just hitting return on them  will open the archive. Simply select what files you want to  extract,  and  copy them out.



*** ARK (ARKive containers) *** SRK (compressed ARKive archives, very rare) *** Document revision: 1.3
*** Last updated: March 11, 2004 *** Compiler/Editor: Peter Schepers *** Contributors/sources: unknown

Written  by  Edward  Rohr,  the  ARKive  program  went  through   several revisions, with the last known being version 3.0.  It  was  intended  as  a replacement for LNX as the author explained he had too many bad experiences
with LyNX destroying his data. Version 3 was also the only one  to  support creation and extraction of the compressed SRK archives.

The ARK format bears a strong resemblance to LNX files in  that  all  the files are simply stored one after the other, and are block aligned to  take up multiples of 254 bytes (256 on a real 1541). However, there is no  BASIC
program at the beginning telling you to "Use XXX to  dissolve  this  file", and therefore there is no reconizeable signature to determine if  the  file is actually an ARK. ARK's can contain up to 255 files, but this  number  is restricted by the limitations of the drive  being  used  for  addition  and extraction.

SRK is the compressed version of ARK. The layout of the directory is  the same as below,  only  the  files  themselves  (except  for  REL)  might  be compressed. As I only seen one file (which was damaged), and my attempts to create one with ARKive 3.0 failed badly, I can't comment on the compression used. The biggest difference is the files contained inside the SRK are  not block-aligned since they are compressed, and therefore must be decompressed to create the destination file, rather than just "unlinked".

The structure of the directory is very simple, where all entries take  up 29 bytes (unlike LNX's variable size). Below is a sample of  an  ARK  file, with a few of its directory entries...

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
-----------------------------------------------   ----------------
0000: 1F 82 9F 42 4F 4F 54 A0 A0 A0 A0 A0 A0 A0 A0 A0   .��BOOT���������
0010: A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 82 F1   ������������.���
0020: 53 55 50 45 52 20 4B 4F 4E 47 A0 A0 A0 A0 A0 A0   SUPER�KONG������
0030: 00 00 00 00 00 00 00 00 00 79 00 82 FB 41 54 4F   ���������y���ATO
0040: 4D 49 43 20 48 41 4E 44 42 41 4C 4C A0 00 00 00   MIC�HANDBALL����
0050: 00 00 00 00 00 00 0F 00 82 FE 58 45 52 4F 4E 53   ������.���XERONS
0060: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 00 00 00 00 00 00   ����������������
0070: 00 00 00 2A 00 82 FF 57 45 54 20 50 41 49 4E 54   ���*���WET�PAINT
0080: A0 A0 A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00   ����������������
0090: 12 00 82 5A 47 52 4F 55 4E 44 20 53 4E 49 50 45   .��ZGROUND�SNIPE

Byte:   $00: Number of files in the ARKive ($1F = 31 files)
01-1D: First directory entry (29 bytes per entry)
01: File Attribute (same as a D64 attribute) Typical values for this location are: $80 - DEL 81 - SEQ
82 - PRG 83 - USR  84 - REL
Bit 0-2: The actual filetype 000 (0) - DEL 001 (1) - SEQ 010 (2) - PRG 011 (3) - USR 100 (4) - REL
Values 5-15 are illegal types.
Bit 3: Not used
Bit 4: Compressed flag (only for SRK).  If  set,  file  is compressed. Not used in ARK files.
Bit 5: Not used
Bit 6: Locked flag (Set produces ">" locked files)
Bit 7: Closed flag  (not  set  produces  "*",  or  "splat" files)
02: LSU byte (see "INTRO.TXT" document for description of "LSU")
03-12: 16-byte filename (in PETASCII, padded with $A0)
13: REL file RECORD size
14-19: Unused (can contain the unused locations from the D64 entry)
1A: REL file side sector block count (side sector info contained at end of file)
1B: Number of bytes+1 used in the last side sector entry
1C-1D: Length of file, in sectors (low/high byte order)
1E-3A: Second directory entry
3B-57: Third directory entry
58-74: Fourth directory entry
75-91: Fifth directory entry
The starting  location  of  the  file  information  takes  only  a  small calculation to find out. As we have 31 entries, the total byte size of  the directory is 31 * 29 + 1 = 900 bytes (the 1 comes from the  first  byte  of the file, which represents the # of entries). Now,  we  take  the  900  and divide it by 254 to see the number of blocks, 900/254 = 3.543. If there  is any remainder, we always round up to the nearest  integer,  which  in  this case makes it 4 blocks. So now we know that the file information starts  at 4*254 = 1016 ($03F8 offset)

REL files are stored like a normal  file  except  the  side  sectors  are stored directly following the normal file data.  It  would  seem  that  the actual contents of the side sectors are unimportant (except for the  RECORD length), just that the correct number of blocks exist.

Seeing as no emulator that I know of supports ARK format, I can't see any usefulness in using it. It does have a  better directory structure than  LNX as each entry has a consistent byte size (versus LNX's variable size).

There are also a few utilities for UnARK'ing on the  PC.  It  would  seem that LNX is the better supported format (although I think it shouldn't be), In both the C64 and  the  emulators.  64COPY  supports  these  files  on  a read-only basis, allowing you  to  convert  them  to  another  format,  but nothing else. Star Commander also contains a  utility  called  Star  Arkive which will un-Arkive these files into a D64 image.

---------------------------------------------------------------------------

What it takes to support ARK:

ARK shares many features with LNX. It has a directory size that is always a multiple of 254 bytes, and the files contained are also block aligned  to 254 byte boundaries. The directory entries also have room  for  the  unused
part of the D64 entry, used for  time/date  stamps,  and  it  supports  REL files. Unlike LNX, this format uses a consistent 29-byte  directory  entry, which is a very great advantage.

However, it has a few drawbacks as well.  It  contains  no  recognizeable signature, and can only hold up to 255 files. The most  annoying  thing  is there is no provision for having a multi-block directory, with only  a  few entries (which by the way LNX allows for).  This  means  I  cannot  have  a directory with only 2 entries, yet have the directory take up 2 blocks.

For the 1541, this limitation makes no difference, but on a PC it makes a world of difference. If I wanted to add files to an existing ARK file on  a PC, I might have to increase the directory by several blocks, and on  a  PC that takes some work.

This also means that I cannot cancel a "copy"  operation  in  the  middle because I may end with a directory with too many blocks for the  number  of entries it contains.



*** Binary/Raw files *** Document revision: 1.3 *** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers *** Contributors/sources: none

This is really a non-format, as it has no specific layout whatsoever, but instead is simply a data file. This does make it difficult to describe  any general layout, as there are many  possibilities.  It  is  assumed  that  a
binary is  a  single  file,  usually  having  no  special  extension  (like LNX/SFX/SDA, etc), sitting on a PC hard disk, not  inside  of  *any*  other file (like in a D64/T64/LNX  etc).  By  looking  at  the  whole  file  (but especially the beginning) with a HEX editor, and a  well-trained  eye,  you can usually determine what file type it is by the BASIC code, load address, and text strings contained within.

Two possible file extensions that binary files  can  use  are  "BIN"  and "PRG". There is a distinction in the 64 community between  these  two  file types. A "BIN" (binary) file is one without a load address  preceeding  the
file data, and a "PRG" (program) file has a load address in the  first  two bytes of the file.

If the file is a normal C64 program, then the first  two  bytes  are  the load address, stored in low/high byte format. If it is a BASIC program  (or has a BASIC header), then the first two bytes might be $01 $08 (or $01  $04 for PET, $01 $1C for C128, the numbers  vary  for  different  systems  like VIC-20, Plus4, C61, etc), and  the  rest  is  line number  pointers,  line numbers and BASIC code.

If it is not a BASIC file (like part of a game loader), then it could  be a machine language file, requiring a SYS call to  execute.  Many  secondary files with multi-file games have load  addresses  other  than  $0801  (like $C000, or $8000 for cartridges), and some  have  none  at  all,  where  theloader program will actually specify where to load the  file.  Below  is  a typical header for a game, using a SYS call to start  (in  this  case,  SYS 2064).

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
-----------------------------------------------   ----------------
0000: 01 08 0E 08 E9 03 9E 20 28 32 30 36 34 29 00 00   ....�.��(2064)��
0010: 00 78 A2 FF 9A A0 00 84 01 A2 CC BD 57 08 9D 33   �x������.�̽W.�3

One reason this  "non-image"  format  is  important  is  because  of  the filename limitations imposed by  the  PC  architecture,  and  some  of  the problems that it can cause. The PC has an 8.3 filename convention (assuming DOS, and not OS/2 or Windows 95/NT long filenames), allowing for, at  most, a filename of 11 characters. The  PC  also  has  character  limitations  on filenames, most of which don't apply to the C64. When converting a C64 file
from any image/archive, you *cannot* use the C64 filename directly  on  the PC since, first of all its likely too long, and  secondly  it  may  contain characters illegal in  the  DOS  world  (i.e.  ASCII  46,  the  'extension' separator).


One other reason that binary is not a good way to keep C64 files is  that you lose the C64 filetype. You *can* set the file  extension  to  show  the type (xxx.PRG, xxx.SEQ), but  this  is  not  typically  done.  If  the  DOS extension is not set, it is much more difficult to  know  what  format  the file originally was.

In order to convert a filename from C64 to  DOS,  the  use  of  translate tables (translating illegal  characters  to  legal  ones)  as  well  as  an algorithm to reduce the filesize down to useable  size  (typically  only  8 characters from 16) must be used. Included  within  the  PC64  distribution archive is a 'C' program which does just what I have described. It contains an algorithm which will remove illegal characters, then reduce the filename down using several different rules, all to make the filename conform to the DOS 8.3 naming standards.

There are some people who feel that with Windows95 (or OS/2,  or  Windows NT) long filename support, we should be able to have  C64  files  with  the full 16 character filename on the PC hard disk. This is a  fallacy  as  the useable character limitations of the C64 and those  of  any  OS  supporting long filenames are not the same.  If  you  convert  a  C64  filename,  many characters must be removed and or changed to allow it to be used in DOS (or Win95).

There is very little benefit or disadvantage to using binary.  About  the only thing which is important to remember is you could  lose  most  of  the original C64  filename,  which  *will*  cause  problems  when  you  try  to reconstruct them. Binaries have no way of preserving the actual long names.

---------------------------------------------------------------------------

Overall Good/Bad of BINARY Files:
Good
* Easily determined filesize (the DOS filesize is the C64 filesize)
* It is the *native* C64 file, so emulators can *easily* support it

Bad
* No 16 char filename, no real C64 filename at all
* No filetype, or special attribute bits
* No REL, GEOS or FRZ file support
* No signature or file description
* Difficult to support multi-file, as  original  C64  filenames  are  not retained
* Since there is no filetype, you may not always be able to determine  if the file is a SEQ, USR or really a PRG without knowledge  of  the  file contents



*** Standard C64 BITMAP Files (HIRES & HIRES-MULTICOLOR) *** Document revision: 1.3
*** Last updated: March 11, 2004 *** Compiler/Editor: Peter Schepers *** Contributors/sources: Peter Weighill

Below is a table to help in the identification of C64  bitmap  files.  If you require further information about how bitmaps are  displayed  then  you should refer to the C64 Programmers Reference Manual.

To automatically identify the type of  file,  you  need  to  compare  the length of the file and the Load address. Once you have identified the  file type, you can then use the bitmap, screen and colour offsets to help in the displaying of the bitmap.

Format for file types:
Load   - Load address (first two bytes of the file)
Length - File length in bytes (including load address bytes)
Bitmap - Bitmap offset (8000 bytes)
Screen - Screen data offset (1000 bytes)
Colour - Colour data offset (1000 bytes)
ScrCol - Screen colour offset (1 byte)

Name (Black/white)    Load  Length Bitmap Screen Colour ScrCol
--------------------- ----- ------ ------ ------ ------ ------
"Art Studio"          $2000 9009   0      8000   -      -
"Doodle"              $5C00 9218   1024   0      -      -
"Image System (hi)"   $4000 9194   0      8192   -      -

Name (Multicolor)     Load  Length Bitmap Screen Colour ScrCol
--------------------- ----- ------ ------ ------ ------ ------
"Artist 64"           $4000 10242  0      8192   9216   10239
"Adv Art Studio"      $2000 10018  0      8000   9016   9001
"Blazing Paddles"     $A000 10242  0      8192   9216   8064
"Koala Painter"       $6000 10003  0      8000   9000   10000
"Image System (mc)"   $3C00 10218  1024   9216   0      9215
"Vidcom 64"           $5800 10050  2048   1024   0      2024
"CDU Paint"           $7EEF 10277  273    8273   9273   10273



*** C128 Auto-boot sector layout *** Document revision: 1.1 *** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers *** Contributors/sources: unknown

The C128 has the ability to auto-boot a floppy disk that is in the  drive when the system is powered up, but only if track  1  sector  0  contains  a specific signature. Below is  a  dump  of  an  auto-boot  sector  with  its signature.

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
 -----------------------------------------------  ----------------
0000: 43 42 4D 00 0C 00 02 00 00 A5 D7 C9 80 F0 03 20  CBM��������ɀ���
0010: 5F FF A9 05 8D 06 D5 A9 4E 8D 00 FF 4C 00 0C 00  _�����թN���L���
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

Bytes 00-02: Auto-boot signature 'CBM'
03-04: ???
05-06: ???
07-08: ???
09-1E: Boot code
1F-FF: ???

Below is a disassembly of the machine code contained from 09-1E.

org = $0c00

      lda $d7
      cmp #$80
      beq skip1
      jsr $ff5f
skip1 lda #$05
      sta $d506
      lda #$4e
      sta $ff00
      jmp $0c00
.end

The only document I have found which attempts to explain  the  layout  of the C128 boot sector doesn't fit at all for the above sector layout.  I  am therefore not yet sure of all the details in the above sector.  Anyone  who has more info can contact me so I can update this document.



*** FRZ (C64s saved-session FRoZen files) *** Document revision: 1.3 *** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers *** Contributors/sources: Miha Peternel

These files, similar in nature to  PC64's  .C64  files,  are  a  complete memory dump of the 64K RAM, color RAM, and all I/O ports and CPU registers. The only file which can hold FRZ files is a T64, as its  directory/filetype values allow for it. These files (up to C64s V2.0), when converted  to  raw binaries, are 66806 bytes large.

01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
----------------------------------------------
00000: 00 00 .. .. .. .. .. .. .. .. .. .. .. .. .. ..  <- Load Address
 ...
00000: .. .. 2F 47 00 AA B1 91 B3 00 00 00 00 00 00 FF  <- 64k main RAM
00010: 00 00 00 40 02 00 BE 00 19 16 00 00 C9 9E 00 00
00020: 00 00 00 00 40 02 69 00 00 00 03 00 00 01 08 2A
00030: 3A A8 3A AA 4D C9 9E C9 9E 00 A0 BE 00 00 00 D9
 ...
10000: .. .. 01 01 01 01 01 01 01 01 01 01 01 01 01 01  <- Color RAM
10010: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
10020: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
10030: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
 ...
10400: .. .. F1 B0 F1 01 69 20 3A 00 00 00 00 00 00 00  <- I/O
10410: 00 00 00 00 00 00 00 00 00 00 00 9B 37 00 00 00
10420: 08 00 15 0F F0 00 00 00 00 00 00 00 01 02 03 04
10430: 00 01 02 03 04 05 06 07 4C 00 00 00 00 00 00 00
 ...

Bytes:$00000-00001: Load address (always $00 $00)
00002-10001: Main 64k RAM ($0000-FFFF)
0002-10401: Color RAM ($D800-DBFF)
10402-10409: CPU registers (8 bytes) in the following order:
          - PC (Program Counter, 2 bytes),
                       - SP (Stack Pointer, 2 bytes),
                       - A (Accumulator, 2 bytes)
                       - X/Y (X and Y registers, 2 bytes)
         1040A-10438: VIC-II ($D000, 47 bytes)
         10439-10455: SID ($D400, 29 bytes)
         10456-10465: CIA #1 ($DC00, 16 bytes)
         10466-10475: CIA #2 ($DD00, 16 bytes)
         10476-104F5: CPU Task data (128 bytes), containing:
                       - Shadow registers
                       - Emulation Registers

  Seeing as each emulator uses its own format  for  its  "snapshot"  files,
there is no simple conversion method to take one snapshot (i.e. a PC64 .C64
file) and convert it to another emulator snapshot format (i.e. a  C64s  FRZ
file). The only commonalities would be the  main  64k  RAM  and  color  RAM
areas, whereas the rest of the file would be quite different.


*** CKIT (Compression KIT compressed files)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Paul David Doherty,
                          Todd Elliott

  Written by Eugene F. Barker and Ryan Vander  Stoep,  this  archiver  does
whole-disk archiving from the various Commodore drives (1541/1571/1581), as
well as the larger CMD drives (hard disks). The  latest  known  version  is
"CKIT-94", meaning it was released  in  1994.  The  compressor  program  is
commercial  and  dongle  protected,  but  the  decompressor  is  publically
available. From reports I have received the compression used is RLE,  which
is not generally very good and it is also  not  very  fast.  One  point  in
CKIT's favor is that  it  supports  all  the  presently  available  storage
devices (CMD hard disks, Commodore 15xx floppy drives).

  The file extension for single disk files (i.e.  when  a  compressed  disk
archive only takes up one archive file) is "C4-". If an compressed  archive
takes more than 1 file, the extension changes to "C4A" for  the  first  and
"C`A" for the second. I do  not  know  what  the  extensions  will  be  for
compressed files taking more than two files, but CKIT  does  allow  for  an
archive to span up to 27 disks.

  The header of the compressed file always starts  with  the  string  "MMS"
(with a  space  and  $00  null  termination)  which  stands  for  "Mad  Man
Software", the company which makes the product.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 4D 4D 53 20 00 58 58 21 90 89 A0 00 60 00 04 00   MMS��XX!����`�.�
0010: 00 29 5A EC 94 03 40 06 20 2F BF D5 20 B4 68 81   �)Z��.@.�/����h�
0020: A0 8D 10 B4 10 AF 15 03 61 08 07 50 00 10 80 68   ��.�.�..a..P�.�h
0030: 8A 88 08 91 03 32 1A 0F B7 30 1D 94 D0 7B 28 80   ��.�.2..�0.��{(�

  Byte: $0000-0004 - ASCII string "MMS " with null termination.
         0005-0006 - Original Disk ID
         0007-???? - Compressed data

Any other information on this format would be greatly appreciated.


*** CPK
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Andre Fachat

  This format, created by Andre Fachat, was not designed for the  emulators
specifically, but was made primarily for Andre's own purposes.

  It is a very basic format using simple RLE compression,  with  each  file
following in sequential order (as Andre put it, "its similar to a UNIX  TAR
file"). There is no central directory, none of the files are byte  aligned,
and it uses compression so every file will be different.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 01 40 41 2E 41 4E 4C 2C 50 00 01 08 24 08 64 00   .@A.ANL,P�..$.d�
0010: 99 22 93 20 20 20 41 4E 4C 45 49 54 55 4E 47 20   �"����ANLEITUNG�
0020: 5A 55 4D 20 40 41 53 53 45 4D 42 4C 45 52 00 4E   ZUM�@ASSEMBLER�N
0030: 08 6E 00 99 22 11 40 41 53 53 20 49 53 54 20 45   .n��".@ASS�IST�E
0040: 49 4E 20 32 2D 50 41 53 53 2D 41 53 53 45 4D 42   IN�2-PASS-ASSEMB
0050: 4C 45 52 2E 20 44 45 52 00 78 08 78 00 99 22 11   LER.�DER�x.x��".

  The first byte of the file is the version byte. Presently,  only  $01  is
supported.

0000: 01 .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..   ................

  The filename  follows,  stored  in  standard  PETASCII,  and  no  padding
characters ($A0) are included.

0000: .. 40 41 2E 41 4E 4C .. .. .. .. .. .. .. .. ..   .@A.ANL.........

  The filetype is attached to the end of the filename in the form of  ',x',
where x is the filetype used (P,S,U), and it is in PETASCII upper case. The
filename ends with a $00 (null terminated). REL files are  *not*  supported
as there is no provision made for the RECORD size byte.

  Note that not *all* CPK files will have the ",x" extension added  on.  If
it doesn't exist, assume that the file is a "PRG" type.

0000: .. .. .. .. .. .. .. 2C 50 00 .. .. .. .. .. ..   .......,P�......

Following the filename, we get program data.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: .. .. .. .. .. .. .. .. .. .. 01 08 24 08 64 00   ............$.d�
0010: 99 22 93 20 20 20 41 4E 4C 45 49 54 55 4E 47 20   �"����ANLEITUNG�
 ...
0270: 00 83 0A E6 00 99 22 11 20 20 31 32 33 F7 08 20   ������".��123�.�
0280: 2D 44 45 5A 49 4D 41 4C 00 A4 0A F0 00 99 22 11   -DEZIMAL������".
0290: 20 20 24 33 34 35 F7 07 20 2D 48 45 58 41 44 45   ��$345�.�-HEXADE

  The data requires some explanation as it uses RLE (Run  Length  Encoding)
compression. When creating CPK files, data in the file to be compressed  is
scanned for runs of repeating bytes, and when a string of 3 or more (up  to
255) is found, then the following sequence of bytes is output...

  $F7 $xx $yy - where F7 is the code used for "encoded  sequence  follows",
                $xx is the number of times to repeat the byte  and  $yy  is
                the byte to repeat. Using the sample below, we see  the  F7
                code, then a "repeat 7 times the number $20"

0290: .. .. .. .. .. .. F7 07 20 .. .. .. .. .. .. ..   ......�.�.......

  Using $F7 as the encoder byte presents one problem: When encoding a file,
and we encounter an $F7, what does the packer do? Simple, it  gets  encoded
into $F7 $xx $F7 meaning repeat $F7 for as many times as is needed (if  its
only 1 $F7, then the value for $xx  is  $01).  The  code  'F7'  was  chosen
because it is not a 6502 opcode, a BASIC token, or any commonly used  byte,
but *not* because it has the least statistical probability of occuring.

  The stored program ends when the string $F7  $00  is  encountered,  since
this sequence can not occur in the file naturally. If you  need  to  search
through a CPK file for the filenames, do a  hex  search  for  all  $F7  $00
sequences, since they preceed all filenames except the first.

  The end of a CPK file can be found two different ways:

    1. When an EOF (end of file) occurs, after an $F7  $00  byte  sequence.
       This is the normal method.
    2. When a filename of $00 occurs, meaning there is no filename, just  a
       null termination. This is not much used anymore.

  Using method #1 for ending the file  is  more  common  because  it  makes
adding files to the CPK file very easy. All you have to do  as  append  the
new filename/data to the container. Using method #2 means you have to check
and see if the last three characters are $F7 $00 $00, and start writing the
new file into the container starting after the first $00.

  In order to extract *one* specific file, you would need to read the whole
file until you find the filename you want, then output that file  only.  As
this format has no central directory and no file location references, there
is no other way to do it.

  This format has not been used for some time now, as when it came out  D64
and T64 were also being developed and  accepted  into  common  use.  It  is
unlikely you will find *any* files in this format.  64COPY  V3.2  (and  up)
does support extraction of these files just in case any are encountered.


*** CRT - CaRTridge Images (from the CCS64 emulator)
*** Document revision: 1.15
*** Last updated: Dec 10, 2009
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Per Hakan Sundell,
                          Markus Brenner
                          Marco Van Den Heuvel
                          Thomas Giesel

  Cartridge files were introduced in the CCS64  emulator,  written  by  Per
Hakan Sundell, and use the ".CRT" file extension. This format  was  created
to handle the various ROM cartridges that exist, such as Action Replay, the
Power cartridge, and the Final Cartridge.

  Normal game cartridges can load  into  several  different  memory  ranges
($8000-9FFF,  $A000-BFFF  or  $E000-FFFF).  Newer   utility   and   freezer
cartridges were less intrusive, hiding themselves until  called  upon,  and
still others used bank-switching techniques to allow much larger ROM's than
normal. Because of these "stealthing" and bank-switching methods, a special
cartridge format  was  necessary,  to  let  the  emulator  know  where  the
cartridge should reside, the control line  states  to  enable  it  and  any
special hardware features it uses.

  Here is a dump of a sample 8K normal cartridge,  "Attack  Of  The  Mutant
Camels"...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 00 00 01 00 00 00 00 00 00   ���@������������
0020: 41 54 54 41 43 4B 20 4F 46 20 54 48 45 20 4D 55   ATTACK�OF�THE�MU
0030: 54 41 4E 54 20 43 41 4D 45 4C 53 00 00 00 00 00   TANT�CAMELS�����
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: D3 9B BC FE C3 C2 CD 38 30 EA EA EA A9 01 85 13   ӛ�����80�������
0060: 4C B3 9B A9 08 85 5A 88 D0 FD C6 5A D0 F9 60 D0   L�����Z����Z��`�

  Bytes:$0000-000F - 16-byte cartridge signature  "C64  CARTRIDGE"  (padded
                     with space characters)
         0010-0013 - File header length  ($00000040,  in  high/low  format,
                     calculated from offset $0000). The default and minimum
                     value is $40. Some faulty cartridge images exist which
                     show an incorrect value of $00000020.
         0014-0015 - Cartridge version (high/low, presently 01.00)
         0016-0017 - Cartridge hardware type ($0000, high/low)
                       0 - Normal cartridge
                       1 - Action Replay
                       2 - KCS Power Cartridge
                       3 - Final Cartridge III
                       4 - Simons Basic
                       5 - Ocean type 1 (*note)
                       6 - Expert Cartridge
                       7 - Fun Play, Power Play
                       8 - Super Games
                       9 - Atomic Power
                      10 - Epyx Fastload
                      11 - Westermann Learning
                      12 - Rex Utility
                      13 - Final Cartridge I
                      14 - Magic Formel
                      15 - C64 Game System, System 3
                      16 - WarpSpeed
                      17 - Dinamic (**note)
                      18 - Zaxxon, Super Zaxxon (SEGA)
                      19 - Magic Desk, Domark, HES Australia
                      20 - Super Snapshot 5
                      21 - Comal-80
                      22 - Structured Basic
                      23 - Ross
                      24 - Dela EP64
                      25 - Dela EP7x8
                      26 - Dela EP256
                      27 - Rex EP256
                      28 - Mikro Assembler
                      29 - reserved
                      30 - Action Replay 4
                      31 - StarDOS
                      32 - EasyFlash
              0018 - Cartridge port /EXROM line status
                      0 - active (low)
                      1 - inactive (high)
              0019 - Cartridge port /GAME line status
                      0 - active (low)
                      1 - inactive (high)
         001A-001F - Reserved for future use
         0020-003F - 32-byte cartridge  name  "CCSMON"  (uppercase,  padded
                     with null characters)
         0040-xxxx - Cartridge contents (called CHIP PACKETS, as there  can
                     be more than one  per  CRT  file).  See  below  for  a
                     breakdown of the CHIP format.

  The /EXROM and /GAME lines are active low lines, so a 0 means  active  or
selected and a 1 means disabled or not selected.

  (*Note: Ocean type 1 includes Navy Seals, Robocop 2 & 3,  Shadow  of  the
    Beast, Toki, Terminator 2 and more)

  (**Note: Dinamic includes Narco Police and more)


---------------------------------------------------------------------------


CHIP Contents
-------------

  The following is the contents of the CHIP packet, from position $0040  on
in the CRT file. Note I have re-adjusted the starting address to be  $0000,
since we are now looking at a file contained in the .CRT file, and all size
references are from where it starts.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0010: D3 9B BC FE C3 C2 CD 38 30 EA EA EA A9 01 85 13   ӛ�����80�������
0020: 4C B3 9B A9 08 85 5A 88 D0 FD C6 5A D0 F9 60 D0   L�����Z����Z��`�
0030: F2 60 A9 04 85 49 A9 00 85 48 A2 00 A5 48 9D 40   �`���I���H���H�@
0040: 03 A5 49 9D 60 03 A5 48 18 69 28 85 48 A5 49 69   ��I�`��H�i(�H�Ii
0050: 00 85 49 E8 E0 18 D0 E4 60 A6 03 A4 02 BD 40 03   ��I�����`�����@�

  Bytes:$0000-0003 - Contained ROM signature "CHIP" (note there can be many
                     modules in a .CRT file)
         0004-0007 - Total packet length ($00002010,  ROM  image  size  and
                     header combined) (high/low format)
         0008-0009 - Chip type
                      0 - ROM
                      1 - RAM, no ROM data
                      2 - Flash ROM
         000A-000B - Bank number ($0000 - normal cartridge)
         000C-000D - Starting load address (high/low format)
         000E-000F - ROM image size in bytes  (high/low  format,  typically
                     $2000 or $4000)
         0010-xxxx - ROM data


---------------------------------------------------------------------------


  The following is a chart taken from the "Commodore Programmers  Reference
Guide". It details the state of various areas of memory  depending  on  the
state of the control lines.


Legend:
L - ROML (low)
H - ROMH (high)
G - /GAME (active low)
E - /EXROM (active low)

Addr       LHGE   LHGE   LHGE   LHGE   LHGE   LHGE   LHGE   LHGE   LHGE
Range
           1111   101X   1000   011X   001X   1110   0100   1100   XX01
         default                00X0                             Ultimax
-------------------------------------------------------------------------
E000-FFFF Kernal  RAM    RAM   Kernal  RAM   Kernal Kernal Kernal ROMH(*)
D000-DFFF IO/CHR IO/CHR IO/RAM IO/CHR  RAM   IO/CHR IO/CHR IO/CHR   I/O
C000-CFFF  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
A000-BFFF BASIC   RAM    RAM    RAM    RAM   BASIC   ROMH   ROMH    -
8000-9FFF  RAM    RAM    RAM    RAM    RAM    ROML   RAM    ROML  ROML(*)
4000-7FFF  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
1000-3FFF  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
0000-0FFF  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM

(*) Internal memory does not respond to write accesses in these areas


  From the above chart, the following table can be built. It shows standard
cartridges, either 8K or 16K in size, and the memory ranges they load into.

         Type     Size  /GAME  /EXROM    Low Bank    High Bank
                  in K   Line   Line      (ROML)      (ROMH)
         -----------------------------------------------------
         Normal    8k     hi     lo     $8000-9FFF     ----
         Normal    16k    lo     lo     $8000-9FFF  $A000-BFFF
         Ultimax   8k     lo     hi     $E000-FFFF     ----
         Ultimax   16k    lo     hi     $8000-9FFF  $E000-FFFF

  The ROMH and ROML lines are CPU-controlled status  lines,  used  to  bank
in/out RAM, ROM or I/O, depending on what is needed at the time. The  /GAME
and /EXROM lines are active-low lines.

  Ultimax cartridges typically are situated  in  the  $E000-FFFF  (8K)  ROM
address range. There are some cartridges  which  only  use  4K  of  the  8K
allocation. If the cartridge is 16K in size, then it will  reside  in  both
$8000-9FFF and $E000-FFFF.

  Ultimax mode is very different from most other cartridges. When  enabled,
there is 4Kb of RAM at $0000-$0FFF, 8Kb of cartridge  ROM  at  $8000-$9FFF,
4Kb  of  I/O  registers  at  $D000-$DFFF  and  8Kb  of  cartridge  rom   at
$E000-$FFFF. All other addresses are unusable.


---------------------------------------------------------------------------


Cartridge Specifics
-------------------

0 - Normal cartridge

    Size      : 8Kb
    Addr Range: $8000-9FFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 00 00 01 00 00 00 00 00 00   ���@������������
0020: 41 54 54 41 43 4B 20 4F 46 20 54 48 45 20 4D 55   ATTACK�OF�THE�MU
0030: 54 41 4E 54 20 43 41 4D 45 4C 53 00 00 00 00 00   TANT�CAMELS�����
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: D3 9B BC FE C3 C2 CD 38 30 EA EA EA A9 01 85 13   ӛ�����80�������



      The second sample below is a dump of "Music Machine", a  4Kb  ULTIMAX
    mode cartridge. It  is  still  identified  as  a  "standard  cartridge"
    according to the ID.

    Size      : 4Kb (ULTIMAX mode)
    Addr range: $F000-F7FF
    /EXROM    : inactive (1)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 00 01 00 00 00 00 00 00 00   ���@������������
0020: 4D 55 53 49 43 20 4D 41 43 48 49 4E 45 00 00 00   MUSIC�MACHINE���
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 10 10 00 00 00 00 F0 00 10 00   CHIP������������
0050: 3C 66 C3 C3 66 3C FF FF 18 3C 66 7E 66 66 66 00   <f��f<���<f~fff�



      The third sample is a dump of "Adventure Creator",  a  16Kb  standard
    cartridge.

    Size      : 16Kb
    Addr range: $8000-BFFF
    /EXROM    : active (0)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 00 00 00 00 00 00 00 00 00   ���@������������
0020: 41 64 76 65 6E 74 75 72 65 20 43 72 65 61 74 6F   Adventure�Creato
0030: 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   r���������������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00   CHIP��@�������@�
0050: 09 80 81 EA C3 C2 CD 38 30 A2 00 78 D8 8E 11 D0   �������80��x؎��


===========================================================================


1 - Action Replay

    Size      : 32Kb (4 banks of 8Kb each)
    Addr range: $8000-9FFF (all modules)
    /EXROM    : active (0)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 01 00 00 00 00 00 00 00 00   ���@������������
0020: 41 63 74 69 6F 6E 20 52 65 70 6C 61 79 20 56 00   Action�Replay�V�
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: 09 80 0C 80 C3 C2 CD 38 30 4C 60 80 4C 63 80 4C   �������80L`�Lc�L


===========================================================================


2 - KCS Power Cartridge

    Size      : 16Kb (2 banks of 8K each)
    Addr range: module #1: $8000-9FFF
                module #2: $A000-BFFF
    /EXROM    : active (0)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 20 01 00 00 02 00 00 00 00 00 00 00 00   ����������������
0020: 4B 43 53 20 50 6F 77 65 72 20 43 61 72 74 72 69   KCS�Power�Cartri
0030: 64 67 65 00 00 00 00 00 00 00 00 00 00 00 00 00   dge�������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: 09 80 5E FE C3 C2 CD 38 30 78 D8 A2 FF 9A A9 27   ��^����80xآ���'
....
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00   CHIP������������
2060: 97 E3 16 A1 FF FF FF 20 13 A0 A5 01 09 01 85 01   ����������������


===========================================================================


3 - Final Cartridge III

    Size      : 64Kb (4 banks of 16Kb each)
    Addr range: $8000-BFFF (all modules)
    /EXROM    : inactive (1)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 03 01 01 00 00 00 00 00 00   ���@������������
0020: 46 69 6E 61 6C 20 43 61 72 74 72 69 64 67 65 20   Final�Cartridge�
0030: 49 49 49 20 31 39 38 37 00 00 00 00 00 00 00 00   III�1987��������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00   CHIP��@�������@�
0050: 09 80 5E FE C3 C2 CD 38 30 4C 4C 80 4C 55 95 4C   ��^����80LL�LU�L
....
4050: 43 48 49 50 00 00 40 10 00 00 00 01 80 00 40 00   CHIP��@�������@�
4060: 01 02 00 81 5D 81 61 81 99 81 D8 81 0B 82 33 82   ����]�a���؁��3�
....
8060: 43 48 49 50 00 00 40 10 00 00 00 02 80 00 40 00   CHIP��@�������@�
8070: 20 43 80 20 52 80 A9 4E 20 05 DE 20 FD BF AD 39   �C��R��N�������9
....
C070: 43 48 49 50 00 00 40 10 00 00 00 03 80 00 40 00   CHIP��@�������@�
C080: A2 06 BD DD 85 95 05 CA 10 F8 AE A0 02 E8 EC A2   ���݅�����������

    A total of 64 kB of ROM memory  is  organized  into  four  $4000  banks
    located at $8000-$BFFF. Bank switching is  done  by  writing  the  bank
    number plus $40 into memory location $DFFF.  For  instance,  to  select
    bank 2, $DFFF is set to $42.

    The CRT file contains four CHIP blocks, each block with a start address
    of $8000, length $4000 and the bank number in the bank  field.  In  the
    cartridge header, both /EXROM ($18) and /GAME ($19) are  set  to  1  to
    enable the 16 kB ROM configuration.


===========================================================================


4 - Simons Basic

    Size      : 16Kb (2 banks of 8kb each)
    Addr range: module #1: $8000-9FFF
                module #2: $A000-BFFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 04 00 01 00 00 00 00 00 00   ���@������������
0020: 53 69 6D 6F 6E 27 73 20 42 61 73 69 63 00 00 00   Simon's�Basic���
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: 52 81 52 81 C3 C2 CD 38 30 41 4C 52 81 20 2C 81   R�R����80ALR��,�
....
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00   CHIP������������
2060: 20 A4 A6 99 9E CB A0 05 A5 A8 91 20 A4 A6 99 A2   �����ˠ���������

    SIMONS BASIC permanently uses 16 kB ($4000) bytes of  cartridge  memory
    from $8000-$BFFF. However, through some custom bank-switching logic the
    upper area ($A000-$BFFF) may be disabled so Simons BASIC may use it  as
    additional RAM. Writing a value of $01 to address location $DE00  banks
    in ROM, $00 disables ROM and enables RAM.

    (A user reported that simply loading from any  $DExx  address  switched
    the configuration to 8K, opening up  $A000-BFFF,  and  writing  to  any
    $DExx address re-enables the 16K layout.)

    The CRT file contains two CHIP blocks of length $2000 each,  the  first
    block having a start address of $8000, the second block $A000.  In  the
    cartridge header, /EXROM ($18) is set to 0 & /GAME ($19) is set to 1 to
    indicate the RESET/power-up configuration of 8 kB ROM.


===========================================================================


5 - Ocean type 1

    Size      :  16 Kb (2 banks), banks are 8Kb
                 32 Kb (4 banks)
                 64 Kb (8 banks)
                128 Kb (16 banks)
                256 Kb (32 banks)
                512 Kb (64 banks)
    Addr range: Banks 00-15: $8000-9FFF
                Banks 16-31: $A000-BFFF (except Terminator 2)
    /EXROM    : active (0)
    /GAME     : active (0)

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
       -----------------------------------------------   ----------------
00000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
00010: 00 00 00 40 01 00 00 05 00 00 00 00 00 00 00 00   ���@������������
00020: 53 48 41 44 4F 57 20 4F 46 20 54 48 45 20 42 45   SHADOW�OF�THE�BE
00030: 41 53 54 00 00 00 00 00 00 00 00 00 00 00 00 00   AST�������������
00040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
00050: 09 80 83 81 C3 C2 CD 38 30 4C 83 81 4C 76 82 80   �������80L��Lv��
 ....
02050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00   CHIP������������
02060: 59 6D 00 56 AD 00 55 AE F0 00 01 A0 FE 00 01 F8   Ym�V��U���������
 ....
20140: 43 48 49 50 00 00 20 10 00 00 00 10 A0 00 20 00   CHIP������������
20150: 0A 9A 55 FF 9B 69 57 FE AA 65 96 FE 65 0F D6 D9   ��U��iW��e��e���

    Here is a partial list of the OCEAN cartridges:

    Fort Apocalypse     ( 16 Kb)
    Ghostbusters        ( 32 Kb)
    Kung Fu Master      ( 32 Kb)
    Leaderboard Golf    ( 32 Kb)
    Tournament Tennis   ( 32 Kb)
    Badlands            ( 64 Kb)
    Vindicators         ( 64 Kb)
    Wonderboy           ( 64 Kb)
    Batman The Movie    (128 Kb)
    Battle Command      (128 Kb)
    Double Dragon       (128 Kb)
    Navy Seals          (128 Kb)
    Pang                (128 Kb)
    Robocop 3           (128 Kb)
    Space Gun           (128 Kb)
    Toki                (128 Kb)
    Chase H.Q. II       (256 Kb)
    Robocop 2           (256 Kb)
    Shadow of the Beast (256 Kb)
    Terminator 2        (512 Kb)

    Memory is divided into 8Kb banks. For  the  lower  128Kb  (bank  0-15),
    memory is banked into  $8000-$9FFF  and  for  the  upper  128Kb  (banks
    16-31), memory is banked into $A000-$BFFF. When a  bank  in  the  range
    0-15 is banked in, the second bank range $A000-BFFF is undefined.  When
    a bank in the range from 16-31 is banked  in  then  the  address  range
    $8000-9FFF is undefined.

    The expection to this is the Terminator 2 cartridge. It  loads  all  64
    banks at $8000-$9FFF, and BASIC is visible from $A000-BFFF.

    Bank switching is done by writing to $DE00. The lower six bits give the
    bank number (ranging from 0-63). Bit 8 in this selection word is always
    set.


===========================================================================


6 - Expert Cartridge

    Size      : 8Kb
    Addr range: $8000-9FFF
    /EXROM    : inactive (1)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 06 01 01 00 00 00 00 00 00   ���@������������
0020: 45 78 70 65 72 74 20 43 61 72 74 72 69 64 67 65   Expert�Cartridge
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 40 10 00 02 00 00 80 00 20 00   CHIP��@���������
0050: 00 00 00 0A F3 00 00 00 00 00 00 00 00 00 00 00   ����������������


===========================================================================


7 - Fun Play, Power Play

    Size      : 128Kb (16 banks of 8Kb modules)
    Addr range: $8000-9FFF (all modules)
    /EXROM    : active (0)
    /GAME     : active (0)

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
       -----------------------------------------------   ----------------
00000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
00010: 00 00 00 40 01 00 00 07 00 00 00 00 00 00 00 00   ���@������������
00020: 46 55 4E 20 50 4C 41 59 00 00 00 00 00 00 00 00   FUN�PLAY��������
00030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
00050: 1E 80 86 EA C3 C2 CD 38 30 1B 00 81 0D 08 80 00   �������80�������
 ....
02050: 43 48 49 50 00 00 20 10 00 00 00 08 80 00 20 00   CHIP������������
02060: 78 A2 F0 86 01 BD 1D 08 9D F8 00 CA D0 F7 4C 00   x�������������L�
 ....
04060: 43 48 49 50 00 00 20 10 00 00 00 10 80 00 20 00   CHIP������������
04070: 38 E5 68 85 03 B0 11 27 03 12 C0 18 69 27 42 90   8�h����'����i'B�
 ....
06070: 43 48 49 50 00 00 20 10 00 00 00 18 80 00 20 00   CHIP������������
06080: 44 D0 5E 06 02 C0 44 11 40 04 11 44 01 5F 1C 73   D�^���D�@��D�_�s
 ....
1E130: 43 48 49 50 00 00 20 10 00 00 00 39 80 00 20 00   CHIP�������9����
1E140: 85 EB 41 EA 9E 08 03 00 C0 06 18 01 00 C0 08 03   ��A�������������

      The FUN PLAY Cartridge uses $DE00 for bank selection,  and  uses  8Kb
    banks ($2000) at $8000-$9FFF. There are 16 banks of ROM memory and  are
    referenced by the following values:

    $00 -> Bank 0
    $08 -> Bank 1
    $10 -> Bank 2
    $18 -> Bank 3
    $20 -> Bank 4
    $28 -> Bank 5
    $30 -> Bank 6
    $38 -> Bank 7
    $01 -> Bank 8
    $09 -> Bank 9
    $11 -> Bank 10
    $19 -> Bank 11
    $21 -> Bank 12
    $29 -> Bank 13
    $31 -> Bank 14
    $39 -> Bank 15

      The bank field in the chip headers is  set  according  to  the  value
    written to $DE00. The following bits are  used  for  bank  decoding  in
    $DE00 (0 being the LSB, 3 being the MSB).

        Bit# 76543210
             xx210xx3

      After copying memory from the ROM banks, the selection program writes
    a value of $86 to $DE00. This seems either  to  reset  or  disable  the
    cartridge ROM.


===========================================================================


8 - Super Games

    Size      : 64Kb (4 banks of 16Kb each)
    Addr range: $8000-BFFF (all modules)
    /EXROM    : active (0)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 08 00 00 00 00 00 00 00 00   ���@������������
0020: 53 55 50 45 52 20 47 41 4D 45 53 00 00 00 00 00   SUPER�GAMES�����
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00   CHIP��@�������@�
0050: 0A 80 0A 80 C3 C2 CD 38 30 00 A9 80 A0 00 85 FB   �������80�������
....
4050: 43 48 49 50 00 00 40 10 00 00 00 01 80 00 40 00   CHIP��@�������@�
4060: 27 80 A8 80 C3 C2 CD 38 30 00 40 C0 40 C0 40 C0   '������80�@�@�@�
....
8060: 43 48 49 50 00 00 40 10 00 00 00 02 80 00 40 00   CHIP��@�������@�
8070: 00 00 00 49 4D C7 64 47 46 45 F3 48 DC 08 7E 0B   ���IM�dGFE�H��~�
....
C070: 43 48 49 50 00 00 40 10 00 00 00 03 80 00 40 00   CHIP��@�������@�
C080: D5 F9 F0 C1 D5 F7 F0 BD E8 B5 02 F0 FB C9 05 30   ���������������0

      The SUPER GAMES cartridge uses 4  16Kb  banks  ($8000-$BFFF)  of  ROM
    memory. Bank selecting is done by writing to $DF00.

    Values for $DF00:

    $00 -> Bank 0
    $01 -> Bank 1 (also value $09 used)
    $02 -> Bank 2
    $03 -> Bank 3

      Bit #2:   0 = ROM $8000-$BFFF
                1 = ROM $8000-$9FFF
      Bit #3:   0 = ?
                1 = if bit #2 AND #3 are on (1) then the module is off


===========================================================================


9 - Atomic Power

    Size      : 32Kb (4 banks of 8Kb modules)
    Addr range: $8000-9FFF (all modules)
    /EXROM    : active (0)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 09 00 00 00 00 00 00 00 00   ���@������������
0020: 41 74 6F 6D 69 63 20 50 6F 77 65 72 00 00 00 00   Atomic�Power����
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: 09 80 0C 80 C3 C2 CD 38 30 4C 41 80 4C 1E 80 4C   �������80LA�L��L
....
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00   CHIP������������
2060: 09 80 0C 80 C3 C2 CD 38 30 4C 3F 80 4C 91 80 4C   �������80L?�L��L
....
4060: 43 48 49 50 00 00 20 10 00 00 00 02 80 00 20 00   CHIP������������
4070: EF FC 09 80 C3 C2 CD 38 30 4C 27 80 4C DB 81 4C   �������80L'�LہL
....
6070: 43 48 49 50 00 00 20 10 00 00 00 03 80 00 20 00   CHIP������������
6080: 09 80 0C 80 C3 C2 CD 38 30 4C 73 86 4C 30 80 4C   �������80Ls�L0�L


===========================================================================


10 - Epyx Fastload

     Size      : 8Kb
     Addr range: $8000-9FFF
     /EXROM    : inactive (1)
     /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 0A 01 01 00 00 00 00 00 00   ���@������������
0020: 45 50 59 58 20 46 41 53 54 4C 4F 41 44 00 00 00   EPYX�FASTLOAD���
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: 30 80 5E FE C3 C2 CD 38 30 20 04 90 4C 38 DF AB   0�^����80���L8߫


===========================================================================


11 - Westermann Learning

     Size      : 16Kb
     Addr Range: $8000-BFFF
     /EXROM    : active (0)
     /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 0B 00 00 00 00 00 00 00 00   ���@������������
0020: 57 45 53 54 45 52 4D 41 4E 4E 00 00 00 00 00 00   WESTERMANN������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 40 00   CHIP����������@�
0050: 09 80 9C 80 C3 C2 CD 38 30 A2 00 8E 16 D0 20 84   �������80�������


===========================================================================


12 - Rex Utility

     Size      : 8K
     Addr range: $8000-9FFF
     /EXROM    : active (0)
     /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 0C 00 01 00 00 00 00 00 00   ���@������������
0020: 52 45 58 00 00 00 00 00 00 00 00 00 00 00 00 00   REX�������������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00   CHIP������������
0050: 08 80 C1 FE C3 C2 CD 38 30 6C 95 E3 20 A3 FD 20   �������80l������


===========================================================================


13 - Final Cartridge I

     Size      : 16Kb
     Addr range: $8000-BFFF
     /EXROM    : inactive (1)
     /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20   C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 0D 01 01 00 00 00 00 00 00   ���@������������
0020: 54 68 65 20 46 69 6E 61 6C 20 43 61 72 74 72 69   The�Final�Cartri
0030: 64 67 65 20 49 00 00 00 00 00 00 00 00 00 00 00   dge�I�����������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00   CHIP��@�������@�
0050: 80 BA 5E FE C3 C2 CD 38 30 00 A0 A0 20 2D FE 58   ��^����80����-�X


===========================================================================


14 - Magic Formel

     Size      : 64Kb (8 banks of 8Kb)
     Addr range: $E000-FFFF
     /EXROM    : inactive (1)
     /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 0E 01 01 00 00 00 00 00 00  ���@������������
0020: 4D 61 67 69 63 20 46 6F 72 6D 65 6C 00 00 00 00  Magic�Formel����
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 E0 00 20 00  CHIP������������
0050: 4D 46 30 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF0���`���`���`�
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 E0 00 20 00  CHIP������������
2060: 4C 5F E4 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  L_����`���`���`�
...
4060: 43 48 49 50 00 00 20 10 00 00 00 02 E0 00 20 00  CHIP������������
4070: 4D 46 32 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF2���`���`���`�
...
6070: 43 48 49 50 00 00 20 10 00 00 00 03 E0 00 20 00  CHIP������������
6080: 4D 46 33 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF3���`���`���`�
...
8080: 43 48 49 50 00 00 20 10 00 00 00 04 E0 00 20 00  CHIP������������
8090: 4D 46 34 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF4���`���`���`�
...
A090: 43 48 49 50 00 00 20 10 00 00 00 05 E0 00 20 00  CHIP������������
A0A0: 4D 46 35 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF5���`���`���`�
...
C0A0: 43 48 49 50 00 00 20 10 00 00 00 06 E0 00 20 00  CHIP������������
C0B0: 4D 46 36 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF6���`���`���`�
..
E0B0: 43 48 49 50 00 00 20 10 00 00 00 07 E0 00 20 00  CHIP������������
E0C0: 4D 46 37 8D 00 DF 60 8D 01 DF 60 8D 02 DF 60 8D  MF7���`���`���`�


===========================================================================


15 - C64 Game System, System 3

     Size      : 512Kb (64 banks of 8Kb each)
     Addr range: $8000-9FFF (all modules)
     /EXROM    : active (0)
     /GAME     : inactive (1)

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
000000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
000010: 00 00 00 40 01 00 00 0F 00 01 00 00 00 00 00 00  ���@������������
000020: 43 36 34 47 53 20 43 61 72 74 72 69 64 67 65 00  C64GS�Cartridge�
000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
000050: 6D 80 C5 80 C3 C2 CD 38 30 4C CB 80 4C 36 84 4C  m�ŀ���80LˀL6�L
....
002050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP������������
002060: 18 D0 A9 FF 8D 15 D0 8D 1D D0 8D 17 D0 A2 07 A9  �Щ���Ѝ�Ѝ�Т��
....
004060: 43 48 49 50 00 00 20 10 00 00 00 02 80 00 20 00  CHIP������������
004070: E0 08 19 21 77 84 52 98 9F 80 A5 21 31 01 31 89  ���!w�R����!1�1�
....
006070: 43 48 49 50 00 00 20 10 00 00 00 03 80 00 20 00  CHIP������������
006080: C0 08 1C 1D A0 92 03 03 D8 AA 04 C0 B8 01 40 EA  ��������ت���@�
....
07E430: 43 48 49 50 00 00 20 10 00 00 00 3F 80 00 20 00  CHIP�������?����
07E440: 45 20 41 20 42 49 47 20 58 FE 4F 4E 20 54 48 49  E�A�BIG�X�ON�THI

    Here is a list of the known cartridges:

    C64GS 4-in-1      (Commodore)  (512 kB)
    Last Ninja Remix  (System 3)   (512 kB)
    Myth              (System 3)   (512 kB)

    ROM memory is organized in 8Kb ($2000) banks  located  at  $8000-$9FFF.
    Bank switching is done by writing to address $DE00+X, where  X  is  the
    bank number (STA $DE00,X). For instance, to read from bank  3,  address
    $DE03 is accessed.

    The CRT file contains a string of CHIP blocks, each block with a  start
    address of $8000, length $2000 and the bank number in the  bank  field.
    In the cartridge header, /EXROM ($18) is set to 0, /GAME ($19)  is  set
    to 1 to enable the 8Kb ROM configuration.


===========================================================================


16 - WarpSpeed

     Size      : 16Kb
     Addr range: $8000-BFFF
     /EXROM    : inactive (1)
     /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 10 01 01 00 00 00 00 00 00  ���@������������
0020: 57 61 72 70 73 70 65 65 64 00 00 00 00 00 00 00  Warpspeed�������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00  CHIP��@�������@�
0050: 4C 22 80 4C 22 80 FF 43 42 4D 20 53 E4 20 18 E5  L"�L"��CBM�S����

     After RESET or  POWER  ON,  16kB  of  Cartridge  ROM  are  visible  at
     $8000-$BFFF. Additionally, ROM normally located  at  $9E00-$9FFF  is
     mirrored into IO1 and  IO2  at  $DE00-$DFFF.  ROM  at  $8000-$BFFF  is
     disabled by writing into the IO2 area (typically  $DF00)  and  may  be
     re-enabled by writing  into  IO1  ($DE00).  However,  the  $DE00-$DFFF
     (IO1/IO2) area itself always remains mapped to cartridge ROM.


===========================================================================


17 - Dinamic

     Size      : 128Kb (16 banks of 8Kb each)
     Addr range: $8000-9FFF (all modules)
     /EXROM    : active (0)
     /GAME     : inactive (1)

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
000000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
000010: 00 00 00 40 01 00 00 11 00 01 00 00 00 00 00 00  ���@������������
000020: 4E 61 72 63 6F 20 50 6F 6C 69 63 65 00 00 00 00  Narco�Police����
000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
000050: 0B 80 0B 80 C3 C2 CD 38 30 00 00 78 A2 FF 9A D8  �������80��x����
..
002050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP������������
002060: 1C 8C 1B 8C 16 16 8F 16 16 88 1C 1C 86 1C 1C 89  ����������������
..
004060: 43 48 49 50 00 00 20 10 00 00 00 02 80 00 20 00  CHIP������������
004070: B6 02 07 08 07 07 00 0A 0A B6 00 05 0A 00 07 07  ����������������
..
01E130: 43 48 49 50 00 00 20 10 00 00 00 0F 80 00 20 00  CHIP������������
01E140: 00 D5 70 03 F5 70 0F 5F 70 0F F7 70 35 FD F0 37  ��p��p�_p��p5��7

    Here is a list of the known DINAMIC cartridges:

    Narco Police  (128 kB)
    Satan         (128 kB)

    ROM memory is organized in 8Kb ($2000) banks  located  at  $8000-$9FFF.
    Bank switching is done by reading from address $DE00+X, where X is  the
    bank number (LDA $DE00,X). For instance, to read from bank  3,  address
    $DE03 is accessed.

    The CRT file contains a string of CHIP blocks, each block with a  start
    address of $8000, length $2000 and the bank number in the  bank  field.
    In the cartridge header, /EXROM ($18) is set to 0 & /GAME ($19) is  set
    to 1 to enable the 8Kb ROM configuration.


===========================================================================


18 - Zaxxon, Super Zaxxon (SEGA)

     Size      : 20Kb (3 banks of different sizes)
     Addr range: $8000-8FFF (mirrored in $9000-9FFF, module 0, chip U1)
                 $A000-BFFF (banked modules 1 and 2, chip U2)
     /EXROM    : active (0)
     /GAME     : active (0)

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
000000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
000010: 00 00 00 40 01 00 00 12 00 00 00 00 00 00 00 00  ���@������������
000020: 5A 61 78 78 6F 6E 00 00 00 00 00 00 00 00 00 00  Zaxxon����������
000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000040: 43 48 49 50 00 00 10 10 00 00 00 00 80 00 10 00  CHIP������������
000050: 0D 80 29 80 C3 C2 CD 38 30 78 4C 09 80 78 A9 00  ��)����80xL��x��
..
001050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00  CHIP������������
001060: A2 0F BD 00 20 D0 04 CA 10 F8 60 BD 70 20 F0 0D  ����������`�p���
..
003060: 43 48 49 50 00 00 20 10 00 00 00 01 A0 00 20 00  CHIP������������
003070: 65 A2 36 A3 E7 A3 CB A4 94 A5 86 A6 5E A7 35 A8  e�6���ˤ����^�5�

    The (Super) Zaxxon carts use a 4Kb ($1000) ROM at $8000-$8FFF (mirrored
    in $9000-$9FFF) along with two 8Kb ($2000) cartridge banks  located  at
    $A000-$BFFF. One of the two banks is selected by doing a read access to
    either the $8000-$8FFF area (bank 0 is selected) or to $9000-$9FFF area
    (bank 1 is selected). /EXROM ($18 = $00) and /GAME ($19  =  $00)  lines
    are always pulled to GND to select the 16 kB ROM configuration.

    The CRT file includes three CHIP blocks:
    a) bank = 0, load address = $8000, size = $1000
    b) bank = 0, load address = $A000, size = $2000
    c) bank = 1, load address = $A000, size = $2000


===========================================================================


19. Magic Desk, Domark, HES Australia

    Size      : 32Kb, 64Kb or 128Kb sizes (4 to 16 banks of 8Kb each)
    Addr range: $8000-9FFF (all banks)
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 13 00 01 00 00 00 00 00 00  ���@������������
0020: 4D 61 67 69 63 20 44 65 73 6B 00 00 00 00 00 00  Magic�Desk������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
0050: 09 80 C6 CA C3 C2 CD 38 30 8E 16 D0 20 A3 FD 20  �������80�������
..
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP������������
2060: 00 3F 0A 01 00 86 4E 24 28 31 30 29 3A 4A 4F 59  �?����N$(10):JOY
..
4060: 43 48 49 50 00 00 20 10 00 00 00 02 80 00 20 00  CHIP������������
4070: 00 8B C9 28 4E 24 2C 31 29 B3 B1 22 FF 22 A7 32  ���(N$,1)��"�"�2
..
6070: 43 48 49 50 00 00 20 10 00 00 00 03 80 00 20 00  CHIP������������
6080: AE 01 83 33 2C 37 2C 22 32 29 20 44 45 4C 20 4B  ���3,7,"2)�DEL�K

    This cartridge type is very similar to the OCEAN cart type: ROM  memory
    is  organized  in  8Kb  ($2000)  banks  located  at  $8000-$9FFF.  Bank
    switching is done by writing the bank number to $DE00.  Different  from
    the Ocean type, bit 8 is cleared for selecting one of the ROM banks. If
    bit 8 is set ($DE00 = $80), the /GAME  &  /EXROM  lines  are  disabled,
    turning on RAM at $8000-$9FFF instead of ROM.

    In the cartridge header, /EXROM ($18) is set to 0, /GAME ($19)  is  set
    to 1 to indicate the RESET/power-up configuration of 8 kB ROM.

    Here is a list of the known cartridges:

    Ghosbusters        (HES Australia)   (32 kB)
    Magic Desk         (Commodore)       (32 kB)
    Badlands           (Domark)          (64 kB)
    Vindicators        (Domark)          (64 kB)
    Wonderboy          (HES Australia)   (64 kB)
    Cyberball          (Domark)         (128 kB)


===========================================================================


20. Super Snapshot 5

    Size      : 64Kb (4 banks of 16Kb each)
    Addr range: $8000-BFFF
    /EXROM    : inactive (1)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 14 01 01 00 00 00 00 00 00  ���@������������
0020: 53 75 70 65 72 20 53 6E 61 70 73 68 6F 74 20 35  Super�Snapshot�5
0030: 20 4E 54 53 43 00 00 00 00 00 00 00 00 00 00 00  �NTSC�����������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00  CHIP��@�������@�
0050: 09 80 59 80 C3 C2 CD 38 30 20 03 9F 00 FA F4 20  ��Y����80�������
...
4050: 43 48 49 50 00 00 40 10 00 00 00 01 80 00 40 00  CHIP��@�������@�
4060: 79 DE BC FE C3 C2 CD 38 30 A9 05 8D 20 D0 8D 21  y޼����80����Ѝ!
...
8060: 43 48 49 50 00 00 40 10 00 00 00 02 80 00 40 00  CHIP��@�������@�
8070: 50 DE BC FE C3 C2 CD 38 30 A9 0A 85 6A A9 0D 85  P޼����80���j���
...
C070: 43 48 49 50 00 00 40 10 00 00 00 03 80 00 40 00  CHIP��@�������@�
C080: 50 DE BC FE C3 C2 CD 38 30 85 07 20 1A AD A5 76  P޼����80������v


===========================================================================


21. Comal-80

    Size      : 64Kb (4 banks of 16Kb each)
    Addr range: $8000-BFFF
    /EXROM    : inactive (1)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 15 01 01 00 00 00 00 00 00  ���@������������
0020: 43 6F 6D 61 6C 20 38 30 00 00 00 00 00 00 00 00  Comal�80��������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00  CHIP��@�������@�
0050: 87 87 70 CF C3 C2 CD 38 30 4C AA CF 4C 70 CF 4C  ��p����80L��Lp�L
...
4050: 43 48 49 50 00 00 40 10 00 00 00 01 80 00 40 00  CHIP��@�������@�
4060: AA CF 70 CF C3 C2 CD 38 30 01 29 01 28 01 2C 04  ��p����80�)�(�,�
...
8060: 43 48 49 50 00 00 40 10 00 00 00 02 80 00 40 00  CHIP��@�������@�
8070: AA CF 70 CF C3 C2 CD 38 30 91 92 92 92 92 92 92  ��p����80�������
...
C070: 43 48 49 50 00 00 40 10 00 00 00 03 80 00 40 00  CHIP��@�������@�
C080: 7B C8 7E C8 C3 C2 CD 38 30 43 4F 4D 41 4C 80 93  {�~����80COMAL��


    The Comal-80 Cartridge uses $DE00 for bank  selection,  and  uses  16Kb
    banks ($4000) at $8000-$BFFF. There are 4 banks of ROM memory  and  are
    referenced by the following values:

       $80 -> Bank 0
       $81 -> Bank 1
       $82 -> Bank 2
       $83 -> Bank 3


===========================================================================


22. Structured Basic

    Size      : 16Kb (2 banks of 8Kb each)
    Addr range: $8000-9FFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

    No sample data/file available.

    Any read/write access to $DE00 or $DE01 will switch in bank 0.
    Any read/write access to $DE02 will switch in bank 1.
    Any read/write access to $DE03 will switch off /EXROM.


===========================================================================


23. Ross

    Size      : 16Kb or 32Kb sizes (1 or 2 banks of 16Kb each)
    Addr range: $8000-BFFF
    /EXROM    : active (0)
    /GAME     : active (0)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 17 00 00 00 00 00 00 00 00  ���@������������
0020: 52 6F 73 73 20 31 34 00 00 00 00 00 00 00 00 00  Ross�14���������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 40 10 00 00 00 00 80 00 40 00  CHIP��@�������@�
0050: 09 80 09 80 C3 C2 CD 38 30 A2 00 BD 20 80 4D 0E  �������80�����M�
...
4050: 43 48 49 50 00 00 40 10 00 00 00 01 80 00 40 00  CHIP��@�������@�
4060: 3F 5A 4D 4D 50 4D 8D 25 3F 1A 1F 77 3F CD E0 3F  ?ZMMPM�%?��w?��?

    Any read access to $DE00 will switch in bank 1 (if cart is 32Kb).
    Any read access to $DF00 will switch off /EXROM and /GAME.


===========================================================================


24. Dela EP64

    Size      : 8Kb to 72kb sizes (1 to 9 banks of 8Kb each,
                                   or 1 bank of 8Kb and 1 or 2 banks
                                   of 32Kb each)
    Addr range: $8000-9FFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 18 00 01 00 00 00 00 00 00  ���@������������
0020: 44 45 4C 41 20 45 50 36 34 00 00 00 00 00 00 00  DELA�EP64�������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
0050: 00 85 5E FE C3 C2 CD 38 30 FF FF FF FF FF FF FF  ��^����80�������
...
2050: 43 48 49 50 00 00 80 10 00 00 00 01 80 00 80 00  CHIP������������
2060: 54 45 53 54 0D 2A 0D 54 45 20 36 34 0D 00 00 00  TEST�*�TE�64����

    This is an eprom cartridge. It has 1 2764 (8Kb) which  holds  the  base
    eprom with the base menu, and 2 27256 eproms of  which  8Kb  parts  are
    banked into the $8000-9FFF area.

    The bank selecting is done by writing to $DE00. The following bits  are
    used for bank decoding in $DE00 (0 being the LSB, 3 being the MSB).

         Bit# 76543210
              xx10xx32

    Any bank value below 4 or above 11 switches in the base bank (bank 0).

    The bit values for each eprom bank are :

    eprom bank 1 : xx00xx01
    eprom bank 2 : xx01xx01
    eprom bank 3 : xx10xx01
    eprom bank 4 : xx11xx01
    eprom bank 5 : xx00xx10
    eprom bank 6 : xx01xx10
    eprom bank 7 : xx10xx10
    eprom bank 8 : xx11xx10

    Setting bit 7 high will disablef /EXROM (set to high)


===========================================================================


25. Dela EP7x8

    Size      : 8Kb to 64kb sizes (1 to 8 banks of 8Kb each)
    Addr range: $8000-9FFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 19 00 01 00 00 00 00 00 00  ���@������������
0020: 44 45 4C 41 20 45 50 37 78 38 00 00 00 00 00 00  DELA�EP7x8������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
0050: 09 80 5E FE C3 C2 CD 38 30 78 A2 FF 9A D8 8E 16  ��^����80x���؎�
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP������������
2060: 94 83 A0 83 C3 C2 CD 38 30 02 BB 5A 30 5F EE 3D  �������80��Z0_�=

    This is an eprom cartridge. It has 8 8Kb banks of which the first holds
    the base menu, the other eproms can be banked into the $8000-9FFF area.

    The bank selecting is done by writing to $DE00. Each low bit is used to
    bank in the respective eprom. If all bits are high then the  /EXROM  is
    disabled (set to high).

    The bit values for each eprom bank is:

    eprom bank 1 : 11111110 ($FE) (base eprom)
    eprom bank 2 : 11111101 ($FD)
    eprom bank 3 : 11111011 ($FB)
    eprom bank 4 : 11110111 ($F7)
    eprom bank 5 : 11101111 ($EF)
    eprom bank 6 : 11011111 ($DF)
    eprom bank 7 : 10111111 ($BF)
    eprom bank 8 : 01111111 ($7F)

    /EXROM off   : 11111111 ($FF)


===========================================================================


26. Dela EP256

    Size      : 8Kb to 262kb sizes (1 to 33 banks of 8Kb each)
    Addr range: $8000-9FFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 1A 00 01 00 00 00 00 00 00  ���@������������
0020: 44 45 4C 41 20 45 50 32 35 36 00 00 00 00 00 00  DELA�EP256������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
0050: 00 85 5E FE C3 C2 CD 38 30 93 0D 2B 2B 2B 20 45  ��^����80��+++�E
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP������������
2060: 09 80 28 80 C3 C2 CD 38 30 78 A2 05 8E 16 D0 20  ��(����80x������
...
4060: 43 48 49 50 00 00 20 10 00 00 00 02 80 00 20 00  CHIP������������
4070: 0B 80 BC FE C3 C2 CD 38 30 DC 10 8E 16 D0 20 87  �������80�������
...
6070: 43 48 49 50 00 00 20 10 00 00 00 03 80 00 20 00  CHIP������������
6080: 09 80 F6 8E C3 C2 CD 38 30 A2 C8 8E 16 D0 20 ..  �������80�Ȏ���.
...
8080: 43 48 49 50 00 00 20 10 00 00 00 04 80 00 20 00  CHIP������������
8090: 94 83 A0 83 C3 C2 CD 38 30 02 BB 5A 30 5F EE 3D  �������80��Z0_�=

    This is an eprom cartridge. It has 33 8Kb  banks  of  which  the  first
    holds the base menu, the other eproms can be banked into the $8000-9FFF
    area.

    The bank selecting is done by writing to $DE00.

    The values for the (extra) eprom banks are:

    eprom banks  1- 8 : $38-3F
    eprom banks  9-16 : $28-2F
    eprom banks 17-24 : $18-1F
    eprom banks 25-32 : $08-0F

    Setting bit 7 high will disable /EXROM (set to high)


===========================================================================


27. Rex EP256

    Size      : 8Kb to 262kb sizes (1 bank of 8Kb and 1 to  8  banks  of
                                   either 8Kb, 16Kb or 32Kb)

    Addr range: $8000-9FFF
    /EXROM    : active (0)
    /GAME     : inactive (1)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 43 36 34 20 43 41 52 54 52 49 44 47 45 20 20 20  C64�CARTRIDGE���
0010: 00 00 00 40 01 00 00 1B 00 01 00 00 00 00 00 00  ���@������������
0020: 52 45 58 20 45 50 32 35 36 00 00 00 00 00 00 00  REX�EP256�������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 43 48 49 50 00 00 20 10 00 00 00 00 80 00 20 00  CHIP������������
0050: 09 80 C1 FE C3 C2 CD 38 30 20 A3 FD 20 50 FD 20  �������80����P��
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP������������
2060: 09 80 F2 8F C3 C2 CD 38 30 A2 C8 8E 16 D0 20 A3  �������80�Ȏ����
...
4060: 43 48 49 50 00 00 40 10 00 00 00 02 80 00 40 00  CHIP��@�������@�
4070: 09 80 09 80 C3 C2 CD 38 30 58 D8 20 84 FF 20 8A  �������80X������

    This is an eprom cartridge. It has 9 eprom sockets, of which the  first
    holds the base eprom with the base menu which  is  an  8Kb  eprom,  the
    other eprom sockets can handle 8Kb, 16Kb or 32Kb eproms, of  which  8kb
    can be banked into the $8000-9FFF area.

    The bank selecting is done by  writing  to  $DFA0.  Bits  2,  1  and  0
    determine which socket is used and bits 5 and 4 are used to  select  an
    8Kb piece of the eprom.

    The possible values for bits 5 and 4 for the (extra) eprom banks are:

     8Kb        : 3, 2, 1, 0

    16Kb bank 0 : 2, 0
    16Kb bank 1 : 3, 1

    32Kb bank 0 : 0
    32Kb bank 1 : 1
    32Kb bank 2 : 2
    32Kb bank 3 : 3

    Reading from $DFC0 disables /EXROM (set to 1)
    Reading from $DFE0 enabled /EXROM (set to 0)


===========================================================================


28. Mikro Assembler

    Size      :
    Addr range:
    /EXROM    :
    /GAME     :

    No information yet.


===========================================================================


29. Reserved


===========================================================================


30. Action Replay 4 (AR4)

    Size      :
    Addr range:
    /EXROM    :
    /GAME     :

    No information yet.


===========================================================================


31. StarDOS

    Size      :
    Addr range:
    /EXROM    :
    /GAME     :

    No information yet.


===========================================================================


32. EasyFlash

    Size      :
    Addr range:
    /EXROM    :
    /GAME     :

    No information yet.


*** CVT (ConVerT containers)
*** Document revision: 1.3
*** Last updated: Oct 1, 2007
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Joe Forster/STA

  These are sequential representations of GEOS files, both  sequential  and
VLIR. In order to be transmitted and up/downloaded, they must be  converted
to this intermediate format because the file's INFO block (and record block
for a VLIR) must be included. Note that the track/sector references at  the
beginning of each sector are not included here, making the block  size  254
bytes. Also, any values in track/sector references are invalid,  since  the
value is sure to change once the file is converted back from CVT to a  GEOS
format.

  I will not include much of the GEOS file layout details here, as you  can
read the GEOS.TXT document to get the information.

  With CVT's that contain VLIR files, there  are  four  distinct  sections:
signature, info, record and data. CVT's that contain non-VLIR  files  (i.e.
standard GEOS sequential) do not include the record block.

  The first part, which exists in both CVT types, is the  signature  block.
It contains the complete directory entry and CVT file signature.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 83 00 00 44 45 53 4B 20 54 4F 50 A0 A0 A0 A0 A0   ���DESK�TOP�����
0010: A0 A0 A0 00 00 01 04 58 08 13 0D 23 78 00 50 52   �����..X...#x�PR
0020: 47 20 66 6F 72 6D 61 74 74 65 64 20 47 45 4F 53   G�formatted�GEOS
0030: 20 66 69 6C 65 20 56 31 2E 30 00 00 00 00 00 00   �file�V1.0������
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .. ..   ��������������..

    Byte:$00-1D: Complete directory entry. Note that the first two bytes of
                 *any* directory entry are never used,  and  thus  are  not
                 incuded here either.
          1E-39: File signature. It can contain "PRG formatted..." or  "SEQ
                 formatted...". Here we can check that the  CVT  is  really
                 what it claims.
          3A-FD: Usually $00

What follows the signature block is the complete GEOS file INFO block.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
00F0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. 03 15   ................
0100: BF FF FF FF 92 49 01 FF FF 01 80 00 1D BF FF DD   �����I.��.��.���
0110: A0 00 5D BF FF C1 A0 00 5D A1 C6 55 A0 29 5D A0   ��]����]��U�)]�
0120: C9 41 A1 09 41 B9 D6 41 A8 00 41 BF FF C1 80 00   �A�.A��A��A����
0130: 1D 9C 00 15 9C 00 15 80 00 1D 80 00 01 FF FF FF   .��.��.��.��.���
0140: 83 04 01 56 19 55 19 75 51 64 65 73 6B 54 6F 70   �..V.U.uQdeskTop
0150: 20 41 4D 20 20 56 32 2E 30 00 00 00 00 42 72 69   �AM��V2.0����Bri
0160: 61 6E 20 44 6F 75 67 68 65 72 74 79 00 00 00 00   an�Dougherty����
0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0180: 00 00 00 00 00 4C 2A 5B 4C 59 5D 4C A7 61 4C 3A   �����L*[LY]L�aL:
0190: 62 AD 8A 84 D0 01 60 20 7E 23 20 9C 55 73 65 20   b����.`�~#��Use�
01A0: 74 68 65 20 64 65 73 6B 54 6F 70 20 74 6F 20 6D   the�deskTop�to�m
01B0: 61 6E 61 67 65 20 61 6E 64 20 6D 61 6E 69 70 75   anage�and�manipu
01C0: 6C 61 74 65 20 79 6F 75 72 20 66 69 6C 65 73 2E   late�your�files.
01D0: 00 03 20 E3 5C 68 85 FB 20 4F 61 20 13 61 20 32   �.��\h���Oa�.a�2
01E0: 61 20 F2 5C A9 0C 20 CC 49 A9 2E 85 13 A9 F9 85   a��\�.��I�.�.���
01F0: 12 A9 2F 85 15 A9 01 85 14 A9 84 85 .. .. .. ..   .�/�.�.�.���....

  The third block is the RECORD block. In the  sequential  version  of  the
CVT, this block won't exist. The way  to  tell  if  the  file  is  VLIR  or
sequential is to look at byte position 23  of  the  directory  entry  (from
above, it's value is $01). If it's a $00, the file is sequential,  if  it's
$01 it's VLIR.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
01F0: .. .. .. .. .. .. .. .. .. .. .. .. 43 41 0A 0B   ............CA..
0200: 0B F4 0A 8C 0B A1 09 70 00 00 00 00 00 00 00 00   .���.��p��������
0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02F0: 00 00 00 00 00 00 00 00 00 00 .. .. .. .. .. ..   ����������......

  Note that the RECORD block is modified  from  the  original  GEOS  entry.
Instead of containing the track and sector  references,  we  now  have  the
sector count and the size of the last sector in the chain. Looking over the
block above, we get the following usage chart:

      Count  Size   Comment
      -----  ----   --------------------------------------
       43     41    Sector count=67, last sector index=$41
       0A     0B    Sector count=10, last sector index=$0B
       0B     F4    Sector count=11, last sector index=$F4
       0A     8C    Sector count=10, last sector index=$8C
       0B     A1    Sector count=11, last sector index=$A1
       09     70    Sector count=9,  last sector index=$70
       00     00    No more records.

Two things of interest can be noted from the record block...

  1. When a 00/00 is encountered, the record block is done.
  2. When a 00/FF is encountered,  the  record  does  not  exist  (see  the
     GEOS.TXT format for more info on invalid records), but the entry  must
     still be made in the re-created RECORD block.

  From here on we have the actual data, all of  the  record  chains  strung
together to form one long file. All of this data must be  broken  apart  to
form the original records that GEOS expects.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
02F0: .. .. .. .. .. .. .. .. .. .. A9 00 8D EE 04 A4   ..........����.�
0300: FE B9 86 84 30 06 29 0F C9 02 D0 12 A4 70 B9 86   ����0.).�.�.�p��
0310: 84 30 06 29 0F C9 02 D0 05 A9 07 8D A0 1D 20 1E   �0.).�.�.�.��.�.
0320: 23 20 04 1A 8A D0 20 20 12 1A 18 A9 00 6D F4 03   #�..����...��m�.
0330: 8D F4 03 A9 03 6D F5 03 8D F5 03 20 C5 22 20 7C   ��.�.m�.��.��"�|
0340: 1B 20 04 1A 20 6B 1A A9 08 8D A0 1D B8 50 53 8D   .�..�k.�.��.�PS�
0350: EE 04 20 12 1A A2 00 A4 70 20 3F 24 C9 04 B0 3F   �.�..���p�?$�.�?


*** D2M (Electronic form of a CMD FD2000 1.56 Mb floppy disk)
*** DNP (Electronic form of a CMD hard Disk Native Partition)
*** Document revision: 1.3
*** Last updated: Nov 27, 2005
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Torsten Hinrichs (sample files),
                          Malte Munde (sample files),
                          Wolfgang Moser,
                          Roberto Muscedere,
                          Bo Zimmerman (sample DNP files)

  Much of the information contained in this document has been  gathered  by
dissecting FD2000 floppy images (in D2M format) and DNP hard  disk  images,
comparing them, and arriving at some well-educated conclusions. Comparisons
to some other disk types (D81, D64) have  helped  immeasurably.  Therefore,
some of the information presented here might not be accurate or complete.

  CMD devices  are  incredibly  compatible.  The  FD2000  is  is  backwards
compatible to the Commodore 1581 floppy, contains the JiffyDos  fastloader,
and even supports the GEOS OS. Inserting a native-formatted  FD2000  floppy
keeps the drive in its native mode support, but inserting a  1581-formatted
disk will put the drive into  "1581  compatible"  mode.  It  even  supports
"emulated" partitions of 1541, 1571  and  1581  disks  on  native-formatted
disks.

  The D2M image is considered a "container"  image  as  it  contains  other
image types like D64, D71, D81 and native partitions as well. The container
nature makes supporting D2M more difficult than other image types.

  The extension DNP was arrived at after discussions between  Bo  Zimmerman
and this  document  author.  It  stands  for  CM(D)  (N)ative  (P)artition.
Unfortunately we could not assign it CMD as that would  conflict  with  the
Windows OS CMD interpeter batch files.

  There are several different ways to view the layout of  FD2000  floppies.
At the controller level, the disk has 81 tracks (physically numbered  0  to
80), 10 sectors-per-track, 2 disk sides with  1024  bytes  per  sector.  In
Commodore  logical  terms,  it  has  81  tracks  (1  to  81  logical),   80
sectors-per-track with 256 bytes per sector, totalling 6480 sectors  total.
This makes the disk 1.56Mb in  size.  The  last  track  (81,  image  offset
$190000) is reserved and should not be used for data  storage.  This  makes
the file size 1658880 without error bytes attached, or 1665360  bytes  with
error bytes attached.

  Seeing as the disk is 6480  sectors  large,  we  need  6480  error  bytes
attached to the end of the image for an extended image type. About the only
use for the error bytes is when emulating 1541 or 1571 drive types,  and  a
bad sector for copy protection is needed. The job codes these  error  bytes
represent only really apply the 1541 and 1571 drives.

  While it may seem logical to interact with the disk with  81  tracks,  it
fails in practice and the reason is simple. Internally, all track &  sector
links in the native and emulated partitions (not system) refer to the  disk
as a 256 sector/track so you must work with the disk this way.  This  means
the FD2000 image actually has 26 tracks, 25 for the  image  and  a  partial
track 26 (80 sectors only)  for  the  system  partition.  Coding  a  proper
support structure for one CMD device image like D2M  means  that  it  would
also be easy to make it work for any other image like DNP (except  for  the
lack of a system partition).

  So, what does it mean when track 2 sector 233 ($02/$E9) is  accessed?  To
answer this,  we  need  to  convert  the  track  and  sector  numbers  into
HEXADECIMAL, because calculating the resulting offset location become  very
simple. Taking the example above (track 2 sector 233), convert them to  HEX
numbers...

     track 2   -> $02
    sector 233 -> $E9

  subtract 1 from the track value (because all track references are from 1,
not zero), attach the sector value to the end, and then attach a $00 to the
end...

    ($track-1):$sector:$00  or  $01E900.

  This is the offset value into the existing partition to  access  track  1
sector 233.

  Additionally, each partition internally always starts from track  1.  How
is this possible? Well, the system partition table specifies what offset  a
partition starts at (in system blocks), and once inside the partition,  all
track references now start at 1. This means *you* must keep  track  of  the
offset where each partition exists once you are inside. As  a  bonus,  this
also means that moving a partition from one disk to another should be  very
simple because all the track/sector references and  chains  are  "relative"
and do not have to be adjusted.

  CMD devices like the FD2000 floppy and CMD hard disks contain  a  "system
partition" (described later) which stores up to 31 user-created  partitions
(also called segments), with the types defined below. One of the partitions
will be set as the default so that when the disk is inserted in the floppy,
the default partition will be entered automatically.  The  first  entry  is
always set as the "system" entry.

  There are several different types of partitions, which are...

   Type  Description                 Size
   ----  --------------------------- -----------------------------------
    00   No partition                0
    01   Native partition            variable (min 256 512-byte blocks)
    02   Emulated 1541 drive (D64)   342 512-byte blocks (684 sectors)
    03   Emulated 1571 drive (D71)   684 512-byte blocks (1368 sectors)
    04   Emulated 1581 drive (D81)   1600 512-byte blocks (3200 sectors)
   255   System partition (track 81)

  The emulated drive partitions are a direct sector copy of the disk  type.
This means the track/sector references are just as a normal disk would  be,
even though the FD2000 doesn't normally do things this way. If you were  to
sector-by-sector copy the data out from this emulated partition  to  a  new
file, you would have a D64 (or D71/D81) image file in all respects.

  There are two things to watch out for if you intend to copy the data from
emulated partitions out to a real disk. Both the 1541 and the 1571  contain
extra "filler" sectors on the end. The 1541  contains  one,  and  the  1571
contains two. A partial explanation for this behaviour is that  the  FD2000
system partition works with 512-byte blocks, meaning all partitions must be
even numbers (in 256-byte blocks). Therefore the 1541 size  is  incremented
to the next logical size (684) to make is an even value. The 1571 is simply
a doubling of the 1541 size, even though this means it now  contains  *two*
extra filler sectors (which are now completely unnecessary).

  For more information on the layout of 1541 (D64), 1571 (D71), 1581 (D81),
GEOS, REL or any  of  the  specific  file  types  on  the  disks,  see  the
appropriate documentation which should be included with this one.

  It is the native partition type which is the most powerful to use because
it is capable of so much, being a greatly improved  disk  format  over  the
D64.




The System Partition (D2M/D4M images only)
------------------------------------------

  Every CMD storage device contains a system partition,  but  not  all  the
images do. The D2M and D4M images do contain the system partition, but  the
DNP image does not as it is only a copy of  the  native  partition  portion
from a CMD hard disk. Therefore this section  only  refers  to  the  floppy
(D2M) images.

  The system partition exists at track 26 (offset $190000), and  is  broken
up into several different  areas.  With  only  80  sectors  on  this  track
(instead of the normal 256), there is potentially  a  lot  of  information.
However, only sector 5 and 8-11 seem to be used.

  The system partition contains no BAM map. In order to add new partitions,
a pseudo-map would need to be built based on the existing partition entries
starting positions and sizes to know where there is empty space on the disk
for more partitions.

  Sector 5 (offset $190500) holds the  DevBlock,  the  "device  information
block". Most of the information here is unknown,  but  it  likely  contains
information about the device itself, and possibly which partition is set as
the default. This block should be duplicated as-is when  generating  a  D2M
image file as it does not appear to change across any of  the  images  that
have been seen.

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
190500: 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190510: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190520: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190530: FF FF FF FF FF FF FF FF 00 00 FF FF FF FF FF FF  ����������������
190540: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190550: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190560: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190570: 00 0C FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190580: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
190590: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
1905A0: FF FF FF FF FF FF FF FF 00 80 FF FF FF FF FF FF  ����������������
1905B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
1905C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
1905D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
1905E0: 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1905F0: 43 4D 44 20 46 44 20 53 45 52 49 45 53 20 20 20  CMD�FD�SERIES���

     Byte:$00-EF: unknown
           F0-FF: Disk identifier string (in ASCII, padded with $20)


  Sectors 8-11 (offset $190800-190BFF) hold the system partition  directory
containing information for as many as 31 separate partitions.  The  example
below shows the 4 allowed partition types along with the required  "SYSTEM"
entry. All partition entries are 32 bytes long but the first two bytes  are
not used for the entry.

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
190800: 01 01 FF 00 00 53 59 53 54 45 4D A0 A0 A0 A0 A0  �����SYSTEM�����
190810: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 00 00  ����������������
190820: 00 00 04 00 00 31 35 38 31 2F 50 41 52 54 49 54  �����1581/PARTIT
190830: 49 4F 4E A0 A0 00 00 00 00 00 00 00 00 00 06 40  ION������������@
190840: 00 00 03 00 00 31 35 37 31 50 41 52 54 49 54 49  �����1571PARTITI
190850: 4F 4E A0 A0 A0 00 06 40 00 00 00 00 00 00 02 AC  ON�����@��������
190860: 00 00 02 00 00 31 35 34 31 50 41 52 54 49 54 49  �����1541PARTITI
190870: 4F 4E A0 A0 A0 00 08 EC 00 00 00 00 00 00 01 56  ON�������������V
190880: 00 00 01 00 00 4E 41 54 49 56 2D 50 41 52 54 49  �����NATIV-PARTI
190890: 54 49 4F 4E A0 00 0A 42 00 00 00 00 00 00 02 00  TION���B��������
1908A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1908B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1908C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1908D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1908E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1908F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190900: 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190920: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1909A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1909B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1909C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1909D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1909E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
1909F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A00: 01 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190A90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190AA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190AB0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190AC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190AD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190AE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190AF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B00: 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190B90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190BA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190BB0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190BD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
190BF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

  Notice that the chain links are 1/1, 1/2, 1/3, and ends with  a  $00/$FF.
What is happening here is the drive is using  26/5  as  the  start  of  the
system partition, which now make 26/5 appear as logical  1/0.  This  is  an
example of partitions starting at  track  1  internally  even  though  they
physically reside elsewhere. Therefore, even though  the  system  partition
starts at 26/5, this is actually logical track/sector 1/0 and you  need  to
keep track of the starting offset of this partition so that accesses  still
start as 26/5.

  The first entry is the root name. This entry must exist first...

190800: 01 01 FF 00 00 53 59 53 54 45 4D A0 A0 A0 A0 A0  �����SYSTEM�����
190810: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 00 00  ����������������

     Byte:$00-01: track/sector reference to next partition block
              02: Partition type (255=system partition)
           03-04: unknown, set to $00
           05-14: root name (16 characters, padded with $A0)
           15-1F: set to $00

  The next entry is the first partition...

190820: 00 00 04 00 00 31 35 38 31 2F 50 41 52 54 49 54  �����1581/PARTIT
190830: 49 4F 4E A0 A0 00 00 00 00 00 00 00 00 00 06 40  ION������������@

     Byte:$00-01: not used
              02: Partition type
                   00 - No partition
                   01 - Native FD2000 partition
                   02 - Emulated 1541 disk (D64)
                   03 - Emulated 1571 disk (D71)
                   04 - Emulated 1581 disk (D81)
           03-04: unknown, set to $00
           05-14: Partition name (16 bytes, padded with $A0)
              15: unknown, set to $00
           16-17: Starting offset to partition, in hi/lo format (note  that
                  these blocks are 512-byte blocks)
           18-1D: unknown, set to $00
           1E-1F: Partition size, in hi/lo format (note that  these  blocks
                  are again 512-bytes in size)

  *Note: the "partition size" and "starting offset" values are  some  other
examples of the oddities of the FD2000 layout. They are counted in 512-byte
sectors, not the standard 256-byte sectors of other Commodore  disks.  What
this means is you must double the value to get the actual size in  256-byte
sectors.

  In the case of emulated drive partitions, the size is already  known,  as
it is a sector-for-sector duplicate of the emulated disk. An emulated  1541
disk will have one extra sector at the end of the image because  it  is  an
odd size (683) and the size must always be even,  being  multiples  of  512
bytes.

  The third partition example from above ("1571PARTITION")  shows  a  block
offset of $0640 and a block size of $02AC.  Since  these  are  in  512-byte
blocks, we need to double them to  get  the  real  256-byte  sector  values
($0C80 and $0558). This means that this partition  starts  at  file  offset
$0C8000, and is $0558 (or 1368) sectors large. The file offset number  must
be remembered as all references within the partition must be added  to  the
above offset value to get the real offset into the D2M image.



Native Partitions (D2M and DNP images)
--------------------------------------

  All partitions inside of a D2M image must start on a 512  byte  boundary,
and end on one as well. The minimum size for  a  native  partition  is  256
system blocks (or 512 sectors in 256-byte sectors). Part of the reason  for
the minimum size is the number of blocks  that  the  BAM  and  other  areas
allocate (35 blocks) even before you get a chance to do anything.

  Keep in mind that a DNP image does not contain a system partition but  is
only the native partition from  a  CMD  hard  disk.  It  is  therefore  not
considered a "container" image type. The maximum track size for DNP is 255.
This puts the upper limit on this image at 16,711,680 bytes.  To  determine
the track size of a DNP image, simply divide the image size  by  65536.  If
there is any remainder, this means there is a partial track stored  at  the
top so increment the track size by one.

  The first sector ($01/$00) of a native partition is reserved for the C128
boot block. CMD designed the drive this way, allocating  the  first  sector
automatically, so the partition HEX dump will start  at  the  next  sector,
$01/$01.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 01 24 48 00 53 55 42 44 49 52 31 38 A0 A0 A0 A0  �$H�SUBDIR18����
0010: A0 A0 A0 A0 A0 A0 54 49 A0 31 48 A0 A0 00 00 00  ������TI�1H�����
0020: 01 23 01 01 01 22 02 00 00 00 00 00 00 00 00 00  �#���"����������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00A0: 00 00 00 00 00 00 00 00 00 00 00 01 25 47 45 4F  ������������%GEO
00B0: 53 20 66 6F 72 6D 61 74 20 56 31 2E 31 00 00 00  S�format�V1.1���
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

     Byte:$00-01: Track/sector reference to root directory  block  of  this
                  partition ($01/$24).
              02: Disk format type ("H")
              03: unknown, set to $00
           04-15: Disk name (16 characters, padded with $A0)
           16-17: Disk ID's ("TI")
              18: Set to $A0
              19: DOS Version ("1")
              1A: Disk format type ("H")
           1B-1C: Set to $A0
           1D-1F: unknown, set to $00
           20-21: Track/Sector pointer to present directory header block
           22-23: Track/Sector pointer to  parent  directory  header  block
                  (set to $00/$00 when at the top of the directory)
           24-25: Track/Sector pointer to dir entry in  previous  directory
                  (set to $00/$00 when at the top of the directory)
              26: Index pointer to dir entry in parent  directory  (set  to
                  $00 if at the top of the directory)
           27-AA: unknown, set to $00
           AB-AC: GEOS border sector
           AD-BC: GEOS format string (GEOS format Vx.x)
           BD-FF: Unknown, set to 00

  The references at $20 through $26 take a  little  more  explanation.  The
track/sector link at $20-$21 points to the header of the present directory.
This way when you are in the directory listing, you know where  the  header
block is, and it can be accessed to find out how to go back one  level,  or
change the header name, etc.

  The t/s link at $22-23 points back to the immediately previous  directory
(parent entry), allowing you to go backwards up the directory tree one step
at a time. Note that there is no value for a jump back  to  the  top  level
directory. This value is known only when you enter the partition.

  The t/s link at $24-25 points to the  sector  where  the  entry  for  the
present directory name exists (one level up), and the value at $26  is  the
real index into this sector pointing directly at the name.  This  entry  is
important because if you add extra entries  to  a  directory,  forcing  the
addition of another sector, the parent entry must be  updated  with  a  new
block count. The reference at $24-26 tells you  exactly  where  the  parent
entry is.

  If the directory header contains the GEOS format signature at offset $AD,
then the directory is ready for GEOS use. See  the  GEOS.TXT  document  for
more  explanation  of  GEOS  features.  It  is  not   known   if   children
subdirectories under a parent which is GEOS formatted  must  also  be  GEOS
format. However, each directory, regardless of where it is, uses  it's  own
GEOS border sector if it is formatted for GEOS.


  The BAM map for a native partition starts at track 1 sector 2 and extends
up to sector 33. Why is it 32 sectors long? A native partition supports  up
to 255 tracks (at 256 sectors per track). Doing the math,  this  makes  the
BAM table 8160 bytes long, or approximately 32 sectors. A native  partition
inside of a D2M image can only go up to track 25 of 255 due to the physical
size limits of the D2M, so most of the table  is  unused  and  filled  with
$FF's. However, a DNP image can use up to 255 tracks,  so  the  entire  BAM
will be used.

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
000200: 00 00 48 B7 4A 4F C0 00 19 00 00 00 00 00 00 00  ��H�JO����������
000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000220: 00 00 00 00 0F FF FF FF 00 00 00 00 00 00 00 00  ����������������
000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0002A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0002B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0002C0: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00  ������������@���
0002D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0002E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0002F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
  ..
000500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
000530: 00 00 00 00 00 00 00 07 FF FF FF FF FF FF FF FF  ����������������
000540: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������
000550: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ����������������

     Byte:$00-01: unknown, set to $00
              02: Disk format type ("H")
              03  1's complement of format type ("H" EOR $FF)
           04-05: Disk ID's ("JO")
              06: unknown (seems to be the same value from the 1581  image,
                  I/O byte)
                    bit 7 set   - Verify on
                    bit 7 clear - Verify off
                    bit 6 set   - Check header CRC
                    bit 6 clear - Don't check header CRC
              07: unknown, set to $00
              08: Last available track # in partition ($19=#25)
           09-1F: unknown, set to $00
           20-FF: BAM for tracks 1-7


      BAM block    Covers tracks
    ------------   ------------------------------
     1 (#01/#02)    01-07 (starts at offset $20)
     2 (#01/#03)    08-15 (starts at offset $00)
     3 (#01/#04)    16-23          ''
     4 (#01/#05)    24-31          ''
       ...           ...
    30 (#01/#31)   232-239         ''
    31 (#01/#32)   240-247         ''
    32 (#01/#33)   248-255         ''

    Track  Offset Range
    -----  --------------
      01   $000220-00023F
      02   $000240-00025F
      03   $000260-00027F
      04   $000280-00029F
      ..
     253   $0021A0-0021BF
     254   $0021C0-0021DF
     255   $0021E0-0021FF


  The BAM bit breakdown is not  very  complicated.  Each  track  allocation
takes exactly 32 bytes. Looking at the above  entry,  we  can  extract  the
entry for track 1 (all 256 sectors), which starts at  track  1,  sector  2,
offset $20 ($000220)...

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
000220: 00 00 00 00 0F FF FF FF 00 00 00 00 00 00 00 00  ����������������
000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

  Each byte represents 8 sectors. The first series of six bytes are  broken
down as follows...

      Byte 0     Byte 1     Byte 2     Byte 3     Byte 4     Byte 5
     76543210   76543210   76543210   76543210   76543210   76543210
     --------   --------   --------   --------   --------   --------
     00000000   00000000   00000000   00000000   00001111   11111111
     �      �   �      �   �      �   �      �   �      �   �      �
     �      �   �      �   �      �   �      �   �      �   �      �
     �      �   �      �   �      �   �      �   �      �   �      �
     �      �   �      �   �      �   �      �   �      �   �      �
     �    Sec 7 �   Sec 15 �   Sec 23 �   Sec 31 �   Sec 39 �   Sec 47
    Sec 0      Sec 8     Sec 16    Sec 24     Sec 32     Sec 40

  Byte #0 covers sector 0-7, #1 covers 8-15 and so on. A '1' bit means  the
sector is free, and a '0' bit means the sector is allocated (used). For  an
empty partition, sectors 0-34 are always allocated. Note that  even  though
sector 0 is not used (completely empty), it is still allocated.


  Looking back to the first sector of the partition block, it had the  next
t/s link set as $01/$22 (offset $002200), so  here  is  the  dump  of  that
sector, which is the first directory block. This block is very  similar  in
layout to a normal disk (D64, etc) containing GEOS files.

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
002200: 01 23 86 01 40 45 43 48 4F 20 48 41 57 4B A0 A0  �#��@ECHO�HAWK��
002210: A0 A0 A0 A0 A0 00 00 00 00 60 01 02 15 13 02 00  ���������`������
002220: 00 00 86 02 32 50 4C 55 52 41 4C A0 A0 A0 A0 A0  ����2PLURAL�����
002230: A0 A0 A0 A0 A0 00 00 00 00 60 01 02 15 19 02 00  ���������`������
002240: 00 00 86 03 04 52 45 41 43 54 4F 52 A0 A0 A0 A0  �����REACTOR����
002250: A0 A0 A0 A0 A0 00 00 00 00 60 01 02 15 20 04 00  ���������`������
002260: 00 00 86 04 D8 54 48 45 20 54 52 41 49 4E A0 A0  �����THE�TRAIN��
002270: A0 A0 A0 A0 A0 00 00 00 00 60 01 0A 10 23 03 00  ���������`���#��
002280: 00 00 86 06 62 49 4E 46 49 4C 54 52 41 54 4F 52  ����bINFILTRATOR
002290: A0 A0 A0 A0 A0 00 00 00 00 60 01 0A 10 2B 06 00  ���������`���+��
0022A0: 00 00 86 08 FE 53 54 4F 4E 45 20 41 47 45 A0 A0  �����STONE�AGE��
0022B0: A0 A0 A0 A0 A0 00 00 00 00 60 01 0A 12 04 05 00  ���������`������
0022C0: 00 00 86 0A D6 4E 49 43 4B 20 46 41 4C 44 4F 20  �����NICK�FALDO�
0022D0: 47 4F 4C 46 A0 00 00 00 00 60 01 0A 12 09 02 00  GOLF�����`������
0022E0: 00 00 86 0A D8 52 2D 54 59 50 45 A0 A0 A0 A0 A0  �����R-TYPE�����
0022F0: A0 A0 A0 A0 A0 00 00 00 00 60 01 0A 12 0D 05 00  ���������`������

     Byte:$00-01: T/S link to next directory block (set to $00/$FF if  it's
                  the last sector of the directory)
              02: Entry type. Typical values for this location are:
                   $00 - Scratched (deleted file entry)
                    80 - DEL file
                    81 - SEQ file
                    82 - PRG file
                    83 - USR file
                    84 - REL file
                    85 - 1581 partition (only in emulated 1581 disks)
                    86 - Native FD2000 subdirectory
                   Bit:0-3: The actual filetype
                            000 (0) - DEL
                            001 (1) - SEQ
                            010 (2) - PRG
                            011 (3) - USR
                            100 (4) - REL
                            101 (5) - 1581 partition
                            110 (6) - FD2000 subdirectory
                            Values 7-15 are illegal
                         4: Not used
                         5: Used only during SAVE-@ replacement (?)
                         6: Locked flag (if set produces ">" locked files)
                         7: Closed flag (Not set produces "*",  or  "splat"
                            files)
            03-04: Track/sector location of first sector of entry
            05-14: 16 character filename (in PETASCII, padded with $A0)
            15-16: Starting track/sector of REL super-side-sector info  (If
                   GEOS file, t/s link to info block)
               17: REL record length (if GEOS  file,  GEOS  file  structure
                   descriptor, $00=sequential, $01=VLIR file)
               18: unknown, set to  $00  (If  GEOS  file,  GEOS  file  type
                   descriptor)
            19-1D: File time/date stamp (seconds are not stored).  This  is
                   the same timestamp that GEOS uses.
                     19: Year (add 1900 for real year)
                     1A: Month (1=JAN, 2=FEB etc)
                     1B: Day (#1-#31)
                     1C: Hour (24 hour time, #00-#23)
                     1D: Minute (#00-#59)
            1E-1F: Size in sectors, low/high byte order ($1E + $1F *  256).
                   The filesize in bytes is <= #sectors * 254
            20-3F: Second dir entry. From now on the  first  two  bytes  of
                   each entry in the sector should be $00/$00, as they  are
                   unused.
            40-5F: Third dir entry
            60-7F: Fourth dir entry
            80-9F: Fifth dir entry
            A0-BF: Sixth dir entry
            C0-DF: Seventh dir entry
            E0-FF: Eighth dir entry

  The above "size" at $1E-1F can either be the sector  count  of  the  file
entry (file size), or the directory size if it's a directory. If  it  is  a
directory, it counts both the header and directory blocks but not any files
or subsequent subdirectory blocks. This value will increment if  any  extra
directory blocks that need to be allocated to store more files/directories.

  Directory space is allocated dynamically, so the size will vary depending
on how many entries are in the subdirectory, and how many blocks the  whole
directory takes. It might help to think of the native  partition  directory
structure and capabilities as you would on a MSDOS machine. They  are  both
dynamic, and appear to support as many subdirectories as disk space allows.
There does not appear to be any limit on how many directory levels deep one
can go. The "xxx blocks free" that would be seen after a directory  listing
would apply across the entire partition, as does the BAM for the partition.

  Also note the timestamp on bytes $19-1D. The FD2000 drive has a  built-in
real-time clock, allowing for an  accurate  time/date  stamp  on  file  and
directory creation. It is the same stamp that GEOS has used for years.  For
more info on GEOS files, read the GEOS.TXT document.


  Looking back at the first directory block, it had the entry  "ECHO  HAWK"
set as a subdirectory, with it's T/S location as $01/$40 (offset  $004000),
and it's block size as 2. Here is the dump  of  the  first  block  of  that
subdirectory.

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
004000: 01 41 48 00 45 43 48 4F 20 48 41 57 4B A0 A0 A0  �AH�ECHO�HAWK���
004010: A0 A0 A0 A0 A0 A0 4A 4F A0 31 48 A0 A0 00 00 00  ������JO�1H�����
004020: 01 40 01 01 01 22 02 00 00 00 00 00 00 00 00 00  �@���"����������
004030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
004040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
004050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
004060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
004070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
004080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
004090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
0040F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

     Byte:$00-01: Track/sector link to next directory  block  ($01/$41,  or
                  $004100)
              02: Disk format type ("H")
              03: unknown, set to $00
           04-15: Directory name (16 characters, padded with $A0)
           16-17: Disk ID's ("JO")
              18: Set to $A0
              19: DOS version ("1")
              1A: Disk format type ("H")
           1B-1C: Set to $A0
           1D-1F: unknown, set to $00
           20-21: Track/Sector pointer to present  directory  header  block
                  ($01/$40, points to itself)
           22-23: Track/Sector pointer to  parent  directory  header  block
                  ($01/$01, points to previous directory)
           24-25: Track/Sector pointer to dir entry in  previous  directory
                  ($01/$22)
              26: Index pointer to dir entry in parent  directory ($02)
           27-FF: unknown, set to $00

  Each directory is preceeded by this "header" block,  including  the  root
(from above). This block is necessary because it is the only location which
can hold the "directory" name,  and  all  the  track/sector  pointers  into
various levels of the directory structure.


  From here, we go to the next block of the directory, holding  the  actual
file listing, possibly with more subdirectories. This is block #2  (out  of
2) of the entry total. The layout  and  description  is  the  same  as  the
previous example of the first directory block.




Creating A D2M Image
--------------------

  Follow these steps to create a  D2M  image.  These  instructions  do  not
describe how to create a partition entry or subdirectories. For this  info,
you will need to read the above information very carefully.

  1. Create a new file, and write out 6480 256-byte blocks of zero's.

  2. If you need error bytes, write out another 6480 bytes of  $01's.  This
     is the job code for "no error".

  3. Copy the DevBlock exactly, as shown previously (located in an existing
     image at track 26, sector 5, or offset $190500).

  4. Create the system partition  as  described  above  (track  26,  sector
     8-11).

  5. Make sure the "SYSTEM" entry exists as the first entry in  the  system
     partition.


*** D64 (Electronic form of a physical 1541 disk)
*** Document revision: 1.11
*** Last updated: Nov 7, 2008
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Immers/Neufeld "Inside Commodore  DOS"
                          Wolfgang Moser

(Note: This document will try to explain the layout of the 1541  disks,  as
well as some of the files they contain. However, I do not explain  GEOS  or
REL files here. See the file GEOS.TXT or REL.TXT for  more  information  on
those file types or disk structure). Special thanks to Wolfgang  Moser  for
his work on identifying the differences between the various 'Speeder' DOS's
that exist. This information is included in a table later in this document.

  First and foremost we have D64, which is  basically  a  sector-for-sector
copy of a 1540/1541 disk. There are several versions of these which I  will
cover shortly. The standard D64 is a 174848 byte file comprised of 256 byte
sectors arranged in 35 tracks with a varying number of  sectors  per  track
for a total of 683 sectors. Track counting starts at 1, not 0, and goes  up
to 35. Sector counting starts at 0, not 1, for the first sector,  therefore
a track with 21 sectors will go from 0 to 20.

  The original media (a 5.25" disk) has the tracks  laid  out  in  circles,
with track 1 on the very outside of the disk  (closest  to  the  sides)  to
track 35 being on the inside of the disk (closest to the inner  hub  ring).
Commodore, in their infinite wisdom, varied the number of sectors per track
and data densities across the disk to optimize available storage, resulting
in the chart below. It shows the sectors/track for a  standard  D64.  Since
the outside diameter of a circle is  the  largest  (versus  closer  to  the
center), the outside tracks have the largest amount of storage.

        Track   Sectors/track   # Sectors   Storage in Bytes
        -----   -------------   ---------   ----------------
         1-17        21            357           7820
        18-24        19            133           7170
        25-30        18            108           6300
        31-40(*)     17             85           6020
                                   ---
                                   683 (for a 35 track image)

  Track #Sect #SectorsIn D64 Offset   Track #Sect #SectorsIn D64 Offset
  ----- ----- ---------- ----------   ----- ----- ---------- ----------
    1     21       0       $00000      21     19     414       $19E00
    2     21      21       $01500      22     19     433       $1B100
    3     21      42       $02A00      23     19     452       $1C400
    4     21      63       $03F00      24     19     471       $1D700
    5     21      84       $05400      25     18     490       $1EA00
    6     21     105       $06900      26     18     508       $1FC00
    7     21     126       $07E00      27     18     526       $20E00
    8     21     147       $09300      28     18     544       $22000
    9     21     168       $0A800      29     18     562       $23200
   10     21     189       $0BD00      30     18     580       $24400
   11     21     210       $0D200      31     17     598       $25600
   12     21     231       $0E700      32     17     615       $26700
   13     21     252       $0FC00      33     17     632       $27800
   14     21     273       $11100      34     17     649       $28900
   15     21     294       $12600      35     17     666       $29A00
   16     21     315       $13B00      36(*)  17     683       $2AB00
   17     21     336       $15000      37(*)  17     700       $2BC00
   18     19     357       $16500      38(*)  17     717       $2CD00
   19     19     376       $17800      39(*)  17     734       $2DE00
   20     19     395       $18B00      40(*)  17     751       $2EF00

  (*)Tracks 36-40 apply to 40-track images only

  The directory track should be contained totally on track 18. Sectors 1-18
contain the entries and sector 0 contains the BAM (Block Availability  Map)
and disk name/ID. Since the directory is only 18 sectors large (19 less one
for the BAM), and each sector can contain only  8  entries  (32  bytes  per
entry), the maximum number of directory entries is 18 * 8 = 144. The  first
directory sector is always 18/1, even though the t/s pointer at 18/0 (first
two bytes) might point somewhere else.  It  then  follows  the  same  chain
structure as a normal file, using a sector interleave of 3. This makes  the
chain links go 18/1, 18/4, 18/7 etc.

  Note that you can extend the directory off of track  18,  but  only  when
reading the disk or image. Attempting to write to a directory sector not on
track 18 will cause directory corruption.  See  the  section  below  called
Non-Standard & Long Directories.

Each directory sector has the following layout (18/1 partial dump):

00: 12 04 81 11 00 4E 41 4D 45 53 20 26 20 50 4F 53 <- notice the T/S link
10: 49 54 A0 A0 A0 00 00 00 00 00 00 00 00 00 15 00 <- to 18/4 ($12/$04)
20: 00 00 84 11 02 41 44 44 49 54 49 4F 4E 41 4C 20 <- and how its not here
30: 49 4E 46 4F A0 11 0C FE 00 00 00 00 00 00 61 01 <- ($00/$00)

  The first two bytes of the sector ($12/$04) indicate the location of  the
next track/sector of the directory (18/4). If the track is set to $00, then
it is the last sector of the directory. It is possible,  however  unlikely,
that the directory may *not* be competely on track 18 (some disks do  exist
like this). Just follow the chain anyhow.

  When the directory is done, the track value will be $00. The sector  link
should contain a value of $FF, meaning the whole sector is  allocated,  but
the actual value doesn't matter. The drive will return  all  the  available
entries anyways. This is a breakdown of a  standard  directory  sector  and
entry:

  Bytes: $00-1F: First directory entry
          00-01: Track/Sector location of next directory sector ($00 $00 if
                 not the first entry in the sector)
             02: File type.
                 Typical values for this location are:
                   $00 - Scratched (deleted file entry)
                    80 - DEL
                    81 - SEQ
                    82 - PRG
                    83 - USR
                    84 - REL
                 Bit 0-3: The actual filetype
                          000 (0) - DEL
                          001 (1) - SEQ
                          010 (2) - PRG
                          011 (3) - USR
                          100 (4) - REL
                          Values 5-15 are illegal, but if used will produce
                          very strange results. The 1541 is inconsistent in
                          how it treats these bits. Some routines use all 4
                          bits, others ignore bit 3,  resulting  in  values
                          from 0-7.
                 Bit   4: Not used
                 Bit   5: Used only during SAVE-@ replacement
                 Bit   6: Locked flag (Set produces ">" locked files)
                 Bit   7: Closed flag  (Not  set  produces  "*", or "splat"
                          files)
          03-04: Track/sector location of first sector of file
          05-14: 16 character filename (in PETASCII, padded with $A0)
          15-16: Track/Sector location of first side-sector block (REL file
                 only)
             17: REL file record length (REL file only, max. value 254)
          18-1D: Unused (except with GEOS disks)
          1E-1F: File size in sectors, low/high byte  order  ($1E+$1F*256).
                 The approx. filesize in bytes is <= #sectors * 254
          20-3F: Second dir entry. From now on the first two bytes of  each
                 entry in this sector  should  be  $00  $00,  as  they  are
                 unused.
          40-5F: Third dir entry
          60-7F: Fourth dir entry
          80-9F: Fifth dir entry
          A0-BF: Sixth dir entry
          C0-DF: Seventh dir entry
          E0-FF: Eighth dir entry

Files, on a standard 1541, are stored using an interleave of 10. Assuming a
starting track/sector of 17/0, the chain  would  run  17/0,  17/10,  17/20,
17/8, 17/18, etc.

Note: No GEOS entries are listed in the above description. See the GEOS.TXT
      file for GEOS info.


*** Non-Standard & Long Directories

  Most Commdore floppy disk drives use a single dedicated  directory  track
where all filenames are stored. This limits the number of files stored on a
disk based on the number of sectors on the directory track. There are  some
disk images that contain more files than would normally  be  allowed.  This
requires extending  the  directory  off  the  default  directory  track  by
changing the last directory sector pointer to a new track,  allocating  the
new sectors in the BAM, and manually  placing  (or  moving  existing)  file
entries there. The directory of an extended disk can be read and the  files
that reside there can be loaded without problems on a real drive.  However,
this is still a very dangerous practice as writing to the extended  portion
of the directory will cause directory corruption in the non-extended  part.
Many of the floppy drives core ROM routines ignore the track value that the
directory is on and assume the default directory track for operations.

  To explain: assume that the directory has been extended from track 18  to
track 19/6 and that the directory is full except for a few slots  on  19/6.
When saving a new file, the drive DOS will find an empty file slot at  19/6
offset $40 and correctly write the filename and a  few  other  things  into
this slot. When the file is done being saved  the  final  file  information
will be written to 18/6 offset $40 instead of 19/6 causing  some  directory
corruption to the entry at 18/6. Also, the  BAM  entries  for  the  sectors
occupied by the new file will not be saved and the new file will be left as
a SPLAT (*) file.

  Attempts to validate the disk will result in those files residing off the
directory track to not be allocated in the BAM, and  could  also  send  the
drive into an endless loop. The default directory track is assumed for  all
sector reads when validating so if the directory goes  to  19/6,  then  the
validate code will read 18/6  instead.  If  18/6  is  part  of  the  normal
directory chain then the validate routine will loop endlessly.


*** BAM layout

The layout of the BAM area (sector 18/0) is a bit more complicated...

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 12 01 41 00 12 FF F9 17 15 FF FF 1F 15 FF FF 1F
10: 15 FF FF 1F 12 FF F9 17 00 00 00 00 00 00 00 00
20: 00 00 00 00 0E FF 74 03 15 FF FF 1F 15 FF FF 1F
30: 0E 3F FC 11 07 E1 80 01 15 FF FF 1F 15 FF FF 1F
40: 15 FF FF 1F 15 FF FF 1F 0D C0 FF 07 13 FF FF 07
50: 13 FF FF 07 11 FF CF 07 13 FF FF 07 12 7F FF 07
60: 13 FF FF 07 0A 75 55 01 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 01 08 00 00 03 02 48 00
80: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01
90: 53 48 41 52 45 57 41 52 45 20 31 20 20 A0 A0 A0
A0: A0 A0 56 54 A0 32 41 A0 A0 A0 A0 00 00 00 00 00
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

  Bytes:$00-01: Track/Sector location of the first directory sector (should
                be set to 18/1 but it doesn't matter, and don't trust  what
                is there, always go to 18/1 for first directory entry)
            02: Disk DOS version type (see note below)
                  $41 ("A")
            03: Unused
         04-8F: BAM entries for each track, in groups  of  four  bytes  per
                track, starting on track 1 (see below for more details)
         90-9F: Disk Name (padded with $A0)
         A0-A1: Filled with $A0
         A2-A3: Disk ID
            A4: Usually $A0
         A5-A6: DOS type, usually "2A"
         A7-AA: Filled with $A0
         AB-FF: Normally unused ($00), except for 40 track extended format,
                see the following two entries:
         AC-BF: DOLPHIN DOS track 36-40 BAM entries (only for 40 track)
         C0-D3: SPEED DOS track 36-40 BAM entries (only for 40 track)

Note: The BAM entries for SPEED, DOLPHIN and  ProLogic  DOS  use  the  same
      layout as standard BAM entries.

  One of the interesting things from the BAM sector is the byte  at  offset
$02, the DOS version byte. If it is set to anything other than $41 or  $00,
then we have what is called "soft write protection". Any attempt  to  write
to the disk will return the "DOS Version" error code 73  ,"CBM  DOS  V  2.6
1541". The 1541 is simply telling  you  that  it  thinks  the  disk  format
version is incorrect. This message will normally come  up  when  you  first
turn on the 1541 and read the error channel. If you write a $00  or  a  $41
into 1541 memory location $00FF (for device 0),  then  you  can  circumvent
this type of write-protection, and change the DOS version back to  what  it
should be.

  The BAM entries require a bit (no pun intended) more of a breakdown. Take
the first entry at bytes $04-$07 ($12 $FF $F9 $17). The first byte ($12) is
the number of free sectors on that track. Since we are looking at the track
1 entry, this means it has 18 (decimal) free sectors. The next three  bytes
represent the bitmap of which sectors are used/free. Since it is 3 bytes (8
bits/byte) we have 24 bits of storage. Remember that at  most,  each  track
only has 21 sectors, so there are a few unused bits.

   Bytes: 04-07: 12 FF F9 17   Track 1 BAM
          08-0B: 15 FF FF FF   Track 2 BAM
          0C-0F: 15 FF FF 1F   Track 3 BAM
          ...
          8C-8F: 11 FF FF 01   Track 35 BAM

  These entries must be viewed in binary to make any sense. We will use the
first entry (track 1) at bytes 04-07:

     FF=11111111, F9=11111001, 17=00010111

In order to make any sense from the binary notation, flip the bits around.

                   111111 11112222
        01234567 89012345 67890123
        --------------------------
        11111111 10011111 11101000
        ^                     ^
    sector 0              sector 20

  Since we are on the first track, we have 21 sectors, and only use  up  to
the bit 20 position. If a bit is on (1), the  sector  is  free.  Therefore,
track 1 has sectors 9,10 and 19 used, all the rest are free.  Any  leftover
bits that refer to sectors that don't exist, like bits 21-23 in  the  above
example, are set to allocated.

  Each filetype has its own unique properties, but most follow  one  simple
structure. The first file sector is pointed to by the directory and follows
a t/s chain, until the track value reaches  $00.  When  this  happens,  the
value in the sector link location indicates how much of the sector is used.
For example, the following chain indicates a file 6 sectors long, and  ends
when we encounter the $00/$34 chain. At this point the last sector occupies
from bytes $02-$34.

    1       2       3       4       5       6
  ----    -----   -----   -----   -----   -----
  17/0    17/10   17/20   17/1    17/11    0/52
 (11/00) (11/0A) (11/14) (11/01) (11/0B)  (0/34)


---------------------------------------------------------------------------


*** Variations on the D64 layout

    
These are some variations of the D64 layout:

  1. Standard 35 track layout but with 683 error bytes added on to the  end
     of the file. Each byte of the  error  info  corresponds  to  a  single
     sector stored in the D64, indicating if the  sector  on  the  original
     disk contained an error. The first byte is for track 1/0, and the last
     byte is for track 35/16.

  2. A 40 track layout, following the same layout as a 35 track  disk,  but
     with 5 extra tracks. These contain 17 sectors each, like tracks 31-35.
     Some of the PC utilities do allow you to create and  work  with  these
     files. This can also have error bytes attached like variant #1.

  3. The Commodore 128 allowed for "auto-boot" disks. With  this,  t/s  1/0
     holds a specific byte sequence which the computer recognizes  as  boot
     code. See the document C128BOOT.TXT for more info.


  Below is a small chart detailing the standard file sizes of  D64  images,
35 or 40 tracks, with or without error bytes.

     Disk type                  Size
     ---------                  ------
     35 track, no errors        174848
     35 track, 683 error bytes  175531
     40 track, no errors        196608
     40 track, 768 error bytes  197376


  The following table (provided by Wolfgang Moser) outlines the differences
between the standard 1541 DOS and the various "speeder" DOS's  that  exist.
The 'header 7/8' category is the 'fill bytes' as  the  end  of  the  sector
header of  a  real  1541  disk  See  the  document  G64.TXT  for  a  better
explanation of these bytes.

        Disk format             |Tracks|Header 7/8|Dos type|DiskDos
                                |      |allsechdrs|        |vs.type
       ============================================================
        Original CBM DOS v2.6   |  35  | $0f  $0f |  "2A"  |$41/'A'
       ------------------------------------------------------------
        *SpeedDOS+              |  40  | $0f  $0f |  "2A"  |$41/'A'
       ------------------------------------------------------------
        ProfessionalDOS Initial |  35  | $0f  $0f |  "2A"  |$41/'A'
          (Version 1/Prototype) |  40  | $0f  $0f |  "2A"  |$41/'A'
       ------------------------------------------------------------
        ProfDOS Release         |  40  | $0f  $0f |  "4A"  |$41/'A'
       ------------------------------------------------------------
        Dolphin-DOS 2.0/3.0     |  35  | $0f  $0f |  "2A'  |$41/'A'
        Dolphin-DOS 2.0/3.0     |  40  | $0d  $0f |  "2A'  |$41/'A'
       ------------------------------------------------------------
        PrologicDOS 1541        |  35  | $0f  $0f |  "2A'  |$41/'A'
        PrologicDOS 1541        |  40  | $0f  $0f |  "2P'  |$50/'P'
        ProSpeed 1571 2.0       |  35  | $0f  $0f |  "2A'  |$41/'A'
        ProSpeed 1571 2.0       |  40  | $0f  $0f |  "2P'  |$50/'P'
       ------------------------------------------------------------

*Note: There are also clones of SpeedDOS that exist, such  as  RoloDOS  and
       DigiDOS. Both are just a change of the DOS startup string.

  The location of the extra BAM information in sector 18/0,  for  40  track
images, will be different depending on what standard the  disks  have  been
formatted with. SPEED DOS stores them from $C0 to $D3, DOLPHIN  DOS  stores
them from $AC to $BF and PrologicDOS stored them right after  the  existing
BAM entries from $90-A3. PrologicDOS also  moves  the  disk  label  and  ID
forward from the standard location of $90 to $A4. 64COPY and Star Commander
let you select from several different types of extended  disk  formats  you
want to create/work with.

  All three of the speeder DOS's mentioned above don't alter  the  standard
sector interleave of 10 for files and 3 for directories. The reason is that
they use a memory cache installed in the drive which reads the entire track
in one pass. This alleviates the need for custom interleave values. They do
seem to alter the algorithm that finds the next available  free  sector  so
that the interleave value can deviate from 10 under certain  circumstances,
but I don't know why they would bother.


  Below is a HEX dump of a Speed DOS BAM sector. Note the location of the
extra BAM info from $C0-D3.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0070: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01  ����������������
0080: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01  ����������������
0090: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0  ����������������
00A0: A0 A0 30 30 A0 32 41 A0 A0 A0 A0 00 00 00 00 00  ��00�2A���������
00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00C0: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01  ����������������
00D0: 11 FF FF 01 00 00 00 00 00 00 00 00 00 00 00 00  ����������������


  Below is a HEX dump of a Dolphin DOS BAM sector. Note the location of the
extra BAM info from $AC-BF.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0070: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01  ����������������
0080: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01  ����������������
0090: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0  ����������������
00A0: A0 A0 30 30 A0 32 41 A0 A0 A0 A0 00 11 FF FF 01  ��00�2A���������
00B0: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01  ����������������
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������


  Below is a HEX dump of a PrologicDOS BAM sector. Note that the disk  name
and ID are now located at $A4 instead of starting at $90.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0070: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01  ����������������
0080: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01  ����������������
0090: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01  ����������������
00A0: 11 FF FF 01 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0  ����������������
00B0: A0 A0 A0 A0 A0 A0 30 30 A0 32 50 A0 A0 A0 A0 00  ������00�2P�����
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
00ED: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������


---------------------------------------------------------------------------

*** Error codes

  Here is the meaning of the error bytes added onto the end of any extended
D64. The CODE is the same as that generated by the 1541 drive controller...
it reports these numbers, not the error code we usually see when  an  error
occurs.

  Some of what comes  below  is  taken  from  Immers/Neufeld  book  "Inside
Commodore DOS". Note the descriptions are not  completely  accurate  as  to
what the drive DOS is actually doing to seek/read/decode/write sectors, but
serve as simple examples only. The "type" field is where the error  usually
occurs, whether it's searching for any SYNC mark, any header ID, any  valid
header, or reading a sector.

  These first errors are "seek" errors, where the disk controller is simply
reading headers and looking at descriptor bytes, checksums, format ID's and
reporting what errors it sees. These errors do *not* necessarily  apply  to
the exact sector being looked for. This fact  makes  duplication  of  these
errors very unreliable.

    Code  Error  Type   1541 error description
    ----  -----  ----   ------------------------------
     03    21    Seek   No SYNC sequence found.

                        Each  sector  data  block  and  header  block   are
                        preceeded by SYNC marks. If *no* sync  sequence  is
                        found within 20 milliseconds (only ~1/10 of a  disk
                        rotation!) then this error is generated. This error
                        used to mean the entire track is bad, but  it  does
                        not have to be the case. Only a small area  of  the
                        track needs to be without  a  SYNC  mark  and  this
                        error will be generated.

                        Converting this error to a D64 is very  problematic
                        because it depends on where the physical head is on
                        the disk when a read attempt is made. If it  is  on
                        valid header/sectors then it  won't  occur.  If  it
                        happens over an area without SYNC  marks,  it  will
                        happen.


     02    20    Seek   Header descriptor byte not found (HEX $08, GCR $52)

                        Each sector is preceeded by an  8-byte  GCR  header
                        block, which starts with the value  $52  (GCR).  If
                        this value is not found  after  90  attempts,  this
                        error is generated.

                        Basically, what a track  has  is  SYNC  marks,  and
                        possibly valid data blocks,  but  no  valid  header
                        descriptors.


     09    27    Seek   Checksum error in header block

                        The  header  block  contains  a   checksum   value,
                        calculated by XOR'ing the TRACK,  SECTOR,  ID1  and
                        ID2 values. If this checksum is wrong,  this  error
                        is generated.


     0B    29    Seek   Disk sector ID mismatch

                        The ID's from the header  block  of  the  currently
                        read sector are compared against the ones from  the
                        low-level header of 18/0. If there is  a  mismatch,
                        this error is generated.


     02    20    Seek   Header block not found

                        This error can be reported again when searching for
                        the correct header block. An image of the header is
                        built and searched for, but not found after 90 read
                        attempts.  Note  the  difference  from  the   first
                        occurance. The first one only searches for a  valid
                        ID, not the whole header.

  Note that error 20 occurs twice during this phase. The first time is when
a header ID is being searched for, the second is  when  the  proper  header
pattern for the sector being searched for is not found.


  From this point on, all the errors apply to the specific sector  you  are
looking for. If a read passed all the previous checks, then we are  at  the
sector being searched for.

  Note that the entire sector is read before  these  errors  are  detected.
Therefore the data, checksum and off bytes are available.

    Code  Error  Type   1541 error description
    ----  -----  ----   ------------------------------
     04    22    Read   Data descriptor byte not found (HEX $07, GCR $55)

                        Each sector data block is preceeded  by  the  value
                        $07, the "data block" descriptor. If this value  is
                        not there, this error is  generated.  Each  encoded
                        sector  has  actually  260  bytes.  First  is   the
                        descriptor byte, then  follows  the  256  bytes  of
                        data, a checksum, and two "off" bytes.


     05    23    Read   Checksum error in data block

                        The checksum of  the  data  read  of  the  disk  is
                        calculated, and compared against the one stored  at
                        the end of the sector. If  there's  a  discrepancy,
                        this error is generated.


     0F    74    Read   Drive Not Ready (no disk in drive or no device 1)


  These errors only  apply  when  writing  to  a  disk.  I  don't  see  the
usefulness of having these as they cannot be present when only *reading*  a
disk.

    Code  Error  Type   1541 error description
    ----  -----  ----   ------------------------------
     06    24    Write  Write verify (on format)


     07    25    Write  Write verify error

                        Once the GCR-encoded sector  is  written  out,  the
                        drive waits for the sector to come around again and
                        verifies the whole 325-byte GCR block.  Any  errors
                        encountered will generate this error.


     08    26    Write  Write protect on

                        Self explanatory. Remove the write-protect tab, and
                        try again.


     0A    28    Write  Write error

                        In actual fact, this error never occurs, but it  is
                        included for completeness.


  This is not an error at all, but when gets reported when the  read  of  a
sector is ok.

    Code  Error  Type   1541 error description
    ----  -----  ----   ------------------------------
     01    00    N/A    No error.

                        Self explanatory. No errors were  detected  in  the
                        reading and decoding of the sector.


  The advantage with using the 35 track D64  format,  regardless  of  error
bytes, is that it can be converted directly back to a 1541 disk  by  either
using the proper cable and software on the PC, or send it down to  the  C64
and writing it back to a 1541. It is the best documented format since it is
also native to the C64, with many books explaining the disk layout and  the
internals of the 1541.


---------------------------------------------------------------------------

*** Supporting D64 files

  The D64 layout is reasonably robust,  being  that  it  is  an  electronic
representation of a physical 1541  disk.  It  shares  *most*  of  the  1541
attributes and it supports all file formats, since all C64 files came  from
here. The only file I have found that can't be copied to a D64 is a T64 FRZ
(FRoZen files), since you lose the extra file type attribute.

  Since the D64 layout seems to be an exact byte copy of a 1541 floppy,  it
would appear to be the perfect format for *any* emulator. However, it  does
not contain certain vital bits of information that, as a user, you normally
don't have access to.

  Preceeding each sector on a real  1541  disk  is  a  header  block  which
contains the sector ID bytes and checksum. From the  information  contained
in the header, the drive determines if there's  an  error  on  that  header
(27-checksum error, 29-disk ID mismatch). The sector itself  also  contains
info (data block signature, checksum) that result in  error  detection  (23
checksum, 22 data block not present, etc). The error bytes had to be  added
on to the D64 image, "extending"  the  format  to  take  into  account  the
missing info.

  The disk ID is important in the copy protection of  some  programs.  Some
programs fail to work properly since the D64 doesn't  contain  these  ID's.
These bytes would be an addition to the format which has  never  been  done
and would be difficult to do. (As an aside, the  4-pack  ZipCode  files  do
contain the original master disk ID, but these are lost in  the  conversion
of a ZipCode to a D64. Only storing *one* of the ID's is  not  enough,  all
the sector ID's should be kept.)

  The extended track 1541 disks also presented  a  problem,  as  there  are
several different formats (and how/where to store the extra BAM entries  in
a sector that was not designed for  them,  yet  still  remain  compatible).
Because of the additions to the format (error bytes and  40  tracks)  there
exists 4 different types of D64's, all recognizeable by their size.

  It is also the only format that uses the sector count for the  file  size
rather than  actual  bytes  used.  This  can  present  some  problems  when
converting/copying the to another format because you may have to  know  the
size before you begin (see LBR format).

  It also contains no consistent signature, useful for recognizing  if  D64
is really what it claims to be. In order to determine if a file is  a  D64,
you must check the file size.

---------------------------------------------------------------------------

*** Overall Good/Bad of D64 Files:

  Good
  ----
  * D64 files are the most widely supported and well-defined format, as  it
    is simply an electronic version of a 1541 disk

  * Supports *all* filenames, even those with $00's in them

  * Filenames are padded with the standard $A0 character

  * Supports REL and all GEOS files

  * Allows complete directory customization

  * Because it is a random-access  device,  it  supports  fast-loaders  and
    random sector access

  * PC Cluster slack-space loss is minimized since the  file  is  a  larger
    fixed size

  * Has a label (description) field

  * Format extentible to allow for 40-track disks

  * With  the  inclusion  of  error  bytes,  you  have  support  for  basic
    copy-protection

  * Files on a disk can easily be re-written, as  long  as  there  is  free
    blocks



  Bad
  ---
  * The format doesn't contain *all* the info from the 1541 disk (no sector
    header info like  ID  bytes,  checksums).  This  renders  some  of  the
    original special-loaders and copy-protection useless.

  * You don't *really* know the file size of the  contained  C64  files  in
    bytes, only blocks

  * It can't store C64s FRZ files due to FRZ files needing a  special  flag
    that a D64 can't store. This is by no means a big problem.

  * It is not an expandable filetype, like LNX or T64

  * Unless most of the space on a D64 disk is used,  you  do  end  up  with
    wasted space

  * Directory limited to 144 files maximum

  * Cannot have loadable files with the same names

  * Has no recognizeable file signature (unlike most  other  formats).  The
    only reliable way to know if a file is a D64 is by its size

  * It is too easy for people to muck up the standard layout

  * It is much more difficult to support  fully,  as  you  really  need  to
    emulate the 1541 DOS (sector interleave, REL files, GEOS VLIR files)


*** D71 (Electronic form of a double-sided 1571 disk)
*** Document revision: 1.5
*** Last updated: Nov 7, 2008
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: unknown

  Similar to  the  D64  (1541),  the  1571  drive  can  operate  in  either
single-sided (1541 compatible) mode or double-sided (1571)  mode.  In  this
document I will be  dealing  with  the  double-sided  mode  only.  For  the
breakdown of the single-sided mode, read the D64.TXT document.

  The D71 has 70 tracks, double that of the 1541, with a DOS file  size  of
349696 bytes. If the error byte block (1366 bytes) is attached, this  makes
the file size 351062 bytes. The track range and offsets into the D71  files
are as follows:

            Track       Sec/trk   # Sectors
        --------------  -------   ---------
         1-17 (side 0)    21         357
        18-24 (side 0)    19         133
        25-30 (side 0)    18         108
        31-35 (side 0)    17          85
        36-52 (side 1)    21         357
        53-59 (side 1)    19         133
        60-65 (side 1)    18         108
        66-70 (side 1)    17          85
                                     ---
                              total 1366


  Track #Sect #SectorsIn D71 Offset    Track #Sect #SectorsIn D71 Offset
  ----- ----- ---------- ----------    ----- ----- ---------- ----------
    1     21       0       $00000        36    21     683       $2AB00
    2     21      21       $01500        37    21     704       $2C000
    3     21      42       $02A00        38    21     725       $2D500
    4     21      63       $03F00        39    21     746       $2EA00
    5     21      84       $05400        40    21     767       $2FF00
    6     21     105       $06900        41    21     788       $31400
    7     21     126       $07E00        42    21     809       $32900
    8     21     147       $09300        43    21     830       $33E00
    9     21     168       $0A800        44    21     851       $35300
   10     21     189       $0BD00        45    21     872       $36800
   11     21     210       $0D200        46    21     893       $37D00
   12     21     231       $0E700        47    21     914       $39200
   13     21     252       $0FC00        48    21     935       $3A700
   14     21     273       $11100        49    21     956       $3BC00
   15     21     294       $12600        50    21     977       $3D100
   16     21     315       $13B00        51    21     998       $3E600
   17     21     336       $15000        52    21    1019       $3FB00
   18     19     357       $16500        53    19    1040       $41000
   19     19     376       $17800        54    19    1059       $42300
   20     19     395       $18B00        55    19    1078       $43600
   21     19     414       $19E00        56    19    1097       $44900
   22     19     433       $1B100        57    19    1116       $45C00
   23     19     452       $1C400        58    19    1135       $46F00
   24     19     471       $1D700        59    19    1154       $48200
   25     18     490       $1EA00        60    18    1173       $49500
   26     18     508       $1FC00        61    18    1191       $4A700
   27     18     526       $20E00        62    18    1209       $4B900
   28     18     544       $22000        63    18    1227       $4CB00
   29     18     562       $23200        64    18    1245       $4DD00
   30     18     580       $24400        65    18    1263       $4EF00
   31     17     598       $25600        66    17    1281       $50100
   32     17     615       $26700        67    17    1298       $51200
   33     17     632       $27800        68    17    1315       $52300
   34     17     649       $28900        69    17    1332       $53400
   35     17     666       $29A00        70    17    1349       $54500

  The directory structure is the same as a D64/1541. All the same filetypes
apply, the directory still only holds 144 files per disk  and  should  only
exist on track 18.

  The first two bytes of the sector ($12/$04 or 18/4) indicate the location
of the next track/sector of the directory. If the track  value  is  set  to
$00, then it is the last sector of the directory. It is  possible,  however
unlikely, that the directory may *not* be competely on track 18 (some disks
do exist like this). Just follow the chain anyhow.

  When the directory is done, the track value will be $00. The sector  link
should contain a value of $FF, meaning the whole sector is  allocated,  but
the actual value doesn't matter. The drive will return  all  the  available
entries anyways. This is a breakdown of a  standard  directory  sector  and
entry:

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 12 04 82 11 00 4A 45 54 20 53 45 54 20 57 49 4C   ���.�JET�SET�WIL
10: 4C 59 A0 A0 A0 00 00 00 00 00 00 00 00 00 2B 00   LY������������+�
20: 00 00 82 0F 01 4A 53 57 20 31 A0 A0 A0 A0 A0 A0   ���..JSW�1������
30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 BF 00   ����������������
40: 00 00 82 06 03 53 4F 4E 20 4F 46 20 42 4C 41 47   ���..SON�OF�BLAG
50: 47 45 52 A0 A0 00 00 00 00 00 00 00 00 00 AE 00   GER�������������
60: 00 00 82 15 0D 50 4F 54 54 59 20 50 49 47 45 4F   ���..POTTY�PIGEO
70: 4E A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 A2 00   N���������������
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������

  Bytes: $00-1F: First directory entry
          00-01: Track/Sector location of next directory sector ($00/$FF if
                 its the last sector)
             02: File type.
                 Typical values for this location are:
                   $00 - Scratched (deleted file entry)
                    80 - DEL
                    81 - SEQ
                    82 - PRG
                    83 - USR
                    84 - REL
                 Bit 0-3: The actual filetype
                          000 (0) - DEL
                          001 (1) - SEQ
                          010 (2) - PRG
                          011 (3) - USR
                          100 (4) - REL
                          Values 5-15 are illegal, but if used will produce
                          very strange results. The 1541 is inconsistent in
                          how it treats these bits. Some routines use all 4
                          bits, others ignore bit 3,  resulting  in  values
                          from 0-7.
                 Bit   4: Not used
                 Bit   5: Used only during SAVE-@ replacement
                 Bit   6: Locked flag (Set produces ">" locked files)
                 Bit   7: Closed flag  (Not  set  produces  "*", or "splat"
                          files)
          03-04: Track/sector location of first sector of file
          05-14: 16 character filename (in PETASCII, padded with $A0)
          15-16: Track/Sector location of side-sector block (REL file only)
             17: REL file record length (REL file only)
          18-1D: Unused (except with GEOS disks)
          1C-1D: Track/sector of replacement  file  (only  used  during  an
                 @SAVE or an @OPEN command)
          1E-1F: File size in sectors, low/high  byte  order  ($1E+$1F*256).
                 The approx. filesize in bytes is <= #sectors * 254
          20-3F: Second dir entry. From now on the first two bytes of  each
                 entry in this  sector  should  be  $00/$00,  as  they  are
                 unused.
          40-5F: Third dir entry
          60-7F: Fourth dir entry
          80-9F: Fifth dir entry
          A0-BF: Sixth dir entry
          C0-DF: Seventh dir entry
          E0-FF: Eighth dir entry

  When the 1571 is in is native ("1571") mode,  files  are  stored  with  a
sector interleave of 6, rather than 10 which the  1541  (and  the  1571  in
"1541" mode) uses. The directory still uses an interleave of 3.


*** Non-Standard & Long Directories

  Most Commdore floppy disk drives use a single dedicated  directory  track
where all filenames are stored. This limits the number of files stored on a
disk based on the number of sectors on the directory track. There are  some
disk images that contain more files than would normally  be  allowed.  This
requires extending  the  directory  off  the  default  directory  track  by
changing the last directory sector pointer to a new track,  allocating  the
new sectors in the BAM, and manually  placing  (or  moving  existing)  file
entries there. The directory of an extended disk can be read and the  files
that reside there can be loaded without problems on a real drive.  However,
this is still a very dangerous practice as writing to the extended  portion
of the directory will cause directory corruption in the non-extended  part.
Many of the floppy drives core ROM routines ignore the track value that the
directory is on and assume the default directory track for operations.

  To explain: assume that the directory has been extended from track 18  to
track 19/6 and that the directory is full except for a few slots  on  19/6.
When saving a new file, the drive DOS will find an empty file slot at  19/6
offset $40 and correctly write the filename and a  few  other  things  into
this slot. When the file is done being saved  the  final  file  information
will be written to 18/6 offset $40 instead of 19/6 causing  some  directory
corruption to the entry at 18/6. Also, the  BAM  entries  for  the  sectors
occupied by the new file will not be saved and the new file will be left as
a SPLAT (*) file.

  Attempts to validate the disk will result in those files residing off the
directory track to not be allocated in the BAM, and  could  also  send  the
drive into an endless loop. The default directory track is assumed for  all
sector reads when validating so if the directory goes  to  19/6,  then  the
validate code will read 18/6  instead.  If  18/6  is  part  of  the  normal
directory chain then the validate routine will loop endlessly.


*** Bam layout

  The BAM is somewhat different as it now has to take 35  new  tracks  into
account. In order to do this, most of the extra BAM information  is  stored
on track 53/0, and the remaining sectors on track 53 are marked in the  BAM
as allocated. This does mean that except for one allocated sector on  track
53, the rest of the track is unused and wasted. (Track 53 is the equivalent
to track 18, but on the flip side of the disk). Here is a dump of the first
BAM sector...

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 12 01 41 80 12 FF F9 17 15 FF FF 1F 15 FF FF 1F   ..A�.��..��..��.
10: 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F   .��..��..��..��.
20: 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F   .��..��..��..��.
30: 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F   .��..��..��..��.
40: 15 FF FF 1F 15 FF FF 1F 11 FC FF 07 13 FF FF 07   .��..��..��..��.
50: 13 FF FF 07 13 FF FF 07 13 FF FF 07 13 FF FF 07   .��..��..��..��.
60: 13 FF FF 07 12 FF FF 03 12 FF FF 03 12 FF FF 03   .��..��..��..��.
70: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01   .��..��..��..��.
80: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01   .��..��..��..��.
90: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0   ����������������
A0: A0 A0 30 30 A0 32 41 A0 A0 A0 A0 00 00 00 00 00   ��00�2A���������
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 15 15 15   �������������...
E0: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 00 13   ................
F0: 13 13 13 13 13 12 12 12 12 12 12 11 11 11 11 11   ................

  Bytes:$00-01: Track/Sector location of the first directory sector (should
                be set to 18/1 but it doesn't matter, and don't trust  what
                is there, always go to 18/1 for first directory entry)
            02: Disk DOS version type (see note below)
                  $41 ('A') = 1541
            03: Double-sided flag
                $00 - Single sided disk
                $80 - Double sided disk
         04-8F: BAM entries for each track, in groups  of  four  bytes  per
                track, starting on track 1.
         90-9F: Disk Name (padded with $A0)
         A0-A1: Filled with $A0
         A2-A3: Disk ID
            A4: Usually $A0
         A5-A6: DOS type, usually "2A"
         A7-AA: Filled with $A0
         AB-DC: Not used ($00's)
         DD-FF: Free sector count for tracks 36-70 (1 byte/track).

  The "free sector" entries for tracks 36-70 are likely  included  here  in
the first BAM sector due to some memory restrictions  in  the  1571  drive.
There is only enough memory available for one BAM sector, but in  order  to
generate the "blocks free" value at the end of  a  directory  listing,  the
drive needs to know the extra track "free  sector"  values.  It  does  make
working with the BAM a little more difficult, though.

  These are the values that would normally be with the  4-byte  BAM  entry,
but the rest of the entry is contained on 53/0.

Note: If the DOS version byte is set to anything other  than  $41  or  $00,
then we have what is called "soft write protection". Any attempt  to  write
to the disk will return the "DOS Version" error code 73. The 1571 is simply
telling you that it thinks the disk format version is incorrect.

  The BAM entries require some explanation. Take the first entry  at  bytes
$04-$07 ($12 $FF $F9 $17). The first byte  ($12)  is  the  number  of  free
sectors on that track. Since we are looking at  the  track  1  entry,  this
means it has 18 (decimal) free sectors.

  The next three bytes represent the bitmap of which sectors are used/free.
Since it is 3 bytes (8 bits/byte) we have 24 bits of storage. Remember that
at most, each track only has 21 sectors, so there are a  few  unused  bits.
These entries must be viewed in binary to make any sense. We will  use  the
first entry (track 1) at bytes 04-07:

     FF=11111111, F9=11111001, 17=00010111

In order to make any sense from the binary notation, flip the bits around.

                   111111 11112222
        01234567 89012345 67890123
        --------------------------
        11111111 10011111 11101000
        ^                     ^
    sector 0              sector 20

  Since we are on the first track, we have 21 sectors, and only use  up  to
the bit 20 position. If a bit is on (1), the  sector  is  free.  Therefore,
track 1 has sectors 9,10 and 19 used, all the rest are free.

In order to complete the BAM, we must check 53/0.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF   ��.��.��.��.��.�
10: FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF   �.��.��.��.��.��
20: 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F   .��.��.��.��.��.
30: FF FF 1F 00 00 00 FF FF 07 FF FF 07 FF FF 07 FF   ��.�����.��.��.�
40: FF 07 FF FF 07 FF FF 07 FF FF 03 FF FF 03 FF FF   �.��.��.��.��.��
50: 03 FF FF 03 FF FF 03 FF FF 03 FF FF 01 FF FF 01   .��.��.��.��.��.
60: FF FF 01 FF FF 01 FF FF 01 00 00 00 00 00 00 00   ��.��.��.�������
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������

Each track from 36-70 has 3 byte entries, starting at address $00.

      Byte: $00-02: FF FF 1F  - BAM map for track 36
             03-05: FF FF 1F  - BAM map for track 37
             ...
             33-35: 00 00 00  - BAM map for track 53
             ...
             66-68: FF FF 01  - BAM map for track 70
             69-FF:           - Not used

  You can break down the entries for tracks 36-70 the same way as track  1,
just combine the free sector bytes from 18/0 and the BAM usage from  53  to
get the full 4-byte entry.

  Just like a D64, you can attach error bytes to the file, for sector error
information. This block is 1366 bytes long, 1 byte for  each  of  the  1366
sectors in the image. With the error bytes, the file size is 351062 bytes.


-------------------------------------------------------------------------------

*** REL files

  The REL filetype requires some extra explaining. It was designed to  make
access to data *anywhere* on the disk  very  fast.  Take  a  look  at  this
directory entry...

00: 00 00 84 11 02 41 44 44 49 54 49 4F 4E 41 4C 20  ���..ADDITIONAL�
10: 49 4E 46 4F A0 11 0C FE 00 00 00 00 00 00 61 01  INFO�..�������a.

  The third byte ($84) indicates this entry is a  REL  file  and  that  the
three normally empty entries at offset $15, $16 and $17  are  now  used  as
they are explained above. It's  the  track/sector  chain  that  this  entry
points to, called the SIDE SECTOR, which is of interest here (in this case,
17/12). If  you  check  the  D64  document  for  a  REL  file  and  do  the
calculations, you will find that the maximum file size of the REL  file  is
720 data sectors.

The side sector layout is the same as the D64.

00: 02 11 00 FE 11 0C 07 13 04 09 00 00 00 00 00 00
10: 11 02 11 0D 11 03 11 0E 11 04 11 0F 11 05 11 10

  Bytes:   $00: Track location of next side-sector ($00 if last sector)
            01: Sector location of next side-sector
            02: Side-sector block number (first sector is $00, the next  is
                $01, then $02, etc)
            03: REL file RECORD size (from directory entry)
         04-0F: Track/sector locations of the six other side-sectors.  Note
                the first entry is this very sector we  have  listed  here.
                The next is the next t/s listed at  the  beginning  of  the
                sector. All of this information must be correct. If one  of
                these chains is $00/$00, then we have no more side sectors.
                Also, all of these (up to six) side sectors must  have  the
                same values in this range.
         10-FF: T/S chains of *each* sector of the data  portion.  When  we
                get a $00/$00, we are at the end of the file.

---------------------------------------------------------------------------

*** Overall Good/Bad of D71 Files:

  Good
  ----
  * Most emualators support these.

  * Supports *all* filenames, even those with 00's in them

  * Filenames are padded with the standard $A0 character

  * Supports GEOS files

  * Supports REL files

  * Allows full directory customization

  * Because it is a random-access  device,  it  supports  fast-loaders  and
    random sector access

  * Cluster slack-space loss is minimized since the file is a larger  fixed
    size

  * Has a label (description) field

  * With  the  inclusion  of  error  bytes,  you  have  support  for  basic
    copy-protection

  * Files on a disk can easily be re-written, as  long  as  there  is  free
    blocks



  Bad
  ---
  * The format doesn't contain *all* the info from the 1571 disk (no sector
    header info like  ID  bytes,  checksums).  This  renders  some  of  the
    original special-loaders and copy-protection useless.

  * You don't *really* know the file size of the  contained  C64  files  in
    bytes, only blocks

  * It can't store C64s FRZ files due to FRZ files needing a  special  flag
    that a D71 can't store

  * It is not an expandable filesize, like LNX or T64

  * Unless most of the space on a D71 disk is used, you do end up with lost
    space

  * Directory limited to 144 files maximum

  * Cannot have loadable files with the same names

  * Has no recognizeable file signature (unlike most  other  formats).  The
    only reliable way to know if a file is a D71 is by its size

  * It is too easy for people to muck up the standard layout

  * It is much more difficult to support  fully,  as  you  really  need  to
    emulate the 1571 DOS (sector interleave, REL support, GEOS interleave)


*** D80 (Disk image of an 8050 diskette, single-sided)
*** D82 (Disk image of an 8250 diskette, double-sided)
*** Document revision: 1.3
*** Last updated: Nov 7, 2008
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: "Complete Commodore Innerspace Anthology"

  This is a sector-for-sector copy of an 8x50 floppy disk.  The  file  size
for an 8050 image is 533248 bytes, and the 8250 image is 1066496 bytes.  It
is comprised of 256-byte sectors arranged across 77 tracks (or 154  for  an
8250), with a varying number of sectors per  track  for  a  total  of  2083
sectors (or 4166 for an 8250). Track counting  starts  at  1  (not  0)  and
sector counting starts at 0 (not 1), therefore a track with 29 sectors will
go from 0 to 28.

  The only sample files I had to work with were those created by  the  VICE
emulator. I can only assume that the way VICE  worked  with  the  image  is
correct and all of the image specifics contained herein are based on  those
samples. Any deviation from the way that the 8x50 drive actually  works  is
unfortunate but unavoidable.

  The original media (a 5.25" disk) has the tracks  laid  out  in  circles,
with track 1 on the very outside of the disk  (closest  to  the  sides)  to
track 77 being on the inside of the disk (closest to the inner  hub  ring).
Commodore, in their infinite wisdom, varied the number of sectors per track
and data densities across the disk to optimize available storage, resulting
in the chart below. It shows the sectors/track for a D80 and D82. Since the
outside diameter of a circle is the largest (versus closer to the  center),
the outside tracks have the largest amount of storage.


        Track Range    Sectors/track   # Sectors
      --------------   -------------   ---------
       1-39,  78-116        29           1131
      40-53, 117-130        27            378
      54-64, 131-141        25            275
      65-77, 142-154        23            299
                                         ----
                                  Total  2083 (double this for an 8250)


  Track #Sect #SectorsIn D8x Offset | Track #Sect #SectorsIn D8x Offset
  ----- ----- ---------- ---------- | ----- ----- ---------- ----------
   1     29      0        $000000   |  78    29      2083      $82300
   2     29      29          1D00   |  79    29      2112       84000
   3     29      58          3A00   |  80    29      2141       85D00
   4     29      87          5700   |  81    29      2170       87A00
   5     29      116         7400   |  82    29      2199       89700
   6     29      145         9100   |  83    29      2228       8B400
   7     29      174         AE00   |  84    29      2257       8D100
   8     29      203         CB00   |  85    29      2286       8EE00
   9     29      232         E800   |  86    29      2315       90600
   10    29      261        10500   |  87    29      2344       92800
   11    29      290        12200   |  88    29      2373       94500
   12    29      319        13F00   |  89    29      2402       96200
   13    29      348        15C00   |  90    29      2431       97F00
   14    29      377        17900   |  91    29      2460       99C00
   15    29      406        19600   |  92    29      2489       9B900
   16    29      435        1B300   |  93    29      2518       9D600
   17    29      464        1D000   |  94    29      2547       9F300
   18    29      493        1ED00   |  95    29      2576       A1000
   19    29      522        20A00   |  96    29      2605       A2D00
   20    29      551        22700   |  97    29      2634       A4A00
   21    29      580        24400   |  98    29      2663       A6700
   22    29      609        26100   |  99    29      2692       A8400
   23    29      638        27E00   |  100   29      2721       AA100
   24    29      667        29B00   |  101   29      2750       A6E00
   25    29      696        2B800   |  102   29      2779       ADB00
   26    29      725        2D500   |  103   29      2808       AF800
   27    29      754        2F200   |  104   29      2837       B1500
   28    29      783        30F00   |  105   29      2866       B3200
   29    29      812        32C00   |  106   29      2895       B4F00
   30    29      841        34900   |  107   29      2924       B6C00
   31    29      870        36600   |  108   29      2953       B8900
   32    29      899        38300   |  109   29      2982       BA600
   33    29      928        3A000   |  110   29      3011       BC300
   34    29      957        3BD00   |  111   29      3040       BE000
   35    29      986        3DA00   |  112   29      3069       BFD00
   36    29      1015       3F700   |  113   29      3098       C1A00
   37    29      1044       41400   |  114   29      2137       C3700
   38    29      1073       43100   |  115   29      3156       C5400
   39    29      1102       44E00   |  116   29      3185       C7100
   40    27      1131       46B00   |  117   27      3214       C8E00
   41    27      1158       48600   |  118   27      3241       CA900
   42    27      1185       4A100   |  119   27      3268       CC400
   43    27      1212       4BC00   |  120   27      3295       CDF00
   44    27      1239       4D700   |  121   27      3322       CFA00
   45    27      1266       4F200   |  122   27      3349       D1500
   46    27      1293       50D00   |  123   27      3376       D3000
   47    27      1320       52800   |  124   27      3403       D4B00
   48    27      1347       54300   |  125   27      3430       D6600
   49    27      1374       55E00   |  126   27      3457       D8100
   50    27      1401       57900   |  127   27      3484       D9C00
   51    27      1428       59400   |  128   27      3511       DB700
   52    27      1455       5AF00   |  129   27      3538       DD200
   53    27      1482       5CA00   |  130   27      3565       DED00
   54    25      1509       5E500   |  131   25      3592       E0800
   55    25      1534       5FE00   |  132   25      3617       E2100
   56    25      1559       61700   |  133   25      3642       E3A00
   57    25      1584       63000   |  134   25      3667       E5300
   58    25      1609       64900   |  135   25      3692       E6C00
   59    25      1634       66200   |  136   25      3717       E8500
   60    25      1659       67B00   |  137   25      3742       E9E00
   61    25      1684       69400   |  138   25      3767       E6700
   62    25      1709       6AD00   |  139   25      3792       ED000
   63    25      1734       6C600   |  140   25      3817       EE900
   64    25      1759       6DF00   |  141   25      3842       F0200
   65    23      1784       6F800   |  142   23      3867       F1B00
   66    23      1807       70F00   |  143   23      3890       F3200
   67    23      1830       72600   |  144   23      3913       F4900
   68    23      1853       73D00   |  145   23      3936       F6000
   69    23      1876       75400   |  146   23      3959       F7700
   70    23      1899       76B00   |  147   23      3982       F8E00
   71    23      1922       78200   |  148   23      4005       FA500
   72    23      1945       79900   |  149   23      4028       FBC00
   73    23      1968       7B000   |  150   23      4051       FD300
   74    23      1991       7C700   |  151   23      4074       FEA00
   75    23      2014       7DE00   |  152   23      4097      100100
   76    23      2037       7F500   |  153   23      4120      101800
   77    23      2060       80C00   |  154   23      4143      102F00

  The BAM (Block Availability Map) is on track  38.  The  D80  is  only  77
tracks and so the BAM is contained on 38/0 and 38/3. The D82  contains  154
tracks and so the BAM is larger and is contained on 38/0,  38/3,  38/6  and
38/9. The BAM interleave is 3.

  The directory is on track 39, with 39/0 contains the  header  (DOS  type,
disk name, disk ID's) and sectors 1-28 contain the directory entries.  Both
files and the directory use an interleave of 1. Since the directory is only
28 sectors large (29 less one for the header), and each sector can  contain
only 8 entries (32 bytes  per  entry),  the  maximum  number  of  directory
entries is 28 * 8 = 224. The first directory sector is always 39/1. It then
follows a chain structure using a sector interleave of 1 making  the  links
go 39/1, 39/2, 39/3 etc.

  When reading a disk, you start with 39/0 (disk label/ID) which points  to
38/0 (BAM0), 38/3 (BAM1), 38/6 (BAM2, D82 only), 38/9 (BAM3, D82 only), and
finally to 39/1 (first dir entry sector). When writing a file  to  a  blank
disk, it will start at 38/1 because 38/0 is already allocated.


Below is a dump of the header sector 39/0:

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 26 00 43 00 00 00 73 61 6D 70 6C 65 20 64 38 30  &�C���sample�d80
10: A0 A0 A0 A0 A0 A0 A0 A0 65 72 A0 32 43 A0 A0 A0  ��������er�2C���
20: A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
...
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

  Byte:$00-01: T/S pointer to first BAM sector (38/0)
           02: $43 'C' is for DOS format version
           03: Reserved
        04-05: Unused
        06-16: Disk name, padded with 0xA0 ("sample d80")
           17: 0xA0
        18-19: Disk ID bytes "er"
           1A: 0xA0
        1B-1C: DOS version bytes "2C".
        1D-20: 0xA0
        21-FF: Unused


Below is a dump of the first directory sector, 39/1

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 27 02 82 26 01 54 45 53 54 A0 A0 A0 A0 A0 A0 A0  '��&�TEST�������
10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00  ����������������
20: 00 00 82 26 02 54 45 53 54 32 A0 A0 A0 A0 A0 A0  ���&�TEST2������
30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00  ����������������
40: 00 00 82 26 04 54 45 53 54 33 A0 A0 A0 A0 A0 A0  ���&�TEST3������
50: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 05 00  ����������������
60: 00 00 82 26 0B 54 45 53 54 34 A0 A0 A0 A0 A0 A0  ���&�TEST4������
70: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 09 00  ����������������
80: 00 00 82 26 14 54 45 53 54 35 A0 A0 A0 A0 A0 A0  ���&�TEST5������
90: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0C 00  ����������������
A0: 00 00 82 28 00 54 45 53 54 36 A0 A0 A0 A0 A0 A0  ���(�TEST6������
B0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00  ����������������
C0: 00 00 82 28 01 54 45 53 54 37 A0 A0 A0 A0 A0 A0  ���(�TEST7������
D0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00  ����������������
E0: 00 00 82 28 02 54 45 53 54 38 A0 A0 A0 A0 A0 A0  ���(�TEST8������
F0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00  ����������������

  The first two bytes  of  the  directory  sector  ($27/$02)  indicate  the
location of the next track/sector of the directory (39/2). If the track  is
set to $00, then it is the last sector of the directory.

  When the directory is done, the track value will be $00. The sector  link
should contain a value of $FF, meaning the whole sector is  allocated,  but
the actual value doesn't matter. The drive will return  all  the  available
entries anyways. This is a breakdown of a  standard  directory  sector  and
entry:

  Bytes: $00-1F: First directory entry
          00-01: Track/Sector location of next directory sector ($00 $00 if
                 not the first entry in the sector)
             02: File type.
                 Typical values for this location are:
                   $00 - Scratched (deleted file entry)
                    80 - DEL
                    81 - SEQ
                    82 - PRG
                    83 - USR
                    84 - REL
                 Bit 0-3: The actual filetype
                          000 (0) - DEL
                          001 (1) - SEQ
                          010 (2) - PRG
                          011 (3) - USR
                          100 (4) - REL
                          Values 5-15 are illegal, but if used will produce
                          very strange results.
                 Bit   4: Not used
                 Bit   5: Used only during SAVE-@ replacement
                 Bit   6: Locked flag (Set produces ">" locked files)
                 Bit   7: Closed flag  (Not  set  produces  "*", or "splat"
                          files)
          03-04: Track/sector location of first sector of file
          05-14: 16 character filename (in PETASCII, padded with $A0)
          15-16: Track/Sector location of first side-sector block (REL file
                 only)
             17: REL file record length (REL file only, max. value 254)
          18-1D: Unused
          1E-1F: File size in sectors, low/high byte  order  ($1E+$1F*256).
                 The approx. filesize in bytes is <= #sectors * 254
          20-3F: Second dir entry. From now on the first two bytes of  each
                 entry in this sector  should  be  $00  $00,  as  they  are
                 unused.
          40-5F: Third dir entry
          60-7F: Fourth dir entry
          80-9F: Fifth dir entry
          A0-BF: Sixth dir entry
          C0-DF: Seventh dir entry
          E0-FF: Eighth dir entry


*** Non-Standard & Long Directories

  Most Commdore floppy disk drives use a single dedicated  directory  track
where all filenames are stored. This limits the number of files stored on a
disk based on the number of sectors on the directory track. There are  some
disk images that contain more files than would normally  be  allowed.  This
requires extending  the  directory  off  the  default  directory  track  by
changing the last directory sector pointer to a new track,  allocating  the
new sectors in the BAM, and manually  placing  (or  moving  existing)  file
entries there. The directory of an extended disk can be read and the  files
that reside there can be loaded without problems on a real drive.  However,
this is still a very dangerous practice as writing to the extended  portion
of the directory will cause directory corruption in the non-extended  part.
Many of the floppy drives core ROM routines ignore the track value that the
directory is on and assume the default directory track for operations.

  To explain: assume that the directory has been extended from track 18  to
track 19/6 and that the directory is full except for a few slots  on  19/6.
When saving a new file, the drive DOS will find an empty file slot at  19/6
offset $40 and correctly write the filename and a  few  other  things  into
this slot. When the file is done being saved  the  final  file  information
will be written to 18/6 offset $40 instead of 19/6 causing  some  directory
corruption to the entry at 18/6. Also, the  BAM  entries  for  the  sectors
occupied by the new file will not be saved and the new file will be left as
a SPLAT (*) file.

  Attempts to validate the disk will result in those files residing off the
directory track to not be allocated in the BAM, and  could  also  send  the
drive into an endless loop. The default directory track is assumed for  all
sector reads when validating so if the directory goes  to  19/6,  then  the
validate code will read 18/6  instead.  If  18/6  is  part  of  the  normal
directory chain then the validate routine will loop endlessly.


*** BAM layout

  The BAM only occupies up to four sectors on track 38, so the rest of  the
track is empty and is available for file storage. Below is a  dump  of  the
first BAM block, 38/0. A D80 will only contain two BAM  sectors,  38/0  and
38/3. A D82 needs two extra BAM sectors for the extra  tracks.  Each  entry
takes 5 bytes, 1 for the free count on that track, and 4 for the BAM bits.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 26 03 43 00 01 33 1D FF FF FF 1F 1D FF FF FF 1F  &�C��3����������
10: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D  ����������������
20: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF  ����������������
30: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF  ����������������
40: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF  ����������������
50: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F  ����������������
60: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D  ����������������
70: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF  ����������������
80: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF  ����������������
90: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF  ����������������
A0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F  ����������������
B0: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1B  ����������������
C0: F6 FF FF 1F 1B FC FF FF 1F 1B FF FF FF 07 1B FF  ����������������
D0: FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF  ����������������
E0: FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF  ����������������
F0: 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07  ����������������

  Byte:$00-01: T/S pointer to second BAM sector (38/3)
           02: DOS version byte (0x43='C')
           03: Reserved
           04: Lowest track covered by this BAM (0x01=1)
           05: Highest+1 track covered by this BAM (0x33=51)
        06-0A: BAM for track 1. The first byte shows the "blocks free"  for
               this track, the remaining 4 show the BAM for the track.
        0B-0F: BAM for track 2
        ...
        FB-FF: BAM for track 50


  Being bit-based, the BAM entries need some explanation. The  first  track
entry in the above BAM sector is at offset 06, "1D FF FF FF 1F". The  first
number is how many blocks are free on this track ($1D=29) and the remainder
is the bit representation of the usage map for  the  track.  These  entries
must be viewed in binary to make any sense. First  convert  the  values  to
binary:

     FF=11111111, FF=11111111, FF=11111111, 1F=00011111

In order to make any sense from the binary notation, flip the bits around.

                   111111 11112222 222222
        01234567 89012345 67890123 456789...
        -------------------------- ---------
        11111111 11111111 11111111 11111000
        ^                              ^
    sector 0                       sector 28

  Since we are on the first track, we have 29 sectors, and only use  up  to
the bit 28 position. If a bit is on (1), the  sector  is  free.  Therefore,
track 1 is clean, all sectors are free. Any leftover  bits  that  refer  to
sectors that don't exist, like bits 29-31 in the above example, are set  to
allocated.



Second BAM block 38/3, D80 only.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 27 01 43 00 33 4E 1B FF FF FF 07 1B FF FF FF 07  '�C�3N����������
10: 1B FF FF FF 07 19 FF FF FF 01 19 FF FF FF 01 19  ����������������
20: FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF  ����������������
30: FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF FF  ����������������
40: FF 01 19 FF FF FF 01 19 FF FF FF 01 17 FF FF 7F  ���������������
50: 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00  �������������
60: 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17  �������������
70: FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF  �������������
80: FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 00 00 00  �������������
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

  Byte:$00-01: T/S pointer to first directory sector (39/1)
           02: DOS version byte (0x43 'C')
           03: Reserved
           04: Lowest track covered by this BAM (0x33=51)
           05: Highest+1 track covered by this BAM (0x43=78)
        06-0A: BAM for track 51. The first byte shows the "blocks free" for
               this track, the remaining 4 show the BAM for the track.
        0B-0F: BAM for track 52
        ...
        88-8C: BAM for track 77
        8D-FF: Not used for an D80 (8050)


Second BAM block 38/3, D82 only

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 26 06 43 00 33 65 1B FF FF FF 07 1B FF FF FF 07  &�C�3e����������
10: 1B FF FF FF 07 19 FF FF FF 01 19 FF FF FF 01 19  ����������������
20: FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF  ����������������
30: FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF FF  ����������������
40: FF 01 19 FF FF FF 01 19 FF FF FF 01 17 FF FF 7F  ���������������
50: 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00  �������������
60: 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17  �������������
70: FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF  �������������
80: FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 1D FF FF  �������������
90: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF  ����������������
A0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F  ����������������
B0: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D  ����������������
C0: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF  ����������������
D0: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF  ����������������
E0: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF  ����������������
F0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F  ����������������

  Byte:$00-01: T/S pointer to second BAM sector (38/6)
           02: DOS version byte (0x43='C')
           03: Reserved
           04: Lowest track covered by this BAM (0x33=51)
           05: Highest+1 track covered by this BAM (0x65=101)
        06-0A: BAM for track 51. The first byte shows the "blocks free" for
               this track, the remaining 4 show the BAM for the track.
        0B-0F: BAM for track 52
        ...
        FB-FF: BAM for track 100


Third BAM block 38/6, D82 only

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 26 09 43 00 65 97 1D FF FF FF 1F 1D FF FF FF 1F  &�C�e�����������
10: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D  ����������������
20: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF  ����������������
30: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF  ����������������
40: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF  ����������������
50: 1F 1D FF FF FF 1F 1B FF FF FF 07 1B FF FF FF 07  ����������������
60: 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B  ����������������
70: FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF  ����������������
80: FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF  ����������������
90: FF 07 1B FF FF FF 07 1B FF FF FF 07 19 FF FF FF  ����������������
A0: 01 19 FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01  ����������������
B0: 19 FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19  ����������������
C0: FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF  ����������������
D0: FF FF 01 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF  ��������������
E0: 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F  ������������
F0: 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00  �������������

  Byte:$00-01: T/S pointer to fourth BAM sector (38/9)
           02: DOS version byte (0x43='C')
           03: Reserved
           04: Lowest track covered by this BAM (0x65=101)
           05: Highest+1 track covered by this BAM (0x97=151)
        06-0A: BAM for track 101. The first byte shows  the  "blocks  free"
               for this track, the remaining 4 show the BAM for the track.
        0B-0F: BAM for track 102
        ...
        FB-FF: BAM for track 150


Fourth BAM block 38/9, D82 only

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 27 01 43 00 97 9B 17 FF FF 7F 00 17 FF FF 7F 00  '�C�����������
10: 17 FF FF 7F 00 17 FF FF 7F 00 00 00 00 00 00 00  ��������������
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

  Byte:$00-01: T/S pointer to first directory sector (39/1)
           02: DOS version byte (0x43 'C')
           03: Reserved
           04: Lowest track covered by this BAM (0x97=151)
           05: Highest+1 track covered by this BAM (0x9B=155)
        06-0A: BAM for track 151. The first byte shows the "blocks free" for
               this track, the remaining 4 show the BAM for the track.
        0B-0F: BAM for track 152
        ...
        15-19: BAM for track 154
        1A-FF: Not used


For more information on file storage, GCR layout, or disk  errors  see  the
D64.TXT and G64.TXT documents.


*** D81 (Electronic form of a physical 1581 disk)
*** Document revision: 1.4
*** Last updated: Nov 7, 2008
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: unknown

  Like D64 and D71, this is a byte for byte copy of a physical  1581  disk.
It consists of 80 tracks, 40 sectors each (0 to 39) for a  size  of  819200
bytes, or 3200 sectors. If the error byte block is attached, this makes the
file size 822400 bytes.

  There are three sectors on the directory track used  for  disk  internals
(header and BAM), leaving 37 sectors for filename  entries,  thus  allowing
for 296 files (37 * 8) to be stored at the root level of the disk.

  The actual physical layout on the disk is quite different from  what  the
user sees, but this is unimportant to  the  scope  of  this  document.  One
important difference from the D64 and D71 is all the sector interleaves  is
now 1 for both files and directory storage (rather than 3 for directory and
10 for file on a D64/D71) . This is due to the built-in  buffering  in  the
1581. When reading a sector, the whole track will be  buffered  in  memory,
and any sectors being modified will be done in memory. Once it  has  to  be
written, the whole track will be written out in one step.


  The track range and offsets into the D81 files are as follows:

  Track #Sect #SectorsIn D81 Offset  |  Track #Sect #SectorsIn D81 Offset
  ----- ----- ---------- ----------  |  ----- ----- ---------- ----------
    1     40       0       $00000    |    41     40    1600       $64000
    2     40      40       $02800    |    42     40    1640       $66800
    3     40      80       $05000    |    43     40    1680       $69000
    4     40     120       $07800    |    44     40    1720       $6B800
    5     40     160       $0A000    |    45     40    1760       $6E000
    6     40     200       $0C800    |    46     40    1800       $70800
    7     40     240       $0F000    |    47     40    1840       $73000
    8     40     280       $11800    |    48     40    1880       $75800
    9     40     320       $14000    |    49     40    1920       $78000
   10     40     360       $16800    |    50     40    1960       $7A800
   11     40     400       $19000    |    51     40    2000       $7D000
   12     40     440       $1B800    |    52     40    2040       $7F800
   13     40     480       $1E000    |    53     40    2080       $82000
   14     40     520       $20800    |    54     40    2120       $84800
   15     40     560       $23000    |    55     40    2160       $87000
   16     40     600       $25800    |    56     40    2200       $89800
   17     40     640       $28000    |    57     40    2240       $8C000
   18     40     680       $2A800    |    58     40    2280       $8E800
   19     40     720       $2D000    |    59     40    2320       $91000
   20     40     760       $2F800    |    60     40    2360       $93800
   21     40     800       $32000    |    61     40    2400       $96000
   22     40     840       $34800    |    62     40    2440       $98800
   23     40     880       $37000    |    63     40    2480       $9B000
   24     40     920       $39800    |    64     40    2520       $9D800
   25     40     960       $3C000    |    65     40    2560       $A0000
   26     40    1000       $3E800    |    66     40    2600       $A2B00
   27     40    1040       $41000    |    67     40    2640       $A5000
   28     40    1080       $43800    |    68     40    2680       $A7800
   29     40    1120       $46000    |    69     40    2720       $AA000
   30     40    1160       $48800    |    70     40    2760       $AC800
   31     40    1200       $4B000    |    71     40    2800       $AF000
   32     40    1240       $4D800    |    72     40    2840       $B1800
   33     40    1280       $50000    |    73     40    2880       $B4000
   34     40    1320       $52800    |    74     40    2920       $B6800
   35     40    1360       $55000    |    75     40    2960       $B9000
   36     40    1400       $57800    |    76     40    3000       $BB800
   37     40    1440       $5A000    |    77     40    3040       $BE000
   38     40    1480       $5C800    |    78     40    3080       $C0800
   39     40    1520       $5F000    |    79     40    3120       $C3000
   40     40    1560       $61800    |    80     40    3160       $C5800


  The header sector is stored at 40/0, and contains the disk name,  ID  and
DOS version bytes, but the BAM is no longer contained here (like the D64).

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 28 03 44 00 31 35 38 31 20 55 54 49 4C 49 54 59   (.D�1581�UTILITY
10: 20 56 30 31 A0 A0 47 42 A0 33 44 A0 A0 00 00 00   �V01��GB�3D�����
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������

  Bytes:$00-01: Track/Sector location of the first directory sector (should
                be set to 40/3 but it doesn't matter, and don't trust  what
                is there, always go to 40/3 for first directory entry)
            02: Disk DOS version type (see note below)
                  $44 ('D')=1581
            03: $00
         04-13: 16 character Disk Name (padded with $A0)
         14-15: $A0
         16-17: Disk ID
            18: $A0
            19: DOS Version ("3")
            1A: Disk version ("D")
         1B-1C: $A0
         1D-FF: Unused (usually $00)

  The following might be set if the disk is a GEOS  format  (this  info  is
based on the D64 layout, and might not prove to be true)

         AB-AC: Border sector (GEOS only, else set to $00)
         AD-BC: GEOS ID string ("geos FORMAT V1.x" GEOS only, else $00)
         BD-FF: Unused (usually $00)

Note: If the DOS version byte is changed to anything other than a  $44  (or
$00), then we have what is called "soft write protection". Any  attempt  to
write to the disk will return the "DOS Version" error code 73. The drive is
simply telling you that it thinks the disk format version is incompatible.

  The directory track should be contained totally on track 40. Sectors 3-39
contain the entries and sector 1 and 2 contain the BAM (Block  Availability
Map). Sector 0 holds the disk name and ID. The first  directory  sector  is
always 40/3, even though the t/s pointer at 40/0 (first  two  bytes)  might
point somewhere else. It goes linearly up the  sector  count,  3-4-5-6-etc.
Each sector holds up to eight entries.

  The first two bytes of the sector ($28/$04) indicate the location of  the
next track/sector of the directory (40/4). If the track is set to $00, then
it is the last sector of the directory. It is possible,  however  unlikely,
that the directory may *not* be competely on  track  40.  Just  follow  the
chain anyhow.

  When the directory is done (track=$00), the sector should contain an $FF,
meaning the whole sector is allocated. Theactual value  doesn't  matter  as
all the entries will be returned anyways. Each  directory  sector  has  the
following layout:

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 28 04 81 2B 00 53 43 52 45 45 4E 20 20 33 A0 A0   (.�+�SCREEN��3��
10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 02 00   ��������������.�
20: 00 00 81 2B 01 53 43 52 45 45 4E 20 20 34 A0 A0   ���+.SCREEN��4��
30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 03 00   ��������������.�
40: 00 00 81 2B 02 53 43 52 45 45 4E 20 20 35 A0 A0   ���+.SCREEN��5��
50: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 07 00   ��������������.�
60: 00 00 81 2B 08 53 43 52 45 45 4E 20 20 36 A0 A0   ���+.SCREEN��6��
70: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 08 00   ��������������.�
80: 00 00 81 2B 14 53 43 52 45 45 4E 20 20 37 A0 A0   ���+.SCREEN��7��
90: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 07 00   ��������������.�
A0: 00 00 81 24 00 53 43 52 45 45 4E 20 20 38 A0 A0   ���$�SCREEN��8��
B0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0B 00   ��������������.�
C0: 00 00 82 24 04 46 49 4C 45 34 32 39 33 36 39 30   ���$.FILE4293690
D0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 07 00   ��������������.�
E0: 00 00 82 24 06 46 49 4C 45 32 35 37 38 38 31 35   ���$.FILE2578815
F0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 05 00   ��������������.�

  Bytes: $00-1F: First directory entry
          00-01: Track/Sector location of next directory sector
             02: File type.
                 Bit 0-3: The actual filetype
                          000 (0) - DEL ($00)
                          001 (1) - SEQ ($81)
                          010 (2) - PRG ($82)
                          011 (3) - USR ($83)
                          100 (4) - REL ($84)
                          101 (5) - CBM ($85, partition or sub-directory)
                          Values 6-15 are illegal, but if used will produce
                          very strange results.
                 Bit   4: Not used
                 Bit   5: Used only during SAVE-@ replacement
                 Bit   6: Locked flag (Set produces ">" locked files)
                 Bit   7: Closed flag  (Not  set  produces  "*", or "splat"
                          files)
                 Typical values for this location are:
                   $00 - Scratched (deleted file entry)
                    80 - DEL
                    81 - SEQ
                    82 - PRG
                    83 - USR
                    84 - REL
                    85 - CBM
          03-04: Track/sector location of first sector of file or partition
          05-14: 16 character filename (in PETASCII, padded with $A0)
          15-16: Track/Sector location of first  SUPER  SIDE  SECTOR  block
                 (REL file only)
             17: REL file record length (REL file only)
          18-1D: Unused (except with GEOS disks)
          1C-1D: (Used during an @SAVE or @OPEN, holds the new t/s link)
          1E-1F: File or partition size in  sectors,  low/high  byte  order
                 ($1E+$1F*256). The  approx.  file  size  in  bytes  is  <=
                 #sectors * 254
          20-3F: Second dir entry. From now on the first two bytes of  each
                 entry in this  sector  should  be  $00/$00,  as  they  are
                 unused.
          40-5F: Third dir entry
          60-7F: Fourth dir entry
          80-9F: Fifth dir entry
          A0-BF: Sixth dir entry
          C0-DF: Seventh dir entry
          E0-FF: Eighth dir entry


*** Non-Standard & Long Directories

  Most Commdore floppy disk drives use a single dedicated  directory  track
where all filenames are stored. This limits the number of files stored on a
disk based on the number of sectors on the directory track. There are  some
disk images that contain more files than would normally  be  allowed.  This
requires extending  the  directory  off  the  default  directory  track  by
changing the last directory sector pointer to a new track,  allocating  the
new sectors in the BAM, and manually  placing  (or  moving  existing)  file
entries there. The directory of an extended disk can be read and the  files
that reside there can be loaded without problems on a real drive.  However,
this is still a very dangerous practice as writing to the extended  portion
of the directory will cause directory corruption in the non-extended  part.
Many of the floppy drives core ROM routines ignore the track value that the
directory is on and assume the default directory track for operations.

  To explain: assume that the directory has been extended from track 18  to
track 19/6 and that the directory is full except for a few slots  on  19/6.
When saving a new file, the drive DOS will find an empty file slot at  19/6
offset $40 and correctly write the filename and a  few  other  things  into
this slot. When the file is done being saved  the  final  file  information
will be written to 18/6 offset $40 instead of 19/6 causing  some  directory
corruption to the entry at 18/6. Also, the  BAM  entries  for  the  sectors
occupied by the new file will not be saved and the new file will be left as
a SPLAT (*) file.

  Attempts to validate the disk will result in those files residing off the
directory track to not be allocated in the BAM, and  could  also  send  the
drive into an endless loop. The default directory track is assumed for  all
sector reads when validating so if the directory goes  to  19/6,  then  the
validate code will read 18/6  instead.  If  18/6  is  part  of  the  normal
directory chain then the validate routine will loop endlessly.


*** BAM layout

  The BAM is located on 40/1 (for side 0, tracks 1-40) and 40/2  (for  side
1, tracks 41-80). Each entry takes up six bytes, one for the "free  sector"
count and five for the allocation bitmap.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 28 02 44 BB 47 42 C0 00 00 00 00 00 00 00 00 00   (.D�GB����������
10: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
20: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
30: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
40: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
50: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
60: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
70: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
80: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
90: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
A0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
B0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
C0: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
D0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
E0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
F0: FF FF FF FF 28 FF FF FF FF FF 24 F0 FF 2D FF FE   ����(�����$��-��

    Bytes:$00-01: Track/sector of next bam sector (40/2)
              02: Version # ('D')
              03: One's complement of version# ($BB)
           04-05: Disk ID bytes (same as 40/0 Disk ID)
              06: I/O byte
                   bit 7 set   - Verify on
                   bit 7 clear - Verify off
                   bit 6 set   - Check header CRC
                   bit 6 clear - Don't check header CRC
              07: Auto-boot-loader flag (see section at end of document)
           08-0F: Reserved for future (set to $00)
           10-15: BAM entry for track 1 (track 41, side 1)
           16-1B: BAM entry for track 2 (track 42, side 1)
            ...
           46-4B: BAM entry for track 10 (track 50, side 1)
            ...
           82-87: BAM entry for track 20 (track 60, side 1)
            ...
           BE-C3: BAM entry for track 30 (track 70, side 1)
            ...
           FA-FF: BAM entry for track 40 (track 80, side 1)

  The BAM entries require some explanation, so lets look at  the  track  40
entry at bytes $FA-FF ($24 $F0 $FF $2D $FF $FE). The first byte ($24, or 36
decimal) is the number of free sectors on that track. The next  five  bytes
represent the bitmap of which sectors are used/free. Since it is five bytes
(8 bits/byte) we have  40  bits  of  storage.  Since  this  format  has  40
sectors/track, the whole five bytes are used.

F0: .. .. .. .. .. .. .. .. .. .. 24 F0 FF 2D FF FE   ����(�����$��-��

  The last five bytes of any BAM entry must be viewed in binary to make any
sense. We will once again use track 40 as our reference:

     F0=11110000, FF=11111111, 2D=00101101, FF=11111111, FE=11111110

In order to make any sense from the binary notation, flip the bits around.

                      111111 11112222 22222233 33333333
   Sector  01234567 89012345 67890123 45678901 23456789
           -------------------------- -------- --------
           00001111 11111111 10110100 11111111 01111111

Note that if a bit is on (1), the sector is free. Therefore, track  40  has
sectors 0-3, 17, 20, 22, 23 and 32 used, all the rest are free.

The second BAM (for side 1) contains the entries for tracks 41-80.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 00 FF 44 BB 47 42 C0 00 00 00 00 00 00 00 00 00   (.D�GB����������
10: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
20: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
30: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
40: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
50: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
60: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
70: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
80: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
90: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
A0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
B0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
C0: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����
D0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   (�����(�����(���
E0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF   ��(�����(�����(�
F0: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF   ����(�����(�����

  It is laid out exactly as the side 0 BAM except for one  difference.  The
track/sector reference for the  next  sector  should  be  set  to  $00/$FF,
indicating there is no next sector.


---------------------------------------------------------------------------

*** REL files


  The REL filetype requires some extra explaining. It was designed to  make
access to data *anywhere* on the disk  very  fast.  Take  a  look  at  this
directory entry...

00: 00 FF 84 27 00 41 44 44 49 54 49 4F 4E 41 4C 20   ���'�ADDITIONAL�
10: 49 4E 46 4F A0 27 02 FE 00 00 00 00 00 00 D2 0B   INFO�'...������.

  The third byte ($84) indicates this entry is a  REL  file  and  that  the
three normally empty entries at offset $15, $16 and $17  are  now  used  as
they are explained above. It's  the  track/sector  chain  that  this  entry
points to, called the SUPER SIDE SECTOR, which is of interest here (in this
case, 39/2). The SUPER SIDE SECTOR is very different from the  D64  format.
If you check the D64 entry for a REL file and do the calculations, you will
find that the maximum file size of the REL file is 720 data  sectors.  With
the new SUPER SIDE SECTOR, you can  now  have  126  groups  of  these  SIDE
SECTORS chains,  allowing  for  file  sizes  up  to  (theoretically)  90720
sectors, or about 22.15 Megabytes.

Here is a dump of the beginning of the SUPER SIDE SECTOR...

00: 27 01 FE 27 01 15 09 03 0F 38 16 4A 1C 00 00 00   '.�'.....8.J.���
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������

  Bytes:$00-01: Track/sector of first side sector in group 0
            02: Always $FE
         03-04: Track/sector of first side sector in group 0 (again)
         ...
         FD-FE: Track/sector of first side sector in group 125
            FF: Unused (likely $00)


The side sector layout is the same as the D64/1571.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 12 0A 00 FE 15 09 12 0A 0F 0B 0C 0C 09 0D 06 0E
10: 15 07 15 08 15 0A 15 0B 15 0C 15 0D 15 0E 15 0F
20: 15 10 15 11 15 12 15 13 15 14 15 15 15 16 15 17
30: 15 18 15 19 15 1A 15 1B 15 1C 15 1D 15 1E 15 1F
40: 15 20 15 21 15 22 15 23 15 24 15 25 15 26 15 27
50: 14 00 14 01 14 02 14 03 14 04 14 05 14 06 14 07
60: 14 08 14 09 14 0A 14 0B 14 0C 14 0D 14 0E 14 0F
70: 14 10 14 11 14 12 14 13 14 14 14 15 14 16 14 17
80: 14 18 14 19 14 1A 14 1B 14 1C 14 1D 14 1E 14 1F
90: 14 20 14 21 14 22 14 23 14 24 14 25 14 26 14 27
A0: 13 00 13 01 13 02 13 03 13 04 13 05 13 06 13 07
B0: 13 08 13 09 13 0A 13 0B 13 0C 13 0D 13 0E 13 0F
C0: 13 10 13 11 13 12 13 13 13 14 13 15 13 16 13 17
D0: 13 18 13 19 13 1A 13 1B 13 1C 13 1D 13 1E 13 1F
E0: 13 20 13 21 13 22 13 23 13 24 13 25 13 26 13 27
F0: 12 00 12 01 12 02 12 03 12 04 12 05 12 06 12 07

  Bytes:   $00: Track location of next side-sector ($00 if last sector)
            01: Sector location of next side-sector
            02: Side-sector block number (first sector is $00, the next  is
                $01, then $02, etc)
            03: REL file RECORD size (from directory entry)
         04-0F: Track/sector locations of the six other side-sectors.  Note
                the first entry is this very sector we  have  listed  here.
                The next is the next t/s listed at  the  beginning  of  the
                sector. All of this information must be correct. If one  of
                these chains is $00/$00, then we have no more side sectors.
                Also, all of these (up to six) side sectors must  have  the
                same values in this range.
         10-FF: T/S chains of *each* sector of the data  portion.  When  we
                get a $00/$00, we are at the end of the file.

---------------------------------------------------------------------------

*** 1581 Partitions and Sub-directories

  At the beginning of this document it was stated that the  1581  can  hold
296 entries "at the root level". The 1581 also has the ability to partition
areas  of  the  disk.  Under  the  right  conditions   these   can   become
sub-directories,  acting  as  a  small  diskette,  complete  with  its  own
directory and BAM. When you are inside of a sub-directory, no  other  files
except those in that directory are visible, or can be affected.

  To the 1581, this file will show up as a "CBM" filetype in  a  directory.
All this does is tell the disk that a file, starting  at  X/Y  track/sector
and Z sectors large exists. Doing a validate will not harm these  files  as
they have a directory entry, and are fully allocated in the BAM.

  There are two main uses for partitions.  One  is  to  simply  allocate  a
section of the disk to be used for direct-access reads/writes, and lock  it
away  from  being  overwritten  after  a  VALIDATE.  The  second  is  as  a
sub-directory, basically a small "disk within a disk".

  In order to use a partition as a sub-directory, it  must  adhere  to  the
following four rules:

  1. If must start on sector 0
  2. It's size must be in multiples of 40 sectors
  3. It must be a minimum of 120 sectors long (3 tracks)
  4. If must not start on or cross  track  40,  which  limits  the  biggest
     directory to 1600 sectors (tracks 1-39).

This is a dump of a sub-directory entry:

00: 00 FF 85 29 00 50 41 52 54 49 54 49 4F 4E 20 31   ���)�PARTITION�1
10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 40 06   ��������������@.

  It is a partition starting on track 41/0, extends for 1600  sectors,  and
has been formatted as a  sub-directory.  Note  that  when  a  partition  is
created, the area being allocated is not touched in any way. If you want it
set up as a sub-directory, you must issue the FORMAT command to the 1581 to
create the central directory and BAM. Also note  that  from  the  directory
entry you can't tell whether it is a sub-directory or  not,  just  that  it
fits the sub-directory parameters.

  The BAM track for the sub-directory exists on  the  first  track  of  the
partition, and has the same layout as the disk BAM on track 40. The biggest
difference is the "disk name" is what what given  when  the  partition  was
formatted rather than what the actual disk name is. Also,  except  for  the
free sectors in the partition area, all other sectors in the  BAM  will  be
allocated.

  If the partition size doesn't match the above rules for a  sub-directory,
it will simply exist as a "protected" area of the disk, and can't be used a
sub-directory. Either way, it still shows up as a "CBM" type in a directory
listing. Below is a dump of a 10-sector partition starting  on  track  5/1,
which does not qualify as a sub-directory...

00: 00 00 85 05 01 53 4D 41 4C 4C 50 41 52 54 20 32   ���..SMALLPART�2
10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0A 00   ����������������

  The master BAM shows the entry for this partition on track 5...

00: 28 02 44 BB 43 44 C0 00 00 00 00 00 00 00 00 00   (.D�CD����������
10: 23 C1 FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF   #�����(�����(���
20: FF FF 28 FF FF FF FF FF 1E 01 F8 FF FF FF 28 FF   ��(�����..����(�
                            ^^^^^^^^^^^^^^^^^

  The breakdown of the BAM  shows  the  allocation  for  this  track,  with
sectors 1-10 allocated, as it should be.

  10000000 00011111 11111111 11111111 11111111
  ^          ^          ^          ^         ^
  0          10         20         30        39

  Partitions and sub-directories  share  one  very  important  trait.  When
created, the sub-directory entry simply has the starting  track/sector  and
the size of the partition in  sectors.  Partitions  are  created  linearly,
meaning if one starts on 30/1 and is of size 15 sectors,  then  the  sector
range from 1 through 15 on track 30 will be allocated. If a partition  size
crosses a track boundary, the allocation will continue on  the  next  track
starting on sector 0, and going up.

  The section allocated will *not* have a track/sector chain  like  a  file
would, but rather is dependant on the directory entry to keep it from being
overwritten. You can store whatever you want to in the allocated area.


---------------------------------------------------------------------------

*** AUTO-BOOT LOADER

  If byte $07 in the BAM is set, then when the drive is  reset  (and  other
circumstances) it will look for a USR file called "COPYRIGHT CBM 86".  This
file will then be loaded into the drive RAM and executed.

  The format for this auto-loader file is fairly basic. It  starts  with  a
two-byte load address, a size byte, program data, and  a  checksum  at  the
end.

    Bytes:      00-01: Load address, low/high format
                   02: Size of program (SZ) (smaller than 256 bytes)
         03-(03+SZ-1): Program data
                03+SZ: Checksum byte

---------------------------------------------------------------------------

*** Overall Good/Bad of D81 Files:

  Good
  ----
  * Most emulators support them
 
  * Supports *all* filenames, even those with $00's in them

  * Filenames padded with the standard $A0 character

  * Supports GEOS files

  * Supports REL files

  * Allows directory customization

  * Because it is a random-access  device,  it  supports  fast-loaders  and
    random sector access

  * Cluster slack-space loss is minimized since the file is a larger  fixed
    size

  * Has a label (description) field

  * With  the  inclusion  of  error  bytes,  you  have  support  for  basic
    copy-protection

  * Files on a disk can easily be re-written, as  long  as  there  is  free
    blocks



  Bad
  ---
  * The format doesn't contain *all* the info from the 1581 disk (no sector
    header info like  ID  bytes,  checksums).  This  renders  some  of  the
    original special-loaders and copy-protection useless.

  * You don't *really* know the file size of the  contained  C64  files  in
    bytes, only blocks

  * It can't store C64s FRZ files (due to FRZ files needing a special  flag
    that a D81 can't store)

  * Directory limited to 296 files maximum

  * It is not an expandable filesize, like LNX or T64, but the directory is
    large enough not to worry about this limitation

  * Unless most of the space on a D81 disk is used, you do end up with lost
    space

  * Cannot have loadable files with the same names

  * Has no recognizeable file signature (unlike most  other  formats).  The
    only reliable way to know if a file is a D81 is by its size

  * It is too easy for people to muck up the standard layout

  * It is much more difficult to support  fully,  as  you  really  need  to
    emulate the 1581 DOS (sector interleave, REL support, GEOS interleave)


*** Disk File Layout (D64, D71, D81)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Source: Joe Forster/STA (internal rev 0.10)

Introduction
------------

  This document describes how Commodore drives lay out  files  when  saving
them onto the disk. It does not describe how the Commodore disk or the  BAM
is laid out or how you  can  manage  it,  you  can  read  that  in  another
document. The description also covers  GEOS,  which  uses  its  own  layout
scheme for saving files onto disks. Note that Commodore 1541, 1571 and 1581
drives all use the same scheme, but with different parameters.

  The Pascal source below was verified against real disks written  by  real
drives and proved to lay out files exactly the same way as Commodore drives
and GEOS do. It has been translated into C, as well. These  algorithms  may
be too complicated for your particular needs  because  they  take  so  many
parameters into account. Feel free to strip off whatever you don't need.

  Please, note that,  while  the  algorithms  simulate  the  real  behavior
exactly, the reason for this behavior is not always  fully  known.  As  you
will find below, sometimes we can only assume  the  reason.  If  you  think
these assumptions are incorrect then, please, tell us. We'll be  more  than
happy to discuss and, possibly, include it.




Finding the first block
-----------------------

  Commodore drives, as most floppy drives,  have  a  relatively  slow  head
movement. To speed up data access, it's certainly a good idea  to  put  the
directory into the center of the disk so that, when moving  the  head  from
the directory area to the actual file  data  and  back,  head  movement  is
minimized. On Commodore disks, the directory is on the central track:  this
is track 18 on 1541 disks, track 18 and track 53 (the flip  side  of  track
18) on double-sided 1571 disks, and track 40 on 1581 disks.

  When trying to find a free sector for the first block of  the  file,  the
drive first searches on the track just "below" the  directory  track,  then
the track just "above" the directory track, then 2 below,  2  above,  etc.,
moving away from the directory track. This assures that the first block  of
the file will be as close to the directory track as possible.  Again,  this
minimizes head movement.

  When a track is found, that contains one or more free sectors,  then  the
drive simply grabs the first free  sector  on  that  track,  starting  with
sector zero and going upwards, and allocates it for the first block of  the
file.

  If there are no free sectors left then you get the  '72,DISK  FULL,00,00'
error message. If a track is found, whose "number of free sectors"  counter
in the BAM is not zero, but the sector  allocation  bitmap  shows  no  free
sectors then the BAM is damaged. It is highly recommended  that  you  check
the BAM prior to saving files onto the disk, and refuse to do  anything  if
you find such inconsistensies. The BAM should be repaired, for example with
a validate, first.




Finding the next block
----------------------

  There's another algorithm for finding successive sectors for the file. It
is executed each time whenever a new sector is needed to  hold  file  data.
The algorithm makes use of  an  interesting  parameter,  the  "interleave".
Because transferring data to  the  host  machine  is  so  slow,  the  drive
shouldn't lay out data of the same file sequentially onto  sectors  of  the
same track. If it wrote the first block of data onto sector zero  and  then
second block onto sector one etc. then, while it is sending data read  from
sector zero to the host machine, the disk would keep  spinning  and  sector
one would leave the read/write head. As soon as the data transmission ends,
the drive would try to read sector one, to get the next block of data,  and
it would find that it has to wait about half a revolution for sector one to
appear again under the read/write head. Therefore, data shouldn't  be  laid
out sequentially but, rather, there should be  "holes"  between  successive
blocks of the same file. Of course, this doesn't mean holes  with  no  data
inside. It only means that data is laid out e.g.  onto  each  even  sector:
sector zero, then sector two, four etc. Then  the  drive  will  have  time,
while sector one, three and five is under the read/write head, to send  the
contents of sector zero, two and four to the host machine. When the end  of
the track is reached, you start again with odd sectors - after all, a track
is an endless circle - and fill in the holes you made by using every second
sector only.

  The distance of successive blocks is what we call "interleave".  On  some
disks, physical sectors are laid out in a non-sequential manner,  that's  a
"hard" interleave. Commodore drives  do  lay  out  physical  sectors  in  a
sequential manner but they put data onto them in  a  non-sequential  order,
that's a "soft" interleave. In the example above,  we  were  using  a  soft
interleave of two, that is, the distance between two successive  blocks  of
the same file was two sectors.

  The optimal interleave for a disk highly depends on how fast data can  be
transmitted to  the  host  machine.  For  a  high  transmission  rate,  the
interleave can be smaller because not much time is needed to  transfer  the
contents of the current sector, therefore successive sectors may be  closer
to each other. For  a  low  transmission  rate,  such  as  the  default  of
Commodore drives, a higher interleave is needed. In particular, 1541 drives
are using an interleave of 10 sectors, 1571 drives use 6 sectors  and  1581
drives use 1 sector, by default. The reason for the  latter  is  that  1581
drives contain a track cache, they can read in a whole track  of  data  and
then transmit data right from the  memory  to  the  host  machine,  without
having to actually access the disk. In this case, there's no real need  for
an interleave, sectors may be laid out  in  a  sequential  manner  -  which
corresponds with  an  interleave  value  of  one  -  without  any  possible
performance penalty.

  So, when the drive finished writing the current block of a file and there
still are free sectors left on the current track, it tries to continue with
the sector that is an "interleave" number of sectors away from the  current
one. It adds the interleave to the current sector number. If  it  runs  off
the current track - the sector number becomes invalid - then  it  subtracts
the number of sectors on the track, which will correct the result.  If  the
corrected result is not sector zero then it subtracts one  more.  This  is,
most probably, some kind of an  empirical  optimization,  because  the  gap
between the last and first sector on a track is always a  bit  longer  than
the other gaps.

  If the sector, the drive arrived at this way, is free then it already has
the sector it needs. If it's used, however, then the drive keeps  searching
for free sectors, starting from this sector, at steps of one.  It  searches
towards the end of the track, then wraps back  to  sector  zero  and  moves
further upwards. As the BAM stated that there are still free sectors on the
current track, it shouldn't arrive back at the sector it started  from.  If
it does then the BAM is damaged.

  If the current track is already full then the drive moves one track  away
from the directory track but keeps the sector number used on  the  previous
track. If there are some free sectors on this  new  track  then  the  drive
tries to find a free sector, using the method  described  in  the  previous
paragraphs, including adding the interleave to the sector number first. The
reason for this, most probably, is that sectors of the same  sector  number
are at about the same angle on all tracks.  Therefore,  when  you  finished
writing sector zero on a track and move to an adjacent track  then  you'll,
probably, read sector one as  the  first  sector  that  arrives  under  the
read/write head on  that  track.  This  means,  you  can  keep  adding  the
interleave, as if you were still on the same track.

  If, while moving away from the directory track, the  algorithm  runs  off
the disk, it tries again on the other half of the disk. If it  stepped  off
track one downwards then it tries again  with  the  track  just  above  the
directory track, going upwards. If it stepped off the highest track upwards
then it tries again with the track just below the  directory  track,  going
downwards. Therefore, at least, two tries should be made:  on  the  current
half of the disk and the other half. For  some  unknown  reason,  Commodore
1541 drives do three tries, which the algorithm below follows. When jumping
to the other half of the disk, the sector number is zeroed. The reason  for
this, probably, is that moving the read/write head to such a great distance
takes away so much time that there's no telling which sector it  will  read
first, arriving at the destination track, so there's no point  keeping  the
previous sector number.

  An extra feature of the algorithms below is that you can also  save  file
data onto free sectors of the directory track. The directory track will  be
used only if all other parts of the disk are completely  full.  Apart  from
this, everything above applies to the directory track, as well.

  It's worth mentioning that this "finding the  next  block"  algorithm  is
used also for finding the next block for the directory, when extending  it.
The only difference is that, in this case, a lower interleave of 3  sectors
is used by 1541 and 1571 drives, by default, because no  data  transmission
to the host machine is involved while processing the directory  data.  1581
drives, as usual, use an interleave of 1 sector.



---------------------------------------------------------------------------


GEOS
----

  GEOS works quite differently from  the  original  drive  DOS.  It  starts
saving files on track one and goes upwards  until  it  fills  up  the  last
track. On its way, of course, it skips the directory tracks.  Actually,  it
uses the same algorithm for finding the first and the next  sectors  for  a
file and even for extending the directory, too.

  Because it has a built-in fast loader, it uses  an  interleave  different
from the original: 8 sectors for 1541 disks. As tests  show,  it  uses  the
original interleave of 6 sectors for 1571  disks  and  1  sector  for  1581
disks, perhaps, because these drives  are  fast  enough  anyway.  The  same
applies for extending the directory which is, again, handled  by  the  same
algorithm, probably, because directory data has to be  transferred  to  the
host machine as it is processed by the GEOS disk  driver  rather  than  the
drive itself.

  GEOS also introduces some kind of a "sector skewing".  Unlike  on  normal
Commodore disks, sectors of the same sector number but on different  tracks
are not at the same angle on the disk. As you  move  away  from  a  certain
track, sector zero  also  slides  away  in  one  direction.  The  distance,
measured by the difference in the sector number, of sectors  at  about  the
same angle on adjacent tracks is the "skew" value. Again, if  this  applies
to physical sectors than that's  a  "hard"  skew.  For  logical  sectors  -
successive blocks of the same file -, that's a "soft" skew. The skew  value
used by GEOS is  computed  by  a  relatively  complicated  formula:  "track
distance" * 2 + 4 + "interleave".

  When stepping onto a new track, GEOS tries to save the next block of file
data onto the sector whose sector number is equal  to  the  result  of  the
above formula. (Strangely enough, the result is not  added  to  the  sector
number but rather assigned to, so it might not  be  a  sector  skew,  after
all.) If this sector is already used then, similarly to the original  drive
DOS, GEOS goes through  the  track  sequentially,  at  steps  of  one,  and
searches for the first free sector after this one.



---------------------------------------------------------------------------


Pascal source
-------------

{=== Start of Pascal source ==============================================}

{--- Global variables ---}

var
{When True, this is a GEOS-formatted disk, therefore, files have to be
  saved the GEOS way onto it}
  GEOSFormat,
{When True, free sectors on the directory track are also allowed to hold
  file data if the disk otherwise gets full}
  CopyToDirTrack: Boolean;
{Track number of current block of file}
  Track,
{Sector number of current block of file}
  Sector,
{Track number of first track (may be above one for subdirectories on 1581
  disks)}
  FirstTrack,
{Track number of last track plus one (may be below the physical end of
  disk for subdirectories on 1581 disks)}
  LastTrack,
{Track number of physically last track plus one}
  MaxTrack,
{Track number of directory track}
  DirTrack,
{Track number of secondary directory track (for 1571 disks); 255 (a
  non-existent track), if not available}
  DirTrack2,
{Soft interleave}
  Interleave: Byte;

{--- Support routines ---}

{Determine if there's, at least, one free sector on a track
  Input : Track: the track to check
  Output: when True, there's, at least, one free sector on the track}
function IsTrackFree(Track: Byte): Boolean;

{Determine if a sector is free
  Input : Track: the track number of sector to check
          Sector: the sector number of sector to check
  Output: when True, the sector is free; otherwise used}
function IsSectorFree(Track, Sector: Byte): Boolean;

{Determine the number of sectors (or the highest valid sector number
  plus one) for a track
  Input : Track: track number
  Output: the number of sectors on the track}
function SectorNum(Track: Byte): Byte;

{--- Implementation of algorithms ---}

{Prototype for NextCopyBlock}
function NextCopyBlock: Boolean;

{Find a sector for the first block of the file, using variables Track and
  Sector
  Output: when True, a sector was found; otherwise no more sectors left}
function FirstCopyBlock: Boolean;
var
  Found: Boolean;
  MaxSector,
  Distance: Byte;
begin
{We found no free sector yet}
  Found := False;
{If this is a GEOS-formatted disk then use the other routine, from track
  one upwards}
  if GEOSFormat then
  begin
    Track := 1;
    Sector := 0;
    Found := NextCopyBlock;
  end
  else
  begin
{If it's a normal disk then we start off with tracks just besides the
  directory track}
    Distance := 1;
{Search until we find a free block or moved too far from the directory
  track}
    while not Found and (Distance < 128) do
    begin
{Check the track below the directory track first}
      Track := DirTrack - Distance;
{If the track is inside the valid range then check if there's a free
  sector on it}
      if (Track >= FirstTrack) and (Track < LastTrack) then
        Found := IsTrackFree(Track);
      if not Found then
      begin
{If no luck then check the track above the directory track}
        Track := DirTrack + Distance;
{If the track is inside the valid range then check if there's a free
  sector on it}
        if Track < LastTrack then Found := IsTrackFree(Track);
      end;
{If no luck either then move one track away from the directory track and
  try again}
      if not Found then Inc(Distance);
    end;
{If the whole disk is full and we're allowed to use the directory track
  for file data then try there, too}
    if not Found and CopyToDirTrack then
    begin
      Track := DirTrack;
      Found := IsTrackFree(Track);
    end;
{If we finally found a track with, at least, one free sector then search
  for a free sector in it}
    if Found then
    begin
{Determine how many sectors there are on that track}
      MaxSector := SectorNum(Track);
{Start off with sector zero}
      Sector := 0;
      repeat
{Check if the current sector is free}
        Found := IsSectorFree(Track, Sector);
{If it isn't then go on to the next sector}
        if not Found then Inc(Sector);
{Repeat the check until we find a free sector or run off the track}
      until Found or (Sector >= MaxSector);
    end;
  end;
{Return the search result}
  FirstCopyBlock := Found;
end;

{-------------------------------------------------------------------------}

{Find a sector for the next block of the file, using variables Track and
  Sector
  Output: when True, a sector was found; otherwise no more sectors left}
function NextCopyBlock: Boolean;
var
  Found: Boolean;
  Tries,
  MaxSector,
  CurSector,
  CurTrack: Byte;
begin
  if (Track = 0) or (Track >= MaxTrack) then
  begin
{If we somehow already ran off the disk then there are no more free
  sectors left}
    NextCopyBlock := False;
  end
  else
  begin
{Set the number of tries to three}
    Tries := 3;
{We found no free sector yet}
    Found := False;
{Remember the current track number}
    CurTrack := Track;
{Keep trying until we find a free sector or run out of tries}
    while not Found and (Tries > 0) do
    begin
{Get the number of sectors on the current track}
      MaxSector := SectorNum(Track);
{If there's, at least, one free sector on the track then get searching}
      if IsTrackFree(Track) then
      begin
{If this is a non-GEOS disk or we're still on the same track of a
  GEOS-formatted disk then...}
        if (Track = CurTrack) or not GEOSFormat then
        begin
{Move away an "interleave" number of sectors}
          Inc(Sector, Interleave);
{Empirical GEOS optimization, get one sector backwards if over track 25}
          if GEOSFormat and (Track >= 25) then Dec(Sector);
        end
        else
        begin
{For a different track of a GEOS-formatted disk, use sector skew}
          Sector := (Track - CurTrack) shl 1 + 4 + Interleave;
        end;
{If we ran off the track then correct the result}
        while Sector >= MaxSector do
        begin
{Subtract the number of sectors on the track}
          Dec(Sector, MaxSector);
{Empirical optimization, get one sector backwards if beyond sector zero}
          if (Sector > 0) and not GEOSFormat then Dec(Sector);
        end;
{Remember the sector we finally arrived at}
        CurSector := Sector;
        repeat
{Check if the current sector is free}
          Found := IsSectorFree(Track, Sector);
{If it isn't then go to the next sector}
          if not Found then Inc(Sector);
{If we ran off the track then wrap around to sector zero}
          if Sector >= MaxSector then Sector := 0;
{Keep searching until we find a free sector or arrive back at the
  original sector}
        until Found or (Sector = CurSector);
      end
      else
      begin
{If the current track is used up completely then...}
        if GEOSFormat then
        begin
{Move one track upwards on a GEOS-formatted disk}
          Inc(Track);
{Skip the directory tracks on the way}
          if (Track = DirTrack) or (Track = DirTrack2) then Inc(Track);
{If we ran off the disk then there are no more tries}
          if Track = LastTrack then Tries := 0;
        end
        else
        begin
{If we already tried the directory track then there are no more tries}
          if Track = DirTrack then
          begin
            Tries := 0;
          end
          else
          begin
            if Track < DirTrack then
            begin
{If we're below the directory track then move one track downwards}
              Dec(Track);
              if Track < FirstTrack then
              begin
{If we ran off the disk then step back to the track just above the
  directory track and zero the sector number}
                Track := DirTrack + 1;
                Sector := 0;
{If there are no tracks available above the directory track then there
  are no tries left; otherwise just decrease the number of tries}
                if Track < LastTrack then Dec(Tries) else Tries := 0;
              end;
            end
            else
            begin
{If we're above the directory track then move one track upwards}
              Inc(Track);
{Skip the secondary directory track on the way}
              if Track = DirTrack2 then Inc(Track);
              if Track = LastTrack then
              begin
{If we ran off the disk then step back to the track just below the
  directory track and zero the sector number}
                Track := DirTrack - 1;
                Sector := 0;
{If there are no tracks available below the directory track then there
  are no tries left; otherwise just decrease the number of tries}
                if Track >= FirstTrack then Dec(Tries) else Tries := 0;
              end;
            end;
          end;
        end;
      end;
      if not Found and (Tries = 0) and (Track <> DirTrack) and
        CopyToDirTrack then
      begin
{If we haven't found any free sector, ran out of tries and haven't tried
  the directory track yet, although it's declared as available for file
  data, then give the directory track an extra try}
        Track := DirTrack;
        Inc(Tries);
      end;
    end;
{Return the search result}
    NextCopyBlock := Found;
  end;
end;

{=== End of Pascal source ================================================}



---------------------------------------------------------------------------


C source
--------

/* === Start of C source =============================================== */

/* Type definitions */

#define byte unsigned char
#define boolean unsigned char
#define true (0 == 0)
#define false (0 == 1)

/* --- Global variables --- */

boolean
/* When true, this is a GEOS-formatted disk, therefore, files have to be
   saved the GEOS way onto it */
  GEOSFormat,
/* When true, free sectors on the directory track are also allowed to hold
   file data if the disk otherwise gets full */
  CopyToDirTrack;
byte
/* Track number of current block of file */
  Track,
/* Sector number of current block of file */
  Sector,
/* Track number of first track (may be above one for subdirectories on 1581
   disks) */
  FirstTrack,
/* Track number of last track plus one (may be below the physical end of
   disk for subdirectories on 1581 disks) */
  LastTrack,
/* Track number of physically last track plus one */
  MaxTrack,
/* Track number of directory track */
  DirTrack,
/* Track number of secondary directory track (for 1571 disks); 255 (a
   non-existent track), if not available */
  DirTrack2,
/* Soft interleave */
  Interleave;

/* --- Support routines --- */

/* Determine if there's, at least, one free sector on a track
   Input : Track: the track to check
   Output: when true, there's, at least, one free sector on the track */
boolean IsTrackFree(byte Track);

/* Determine if a sector is free
   Input : Track: the track number of sector to check
           Sector: the sector number of sector to check
  Output: when true, the sector is free; otherwise used */
boolean IsSectorFree(byte Track, byte Sector);

/* Determine the number of sectors (or the highest valid sector number
   plus one) for a track
   Input : Track: track number
   Output: the number of sectors on the track */
byte SectorNum(byte Track);

/* --- Implementation of algorithms --- */

/* Prototype for NextCopyBlock() */
boolean NextCopyBlock();

/* Find a sector for the first block of the file, using variables Track and
   Sector
   Output: when true, a sector was found; otherwise no more sectors left */
boolean FirstCopyBlock()
{
  boolean Found;
  byte MaxSector,
    Distance;
/* We found no free sector yet */
  Found = false;
/* If this is a GEOS-formatted disk then use the other routine, from track
   one upwards */
  if (GEOSFormat)
  {
    Track = 1;
    Sector = 0;
    Found = NextCopyBlock();
  }
  else
  {
/* If it's a normal disk then we start off with tracks just besides the
   directory track */
    Distance = 1;
/* Search until we find a free block or moved too far from the directory
   track */
    while (!Found && (Distance < 128))
    {
/* Check the track below the directory track first */
      Track = DirTrack - Distance;
/* If the track is inside the valid range then check if there's a free
   sector on it */
      if ((Track >= FirstTrack) && (Track < LastTrack))
        Found = IsTrackFree(Track);
      if (!Found)
      {
/* If no luck then check the track above the directory track */
        Track = DirTrack + Distance;
/* If the track is inside the valid range then check if there's a free
   sector on it */
        if (Track < LastTrack) Found = IsTrackFree(Track);
      }
/* If no luck either then move one track away from the directory track and
  try again */
      if (!Found) Distance++;
    }
/* If the whole disk is full and we're allowed to use the directory track
   for file data then try there, too */
    if (!Found && CopyToDirTrack)
    {
      Track = DirTrack;
      Found = IsTrackFree(Track);
    }
/* If we finally found a track with, at least, one free sector then search
   for a free sector in it */
    if (Found)
    {
/* Determine how many sectors there are on that track */
      MaxSector = SectorNum(Track);
/* Start off with sector zero */
      Sector = 0;
      do
      {
/* Check if the current sector is free */
        Found = IsSectorFree(Track, Sector);
/* If it isn't then go on to the next sector */
        if (!Found) Sector++;
/* Repeat the check until we find a free sector or run off the track */
      } while (!Found && (Sector < MaxSector));
    }
  }
/* Return the search result */
  return(Found);
}

/* --------------------------------------------------------------------- */

/* Find a sector for the next block of the file, using variables Track and
   Sector
   Output: when true, a sector was found; otherwise no more sectors left */
boolean NextCopyBlock()
{
  boolean Found;
  byte Tries,
    MaxSector,
    CurSector,
    CurTrack;
  if ((Track == 0) || (Track >= MaxTrack))
  {
/* If we somehow already ran off the disk then there are no more free
   sectors left */
    return(false);
  }
  else
  {
/* Set the number of tries to three */
    Tries = 3;
/* We found no free sector yet */
    Found = false;
/* Remember the current track number */
    CurTrack = Track;
/* Keep trying until we find a free sector or run out of tries */
    while (!Found && (Tries > 0))
    {
/* Get the number of sectors on the current track */
      MaxSector = SectorNum(Track);
/* If there's, at least, one free sector on the track then get searching */
      if (IsTrackFree(Track))
      {
/* If this is a non-GEOS disk or we're still on the same track of a
  GEOS-formatted disk then... */
        if ((Track == CurTrack) || !GEOSFormat)
        {
/* Move away an "interleave" number of sectors */
          Sector += Interleave;
/* Empirical GEOS optimization, get one sector backwards if over track 25 */
          if (GEOSFormat && (Track >= 25)) Sector--;
        }
        else
        {
/* For a different track of a GEOS-formatted disk, use sector skew */
          Sector = ((Track - CurTrack) << 1) + 4 + Interleave;
        }
/* If we ran off the track then correct the result */
        while (Sector >= MaxSector)
        {
/* Subtract the number of sectors on the track */
          Sector -= MaxSector;
/* Empirical optimization, get one sector backwards if beyond sector zero */
          if ((Sector > 0) && !GEOSFormat) Sector--;
        }
/* Remember the sector we finally arrived at */
        CurSector = Sector;
        do
        {
/* Check if the current sector is free */
          Found = IsSectorFree(Track, Sector);
/* If it isn't then go to the next sector */
          if (!Found) Sector++;
/* If we ran off the track then wrap around to sector zero */
          if (Sector >= MaxSector) Sector = 0;
/* Keep searching until we find a free sector or arrive back at the
  original sector */
        } while (!Found && (Sector != CurSector));
      }
      else
      {
/* If the current track is used up completely then... */
        if (GEOSFormat)
        {
/* Move one track upwards on a GEOS-formatted disk */
          Track++;
/* Skip the directory tracks on the way */
          if ((Track == DirTrack) || (Track == DirTrack2)) Track++;
/* If we ran off the disk then there are no more tries */
          if (Track == LastTrack) Tries = 0;
        }
        else
        {
/* If we already tried the directory track then there are no more tries */
          if (Track == DirTrack)
          {
            Tries = 0;
          }
          else
          {
            if (Track < DirTrack)
            {
/* If we're below the directory track then move one track downwards */
              Track--;
              if (Track < FirstTrack)
              {
/* If we ran off the disk then step back to the track just above the
  directory track and zero the sector number */
                Track = DirTrack + 1;
                Sector = 0;
/* If there are no tracks available above the directory track then there
  are no tries left; otherwise just decrease the number of tries */
                if (Track < LastTrack) Tries--; else Tries = 0;
              }
            }
            else
            {
/* If we're above the directory track then move one track upwards */
              Track++;
/* Skip the secondary directory track on the way */
              if (Track == DirTrack2) Track++;
              if (Track == LastTrack)
              {
/* If we ran off the disk then step back to the track just below the
  directory track and zero the sector number */
                Track = DirTrack - 1;
                Sector = 0;
/* If there are no tracks available below the directory track then there
  are no tries left; otherwise just decrease the number of tries */
                if (Track >= FirstTrack) Tries--; else Tries = 0;
              }
            }
          }
        }
      }
      if (!Found && (Tries == 0) && (Track != DirTrack) && CopyToDirTrack)
      {
/* If we haven't found any free sector, ran out of tries and haven't tried
  the directory track yet, although it's declared as available for file
  data, then give the directory track an extra try */
        Track = DirTrack;
        Tries++;
      }
    }
/* Return the search result */
    return(Found);
  }
}

/* === End of C source ================================================= */

History:
  2000-05-05    0.01    Initial internal release
  2000-05-08    0.02    New: Translated the Pascal source to C
                        New: Separated text into numbered sections
                        Mod: Changed wording to make it more understandable
  2000-06-29    0.03    Fix: Fixed a couple of typos
  2000-07-28    0.04    Mod: Changed some wording again
  2000-11-05    0.05    Fix: Fixed some syntactical errors in the C source
  2001-02-22    0.10    Fix: Fixed some typos
                        Fix: Bytes, booleans are unsigned chars in C source


*** F64 (a companion file to certain D64's)
*** Document revision: 1.6
*** Last updated: March 19, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Christian Link,
                          Joe Forster/STA

  Created by a program called FCOPY-PC, written by M. Edzes  in  the  early
1990's and based on a hack of  the  1541  copy  program  called  FCOPY  III
written by Thomas Templemann, these files contain  some  extra  information
about the associated D64 files like the low-level disk ID, sector checksum,
valid sector flag and sector header ID. These files are very rare, and  are
only found on a CD called "C64 CD 96",  also  known  as  the  "Unicorn"  CD
available from the Whiz-zards group.

  Some of what you are about to read is pure conjecture on the part of  the
author to explain what these files are. Some of the  explanation  regarding
this file description comes from documentation provided by Joe Forster/STA,
and much of it  comes  from  the  experiments  that  the  author  of  these
documents has conducted.

  They all appear to be the same size, 2051 bytes, and seem to  start  with
the DISK ID from  the  D64  image.  The  F64  definition  only  encompasses
standard 35-track disk images.  No  consideration  was  made  for  40-track
images.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 30 34 .. .. .. .. .. .. .. .. .. .. .. .. .. ..   04..............

  Here the DISK ID is "04", and is likely obtained from the  sector  header
ID for track 18/0 (not the one visible on the BAM sector).

  Once we take into account the first two bytes, this leaves the  remaining
2049 bytes. Dividing this number  by  683  (the  number  of  sectors  in  a
standard 35 track D64 image) leaves us a grouping of 3  bytes  per  sector.
Below is a dump of the first few bytes  of  the  F64  files,  and  we  will
examine a few of the 3-byte descriptions.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: .. .. 2D 07 01 2B 07 8D 2B 07 47 2B 07 AE 2B 07   ..-��+��+�G+��+�
0010: 80 2B 07 C3 2B 07 1C 2B 07 4E 2B 07 EC 2B 07 47   �+��+��+�N+��+�G
0020: 2B 07 FE 2B 07 5F 2B 07 69 2B 07 F3 2B 07 90 2B   +��+�_+�i+��+��+
0030: 07 22 2B 07 4D 2D 07 01 2D 07 01 2D 07 01 2D 07   �"+�M-��-��-��-�

  The first sector has a description of "2D 07 01".

  Byte: 00 - "2D". This is the sector status code, representing whether the
             sector is ok, empty, or contains an error. This value  can  be
             one  of  the  following  characters  (excluding  the   quotes)
             "+-?HLICFSP". The number in brackets following the "error  xx"
             is the value used for a D64 error block.

             '+' (0x2B) : The sector is ok (D64 code 1)

             '-' (0x2D) : The sector is ok  (D64  code  1),  but  is  empty
                          (contains the $xx $01 $01... format pattern)

             '?' (0x3F) : The sector cannot be found. No evidence  that  it
                          exists at all. Convert this to 'H' error 20  (D64
                          code 2)

             'H' (0x48) : Error 20 (D64 code 2). No header ID can be  found
                          for the sector.

             'L' (0x4C) : Error 21 (D64 code 3). There is no SYNC  mark  on
                          the track.

             'I' (0x49) : Error 22 (D64 code 4). The data  descriptor  byte
                          (byte $01) has an  incorrect  value.  This  error
                          will also come with a invalid value for byte $01.

             'C' (0x43) : Error 23 (D64 code 5). The data block checksum is
                          wrong.  This  error  will  also  come   with   an
                          incorrect value for byte $02.

             'F' (0x46) : Means a "killer track" (whole track  filled  with
                          SYNC marks). Only one sample disk has this  error
                          on it.

             'H' (0x48) : Error 27 (D64 code 9). The sector header checksum
                          is wrong. Note that 'H' also represents Error 20.

             'S' (0x53) : Unknown. No sample files  exist  and  the  source
                          code doesn't  explain  it.  Possibly  a  "verify"
                          error, which isn't useful here.

             'P' (0x50) : Unknown. No sample files exist,  and  the  source
                          code  doesn't  explain   it.   Possibly   another
                          "verify" error, which isn't useful here.

        01 - "07". This is the "data descriptor byte" meaning the sector is
             OK, and exists. If it was a value other than $07, we  have  an
             error 22 ("data block not found").

        02 - "01". This is the data block checksum for the  sector.  It  is
             arrived at by XOR'ing all 256 data bytes, from position 00  to
             position FF.

  The second sector has a description of "2B 07 8D". From the above layout,
this means the sector data is ok, the data header is ok ("07"), and  has  a
checksum of "8D" (calculated and verified from the D64).

  One aspect that is unknown is the nature of the sector data when no  data
is sent. Only three codes send valid sector data ('+', 'C'  and  'I').  The
rest send an "empty" sector (filled with $01). However, the first  byte  is
not always $4B as it would be with a standard 1541 format. I've  seen  $01,
$41 (A) and $4B (K). If they represent something, I don't know.

  The two bytes following the F64 code should  be  incorporated  back  into
sector when an attempt is made to convert an F64/D64 image to  a  GCR-based
image (G64, ZipCode Sixpack). However, not all is understood about  how  to
actually do that because they have not been fully decoded yet. The 'I'  and
'C' codes are easy as the ID and checksum values can be used  to  construct
the data portion. However, constructing the header  (for  error  code  'H')
from the two bytes is more difficult as they always seem to be ID  $07  and
checksum $01.

  It is important to note that error 29 cannot be represented by  F64,  and
this is a serious limitation.  There  is  no  way  to  do  so  because  the
individual sector ID's are not stored in the F64 file. Not  only  that  but
the original program FCOPY III that FCOPY-PC is  based  on  doesn't  detect
them either. FCOPY III simply reads the header, if possible, and copies  it
to a destination disk. No checking of the header  ID's  was  done  (because
track 18/0 is not read prior to copying the disk). Error 29 is  actually  a
valid header since there is both a header ID and a valid checksum.

  Also important is the dual nature of the 'H' header error code  for  both
error 20 and 27. In tests that were conducted using both single-sector  and
full-track errors of 20 and  27,  it  is  somewhat  possible  to  tell  the
difference on full-track errors only. Full track error 20  always  puts  an
'H'  code  on  sector  0,  and  '?'  codes  for  the  rest  of  the  track.
Single-sector error 20's are always an 'H'.  Full-track  error  27s  always
have the 'H' code _not_ on sector 0, and the rest of the track filled  with
'?' codes. This is by no means a definitive way to  tell  them  apart,  but
simply based on observation.

-----

  Below are the  notes  that  I  took  regarding  the  error  codes  as  my
investigation proceeded. It might prove to be an interesting read.



  According to the FCOPY source code, these errors have valid  sector  data
sent:

  + : Sector is OK (no errors) and read intact. It doesn't  have  to  match
      the BAM entry and it sometimes exists when the sector is filled  with
      0x01, appearing to be empty.

  C : Error 23 "Bad Data Checksum". Always with a  ID  7  and  a  bad  data
      checksum value. Use the data ID and the checksum when constructing  a
      sector destined for GCR,

  I : Error 22 "Data ID not found". Both the ID and checksum values can  be
      anything and the sector doesn't always seem to have any  useful  data
      in it. Source code says "header chksum" bad.

  According to the source code, these errors have no valid sector data sent
(sends an empty sector, xx 01 01 01...):

  - : Sector has no data in it (xx 01 01) but it doesn't  always  mean  the
      sector is not used and it doesn't have to match the BAM. You  do  not
      have to use the values in the ID  and  checksum  bytes  as  they  are
      valid.

  H : Error 20 "Header ID not found" &  Error  27  "Bad  Header  Checksum".
      Always with an ID 7 and a checksum of  1.  Source  simply  says  "bad
      header". Didn't find the 0x52 header ID  or  because  there's  a  bad
      checksum the contents of the header  are  unreliable  and  discarded.
      Error 27 covers the entire track, but  error  20  can  exist  on  one
      sector. When an entire track of error 20 occurs, the 'H' error is  on
      the first sector. When an entire track of 27 occurs, 'H' is somewhere
      else (typically sector 3-4)

  L : Error 21 "No SYNC mark found". Always on sector 0,  and  preceeds  an
      entire track of '?'. Is with ID 7 and checksum 1)

  ? : No sector header/data could be read,  no  evidence  that  the  sector
      existed. Doesn't have to fill a track. Is typically  with  ID  7  and
      checksum 1. Recommend to change this to an error 20, except when with
      an 'L' or 'F' code.

  F : Always on sector 0 and preceeds an entire track of  '?'.  Looks  very
      similar to L (Disk1932 from the CD 64CD96 is the only sample  of  'F'
      errors). This could be a 'killer track'

  S : Haven't seen it yet. Source only refers to it. Might  be  a  "verify"
      error

  P : Haven't seen it yet. Source only refers to it. Might  be  a  "verify"
      error


*** G64 (raw GCR binary representation of a 1541 diskette)
*** Document revision: 1.9
*** Last updated: Feb 19, 2008
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Markus Brenner,
                          Immers/Neufeld "Inside Commodore DOS",
                          Wolfgang Moser

  This format was defined in 1998 as a cooperative effort  between  several
emulator people,  mainly  Per  Hakan  Sundell  (author  of  the  CCS64  C64
emulator),  Andreas  Boose  (of  the  VICE  CBM  emulator  team)  and   Joe
Forster/STA  (the  author  of  Star  Commander).  It  was  the  first  real
cooperative attempt to create a format for  the  emulator  community  which
removed almost all of the drawbacks of the other  existing  image  formats,
primarily D64. The G64 format is not specifically  designed  to  hold  only
1541 images, but they are presently the only G64 images  in  existance  and
why this document only refers to the 1541 and D64's.

  The intention behind G64 is not to replace the widely used D64 format, as
D64 works fine with the vast majority of disks in existence. It is intended
for those small percentage of programs which demand to work with  the  1541
drive in a non-standard way, such as reading or writing data  in  a  custom
format. The best example is with speeder software such as Action  Cartridge
in "warp save" mode or Vorpal and V-MAX which write  track/sector  data  in
another format other than  standard  GCR.  The  other  obvious  example  is
copy-protected software which looks for some specific data on a track, like
the disk ID, which is not stored in a standard D64 image.

  One protection method that G64 has trouble emulating  is  data  alignment
between tracks. Some  protection  methods  rely  on  data  being  in  exact
positions when the head is stepped from one track to another.  Imagine  two
concentric circles representing the data tracks, with a drive head  reading
data from one track, stepping over to the other track and expecting to find
some specific data where it is now. Unless you can read track data  from  a
1541 so it is aligned with the  previous  track,  write  it  into  the  G64
appropriately, and also read the resulting G64 data with this alignment  in
mind, the protection check will likely fail. Other methods like  weak  bits
are also hard to emulate.

  G64 has a deceptively simply layout for what it is capable of  doing.  We
have a signature, version byte, some predefined size values, and  a  series
of offsets to the track data and speed zones. It is what's contained in the
track data areas and speed zones which is  really  at  the  heart  of  this
format.

  Each track data area is simply the raw stream of GCR data, just what  the
read head would see when a diskette is rotating past it. How the data  gets
interpreted is up to the program trying to access  the  disk.  Because  the
data is stored in such a low-level manner, just about anything can be done.
Most tracks will be in the standard format with  with  SYNC  markers,  GAP,
header, data blocks and checksums. The arrangement of the data when  it  is
in a standard GCR sector layout is covered at the end of this document.  It
is the tracks that don't follow the standard which are the reason for G64's
existance and the hardest to decode.

  Below is a dump of the  header,  broken  down  into  its  various  parts.
Following that is a breakdown of the track offset  and  speed  zone  offset
areas, as they demand much more explanation.


Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
----  -----------------------------------------------   ----------------
0000: 47 43 52 2D 31 35 34 31 00 54 F8 1E .. .. .. ..   GCR-1541�T��....

  Bytes: $0000-0007: File signature "GCR-1541"
               0008: G64 version (presently only $00 defined)
               0009: Number of tracks in image (usually $54, decimal 84)
          000A-000B: Maximum track size in bytes in LO/HI format

  Now, why are there 84 tracks defined when a normal D64 disk only  has  35
tracks? By definition, an image of a 1541 must include all the tracks  that
a real 1541 can access, which is at most 42 tracks and 42 half tracks. Even
though using more than 35 tracks is not typical, it was important to define
this format from the start with what the 1541 is capable of doing, and  not
just what it typically does. Some 1541 drives  may  have  problems  reading
past track 40, and pushing  the  head  past  track  42  might  be  somewhat
hazardous to the health of the drive as the head could get stuck.

  The typical value seen for the maximum track size is 7928.  This  is  the
value used for 1541 images which use standard GCR encoding. This  value  is
determined by the fastest write speed possible (speed zone 0), coupled with
the average rotation speed of the  disk  (300  rpm),  and  assuming  normal
Commodore GCR data formatting. After some math, the  answer  that  actually
comes up is 7692 bytes. Allowing for a slower disk rotation of -3%, , which
would allow more data to be written, and  some  rounding,  7928  bytes  per
track was arrived at.

  Even though it might appear so, it is very important to  know  that  this
maximum track size value is not a fixed or  hard-coded  value.  This  value
depends on the what the original  disk  was  and  the  GCR  encoding  used.
Non-1541 images such as SFD1001 or 8050 will result  in  different,  likely
larger, track sizes. Also, disks with non-standard GCR encoding like  those
using V-MAX can result in tracks exceeding 8000 bytes.

  Since it is a flexible format in both track count and  track  byte  size,
file sizes can vary greatly. However, given a few constants like 42  tracks
with no halftracks, a consistent track size of  7928  bytes  and  no  speed
offset entries, the typical file size will be 333744 bytes.

  In my investigation using MNIB (a utility by Markus Brenner  that  allows
you to nibble a 1541 diskette to  the  PC  in  G64  format)  on  a  cleanly
formatted 1541 disk (using the built-in 1541 format  command),  I  saw  the
following numbers, compared with the defaults that MNIB uses:

                Track Range  Avg Size  MNIB
                             (bytes)   Size
                -----------  --------  ----
                   1-17       ~7720    7692
                  18-24       ~7165    7142
                  25-30       ~6690    6666
                  31-         ~6270    6250

  Note that  the  first  size  number  (7720)  is  larger  than  previously
mentioned track size of 7692. Why? Likely the drive that I used  to  create
and nibble the clean disk was rotating a little bit  slower  than  300  RPM
(~299 RPM), so more data than normal was stored on each track. I calculated
the percentage difference between my numbers and the established  benchmark
of 7692, multiplied all my numbers by  this  factor,  and  arrived  at  the
following chart:

                Track Range   Size    MNIB
                             (bytes)  Size
                -----------  -------  ----
                   1-17       7692    7692
                  18-24       7139    7142
                  25-30       6666    6666
                  31-         6247    6250

  See how close the real numbers come to what MNIB uses?  I  can  attribute
the differences of a few bytes to  my  own  rounding  errors.  Therefore  I
conclude that the numbers MNIB uses can be taken as the standard  that  all
1541-compatible G64 tracks should be created with.

  All of the  above  calculations  are  shown  here  to  establish  a  safe
benchmark to create G64 images in the event that someday we can  copy  them
back to a real 1541 disk. If the G64 track size was  too  large,  it  might
happen that the track cannot be written back out. By using the  above  MNIB
track size numbers, this problem should be alleviated.

  Below is a dump of the first section of a G64 file, showing  the  offsets
to the data portion for each track and half-track entry.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: .. .. .. .. .. .. .. .. .. .. .. .. AC 02 00 00   ............����
0010: 00 00 00 00 A6 21 00 00 00 00 00 00 A0 40 00 00   �����!�������@��
0020: 00 00 00 00 9A 5F 00 00 00 00 00 00 94 7E 00 00   �����_�������~��
0030: 00 00 00 00 8E 9D 00 00 00 00 00 00 88 BC 00 00   ����������������
0040: 00 00 00 00 82 DB 00 00 00 00 00 00 7C FA 00 00   ������������|���
0050: 00 00 00 00 76 19 01 00 00 00 00 00 70 38 01 00   ����v�������p8��
0060: 00 00 00 00 6A 57 01 00 00 00 00 00 64 76 01 00   ����jW������dv��
0070: 00 00 00 00 5E 95 01 00 00 00 00 00 58 B4 01 00   ����^�������X���
0080: 00 00 00 00 52 D3 01 00 00 00 00 00 4C F2 01 00   ����R�������L���
0090: 00 00 00 00 46 11 02 00 00 00 00 00 40 30 02 00   ����F�������@0��
00A0: 00 00 00 00 3A 4F 02 00 00 00 00 00 34 6E 02 00   ����:O������4n��
00B0: 00 00 00 00 2E 8D 02 00 00 00 00 00 28 AC 02 00   ����.�������(���
00C0: 00 00 00 00 22 CB 02 00 00 00 00 00 1C EA 02 00   ����"�����������
00D0: 00 00 00 00 16 09 03 00 00 00 00 00 10 28 03 00   �������������(��
00E0: 00 00 00 00 0A 47 03 00 00 00 00 00 04 66 03 00   �����G�������f��
00F0: 00 00 00 00 FE 84 03 00 00 00 00 00 F8 A3 03 00   ����������������
0100: 00 00 00 00 F2 C2 03 00 00 00 00 00 EC E1 03 00   ����������������
0110: 00 00 00 00 E6 00 04 00 00 00 00 00 E0 1F 04 00   ����������������
0120: 00 00 00 00 DA 3E 04 00 00 00 00 00 D4 5D 04 00   �����>�������]��
0130: 00 00 00 00 CE 7C 04 00 00 00 00 00 C8 9B 04 00   �����|������ț��
0140: 00 00 00 00 C2 BA 04 00 00 00 00 00 BC D9 04 00   ����º����������
0150: 00 00 00 00 B6 F8 04 00 00 00 00 00 .. .. .. ..   �����������.....

  Bytes: $000C-000F: Offset  to  stored  track  1.0  ($000002AC,  in  LO/HI
                     format, see below for more)
          0010-0013: Offset to stored track 1.5 ($00000000)
          0014-0017: Offset to stored track 2.0 ($000021A6)
             ...
          0154-0157: Offset to stored track 42.0 ($0004F8B6)
          0158-015B: Offset to stored track 42.5 ($00000000)

  The track offsets rquire some explanation. When one is set to all 0's, no
track data exists for this entry. If there is a value, it  is  an  absolute
reference into the file (starting from the beginning of the file).

  If an image stored here only contains 35 tracks  (e.g.  a  standard  1541
disk), then all the offset values for track 35.5 and higher will be set  to
0. This can be used to detect the maximum track count when converting to  a
D64 image. Since D64's cannot hold over 40 tracks, and typically only  have
35, some information will be lost when converting a G64.

  From the track 1.0 entry we see it is set for $000002AC.  Going  to  that
file offset, here is what we see...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
02A0: .. .. .. .. .. .. .. .. .. .. .. .. 0C 1E FF FF   ............����
02B0: FF FF FF 52 54 B5 29 4B 7A 5E 95 55 55 55 55 55   ���RT�)Kz^�UUUUU
02C0: 55 55 55 55 55 55 FF FF FF FF FF 55 D4 A5 29 4A   UUUUUU�����Uԥ)J
02D0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR

  Bytes: $02AC-02AD: Actual size of stored track (7692 or $1E0C,  in  LO/HI
                     format)
          02AE-02AE+$1E0C: Track data

  Following the track data is filler bytes. In this  case,  there  are  368
bytes of unused space. This space can contain anything, but for the sake of
those wishing to compress these images for storage, they should all be  set
to the same value. In the sample I used, these are all set to $FF.

  Below is a dump of the end of the track 1.0 data area.  Note  the  actual
track data ends at address $20B9, with the rest of the block being  unused,
and set to $FF.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
1FE0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR
1FF0: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94   ��)JR��)JR��)JR�
2000: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5   �)JR��)JR��)JR��
2010: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29   )JR��)JR��)JR��)
2020: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A   JR��)JR��)JR��)J
2030: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
2040: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
2050: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
2060: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
2070: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
2080: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
2090: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
20A0: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55   UUUUUUUUUUUUUUUU
20B0: 55 55 55 55 55 55 55 55 55 55 FF FF FF FF FF FF   UUUUUUUUUU������
20C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
20D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
20E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
20F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2100: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2110: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2120: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2130: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2140: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2150: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2160: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2170: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2180: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
2190: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF   ����������������
21A0: FF FF FF FF FF FF .. .. .. .. .. .. .. .. .. ..   ������..........


  Now we can look at the speed zone area. Below is a dump of the speed zone
offsets.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0150: .. .. .. .. .. .. .. .. .. .. .. .. 03 00 00 00   ............����
0160: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
0170: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
0180: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
0190: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
01A0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
01B0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
01C0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
01D0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00   ����������������
01E0: 00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00   ����������������
01F0: 00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00   ����������������
0200: 00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00   ����������������
0210: 00 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00   ����������������
0220: 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00   ����������������
0230: 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00   ����������������
0240: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00   ����������������
0250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
02A0: 00 00 00 00 00 00 00 00 00 00 00 00 .. .. .. ..   ������������....

  Bytes: $015C-015F: Speed zone entry for track 1 ($03,  in  LO/HI  format,
                     see below for more)
          0160-0163: Speed zone entry for track 1.5 ($03)
             ...
          02A4-02A7: Speed zone entry for track 42 ($00)
          02A8-02AB: Speed zone entry for track 42.5 ($00)

  Starting at $02AC is the first track entry (from above, it is  the  first
entry for track 1.0)

  The speed offset entries can be a little more complex. The 1541 has  four
speed zones defined, which means the drive can write data at four  distinct
speeds. On a normal 1541 disk, these zones are as follows:

        Track Range  Storage in Bytes    Speed Zone
        -----------  ----------------    ----------
           1-17           7820               3  (slowest writing speed)
          18-24           7170               2
          25-30           6300               1
          31-4x           6020               0  (fastest writing speed)


  Note that you can, through custom programming of  the  1541,  change  the
speed zone of any track to something different (change the 3 to  a  0)  and
write data differently.

  From the above speed zone sample, all the zones  use  4-byte  entries  in
lo-hi format. If the value of the entry is less than 4, then  there  is  no
speed offset block for the track and the value  is  applied  to  the  whole
track. If the value is greater than 4 then we have an  actual  file  offset
referencing a speed zone block for the track.

  In the above example shown, there were no offsets defined,  so  no  speed
zone block dump can be shown. However, I can define what should  be  there.
You will have a block of data, 1982 bytes long. Each  byte  is  encoded  to
represent the speed of 4 bytes in the track offset area, and is broken down
as follows:

  Speed entry $FF:  in binary %11111111
                               ��������
                               � � � �
                               � � � �� 4'th byte speed (binary 11, 3 dec)
                               � � ���� 3'rd byte speed (binary 11, 3 dec)
                               � ������ 2'nd byte speed (binary 11, 3 dec)
                               �������� 1'st byte speed (binary 11, 3 dec)

  It was very smart of the designers of the G64 format  to  allow  for  two
speed zone settings, one in the offset block and another defining the speed
on a per-byte basis. If you are working with  a  normal  disk,  where  each
track is one constant speed, then  you  don't  need  the  extra  blocks  of
information hanging around the image, wasting space.


  What may not be obvious is the flexibility of this format to  add  tracks
and speed offset zones at will. If a program decides to write a  track  out
with varying speeds, and no speed offset exist, a new block will be created
by appending it to the end of the image, and the offset  pointer  for  that
track set to point to the new block. If a track has no offset yet,  meaning
it doesn't exist (like a half-track), and one needs to be added,  the  same
procedure applies. The location of the actual track or speed zone  data  is
not important, meaning they do not have to be in linear  order  since  they
are all referenced by the offsets at the beginning of the image.




Analysing the GCR data stream
-----------------------------

  Since the information stored in the track data area is in GCR format,  it
is not as simple to analyse as a normal 256-byte sector would be. Here is a
dump of a portion of the GCR data, and what to look for...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 0C 1E FF FF FF FF FF 52 54 B5 29 4B 7A 5E 95 55   �������RT�)Kz^�U
0010: 55 55 55 55 55 55 55 55 55 55 FF FF FF FF FF 55   UUUUUUUUUU�����U
0020: D4 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94   ԥ)JR��)JR��)JR�
0030: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5   �)JR��)JR��)JR��
0040: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29   )JR��)JR��)JR��)
0050: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A   JR��)JR��)JR��)J
0060: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR
0070: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94   ��)JR��)JR��)JR�
0080: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5   �)JR��)JR��)JR��
0090: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29   )JR��)JR��)JR��)
00A0: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A   JR��)JR��)JR��)J
00B0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR
00C0: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94   ��)JR��)JR��)JR�
00D0: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5   �)JR��)JR��)JR��
00E0: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29   )JR��)JR��)JR��)
00F0: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A   JR��)JR��)JR��)J
0100: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR
0110: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94   ��)JR��)JR��)JR�
0120: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5   �)JR��)JR��)JR��
0130: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29   )JR��)JR��)JR��)
0140: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A   JR��)JR��)JR��)J
0150: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR
0160: 94 A5 29 4A 55 55 55 55 55 55 FF FF FF FF FF 52   ��)JUUUUUU�����R
0170: 54 A5 2D 4B 7A 5E 95 55 55 55 55 55 55 55 55 55   T�-Kz^�UUUUUUUUU
0180: 55 55 FF FF FF FF FF 55 D4 A5 29 4A 52 94 A5 29   UU�����Uԥ)JR��)
0190: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A   JR��)JR��)JR��)J
01A0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52   R��)JR��)JR��)JR
01B0: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94   ��)JR��)JR��)JR�
01C0: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5   �)JR��)JR��)JR��

  We need to establish a marker by which one can  start  to  interpret  the
data. Always look for a group of at least 10 1-bits (two 'F's in a row  and
a bit more), as they establish the SYNC mark. The 1541 actually writes  out
a SYNC mark of 40 'on' bits (10 'F's in a  row).  Note  that  there  are  2
groups of SYNC marks quite close together, one for the  sector  header  and
one for the sector data. In the above example, there is 2 groups of "FF  FF
FF FF FF". The first one is the header SYNC and the second one is the  data
SYNC.

  An important point here: some documentation refers to  the  minimum  SYNC
mark as being at least 12 bits wide, and claims that one of  that  size  is
still not entirely reliable. Thus Commodore chose to use 40  bits  for  the
SYNC mark, making it impossible for the drive read electronics to miss.

  If the GCR data is not in the standard sector layout, then anything  goes
for interpreting the data. If no standard SYNC  mark  can  be  found,  then
there is no simple way to extract any useful data.


  Here's the layout of a standard low-level pattern on a 1541 disk. Use the
above example to follow along.

   1. Header sync   FF FF FF FF FF (40 'on' bits, not GCR encoded)
   2. Header info   52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes)
   3. Header gap    55 55 55 55 55 55 55 55 55 (9 bytes, never read)
   4. Data sync     FF FF FF FF FF (40 'on' bits, not GCR encoded)
   5. Data block    55...4A (325 GCR bytes)
   6. Tail gap      55 55 55 55...55 55 (4 to 19 bytes, never read)
   1. Header sync   (SYNC for the next sector)


  The 10 header info bytes (#2) are GCR encoded and must be decoded down to
it's normal 8 bytes to be understood. Once decoded,  its  breakdown  is  as
follows:

   Byte  $00 - header block ID ($08)
          01 - header block checksum (EOR of $02-$05)
          02 - Sector# of data block
          03 - Track# of data block
          04 - Format ID byte #2
          05 - Format ID byte #1
       06-07 - $0F ("off" bytes)

  The header gap (#3) is 8 bytes on the early 1540/1541 ROM versions, but 9
bytes in the later revisions. The 1541 doesn't read  the  header  gap,  but
simply waits it out to write out the  sector  data.  When  sector  data  is
written, the SYNC mark is re-written as well.

  There is some controversy over the header gap (#3). Most people assume it
to be 9 bytes of 0x55 characters, but the early 1540/1541 drives used  only
8. This caused an write incompatability with the existing 4040 disks of the
day. In 1541 ROM revision 901225-3 this error was fixed, and now all drives
write out 9 of the 0x55 characters for the gap. The book "Inside  Commodore
DOS"  by  Immers/Neufeld  documents  the  write  incompatibilty  and   what
corruption happens at a low level when writing to a disk with a header  gap
of 8 bytes on a disk that normally expects a gap of 9 bytes.

  The tail gap (#6) is the unused space between the end of one  data  block
and the start of the next. It will vary in size depending on what track you
are on, how fast the drive that created the disk was rotating at, and  what
program was used to format the disk. The stock 1541 format code is supposed
to determine how big a track is and divide up the extra unused  space  into
each tail gap. However, many disks will show a much larger tail gap between
the last sector and sector 0. In tests that the author conducted on a  real
1541 disk, gap sizes of 8 to 19 bytes were seen.


  The 325 byte data block (#5) is GCR encoded and must be  decoded  to  its
normal 260 bytes to be understood. For comparison, ZipCode Sixpack  uses  a
326 byte GCR sector (why?), but the last byte (when properly rearranged) is
not used. The data block is made up of the following:

  Byte    $00 - data block ID ($07)
       01-100 - 256 bytes sector data
          101 - data block checksum (EOR of $01-100)
      102-103 - $00 ("off" bytes, to make the sector size a multiple of 5)


  The most reliable way to read G64 track data is to read it as  bits,  not
bytes, as there is no way to be sure that all  the  data  is  byte-aligned.
This simulates the way a 1541 drive reads data as well  as  the  head  only
reads bits as well. The starting location of the track data  is  known,  as
well as the track size so the boundaries of the  track  limits  (start  and
end) are obtainable.

  What follows is a very simply  point-form  list  of  how  to  read  data,
finding sync marks, header blocks and sector blocks.

    1. Search for SYNC (at least 10 or more 1 bits)
    2. Check for header ID after SYNC (GCR 0x52)
    3. If header, read the remaining 9 header bytes
    4. Decode header and get sector value
    5. Search for SYNC again
    6. Check for data ID after SYNC (GCR 0x55).
    7. If data, read and store with previous header.
    8. Have we finished reading the track... stop
    9. Back to 1


*** GEOS VLIR (Variable Length Index Record)
*** Document revision: 1.4
*** Last updated: Nov 27, 2005
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Paul David Doherty,
                          Andreas Varga,
                          Joe Forster/STA

  Later on in the life of the C64, the GEOS OS came out. It  was  a  system
much like many other windowing OS's (MAC  OS,  Windows)  in  that  it  used
icons, windows, a mouse pointer and resource drivers. In order  to  contain
all the information needed for the windowing system (icon, window position,
creation time/date), a new filetype called VLIR was  needed  and  directory
changes were made. While GEOS files might not be of interest to many of the
emulator users, it is likely that these  files  will  be  encountered,  and
knowledge of them would be helpful.

  There are actually two types of GEOS files, VLIR  and  SEQuential.  Don't
confuse the GEOS SEQuential type with that of the standard  D64  SEQ  file.
They are related, but not the same.  VLIR  are  described  in  more  detail
following this paragraph. GEOS SEQuential files  are  all  non-VLIR  files,
including normal PRG, USR and SEQ types.

  GEOS files usually have an entity  attached  called  an  INFO  block.  It
contains ICON info, author, file description, load  address  etc.  However,
just because an INFO block does not exist for a given file, does  not  mean
that the file is not a GEOS file.

  Each GEOS VLIR file or application is comprised of many  separate  chains
(called RECORDS) for different sections of the app/file. Each RECORD can be
loaded in separately and overtop of other ones. Below  is  a  dump  of  the
first directory sector of the GEOS 2.0 disk. Note  the  first  entry  seems
normal enough, but the rest have additional  information  in  the  normally
unused section of the entry.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 12 04 82 13 00 47 45 4F 53 20 56 32 2E 30 20 45  <- Normal entry
10: 4E 47 4C 2E A0 00 00 00 00 00 00 00 00 00 58 00
20: 00 00 83 02 02 44 45 53 4B 20 54 4F 50 A0 A0 A0  <- First GEOS file.
30: A0 A0 A0 A0 A0 02 0F 01 04 58 08 13 0D 23 78 00  <- Note extra info
40: 00 00 83 0B 13 43 4F 4D 4D 20 31 33 35 31 28 61     from offset $15 to
50: 29 A0 A0 A0 A0 08 0F 00 0A 58 05 09 15 24 03 00     $1D.
60: 00 00 83 0F 0D 4D 50 53 2D 38 30 31 A0 A0 A0 A0
70: A0 A0 A0 A0 A0 0F 05 00 09 56 07 19 01 00 04 00
80: 00 00 83 08 0D 43 4F 4E 46 49 47 55 52 45 A0 A0
90: A0 A0 A0 A0 A0 08 05 01 0E 58 05 1F 0B 31 4E 00
A0: 00 00 83 01 10 50 41 49 4E 54 20 44 52 49 56 45
B0: 52 53 A0 A0 A0 01 08 00 06 57 08 0C 0E 00 12 00
C0: 00 00 83 0B 05 70 72 65 66 65 72 65 6E 63 65 20
D0: 6D 67 72 A0 A0 0B 12 00 05 56 0A 09 13 2D 16 00
E0: 00 00 83 08 11 70 61 64 20 63 6F 6C 6F 72 20 6D
F0: 67 72 A0 A0 A0 08 07 00 05 58 05 19 0C 10 16 00

  Lets analyze the second entry to see what's all involved with GEOS files.
Note, the offset values have been changed to 0 to make referencing easier.

00: 00 00 83 02 02 44 45 53 4B 20 54 4F 50 A0 A0 A0
10: A0 A0 A0 A0 A0 02 0F 01 04 58 08 13 0D 23 78 00

  Byte:   $02: C64 filetype (see the section on D64 for an explanation) REL
               files are not allowed.
        03-04: Starting track/sector (02/02 from above) of C64 file if GEOS
               filetype is $00. If GEOS filetype is non-zero,  track/sector
               of single-sector RECORD block
        05-14: Filename (in ASCII, padded with $A0, case varies)
        15-16: Track/sector location of info block
           17: GEOS file structure
                 $00 - Sequential
                  01 - VLIR file
           18: GEOS filetype
                 $00 - Non-GEOS (normal C64 file)
                  01 - BASIC
                  02 - Assembler
                  03 - Data file
                  04 - System File
                  05 - Desk Accessory
                  06 - Application
                  07 - Application Data (user-created documents)
                  08 - Font File
                  09 - Printer Driver
                  0A - Input Driver
                  0B - Disk Driver (or Disk Device)
                  0C - System Boot File
                  0D - Temporary
                  0E - Auto-Execute File
               0F-FF - Undefined
           19: Year (1900 + value)
           1A: Month (1-12, $01 to $0C)
           1B: Day (1-31, $01 to $1F)
           1C: Hour (0-23, $00 to $17) in military format
           1D: Minute (0-59, $00 to $3B)
        1E-1F: Filesize, in sectors (low/high byte order)

  If the values at byte $18 is 00 then we have a  normal,  sequential,  C64
file, without an info block. If the value at byte  $18  is  anything  other
than 00, we have a GEOS file, be it VLIR or sequential, with an info block.

  One big addition to the directory is the TIME STAMP contained at $19-$1D.
The year is simply the number 1900 plus whatever is stored at that location
so the year 2005 would have a $69 (105 decimal) stored there. The  rest  of
the values are limited as described above.


  The INFO BLOCK stores items like  the  ICON,  size,  load  address,  file
types, description, etc, and is always only 1 sector long. Since there is a
fixed space to store information, the ICON height, width and bitmap  length
must be the same. Here is a sample info block, and layout...

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 00 FF 03 15 BF 3F 83 F8 40 44 04 8E 38 E2 B5 93  �����?��@D��8ⵓ
10: 59 AA 92 A9 B5 93 59 AA 92 A9 BF 93 F9 B1 93 19  Y�����Y���������
20: 8E 10 E1 BB 93 B9 B5 93 59 AA 92 A9 B5 93 59 AE  ��ồ���Y�����Y�
30: 92 E9 B1 93 19 80 10 01 BF 93 F9 FF D7 FD 80 38  �鱓�����������8
40: 03 FF FF FF 83 05 00 00 2E D9 54 00 2E 50 68 6F  ��������.�T�.Pho
50: 74 6F 20 4D 67 72 20 20 20 56 32 2E 31 00 00 00  to�Mgr���V2.1���
60: 00 43 68 72 69 73 20 48 61 77 6C 65 79 00 00 00  �Chris�Hawley���
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
80: 00 00 00 00 00 00 00 00 00 53 61 76 65 20 70 68  ���������Save�ph
90: 6F 74 6F 20 69 6D 61 67 65 73 20 69 6E 20 61 20  oto�images�in�a�
A0: 53 61 76 65 20 70 68 6F 74 6F 20 69 6D 61 67 65  Save�photo�image
B0: 73 20 69 6E 20 61 20 70 68 6F 74 6F 20 61 6C 62  s�in�a�photo�alb
C0: 75 6D 20 66 6F 72 20 6C 61 74 65 72 20 75 73 65  um�for�later�use
D0: 20 69 6E 20 67 65 6F 57 72 69 74 65 20 6F 72 20  �in�geoWrite�or�
E0: 67 65 6F 50 61 69 6E 74 2E 00 02 85 06 85 07 85  geoPaint.�������
F0: 08 85 09 85 16 A9 04 85 11 A9 00 85 10 4C 2F C2  �������������L/�

  Byte: $00-01: Contains $00/$FF since its only 1 sector long
         02-04: Information sector ID bytes (03 15 BF). The "03" is  likely
                the bitmap width, and the "15" is likely the bitmap height,
                but rare exceptions do exist to this!
         05-43: Icon bitmap (sprite format, 63 bytes)
            44: C64 filetype (same as that from the directory entry)
            45: GEOS filetype (same as that from the directory entry)
            46: GEOS file structure (same as that from the dir entry)
         47-48: Program load address
         49-4A: Program end address (only with accessories)
         4B-4C: Program start address
         4D-60: Class text (terminated with a $00)
         61-74: Author (with application data: name  of  application  disk,
                terminated with a $00. This string may not  necessarily  be
                set, or it may contain invalid data)
                The following GEOS files have authors:
                  1 - BASIC
                  2 - Assembler
                  5 - Desk Accessory
                  6 - Application
                  9 - Printer Driver
                 10 - Input Driver
         75-88: If a document, the name of the application that created it.
         89-9F: Available for applications, unreserved.
         A0-FF: Description (terminated with a $00)

Note: all the text strings above are in ASCII, not PETASCII.

  If the file is a VLIR, then the RECORD block is of interest. This  single
sector is made up of up to 127 track/sector pointers, each of  which  point
to program sections (called RECORDS). VLIR files are comprised of  loadable
RECORDS (overlays, if you wish to use PC terminology). The first RECORD  is
what is always loaded first when you run that application. After that,  the
OS loads whatever RECORD it needs. Here is a partial sample of  the  RECORD
sector...

00: 00 FF 08 00 09 04 09 03 0A 0A 0B 11 0F 11 00 00
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

  Byte: $00-01: Contains 00/FF since its only 1 sector long
         02-03: Starting track/sector (8,0) for the first RECORD
         04-05: Starting track/sector (9,4) for the second RECORD
         06-07: Starting track/sector (9,3) for the third RECORD
         08-09: fourth RECORD (10/10)
         0A-0B: fifth RECORD (11/17)
         0C-0D: sixth RECORD (15/17)
         0E-0F: seventh RECORD (0/0)

  When a T/S link of $00/$00 is encountered, we  are  at  the  end  of  the
RECORD block. If the T/S  link  is  a  $00/$FF,  then  the  record  is  not
available.

  Note that if you add up the sectors so far, we have only  used  two,  one
for the INFO sector and one for the RECORD sector. Obviously there are more
used, and they are contained in the sector chains from the  RECORD  sector.
Each t/s link in the RECORD sector points to a chain of sectors, the length
of which is included in the  sector  count  for  the  GEOS  file.  Doing  a
VALIDATE on a GEOS disk when not in GEOS would de-allocate all these sector
chains (and the RECORD sector as well), which would not be good!


  Below is the dump of a BAM sector from a  GEOS-formatted  D64  image  and
there are some changes for GEOS. We have all the typical data (forward  t/s
pointer to 18/1, DOS type, disk name/id) but we also have  the  GEOS-format
signature from $AB-BC. From observation, any GEOS-formatted disk will  have
the GEOS signature written in the same place (offset  $AB)  in  the  sector
that contains the disk name/ID.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
    -----------------------------------------------  ----------------
00: 12 01 41 00 13 FE DF 1F 0A 69 29 0D 15 FF FF 1F  ��A������i)�����
10: 0C 96 D6 16 01 00 00 10 00 00 00 00 11 FD BD 1D  ����������������
20: 15 FF FF 1F 0C 96 D6 16 00 00 00 00 00 00 00 00  ����������������
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
40: 00 00 00 00 00 00 00 00 0F FC FD 05 00 00 00 00  ����������������
50: 00 00 00 00 06 05 05 05 01 00 40 00 00 00 00 00  ����������@�����
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
80: 00 00 00 00 00 00 00 00 01 00 02 00 11 FF FF 01  ����������������
90: 41 70 70 6C 69 63 61 74 69 6F 6E 73 A0 A0 A0 A0  Applications����
A0: A0 A0 4A 44 A0 32 41 A0 A0 A0 A0 13 08 47 45 4F  ��JD�2A������GEO
B0: 53 20 66 6F 72 6D 61 74 20 56 31 2E 30 50 BD 1E  S�format�V1.0P��
C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
D0: 00 00 00 00 00 00 00 00 00 00 00 18 2D 00 00 00  ������������-���
E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������
F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ����������������

  Bytes:$00-01: Track/Sector location of the first directory sector (should
                be 18,1, but it doesn't seem to matter)
            02: Disk DOS version type
                  $41=1541
            03: $2A, DOS version.
         04-8F: BAM entries for each track, in groups  of  four  bytes  per
                track, starting on track 1
         90-9F: Disk Name (padded with $A0)
         A0-A1: Filled with $A0
         A2-A3: Disk ID
            A4: Usually $A0
         A5-A6: DOS type, usually "2A"
         A7-AA: Filled with $A0
         AB-AC: Border sector trk/sec (see below)
         AD-BC: GEOS ID string ("GEOS format V1.x", in ASCII)
         BD-DC: Unused (usually $00)
         DD-FF: Free sector info for tracks  36-70,  used  on  double-sided
                1571 disks only!

  The first two bytes at $AB/$AC ($13 $08) are the track/sector location of
the BORDER SECTOR, which is one sector long,  has  the  same  layout  as  a
normal directory sector, and is used for copying files  from  one  disk  to
another. When you need to copy a file, you drag the icon to the  bottom  of
the screen and the file is moved from its normal location in the  directory
to the border sector. Since it is  only  1  sector,  it  can  only  hold  8
entries.


  If you want to check to see if a disk is formatted for  GEOS,  check  the
string in the BAM sector starting at $AD (offset 173) for the string  "GEOS
format". If it does not match, the disk is not in GEOS format. This is  the
way that GEOS itself verifies if a disk is GEOS formatted.


  On a D64/1541, here is how GEOS allocates blocks as it either saves files
or needs blocks for other purposes:

Saving files: When there's still at least one free  block  in  the  current
track, then the next block is searched for starting at the sector which  is
away from the current one by at least the soft interleave.  The  exceptions
are track 25 and  above  where  the  interleave  changes  to  the  original
interleave _minus one_.

When stepping to the next track, the sector where the  next  block  of  the
files is saved to is computed as following:

  New sector = (Next track - Previous Track) * 2 + 4 + Soft interleave

Getting the Border Sector: When allocating  the  GEOS  border  sector,  the
search starts upwards from sector 19/0 for a  free  sector  and  then  from
sector 1/0 if no free one has been found yet.

Getting the first sector for saving a file: Start searching from sector 1/0
and, on the first track that has  at  least  one  free  sector,  you  start
searching at the sector computed by the form above.


  Seeing as this is not an emulator format,  I  will  not  comment  on  its
relative merits. It is simply another C64 file type.



How to detect if a file is GEOS
-------------------------------

1. Check the bottom 3 bits of the D64 file type (byte position $02  of  the
   directory entry). If it is not 0, 1 or 2  (but  3  or  higher,  REL  and
   above), the file cannot be GEOS.

2. Check the FILE STRUCTURE and FILE TYPE bytes (byte position $23 and  $24
   respectively). If they are both $00, then the file is not GEOS, but is a
   normal D64 filetype (no INFO block either).

3. Check the FILE STRUCTURE byte (position $23). If it  is  anything  other
   than $00 or $01, then the file is not GEOS (as those are the only  legal
   values).

4. If you've reached this point, and everything looks ok, then the file  is
   GEOS. Now, if the FILE STRUCTURE byte (position $23) is a $01, then  the
   file is a GEOS VLIR, otherwise it is a GEOS SEQ.

5. Check the FILE TYPE byte (position $24). If it is non-zero,  then  there
   is likely an INFO block attached.  Check  the  track/sector  pointer  at
   position $21/22 to see if they are valid numbers (track within the specs
   of the disk and sector in range for the track value). If they look good,
   then the info block exists.






*** LBR (LiBRary containers, C64 version only)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/samples: Joe Forster/STA

  There are two different types of LBR files, one for the C64 and one  more
commonly used by CP/M (in this case on the  C128).  This  explanation  only
deals with the C64 type.

  This is a native C64 format, slightly similar in  structure  to  ARK/LNX.
There exists a program on the C64 called  "Library  10.0"  which  seems  to
maintain these containers. From the information in the  program  (which  is
written in BASIC with a small ML subroutine), it appears  the  program  was
really meant for up/downloading files from BBS's.  From  looking  over  the
text in Library V7.0, the author appears to be Mike Swanson,  or  at  least
the author of that version.

  The container starts out with a 3 byte signature ("DWB"), the  file  size
and file types are stored in  ASCII  with  a  single  space  padding  their
start/end, and all strings and numbers are terminated with a <CR>.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 44 57 42 20 39 20 0D 53 55 50 45 52 20 44 4F 53   DWB�9��SUPER�DOS
0010: 0D 50 0D 20 31 35 30 37 20 0D 44 4D 43 20 31 2E   �P��1507��DMC�1.
0020: 32 2F 47 52 41 46 46 49 54 59 0D 50 0D 20 32 30   2/GRAFFITY�P��20
0030: 32 34 31 20 0D 42 2E 44 45 4C 54 41 20 5A 41 4B   241��B.DELTA�ZAK
0040: 20 2E 44 4D 43 0D 50 0D 20 32 37 30 32 20 0D 42   �.DMC�P��2702��B
0050: 2E 52 4F 43 4B 20 5A 41 4B 31 20 2E 44 4D 43 0D   .ROCK�ZAK1�.DMC�
0060: 50 0D 20 32 38 38 36 20 0D 49 4E 46 4F 52 4D 41   P��2886��INFORMA
0070: 54 49 4F 4E 2E 2E 2E 0D 50 0D 20 38 38 34 38 20   TION...�P��8848�
0080: 0D 42 2E 4B 49 44 44 49 4E 47 20 20 20 2E 44 4D   �B.KIDDING���.DM
0090: 43 0D 50 0D 20 32 38 39 31 20 0D 42 2E 47 41 4C   C�P��2891��B.GAL
00A0: 57 41 59 20 5A 41 4B 2E 44 4D 43 0D 50 0D 20 32   WAY�ZAK.DMC�P��2
00B0: 38 36 30 20 0D 42 2E 41 20 4D 55 53 49 43 20 20   860��B.A�MUSIC��
00C0: 20 2E 44 4D 43 0D 50 0D 20 33 31 33 37 20 0D 47   �.DMC�P��3137��G
00D0: 2E 50 41 43 4D 41 4E 49 41 20 20 2E 44 4D 43 0D   .PACMANIA��.DMC�
00E0: 50 0D 20 33 32 36 32 20 0D 01 08 0B 08 00 00 9E   P��3262���������

  The first 3 bytes are the signature to the file, "DWB", perhaps the  true
authors initials...

0000: 44 57 42 .. .. .. .. .. .. .. .. .. .. .. .. ..   DWB.............

  Following this is the number of entries in the directory (9). See how  it
has a space preceeding it, trailing it, and  a  <CR>  at  the  end  of  the
string.

0000: .. .. .. 20 39 20 0D .. .. .. .. .. .. .. .. ..   ...�9�..........

  Following this we have the first directory  entry.  The  file  is  "Super
DOS", it is a program file ("P"), and it is 1507 bytes long. The  filenames
are not stored with any shift-space padding (like most other  formats),  so
the directory entries vary widely in size. The filename does get terminated
with a <CR>. From my experiments with the Library program,  it  does  *not*
support REL files.

0000: .. .. .. .. .. .. .. 53 55 50 45 52 20 44 4F 53   .......SUPER�DOS
0010: 0D 50 0D 20 31 35 30 37 20 0D .. .. .. .. .. ..   .P.�1507�.......

  Following this are the remaining directory entries.

0010: .. .. .. .. .. .. .. .. .. .. 44 4D 43 20 31 2E   ..........DMC�1.
0020: 32 2F 47 52 41 46 46 49 54 59 0D 50 0D 20 32 30   2/GRAFFITY.P.�20
0030: 32 34 31 20 0D .. .. .. .. .. .. .. .. .. .. ..   241�............
 ...
00C0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 47   ...............G
00D0: 2E 50 41 43 4D 41 4E 49 41 20 20 2E 44 4D 43 0D   .PACMANIA��.DMC.
00E0: 50 0D 20 33 32 36 32 20 0D .. .. .. .. .. .. ..   P.�3262�.......

  If it is not obvious yet, there is no way to know where the first  file's
data starts in the container until the whole directory has been  read.  The
byte following the <CR> of the last entry it is the first byte of the first
entry.

00E0: .. .. .. .. .. .. .. .. .. 01 08 0B 08 00 00 9E   .............���

  From the starting location of the file file's data, you can now calculate
where all the other entries start by using the file size, contained in each
directory entry. In this case, the first file starts at $00E9 (offset 233).
The second will then start at $06CC (1740).

06C0: .. .. .. .. .. .. .. .. .. .. .. .. 01 08 0B 08  .................

  64COPY supports this format on a read-only basis, allowing you to convert
the files contained to another format.

---------------------------------------------------------------------------

What it takes to support LBR:

  Except for a simple layout, and a 3-byte signature to identify the  file,
a few obvious deficiencies exist in the LBR layout which can  make  support
difficult.

  Reading LBR files, in order to copy files out, is relatively  easy.  Once
the directory is read we know all the file sizes, and we  also  know  where
the first file starts. It is a simple matter to figure out where each  file
actually starts in the LBR from this information.

  Writing LBR is more difficult as it would appear that you must  know  the
size of each file *before* you create the LBR header. It would also  appear
that the whole directory must be created before *any* file copying can take
place. When copying files from a D64 to an LBR, you don't know the  *exact*
file size as they are stored in sectors. You would need to scan the  source
file, tracing the sectors until the last one to determine its size.

  Unlike LNX/ARK, the size of the directory is not made to  fit  blocks  of
254 bytes (for easy 1541 usage), and the files are not aligned to 254  byte
boundaries. This makes deleting files more difficult  as  no  matter  which
file gets deleted, the whole file will have to be re-written.

  The lack of a consistent directory entry size (like D64's 32 bytes)  also
makes working with LBR inconvenient. Many of the file formats for  the  C64
and the emulators suffer from this lack of a  well-defined  layout.  It  is
understandable, however, why  formats  like  LBR  (and  LNX)  create  their
entries in ASCII rather than binary as it's easier to use BASIC and  output
a number in ASCII (delimited with a <CR>) than to calculate and output  the
value in binary format.

  The last negative for LBR is it doesn't support REL or  GEOS  files,  but
thats not so important.

*** LHA, LZH, LZS (LHArc compressed files)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/samples: Joe Forster/STA, net documents

  These files are created with LHA on the C64 (or C128),  and  can  present
special problems to the typical PC user. The compression used  is  LH1,  an
old method used on LZH 1.xx (pre-version 2), so any version of LHA  on  the
PC can  uncompress  them.  However,  LHA  allows  filenames  of  up  to  18
characters long, and DOS doesn't know how to handle them (Windows 95  unLHA
utilities will extract the full  filename).  Usually,  some  of  the  files
already  uncompressed  will  be  overwritten  by  other  files  just  being
uncompressed because the name seems the same to DOS. To  LHA  however,  the
filenames are quite different.

  LHA archives always have a string two bytes into the file ("-L??-") which
describe the type of compression used. Over the  development  life  of  LHA
there have been several different compression algorithms used. The "??"  in
the "-L??-" can be one of several possibilites, but on the C64 it is likely
limited to "H0" (no compression) and "H1". Newer versions  of  LHA/LZH  use
other combinations like "H2", "H3", "H4", "H5", "ZS", "Z5", and  "Z4".  The
letters typically used in the compression string come from a combination of
the creators initials of the LZ algorithm, Lempel/Ziv, and  the  author  of
the LHA program, Haruyasu Yoshizaki.

The following is a sample of an LHA header. Note the string to  search  for
at byte $0002:

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 24 93 2D 6C 68 31 2D 39 02 00 00 16 04 00 00 00   ..-lh1-.........
0010: 08 4C 14 00 00 0E 73 79 73 2E 48 6F 75 73 65 20   ................
0020: 4D 34 00 53 DE 06 11 1C 12 C4 C8 FA 3A 5B DC CE   ................
0030: B2 FA 38 1E 46 B0 B6 9E 9B 75 7A 49 71 72 B3 53   ................
0040: 6E 4E B4 A0 BF 5E 95 B3 05 8A 75 D5 6C E3 03 4A   ................
0050: 2C 54 F4 AF 05 18 59 E2 F4 34 4A 0A 28 D4 33 E2   ................
0060: C4 9D 04 D7 C7 8B 91 66 0E E5 DE 98 3C 92 CC B5   ................

  The header layout is fairly basic. The header for each file starts  *two*
bytes before the "-lh?-" string. The above example has already been trimmed
down to start at these two bytes. Each header has the same layout, only the
length varies due to the length of the filename. Here is a breakdown of the
above example.

    Bytes: $0000: 24 - Length of header (known as "LEN", not including this
                       and the next byte). If it is zero, we are at the end
                       of the file.
            0001: 93                   - Header checksum
            0002: 2D 6C 68 31 2D       - LHA compression type "-LH1-"
            0007: 39 02 00 00          - Compressed file size ($00000239)
            000B: 16 04 00 00          - Uncompressed file size ($00000416)
            000F: 00 08 4C 14          - Time/date stamp
            0013: 00                   - File attribute
            0014: 00                   - Header level
                                              00 = non-extended header
                                          01, 02 = extended header
            0015: 0E                   - Length of the following filename
            0016: 73 79 73 2E 48 6F 75 - Filename, with a zero and filetype
                  73 65 20 4D 34 00 53   appended ("SYS.HOUSE M4�S"). The
                                         name can be up to 18 characters in
                                         length. Note the length *includes*
                                         the zero and filetype, making the
                                         actual filename length 2 bytes
                                         shorter.
            0024: DE 06                - File data checksum (starts at LEN)
            0026: 11 1C 12 C4 C8 FA... - File data (starts at LEN+2)

  The header checksum at byte $0001 is calculated by adding  the  bytes  in
the header from $0002 (LHA compression type) to LEN+1 (File data checksum),
without carry.

  The time/date stamp (bytes $000F-$0012), is broken down as follows:

      Bytes:$000F-0010: Time of last modification:
                        BITS  0- 4: Seconds divided by 2
                                    (0-58, only even numbers)
                        BITS  5-10: Minutes (0-59)
                        BITS 11-15: Hours (0-23, no AM or PM)
      Bytes:$0011-0012: Date of last modification:
                        BITS  0- 4: Day (1-31)
                        BITS  5- 9: Month (1-12)
                        BITS 10-15: Year minus 1980

  The format of the compressed data is much too complex to get  into  here.
Understanding the layout would require  knowledge  of  Huffman  coding  and
sliding dictionaries, and  is  nowhere  near  as  simple  as  ZipCode!  The
description given in the LHA source  code  for  the  different  compression
modes are as follows:

      -lh0- no compression, file stored
      -lh1- 4k sliding dictionary (max 60 bytes) + dynamic Huffman +  fixed
            encoding of position
      -lh2- 8k sliding dictionary (max 256 bytes) + dynamic Huffman
      -lh3- 8k sliding dictionary (max 256 bytes) + static Huffman
      -lh4- 4k sliding dictionary  (max  256  bytes)  +  static  Huffman  +
            improved encoding of position and trees
      -lh5- 8k sliding dictionary  (max  256  bytes)  +  static  Huffman  +
            improved encoding of position and trees
      -lzs- 2k sliding dictionary (max 17 bytes)
      -lz4- no compression, file stored
      -lz5- 4k sliding dictionary (max 17 bytes)

  There are several utilities that you can use to decompress  these  files,
like the already-mentioned LHA on the PC, or Star  LHA,  one  of  the  many
excellent utilities contained in the Star Commander  distribution  package.
If you use Star LHA, keep in mind it needs the program LHA v2.14 (or newer)
to extract. If an older version of LHA is used (such as the common  version
2.13), then the files being extracted will be corrupt. It will extract  the
files directly into a D64 image, so the long  C64  filenames  will  not  be
lost.

  To an emulator user there is no use to these files, as  their  only  real
usage on a C64 was for storage  and  transmission  benefits.  The  standard
compression program on the PC is PKZIP (or ZIP compatibles), so unless  you
have some need to send *compressed* files back the C64, there is no use  in
using LHA.


*** LNX (LyNX containers)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Marko Makela

  Written by Will Corley (and subsequently cloned  and  rewritten  by  many
others like "Willie" or "S.B."'s "Ultimate Lynx"), this format is  designed
around the sector size of the 1541. It consists of "blocks"  of  254  bytes
each (256 if we are on a real 1541 or a D64 due to  the  inclusion  of  the
track/sector info at the beginning of each sector).

  One word of warning: the  Lynx  utility  "Ultimate  Lynx"  can  sometimes
create LNX containers which do *not* have the sector data block-aligned  to
254-byte boundaries. If they are not aligned, the  files  contained  within
will be corrupt when extracted.

  When these files  are  on  *any*  other  format  they  do  not  have  the
track/sector info, and therefore use only 254 bytes/block. Here is  a  dump
of the directory header of one permutation of the layout...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 01 08 5B 08 0A 00 97 35 33 32 38 30 2C 30 3A 97   ..[.���53280,0:�
0010: 35 33 32 38 31 2C 30 3A 97 36 34 36 2C C2 28 31   53281,0:�646,�(1
0020: 36 32 29 3A 99 22 93 11 11 11 11 11 11 11 11 22   62):�"�........"
0030: 3A 99 22 20 20 20 20 20 55 53 45 20 4C 59 4E 58   :�"�����USE�LYNX
0040: 20 54 4F 20 44 49 53 53 4F 4C 56 45 20 54 48 49   �TO�DISSOLVE�THI
0050: 53 20 46 49 4C 45 22 3A 89 31 30 00 00 00 0D 20   S�FILE":�10���.�
0060: 31 20 20 2A 4C 59 4E 58 20 58 56 20 20 42 59 20   1��*LYNX�XV��BY�
0070: 57 49 4C 4C 20 43 4F 52 4C 45 59 0D 20 34 20 0D   WILL�CORLEY.�4�.
0080: 34 21 5A 4F 4E 45 20 4F 46 20 44 2D 2F 41 56 54   4!ZONE�OF�D-/AVT
0090: 0D 20 37 31 20 0D 50 0D 20 31 36 30 20 0D 31 21   .�71�.P.�160�.1!
00A0: 5A 4F 4E 45 20 4F 46 20 44 2D 2F 41 56 54 0D 20   ZONE�OF�D-/AVT.�
00B0: 37 35 20 0D 50 0D 20 31 35 31 20 0D 32 21 5A 4F   75�.P.�151�.2!ZO
00C0: 4E 45 20 4F 46 20 44 2D 2F 41 56 54 0D 20 31 37   NE�OF�D-/AVT.�17
00D0: 30 20 0D 50 0D 20 32 34 39 20 0D 33 21 5A 4F 4E   0�.P.�249�.3!ZON
00E0: 45 20 4F 46 20 44 2D 2F 41 56 54 0D 20 31 35 38   E�OF�D-/AVT.�158
00F0: 20 0D 50 0D 20 31 33 38 20 0D 00 00 00 00 00 04   �.P..138�.�����
0100: 1A 00 1A 08 05 08 E0 00 FF C2 0D 85 0F 04 39 03   .�....����…..9.

  It starts out with a BASIC program which, when loaded and  run,  displays
the message "Use LYNX to dissolve this file". The actual message  and  size
of the program can change. Usually, its 94 bytes long, from $0000 to $005D.

10 POKE53280,0:POKE53281,0:POKE646,PEEK(162):PRINT"<CLS><DOWN><DOWN><DOWN>
   <DOWN><DOWN><DOWN><DOWN><DOWN>":PRINT"     USE LYNX TO DISSOLVE THIS
   FILE":GOTO10

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 01 08 5B 08 0A 00 97 35 33 32 38 30 2C 30 3A 97   ..[.���53280,0:�
0010: 35 33 32 38 31 2C 30 3A 97 36 34 36 2C C2 28 31   53281,0:�646,�(1
0020: 36 32 29 3A 99 22 93 11 11 11 11 11 11 11 11 22   62):�"�........"
0030: 3A 99 22 20 20 20 20 20 55 53 45 20 4C 59 4E 58   :�"�����USE�LYNX
0040: 20 54 4F 20 44 49 53 53 4F 4C 56 45 20 54 48 49   �TO�DISSOLVE�THI
0050: 53 20 46 49 4C 45 22 3A 89 31 30 00 00 00 .. ..   S�FILE":�10���..

  Following this is the "signature" of the container, as well as  the  size
of the directory (in blocks) and the number of  directory  entries  in  the
container. These are stored in CBM lower case (ASCII for the most part), it
is delimited by <CR> after each entry (except the directory  block  size!),
and has spaces on both sides of the numbers. Normally  the  signature  will
contain the string "LYNX" somewhere.

  You will note that the numbers (and filetype)  stored  in  both  the  LNX
signature and the directory entries are unusual in that they are stored  in
ASCII, not binary (like the D64 entries). The  only  explanation  for  this
seems to be that the utilities used on the C64 to create  them  were  using
the INPUT# and PRINT# routines. These will  store  numbers  as  ASCII,  not
binary, and will truncate with a <CR>.

0050: .. .. .. .. .. .. .. .. .. .. .. .. .. .. 0D 20   ................
0060: 31 20 20 2A 4C 59 4E 58 20 58 56 20 20 42 59 20   1��*LYNX�XV��BY�
0070: 57 49 4C 4C 20 43 4F 52 4C 45 59 0D 20 34 20 0D   WILL�CORLEY.�4�.

  Note:  some  files  have  been  found  which  do  *NOT*  conform  to  the
established LNX header/directory structure.  They  do  not  contain  spaces
after the numbers in the directories, or contain extra spaces  in  the  LNX
header. Such files might give trouble Un-Lynxing on a real C64, and they do
not appear to have been created by Will Corley's standard "LyNX" program.

  So in the above example, we have a directory of 1 block (254 bytes) long,
the file was created by "LYNX XV BY WILL CORLEY", and we have 4 entries  in
the directory. The total directory length is 1 block * 254 bytes=254 bytes.
Therefore at byte $00FE, the program data will start. If the directory size
was 3 blocks, the data would start at $02FA. I do not know what the maximum
size is for either number (dir size/entry total), but it would seem  to  be
that since the 1541 only can  store  144  files,  these  numbers  would  be
limited accordingly.

0080: 34 21 5A 4F 4E 45 20 4F 46 20 44 2D 2F 41 56 54   4!ZONE�OF�D-/AVT
0090: 0D 20 37 31 20 0D 50 0D 20 31 36 30 20 0D .. ..   .�71�.P.�160�...

  This is the first directory entry called "4!ZONE OF D-/AVT".  The  layout
has the filename  (in  PETASCII,  typically  padded  to  16  characters  by
shifted-spaces), followed by the size of the file in blocks of  254  bytes,
the file type (P, S, R, U), and the LSU byte (see "INTRO.TXT" document  for
description of "LSU")

  If the file type is REL, this entry is the  RECORD  size,  and  the  next
entry is the last block size. If the file type is not REL, the  next  entry
will be the next filename.

0090: .. .. .. .. .. .. .. .. .. .. .. .. .. .. 31 21   ..............1!
00A0: 5A 4F 4E 45 20 4F 46 20 44 2D 2F 41 56 54 0D 20   ZONE�OF�D-/AVT.�
00B0: 37 35 20 0D 50 0D 20 31 35 31 20 0D .. .. .. ..   75�.P.�151�.....

This is the second directory entry. It  follows  the  same  layout  as  the
first.

00B0: .. .. .. .. .. .. .. .. .. .. .. .. 32 21 5A 4F   ............2!ZO
00C0: 4E 45 20 4F 46 20 44 2D 2F 41 56 54 0D 20 31 37   NE�OF�D-/AVT.�17
00D0: 30 20 0D 50 0D 20 32 34 39 20 0D 33 21 5A 4F 4E   0�.P.�249�.3!ZON
00E0: 45 20 4F 46 20 44 2D 2F 41 56 54 0D 20 31 35 38   E�OF�D-/AVT.�158
00F0: 20 0D 50 0D 20 31 33 38 20 0D .. .. .. .. .. ..   �.P.�138�.......

This is the third and fourth entry.

00F0: .. .. .. .. .. .. .. .. .. .. 00 00 00 00 .. ..   ..........����..

  The remaining bytes are unused, and exist simply as  filler  to  pad  the
directory so as it takes up to its alloted space (recall it is one block of
254 bytes). Once the directory has ended,  the  real  file  information  is
stored. Since in this example the directory is only 1 block long, the  file
info starts at byte $00FE...

00F0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. 00 04   ..............�.
0100: 1A 00 1A 08 05 08 E0 00 FF C2 0D 85 0F 04 39 03   .�....����.�..9.

  The files are also stored so that they take up the full multiples of  254
bytes. This does result in a little dead space at  the  end  of  each  file
stored, but its a small price to pay for how easy it is  to  construct  and
break up files on a real C64.

  When an LNX file is created, a new file is created on the disk containing
all the necessary information about the files it is going to  contain  such
as  the  BASIC  program,  signature  and  central  directory.  The   header
track/sector link is then pointed to the beginning of the first  file.  The
last sector track/sector link of the first file  is  then  pointed  to  the
start of the second file and so on, until the  last  file  is  added.  This
method makes creating LNX's very quick!

  The advantage to this method is that *no* files are moved or  compressed,
they are simply "linked" together by changing the t/s links to  create  one
large file (hence the name LNX).

  REL file entries are a little more special. The first blocks of the  file
contain the side sector info, followed by  normal  program/data.  The  only
usefulness in containing this side-sector info is so that you don't have to
allocate them after extracting the file, but just change the t/s  links  to
point to the new records.

  One disadvantage to its use on the PC is the lack of a  better  laid  out
central directory, one that had the same number  of  bytes  used  for  each
entry, like the D64, T64, or ARK, and had a user-definable directory  size,
also like the D64/T64. That makes it difficult to add files to an  existing
container on a PC, but 64COPY and Star  Commander  can  add/delete  to  LNX
files.

---------------------------------------------------------------------------

What it takes to support LNX:

  There are many good points to the LNX format,  making  it  only  somewhat
difficult to support. LNX files contain a signature, have a  provision  for
multi-block directories, the files and directory are block-aligned  to  254
byte boundaries, REL files are handled, and you can  store  more  than  144
files (if you want to).

  There is one bad point to LNX files and that is the individual  directory
entry size is not set (like D64's 32 bytes). They are stored in ASCII (like
LBR format), making the entry size  variable.  This  makes  adding/deleting
files difficult in that the directory has to be re-written quite a bit.

  One other bad thing that has developed over time is that many people have
written their own "lynxing" programs, and have deviated from  the  standard
layout. There are many styles of LNX files, earlier versions being somewhat
different from the later ones, but more importantly is there are LNX  files
which don't work with the normal "Will Corley" unLYNXing utilities.

---------------------------------------------------------------------------

Overall Good/Bad of LNX Files:

  Good
  ----
  * Supports the standard 16-char filename,

  * Filenames padded with the standard $A0 character

  * Allows for directory customization, as zero-length files are allowed

  * Expandable central directory

  * Supports REL files

  * It is a very well established file format, many utilities available  to
    work with them

  * Has a file signature

  * Filenames can have 00's in them(?)



  Bad
  ---
  * There are too  many  LNX  programs  out  there,  too  many  LNX  header
    variations, and not all of the utilities make compatible LNX containers

  * Has a very badly laid-out header (ASCII,  not  binary  byte  oriented).
    Each directory entry has a variable length

  * It is not easy to re-write the header and central directory. With  file
    additions/deletions, it is *usually* necessary to re-write  the  entire
    file

  * Since files are stored in block sizes of 254-bytes,  each  stored  file
    usually has some extra lost space

  * Can't store special file attribute bits

  * Does not store GEOS


*** P00/S00/U00/R00 (Container files for the PC64 emulator)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Wolfgang Lorenz

  These files were created  for  use  in  the  PC64  emulator,  written  by
Wolfgang Lorenz. Each one has the  same  layout  with  the  filetype  being
stored in the DOS extension (i.e. Pxx is a PRG, Sxx is a SEQ, Uxx is a  USR
and Rxx is a RELative file), and the header is only 26 bytes long. This  is
a dump of a Pxx file (PRG)...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 46 69 6C 65 00 43 52 49 53 49 53 20 4D   C64File.CRISIS.M
0010: 4F 55 4E 54 41 49 4E 00 00 00 .. .. .. .. .. ..   OUNTAIN.........

  Bytes: $00-06: ASCII string "C64File"
             07: Always $00
          08-17: Filename in PETASCII, padded with $00  (not  $A0,  like  a
                 D64)
             18: Always $00
             19: REL file record size ($00 if not a REL file)
          1A-??: Program data

  The 'xx' in the extension of the file is usually 00, except when we  have
two DOS filenames which would be  the  same,  but  the  C64  filenames  are
different! If we have two C64 filenames which are the same,  they  *cannot*
co-exist in the same directory. If we have two files which do convert  down
to be the same DOS filename, the extension is incremented until  an  unused
one is found (x01, x02, x03, up to x99). We can have up to 99 different C64
files with the same corresponding DOS names as  that's  all  the  extension
will hold (from P00 to P99).

  Each PC64 file only has one entry, there  are  no  multi-file  containers
allowed. This could result in a large number of these files in a directory,
even for only a few programs, as each C64 file will result in a  PC64  file
entry. The best use for a PC64 file is a  single-file  program,  one  which
does not load anything else.

  The DOS filename is generated by an algorithm used  inside  PC64  when  a
file needs to be created. It compresses the 16-byte name down to  one  that
fits the DOS 8 character size limitation.

  One thing which most people might not know is  you  *musn't*  rename  the
P/S/R/U DOS files. If you do, PC64 won't be able to load  them.  When  PC64
goes searching for files, it takes the 16-byte C64 filename, does its magic
to reduce it to 8.3, then looks to see which  DOS  files  match.  Remember,
there could be several files with  the  same  8  character  name,  but  the
extensions will be P00, P01, P02 etc. If it  can't  find  the  16-byte  C64
filename in amongst those that match, it will report a  "File  not  found".
I've tried this with the DOS version (PC64 1.20)  and  it  does  report  an
error locating the file, both in the PC64 File Manager and the 64  emulator
window.

---------------------------------------------------------------------------

What it takes to support PC64 files:

  The biggest benefit to this format is that the layout and usage is fairly
simple to implement. With a consistent  26-byte  header  and  a  signature,
there's very little difficulty in  working  with  them.  Also,  PC64  files
perform best when used on single-file games as they have *no* wasted space.

  One good design aspect of PC64 files is how REL files are supported. LNX,
D64 and ARK all require storage of the side sectors, either  preceeding  or
following the file. R00 does not  need  to  store  these,  making  it  more
efficient.

  The biggest drawback to this format is when converting  small  C64  files
(those of only a few sectors), you could waste hard disk  space  due  to  a
large DOS "slack" area. When DOS stores files of any size, each  one  takes
up a minimum  of  one  cluster,  which  on  small  drives  may  only  be  2
kb/cluster, but on vary large disks could be as high as 32 kb per  cluster.
Any file which is only a few Kb would, on the large disks, only use a small
portion of the total cluster, and thus a lot of wasted  DOS  storage  space
results.

  Another drawback (not obvious right away) is since some games are made up
of a large number of files or varying sizes, it would be best to store each
game in a different sub-directory. If you don't, then you might not be sure
what files belong to what programs, and if you ever want to give a  program
to someone else, there would be  difficulties  re-assembling  the  program.
This makes file management much more user intensive. The D64  format  seems
to be the best one for multi-file games.

  The last negative is that GEOS files cannot be put into the PC64  format.
They must reside on a native D64 disk in order to work.

---------------------------------------------------------------------------

Overall Good/Bad of PC64 Files:


  Good
  ----
  * Has a 16 character filename

  * Filetype is available in the DOS file extension

  * Can easily calculate the file size of the C64 file from  the  DOS  file
    size (DOS size - 26)

  * Efficiently supports 1541 REL files  (R00)  i.e.  no  side-sector  info
    needed (unlike LNX and ARK)

  * A very simple, easy to support file header

  * Can have multiple C64 files with the same name in a DOS directory since
    the file extension will simply change slightly

  * Due to each P00 being a separate DOS file,  the  emulators  can  easily
    rewrite  any  P00  file  they  need  to.  This  can   be   useful   for
    debugging/cracking etc. This is not really an intentional *file* design
    benefit but only an emulator side effect. However it could be useful



  Bad
  ---
  * Filenames are padded with $00, not the standard $A0 character

  * No directory customization, as each PC64 file only holds one C64 file

  * Since the filetype is the DOS  extension,  no  special  attribute  bits
    (write-protect) or non-standard file types (DEL) are kept

  * Unless the user keeps the P00 files organized, you can end  up  with  a
    mass of confusing files in one directory. File management  is  crucial,
    especially with PC64 files. It is best to keep each multi-file  program
    in separate directories. However, each DOS  directory  entry  used  for
    organisational purposes also takes up space.

  * Not yet as widely supported as D64 or T64

  * No GEOS VLIR file structure support

  * No labels/description field in the file header

  * No multi-file support (since it wasn't designed to do this)

  * Each file contains a separate C64 name, and in order to get a  list  of
    all the real C64 names, *each* file must be read  individually  to  get
    this

  * Can't rename the DOS P00 file since PC64 depends on the filename  being
    an algorithmic reduction of the C64 filename. Changing it  likely  will
    likely render the file useless to PC64

  * No 00's allowed in filenames, as this is the truncation character

  * I don't think PC64/WIN supports the original PC64/DOS files

  * Depending on the PC64 filesize and the  DOS  hard  disk  cluster  size,
    there  could  be  significant  cluster  slack-space  loss,   especially
    noticible with many average-size P00 files

    This last detail is the most  insidious,  and  the  most  difficult  to
    explain. The easiest way to check it out is the following:

      1. Generate P00 files from games  in  other  images  like  D64  files
         (multi-file games of course).

      2. Figure out how many  clusters  *each*  file  takes  based  on  the
         present cluster size (this is the more difficult  part),  for  the
         whole directory of P00 files. Multiply the resulting cluster count
         by the cluster size. This is the *actual*  useage  in  hard  drive
         space that the P00 files take.

      3. Total up, in bytes, the whole P00 directory.

      4. Divide the number from (3) into (2) (and multiply by 100)  to  get
         the percentage efficiency. Subtract this number from  100  to  get
         the %-Loss.


    From some experiments I did, I came up with some example %-loss charts,
    one for P00 and one for D64 based on cluster sizes from 32k (large hard
    disk) down to 512 bytes (floppy disk).



        100 P00 files, totalling 1,829,629 bytes.

        Cluster    Actual
         Size      Usage     %-Loss
        -------  ---------   ------
         32k     3,899,392   53.1%
         16k     2,719,744   32.7%
          8k     2,285,568   19.9%
          4k     2,068,480   11.5%
          2k     1,943,552    6.0%
          1k     1,886,208    3.0%
         512     1,854,976    1.4%

     Given what would seem to be average hard disk sizes, I would  estimate
     the %-loss for P00 files to be around 20-40%. When you  have  a  large
     number of P00 files, you are wasting a lot of hard disk space.



         12 D64 files,  totalling  2,098,176  bytes  (these  were  used  to
         generate the above 100 P00 files). Note that these D64 files  were
         *not* necessarily full, but it is assumed that they  are  used  to
         capacity. If they are not, then the %-Loss must be increased.

         Cluster     Actual
          Size       Usage    %-Loss
         -------   ---------  ------
           32k     2,359,296  11.1%
           16k     2,162,688   3.0%
            8k     2,162,688   3.0%
            4k     2,113,536   0.7%
            2k     2,113,536   0.7%
            1k     2,101,248   0.2%
           512     2,101,248   0.2%


     From the above charts, it becomes clear that D64, regardless  of  hard
     disk size, is *much* more efficient at storing files (average of  1-3%
     loss, assuming the files  are  full).  In  fact,  almost  *any*  other
     filetype (T64, LNX, ARK) will be more efficient than  P00  since  they
     are usually much larger than a single cluster.

*** C64 (PC64 saved-session file)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Wolfgang Lorenz

  These are files created when you save a C64 window under PC64 (DOS only).
It consists of a 64k memory dump, color ram dump, I/O ports,  the  name  of
the ROMs you were using at the time, and user-setable options. Typical size
is around 69091 bytes.

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
       -----------------------------------------------
00000: 43 36 34 49 6D 61 67 65 00 .. .. .. .. .. .. ..   C64Image........
 ...
00000: .. .. .. .. .. .. .. .. .. 2F 37 00 AA B1 91 B3
00010: 22 22 00 00 4C 00 FF 00 04 00 00 00 00 00 00 19
00020: 16 00 0A 76 A3 00 00 00 00 00 00 76 A3 B3 BD 00
00030: 00 00 00 00 01 08 03 08 03 08 03 08 00 A0 00 00
 ...
10000: .. .. .. .. .. .. .. .. .. 0E 0E 0E 0E 0E 0E 0E
10010: 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E
10020: 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E
10030: 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E
 ...
10400: .. .. .. .. .. .. .. .. .. 0E 0E 0E 0E 06 06 06
10410: 06 00 00 00 00 00 00 00 00 00 00 C8 00 20 34 37
10420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
10430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
10440: 20 20 20 20 20 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E
 ...

  Byte: $00000-00008: The signature "C64Image" followed by a $00. Note  the
                      varying case of the text.
         00009-10008: Main memory of the C64 (64K, $0000-FFFF)
         10009-10408: Color memory (1k, $D800-DBFF)
         10409-?????: I/O memory and user-selectable options (ROM  version,
                      etc). The ????? means the end  of  the  file  is  not
                      known, since these files can vary in length.

  Since these files are only supported by PC64 for DOS (*NOT*  for  Win95),
it is not worth getting too much into  the  layout.  I  was  attempting  to
decipher the layout of the I/O ports and options area but decided it wasn't
worth it.

*** 64x (PC64/DOS ROM files)
*** Document revision: 1.1
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Wolfgang Lorenz

  These files, used by the PC64 emulator, are simply the BASIC, KERNEL  and
CHARACTER ROM's in electronic form. There contain no signature, but  rather
are raw binary dumps of either the ROM's contained in the C64 computer,  or
other customized ROM's.

  There are three different files,  denoted  by  the  change  in  the  last
character of the file extension...

  64B - BASIC ROM ('B'), This is the ROM from  $A000-BFFF,  which  contains
        the BASIC interpreter. It is always 8192 bytes.
  64C - CHARACTER ROM ('C') This is the ROM from $D000-DFFF, which contains
        the character sets. It is always 4096 bytes.
  64K - KERNEL ROM ('K'). This is the ROM from $E000-FFFF,  which  contains
        all the KERNEL calls and I/O routines. It is always 8192 bytes.

*** C64 (PCLINK container files)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Markus Mehring

  This is another "C64-to-PC" connection program. It was written  by  Peter
Jakab in 1994. With it and a custom interface cable, you  could  link  your
C64 and PC together to use the PC's hard disk  as  a  C64  storage  device.
Files you wanted to be seen would have to be in this ".C64" format.  (Note:
don't confuse these files with PC64's .C64 saved-session files)

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
    -----------------------------------------------   ----------------
00: 38 CD 81 06 50 43 4C 49 4E 4B 20 20 20 00 00 00   8́�PCLINK������
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
20: 00 00 00 00 01 08 0B 08 00 00 9E 32 30 36 31 00   �����������2061�
30: 00 00 78 A2 FB 9A 20 18 E5 20 55 10 A9 00 8D 20   ��x�������U�����

  Bytes: $00-01: PCLINK file signature ($38 $CD)
             02: PRG filetype ($81, *not* $82  as  you  would  expect).  No
                 other filetype was supported.
             03: Filename length ($06)
          04-13: Filename (16 bytes allotted, name padded with $00's)
          14-23: Miscellaneous field (16 bytes allotted) - this  was  never
                 implemented.
            24-: File data starts here

  PCLINK also supports DOS BINARY files if their filename  started  with  a
"#". These files would have no header.

*** PCV (PCVIC VIC-20 emulator saved-session files)
*** Document revision: 1.1
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: unknown

  This is another snapshot file, generated by the  PCVIC  VIC-20  emulator,
written by BW Van Schooten. This description is based on the version 1.0 of
the PCVIC emulator.

  Bytes: $0000-0015 - PCVIC signature string "PCVIC system snapshot",  with
                      a zero terminator
          0016-0017 - Version#, minor (0-99)/major (0-255).
          0018-0019 - Size of register state block (not including this size
                      value)
          001A-XXXX - Register state block, contains system register values
                      and memory expansion settings.
          XXXX-MMMM - Byte-run compression of VIC memory. This excludes
                      the standard ROM areas $8000-8FFF and $C000-CFFF
        (END-1)-END - Two-byte checksum of the data from $0016 to  the  end
                      of the MMMM section.

  Here is most of the contents of the register state block:

     Byte: $00-01 - 6502 X register in low byte, high byte set to 0
            02-03 - 6502 Y register in low byte, high byte set to 0
            04-05 - 6502 SP (stack pointer) in low byte, high byte set to 1
               06 - Unused
               07 - 6502 auxiliary flags. Bits 2-5 are bits 2-5 of the  CPU
                    flag register. All other bits set to 0.

            08-09 - Scanline
                      0-263 - NTSC
                      0-311 - PAL

               0A - VIA1 IFR register
               0B - VIA1 IER register
               0C - VIA2 IFR register
               0D - VIA2 IER register
               0E - VIA1 IRB port
               0F - VIA1 ORB port
               10 - VIA1 IRA port
               11 - VIA1 ORA port
               12 - VIA2 IRB port
               13 - VIA2 ORB port
               14 - VIA2 IRA port
               15 - VIA2 ORA port

               16 - Timer Status. 1=Active, 0=Inactive
                     Bit: 0 - VIA1 Timer 1
                          1 - VIA1 Timer 2
                          2 - VIA2 Timer 1
                          3 - VIA2 Timer 2
                        4-7 - Future expansion, set to 0
               17 - VIA1 Timer 2 Latch
               18 - VIA2 Timer 2 Latch
               19 - VIA1 Timer 2 Timer
               1A - VIA2 Timer 2 Timer

               1B - NMI Flank.
                     0 - NMI was low since last time NMI was sampled
                     1 - NMI was high since last time NMI was sampled
               1C - Memory configuration. If bit set, area is RAM.  If  bit
                    clear, area is either  ROM  or  unavailable.  Each  bit
                    represents an 8Kb block of RAM.
                     Bit: 0 - $0000-1FFF*
                          1 -  2000-3FFF
                          2 -  4000-5FFF
                          3 -  6000-7FFF
                          4 - (always set to 0, ROM)
                          5 -  A000-BFFF
                          6 - (always set to 0, ROM)
                          7 - (always set to 0, ROM)
                     *Note:  The  areas   0000-03ff   and   1000-2000   are
                      considered to be  always  occupied  by  RAM.  For  an
                      unexpanded Vic, all blocks are set to 0. Setting only
                      the low block (bit 0) it  to  1  results  in  3K  RAM
                      expansion.
            1D-1E - 6502 PC (program counter) register
            1F-20 - 6502 main flags
                     Bit: 00 - Don't care
                          01 - Don't care
                          02 - Don't care
                          03 - Don't care
                          04 - Don't care
                          05 - Don't care
                          06 - Zero flag
                          07 - Sign flag
                          08 - Carry flag
                          09 - Set to 0
                          10 - Set to 0
                          11 - Set to 0
                          12 - Set to 0
                          13 - Set to 0
                          14 - Overlfow flag
                          15 - Set to 0
               21 - 6502 A register
               22 - Scan count. CPU cylce count within scan line.
                       0 - End of scan line
                     129 (NTSC) or 131 (PAL) - Start of scan line
               23 - END of register state block.

  The rest of the file consists of  the  RAM  and  I/O  areas.  These  are
byterun compressed, and require source code to  decode  properly,  which  I
will not get into here.

*** S20 (Phau Zeh VIC-20 emulator saved-session files)
*** Document revision: 1.2
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: unknown

  This file is created when you save a  session  in  the  Phau  Zeh  VIC-20
emulator (written by Arne Bockholdt). Like all emulator  saved-session,  it
contains all zero-page RAM, CPU registers, RAM and I/O registers. In  order
for the Phau Zeh emulator to recognize its saved-sessions, it must be saved
with the "S20" extension.

  This document is based on the 0.9.5 revision of the S20  layout,  so  the
actual 1.0 release might be different. The minimum S20 file  size  is  9286
bytes (based on an un-enpanded VIC-20)  and  the  largest  is  36934  bytes
(based on a fully-expanded VIC-20).

   Bytes: $0000-000E - S20 signature string "VIC-20 SNAPSHOT"
                000F - S20 revision
                         $01 - version 0.9.5
                          00, 02-FF - Reserved
                0010 - Machine
                         $00 - Original VIC-20
                          01 - Phau Zeh
                          02 - V20
                          03 - Mac VIC-20 emulator
                          04-FF - Future Expansion (set to $00)
                0011 - Miscellaneous Info. If Byte $16 is set  to  1  (Phau
                       Zeh emu), it is sub-version of the emulator.
                         With $16 set to 1:
                         $01 - PZL
                          02 - PZW
                          00, 03-FF - Future expansion (set to $00)
           0012-0013 - Future Expansion (set to $00)
           0014-0015 - Memory areas saved (in HI-LO format). The  bit  will
                       be set if the memory area is saved,  clear  if  not.
                       Each bit of this  word  represents  a  4Kb  area  of
                       memory. The ROM memory locations  should  always  be
                       clear (not saved), and positions 1 and 9 must always
                       be set and saved.
                         Bit: 00 - RAM $0400-0FFF (only 3Kb for this one)
                              01 - RAM $1000-1FFF
                              02 - RAM $2000-2FFF
                              ...
                              15 - RAM $F000-FFFF
           0016-0017 - VIC-20 ROM memory (in HI-LO format). The bit will be
                       set if the ROM area is saved, clear if not. Each bit
                       represents 4Kb of ROM. VIC-20 ROM  memory  locations
                       should be set to 1, and setting  bits  0  and  1  on
                       would make no sense as  ROM  can't  exist  in  those
                       areas.
                         Bit: 00 - ROM $0000-0FFF
                              01 - ROM $1000-1FFF
                              02 - ROM $2000-2FFF
                              ...
                              15 - ROM $F000-FFFF
                0018 - RAM expansion installed
                        $00 - No expansion
                         03 - 3Kb installed
                         08 - 8Kb installed
                         10 - 16Kb installed
                         18 - 24Kb installed
                         All other values invalid (future expansion)
                0019 - Future expansion (set to $00)

           001A-001B - 6502 Instruction Pointer (HI-LO format)
                001C - 6502 Flag register
                        Bit 0 - Carry Flag
                            1 - Zero Flag
                            2 - Interrupt Flag
                            3 - Decimal Flag
                            4 - Break Flag
                            5 - Always set to 1
                            6 - Overflow Flag
                            7 - Sign Flag
                001D - 6502 Stack Pointer
                001E - 6502 A Register
                001F - 6502 X Register
                0020 - 6502 Y Register
                0021 - NMI status
                        Bit 0 - Set if NMI info valid, clear otherwise
                            7 - Clear if NMI low, set if NMI high
                            All other bits unused.

           0022-0023 - VIA1 Timer 1 Value (HI-LO format)
           0024-0025 - VIA1 Timer 1 Latch (HI-LO format)
           0026-0027 - VIA1 Timer 2 Value (HI-LO format)
                0028 - VIA1 Timer 2 Latch
           0029-002A - VIA2 Timer 1 Value (HI-LO format)
           002B-002C - VIA2 Timer 1 Latch (HI-LO format)
           002D-002E - VIA2 Timer 2 Value (HI-LO format)
                002F - VIA2 Timer 2 Latch
                0030 - Set Interrupt Flag Status bits. 0 = don't set  flag,
                       1 = set flag.
                         Bit 0 - VIA1 Timer 1
                             1 - VIA1 Timer 2
                             2 - VIA2 Timer 1
                             3 - VIA2 Timer 2
                             All other bits clear (future expansion)
                0031 - Future Expansion (set to $00)
                0032 - VIA  Port  Register  Status.  Tells  emulator  which
                       registers are saved in the file.
                        $00 - Nothing saved (not recommended)
                         01 - IR ports saved to the following 4 bytes
                         02 - OR ports saved to the following 4 bytes
                         03-FF - Future expansion
                0033 - VIA1 IRA or ORA (depends on the value in $0032)
                0034 - VIA1 IRB or ORB (depends on the value in $0032)
                0035 - VIA2 IRA or ORA (depends on the value in $0032)
                0036 - VIA2 IRB or ORB (depends on the value in $0032)
           0037-003A - Future expansion (set to $00)

                003B - Video Mode
                        $00 - PAL (6561)
                         01 - NTSC (6560)
                         02-FF - Reserved
           003C-003D - Current scanline
                         PAL: 0-311
                        NTSC: 0-260
                003E - Cycles since  last  scanline  change.  This  is  the
                       number of cycles passed since the lasy scanline  was
                       drawn, or the scanline counter was incremented.
                         PAL: 0-70
                        NTSC: 0-64
           003F-0042 - Future expansion (set to $00)

           0043-0442 - Zero Page RAM $0000-03FF (must be in file)

           0443-1042 - RAM locations $0400-0FFF  contents  (optional,  only
                       when $0014-0015 bit 0 is set)
           1043-2042
       (or)0443-1442 - RAM locations $1000-1FFF (must be in file)
                 ... - (4Kb RAM  blocks  continue,  depending  on  the  bit
                       pattern set in $0014-0015)

         (END-2)-END - Last three bytes set to $FF.

*** Power 64 RAM Snapshot File (C64 emulator on Apple Power Macintosh)
*** Document revision: 1.2
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Peter Weighill

  These files, similar in nature to  PC64's  .C64  files,  are  a  complete
memory dump of the 64K RAM, color RAM, and all I/O ports and CPU registers.
Presently, this format is supported by the  Power64  emulator  and  may  be
added to future versions of the VICE  emulator.  The  file  size  is  69888
bytes.

  The format for RAM Snapshots was adapted from a suggestion by Jouko Valta
for the Vice Emulator on Unix systems.

* Note: All multi-byte values are stored in  big-endian  format  (high/low)
rather than in the little-endian format (low/high) used by the  C64,  since
the Macintosh stores values this way.

No sample memory dump is available.

Byte: $00000-00005: Magic Header (at present $43, $42, $4D, $64, $00,  $00)
                    or "CBM",$64,$00,$00
       00006-00007: Reserved (should be $00, $00)
       00008-00009: Version major and minor ($01, $00, or 1.0)
             0000A: Emulator snapshot ID (Power64 is $2F)
             0000B: Snapshot type (presently $00)
       0000C-0000D: Offset in bytes (high/low), to RAM image  in  snapshot.
                    The header size is presently 256 bytes, so  the  values
                    are $01, $00.
       0000E-0000F: RAM image size (in Kbytes, presently $00,  $40,  or  64
                    Kbytes)
       00010-00011: REU RAM image size (in Kbytes, presently $00, $00)
       00012-0001F: Reserved (should be $00, $00)
       00020-00025: Configuration bit masks (presently all $00)
             00026: I/O RAM size (Power64 value $01)
                       Bit 0: I/O data available (0 = no)
                     1 and 2: Video Display Controller RAM
                              00 = none
                              01 = 16 Kb
                              10 = 64 Kb
                              11 = 32 Kb)
             00027: CPU's available (Power64 value $01)
                    Bit 0: 6502
                        1: Z80
                        2: REC
       00028-00029: 6502 program counter (high/low)
       0002A-0002C: A, X and Y CPU registers
             0002D: 6502 flags register
             0002E: 6502 stack pointer (SP)
             0002F: 6502 I/O port
       00030-0003F: Z80 registers (not used yet, should be $00)
       00040-0004F: REC registers (not used yet, should be $00)
             00050: C64 kernal ID byte (not used yet)
             00051: Kernal patch ID for fastloaders, etc. (not used yet)
       00052-00053: Kernal patch version ID (not used)
       00054-0007F: Kernal version information (not used yet)
       00080-000FF: Miscellaneous info on peripherals (not used yet)
       00100-100FF: 64Kb RAM area (size depends on value in 0000E-0000F)
       10100-110FF: Contents of the C64 I/O area

*** REL (RELative file layout)
*** Document revision: 1.1
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Immers/Neufeld "Inside Commodore DOS"

  This is a filetype native to CBM drive (random access)  devices.  On  the
surface it seems similar to all other filetypes, especially  SEQ,  but  was
designed to make access to data *anywhere* in the file very fast.

  We start by examining a REL file directory entry...

00: 00 00 84 11 02 41 44 44 49 54 49 4F 4E 41 4C 20  ���..ADDITIONAL�
10: 49 4E 46 4F A0 11 0C FE 00 00 00 00 00 00 61 01  INFO�..�������a.

     Bit:$00-01: Track/Sector location of next directory sector ($00 $00 if
                 not the first entry in the sector)
             02: File type.
                 Typical values for this location are:
                   $00 - Scratched (deleted file entry)
                    80 - DEL
                    81 - SEQ
                    82 - PRG
                    83 - USR
                    84 - REL
                 Bit 0-3: The actual filetype
                          000 (0) - DEL
                          001 (1) - SEQ
                          010 (2) - PRG
                          011 (3) - USR
                          100 (4) - REL
                          Values 5-15 are illegal, but if used will produce
                          very strange results. The 1541 is inconsistent in
                          how it treats these bits. Some routines use all 4
                          bits, others ignore bit 3,  resulting  in  values
                          from 0-7.
                 Bit   4: Not used
                 Bit   5: Used only during SAVE-@ replacement
                 Bit   6: Locked flag (Set produces ">" locked files)
                 Bit   7: Closed flag  (Not  set  produces  "*", or "splat"
                          files)
          03-04: Track/sector location of first sector of file
          05-14: 16 character filename (in PETASCII, padded with $A0)
          15-16: Track/Sector location of first side-sector block (REL file
                 only)
             17: REL file record length (REL file only, max. value 254)
          18-1D: Unused (except with GEOS disks)
          1E-1F: File size in sectors, low/high byte  order  ($1E+$1F*256).
                 The approx. filesize in bytes is <= #sectors * 254

  The third byte ($84) indicates this entry is a  REL  file  and  that  the
three normally empty entries at offset $15, $16 and $17  are  now  used  as
they are explained above. It's the sector chain that this entry  points  to
(called the SIDE SECTORS)  which  are  of  interest  here  (in  this  case,
#17/#12). Here is a dump of that sector...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 0C 13 00 FE 11 0C 0C 13 06 09 00 00 00 00 00 00  ����������������
0010: 11 02 11 0D 11 03 11 0E 11 04 11 0F 11 05 11 10  ����������������
0020: 11 06 11 11 11 07 11 12 11 08 11 13 11 09 11 14  ����������������
0030: 11 0A 11 0B 10 00 10 0A 10 14 10 08 10 12 10 06  ����������������
0040: 10 10 10 04 10 0E 10 02 10 0C 10 01 10 0B 10 03  ����������������
0050: 10 0D 10 05 10 0F 10 07 10 11 10 09 10 13 0F 07  ����������������
0060: 0F 11 0F 05 0F 0F 0F 03 0F 0D 0F 01 0F 0B 0F 00  ����������������
0070: 0F 0A 0F 14 0F 08 0F 12 0F 06 0F 10 0F 04 0F 0E  ����������������
0080: 0F 02 0F 0C 0F 09 0F 13 0E 07 0E 11 0E 05 0E 0F  ����������������
0090: 0E 03 0E 0D 0E 01 0E 0B 0E 00 0E 0A 0E 14 0E 08  ����������������
00A0: 0E 12 0E 06 0E 10 0E 04 0E 0E 0E 02 0E 0C 0E 09  ����������������
00B0: 0E 13 0D 07 0D 11 0D 05 0D 0F 0D 03 0D 0D 0D 01  ����������������
00C0: 0D 0B 0D 00 0D 0A 0D 14 0D 08 0D 12 0D 06 0D 10  ����������������
00D0: 0D 04 0D 0E 0D 02 0D 0C 0D 09 0D 13 0C 07 0C 11  ����������������
00E0: 0C 05 0C 0F 0C 03 0C 0D 0C 01 0C 0B 0C 00 0C 0A  ����������������
00F0: 0C 14 0C 08 0C 12 0C 06 0C 10 0C 04 0C 0E 0C 02  ����������������

  Bytes:   $00: Track location of next side-sector ($00 if last sector)
            01: Sector location of next side-sector
            02: Side-sector block number (first sector is $00, the next  is
                $01, then $02, etc)
            03: REL file RECORD size (from directory entry, max. value 254)
         04-0F: Track/sector locations of the six other side-sectors.  Note
                the first entry is this very sector we  have  listed  here.
                The next is the next t/s listed at  the  beginning  of  the
                sector. All of this information must be correct. If one  of
                these chains is $00/$00, then we have no more side sectors.
                Also, all of these (up to six) side sectors must  have  the
                same values in this range.
         10-FF: T/S chains of *each* sector of the data  portion.  When  we
                get a $00/$00, we are at the end of the chain.

  If the speed advantage regarding this type file file isn't  obvious  yet,
consider the following scenario... If we need to access  record  4000,  its
only a couple of calculations to see how many bytes into the file it is...

  4000 * "record length" (254) = byte offset

  Once we know this, we can calculate how many sectors into  the  file  the
  record is...

  byte offset / 254 = # of sectors into REL file

  The divisor value "254" in the above  formula  is  the  number  of  bytes
useable in each sector (256 bytes less the 2 bytes used for the forward t/s
pointer) and has no relation to the "max REL record length".

  Now that we know the number  of  sectors,  we  can  look  it  up  in  our
side-sector tables to see where the record is. The speed of this system  is
truly amazing, given the era of the C64, and a floppy drive.

*** SDA (Self-Dissolving compressed Archive)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Chris Smeets (source code)

  The name stands for "Self-Dissolving Archive", and thats exactly what  it
does. There is a decompression engine at the beginning of the  file  called
by a BASIC SYS command. It will decompress all the files contained  in  the
archive to whatever device you specify, or disk you select.

  I have  found  two  somewhat  different  SDA  files,  one  has  a  longer
decompression header than the other. They  would  appear  to  be  different
revisions of the decompression engine,  likely  version  1  and  version  2
files, but they all seem to be self-extracting ARC files.  There  are  also
different revisions of the version 2 header, where the newer ones allow for
the decompression of more compressed ARC formats. The HEX dump below  is  a
sample of the shorter version of SDA...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 01 08 0D 08 0A 00 9E 28 32 30 36 33 29 00 00 00   ....���(2063)���

  which decodes to...

10 SYS(2063)

  The starting location of  the  first  file  in  an  SDA  archive  can  be
calculated given the BASIC header from above. Here's the steps...

  1. Get the line number of the BASIC SYS statement (here it's 10,  in  the
     longer one its 13)

  2. Subtract 6, and multiply by 254 (result 1016, or $03F8)

  3. If the first number of the SYS call is a 7 (in our  case  it's  a  2),
     then subtract 1 from the previous result. A 7 indicates  it's  a  C128
     archive, a 2 means it's a C64 archive.

  4. You now have the starting position into the SDA archive  to  find  the
     first file.

  From here on, the file has the same layout as an ARC. See the  ARC  topic
for a better description.

  There are some exceptions to the above, expecially with the C128 versions
of files. If the first numeric value of the SYS call is a 7, we have a C128
file. If this is the case, you can assume that the line number value is 15,
rather than using the line number in the BASIC header. Some files I've seen
don't have the proper value for the line number.

  The easiest way the decompress these files is to  use  64COPY.  There  is
also C code available on the High Voltage CD #2 to allow you to  decompress
these files on a PC.

  SDA files can also be decompressed by running it on either a real C64  or
an emulator window, and let the file undo itself to a disk image. ARC files
are decompressable using the C64 program called ARC 2.50.

*** SFX (SelF-eXtracting LHA/LZH compressed files)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Chris Smeets

  These  files  are  actually  LHA  archives,  except  there  they  have  a
decompressor program prepended to the file,  capable  of  decompressing  on
either a C64 or a C128, independant of the load address. The  beginning  of
the file is a BASIC program (with an unusual load address):

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
       -----------------------------------------------
00000: 01 1C 28 1C C6 07 97 32 30 2C 30 3A 8B C2 28 32 <-Note load address
00010: 30 29 B2 30 A7 FE 02 30 3A 9E C2 28 34 36 29 AC
00020: 32 35 36 AA 36 36 3A 80 00 3C 1C D0 07 9E C2 28
00030: 34 34 29 AC 32 35 36 AA 36 36 3A 80 00 00 00 ..

which when decoded looks like this:

1990 POKE20,0:IFPEEK(20)=0THEN<254><2>0:SYSPEEK(46)*256+66:END
2000 SYSPEEK(44)*256+66:END

  This was decoded on a C64... the two codes in line 1990,  the  <254>  and
<2>0 are not decodable on the C64, but are on  the  C128.  The  first  line
checks for whether it is running on a C64 or a 128. If it is a C64, it will
execute the SYS call line 2000, otherwise it executes the SYS on line 1990.

  Later on in the header, we have the copyright  message.  Any  SFX  should
have this message.

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
       -----------------------------------------------   ----------------
00D20: .. .. .. .. .. .. .. .. .. .. .. 43 36 34 2F 43   ...........C64/C
00D30: 31 32 38 20 53 45 4C 46 20 45 58 54 52 41 43 54   128 SELF EXTRACT
00D40: 49 4E 47 20 4C 48 41 52 43 48 49 56 45 0D 43 4F   ING LHARCHIVE.CO
00D50: 50 59 52 49 47 48 54 20 31 39 39 30 20 2D 20 43   PYRIGHT 1990 - C
00D60: 2E 53 4D 45 45 54 53 0D 54 4F 52 4F 4E 54 4F 2C   .SMEETS.TORONTO,
00D70: 43 41 4E 41 44 41 .. .. .. .. .. .. .. .. .. ..   CANADA..

  I have seen two different versions of the header, one which is 3711 bytes
long, and the other standard one which is 3721 bytes long. The only way  to
tell them apart is to examine the byte value at offset $0067 into the file.
If it is $CE, then we have the 3721 byte header. If it is $C4, then  it  is
the shorter 3711 byte header. Notice that the difference  between  the  two
values is 10, the same as the header difference.

  Typically, at address $0E89 (3721 bytes into the file) or at $0E7F  (3711
bytes in) you will find the beginning of the LHA archive,  denoted  by  two
bytes and the signature '-LH1-'.

00E80: .. .. .. .. .. .. .. .. .. 1E B6 2D 6C 68 31 2D   ...........-LH1-

  *ALL* LHA/LZH archives  have  this  type  of  signature  string  in  them
('-lhx-', where x is the type of compression used, with C64 archives  being
1, and most PC archives being 5). The actual archive starts 2 bytes  before
this string is found, and goes to the end of  the  file.  If  you  want  to
convert them to LHA, you can chop the front end off the  file  (up  to  two
bytes before the -lhx- string), and rename it to an LHA. It will then be  a
normal LHA file.

  Another way to handle SFX's is  to  extract  them  with  Star  LHA.  This
program handles both LHA and SFX formats, as they are basically  the  same.
Extract them as you would an LHA file (StarLHA -x xxxxxxxx.SFX).  For  more
information on the LHA/LZH layout, refer to the LHA topic.

*** SID/PSID (Various SIDPlay / PlaySID Formats)
*** Document revision: 1.2
*** Last updated: March 15, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: LaLa,
                          Peter Weighill

  The data files used by SIDPLAY contain binary C64 data and  music  player
machine code. Both, the programmer  on  the  C64  and  this  emulator  need
information on how to access the code inside the binary file.  That  means,
information like the memory location to load the file  to,  the  number  of
tunes, the starting address of the executable  code  and  its  subroutines.
This specific information has to be delivered in either a separate  file  -
which is often called info file - or in form of  a  header  in  the  single
binary data file. A standalone C64 data file without a header or without  a
corresponding info file is considered invalid.

  It is recommended that you get accustomed to one-file sidtunes  with  the
*.sid extension. For raw C64 binary files the extension  .c64  or  .prg  is
preferred in order to be able to assign a .sid extension to the  additional
info file.

Supported and merely used file formats are:

  PlaySID single-file-format (widely known as PSID)

  PlaySID info-file-format (Raw C64 binary file plus Amiga  Workbench  icon
  tooltype file .INFO)

  SIDPLAY info-file-format (Raw C64 binary file  plus  SIDPLAY  ASCII  text
  info file, previously .SID)

  C64 Sidplayer format (.MUS/.STR)

  Raw data or PSID files have appeared as *.data, *.psid or psid.*.


DAT files

  The .DAT file name extension has been introduced by the early versions of
SIDPLAY/DOS. It has never been used to specify a file format. Its main  use
has been in assigning a unique file name extension to any sidtune file, but
especially raw C64 data files, and allowing to use .SID for additional info
files.


INFO files

  These are Amiga Workbench tooltype icons containing binary graphics  data
and ASCII text information strings. They have been used by PlaySID and  are
supported by SIDPLAY. Their file name extension normally is .info or  .INF.
This is a two-file format. A separate C64 binary data file is required.  On
Amiga the  corresponding  C64  data  files  usually  haven't  had  filename
extensions. However, they might have been renamed on other systems.


SIDPLAY info files

  These are plain ASCII text  files  which  have  been  introduced  by  the
earlier versions of SIDPLAY/DOS. They are used to  be  able  to  alter  the
information inside with a normal ASCII text editor. They can  be  converted
to a single file that contains a binary header. This is a two-file  format.
A separate C64 binary data file is required. Notice that each pair of files
usually has the old DOS-naming of .SID for the info file and .DAT  for  the
C64 data file.

  The SIDPLAY info file is derived from the information inside the  PlaySID
one-file format. It is structured like this:

    SIDPLAY INFOFILE
    ADDRESS=<loadAddress>,<initAddress>,<playAddress>
    SONGS=<total>[,<start>]
    SPEED=<hexValue>
    NAME=<name of music/tune>
    AUTHOR=<name of author/composer>
    COPYRIGHT=<year/name of copyright owner/company>
    RELEASED=<year/name of copyright owner/company>
    SIDSONG=<YES|NO>
    RELOC=<hexValue>,<hexValue>
    CLOCK=<PAL|NTSC>
    SIDMODEL=<6581|8580>
    COMPATIBILITY=<R64|BASIC>

  The first line of the text containing ``SIDPLAY INFOFILE'' is  only  used
to identify the type of file.

    ADDRESS=<loadAddress>,<initAddress>,<playAddress>

  Each specified address is a 16-bit effective C64 memory location in  case
insensitive hexa-decimal notation without a prefix, e.g. C000 or E012,  but
neither $FCE2 nor 0xFCE2. Preceding zeroes are ignored.

<loadAddress> is the C64 memory location where  to  put  the  C64  data.  0
means, the data is in original C64 format, i.e. the first two bytes contain
the  little-endian  load  address  (low  byte,  high  byte).  Please  don't
explicitly specify the load address unless required for sure. If  the  load
address is explicitly specified,  some  sidtune  converters  and  utilities
conjecture that the C64 data lacks its load address. Hence they move it  in
front of the C64 data. This would create two redundant  bytes  if  the  C64
data already had a load address in the first two bytes. Additionally, those
extra bytes in the beginning can confuse disassemblers.

<initAddress> is the start address of  the  machine  code  subroutine  that
initializes a song by accepting the contents of the 8-bit 6510  Accumulator
as the song number  parameter.  0  means,  the  address  is  equal  to  the
effective load address.

<playAddress> is the start address of the machine code subroutine that  can
be  called  frequently  to  produce  a  continuous  sound.  0  means,   the
initialization subroutine is expected  to  install  an  interrupt  handler,
which then calls the music player. If so,  the  value  in  the  bank-select
register $01 determines whether the IRQ vector $0314/$0315 (Kernal-ROM  on)
or the IRQ vector $FFFE/$FFFF (Kernal-ROM off) is to be used.

    SONGS=<total>,[<start>]

<total> is the decimal number of songs  (or  sound  effects)  that  can  be
initialized by calling the init address. The minimum is 1.

<start> is the decimal number of the song to be  played  by  default.  This
value is meant as a proposal and is optional. It has a  default  of  1.  It
often specifies the first song you would hear upon starting the program  is
has been taken from.

    SPEED=<value>

<value> is a value in case  insensitive  hexa-decimal  notation  without  a
prefix. Preceding zeroes are ignored. The value contains information  about
the speed of each song. For each song a bit is reserved, bit 0 for song  1,
bit 1 for song 2, and so on. A  bit  set  to  0  means,  the  music  player
subroutine is called at 50 Hz. A bit set to 1  means,  the  real  speed  is
indicated by the CIA 1 Timer A $DC04/05, which defaults to 60  Hz.  To  not
break compatibility to the PlaySID formats, use a maximum of 32 bits, which
is equal to 32 songs. Due to a bug in PlaySID, the  PSID  format  can  only
handle up to 8 songs correctly. On the contrary, the SIDPLAY info format is
extended to 256 bits, which  is  equal  to  256  songs.  Examples:  SPEED=0
replays every song at 50 Hz speed. SPEED=1F replays  songs  1-5  at  60  Hz
speed, all other songs at 50 Hz speed.

    NAME=<name of music/tune>
    AUTHOR=<name of author/composer>
    RELEASED=<year/name of copyright owner/company>
    or
    COPYRIGHT=<year/name of copyright owner/company>

  These three fields are all plain ASCII text strings. There are limited to
a maximum of 80 characters each. To not break compatibility to the  PlaySID
formats, use a maximum of 31 characters.

    SIDSONG=<YES|NO>

  is used to indicate that the corresponding C64 data file is in (Enhanced)
Sidplayer file format. This field is optional and defaults to NO.

    RELOC=<hexValue>,<hexValue>

  is used to indicate a free memory range not used by the sid  tune.  (e.g.
  RELOC=04,65)

    CLOCK=<PAL|NTSC>

  is used to indicate the type of C64 the tune was original written for.

    SIDMODEL=<6581|8580>

  is used to indicate the type of sid chip the tune  was  original  written
  for.

    COMPATIBILITY=<R64|BASIC>

  is used to indicate the compatibility mode of the sid tune. Normally this
would not be included but is set to R64 when  the  tune  includes  "sample"
music and will only play correctly on a real c64 or a newer sidplayer. This
is set to BASIC when the .dat file contains BASIC code.

An example file ``EXAMPLE.SID'' may look like this:

    SIDPLAY INFOFILE
    ADDRESS=2AF0,3002,300C
    SONGS=3,2
    SPEED=0
    NAME=Example
    AUTHOR=Example
    RELEASED=199? (c) Example
    SIDSONG=NO
 

PSID/RSID file header

  The detailed structure of the SID header looks like the following. Header
offsets are in hexadecimal  notation.  Other  integer  values  are  decimal
unless explicitly marked  otherwise.  Any  stored  integer  values  are  in
big-endian format:

  +00    magicID: ``PSID'' or ``RSID''

  This is a four byte long ASCII  character  string  containing  the  value
0x50534944 or 0x52534944. 'RSID' (Real SID) denotes that the file  strictly
requires a true Commodore-64 environment to run properly. 'PSID' files will
generally  run  trouble-free  on  older  PlaySID  and   libsidplay1   based
emulators, too.


  Some words about the Real C64 SID file format (RSID):

  The RSID format was designed  to  contain  tunes  that  are  not  PlaySID
compatible, but strictly require a real C64 environment to run. Tunes  that
are multi-speed and/or contain  samples  and/or  use  additional  interrupt
sources or do busy looping will cause older SID emulators  to  lock  up  or
play very wrongly (if at all).

  By using the name RSID for such rips  all  existing  SID  emulators  will
reject these tunes safely until they can  be  upgraded  to  cope  with  the
additional requirements.

  Due to the nature of these tunes, every effort must be made to make  sure
they are directly runnable on an actual C64 computer.  As  such  the  tunes
will only be presented  with  the  default  C64  power-on  environment  and
expected to configure and use all hardware appropriately.


RSID is based on PSIDv2NG with the following modifications:

  magicID = RSID
  version = only 2
  loadAddress = 0 (reserved)
  playAddress = 0 (reserved)
  speed = 0 (reserved)
  psidSpecific flag is called C64BASIC flag

  The above fields MUST be checked and if any differ from  the  above  then
the tune MUST be rejected.  The  definitions  above  will  force  tunes  to
contain proper hardware configuration  code  and  install  valid  interrupt
handlers.


The default C64 environment is as follows:

  VIC - IRQ set to raster 0, but not enabled.
  CIA 1 timer A - set to 60Hz with the counter running and IRQs active.
  Other timers - disabled and loaded with $FFFF.
  Bank register - $37

  A side effect of the bank register is that init MUST NOT be located under
a ROM/IO memory area (addesses $0000-$07E8, $A000-$BFFF  and  $D000-$FFFF).
Since every effort needs to be made to run the tune on a real C64 the  load
address of the image MUST NOT be set lower than $07E8.

  +04    WORD version

  Available version number can either be 0001 or 0002. Headers of version 2
provide additional fields. RSID and PSID v2NG files must have 0002 here.

  +06    WORD dataOffset

  This is the offset from the start of the file  to  the  C64  binary  data
area. Because of the fixed size of the header, this is  either  0x0076  for
version 1 and 0x007C for version 2.

  +08    WORD loadAddress

  The C64 memory location where to put the C64 data. 0 means the  data  are
in original C64 binary file format, i.e. the first two bytes  of  the  data
contain the little-endian load address (low byte,  high  byte).  This  must
always be true for RSID files. Furthermore, the actual  load  address  must
NOT be less than $07E8 in RSID files.

  You must be absolutely sure what to enter here. There is no way to detect
automatically whether the first two bytes in a C64 data file are  meant  to
be a load address or some arbitrary bytes of code or data. Unless your  C64
file is not a normal binary file and thus has no load address in front, you
need not enter anything else than 0 here. The SID tune will not play if you
specify a load address which is present in the C64 file already.

  Normal C64 binary data files have a  load  address  in  their  first  two
bytes, so they can be  loaded  to  a  pre-defined  destination  address  by
executing LOAD"FILE",8,1, for instance. If a  load  address  is  explicitly
specified in the sidtune info file, some sidtune converters  and  utilities
conjecture that the C64 data don't have a load address in their  first  two
bytes. Hence, the explicit load address from the  info  file  is  moved  in
front of the C64 data to create a valid C64 binary file which can be easily
loaded on a C64, too. If that C64 file were to be saved, it  would  contain
two superfluous data bytes at offset 2 if an original load address had been
in the first two bytes of the old file. This process of adding a  duplicate
load address can be repeated. The file loader  strips  off  the  first  two
bytes (the used load address) and  puts  the  rest  of  the  file  contents
(including the now obsolete load address at file offset 2) into memory.  If
the new load address is the same than the old one the two added bytes cause
the whole data to be displaced by two bytes, which most likely  results  in
malfunctioning code. Also, superfluous bytes in  memory  then  can  confuse
disassemblers which start at the beginning of the file or memory buffer.

  +0A    WORD initAddress

  The start address of the machine code subroutine that initializes a song,
accepting the contents of the 8-bit 6510 Accumulator  as  the  song  number
parameter. 0 means the address is equal to the effective load address.

  In RSID files initAddress must never point to a ROM area ($A000-$BFFF  or
$D000-$FFFF) or be lower than $07E8. Also, if the C64 BASIC  flag  is  set,
initAddress must be 0.

  +0C    WORD playAddress

  The start address of the machine  code  subroutine  that  can  be  called
frequently to produce  a  continuous  sound.  0  means  the  initialization
subroutine is expected to install an interrupt handler,  which  then  calls
the music player at some place. This must always be true for RSID files.

  +0E    WORD songs

  The number of songs (or sound effects) that can be initialized by calling
the init address. The minimum is 1. The maximum is 256.

  +10    WORD startSong

  The song number to be played by default. This value is optional. It often
specifies the first song you would hear upon starting the  program  is  has
been taken from. It has a default of 1.

  +12    LONGWORD speed

  This is a 32 bit big endian number. Each bit  in  'speed'  specifies  the
speed for the corresponding tune number, i.e. bit 0 specifies the speed for
tune 1. If there are more than 32 tunes, the speed specified for tune 32 is
also used for all higher numbered tunes.

  A 0 bit specifies vertical blank interrupt (50Hz PAL, 60Hz NTSC), and a 1
bit specifies CIA 1 timer interrupt (default 60Hz).

  Surplus bits in 'speed' should be set to 0.

  For RSID files 'speed' must always be set to 0.

  Note that if 'play' = 0, the bits in 'speed'  should  still  be  set  for
backwards compatibility with older SID players. New SID players running  in
a C64 environment will ignore the speed bits in this case.

  WARNING: This field does not work  in  PlaySID  for  Amiga  like  it  was
intended, therefore the above is a redefinition  of  the  original  'speed'
field in SID v2NG! See also the 'clock' (video  standard)  field  described
below for 'flags'.

  +16    ``<name>''
  +36    ``<author>''
  +56    ``<released>'' (also known as ``<copyright>'')

  These are 32 byte long zero  terminated  ASCII  character  strings.  Upon
evaluating the header, a zero byte will always be put into the last byte of
each string. So the maximum number of available free characters is 31.

  +76    <data>

  Version 1 of the SID header is complete at this  point.  The  binary  C64
data starts here.

  Version 2 of the header incorporates the v1 header  fields  and  provides
additional fields. Some of these are actually v2NG  specific  -  those  are
noted below.

  +76    WORD flags


This is a 16 bit big endian number containing the following bitfields:

  Bit 0 specifies format of the binary data (musPlayer):
         0 = built-in music player,
         1 = Compute!'s Sidplayer MUS data, music player must be merged.

  If this bit is set, the appended binary data are in Compute!'s  Sidplayer
MUS format, and does not contain  a  built-in  music  player.  An  external
player machine code must be merged to replay such a sidtune.

  Bit 1 specifies whether the tune is PlaySID specific, e.g. uses PlaySID
  samples (psidSpecific):
         0 = C64 compatible,
         1 = PlaySID specific (PSID v2NG)
         1 = C64 BASIC flag (RSID)

This is a v2NG and RSID specific field.

  PlaySID samples were  invented  to  facilitate  playback  of  C64  volume
register samples with the original Amiga PlaySID software. PlaySID  samples
made samples a reality on slow  Amiga  hardware  with  a  player  that  was
updated only once a frame.

  Unfortunately, converting C64 volume samples  to  PlaySID  samples  means
that they can no longer be played on a C64, and furthermore the  conversion
might potentially break the non-sample part of a tune if the timing between
writes to the SID registers is at all altered. This follows from  the  ADSR
bugs in the SID chip.

  Today, the speed of common hardware and the  sophistication  of  the  SID
players is such that there is little need  for  PlaySID  samples.  However,
with  all  the  PlaySID  sample  PSIDs  in  existence  there's  a  need  to
differentiate between SID files containing only original C64 code and  PSID
files containing PlaySID samples or having other PlaySID  specific  issues.
As stated above, bit 1 in 'flags' is reserved for this purpose.

  Since RSID files do not have the need for PlaySID samples, this  flag  is
used for a different purpose: tunes that include a BASIC executable portion
will be played (with the BASIC portion executed) if the C64 BASIC  flag  is
set. At the same time, initAddress must be 0.

  Bits 2-3 specify the video standard (clock):
         00 = Unknown,
         01 = PAL,
         10 = NTSC,
         11 = PAL and NTSC.

This is a v2NG specific field.

  As can be seen from the 'speed' field, it is not possible to specify NTSC
C64 playback. This is unfortunate, since the different clock  speeds  means
that a tune written for the NTSC C64 will be  slightly  detuned  if  played
back on a PAL C64. Furthermore, NTSC C64 tunes driven by a  vertical  blank
interrupt have to be converted to use the CIA 1  timer  to  fit  into  this
scheme. This can cause severe problems, as the NTSC refresh  rate  is  once
every 17045 cycles, while the CIA 1 timer A is latched with  17095  cycles.
Apart from the difference in timing itself, the SID ADSR bugs can  actually
break the tune.

The 'clock' (video  standard)  field  was  introduced  to  circumvent  this
problem.

  Bits 4-5 specify the SID version (sidModel):
         00 = Unknown,
         01 = MOS6581,
         10 = MOS8580,
         11 = MOS6581 and MOS8580.

  This is a v2NG specific field.

  The MOS6581 and  the  MOS8580  have  three  notable  differences.  First,
combined waveforms are generally louder on a MOS8580, to  the  extent  that
some combinations that are clearly audible  on  a  MOS8580  are  completely
silent on a MOS6581. Second, the internal DC levels in the MOS8580  are  so
small that software or hardware tricks must be used to play volume samples.
Third, the MOS8580 analog filter has totally different characteristics from
the MOS6581 analog filter.

  To ensure that music specifically written for one of the two SID versions
can be played back correctly, bits 4-5 in 'flags' are used as stated above.

  Bits 6-15 are reserved and should be set to 0.

  +78    BYTE startPage (relocStartPage)

  This is a v2NG specific field.

  This is an 8 bit number. If 'startPage' is 0, the SID file is clean, i.e.
it does not write outside its data range within the driver ranges. In  this
case the largest free memory range can be determined from the start address
and the data length of the SID binary data. If 'startPage' is  0xFF,  there
is not even a single  free  page,  and  driver  relocation  is  impossible.
Otherwise, 'startPage' specifies the start page of the single largest  free
memory range within the driver ranges. For example, if 'startPage' is 0x1E,
this free memory range starts at $1E00.

  +79    BYTE pageLength (relocPages)

  This is a v2NG specific field.

  This is an 8 bit  number  indicating  the  number  of  free  pages  after
'startPage'. If 'startPage' is not 0 or 0xFF, 'pageLength' is  set  to  the
number of free pages starting at 'startPage'. If 'startPage' is 0 or  0xFF,
'pageLength' must be set to 0.

  The relocation range indicated by  'startPage'  and  'pageLength'  should
never overlap or encompass the load range of the C64 data. For RSID  files,
the relocation range should also not overlap or encompass any  of  the  ROM
areas  ($A000-$BFFF  and  $D000-$FFFF)  or   the   reserved   memory   area
($0000-$03FF).

  +7A    WORD reserved

  This is a 16 bit number and is reserved and should be set to 0.

  +7C    <data>

  Version 2 of the SID header ends here. This offset is the  start  of  the
binary C64 data. See also 'loadAddress' for  what  the  first  2  bytes  of
'data' might indicate.



MUS files

  The .MUS & .STR file name extensions are  used  for  Compute's  Sidplayer
music files.

  The overall file layout is as follows:
    The first two bytes contain the load address.
    The next two bytes contain the length of the data for Voice 1
    The next two bytes contain the length of the data for Voice 2
    The next two bytes contain the length of the data for Voice 3
    Then the data for Voice 1 follows immediately
    Then the data for Voice 2 follows immediately
    Then the data for Voice 3 follows immediately
    Then the text description of the music file (upto 5 lines)

  The data for each Voice consists of a stream of  two  byte  commands  and
should be terminated with a HALT code which is 01 4F.

  The text description can  be  upto  5  lines  long,  each  line  upto  32
characters wide. It is made up of PETSCII characters and may contain colour
codes. The text description should be terminated with a 00 byte (but  might
not be).

*** SPY (SPYne containers)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: John Iannetta

  Created  by  John  Iannetta  around  1995,  these  are  mostly  found  in
Compuserve's CBM applications forum, but do appear in the COMP.BINARIES.CBM
newsgroup as well. It is a self-extracting file, and does  not  employ  any
compression. The word "SPYNE" does not represent any acronym, but is  meant
to represent a "spine", with files linked together like a human spine.

  This format has some similarities to LNX containers in that all the files
are simply stored (with no compression), one after the other, and are  byte
aligned to take up multiples of 254 bytes (256 on a real 1541).  This  does
result in a little dead space at the end of each file  stored,  but  its  a
small price to pay for how easy it is to construct and break up files on  a
real C64/1541.

  SPYne containers do not  contain  a  BASIC  program  (like  LNX)  at  the
beginning telling you to "Use XXX to dissolve this file", since SPYnes  are
self-extracting, and are meant to be loaded ",8,1" on a real C64. There  is
no specific signature to determine if the file is actually a  SPYne.  SPYne
containers can store up to 144 files.

  Each file inside the container can have up to 65535 blocks. However,  the
container itself is limited to (best case) 65519 blocks total (65535  minus
15 blocks for extraction code, and a  minimum  of  1  block  for  directory
entries, 1-8 entries). Worst case for the container size  is  65502  blocks
(15 blocks for extraction and 18 blocks for a directory of 137-144 files).

  This many not make sense at first, but how can  you  load  a  SPYne  file
which exceeds 258 blocks (the maximum memory of the C64)? SPYne  files  can
be as large as 65535 blocks, and it would  seem  impossible  to  work  with
files this large. The answer  is  that  the  SPYne  file  loads  at  $02A7,
trapping the necessary vectors to prevent it from loading the entire  file,
but just the extraction code. Neat trick!

  The first 15 blocks (up to offset 3809 or $0EE1) of the file contain  the
self-extracting code. It  is  an  auto-running  application,  with  a  load
address of $02A7.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: A7 02 20 A0 E5 A9 0A 8D 1E D0 A9 16 8D 18 D0 A9   ���������Щ���Щ
0010: 04 8D 1F D0 20 44 E5 A9 D8 85 FC A0 00 84 FB A2   �����D��؅������
0020: 04 A9 0D 91 FB C8 D0 FB E6 FC CA D0 F6 20 A5 FF   ����������������

  Starting at offset $0EE2 (3810) is the central directory. This address is
exactly 15 blocks into the file (15*254=3810). Each directory entry  is  32
bytes long, with the last two of these being "filler", and unused.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0EE2: 82 00 00 30 32 2E 44 49 47 49 54 41 4C 20 4D 41   ���02.DIGITAL�MA
0EF2: 47 49 43 00 00 00 00 88 18 B5 FF 00 2B 00 00 00   GIC���������+���
0F02: 82 00 00 30 39 2E 2D 2D 2D 3E 20 42 59 20 3C 2D   ���09.--->�BY�<-
0F12: 2D 2D 2D 00 00 00 00 00 7A 44 FF 00 2D 00 00 00   ---�����zD��-���
0F22: 82 00 00 30 33 2E 2D 3E 20 46 4F 52 43 45 53 20   ���03.->�FORCES�
0F32: 3C 2D 2D 00 00 00 00 11 BE 89 FF 00 20 00 00 00   <--�������������
0F42: 82 00 00 30 37 2E 2D 3E 20 4F 46 20 45 56 49 4C   ���07.->�OF�EVIL
0F52: 20 3C 2D 00 00 00 00 4F 78 11 FF 00 26 00 00 00   �<-����Ox���&���
0F62: 82 00 00 30 34 2E 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D   ���04.----------
0F72: 2D 2D 2D 00 00 00 00 40 58 D2 FF 00 28 00 00 00   ---����@X���(���
0F82: 82 00 00 30 31 2E 20 52 45 4C 45 41 53 45 44 20   ���01.�RELEASED�
0F92: 4F 4E A0 00 00 00 00 05 D5 0F FF 00 29 00 00 00   ON����������)���
0FA2: 82 00 00 30 35 2E 20 4A 41 4E 55 41 52 59 20 31   ���05.�JANUARY�1
0FB2: 53 54 20 00 00 00 00 F7 FA EC FF 00 24 00 00 00   ST����������$���
0FC2: 82 00 00 30 38 2E 20 20 20 31 39 39 36 A0 A0 A0   ���08.���1996���
0FD2: A0 A0 A0 00 00 00 00 39 71 C8 FF 00 36 00 82 00   �������9q���6���
0FE2: 00 30 36 2E 20 28 4D 4F 52 45 20 4C 49 4B 45 29   �06.�(MORE�LIKE)
0FF2: A0 00 00 00 00 40 33 CF FF 00 32 00 00 00 82 00   �����@3���2�����
1002: 00 31 30 2E 20 28 31 32 2F 32 38 2F 39 35 21 29   �10.�(12/28/95!)
1012: A0 00 00 00 00 AD 1C 0F FF 00 2B 00 00 00 82 00   ����������+�����
1022: 00 44 49 47 49 54 41 4C 20 4E 4F 54 45 A0 A0 A0   �DIGITAL�NOTE���
1032: A0 00 00 00 00 49 B0 CB 00 00 14 00 00 00 00 00   �����I����������

     Byte:   $00: File type
                   supported values for this location are:
                    $81 - SEQ
                     82 - PRG
                     83 - USR
           01-02: Undefined (00's for now)
           03-12: Filename (padded with $A0's)
           13-16: Undefined (00's for now)
           17-18: File checksum (in low/high byte format)
              19: LSU byte (see "INTRO.TXT"  document  for  description  of
                  "LSU")
              1A: Last file marker
                    FF - more files in container
                    00 - last file in container
              1B: Set to $00
           1C-1D: File sector count (in low/high byte format)
           1E-1F: Not used (and not present on a 254-byte boundary)

  File type support is limited to valid files only. SPYnes  cannot  contain
write-protected, "splat" or DEL files. Without DEL type support, this means
that many "separator" files in the directory cannot be included. REL  files
are partially supported, as only  the  data  portion  is  copied,  and  its
filetype is converted to USR format.

  The checksum at byte offset 17-18 is a simple  16-bit  addition  (without
carry) of the entire  file,  but  does  not  include  the  directory  entry
information.

  Looking at the above HEX dump, at address $0FE0 a  new  filename  starts.
This is two bytes earlier than expected. This occurs  because  the  address
$0FE0 is at a "254-byte boundary address", meaning it is divisible by  254,
with no remainder. Only in the directory area is this  boundary  important,
and when it happens, the last two "filler" bytes  in  the  directory  entry
don't exist.

  SPYne supports two extraction methods, fast and slow. The fast method  is
destructive in that is just breaks up the file into sections, only works on
a 1541/1571 drive, and has no checksum verification. The slow method should
work on any device, is not destructive to the original file, and  uses  the
checksum in the directory entry to verify the data integrity.

  File data starts in the next block following the end  of  the  directory.
You only know where the first file's data starts  once  the  directory  has
been completely read. Since the extraction code takes  up  15  blocks,  and
each 8 files take up another block, we can calculate how many  blocks  into
the container the actual file data starts.

  If we have 11 files, we have  two  directory  blocks  (one  full  with  8
entries, one partial with 3  entries).  Therefore  the  first  file's  data
starts at block 17 (17*254 = 4318, or $10DE). The  second  file's  starting
position can be calculated by adding the block  count  of  the  first  file
(multiplied by 254), and adding this to the first files starting position.

*** T64 (Tape containers for C64s)
*** Document revision: 1.5
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Miha Peternel

  This format, designed  by  Miha  Peternel,  is  for  use  with  his  C64s
emulator. It has a very structured directory with each entry taking  up  32
bytes, and a reasonably well-documented format.

  It has a large header  at  the  beginning  of  the  file  used  for  file
signature, tape name, number of directory entries, used  entries,  and  the
remainder for actual tape directory entries.

  Following immediately after the end of the directory comes the  data  for
each file. Each directory entry includes the information of where its  data
starts in the file (referenced to the beginning of the file),  as  well  as
the starting and ending C64 load addresses. From  these  addresses  we  can
determine how long the stored file is (end-start).

  Unfortunately, in the early days of the C64s emulator,  before  Miha  had
his MAKETAPE utility ready, another program called CONV64 was on the scene,
and it created faulty T64 files. The ending load address was usually set to
$C3C6 regardless of file size. Be aware that these files  are  still  quite
common on the Web and FTP sites.

Here is a HEX dump of the first few bytes of a standard T64 file:

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
        -----------------------------------------------   ----------------
000000: 43 36 34 53 20 74 61 70 65 20 69 6D 61 67 65 20   C64S.tape.image.
000010: 66 69 6C 65 00 00 00 00 00 00 00 00 00 00 00 00   file............
000020: 01 01 90 01 05 00 00 00 43 36 34 53 20 44 45 4D   ........C64S.DEM
000030: 4F 20 54 41 50 45 20 20 20 20 20 20 20 20 20 20   O.TAPE..........
000040: 01 01 01 08 85 1F 00 00 00 04 00 00 00 00 00 00   ................
000050: 53 50 59 4A 4B 45 52 48 4F 45 4B 20 20 20 20 20   SPYJKERHOEK.....
000060: 01 01 01 08 B0 CA 00 00 84 1B 00 00 00 00 00 00   ................
000070: 49 4D 50 4F 53 53 49 42 4C 45 20 4D 49 53 53 2E   IMPOSSIBLE MISS.
...
0003E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0003F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
000400: 1A 08 E4 07 9E 32 30 38 30 14 14 14 14 14 14 14   ................

  The first 32 bytes ($000000-00001F) represent the signature of the  file,
telling us it is a tape container for C64S. Note that it is padded with $00
to make the signature 32 bytes long.

000000: 43 36 34 53 20 74 61 70 65 20 69 6D 61 67 65 20   C64S.tape.image.
000010: 66 69 6C 65 00 00 00 00 00 00 00 00 00 00 00 00   file............

  It is important that the string "C64" be at the  beginning  of  the  file
because it is the string which is common enough to be used to identify  the
file type. There are several variations of  this  string  like  "C64S  tape
file" or "C64 tape image file". The string is stored in ASCII.

  The next 32 bytes contain all the info about the directory  size,  number
of used entries, tape container name, tape version#, etc.

000020: 01 01 90 01 05 00 00 00 43 36 34 53 20 44 45 4D   ........C64S.DEM
000030: 4F 20 54 41 50 45 20 20 20 20 20 20 20 20 20 20   O TAPE..........

Bytes:$20-21: Tape version number of either $0100 or $0101. I am  not  sure
              what differences exist between versions.
       22-23: Maximum  number  of  entries  in  the  directory,  stored  in
              low/high byte order (in this case $0190 = 400 total)
       24-25: Total number of used entries, once again  in  low/high  byte.
              Used = $0005 = 5 entries.
       26-27: Not used
       28-3F: Tape container name, 24 characters, padded with $20 (space)

  The next 32 bytes (and  on  until  the  end  of  the  directory)  contain
individual directory entries.

000040: 01 01 01 08 85 1F 00 00 00 04 00 00 00 00 00 00   ................
000050: 53 50 59 4A 4B 45 52 48 4F 45 4B 20 20 20 20 20   SPYJKERHOEK.....
000060: 01 01 01 08 B0 CA 00 00 84 1B 00 00 00 00 00 00   ................
000070: 49 4D 50 4F 53 53 49 42 4C 45 20 4D 49 53 53 2E   IMPOSSIBLE MISS.

Bytes   $40: C64s filetype
                  0 = free (usually)
                  1 = Normal tape file
                  3 = Memory Snapshot, v .9, uncompressed
              2-255 = Reserved (for memory snapshots)
         41: 1541 file type (0x82 for PRG, 0x81 for  SEQ,  etc).  You  will
             find it can vary  between  0x01,  0x44,  and  the  normal  D64
             values. In reality any value that is not a $00 is  seen  as  a
             PRG file. When this value is a $00 (and the previous  byte  at
             $40 is >1), then the file is a special T64 "FRZ" (frozen) C64s
             session snapshot.
      42-43: Start address (or Load address). This is the first  two  bytes
             of the C64 file which is usually the load  address  (typically
             $01 $08). If the file is a snapshot, the address will be 0.
      44-45: End address (actual end address in memory,  if  the  file  was
             loaded into a C64). If  the  file  is  a  snapshot,  then  the
             address will be a 0.
      46-47: Not used
      48-4B: Offset into the conatiner file (from the beginning)  of  where
             the C64 file starts (stored as low/high byte)
      4C-4F: Not used
      50-5F: C64 filename (in PETASCII, padded with $20, not $A0)

  Typically, an empty entry will have no contents at all, and not just have
the first byte set to $00. If you only set the C64s filetype  byte  to  $00
and then use the file in C64S, you will see  the  entry  is  still  in  the
directory.

0003E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0003F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................

  Starting at $000400 (assuming a directory with 30 entries)  we  now  have
actual file data.

000400: 1A 08 E4 07 9E 32 30 38 30 14 14 14 14 14 14 14   .....2080.......

---------------------------------------------------------------------------

What it takes to support T64:

  This format has some advantages over D64's in that there is  very  little
wasted space, except for the empty directory entries. It is laid  out  very
logically, with entries and headers all being in 32-byte chunks, making for
easy support. There is also a signature, and the directory size  can  be  a
large as you need for expansion.

  One large drawback is it is not  meant  to  support  multi-file  programs
under C64s. If you have a program which requires several  sub-files  to  be
loaded, under C64s a T64 file will not work. It would be best to use a  D64
in this case.

  When removing a file from a T64, you must  remove  the  entry  completely
from the directory. Failure to do  so  results  in  the  file  still  being
visible to C64s. It is not even good enough to set the whole entry to zero,
but it must be *removed*.

  The directory also contains the load start and end addresses. Why?  Since
T64 was designed for C64s, having the load address was something useful  to
show when selecting files inside of C64s. However, the  end  address  would
have been better if it was replaced with "file size", so you  could  easier
determine the file size for display.

  While the directory design allows for C64 file types to be used, it would
appear to be a waste as T64 really only supports loadable files  (PRG)  and
nothing else. REL is out of the question.

  Also, since the filename entries are not padded with A0  characters  (but
rather with spaces), filenames can't have trailing spaces.

  As mentioned previously, there are faulty T64 files around with the 'end load
address' value set to $C3C6. In order to work around this bug,  here's  how
to work with T64 files without relying on this value:

  1. Read in the entire T64 header, ignoring the 'end load address' value

  2. Sort the list by ascending order of offset into the T64

  3. Determine the difference in size (in bytes)  between  the  first  file
     offset and the next one. Remember to add in  the  two  'load  address'
     bytes that are stored in the directory as they are part of the file.

  4. You should now have your file size, and therefore be able to calculate
     the 'end load address' value given the load address.


---------------------------------------------------------------------------

Overall Good/Bad of T64 Files:

  Good
  ----
  * The header  is  *adequately*  defined  (but  some  improvement  in  the
    description would be good)

  * Supports a 16 character filename

  * Has a verifiable file signature

  * The format is extendible (can add delete to even a full container,  the
    central directory doesn't have a small file limit)

  * If you pack the T64 directory full, you minimize the DOS cluster  slack
    space loss, since the file size is variable

  * Has a description field in the header

  * Can have loadable files with the same name(?)



  Bad
  ---

  * Filenames can't have spaces at the ends due to the  padding  characters
    being spaces ($20) and not the standard $A0 character

  * It is not designed to  support  multi-load  programs.  Unless  all  the
    emulators start supporting this, it would not be a  good  idea  to  use
    them this way.

  * Doesn't practically support >63 files (this is a  limitation  of  C64s,
    nothing more)

  * No directory customization, as zero-length files not  allowed  (minimum
    filesize is 2 bytes)

  * No actual file size for contained files is stored, so you need to use a
    poor method to determine the file size based on the load addresses

  * Can't easily re-write contained files as they are  blocked  in  by  the
    files around them

  * No REL file support, as format really only supports PRG's

  * Header could have been  laid  out  better,  to  make  it  a  much  more
    versatile format than it is now

  * Can't have $00's in a filename(?)

  * Even though you can set  the  directory  entry  to  be  the  real  1541
    filetype (SEQ, USR, PRG), C64s still sees them as PRG's (?)

*** TAP (raw C64 cassette TAPE images)
*** Document revision: 1.1
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Per Hakan Sundell,
                          Markus Brenner

  Designed by Per Hakan Sundell (author of the CCS64 C64 emulator) in 1997,
this format attempts to duplicate the data stored on a C64  cassette  tape,
bit for bit. Since it is simply a representation of  the  raw  serial  data
from a tape, it should handle *any* custom tape loaders that exist.

  The TAP images are generally very large, being a minimum of eight  times,
and up to sixteen times as large as what a raw PRG file would be.  This  is
due to the way the data is stored, with each bit of the original  file  now
being one byte large in the TAP file. The layout is fairly simple,  with  a
small 14-byte header followed by file data.


      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 2D 54 41 50 45 2D 52 41 57 00 00 00 00   C64-TAPE-RAW����
0010: 51 21 08 00 2F 0F 0D 31 64 1D 26 0D 07 21 0A 12   Q!��/��1d�&��!��
0020: 4A 2F 2C 34 07 18 0D 31 07 04 23 04 0D 42 0D 1E   J/,4���1��#��B��
0030: 34 04 42 0D 20 15 5E 04 0D 18 61 0D 26 29 34 0D   4�B���^���a�&)4�
0040: 23 0D 07 0A 3F 55 04 0A 13 3F 07 0D 12 2B 18 0A   #���?U���?���+��

    Bytes: $0000-000B: File signature "C64-TAPE-RAW"
                 000C: TAP version (see below for description)
                        $00 - Original layout
                         01 - Updated
            000D-000F: Future expansion
            0010-0013: File  data  size  (not  including  this  header,  in
                       LOW/HIGH format) i.e. This image is $00082151  bytes
                       long.
            0014-xxxx: File data

  In TAP version $00 files, each data byte in the file data area represents
the length of a pulse, when the C64's hardware  will  trigger  again.  This
pulse length is determined by the following formula:

    pulse length (in seconds) = (8 * data byte) / (clock cycles)

  Therefore, a data value of $2F (47 in decimal) would be:

    (47 * 8) / 985248 = .00038975 seconds.

  A data value of $00 represents an "overflow" condition, any pulse  length
which is more that 255 * 8 in length.

  The value of "clock cylces" from above  (985248)  is  based  on  the  PAL
value.  Since  this  file  format  was  developed  in  Europe,   which   is
predominantly PAL video, this is only logical.  The  NTSC  value  would  be
1022730, which is very close to  the  PAL,  and  therefore  won't  cause  a
compatability problem converting European and NTSC tapes. I would stick  to
using the PAL value just in case.


  In TAP version $01 files, the data value of  $00  has  been  re-coded  to
represent values greater than 255 * 8. When a  $00  is  encountered,  three
bytes will follow which are the actual time (in cycles) of a pulse, and the
above formula does not apply.  The  three  bytes  are  stored  in  LOW/HIGH
format.


  The actual interpretation of the serial data takes a little more work  to
explain.  The  typical  ROM  tape  loader  (and  the  turbo  loaders)  will
initialize a timer with a specified value and start it  counting  down.  If
either the tape data changes or the timer runs out, an IRQ will occur.  The
loader will determine which condition caused the  IRQ.  If  the  tape  data
changed before the timer ran out, we have a short pulse, or a "0"  bit.  If
the timer ran out first, we have a long pulse, or a  "1"  bit.  Doing  this
continuously and we decode the entire file.

*** VSF (Vice Snapshot File, saved-session file)
*** Document revision: 1.2
*** Last updated: Oct 1, 2007
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: VICE documentation

  These files are the saved-session files, similar to  C64s  FRZ  and  PC64
saved-session files, which contains the entire state of the CPU,  RAM,  ROM
and I/O of the current emulator session.  The  typical  file  extension  is
".VSF"

  There was a claim that VICE  was  using  the  extension  ".S64"  for  its
snapshot files. A package called UnQuill  (in  unquill.txt  and  unquill.c)
makes mention of VICE saving snapshot files with such an extension.  As  it
turns out, the UNIX version of VICE doesn't attach an extension when saving
a snapshot and the author of UnQuill chose S64 as  the  extension  to  save
them with. Therefore S64 files, if they exist,  are  an  incorrectly  named
VICE snapshot file from the UNIX world.

  The internal structure of a VICE snapshot is a signature, followed  by  a
series of modules, where the module types are determined by the  CPU  which
VICE is emulating. That is, if you are running the  VICE  VIC-20  emulator,
the modules will not all be the same as the C64 emulator.

  The modules contain individual chip or device states,  not  the  complete
state  of  the  emulator.  The  snapshot  format  was  designed  to  be  as
implementation-independent as possible, to  allow  reuse  of  snapshots  in
later versions of the VICE emulator, or even in other emulators.

  The VICE signature is the simple text string...

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 43 45 20 53 6E 61 70 73 68 6F 74 20 46 69   VICE�Snapshot�Fi
0010: 6C 65 1A 00 00 43 31 32 38 00 00 00 00 00 00 00   le���C128�������
0020: 00 00 00 00 00 .. .. .. .. .. .. .. .. .. .. ..   �����...........

      Bytes: $00-12 - VICE signature "VICE Snapshot File" in ASCII followed
                      by a $1A (and padded with $00 if necessary)
              13-14 - Snapshot version $00/$00 (major/minor)
              15-24 - Name of emulated machine in ASCII (padded with  $00).
                      The current machines emulated are  (not  stored  with
                      quotes):
                        "PET"
                        "CBM-II"
                        "VIC20"
                        "C64"
                        "C128"


  From now on, the snapshot file contains MODULES,  with  the  module  name
stored in ASCII. As stated earlier, each  emulated  machine  type  contains
certain modules. Note that each HEX dump which follows will be starting  as
though it is at offset $0000, which means  that  each  one  is  treated  as
though it was its own file. This makes it easier to break down the module.

  The list below shows what modules belong to what machines:

    C64 - MAINCPU, C64MEM, C64ROM, VIC-II, CIA1, CIA2, SID, REU, ACIA1, TPI

   C128 - MAINCPU, C128MEM, C128ROM, VIC-II, CIA1, CIA2, SID, ACIA1, TPI
          (Not yet supported are the 80 column video chip,  cartridges  and
           RAM expansion unit.)

  VIC20 - MAINCPU, VIC20MEM, VIC20ROM, VIC-I, VIA1, VIA2

    PET - MAINCPU, PETMEM, PETROM, CRTC, PIA1, PIA2, VIA, ACIA1

 CBM-II - MAINCPU, CBM2MEM, CBM2ROM, CRTC, VIC-II, CIA1, TPI1, TPI2, ACIA1,
          SID


  There were certain  modules  which  were  either  under  construction  or
included no description at all at the time of writing this document.  These
include:

  MAINCPU (under construction)
  DRIVE module layout (no description)
  RIOT module (no description)
  SID, VIC-I & VIC-II modules (no breakdown)
  REU module(s) (no breakdown)


---------------------------------------------------------------------------


The MAINCPU Module:

Chip type: 6502 (6509 for CBM-II) (still under construction)

  Although usually the CPU is a 6510 (6509 on CBM-II, 6502 on VIC-20), only
the 6502 core is saved here. You will also find a  clock  value  here.  All
other modules save their own clock values relative to this value. The drive
modules save their clocks relative to their appropriate CPUs.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 4D 41 49 4E 43 50 55 00 00 00 00 00 00 00 00 00   MAINCPU���������
0010: 01 00 35 00 00 00 F8 0E AA 00 00 00 00 F3 5E C2   ��5�����������^�
0020: 22 F0 01 00 00 F1 00 AA 00 32 15 09 00 2B 00 00   "��������2���+��
0030: 00 33 FE A9 00 .. .. .. .. .. .. .. .. .. .. ..   �3���...........

      Bytes: $0000-000F - Module type ("MAINCPU"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-0019 - CPU clock value (lo/hi)
                   001A - A register (accumulator)
                   001B - X register
                   001C - Y register
                   001D - Stack pointer
              001E-001F - Program counter
                   0020 - Status register
              0021-0024 - Last opcode
              0025-0028 - Clock value when IRQ line active
              0029-002C - Clock value when NMI line active
              002D-0030 - ???
              0031-0034 - ???


---------------------------------------------------------------------------


The C64MEM Module:

Chip type: Memory - Holds the RAM contents of the C64.  Also  the  CPU  I/O
                    register  contents  are  saved  here.  This  module  is
                    mandatory.

  The size of the C64 memory modules differs  with  each  different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded. The attached cartridges are not yet saved  and
not yet restored upon load.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 4D 45 4D 00 00 00 00 00 00 00 00 00 00   C64MEM����������
0010: 00 00 1A 00 01 00 37 2F 00 00 2F 37 00 AA B1 91   ������7/��/7����
0020: B3 22 22 00 00 00 00 FF 00 00 00 00 00 00 00 00   �""�������������
0030: 19 16 00 0A 76 A3 00 00 00 00 00 00 76 A3 B3 BD   ����v�������v���
0040: 00 00 00 00 00 01 08 03 08 03 08 03 08 00 A0 00   ����������������

      Bytes: $0000-000F - Module type ("C64MEM"), padded with $00
              0010-0011 - Module version $00/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - CPU Port data byte (RAM location $01)
                   0017 - CPU Port direction byte (RAM location $00)
                   0018 - State of the EXROM cartridge line
                   0019 - State of the GAME cartridge line
             001A-10019 - 64K RAM dump


---------------------------------------------------------------------------


The C64ROM Module:

Chip type: ROMs - A dump of the system ROMs (optional)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F         ASCII
      -----------------------------------------------   ----------------
0000: 43 36 34 52 4F 4D 00 00 00 00 00 00 00 00 00 00   C64ROM����������
0010: 00 00 16 50 00 00 85 56 20 0F BC A5 61 C9 88 90   ���P���V����aɈ�
0020: 03 20 D4 BA 20 CC BC A5 07 18 69 81 F0 F3 38 E9   ��Ժ�̼���i���8�
0030: 01 48 A2 05 B5 69 B4 61 95 61 94 69 CA 10 F5 A5   �H���i�a�a�i����
0040: 56 85 70 20 53 B8 20 B4 BF A9 C4 A0 BF 20 59 E0   V�p�S�����Ġ��Y�
0050: A9 00 85 6F 68 20 B9 BA 60 85 71 84 72 20 CA BB   ���oh���`�q�r�ʻ

      Bytes: $0000-000F - Module type ("C64ROM"), padded with $00
              0010-0011 - Module version $00/00 (major/minor)
              0012-0015 - Module size (lo/hi), not including this header
              0016-2015 - KERNAL ROM dump ($E000-FFFF)
              2016-4015 - BASIC ROM dump ($A000-BFFF)
              4016-5015 - CHARGEN ROM cump ($D000-DFFF)


---------------------------------------------------------------------------


The VIC-II Module:

Chip type: 656x - The contents of the VIC-II (C64, C128, or  C500).  Either
                  the VIC-II or the CRTC exists, not both in one snapshot.

Breakdown not available as this module is still under construction.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 43 2D 49 49 00 00 00 00 00 00 00 00 00 00   VIC-II����������
0010: 01 00 DD 04 00 00 01 00 01 0E 0E 0E 0E 0E 0E 0E   ����������������
0020: 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E   ����������������
0030: 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E   ����������������

      Bytes: $0000-000F - Module type ("VIC-II"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-04DC - VIC-II register contents


---------------------------------------------------------------------------


The CIA1 Module:

Chip type: 6526 (the CIA for the interrupts and the keyboard)

  The CIA 6526 is an I/O  port  chip  with  2  8-bit  I/O  ports,  a  shift
register, two timers, a Time of Day clock and interrupts.

 
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 49 41 31 00 00 00 00 00 00 00 00 00 00 00 00   CIA1������������
0010: 01 02 41 00 00 00 7F 00 FF 00 09 2C FF FF 00 00   ��A�������,����
0020: 00 01 00 01 01 08 25 40 FF FF 00 40 00 00 00 00   ������%@���@����
0030: 00 00 02 00 00 00 00 2B 1C 00 00 63 08 28 11 00   �������+���c�(��
0040: 00 .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..   �...............

      Bytes: $0000-000F - Module type ("CIA1"), padded with $00
              0010-0011 - Module version $01/02 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Output register A (ORA)
                   0017 - Output register B (ORB)
                   0018 - Data direction register A (DDRA)
                   0019 - Data direction register B (DDRB)
              001A-001B - Timer A Counter (TAC)
              001C-001D - Timer B Counter (TBC)
                   001E - Time-of-day current 10'th of a second (TOD_TEN)
                   001F - Time-of-day current seconds (TOD_SEC)
                   0020 - Time-of-day current minutes (TOD_MIN)
                   0021 - Time-of-day current hours (TOD_HR)
                   0022 - Shift register contents (SDR)
                   0023 - Mask of enabled interrupts (IER)
                   0024 - Control register A (CRA)
                   0025 - Control register B (CRB)
              0026-0027 - Timer A latch value (TAL)
              0028-0029 - Timer B latch value (TBL)
                   002A - Mask of currently active interrupts (IFR)
                   002B - Bit 6/7 reflect the PB6/7 toggle bit  state.  Bit
                          2/3 reflect  the  corresponding  port  bit  state
                          (PBSTATE)
                   002C - Number of half-bits to still shift in/out of  SDR
                          (SRHBITS)
                   002D - Time-of-day alarm 10'th of a second (ALARM_TEN)
                   002E - Time-of-day alarm seconds (ALARM_SEC)
                   002F - Time-of-day alarm minutes (ALARM_MIN)
                   0030 - Time-of-day alarm hours (ALARM_HR)
                   0031 - Current clock minus the clock when ICR  was  read
                          last plus 128 (READICR)
                   0032 - Bit 0: 1= latched for reading, Bit  1:  2=stopped
                          for writing (TODLATCHED)
                   0033 - Time-of-day latched 10'th of a second (TODL_TEN)
                   0034 - Time-of-day latched seconds (TODL_SEC)
                   0035 - Time-of-day latched minutes (TODL_MIN)
                   0036 - Time-of-day latched hours (TODL_HR)
              0037-003A - Clock  ticks  till  next  10'th  of  a   second
                          (TOD_TICKS)
              003B-003C - The state bits of the CIA timer A  (TASTATE,  new
                          from revision 1.1)
              003D-003E - The state bits of the CIA timer B  (TBSTATE,  new
                          from revision 1.1)

  The last two items have been added in CIA snapshot version 1.1 due to the
improved CIA  emulation  in  the  newer  VICE  versions.  Some  state  bits
correspond to the CIA state as described in the "A Software  Model  of  the
CIA 6526" document by Wolfgang Lorenz, some are delayed versions. For  more
read the source file ciatimer.h.


---------------------------------------------------------------------------


The CIA2 Module:

Chip type: 6526 (the CIA for the userport, IEC-bus and RS232)

(See the CIA1 module for details)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 49 41 32 00 00 00 00 00 00 00 00 00 00 00 00   CIA2������������
0010: 01 02 41 00 00 00 97 00 3F 00 FF FF FF FF 00 00   ��A�����?�������
0020: 00 01 00 00 08 08 FF FF FF FF 00 00 00 00 00 00   ����������������
0030: 00 00 02 00 00 00 00 2B 1C 00 00 28 11 28 11 00   �������+���(�(��
0040: 00 .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..   �...............

      Bytes: $0000-000F - Module type ("CIA2"), padded with $00
              0010-0011 - Module version $01/02 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-xxxx - See the CIA1 breakdown for details


---------------------------------------------------------------------------


The SID Module:

Chip type: 6581 (SID sound chip of the C64/C128)

Breakdown not available yet, as module is still under construction.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 53 49 44 00 00 00 00 00 00 00 00 00 00 00 00 00   SID�������������
0010: 01 00 36 00 00 00 00 00 00 00 00 00 00 00 00 00   ��6�������������
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0030: 00 00 00 00 00 00 .. .. .. .. .. .. .. .. .. ..   ������..........

      Bytes: $0000-000F - Module type ("SID"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-0035 - SID register contents


---------------------------------------------------------------------------


The REU Module:

Chip type: None - The RAM Extension Unit state (optional)

Breakdown not available yet.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 52 45 55 31 37 36 34 00 00 00 00 00 00 00 00 00   REU1764���������
0010: 00 00 2A 00 08 00 00 02 00 00 50 4A 00 00 00 00   ��*�������PJ����
0020: 00 00 00 00 00 00 00 00 00 00 0C 00 76 00 D4 BE   ������������v�Ծ
0030: 81 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������

      Bytes: $000000-00000F - Module type ("REU1764"), padded with $00
              000010-000011 - Module version $00/00 (major/minor)
              000012-000015 - Module size (lo/hi), including this header
              000016-080029 - REU contents


--------------------------------------------------------------------------


The C128MEM Module:

Chip type: RAM - Holds the RAM contents  of  the  C64.  Also  the  CPU  I/O
                 register  contents  are  saved  here.   This   module   is
                 mandatory.

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 31 32 38 4D 45 4D 00 00 00 00 00 00 00 00 00   C128MEM���������
0010: 00 00 21 00 02 00 00 3F 7F 01 41 B7 04 00 00 01   ��!����?�A�����
0020: 00 2F C3 00 00 00 00 00 00 00 00 00 00 00 9B 00   �/��������������
0030: 00 00 00 00 00 00 00 FF FF 1B 00 00 00 00 00 00   ����������������
0040: 00 00 00 00 00 03 02 00 00 00 00 00 00 00 01 1C   ����������������

      Bytes: $000000-00000F - Module type ("C128MEM"), padded with $00
              000010-000011 - Module version $00/00 (major/minor)
              000012-000015 - Module size (lo/hi), including this header
              000016-000021 - MMU registers (MMU)
              000022-020020 - 128K RAM dump (banks 0 and 1)
 

---------------------------------------------------------------------------


The C128ROM Module:

Chip type: ROMs - Dump of the system ROMs (optional)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 31 32 38 52 4F 4D 00 00 00 00 00 00 00 00 00   C128ROM���������
0010: 00 00 16 C0 00 00 A2 FF 78 9A D8 A9 00 8D 00 FF   ��������x�ة����
0020: A2 0A BD 4B E0 9D 00 D5 CA 10 F7 8D 04 0A 20 CD   ���K������������
0030: E0 20 F0 E1 20 42 E2 20 09 E1 20 3D F6 48 30 07   �����B�����=�H0�
0040: A9 A5 CD 02 0A F0 03 20 93 E0 20 56 E0 20 00 C0   �����������V����

      Bytes: $000000-00000F - Module type ("C128ROM"), padded with $00
              000010-000011 - Module version $00/00 (major/minor)
              000012-000015 - Module size (lo/hi), including this header
              000016-002015 - KERNAL ROM dump
              002016-00A015 - BASIC ROM dump
              00A016-00B015 - EDITOR ROM dump
              00B016-00C016 - CHARGEN ROM dump


---------------------------------------------------------------------------


The VIC20MEM Module:

Chip type: RAM - Holds the RAM  contents  of  the  VIC20.  This  module  is
                 mandatory.

  The size of the VIC20 memory modules differs with each  different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded. The attached cartridges are also restored upon
load if they have been saved in the snapshot.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 43 32 30 4D 45 4D 00 00 00 00 00 00 00 00   VIC20MEM��������
0010: 01 00 17 A8 00 00 2F 4C 48 D2 AA D1 91 D3 22 22   ������/LHҪё�""
0020: 00 00 00 00 FF 00 00 00 00 00 00 00 00 19 16 00   ����������������
0030: 0A 76 C3 00 00 00 00 00 00 76 C3 B3 DD 00 00 00   �v�������vó����
0040: 00 00 01 12 03 12 03 12 03 12 00 80 00 00 00 80   ����������������

      Bytes: $0000-000F - Module type ("VIC20MEM"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Configuration register: (CONFIG)
                            Bit 0 set: 3K RAM block present at $0400-0FFF
                            Bit 1 set: 8K RAM block present at $2000-3FFF
                            Bit 2 set: 8K RAM block present at $4000-5FFF
                            Bit 3 set: 8K RAM block present at $6000-7FFF
                            Bit 5 set: 8K RAM block present at $A000-BFFF
              0017-0416 - 1K RAM dump ($0000-03FF)
              0417-1416 - 4K RAM dump ($1000-1FFF)
              1417-1B16 - 2K Color RAM ($9400-9BFF)
              1B17-2816 - 3K RAM dump ($0400-0FFF, if CONFIG bit 0 set)
              2817-4816 - 8K RAM dump ($2000-3FFF, if CONFIG bit 1 set)
              4817-6816 - 8K RAM dump ($4000-5FFF, if CONFIG bit 2 set)
              6817-8816 - 8K RAM dump ($6000-7FFF, if CONFIG bit 3 set)
              8817-A816 - 8K RAM dump ($A000-BFFF, if CONFIG bit 5 set)


---------------------------------------------------------------------------


The VIC20ROM Module:

Chip type: ROMs - Holds the ROM of the VIC20, including  possibly  attached
                  cartridges (optional)

  The size of the VIC20 memory modules differs with each  different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded. The attached cartridges are also restored upon
load if they have been saved in the snapshot.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 43 32 30 52 4F 4D 00 00 00 00 00 00 00 00   VIC20ROM��������
0010: 01 00 17 50 00 00 00 0F DC A5 61 C9 88 90 03 20   ���P����ܥaɈ���
0020: D4 DA 20 CC DC A5 07 18 69 81 F0 F3 38 E9 01 48   ����ܥ��i���8��H
0030: A2 05 B5 69 B4 61 95 61 94 69 CA 10 F5 A5 56 85   ���i�a�a�i����V�
0040: 70 20 53 D8 20 B4 DF A9 C4 A0 DF 20 56 E0 A9 00   p�S���ߩĠ��V���
0050: 85 6F 68 20 B9 DA 60 85 71 84 72 20 CA DB A9 57   �oh���`�q�r��۩W

      Bytes: $0000-000F - Module type ("VIC20ROM"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - ROM configuration byte (CONFIG)
                            Bit 0: 1= ROM block $2xxx enabled.
                            Bit 1: 1= ROM block $3xxx enabled.
                            Bit 4: 1= ROM block $6xxx enabled.
                            Bit 5: 1= ROM block $7xxx enabled.
                            Bit 6: 1= ROM block $Axxx enabled.
                            Bit 7: 1= ROM block $Bxxx enabled.
              0017-2016 - 8K KERNAL ROM dump ($E000-FFFF)
              2017-4016 - 8K BASIC ROM dump ($C000-DFFF)
              4017-5016 - 4K Character ROM dump
              5017-6016 - 4K ROM image of $2xxx (if CONFIG Bit 0 set)
              6017-7016 - 4K ROM image of $3xxx (if CONFIG Bit 1 set)
              7017-8016 - 4K ROM image of $6xxx (if CONFIG Bit 4 set)
              8017-9016 - 4K ROM image of $7xxx (if CONFIG Bit 5 set)
              9017-A016 - 4K ROM image of $Axxx (if CONFIG Bit 6 set)
              A017-B016 - 4K ROM image of $Bxxx (if CONFIG Bit 7 set)


---------------------------------------------------------------------------


The VIC-I Module:

Chip type: 656x - The VIC-I of the VIC20

(Breakdown not available as this module is still under contruction.)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 43 2D 49 00 00 00 00 00 00 00 00 00 00 00   VIC-I�����������
0010: 00 00 2B 08 00 00 01 00 00 00 00 06 06 06 06 06   ��+�������������
0020: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06   ����������������
0030: 06 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01   ����������������
0040: 01 01 01 01 01 01 01 06 06 06 06 06 06 06 06 06   ����������������

      Bytes: $0000-000F - Module type ("VIC-I"), padded with $00
              0010-0011 - Module version $00/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-xxxx - VIC-I register contents


---------------------------------------------------------------------------


The VIA1 Module:

Chip type: 6522 (the VIA for the interrupts and the keyboard)

  The VIA 6522 is the predecessor of the CIA and also an I/O port chip with
2 8-bit I/O ports, a shift register, two timers and interrupts.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 41 31 00 00 00 00 00 00 00 00 00 00 00 00   VIA1������������
0010: 01 00 2C 00 00 00 00 00 F7 FF 26 48 05 2C FF AB   ��,�������&H�,��
0020: F9 80 00 40 DE 00 40 00 00 80 FF 00 .. .. .. ..   ���@��@�����....

      Bytes: $0000-000F - Module type ("VIA1"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Output register A (ORA)
                   0017 - Data direction register A (DDRA)
                   0018 - Output register B (ORB)
                   0019 - Data direction register B (DDRB)
              001A-001B - Timer 1 Latch value (T1L)
              001C-001D - Timer 1 counter value (T1C)
                   001E - Timer 2 latch (T2L)
                          (8 bit as only lower byte is used)
              001F-0020 - Timer 2 counter value (T2C)
                   0021 - RUNFL
                          bit 7: timer 1 will generate IRQ on underflow
                          bit 6: timer 2 will generate IRQ on underflow
                   0022 - Shift register value (SR)
                   0023 - Auxiliary control register (ACR)
                   0024 - Peripheral control register (PCR)
                   0025 - active interrupts (IFR)
                   0026 - interrupt mask (IER)
                   0027 - PB7 - bit 7 = pb7 state
                   0028 - number of half-bits to shift out on SR (SRHBITS)
                   0029 - CABSTATE
                          bit 7: state of CA2 pin
                          bit 6: state of CB2 pin
                   002A - Port A Input Latch (see ACR bit 0) (ILA)
                   002B - Port B Input Latch (see ACR bit 1) (ILB)


---------------------------------------------------------------------------


The VIA2 Module:

Chip type: 6522 (the VIA for the userport, IEC-bus and RS232)

(see the VIA1 module for details)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 56 49 41 32 00 00 00 00 00 00 00 00 00 00 00 00   VIA2������������
0010: 01 00 2C 00 00 00 00 80 00 00 FF FF CE 66 FF AB   ��,����������f��
0020: F9 00 00 40 FE 00 02 80 00 C0 7C 00 .. .. .. ..   ���@������|�....

      Bytes: $0000-000F - Module type ("VIA2"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-002B - See the VIA1 breakdown for details


--------------------------------------------------------------------------


The PETMEM Module:

Chip type: RAM - Holds  the  RAM  contents  of  the  PET.  This  module  is
                 mandatory.

  The size of the PET memory modules differs  with  each  different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 50 45 54 4D 45 4D 00 00 00 00 00 00 00 00 00 00   PETMEM����������
0010: 01 02 1D 88 00 00 02 00 20 00 07 4C 73 C3 22 22   �����������Ls�""
0020: 5B 00 FF 00 01 00 00 00 00 00 00 00 FF FF 16 13   [���������������
0030: 00 08 12 B3 00 00 00 00 00 00 12 B3 E9 CE 00 00   ����������������
0040: 00 00 00 01 04 03 04 03 04 03 04 00 80 00 00 00   ����������������

      Bytes: $0000-000F - Module type ("PETMEM"), padded with $00
              0010-0011 - Module version $01/02 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Configuration value.
                          Bits 0-3: 0 = 40 col PET without CRTC
                                    1 = 40 col PET with CRTC
                                    2 = 80 col PET (with CRTC)
                                    3 = SuperPET
                                    4 = 8096
                                    5 = 8296
                             Bit 6: 1= RAM at $9***
                             Bit 7: 1= RAM at $A***
                   0017 - Keyboard type.
                           0 = UK business
                           1 = Graphics
                           2 = German business
                   0018 - memory size of low 32k in k
                            (possible values 4, 8, 16, 32)
                   0019 - Value of the 8x96 configuration register
                           (CONF8X96)
                   001A - SuperPET config
                              Bit 0: 1 = $9*** RAM enabled
                              Bit 1: 1 = RAM write protected
                              Bit 2: 1 = CTRL register write protected
                              Bit 3: 0 = DIAG pin active
                           Bits 4-7: RAM block in use
              001B-xxxx - 4-32k RAM (not 8296, size depends on MEMSIZE)
              xxxx-xxxx - 2/4k VRAM (not 8296, size depends on CONFIG)
              xxxx-xxxx - 64k expansion RAM (SuperPET and 8096 only)
              xxxx-xxxx - 128k RAM (8296 only)
                   xxxx - POSITIONAL
                           bit 0: 0 = symbolic keyboard mapping
                           bit 0: 1 = positional mapping

The last item has been added in PETMEM snapshot version 1.1. It is  ignored
by earlier restore routines (V1.0) and the V1.1  restore  routines  do  not
change the current setting when reading a V1.0 snapshot.


--------------------------------------------------------------------------


The PETROM Module:

Chip type: ROMs - Holds the ROM of the  PET,  including  possibly  attached
                  cartridges (optional)

  The size of the PET memory modules differs  with  each  different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 50 45 54 52 4F 4D 00 00 00 00 00 00 00 00 00 00   PETROM����������
0010: 01 00 17 50 00 00 04 54 4F 4F 20 4D 41 4E 59 20   ���P���TOO�MANY�
0020: 46 49 4C 45 D3 46 49 4C 45 20 4F 50 45 CE 46 49   FILE�FILE�OPE�FI
0030: 4C 45 20 4E 4F 54 20 4F 50 45 CE 46 49 4C 45 20   LE�NOT�OPE�FILE�
0040: 4E 4F 54 20 46 4F 55 4E C4 0D 53 45 41 52 43 48   NOT�FOUN��SEARCH

      Bytes: $0000-000F - Module type ("PETROM"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - CONFIG
                           Bit 0: 1 = $9*** ROM included
                           Bit 1: 1 = $A*** ROM included
                           Bit 2: 1 = $B*** ROM included
                           Bit 3: 1 = $e900-$efff ROM included
              0017-xxxx - 4k KERNAL ROM image $f000-$ffff
              xxxx-xxxx - 2k EDITOR ROM image $e000-$e7ff
              xxxx-xxxx - 2k CHARGEN ROM image
              xxxx-xxxx - 4k $9*** ROM image (if CONFIG & 1)
              xxxx-xxxx - 4k $A*** ROM image (if CONFIG & 2)
              xxxx-xxxx - 4k $B*** ROM image (if CONFIG & 4)
              xxxx-xxxx - 4k $C*** ROM image
              xxxx-xxxx - 4k $D*** ROM image
              xxxx-xxxx - 7 blocks $e900-$efff ROM image (if CONFIG & 8)


--------------------------------------------------------------------------


The CRTC Module:

Chip type: 6545 - The CRTC of the PET, C6x0 and  C7x0.  This  can  even  be
                  included if it is a dump of a PET without CRTC.

This module is  still  under  construction.  The  values  for  RASTERY  and
RASTERLINE might be bogus.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 52 54 43 00 00 00 00 00 00 00 00 00 00 00 00   CRTC������������
0010: 01 00 55 00 00 00 FF 07 00 08 00 20 00 10 FF 1F   ��U�������������
0020: 00 10 00 02 00 3F 28 32 08 20 10 19 1D 00 08 00   �����?(2��������
0030: 00 10 00 00 00 00 00 00 00 00 00 1F 06 00 00 00   ����������������
0040: 00 10 B0 09 00 00 00 C0 02 1A 01 00 00 00 00 1C   ����������������
0050: 00 39 01 1D 01 .. .. .. .. .. .. .. .. .. .. ..   �9���...........

      Bytes: $0000-000F - Module type ("CRTC"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-0054 - ????


--------------------------------------------------------------------------


The PIA1 Module:

Chip type: 6520 (the PIA for the interrupts, tape and the keyboard)

  The PIA 6520 is a chip with two I/O ports  (Parallel  Interface  Adapter)
and four additional handshake lines. The chip is much the same for  Port  A
and B, only that Port A implements handshaking on read operation and port B
on the write operation.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 50 49 41 31 00 00 00 00 00 00 00 00 00 00 00 00   PIA1������������
0010: 01 00 1D 00 00 00 F9 0F 3C FF 00 3D C0 .. .. ..   ��������<��=�...

      Bytes: $0000-000F - Module type ("PIA1"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Output register A (ORA)
                   0017 - Data Direction Register A (DDRA)
                   0018 - Control Register A (CTRLA)
                   0019 - Output register B (ORB)
                   001A - Data Direction Register B (DDRB)
                   001B - Control Register B (CTRLB)
                   001C - Bit 7:state of CA2, Bit 6:state of CB2 (CABSTATE)


--------------------------------------------------------------------------


The PIA2 Module:

Chip type: 6520 (the PIA for the IEEE488-bus)

(see the PIA1 module for details)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 50 49 41 32 00 00 00 00 00 00 00 00 00 00 00 00   PIA2������������
0010: 01 00 1D 00 00 00 FF 00 3C FF FF 3C C0 .. .. ..   ��������<��<�...

      Bytes: $0000-000F - Module type ("PIA2"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-001C - See the PIA1 breakdown for details


--------------------------------------------------------------------------


The VIA Module:

Chip type: 6522 (the VIA for IEEE488, userport, sound)

(see the VIA1 module for details)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F         ASCII
      -----------------------------------------------    ----------------
0000: 56 49 41 00 00 00 00 00 00 00 00 00 00 00 00 00    VIA�������������
0010: 01 00 2C 00 00 00 00 00 DF 1E FF FF CE 7B 0E 58    ��,����������{�X
0020: 77 00 00 00 0E 40 00 80 00 C0 00 DF .. .. .. ..    w����@������....

      Bytes: $0000-000F - Module type ("VIA"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-002B - See the VIA1 breakdown for details


--------------------------------------------------------------------------


The CBM2MEM Module:

Chip type: RAM - Holds the RAM contents of the CBM-II  models.  Also  holds
                 the exec-bank and indirection bank registers. This  module
                 is mandatory.

  The size of the CBM-II memory modules differs with each different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 42 4D 32 4D 45 4D 00 00 00 00 00 00 00 00 00   CBM2MEM���������
0010: 01 00 1B 10 02 00 01 00 02 0F 01 0F 01 4C A7 9B   �������������L��
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00   ����������������
0030: 00 00 D4 FA 02 00 FF FF 00 FF FF C8 FA 5E FA 01   �������������^��
0040: 00 00 00 00 00 00 00 00 03 00 05 00 02 00 00 00   ����������������
0050: 02 00 00 00 02 00 BD FA 00 00 BD FA 02 00 FF 00   ����������������
0060: 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00   ����������������

      Bytes: $0000-000F - Module type ("CBM2MEM"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Memory size in 128k blocks (MEMSIZE)
                           (1=128k, 2=256k, 4=512k, 8=1024k)
                   0017 - MEMCONFIG
                           Bit 0 = $f0800-$f0fff RAM
                           Bit 1 = $f1000-$f1fff RAM
                           Bit 2 = $f2000-$f3fff RAM
                           Bit 3 = $f4000-$f5fff RAM
                           Bit 4 = $f6000-$f7fff RAM
                           Bit 5 = $fc000-$fcfff RAM
                   0018 - HWCONFIG
                           Bit 0: 0 = CRTC
                                  1 = VIC-II video chip
                                       (Basically the destinction between
                                        C500 and C600/700)
                   0019 - CPUs execution bank register (EXECBANK)
                   001A - CPUs indirection bank register (INDBANK)
              001B-xxxx - 2k system RAM $f0000-$f07ff
              xxxx-xxxx - 2k video RAM $fd000-$fd7ff
              xxxx-xxxx - RAM dump, size according to MEMSIZE
              xxxx-xxxx - if memsize < 1M and CONFIG & 1 then
                            2k RAM $f0800-$f0fff
              xxxx-xxxx - if memsize < 1M and CONFIG & 2 then
                            4k RAM $f1000-$f1fff
              xxxx-xxxx - if memsize < 1M and CONFIG & 4 then
                            8k RAM $f2000-$f3fff
              xxxx-xxxx - if memsize < 1M and CONFIG & 8 then
                            8k RAM $f4000-$f5fff
              xxxx-xxxx - if memsize < 1M and CONFIG & 16 then
                            8k RAM $f6000-$f7fff
              xxxx-xxxx - if memsize < 1M and CONFIG & 32 then
                            4k RAM $fc000-$fcfff

The RAM arrays are only saved if the RAM itself is less  than  1M.  If  the
memory size is 1M then those areas are taken from the bank 15 area  of  the
normal RAM.


--------------------------------------------------------------------------


The CBM2ROM Module:

Chip type: ROMs - Holds the ROM images (optional)

  The size of the CBM-II memory modules differs with each different  memory
configuration. The RAM configuration is saved in the snapshot, and restored
when the snapshot is loaded.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 42 4D 32 52 4F 4D 00 00 00 00 00 00 00 00 00   CBM2ROM���������
0010: 01 00 17 70 00 00 00 4C 09 EE EA 4C 44 E0 4C FE   ���p���L���LD�L�
0020: E0 4C 79 E1 4C 99 E2 4C 3F E0 4C 65 E8 4C DA E0   �Ly�L��L?�Le�L��
0030: 4C 25 E0 4C 3A E0 4C 70 E9 4C F8 E6 B0 0E 86 CA   L%�L:�Lp�L������
0040: 86 CF 84 CB 84 CE 20 CD E0 20 DA E0 A6 CA A4 CB   �τ˄��������ʤ�
0050: 60 A2 00 A0 DC 60 A2 50 A0 19 60 A9 00 A2 23 95   `����`�P��`���#�

      Bytes: $0000-000F - Module type ("CBM2ROM"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - CONFIG
                           Bit 1: 1 = $1*** ROM image included
                           Bit 2: 1 = $2000-$3fff ROM image included
                           Bit 3: 1 = $4000-$5fff ROM image included
                           Bit 4: 1 = $6000-$7fff ROM image included
              0017-xxxx - 8k KERNAL ROM image ($e000-$efff)
              xxxx-xxxx - xK BASIC ROM image
              xxxx-xxxx - 4k CHARGEN ROM image
              xxxx-xxxx - 4k cartridge ROM image for $1***
                           (if CONFIG & 2)
              xxxx-xxxx - 8k cartridge ROM image for $2000-$3fff
                           (if CONFIG & 4)
              xxxx-xxxx - 8k cartridge ROM image for $4000-$5fff
                           (if CONFIG & 8)
              xxxx-xxxx - 8k cartridge ROM image for $6000-$7fff
                           (if CONFIG & 16)


--------------------------------------------------------------------------


The TPI1 Module:

Chip type: 6525 (TPI 1 for IEEE488)

  The TPI 6525 is a chip with three I/O ports (Tri-Port-Interface). One  of
the ports can double as an interrupt prioritizer. Therefore we also have to
save the states of the interrupt stack etc.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 54 50 49 31 00 00 00 00 00 00 00 00 00 00 00 00   TPI1������������
0010: 01 00 20 00 00 00 38 3F 00 3F 7D FF E3 00 00 40   ������8?�?}����@

      Bytes: $0000-000F - Module type ("TPI1"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Port A output register (PRA)
                   0017 - Port B output register (PRB)
                   0018 - Port C output register (PRC)  -  Doubles  as  IRQ
                          latch register
                   0019 - Port A data direction register (DDRA)
                   001A - Port B data direction register (DDRB)
                   001B - Port C data direction register (DDRC)  -  Doubles
                          as IRQ mask register
                   001C - Control Register (CR)
                   001D - Active interrupt register
                   001E - Interrupt stack, the interrupt bits that are  not
                          yet saved (STACK)
                   001F - State of the CA/CB pins... (CABSTATE)
                            Bit 7: State of CA
                            Bit 6: State of CB


--------------------------------------------------------------------------


The TPI2 Module:

Chip type: 6525 (TPI 2 for interrupts and keyboard)

(see the TPI1 module for details)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 54 50 49 32 00 00 00 00 00 00 00 00 00 00 00 00   TPI2������������
0010: 01 00 20 00 00 00 7F FF 00 FF FF 00 00 00 00 00   ���������������

      Bytes: $0000-000F - Module type ("TPI2"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-001F - See the TPI1 breakdown for details


--------------------------------------------------------------------------


The ACIA1 Module:

Chip type: 6551 - An ACIA (RS232 interface) at $DE00 (C64,  optional)  (or)
                  The ACIA for the SuperPET or CBM-II (optional)

  The ACIA 6551 is an RS232 interface chip. VICE emulates RS232 connections
via /dev/ttyS* (Unix) or COM: (DOS/WIN - not yet?). When saving a snapshot,
those connections are of course lost. The state  of  the  ACIA  however  is
restored if possible. I.e. if a connection is already open  when  restoring
the snapshot, this connection is used instead. If no connection is open,  a
carrier/DTR drop is emulated.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 41 63 69 61 31 00 00 00 00 00 00 00 00 00 00 00   Acia1�����������
0010: 01 00 20 00 00 00 00 00 10 00 00 00 00 00 00 00   ����������������

      Bytes: $0000-000F - Module type ("ACIA1"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
                   0016 - Transmit data register (TDR)
                   0017 - Receiver data register (RDR)
                   0018 - Status register (SR)
                   0019 - Command register (CMD)
                   001A - Control register (CTRL)
                   001B -   0 = no data to tx
                            1 = Data is being transmitted
                            2 = Data is being transmitted while data in TDR
                                waiting to  be  put  to  internal  transmit
                                register
              001C-001F - Clock ticks till the next TDR empty interrupt


--------------------------------------------------------------------------


The TPI Module:

Chip type: 6525 (TPI at $DF00 for a parallel  IEEE488  interface,  optional
           module on the C64)

(see the TPI1 module for details)

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 54 50 49 00 00 00 00 00 00 00 00 00 00 00 00 00   TPI�������������
0010: 01 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������

      Bytes: $0000-000F - Module type ("TPI"), padded with $00
              0010-0011 - Module version $01/00 (major/minor)
              0012-0015 - Module size (lo/hi), including this header
              0016-001F - See the TPI1 breakdown for details


--------------------------------------------------------------------------

*** WAV (RIFF audio files) Resource Interchange File Format
*** Document revision: 1.1
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Various net documents

  The WAV file is a variant of  the  RIFF  format,  specifically  used  for
audio. RIFF is a generic format used mainly for video (AVI) and  audio.  It
is built up with "chunks" which contain a chunk ID and a chunk size.

  Below is a dump of a sample WAV file showing the header.

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
      -----------------------------------------------  ----------------
0000: 52 49 46 46 D4 45 CC 01 57 41 56 45 66 6D 74 20  RIFF�E��WAVEfmt�
0010: 10 00 00 00 01 00 02 00 44 AC 00 00 10 B1 02 00  ��������D�������
0020: 04 00 10 00 64 61 74 61 B0 45 CC 01 95 00 6D FF  ����data�E����m�
0030: 97 00 77 FF 6E 00 25 FF 58 00 14 FF 75 00 ED FE  ��w�n�%�X���u���
0040: 62 00 33 FE 2C 00 07 FE C4 FF 7A FE 53 FF C3 FE  b�3�,�����z�S���
0050: 91 FF 83 FE 21 00 91 FE EB 00 0D FF FF 00 57 FF  ����!���������W�
0060: 98 00 C4 FF 9F 00 79 00 60 00 DD 00 07 00 1D 01  ������y�`�������


     $0000-0003: Chunk ID  "RIFF"  in  ASCII  ("RIFX"  files  identify  the
                 samples audio data in hi/lo format instead of  the  normal
                 lo/hi format)

      0004-0007: Chunk size (lo/hi) $01CC45D4=30,164,452 is the total  size
                 minus 8 (these first 8  bytes  are  not  included  in  the
                 overall size)

      0008-000B: Chunk format "WAVE". This format requires two subchunks to
                 exist, "fmt " and "data".

      000C-000F: Subchunk1 ID "fmt ". This describes the format of the next
                 DATA subchunk.

      0010-0013: Subchunk size (lo/hi) $00000010 (usually  this  value  for
                 PCM audio)

      0014-0015: Audio format (1=PCM, 2 and higher are custom) ($0001)
                 - $0001 = standard PCM
                 - $0101 = IBM mu-law (custom)
                 - $0102 = IBM a-law (custom)
                 - $0103 = IBM AVC ADPCM (custom)

      0016-0017: Number of channels (1=mono, 2=stereo, etc) ($0002)

      0018-001B: Sample rate per second (lo/hi) $0000AC44 = 44100

      001C-001F: Byte rate per second (=sample rate * number of channels  *
                 (bits per channel/8)) $0002B110 = 176400

      0020-0021: Block Align (=number of  channels  *  bits  per  sample/8)
                 ($0004).

      0022-0023: Bits per sample (8=8 bits, 16=16  bits)  ($0010).  Samples
                 not using the entire bit range allocated  should  set  the
                 unused bits off.

      0024-0027:  Subchunk2  ID  "data".  This  chunk  contains  the  audio
                 samples. There can be more than one in a WAV file.

      0028-002B: Subchunk2 size (lo/hi) ($01CC45B0=30,164,400)

      002C-xxxx: Audio data (lo/hi),  stored  as  2's  complimented  signed
                 integers in the following order:

                   Sample 1: Channel1 (left)   ($0095=+149)
                   Sample 1: Channel2 (right)  ($FF6D=-)
                   Sample 2: Channel1 (left)   ($0097=+151)
                   Sample 2: Channel2 (right)  ($FF77=-)
                   Sample 3: Channel1 (left)   ($006E=+110)
                   Sample 3: Channel2 (right)  ($FF25=-)

Notes: 8-bit samples are stored as  unsigned  chars,  with  values  ranging
       ranging from 0-255. 16-bit samples are stored  as  signed  integers,
       with values ranging from -32768 to 32767

        00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
        -----------------------------------------------  ----------------
2D402C: 4C 49 53 54 40 00 00 00 49 4E 46 4F 49 53 46 54  LIST@���INFOISFT
2D403C: 15 00 00 00 53 6F 6E 79 20 53 6F 75 6E 64 20 46  ����Sony�Sound�F
2D404C: 6F 72 67 65 20 37 2E 30 00 00 49 45 4E 47 02 00  orge�7.0��IENG��
2D405C: 00 00 20 00 49 43 52 44 0B 00 00 00 32 30 30 33  ����ICRD����2003
2D406C: 2D 31 30 2D 31 37 00 02 .. .. .. .. .. .. .. ..  -10-17��........

  Above is a dump of the end of a WAV file, with the LIST information chunk
shown. The four bytes (40  00  00  00)  immediately  following  the  "LIST"
identifier show the size of the LIST chunk, in LO/HI format. In this  case,
the chunk size is $00000040, or 64 bytes.


          00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F       ASCII
          -----------------------------------------------  ----------------
02F488AC: 63 75 65 20 C4 00 00 00 08 00 00 00 01 00 00 00  cue�������������
02F488BC: 00 C0 21 00 64 61 74 61 00 00 00 00 00 00 00 00  ��!�data��������
02F488CC: 00 C0 21 00 02 00 00 00 00 40 11 00 64 61 74 61  ��!������@��data
02F488DC: 00 00 00 00 00 00 00 00 00 40 11 00 03 00 00 00  ���������@������
02F488EC: 00 00 3A 00 64 61 74 61 00 00 00 00 00 00 00 00  ��:�data��������
02F488FC: 00 00 3A 00 04 00 00 00 00 00 59 00 64 61 74 61  ��:�������Y�data
02F4890C: 00 00 00 00 00 00 00 00 00 00 59 00 05 00 00 00  ����������Y�����
02F4891C: 00 C0 6C 00 64 61 74 61 00 00 00 00 00 00 00 00  ��l�data��������
02F4892C: 00 C0 6C 00 06 00 00 00 00 40 84 00 64 61 74 61  ��l������@��data
02F4893C: 00 00 00 00 00 00 00 00 00 40 84 00 07 00 00 00  ���������@������
02F4894C: 00 80 9A 00 64 61 74 61 00 00 00 00 00 00 00 00  ����data��������
02F4895C: 00 80 9A 00 08 00 00 00 00 00 AC 00 64 61 74 61  ������������data
02F4896C: 00 00 00 00 00 00 00 00 00 00 AC 00 4C 49 53 54  ������������LIST
02F4897C: 84 00 00 00 61 64 74 6C 6C 61 62 6C 07 00 00 00  ����adtllabl����
02F4898C: 01 00 00 00 30 31 00 00 6C 61 62 6C 07 00 00 00  ����01��labl����
02F4899C: 02 00 00 00 30 32 00 00 6C 61 62 6C 07 00 00 00  ����02��labl����
02F489AC: 03 00 00 00 30 33 00 00 6C 61 62 6C 07 00 00 00  ����03��labl����
02F489BC: 04 00 00 00 30 34 00 00 6C 61 62 6C 07 00 00 00  ����04��labl����
02F489CC: 05 00 00 00 30 35 00 00 6C 61 62 6C 07 00 00 00  ����05��labl����
02F489DC: 06 00 00 00 30 36 00 00 6C 61 62 6C 07 00 00 00  ����06��labl����
02F489EC: 07 00 00 00 30 37 00 00 6C 61 62 6C 07 00 00 00  ����07��labl����
02F489FC: 08 00 00 00 30 38 00 00 .. .. .. .. .. .. .. ..  ����08��........

  Above is the "cue " chunk layout, also at  the  end  of  the  WAV.  These
describe cue points (or markers) placed in the WAV file.


  To analyse a WAV file quickly is very easy:

    1. Examine the initial chunk ID (RIFF) and its size. The size should be
       the filesize-8.

    2. Check for the WAVE chunk ID next. If it's not there then  you  don't
       have a proper WAV file.

    3. Now you can start checking the  individual  sub-chunks.  Read  in  8
       bytes. The first four are the sub-chunk ID and the last four are the
       sub-chunk size. If you want to check the contents of  the  sub-chunk
       thats up to you.

    4. If you seek forward in the file the size of the sub-chunk  you  will
       find yourself at the next sub-chunk.


  WAV files can also have other sub-chunk ID's such as FACT, ASFP and LIST.
I will not get into the specifics of these. There are other more  extensive
documents on the web that describe the WAV and RIFF format much better than
I can.

*** WRA, WR3 (WRAptor compressed files, and version 3.0 files)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Todd Elliott,
                          Fender Tucker & Doreen Horne (Loadstar)

  Written by Bill Lucier (copyright 1995), distributed by Loadstar (on disk
and from the website), and  fixed/updated  by  Doreen  Horne,  this  is  an
uncommon compression format as it is a relatively new program.  It  handles
PRG, SEQ, USR and GEOS files (Sequential and VLIR), but not REL  files.  As
of this writing, the latest bug fixed version was 3.0B. It is  the  support
for compressing GEOS files which makes this program special.

  Many thanks to Fender Tucker (from Loadstar) and Doreen Horne  for  their
support on the Wraptor format, as well as authorizing the  release  of  the
source code, and subsequent  documentation  of  the  format.  I  hope  this
prolongs the life and usefulness of Wraptor.

  Wraptor  utilizes  a  variant  of  the  LZSS   (Lempel-Ziv)   compression
algorithm, starting at 9 bits per code. The following is a dump of a sample
WRA file. The four bytes at the beginning of the file, "FF 42  4C  FF"  are
the signature, and preceed each compressed file in the archive. The "42 4C"
are the authors initials, "BL".

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: FF 42 4C FF 50 4F 4F 59 41 4E 00 02 00 82 04 60   �BL�POOYAN�.��.`
0010: 80 50 01 16 41 59 0C 14 F0 81 0C 47 49 31 11 40   �P..AY..��.GI1.@
0020: 9E 4F 2C 90 49 C2 E2 61 3C 82 44 22 94 84 42 C1   �O,�I��a<�D"��B�
0030: C0 B0 62 00 21 82 02 90 62 0C 61 63 19 43 D4 4D   �b�!�.�b.ac.C�M
0040: 20 92 49 D1 F3 13 41 01 E0 02 78 68 37 1C 0D 40   ��I��.A.�.xh7..@
0050: 14 E1 40 00 DD 0B FF 42 4C FF 50 4F 4F 59 41 4E   .�@��.�BL�POOYAN
0060: 2E 4D 41 49 4E 00 02 7E 0C 0A B0 31 31 00 08 00   .MAIN�.~..�11�.�
0070: 00 09 40 00 05 2A 00 02 A5 54 3C 81 10 88 00 08   ��@�.*�.�T<�.��.

  Byte: $00-03: FF 42 4C FF          - Compressed file signature "�BL�"
         04-xx: 50 4F 4F 59 41 4E 00 - File name "POOYAN", terminated  with
                                       a $00 (null) byte
                02                   - File type
                                         01 = SEQ
                                         02 = PRG
                                         03 = USR
                                         04 = GEOS

  What follows the filetype is compressed file data,  up  until  two  bytes
before the next signature, or two bytes to the end of the  file,  whichever
comes first. The two bytes at the end comprise the 16-bit CRC value.

  The Wraptor format does not include information in the header that  would
normally be considered important for generic decompression, such as:

  1. No original or compressed file sizes
  2. No offset to show where the next compressed file starts
  3. No version# info, to know if the decompressor you have is the  correct
     type to uncompress the file. This is determined by the file extension,
     with WR3 being the newest. WRA represents version 1.x and 2.x.


  The original release of Wraptor  (version  1.x)  contained  a  few  bugs,
specifically dealing with the compression and decompression of certain GEOS
filetypes, with all of the other file types (PRG,  SEQ,  USR)  being  fine.
Version 2.x was released, but more bugs with GEOS files  were  found.  Thus
version 3.x was released.

  As of version 3.x, the earlier WRA files are no  longer  supported,  only
the WR3 files. To decode WRA files, you can either use a pre-3.0 version of
Wraptor, or rename the files to end with WR3 and  see  if  version  3  will
unwrap them. If they contain a faulty compressed GEOS file, the file  might
not decompress properly.


  You can get a list of files contained in a WRA/WR3 file by using  one  of
the following two methods:

   1. Decompress each file in succession, a tedious task  at  the  best  of
      times. This *is* the method WRAptor uses to  display  and  decompress
      files in its archives, and it is very slow!

   2. Scan the whole file for the "FF 42 4C FF" signature  preceeding  each
      file, and store the starting offsets. There may  be  the  possibility
      that this signature will show up in the normal compressed  data,  but
      the odds are very low.


  The Wraptor compression on PRG, SEQ and  USR  files  is  very  simple  to
decode. GEOS files are the exception  as  they  need  to  be  reconstructed
exactly as they were, VLIR chains and all. The following C program explains
how basic decompression works, but not for GEOS:


---------------------------------------------------------------------------

/*

   The following code assumes you  have  already  read  in  the  signature,
   filename+NULL and filetype byte, and simply want to decode the data.
   There is no provision made to decode the GEOS data, or actually show how
   to calculate the CRC

*/

void main(void)
{
  FILE *readfile, *writefile;

  int i;

  char data, type, tmp, rep_length, read_bitsize;
  unsigned buff_pointer, dict_offset;

  /* Output stream buffer */
  char buffer[(unsigned)32768];

  /* Compressed file to decode */
  readfile=fopen("compress.wra","rb");

  /* Uncompressed output stream */
  writefile=fopen("uncompressed","wb");

  /* Initial bitsize of the dictionary lookup */
  read_bitsize=8;

  /* Clear buffer pointer */
  buff_pointer=0;

  while(1)
  {
    /* Get compressed yes/no flag (single bit) from the input stream */
    type=get_bits(1);

    /* Normal unencoded data, preceeded by a zero bit */
    if(!type)
    {
      /* Get normal 8-bit byte */
      data=get_bits(8);

      /* Add data to output buffer */
      buffer[buff_pointer]=data;

      /* Calculate the CRC as we read in the data */
      calc_crc(data);

      /* Move pointer for next data byte */
      buff_pointer++;

      /* Has the output buffer filled up? */
      if(buff_pointer>=(unsigned)32768)
      {
        /* Write out the buffer to the output file */
        /* Here is where we would decode the GEOS file structure */
        fwrite(buffer, 1, buff_pointer, writefile);

        /* Reset buffer pointer for another block of data */
        buff_pointer=0;
      }
    }

    /* Encoded data, preceeded by a one bit */
    else
    {
      /* Get dictionary offset */
      dict_offset=get_bits(read_bitsize);

      /* A "0" offset, either an EOF or increase read_bitsize by one */
      if(!dict_offset)
      {
        /* Check next bit */
        tmp=get_bits(1);

        /* If next bit clear, we are at the end of the compressed file */
        if(!tmp)
        {
          /* Write output buffer to the output file */
          /* Here is where we would decode the GEOS file structure */
          fwrite(buffer, 1, buff_pointer,writefile);
          buff_pointer=0;
          break;
        }
        /* If next bit set, increase read_bitsize by one */
        else
        {
          read_bitsize++;
        }
      }

      /* We have a valid offset, get the length */
      else
      {
        /* Length of the stored string, 5 bits */
        rep_length=get_bits(5);

        /*
          Copy the data from in the buffer at the dict_offset position  to
          the end of the buffer
        */

        for(i=0;i<rep_length;i++)
        {
          buffer[buff_pointer]=buffer[dict_offset-1+i];
          buff_pointer++;

          /* Write buffer to output file */
          /* Here is where we would decode the GEOS file structure */
          if(buff_pointer>=(unsigned)32768)
          {
            fwrite(buffer, 1, buff_pointer,writefile);
            buff_pointer=0;
          }
        }
      }
    }
  }

  /* Get the two-byte CRC which follows the compressed data stream */
  get_crc();

  /* Make sure the CRC you read matches the one you calculated */
  check_crc();

  fclose(readfile);
  fclose(writefile);
}


*** X64 (X64 and VICE emulator image files)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Jouko Valta

  This file type, created by Teemu Rantanen, is used on the X64 emulator (a
UNIX-based emulator) which has been superceeded by VICE. Both Vice and  X64
support the X64 file standard, with Vice also supporting  the  regular  D64
and T64 files.

  X64 is not a specific type of file, but rather  encompasses  *all*  known
C64 disk types (hard disk, floppies, etc). An X64 is created by  prepending
a 64-byte header to  an  existing  image  (1541,  1571,  etc)  and  setting
specific bytes which describe what type of image follows. This  header  has
undergone some revision, and this description file is  based  on  the  1.02
version, which was the last known at the time of writing.

  The most common X64 file you will  see  is  the  D64  variety,  typically
174912 bytes long (174848 for the D64 and 64 bytes for the header, assuming
no error bytes are appended). The header layout (as used in 64COPY)  is  as
follows:

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 43 15 41 64 01 02 01 23 00 00 00 00 00 00 00 00   C.Ad...#��������
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
0040: XX XX XX                     <- standard C64 image starts here....

   Bytes:$00-03: This is the "Magic header" ($43 $15 $41 $64)
             04: Header version major ($01)
             05: Header version minor ($01, now its up to $02)
             06: Device type represented ($00)
                  $00=1540 See note below...
                  $01=1541 (Default)
                  $02=1542
                  $03=1551
                  $04=1570
                  $05=1571
                  $06=1572
                  $08=1581
                  $10=2031,4031
                  $11=2040,3040
                  $12=2041
                  $18=4040
                  $20=8050
                  $21=8060
                  $22=8061
                  $30=SFD-1001
                  $31=8250
                  $32=8280
             07: Maximum tracks in image (only in version 1.02 or greater)
                  1540/41/70:  35
                        1571:  35
                        1581:  80 (Logical single-sided disk)
             08: Number of disk sides in image. This value must be $00  for
                 all 1541 and 1581 formats.
                  $00=No second side
                  $01=Second side
             09: Error data flag. I assume that if this  location  has  any
                 non-zero value in it, this will indicate the existance  of
                 the error bytes. For a description of the error bytes, see
                 the D64 topic dealing with extended formats.
          0A-1F: Unused, set to $00
          20-3E: Disk image description (in ASCII or ISO Latin/1)
             3F: Always set to $00
            40-: Standard C64 file begins here

  The first four bytes used for the device type at  position  $06  ($00  to
$03) are functionally the same, and are compatible with  older  version  of
X64 files. Some old X64 files might have $00 for the device  type  (instead
of $01), but it makes no real difference.

  As most instances of X64 files will be strictly 1541 images, bytes  08-3F
are set to zero, and some versions of the  X64  emulator  don't  use  bytes
08-3F.

  There is no advantage for PC users to use this format since virtually  no
PC emulator that I know of uses them, and for the most  part,  it  provides
the same functionality as a D64 file.

  In order to read a generic X64 file, first you must determine that it  is
an X64, and then determine the type of file it  contains.  In  effect,  you
have  to  double-decode  the  file,  which  makes  support  a  little  more
difficult. Also, you would have to be able to work with *all* of the  types
of drives that X64 supports, a daunting task.

  Its only advantage is that  is  encompasses  all  of  the  standard  disk
formats on the C64. If other disk types  were  common  (like  1581  or  CMD
disks), then this format might be more popular.

*** ZIP (PKZip compressed files)
*** Document revision: 1.3
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: net documents

  The files seen on the C64 are generally  PKZIP  1.1-compatible  archives,
using the older IMPLODE algorithm, which are decompressible on the C64/C128
using various utilities. All versions of PKUNZIP (and compatible  programs)
will also handle the older archives. The explanation I provide below covers
up to the newest version PKZIP at the time of writing this document, 2.04g.

  They always start with the 'PK' string at the beginning of the file,  and
the first filename follows very closely. The example  archive  below  holds
4-pack ZipCode files, as the filename shows:

       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
       -----------------------------------------------   ----------------
00000: 50 4B 03 04 14 00 00 00 08 00 00 00 00 00 19 A1   PK..............
00010: EB 0D C2 45 00 00 50 69 00 00 07 00 00 00 31 21   ..............1!
00020: 4D 53 48 4F 57 E4 BC 7B 5C 53 47 DA 38 3E 67 CE   MSHOW...........

  Bytes: $00-03: PKZIP local file header signature ($50 $4B $03 $04,  first
                 two bytes are ASCII "PK"). This signature is used  at  the
                 beginning of *each* compressed file.
          04-05: Program version that created archive:
                  decimal value/10 = major version # (in this case 2)
                  decimal value%10 = minor version # (in this case .0)
          06-07: General purpose bit flags:
                  bit 0:    set - file is encrypted
                          clear - file is not encrytped
                  bit 1: if compression method 6 used (imploding)
                            set - 8K sliding dictionary
                          clear - 4K sliding dictionary
                  bit 2: if compression method 6 used (imploding)
                            set - 3 Shannon-Fano trees were used to  encode
                                    the sliding dictionary output
                          clear - 2 Shannon-Fano trees were used

                          For method 8 compression (deflate):
                           bit 2  bit 1
                             0      0    Normal (-en) compression
                             0      1    Maximum (-ex) compression
                             1      0    Fast (-ef) compression
                             1      1    Super Fast (-es) compression

                          Note:  Bits  1  and  2  are  undefined   if   the
                          compression method is any other than 6 or 8.
                  bit 3: if compression method 8 (deflate)
                            set - the fields crc-32,  compressed  size  and
                                  uncompressed size are set to zero in  the
                                  local header. The correct values are  put
                                  in  the   data   descriptor   immediately
                                  following the compressed data.

                  The upper three bits are reserved and used internally  by
                  the software when processing the zipfile.  The  remaining
                  bits are unused.
          08-09: Compression method:
                  0 - Stored (no compression)
                  1 - Shrunk
                  2 - Reduced with compression factor 1
                  3 - Reduced with compression factor 2
                  4 - Reduced with compression factor 3
                  5 - Reduced with compression factor 4
                  6 - Imploded
                  7 - Reserved for Tokenizing compression algorithm
                  8 - Deflated
          0A-0B: Last modified file time in MSDOS format
                  Bits 00-04: Seconds/2 (0-58, only even numbers)
                       05-10: Minutes (0-59)
                       11-15: Hours (0-23, no AM or PM)
          0C-0D: Last modified file date in MSDOS format
                  Bits 00-04: Day (1-31)
                       05-09: Month (1-12)
                       10-15: Year minus 1980
          0E-11: CRC-32 of file (low-high format)
          12-15: Compressed size of file (low-high format)
          16-19: Uncompressed size of file (low-high format)
          1A-1B: Filename length (FL)
          1C-1D: Extra field length, description (EFL)
          1E-(1E+FL-1): Filename
          (1E+FL)-(1E+FL+EFL-1): Extra field

  You will notice that in the above byte layout, there is no mention of C64
filetype. That particular field seems to be stored in the central directory
at the end of the ZIP archive.

  There are several other signatures used within the ZIP format.  The  byte
sequence 50 4B 01 02 is used  to  signify  the  beginning  of  the  central
directory while the byte sequence 50 4B 05 06 is used to show  the  end  of
the central directory.

  The above explanation is only included for completeness.  Without  source
code, it is almost impossible to work with ZIP archives.

*** DiskPacked ZipCode (4 or 5 file version, 1!xxxxxx, 2!xxxxxx, etc)
*** Document revision: 1.2
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Paul David Doherty

  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.

*** FilePacked ZipCode (A!xxxxxx, B!xxxxxx, etc)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Joe Forster/STA

  This is another rarely seen format, and is very similar to the Diskpacked
(4-pack) Zipcode in structure. It is comprised of a series of files denoted
by A!xxxxxx and B!xxxxxx, with letters instead  of  numbers  as  the  first
characters of the filename. It also contains one other file called X!xxxxxx
which contains a directory of the files stored in the overall archive. Here
is the layout of the files:

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: FF 03 A6 11 0A 01 08 0E 08 CE 07 9E 20 28 32 30   �������������(20
0010: 36 34 29 00 00 00 78 A9 34 85 01 A2 05 BD 42 08   64)���x�4�����B�
0020: 9D 2D 00 CA 10 F7 9A A0 00 C6 32 CE 2C 08 B1 31   �-��������2�,��1
0030: 99 00 00 C8 D0 F8 A5 32 C9 08 D0 ED B9 48 08 99   �������2�����H��
0040: 00 01 C8 D0 F7 4C 00 01 01 08 46 4D F3 BB B1 2F   �����L����FM���/

  Bytes: 00-01: Load Address, low/high format, usually $FF $03, or $03FF)
            02: Number of sectors in the file (maximum 166, or $A6)
         03-??: Zipcoded sector data starts here

  If 166 sectors was not enough to store the file then more x!xxxxxx  files
are needed, and the layout is the same. This makes the resulting file  size
of each section approximately the same as the 4-pack zipcode would  be,  as
166 sectors is 1/4 of a normal D64 (664 sector) disk.

  The sector information is zipcoded  in  the  same  manner  as  Diskpacked
4-pack Zipcodes, but the sector size (excluding the t/s link) is 254 bytes,
not 256 as in 4-pack zipcode. The compression is still stored  in  the  top
two bits of the track link, and the remainder of the sector (254 bytes)  is
encoded. Each block of the file is stored  in  full,  even  the  last  one,
though it is rarely completely used.

  Bits
  ----
   00 - No compression, the sector is stored in full. The  next  254  bytes
        contains the remainder of the sector information.
   01 - Sector is filled with *one* character. The next  character  is  the
        fill byte. Repeat it 254 times, and fill the sector.
   10 - Sector is compressed using RLE compression (see 4-pack ZipCode  for
        details)
   11 - Unused

  If the track is decoded as $00, then we are on  the  last  block  of  the
file, and the sector represents the number of bytes used.


  The special file, X!xxxxxx, as mentioned above, contains a listing of all
the files in the archive. It has most of the information that the  D64/1541
entry would. Here is the layout:


      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: 01 08 0B 08 00 00 9E 32 30 36 31 00 00 00 A0 00   �������2061�����
0010: 8C 20 D0 8C 21 D0 B9 C7 08 F0 06 20 D2 FF C8 D0   ��Ќ!й���������
0020: F5 85 FF 85 FB A0 0A 84 FC 85 FD 85 FE A0 11 B1   ����������������
0030: FB 48 AA C8 B1 FB 48 A8 20 4B 09 20 41 09 8A 20   �H�ȱ�H��K��A���
0040: 41 09 98 20 41 09 68 AA 68 18 65 FD 85 FD 8A 65   A���A�h�h�e����e
0050: FE 85 FE 20 39 09 20 3C 09 A0 00 B1 FB C9 A0 F0   ����9��<�����ɠ�
0060: 08 20 41 09 C8 C0 10 D0 F2 20 3C 09 C0 13 F0 06   ��A�������<�����
0070: 20 39 09 C8 D0 F6 A0 10 B1 FB 29 7F 20 41 09 20   �9��������)�A��
0080: 3F 09 A5 FB 18 69 15 85 FB 90 02 E6 FC E6 FF A5   ?����i����������
0090: FF CD FF 09 D0 97 AA A0 00 20 4B 09 8E 08 09 8C   ����З����K�����
00A0: 09 09 A6 FD A4 FE 20 4B 09 8D 1A 09 8E 1B 09 8C   �������K��������
00B0: 1C 09 AD FE 09 09 30 8D 2D 09 A0 00 B9 F7 08 F0   ������0�-�������
00C0: 06 20 41 09 C8 D0 F5 60 93 9B 11 11 11 11 11 11   ��A����`��������
00D0: 11 11 11 11 11 11 11 11 11 11 48 4F 4C 44 20 53   ����������HOLD�S
00E0: 54 4F 50 20 54 4F 20 50 41 55 53 45 20 4C 49 53   TOP�TO�PAUSE�LIS
00F0: 54 49 4E 47 3A 0D 0D 00 0D 0D 54 4F 54 41 4C 20   TING:�����TOTAL�
0100: 46 49 4C 45 53 20 20 3D 20 30 30 0D 54 4F 54 41   FILES��=�00�TOTA
0110: 4C 20 42 4C 4F 43 4B 53 20 3D 20 30 30 30 0D 50   L�BLOCKS�=�000�P
0120: 41 43 4B 45 44 20 46 49 4C 45 53 20 3D 20 30 0D   ACKED�FILES�=�0�
0130: 05 5B 5A 43 20 49 49 5D 0D 00 A9 20 2C A9 22 2C   �[ZC�II]����,�",
0140: A9 0D 20 D2 FF A5 91 C9 7F F0 FA 60 8E 92 09 8C   ����������`����
0150: 93 09 A0 02 A9 30 99 96 09 88 10 FA A2 02 AD 92   �����0����������
0160: 09 38 FD 8F 09 8D 94 09 AD 93 09 E9 00 8D 95 09   �8��������������
0170: 90 11 AD 94 09 8D 92 09 AD 95 09 8D 93 09 FE 96   ����������������
0180: 09 D0 DB CA 10 D8 AD 98 09 AE 97 09 AC 96 09 60   �����ح��������`
0190: 01 0A 64 00 00 00 00 31 32 33 00 00 00 00 00 00   ��d����123������
01A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
01C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
01D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
01F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04   ����������������
0200: 0E 4D 55 53 49 43 20 53 45 4C 45 43 54 4F 52 A0   �MUSIC�SELECTOR�
0210: A0 D0 B6 00 11 00 31 30 30 31 20 4C 45 54 54 45   �ж���1001�LETTE
0220: 52 20 2D 56 2D A0 D0 72 00 13 00 4E 45 57 20 4D   R�-V-��r���NEW�M
0230: 41 49 4C 2F 44 44 A0 A0 A0 A0 A0 D0 1E 00 19 00   AIL/DD����������
0240: 4A 41 43 4B 20 54 48 45 20 4E 49 50 50 45 52 A0   JACK�THE�NIPPER�
0250: D0 C0 00 1A 06 54 55 52 4E 45 52 20 49 49 A0 A0   �����TURNER�II��
0260: A0 A0 A0 A0 A0 D0 2B 00 07 00 53 43 52 45 45 4E   ������+���SCREEN
0270: 20 20 30 A0 A0 A0 A0 A0 A0 A0 D3 07 00 05 00 53   ��0������������S
0280: 43 52 45 45 4E 20 20 31 A0 A0 A0 A0 A0 A0 A0 D3   CREEN��1��������
0290: 0C 00 05 01 53 43 52 45 45 4E 20 20 32 A0 A0 A0   ����SCREEN��2���
02A0: A0 A0 A0 A0 D3 0B 00 04 00 53 43 52 45 45 4E 20   ���������SCREEN�
02B0: 20 33 A0 A0 A0 A0 A0 A0 A0 D3 02 00 04 01 53 43   �3������������SC
02C0: 52 45 45 4E 20 20 34 A0 A0 A0 A0 A0 A0 A0 D3 03   REEN��4���������
02D0: 00 04 03 53 43 52 45 45 4E 20 20 35 A0 A0 A0 A0   ���SCREEN��5����
02E0: A0 A0 A0 D3 07 00 04 07 53 43 52 45 45 4E 20 20   ��������SCREEN��
02F0: 36 A0 A0 A0 A0 A0 A0 A0 D3 08 00 03 00 53 43 52   6������������SCR
0300: 45 45 4E 20 20 37 A0 A0 A0 A0 A0 A0 A0 D3 07 00   EEN��7����������
0310: 03 01 53 43 52 45 45 4E 20 20 38 A0 A0 A0 A0 A0   ��SCREEN��8�����
0320: A0 A0 D3 0B 00 03 09 .. .. .. .. .. .. .. .. ..   �������.........

  Bytes: 0000-01FE: BASIC program which lists the contents of  the  archive
                    (a SYS 2061 call to an ML program)
              01FF: Number of archive (x!xxxxxx)  files.  Since  the  upper
                    value is  4,  we  have  A!xxxxxx,  B!xxxxxx,  C!xxxxxx,
                    D!xxxxxx and X!xxxxxx.
              0200: Number of C64 files contained in the directory (14)
              0201: Start of the directory

  Each file has a directory entry in the X!xxxxxx file, starting at  $0201,
each 21 bytes long, and laid out as follows:

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0200: .. 4D 55 53 49 43 20 53 45 4C 45 43 54 4F 52 A0   .MUSIC�SELECTOR�
0210: A0 D0 B6 00 11 00 31 30 30 31 20 4C 45 54 54 45   �ж���1001�LETTE
0220: 52 20 2D 56 2D A0 D0 72 00 13 00 4E 45 57 20 4D   R�-V-��r���NEW�M
0230: 41 49 4C 2F 44 44 A0 A0 A0 A0 A0 D0 1E 00 19 00   AIL/DD����������
0240: 4A 41 43 4B 20 54 48 45 20 4E 49 50 50 45 52 A0   JACK�THE�NIPPER�
0250: D0 C0 00 1A 06 54 55 52 4E 45 52 20 49 49 A0 A0   �����TURNER�II��
0260: A0 A0 A0 A0 A0 D0 2B 00 07 00 53 43 52 45 45 4E   ������+���SCREEN
0270: 20 20 30 A0 A0 A0 A0 A0 A0 A0 D3 07 00 05 00 53   ��0������������S
0280: 43 52 45 45 4E 20 20 31 A0 A0 A0 A0 A0 A0 A0 D3   CREEN��1��������
0290: 0C 00 05 01 53 43 52 45 45 4E 20 20 32 A0 A0 A0   ����SCREEN��2���
02A0: A0 A0 A0 A0 D3 0B 00 04 00 53 43 52 45 45 4E 20   ���������SCREEN�
02B0: 20 33 A0 A0 A0 A0 A0 A0 A0 D3 02 00 04 01 53 43   �3������������SC
02C0: 52 45 45 4E 20 20 34 A0 A0 A0 A0 A0 A0 A0 D3 03   REEN��4���������
02D0: 00 04 03 53 43 52 45 45 4E 20 20 35 A0 A0 A0 A0   ���SCREEN��5����
02E0: A0 A0 A0 D3 07 00 04 07 53 43 52 45 45 4E 20 20   ��������SCREEN��
02F0: 36 A0 A0 A0 A0 A0 A0 A0 D3 08 00 03 00 53 43 52   6������������SCR
0300: 45 45 4E 20 20 37 A0 A0 A0 A0 A0 A0 A0 D3 07 00   EEN��7����������
0310: 03 01 53 43 52 45 45 4E 20 20 38 A0 A0 A0 A0 A0   ��SCREEN��8�����
0320: A0 A0 D3 0B 00 03 09 .. .. .. .. .. .. .. .. ..   �������.........

  Bytes:$00-0F: 16 character filename (PETASCII, padded with $A0)
            10: Filetype: (the character "P" "S" or "U"  OR'd  with  0x80).
                This means that the write-protect and splat bits are  *not*
                transferred, neither are custom file types, and REL is  not
                allowed either.
         11-12: Length of the file in sectors (0 for no size)
         13-14: Original starting track/sector of the file

  In order to extract *one* specific file,  you  would  have  to  read  the
entire archive until you came across the directory entry that  you  wanted,
then process that specific file. This format does not  contain  any  offset
references in the central directory for each file, just the  original  file
size, which means that we don't know anything about where a file  might  be
in the archive, since the original sector size doesn't apply as the  stored
file in compressed.

  Since this format seems to be uncommon, I can't see any benefit of  using
it over LNX as a  native  C64  file.  The  only  plus  is  it  uses  simple
compression, whereas LNX does not. However, LNX only uses one file for  the
entire file set stored.

*** SixPack Zipcode (6-file version, 1!!xxxxx, 2!!xxxxx, etc)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Compiler/Editor: Peter Schepers
*** Contributors/sources: Paul David Doherty,
                          Wolfgang Moser

  This is another rare form of ZipCode, spanning six files, and  hence  the
use of the name SixPack. Notice how the filename uses two  "!!"  characters
in it, versus one for the other 4-file or filepacked zipcode formats.

                Name      Track Range
              --------    -----------
              1!!xxxxx       1 - 6
              2!!xxxxx       7 - 12
              3!!xxxxx      13 - 18
              4!!xxxxx      19 - 25
              5!!xxxxx      26 - 32
              6!!xxxxx      33 - 35 (or 40 for 40-track images)

  The format for these is *nothing* like the  4-pack,  as  it  contains  no
compression or track/sector references. Rather,  all  the  sector  data  is
stored in GCR code (Group Code Recording). GCR is the method used to  store
information, at the lowest level, on a 1541  diskette.  It  converts  4-bit
nybbles (2 nybbles per byte, upper 4 bits and lower 4 bits) into an encoded
5-bit GCR code. The conversion chart for 4-bit to 5-bit  conversion  is  as
follows:

          Hex   Binary    GCR (dec)    Hex   Binary    GCR (dec)
          ---   ------   ----------    ---   ------   ----------
           0 -   0000  - 01010 (10)     8 -   1000  - 01001 (9)
           1 -   0001  - 01011 (11)     9 -   1001  - 11001 (25)
           2 -   0010  - 10010 (18)     A -   1010  - 11010 (26)
           3 -   0011  - 10011 (19)     B -   1011  - 11011 (27)
           4 -   0100  - 01110 (14)     C -   1100  - 01101 (13)
           5 -   0101  - 01111 (15)     D -   1101  - 11101 (29)
           6 -   0110  - 10110 (22)     E -   1110  - 11110 (30)
           7 -   0111  - 10111 (23)     F -   1111  - 10101 (21)

If you look over the GCR table, there are two details that should be noted.

  1. You *cannot* combine any group of GCR nybbles into a sequence of  bits
     that contain more than 8 consecutive 1-bits. At least  ten  (or  more)
     consecutive 1-bits is used for a SYNC mark,  used  to  tell  the  disk
     controller that sector data is coming up. (In actual  fact,  the  1541
     records an overkill of 40 sequential 1-bits to the disk as a SYNC mark
     to ensure the controller can find the mark!).

     Note that some documents refer to a minimum of 12 bits  needed  for  a
     SYNC mark. This is likely why Commodore chose to use 40 bits  for  the
     standard mark, as the overkill makes it almost impossible to miss.

  2. There will never be any more than two consecutive 0-bits. This is done
     to insure the accuracy of clocking data back to the  1541  controller.
     Too many zero bits, and the clock  will  go  out  of  sync  and  start
     clocking in phantom '1' bits.

  Using the above table, let's convert some numbers.  For  reasons  I  will
explain later, we must work in groups of four bytes  in  order  to  convert
normal HEX to GCR.

     Using these HEX numbers...

     0D  F5  E4  37

     now, split these values into nybbles and convert to binary...

       0   D       F   5       E   4       3   7
     ---- ----   ---- ----   ---- ----   ---- ----
     0000 1101   1111 0101   1110 0100   0011 0111

     convert nybbles to GCR using the conversion table...

     0000  1101    1111  0101    1110  0100    0011  0111
     ----- -----   ----- -----   ----- -----   ----- -----
     01010 11101   10101 01111   11110 01110   10011 10111

     now, recombine the bit into groups of 8...

     01010 11101   10101 01111   11110 01110   10011 10111
     |       ||          ||         ||          ||       |
     | byte 1||  byte 2  ||  byte 3 ||  byte 4  || byte 5|
     |       ||          ||         ||          ||       |
      -------  ----------  ---------  ----------  -------
     01010111   01101010   11111111    00111010   01110111

     and convert back to HEX...

     01010111   01101010   11111111    00111010   01110111
     --------   --------   --------    --------   --------
        57         6A         FF          3A         77

  So, now we have converted a group of 4 bytes into 5 GCR bytes. The reason
we must encode in groups of 4 is that it is the *minimum* number  of  bytes
which, when converted to GCR bits, is  divisible  by  8  bits  without  any
remainder... 1 byte would be 10 bits, 2 bytes would be 20, 3 bytes would be
30, but 4 bytes is 40 bits, divisible by 8 since it leaves us with 5 groups
of 8 bits.

  Now that we have a foundation of GCR encoding, we can  begin  to  analyse
the layout of the 6-pack zipcode. Below is a sample of the beginning of the
first file (1!!xxxxx):

      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        ASCII
      -----------------------------------------------   ----------------
0000: FF 03 24 52 55 25 29 4B 9A E7 25 55 55 52 55 35   ��$RU%)K��%UURU5
0010: 2D 4B 9A E7 25 55 55 52 54 A5 49 4B 9A E7 25 55   -K��%UURT�IK��%U
0020: 55 52 54 B5 4D 4B 9A E7 25 55 55 52 55 65 39 4B   URT�MK��%UURUe9K
0030: 9A E7 25 55 55 52 55 75 3D 4B 9A E7 25 55 55 52   ��%UURUu=K��%UUR
0040: 54 E5 59 4B 9A E7 25 55 55 52 54 F5 5D 4B 9A E7   T�YK��%UURT�]K��
0050: 25 55 55 52 55 A5 25 4B 9A E7 25 55 55 52 55 B5   %UURU�%K��%UURU�
0060: 65 4B 9A E7 25 55 55 52 54 95 69 4B 9A E7 25 55   eK��%UURT�iK��%U
0070: 55 52 55 95 6D 4B 9A E7 25 55 55 52 55 E5 35 4B   URU�mK��%UURU�5K
0080: 9A E7 25 55 55 52 55 55 75 4B 9A E7 25 55 55 52   ��%UURUUuK��%UUR
0090: 54 D5 79 4B 9A E7 25 55 55 52 55 D5 55 4B 9A E7   T�yK��%UURU�UK��
00A0: 25 55 55 52 57 25 A9 4B 9A E7 25 55 55 52 57 35   %UURW%�K��%UURW5
00B0: AD 4B 9A E7 25 55 55 52 56 A5 C9 4B 9A E7 25 55   �K��%UURV��K��%U
00C0: 55 52 56 B5 CD 4B 9A E7 25 55 55 52 57 65 B9 4B   URV��K��%UURWe�K
00D0: 9A E7 25 55 55 29 0F 05 C0 99 00 02 C8 D0 D4 A9   ��%UU)�������ԩ
00E0: 02 8D 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ����������������
00F0: 00 00 00 00 00 00 00 00 00 41 4D 45 3A 20 31 32   ���������AME:�12
0100: 33 34 15 D4 B5 2D 4B 52 D4 B5 2D 4B 52 D4 B5 2D   34�Ե-KRԵ-KRԵ-
0110: 4B 52 D4 B5 2D 4B 52 D4 B5 2D 4B 52 D4 B5 2D 4B   KRԵ-KRԵ-KRԵ-K
0120: 52 D4 B5 2D 4B 52 D4 B5 2D 4B 52 D4 B5 2D 4B 52   RԵ-KRԵ-KRԵ-KR
0130: D4 B5 2D 4B 52 D4 B5 2D 4B 52 D4 B5 2D 4B 52 D4   Ե-KRԵ-KRԵ-KR�
0140: B5 2D 4B 52 D4 B5 29 4D 55 55 D4 A5 2D 4B 52 D4   �-KRԵ)MUUԥ-KR�
0150: B5 2D 4B 52 D4 B5 2D 4B 52 D4 B5 2D 4B 52 D4 B5   �-KRԵ-KRԵ-KRԵ

  Each file starts with a 3-byte signature, $FF, $03, and then either a $24
for a 35 track image, or a $29 for a 40 track image.

0000: FF 03 24 .. .. .. .. .. .. .. .. .. .. .. .. ..

  Track  information  follows,  and  is  comprised  of  a  256  byte  track
descriptor block (mostly GCR encoded), followed by  sector  information  at
326 bytes/sector. The track descriptor contains the header  information  of
each sector in that track, as well as the number of sectors encoded on that
track.

  The descriptor block is broken up into groups of 10 bytes. Each of  these
groups contains the header information of a sector  stored  in  the  track.
Sectors are stored in the header  in  linear  order,  but  not  necessarily
starting at sector 0. If the numbers doesn't start at  sector  0,  then  it
will go something like this: 4, 5, 6, 7, 8...16, 17, 18, 19, 20, 0,  1,  2,
3. Since this track started on sector 4, notice the wrap-around from sector
20 back to 0 and up to 3.


Here is the layout from the above sample block...

 Pos Byte CGR Contents                    Normal Contents (decoded)
 --- ---- -----------------------------  --------------------------------
                                         Sig Chk Sec Trk Id2 Id1 OffBytes
  0   00: 52 55 25 29 4B 9A E7 25 55 55   08  02  00  01  31  32  0F  0F
  1   0A: 52 55 35 2D 4B 9A E7 25 55 55   08  03  01  01  31  32  0F  0F
  2   14: 52 54 A5 49 4B 9A E7 25 55 55   08  00  02  01  31  32  0F  0F
  3   1E: 52 54 B5 4D 4B 9A E7 25 55 55   08  01  03  01  31  32  0F  0F
  4   28: 52 55 65 39 4B 9A E7 25 55 55   08  06  04  01  31  32  0F  0F
  5   32: 52 55 75 3D 4B 9A E7 25 55 55   08  07  05  01  31  32  0F  0F
  6   3C: 52 54 E5 59 4B 9A E7 25 55 55   08  04  06  01  31  32  0F  0F
  7   46: 52 54 F5 5D 4B 9A E7 25 55 55   08  05  07  01  31  32  0F  0F
  8   50: 52 55 A5 25 4B 9A E7 25 55 55   08  0A  08  01  31  32  0F  0F
  9   5A: 52 55 B5 65 4B 9A E7 25 55 55   08  0B  09  01  31  32  0F  0F
  10  64: 52 54 95 69 4B 9A E7 25 55 55   08  08  0A  01  31  32  0F  0F
  11  6E: 52 55 95 6D 4B 9A E7 25 55 55   08  09  0B  01  31  32  0F  0F
  12  78: 52 55 E5 35 4B 9A E7 25 55 55   08  0E  0C  01  31  32  0F  0F
  13  82: 52 55 55 75 4B 9A E7 25 55 55   08  0F  0D  01  31  32  0F  0F
  14  8C: 52 54 D5 79 4B 9A E7 25 55 55   08  0C  0E  01  31  32  0F  0F
  15  96: 52 55 D5 55 4B 9A E7 25 55 55   08  0D  0F  01  31  32  0F  0F
  16  A0: 52 57 25 A9 4B 9A E7 25 55 55   08  12  10  01  31  32  0F  0F
  17  AA: 52 57 35 AD 4B 9A E7 25 55 55   08  13  11  01  31  32  0F  0F
  18  B4: 52 56 A5 C9 4B 9A E7 25 55 55   08  10  12  01  31  32  0F  0F
  19  BE: 52 56 B5 CD 4B 9A E7 25 55 55   08  11  13  01  31  32  0F  0F
  20  C8: 52 57 65 B9 4B 9A E7 25 55 55   08  16  14  01  31  32  0F  0F

      D2: 29 0F 05 C0 99 00 02 C8 D0 D4   garbage
      DC: A9 02 8D 00 00 00 00 00 00 00   garbage
      E6: 00 00 00 00 00 00 00 00 00 00   garbage
      F0: 00 00 00 00 00 00               garbage
      F6: 41 4D 45 3A 20 31 32 33 34      garbage "AME: 1234"
      FF: 15                              Number of valid sectors contained
                                          with this track ($15=21 dec)

  Each sector header block is  laid  out  in  the  following  order  (after
decoding the 10 GCR bytes to 8 normal bytes):

  Byte:   $00 - Header block descriptor value $08 (SIG value)
           01 - Header checksum (EOR of bytes 02-05) (CHK value)
           02 - Sector number (SEC)
           03 - Track number (TRK)
           04 - Second byte of disk ID (ID2)
           05 - First byte of disk ID (ID1)
        06-07 - "OFF" bytes ($0F's). These "fill" up the header to make  it
                a multiple of 4 bytes, necessary in order to convert it  to
                GCR (as six bytes would be too short to convert)

  The entries for Sectors 17-20 will only  be  valid  if  the  track  being
operated on has that many sectors in it. If the value at $FF is  $00,  then
we have an empty track (bad track from the original  disk,  and  the  whole
track should be set to error code 21). When this happens,  all  the  sector
header info in the track descriptor block will be invalid. If we  only  use
up to sector 16 (for tracks 31 and up), then all  the  info  following  the
entry for sector 16 will be invalid. Invalid data  can  be  anything,  just
ignore it.

  All of the sixpack files I have either created or  received  contain  the
string "AME: 1234" at the end of the track descriptor block. It is likely a
"garbage" string, and can be useful in locating the descriptor blocks  when
manually looking over the sixpack files with a HEX editor, but it shouldn't
be used in any other capacity. You also can't easily tell  what  track  you
are on, but given the track ranges covered by each  file,  and  the  sector
count at the end of the descriptor block, it is possible to figure it out.

  Each sector is 326 bytes long (GCR encoded), and each track is 256  bytes
+ (# of sectors/track * 326) bytes. Track 1 would be 256 +  (21  *  326)  =
7102 bytes. The sector information stored in a specific interleave pattern,
depending on the track we are on (unlike  the  entries  in  the  descriptor
block, which are stored in linear order). Note that if this was a 40  track
image, the interleave pattern for the last set of tracks would apply up  to
track 40 instead of 35.

  Note that the numbers referred to in the "Sector Data Interleave" portion
of the table do *not* refer to actual sector numbers, but correspond to the
group position in the header descriptor block. Thus header group  0  is  at
interleave position 0, header group 1 is stored at interleave  position  8,
etc. The header and sector data must be recombined this way before decoding
the header to see what the real sector value is.

  Track    Sector Data interleave reading pattern
  -----    ----------------------------------------------------
   1-17 -  0,8,16,3,11,19,6,14,1,9,17,4,12,20,7,15,2,10,18,5,13
  18-24 -  0,8,16,5,13,2,10,18,7,15,4,12,1,9,17,6,14,3,11
  25-30 -  0,8,16,6,14,4,12,2,10,1,9,17,7,15,5,13,3,11
  31-40 -  0,8,16,7,15,6,14,5,13,4,12,3,11,2,10,1,9

  The data within each sector is in two sections, and  is  stored  *out  of
order*. This is partially due to the way the 1541 reads the data. The first
256 GCR bytes are read into a buffer, then the remaining 70 GCR  bytes  are
read into an "overflow" buffer. In the Sixpack image, the last 70 bytes (of
the 326) are first, then the first 256 bytes follow, for  reasons  left  up
the author of the sixpack format. You need to re-arrange the data to be  in
the correct order before decoding it. We actually  only  decode  325  bytes
(from 0-324, this 325 bytes, divisible by 5), so the last byte is left out.
Once decoded, we have the following information:

   Bytes:    $000 - Data block descriptor value $07
          001-100 - Normal sector info
              101 - Sector checksum (EOR of the data block, from 001-100)
          102-103 - "OFF" bytes ($00's), used to "fill" up the  sector,  to
                    make it a multiple of 4 bytes.

  ZipCode disks are usually used to transfer  disks  which  contain  errors
(copy-protected disks). It also is used for those disks which  use  unusual
fastloaders such  as  Vorpal  or  Warp25,  which  use  different  low-level
encoding methods.

  The offset for each track into its respective  file  can  vary.  Assuming
that the image contains no errors, we can look at each file  and  calculate
the offset position of where each track should be.

   File 1!!  Offset           File 2!!  Offset
   --------  -------------    --------  -------------
   Track 1   $0003 (3)        Track 7   $0003 (3)
   Track 2   $1BC1 (7105)     Track 8   $1BC1 (7105)
   Track 3   $377F (14207)    Track 9   $377F (14207)
   Track 4   $533D (21309)    Track 10  $533D (21309)
   Track 5   $6EFB (28411)    Track 11  $6EFB (28411)
   Track 6   $8AB9 (35513)    Track 12  $8AB9 (35513)

   File 3!!  Offset           File 4!!  Offset
   --------  -------------    --------  -------------
   Track 13  $0003 (3)        Track 19  $0003 (3)
   Track 14  $1BC1 (7105)     Track 20  $1935 (6453)
   Track 15  $377F (14207)    Track 21  $3267 (12903)
   Track 16  $533D (21309)    Track 22  $4B99 (19353)
   Track 17  $6EFB (28411)    Track 23  $64CB (25803)
   Track 18  $8AB9 (35513)    Track 24  $7DFD (32253)
                              Track 25  $972F (38703)

   File 5!!  Offset           File 6!!  Offset
   --------  -------------    --------  -------------
   Track 26  $0003 (3)        Track 33  $0003 (3)
   Track 27  $17EF (6127)     Track 34  $16A9 (5801)
   Track 28  $2FDB (12251)    Track 35  $2D4F (11599)
   Track 29  $47C7 (18375)    Track 36  $43F5 (17397)
   Track 30  $5FB3 (24499)    Track 37  $5A9B (23195)
   Track 31  $779F (30623)    Track 38  $7141 (28993)
   Track 32  $8E45 (36421)    Track 39  $87E7 (34791)
                              Track 40  $9E8D (40589)


  Looking at the error codes for a normal 1541 disk, let's look at how some
of the errors can be stored in the ZipCode images. The following  chart  is
in reverse order of appearance, with the first errors  being  the  earliest
detected.

  Note that the description of the error may not  be  *completely*  correct
compared to how the drive DOS actually works, but serves  as  a  reasonable
explanation in understanding where the error comes from.

  Err#    Error description and method
  ----    -----------------------------------------------------------------
   21     No SYNC character

          Before we can read any sector from a track, the drive  will  look
          for a special "sync" marker, a minimum series of 10 1-bits. If  a
          sync  marker  is  not  found,  the  track  is  presumed  bad   or
          unformatted.  The  SixPack  will  not  contain  any  sector  data
          following the 256-byte header as there is no track data to store.
          The sector count byte in the track descriptor block will  be  set
          to zero.


   20     Header block descriptor not found

          This applies to individual sectors where the header ID ($08, from
          above) isn't seen where it should be. The actual header is  still
          read and stored, and the data should still be there.


   27     Header block checksum error

          The checksum stored in the sector header block doesn't correspond
          to the checksum calculated for the header. The data block  should
          still be there.


   29     Disk ID mismatch

          The ID's contained in the sector header  block  don't  match  the
          disk master ID (from the header block of track 18/0, not the  one
          at offset $A2/A3 of the sector data). The  data  block  is  still
          present.


   22     Data block descriptor not found

          If the special value $07, preceeding the sector data  isn't  seen
          where it should be, this error is  generated.  The  SixPack  will
          still contain the sector data.


   23     Data block checksum error

          This one comes from the checksum value stored  after  the  sector
          data. If the checksum present  doesn't  match  the  checksum  you
          calculate, this error is  generated.  The  data  block  is  still
          present in the SixPack.


  When decoding these files, and attempting to determine what errors exist,
here are a few tips to work by...

  1. Any errors detected in the track descriptor block (20, 27,  29)  occur
     in linear order (sector 0,1,2,3, etc)

  2. Any error detected in the data block (22, 23) is *out* of  order,  and
     follows the previously laid-out  sector  interleave  pattern  for  the
     given track.


  The real strength of  this  format  is  its  usefulness  in  transmitting
error-protected and non-standard low-level fast-loaded disks. If  the  disk
you wish to transmit has no errors, using this format would be a  waste  as
almost *any* other format will use much less space.

  One caveat to this  format  is  the  unforgiving  nature  of  the  6-pack
creation utility on the C64. The one I used would generate a bad sector  if
it encountered a sector that was only slightly bad, but would normally read
back fine on the 1541 (due to the drive's error-correcting nature).