Go to the first, previous, next, last section, table of contents.


15 The emulator file formats

This chapter gives a technical description of the various files supported by the emulators.

15.1 The T64 tape image format

(This section was taken from the C64S distribution.)

The T64 File Structure was developed by Miha Peternel for use in the C64S emulator. It is easy to use and allows future extensions.

15.1.1 T64 File structure

Offset Size Description
0 64 tape record
64 32*n file records for n directory entries
64+32*n varies binary contents of the files

15.1.2 Tape Record

Offset Size Description
0 32 DOS tape description + EOF (for type)
32 2 tape version ($0200)
34 2 number of directory entries
36 2 number of used entries (can be 0 in my loader)
38 2 free
40 24 user description as displayed in tape menu

15.1.3 File record

Offset Size Description
0 1 entry type (see below)
1 1 C64 file type
2 2 start address
4 2 end address
6 2 free
8 4 offset of file contents start within T64 file
12 4 free
16 16 C64 file name

Valid entry types are:

Code Explanation
0 free entry
1 normal tape file
2 tape file with header: header is saved just before file data
3 memory snapshot v0.9, uncompressed
4 tape block
5 digitized stream
6 ... 255 reserved

Notes:

15.2 The G64 GCR-encoded disk image format

(This section was contributed by Peter Schepers and slightly edited by Ettore Perazzoli.)

This format was defined in 1998 as a cooperative effort between several emulator people, mainly Per Hๅkan 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 public attempt to create a format for the emulator community which removed almost all of the drawbacks of the other existing image formats, namely D64.

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

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 entry in simply the raw stream of GCR data, just what a 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 of the time I would suspect the data in the track would be standard sectors, with SYNC, GAP, header, data and checksums. The arrangement of the data when it is in a standard GCR sector layout is beyond the scope of this document.

Since it is a flexible format in both track count and track byte size, there is no "standard" file size. However, given a few constants like 42 tracks and halftracks, a track size of 7928 bytes and no speed offset entries, the typical file size will a minimum of 333744 bytes.

Below is a dump of the header, broken down into its various parts. After that will be an explanation 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
----  -----------------------------------------------
0000: 47 43 52 2D 31 35 34 31 00 54 F8 1E .. .. .. ..
Offset Description
$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 Size of each stored track in bytes (usually 7928, or $1EF8) in LO/HI format.

An obvious question here is "why are there 84 tracks defined when a normal D64 disk only has 35 tracks?" Well, by definition, this image includes all half-tracks, so there are actually 42 tracks and 42 half tracks. The 1541 stepper motor can access up to 42 tracks and the in-between 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.

At first, the defined track size value of 7928 bytes may seem to be arbitrary, but it is not. It is determined by the fastest write speed possible (speed zone 0), coupled with the average rotation speed of the disk (300 rpm). After some math, the answer that actually comes up is 7692 bytes. Why the discrepency between the actual size of 7692 and the defined size of 7928? Simply put, not all drives rotate at 300 rpm. Some can be faster or slower, so a upper safety margin of +3% was built added, in case some disks rotate slower and can write more data. After applying this safety factor, and some rounding-up, 7928 bytes per track was arrived at.

Also note that this upper limit of 7928 bytes per track really only applies to 1541 and compatible disks. If this format were applied to another disk type like the SFD1001, this value would be higher.

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. Following that is a dump of the speed zone offsets.

Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
----  -----------------------------------------------
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
0060: 00 00 00 00 6A 57 01 00 00 00 00 00 64 76 01 00
0070: 00 00 00 00 5E 95 01 00 00 00 00 00 58 B4 01 00
0080: 00 00 00 00 52 D3 01 00 00 00 00 00 4C F2 01 00
0090: 00 00 00 00 46 11 02 00 00 00 00 00 40 30 02 00
00A0: 00 00 00 00 3A 4F 02 00 00 00 00 00 34 6E 02 00
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
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 .. .. .. ..
Offset Description
$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)
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
      -----------------------------------------------
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 .. .. .. ..
Offset Description
$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 here at $02AC is the first track entry (from above, it is the first entry for track 1.0)

The track offsets (from above) require 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). 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
      -----------------------------------------------
02A0: .. .. .. .. .. .. .. .. .. .. .. .. 0C 1E FF FF
02B0: FF FF FF 52 54 B5 29 4B 7A 5E 95 55 55 55 55 55
02C0: 55 55 55 55 55 55 FF FF FF FF FF 55 D4 A5 29 4A
02D0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52
Offset Description
$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
      -----------------------------------------------
1FE0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52
1FF0: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94
2000: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5
2010: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29
2020: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A
2030: 55 55 55 55 55 55 FF FF FF FF FF FF FF FF FF FF
2040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
2050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
2060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
2070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
2080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
2090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
20A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
20B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
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 .. .. .. .. .. .. .. .. .. ..

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 Speed Zone
1-17 3 (highest writing speed)
18-24 2
25-30 1
31 and up 0 (lowest 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 dump of the speed offset entries above, we see that all the entries are in the range of 0-3. If any entry is less than 4, this is not considered a speed offset but defines the whole track to be recorded at that one speed.

In the example I had, there were no offsets defined, so no speed zone 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 thinking 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 any particular order since they are all referenced by the offsets at the beginning of the image.

15.3 The P64 NRZI flux pulse disk image format

This section is taken from "P64 file format specification" by Benjamin 'BeRo' Rosseaux.

All values are in little endian order !

15.3.1 P64 Header Layout

        0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
      +---------------------------------------------------------------+
0000: |'P'|'6'|'4'|'-'|'1'|'5'|'4'|'1'|    Version    |     Flags     |   
      +---------------+---------------+-------------------------------+
0010: |     Size      | CRC32Checksum |
      +-------------------------------+

Version: File format version, current is 0x00000000 Size Size of the following whole chunk content stream Flags: Bit 0 = Write protect Bit 1-31 = Reserved, all set to 0 when creating a file, preserve existing value when updating CRC32CheckSum: CRC32 checksum of the following whole chunk content stream

15.3.2 P64 Chunk Header Layout

        0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
      +-----------------------------------------------+
0000: |Chunk Signature|      Size     | CRC32Checksum |   
      +-----------------------------------------------+

Chunk signature: Signature of chunk Size: Size of the chunk data CRC32CheckSum: CRC32 checksum of the chunk data

15.3.3 P64 Chunk 'HTPx' Layout

| x = half track index byte | +---------------------------+ Track 18 = Half track 36 = Half track index byte decimal value 36 Half track NRZI transition flux pulse data chunk block

        0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
      +---------------------------------------------------------------+
0000: |  Count pulses |     Size      | ..... Range-encoded data .... |    
      +---------------------------------------------------------------+

Count pulses: Count of the NRZI transition flux pulses in half track Size: Size of the range-encoded data

15.3.4 'HTPx' Range encoded data format

Hint: For a working C implememtation see p64.c and p64.h

The range coder is a FPAQ0-style range coder combined with 12-bit 0-order models, one model per byte with one bit per byte processing.

 +--------------------------------------------------------------------------+
 |   Sub stream     | Count of models |  Size per model  | Total value bits |
 +------------------+-----------------+------------------+------------------+
 |     Position     |        4        |      65536       |        32        |
 +------------------+-----------------+------------------+------------------+
 |     Strength     |        4        |      65536       |        32        | 
 +------------------+-----------------+------------------+------------------+
 |   Position flag  |        1        |        2         |        1         |
 +------------------+-----------------+------------------+------------------+
 |   Strenth flag   |        1        |        2         |        1         | 
 +------------------+-----------------+------------------+------------------+
 +===Total models===|        10       |==================|==================|
 +--------------------------------------------------------------------------+

All initial model state values are initialized with zero. All initial model probability values are initialized with 2048.

These model probability values will be updating in a adaptive way on the fly and not precalculated before the encoding and even not loaded before the decoding, see pseudo code below.

16000000 Hz / 5 rotations per second at 300 RPM = maximal 3200000 flux pulses So NRZI transition flux pulse positions are in the 0 .. 3199999 value range, which is also a exact single rotation, where each time unit is a cycle at 16 MHz with 300 RPM as a mapping for the ideal case. The NRZI transition flux pulse stength are in the 0x00000000 .. 0xffffffff value range, where 0xffffffff indices a strong flux pulse, that always triggers, and 0x00000001 indices a weak flux pulse, that almost never triggers, and 0x00000000 indices a flux pulse, that absolutly never triggers. For 32-bit values, the model sub streams are subdivided byte wide in a little-endian manner, and each byte is processed bitwise with model probability shifting of 4 bits, just as:

Pascal-Style pseudo code:

procedure WriteDWord(Model, Value : longword);                             
var ByteValue, ByteIndex, Context, Bit : longword;                         
begin                                                                      
  for ByteIndex := 0 to 3 do begin                                         
    ByteValue := (Value shr (ByteIndex shl 3)) and $ff;                    
    Context := 1;                                                          
    for Bit := 7 downto 0 do begin                                         
      Context := (Context shl 1) or RangeCoderEncodeBit(                   
                    RangeCoderProbabilities[                               
                     RangeCoderProbabilityOffsets[Model + ByteIndex] +     
                     (((RangeCoderProbabilityStates[Model + ByteIndex]      
                     shl 8) or Context) and $ffff)], 4, (ByteValue shr     
                     Bit) and 1);                                          
    end;                                                                   
    RangeCoderProbabilityStates[Model+ByteIndex] := ByteValue;             
  end;                                                                     
end;                                                                       

And for 1-bit flag values it is much simpler, but also with model probability shifting of 4 bits, just as:

Pascal-Style pseudo code:

procedure WriteBit(Model, Value : longword);                               
begin                                                                      
   RangeCoderProbabilityStates[Model] :=                                   
     RangeCoderEncodeBit(RangeCoderProbabilities[                          
       RangeCoderProbabilityOffsets[Model] +                               
         RangeCoderProbabilityStates[Model]], 4, Value and 1);             
end;                                                                       

The position and strength values are delta-encoded. If a value is equal to the last previous value, then the value will not encoded, instead, a flag for this will encoded. First the position value will encoded, then the stength value. If the last position delta is 0, then it is a track stream end marker.

Pascal-Style pseudo code:

LastPosition := 0;                                                         
PreviousDeltaPosition := 0                                                 
                                                                           
LastStrength := 0;                                                         
                                                                           
for PulseIndex := 0 to PulseCount - 1 do begin                             
                                                                           
  DeltaPosition := Pulses[PulseIndex].Position - LastPosition;             
  if PreviousDeltaPosition <> DeltaPosition then begin                     
    PreviousDeltaPosition := DeltaPosition;                                
    WriteBit(ModelPositionFlag, 1)                                         
    WriteDWord(ModelPosition, DeltaPosition);                              
  end else begin                                                           
    WriteBit(ModelPositionFlag, 0);                                        
  end;                                                                     
  LastPosition := Pulses[PulseIndex].Position;                              
                                                                           
  if LastStrength <> Pulses[PulseIndex].Strength then begin                
    WriteBit(ModelStrengthFlag, 1)                                         
    WriteDWord(ModelStrength, Pulses[PulseIndex].Strength - LastStrength);   
  end else begin                                                           
    WriteBit(ModelStrengthFlag, 0);                                         
  end;                                                                       
  LastStrength := Pulses^[PulseIndex].Strength;                            
                                                                           
end;                                                                       
                                                                           
// End code                                                                
WriteBit(ModelPositionFlag, 1);                                            
WriteDWord(ModelPosition, 0);                                              

The decoding is simply just in the another direction way. Pseudo code for a FPAQ0-style carryless range coder:

Pascal-Style pseudo code:

procedure RangeCoderInit; // At encoding and decoding start                
begin                                                                      
  RangeCode := 0;                                                          
  RangeLow := 0;                                                           
  RangeHigh := $ffffffff;                                                  
end;                                                                       
                                                                           
procedure RangeCoderStart; // At decoding start                            
var Counter : longword;                                                       
begin                                                                      
  for Counter := 1 to 4 do begin                                           
   RangeCode := (RangeCode shl 8) or ReadByteFromInput;                    
  end;                                                                     
end;                                                                       
                                                                           
procedure RangeCoderFlush; // At encoding end                              
var Counter : longword;                                                      
begin                                                                      
  for Counter := 1 to 4 do begin                                           
    WriteByteToOutput(RangeHigh shr 24);                                   
    RangeHigh := RangeHigh shl 8;                                          
  end;                                                                     
end;                                                                        
                                                                           
procedure RangeCoderEncodeNormalize;                                          
begin                                                                      
  while ((RangeLow xor RangeHigh) and $ff000000) = 0 do begin              
   WriteByteToOutput(RangeHigh shr 24);                                    
   RangeLow := RangeLow shl 8;                                             
   RangeHigh := (RangeHigh shl 8) or $ff;                                    
  end;                                                                      
end;                                                                        
                                                                           
function RangeCoderEncodeBit(var Probability : longword; Shift,            
                             BitValue : longword) : longword;               
begin                                                                      
  RangeMiddle := RangeLow + (((RangeHigh - RangeLow) shr 12) *             
                              Probability);                                  
  if BitValue <> 0 then begin                                               
    inc(Probability, ($fff - Probability) shr Shift);                      
    RangeHigh := RangeMiddle;                                                
  end else begin                                                           
    dec(Probability, Probability shr Shift);                               
    RangeLow := RangeMiddle + 1;                                           
  end;                                                                     
  RangeCoderEncodeNormalize;                                               
  result := BitValue;                                                      
end;                                                                       
                                                                            
procedure RangeCoderDecodeNormalize;                                        
begin                                                                      
  while ((RangeLow xor RangeHigh) and $ff000000) = 0 do begin              
    RangeLow := RangeLow shl 8;                                            
    RangeHigh := (RangeHigh shl 8) or $ff;                                 
    RangeCode := (RangeCode shl 8) or ReadByteFromInput;                   
  end;                                                                     
end;                                                                       
                                                                            
function RangeCoderDecodeBit(var Probability : longword;                   
                             Shift : longword) : longword;                 
begin                                                                      
  RangeMiddle := RangeLow + (((RangeHigh - RangeLow) shr 12) *             
                             Probability);                                 
  if RangeCode <= RangeMiddle then begin                                   
    inc(Probability, ($fff - Probability) shr Shift);                      
    RangeHigh := RangeMiddle;                                              
    result := 1;                                                           
  end else begin                                                           
    dec(Probability, Probability shr Shift);                               
    RangeLow := RangeMiddle + 1;                                           
    result := 0;                                                           
  end;                                                                     
  RangeCoderDecodeNormalize;                                               
end;                                                                       

The probability may be never zero! But that can't happen here with this adaptive model in this P64 file format, since the adaptive model uses a shift factor of 4 bits and initial probabilities value of 2048, so the probability has a value range from 15 up to 4080 here. If you do want to use the above range coder routines for other stuff with other probability models, then you must to ensure that the probability output value is never zero, for example with "probability |= (probability < 1); " in C.

15.3.5 P64 Chunk 'DONE' Layout

This is the last empty chunk for to signalize that the correct file end is reached.

15.4 The D64 disk image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

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

Bytes Description
$00-$1F First directory entry
$20-$3F Second dir entry
$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

This is a breakdown of a standard directory entry:

Bytes Description
$00-$01 Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector)
$02 File type
$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 file type field is used as follows:

Bits Description
0-3 The actual file type
4 Unused
5 Used only during SAVE-@ replacement
6 Locked flag (Set produces ">" locked files)
7 Closed flag (Not set produces "*", or "splat" files)

The actual file type can be one of the following:

Binary Decimal File type
0000 0 DEL
0001 1 SEQ
0010 2 PRG
0011 3 USR
0100 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.

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.

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

15.4.2 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 Description
$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 Unused ($00)
$AC-$BF For DOLPHIN DOS track 36-40 BAM entries, otherwise unused ($00)
$C0-$D3 For SPEED DOS track 36-40 BAM entries, otherwise unused ($00)
$D4-$FF Unused ($00)

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 Data Description
$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)

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

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.

Disk format tracks header 7/8 Dos type Diskdos vs. type
Original CBM DOS v2.6 35 $0f $0f "2A" $41/'A'
*SpeedDOS+ 40 $0f $0f "2A" $41/'A'
Professional DOS Initial 35 $0f $0f "2A" $41/'A'
Professional DOS 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
       -----------------------------------------------
 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
 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
       -----------------------------------------------
 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
 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
       -----------------------------------------------
 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
 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

15.4.4 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 : $03 Error : 21 Type : Seek Message : 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.

Code : $02 Error : 20 Type : Seek Message : 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.

Code : $09 Error : 27 Type : Seek Message : 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.

Code : $0B Error : 29 Type : Seek Message : 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.

Code : $02 Error : 20 Type : Seek Message : 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 : $04 Error : 22 Type : Read Message : 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.

Code : $05 Error : 23 Type : Read Message : 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.

Code : $0F Error : 74 Type : Read Message : 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 : $06 Error : 24 Type : Write Message : Write verify (on format)

Code : $07 Error : 25 Type : Write Message : 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.

Code : $08 Error : 26 Type : Write Message : Write protect on

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

Code : $0A Error : 28 Type : Write Message : Write error

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

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

Code : $01 Error : 00 Type : N/A Message : 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.

15.5 The X64 disk image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

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 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
      -----------------------------------------------
0000: 43 15 41 64 01 02 01 23 00 00 00 00 00 00 00 00
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 Description
$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
$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.
$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 device types are:

Value Drive type
$00 1540 See note below...
$01 1541 (Default)
$02 1542
$03 1551
$04 1570
$05 1571
$06 1572
$08 1581
$10 2031 or 4031
$11 2040 or 3040
$12 2041
$18 4040
$20 8050
$21 8060
$22 8061
$30 SFD-1001
$31 8250
$32 8280

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.

15.6 The D71 disk image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

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

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

This is a breakdown of a standard directory entry:

Bytes Description
$00-$01 Track/Sector location of next directory sector ($00/$FF if its the last sector)
$02 File type
$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 file type field is used as follows:

Bits Description
0-3 The actual file type
4 Unused
5 Used only during SAVE-@ replacement
6 Locked flag (Set produces ">" locked files)
7 Closed flag (Not set produces "*", or "splat" files)

The actual file type can be one of the following:

Binary Decimal File type
0000 0 DEL
0001 1 SEQ
0010 2 PRG
0011 3 USR
0100 4 REL

Values 5-15 are illegal, but if used will produce very strange results. The 1571 is inconsistent in how it treats these bits. Some routines use all 4 bits, others ignore bit 3, resulting in values from 0-7.

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.

15.6.1 Non-Standard & Long Directories

Most Commodore 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.

15.6.2 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
    -----------------------------------------------
00: 12 01 41 80 12 FF F9 17 15 FF FF 1F 15 FF FF 1F
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
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 Description
$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
    -----------------------------------------------
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.

15.7 The D81 disk image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

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

Bytes Description
$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
    -----------------------------------------------
00: 28 04 81 2B 00 53 43 52 45 45 4E 20 20 33 A0 A0
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
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
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
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
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
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
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
F0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 05 00
Bytes Description
$00-$1F First directory entry
$20-$3F Second dir entry
$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

This is a breakdown of a standard directory entry:

Bytes Description
$00-$01 Track/Sector location of next directory sector
$02 File type
$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-$1B 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

The file type field is used as follows:

Bits Description
0-3 The actual file type
4 Unused
5 Used only during SAVE-@ replacement
6 Locked flag (Set produces ">" locked files)
7 Closed flag (Not set produces "*", or "splat" files)

The actual file type can be one of the following:

Binary Decimal File type
0000 0 DEL
0001 1 SEQ
0010 2 PRG
0011 3 USR
0100 4 REL
0101 5 CBM (partition or sub-directory)

Values 6-15 are illegal, but if used will produce very strange results.

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

15.7.2 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
    -----------------------------------------------
00: 28 02 44 BB 47 42 C0 00 00 00 00 00 00 00 00 00
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
$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
    -----------------------------------------------
00: 00 FF 44 BB 47 42 C0 00 00 00 00 00 00 00 00 00
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.

15.7.3 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
 10: 49 4E 46 4F A0 27 02 FE 00 00 00 00 00 00 D2 0B

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

15.7.4 1581 Partitions and Sub-directories

At the beginning of this section 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
 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 as 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
 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
 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.

15.7.5 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

15.8 The D80 disk image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

This is a sector-for-sector copy of an 8050 floppy disk. The file size for an 8050 image is 533248 bytes. It is comprised of 256-byte sectors arranged across 77 tracks, with a varying number of sectors per track for a total of 2083 sectors. 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 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. 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 29 1131
40-53 27 378
54-64 25 275
65-77 23 299
Track #Sect #SectorsIn D8x Offset
1 29 0 $00000
2 29 29 $01D00
3 29 58 $03A00
4 29 87 $05700
5 29 116 $07400
6 29 145 $09100
7 29 174 $0AE00
8 29 203 $0CB00
9 29 232 $0E800
10 29 261 $10500
11 29 290 $12200
12 29 319 $13F00
13 29 348 $15C00
14 29 377 $17900
15 29 406 $19600
16 29 435 $1B300
17 29 464 $1D000
18 29 493 $1ED00
19 29 522 $20A00
20 29 551 $22700
21 29 580 $24400
22 29 609 $26100
23 29 638 $27E00
24 29 667 $29B00
25 29 696 $2B800
26 29 725 $2D500
27 29 754 $2F200
28 29 783 $30F00
29 29 812 $32C00
30 29 841 $34900
31 29 870 $36600
32 29 899 $38300
33 29 928 $3A000
34 29 957 $3BD00
35 29 986 $3DA00
36 29 1015 $3F700
37 29 1044 $41400
38 29 1073 $43100
39 29 1102 $44E00
40 27 1131 $46B00
41 27 1158 $48600
42 27 1185 $4A100
43 27 1212 $4BC00
44 27 1239 $4D700
45 27 1266 $4F200
46 27 1293 $50D00
47 27 1320 $52800
48 27 1347 $54300
49 27 1374 $55E00
50 27 1401 $57900
51 27 1428 $59400
52 27 1455 $5AF00
53 27 1482 $5CA00
54 25 1509 $5E500
55 25 1534 $5FE00
56 25 1559 $61700
57 25 1584 $63000
58 25 1609 $64900
59 25 1634 $66200
60 25 1659 $67B00
61 25 1684 $69400
62 25 1709 $6AD00
63 25 1734 $6C600
64 25 1759 $6DF00
65 23 1784 $6F800
66 23 1807 $70F00
67 23 1830 $72600
68 23 1853 $73D00
69 23 1876 $75400
70 23 1899 $76B00
71 23 1922 $78200
72 23 1945 $79900
73 23 1968 $7B000
74 23 1991 $7C700
75 23 2014 $7DE00
76 23 2037 $7F500
77 23 2060 $80C00

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 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), 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
    -----------------------------------------------
00: 26 00 43 00 00 00 73 61 6D 70 6C 65 20 64 38 30
10: A0 A0 A0 A0 A0 A0 A0 A0 65 72 A0 32 43 A0 A0 A0
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
Bytes Description
$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
    -----------------------------------------------
00: 27 02 82 26 01 54 45 53 54 A0 A0 A0 A0 A0 A0 A0
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
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
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
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
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
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
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
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:

Bytes Description
$00-$1F First directory entry
$20-$3F Second dir entry
$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

This is a breakdown of a standard directory entry:

Bytes Description
$00-$01 Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector)
$02 File type
$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

The file type field is used as follows:

Bits Description
0-3 The actual file type
4 Unused
5 Used only during SAVE-@ replacement
6 Locked flag (Set produces ">" locked files)
7 Closed flag (Not set produces "*", or "splat" files)

The actual file type can be one of the following:

Binary Decimal File type
0000 0 DEL
0001 1 SEQ
0010 2 PRG
0011 3 USR
0100 4 REL

Values 5-15 are illegal, but if used will produce very strange results.

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

15.8.2 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. 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
    -----------------------------------------------
00: 26 03 43 00 01 33 1D FF FF FF 1F 1D FF FF FF 1F
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
Bytes Description
$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.

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 27 01 43 00 33 4E 1B FF FF FF 07 1B FF FF FF 07
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
Bytes Description
$00-$01 T/S pointer to second BAM 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

15.9 The D82 disk image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

This is a sector-for-sector copy of an 8250 floppy disk. The file size for an 8250 image is 1066496 bytes. It is comprised of 256-byte sectors arranged across 154 tracks, with a varying number of sectors per track for a total of 4166 sectors. 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 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 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 29 1131
40-53 27 378
55-64 25 275
65-77 23 299
78-116 29 1131
117-130 27 378
131-141 25 275
142-154 23 299
Track #Sect #SectorsIn D82 Offset
1 29 0 $000000
2 29 29 $001D00
3 29 58 $003A00
4 29 87 $005700
5 29 116 $007400
6 29 145 $009100
7 29 174 $00AE00
8 29 203 $00CB00
9 29 232 $00E800
10 29 261 $010500
11 29 290 $012200
12 29 319 $013F00
13 29 348 $015C00
14 29 377 $017900
15 29 406 $019600
16 29 435 $01B300
17 29 464 $01D000
18 29 493 $01ED00
19 29 522 $020A00
20 29 551 $022700
21 29 580 $024400
22 29 609 $026100
23 29 638 $027E00
24 29 667 $029B00
25 29 696 $02B800
26 29 725 $02D500
27 29 754 $02F200
28 29 783 $030F00
29 29 812 $032C00
30 29 841 $034900
31 29 870 $036600
32 29 899 $038300
33 29 928 $03A000
34 29 957 $03BD00
35 29 986 $03DA00
36 29 1015 $03F700
37 29 1044 $041400
38 29 1073 $043100
39 29 1102 $044E00
40 27 1131 $046B00
41 27 1158 $048600
42 27 1185 $04A100
43 27 1212 $04BC00
44 27 1239 $04D700
45 27 1266 $04F200
46 27 1293 $050D00
47 27 1320 $052800
48 27 1347 $054300
49 27 1374 $055E00
50 27 1401 $057900
51 27 1428 $059400
52 27 1455 $05AF00
53 27 1482 $05CA00
54 25 1509 $05E500
55 25 1534 $05FE00
56 25 1559 $061700
57 25 1584 $063000
58 25 1609 $064900
59 25 1634 $066200
60 25 1659 $067B00
61 25 1684 $069400
62 25 1709 $06AD00
63 25 1734 $06C600
64 25 1759 $06DF00
65 23 1784 $06F800
66 23 1807 $070F00
67 23 1830 $072600
68 23 1853 $073D00
69 23 1876 $075400
70 23 1899 $076B00
71 23 1922 $078200
72 23 1945 $079900
73 23 1968 $07B000
74 23 1991 $07C700
75 23 2014 $07DE00
76 23 2037 $07F500
77 23 2060 $080C00
78 29 2083 $082300
79 29 2112 $084000
80 29 2141 $085D00
81 29 2170 $087A00
82 29 2199 $089700
83 29 2228 $08B400
84 29 2257 $08D100
85 29 2286 $08EE00
86 29 2315 $090600
87 29 2344 $092800
88 29 2373 $094500
89 29 2402 $096200
90 29 2431 $097F00
91 29 2460 $099C00
92 29 2489 $09B900
93 29 2518 $09D600
94 29 2547 $09F300
95 29 2576 $0A1000
96 29 2605 $0A2D00
97 29 2634 $0A4A00
98 29 2663 $0A6700
99 29 2692 $0A8400
100 29 2721 $0AA100
101 29 2750 $0ABE00
102 29 2779 $0ADB00
103 29 2808 $0AF800
104 29 2837 $0B1500
105 29 2866 $0B3200
106 29 2895 $0B4F00
107 29 2924 $0B6C00
108 29 2953 $0B8900
109 29 2982 $0BA600
110 29 3011 $0BC300
111 29 3040 $0BE000
112 29 3069 $0BFD00
113 29 3098 $0C1A00
114 29 3137 $0C3700
115 29 3156 $0C5400
116 29 3185 $0C7100
117 27 3214 $0C8E00
118 27 3241 $0CA900
119 27 3268 $0CC400
120 27 3295 $0CDF00
121 27 3322 $0CFA00
122 27 3349 $0D1500
123 27 3376 $0D3000
124 27 3403 $0D4B00
125 27 3430 $0D6600
126 27 3457 $0D8100
127 27 3484 $0D9C00
128 27 3511 $0DB700
129 27 3538 $0DD200
130 27 3565 $0DED00
131 25 3592 $0E0800
132 25 3617 $0E2100
133 25 3642 $0E3A00
134 25 3667 $0E5300
135 25 3692 $0E6C00
136 25 3717 $0E8500
137 25 3742 $0E9E00
138 25 3767 $0EB700
139 25 3792 $0ED000
140 25 3817 $0EE900
141 25 3842 $0F0200
142 23 3867 $0F1B00
143 23 3890 $0F3200
144 23 3913 $0F4900
145 23 3936 $0F6000
146 23 3959 $0F7700
147 23 3982 $0F8E00
148 23 4005 $0FA500
149 23 4028 $0FBC00
150 23 4051 $0FD300
151 23 4074 $0FEA00
152 23 4097 $100100
153 23 4120 $101800
154 23 4143 $102F00

The BAM (Block Availability Map) is on track 38. The D82 is 154 tracks and so the BAM 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), 38/9 (BAM3, 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
    -----------------------------------------------
00: 26 00 43 00 00 00 73 61 6D 70 6C 65 20 64 38 30
10: A0 A0 A0 A0 A0 A0 A0 A0 65 72 A0 32 43 A0 A0 A0
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
Bytes Description
$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 d82")
$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
    -----------------------------------------------
00: 27 02 82 26 01 54 45 53 54 A0 A0 A0 A0 A0 A0 A0
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
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
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
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
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
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
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
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:

Bytes Description
$00-$1F First directory entry
$20-$3F Second dir entry
$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

This is a breakdown of a standard directory entry:

Bytes Description
$00-$01 Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector)
$02 File type
$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

The file type field is used as follows:

Bits Description
0-3 The actual file type
4 Unused
5 Used only during SAVE-@ replacement
6 Locked flag (Set produces ">" locked files)
7 Closed flag (Not set produces "*", or "splat" files)

The actual file type can be one of the following:

Binary Decimal File type
0000 0 DEL
0001 1 SEQ
0010 2 PRG
0011 3 USR
0100 4 REL

Values 5-15 are illegal, but if used will produce very strange results.

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

15.9.2 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 D82 will contain four BAM sectors, 38/0, 38/3, 38/6 and 38/9. 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
    -----------------------------------------------
00: 26 03 43 00 01 33 1D FF FF FF 1F 1D FF FF FF 1F
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
Bytes Description
$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

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 26 06 43 00 33 65 1B FF FF FF 07 1B FF FF FF 07
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
Bytes Description
$00-$01 T/S pointer to third 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

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 26 09 43 00 65 97 1D FF FF FF 1F 1D FF FF FF 1F
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
Bytes Description
$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

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    -----------------------------------------------
00: 27 01 43 00 97 9B 17 FF FF 7F 00 17 FF FF 7F 00
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
Bytes Description
$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

15.10 The P00 image format

(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)

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
      -----------------------------------------------
0000: 43 36 34 46 69 6C 65 00 43 52 49 53 49 53 20 4D
0010: 4F 55 4E 54 41 49 4E 00 00 00
Bytes Description
$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.

15.11 The CRT cartridge image format

This chapter is based on CRT.txt (rev1.14) compiled by Peter Schepers, with additional contributions from Per Hakan Sundell, Markus Brenner, Marco Van Den Heuvel, Groepaz.

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.

15.11.1 Header contents

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  (also  the
                     minimum) value is $40.  Some  cartridges  exist  which
                     show a value of $00000020 which is wrong.
         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*
                       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 - Warp Speed
                      17 - Dinamic**
                      18 - Zaxxon, Super Zaxxon (SEGA)
                      19 - Magic Desk, Domark, HES Australia
                      20 - Super Snapshot V5
                      21 - Comal-80
                      22 - Structured BASIC
                      23 - Ross
                      24 - Dela EP64
                      25 - Dela EP7x8
                      26 - Dela EP256
                      27 - Rex EP256
                      28 - Mikro Assembler
                      29 - Final Cartridge Plus
                      30 - Action Replay 4
                      31 - Stardos
                      32 - EasyFlash
                      33 - EasyFlash Xbank
                      34 - Capture
                      35 - Action Replay 3
                      36 - Retro Replay
                      37 - MMC64
                      38 - MMC Replay
                      39 - IDE64
                      40 - Super Snapshot V4
                      41 - IEEE-488
                      42 - Game Killer
                      43 - Prophet64
                      44 - EXOS
                      45 - Freeze Frame
                      46 - Freeze Machine
                      47 - Snapshot64
                      48 - Super Explode V5.0
                      49 - Magic Voice
                      50 - Action Replay 2
                      51 - MACH 5
                      52 - Diashow-Maker
                      53 - Pagefox
              0018 - Cartridge port EXROM line status
                      0 - inactive
                      1 - active
              0019 - Cartridge port GAME line status
                      0 - inactive
                      1 - active
         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.

(*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)

15.11.2 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 more
                     than one image 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 E - EXROM

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      ----
Normal    16k    lo     lo     $8000     $A000
Ultimax   8k     lo     hi     $E000      ----

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.

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.

15.11.3 Cartridge Specifics

15.11.3.1 0 - Normal cartridge

Size 8Kb
GAME active (1)
EXROM inactive (0)
Load address $8000-9FFF
      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.

Normal cartridge

Size 4Kb (ULTIMAX mode)
GAME inactive (0)
EXROM active (1)
Load address $F000-F7FF
      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.

Normal cartridge

Size 16Kb
GAME inactive (0)
EXROM inactive (0)
Load address $8000-BFFF
      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.Ž?.

15.11.3.2 1 - Action Replay

Size 32Kb (4 banks of 8Kb each)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-9FFF (all modules)
      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

This cart has 32Kb of ROM, and 8Kb of RAM. The bank switching is done by writing to the I/O-1 range as follows:

    bit  meaning
    ---  -------
    7    extra ROM bank selector (A15) (unused)
    6    1 = resets FREEZE-mode (turns back to normal mode)
    5    1 = enable RAM at ROML ($8000-$9FFF) &
             I/O-2 ($DF00-$DFFF = $9F00-$9FFF)
    4    ROM bank selector high (A14)
    3    ROM bank selector low  (A13)
    2    1 = disable cartridge (turn off $DE00)
    1    1 = /EXROM high
    0    1 = /GAME low

Additionally the RAM or ROM can be available through a window in the I/O-2 range.

15.11.3.3 2 - KCS Power Cartridge

module #2 - $A000-BFFF
Size 16Kb (2 banks of 8K each)
GAME inactive (0)
EXROM inactive (0)
Load address module #1 - $8000-9FFF
      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   —.?.????? ฅ???…?

15.11.3.4 3 - Final Cartridge III

Size 64Kb (4 banks of 16Kb each)
GAME active (1)
EXROM active (1)
Load address $8000-BFFF (all modules)
      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.

The banks are arranged in the following way:

    Bank 0:  BASIC, Monitor, Disk-Turbo
    Bank 1:  Notepad, BASIC (Menu Bar)
    Bank 2:  Desktop, Freezer/Print
    Bank 3:  Freezer, Compression

The cartridges uses the entire I/O-1 and I/O-2 range. 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.

The registers are arranged in the following way:

One register at $DFFF:

    bit  meaning
    ---  -------
    7      Hide this register (1 = hidden)
    6      NMI line  (0 = low = active) *1)
    5      GAME line  (0 = low = active) *2)
    4      EXROM line (0 = low = active)
    2-3    unassigned (usually set to 0)
    0-1    number of bank to show at $8000

1) if either the freezer button is pressed, or bit 6 is 0, then an NMI is generated

2) if the freezer button is pressed, GAME is also forced low

The rest of I/O-1/I/O-2 contain a mirror of the last 2 pages of the currently selected ROM bank (also at $dfff, contrary to what some other documents say)

15.11.3.5 4 - Simons' Basic

module #2 - $A000-BFFF
Size 16Kb (2 banks of 8kb each)
GAME active (1)
EXROM inactive (0)
Load address module #1 - $8000-9FFF
      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.

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.

15.11.3.6 5 - Ocean type 1

Banks 16-31 - $A000-BFFF (except Terminator 2)
Size 32Kb, 128Kb, 256Kb or 512Kb sizes (4, 16, 32 or 64 banks of 8Kb)
GAME inactive (0)
EXROM inactive (0)
Load address Banks 00-15 - $8000-9FFF
       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 list of the known OCEAN cartridges:

    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)

The 32Kb type of cart has 4 banks of 8Kb ($2000), banked in at $8000-$9FFF.

The 128Kb type of cart has 16 banks of 8Kb ($2000), banked in at $8000-$9FFF.

The 256Kb type of cart has 32 banks of 8Kb ($2000), 16 banked in at $8000-$9FFF, and 16 banked in at $A000-$BFFF.

The 512Kb type of cart has 64 banks of 8Kb ($2000), banked in at $8000-$9FFF.

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.

15.11.3.7 6 - Expert Cartridge

Size 8Kb
GAME active (1)
EXROM active (1)
Load address $8000-9FFF
      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   ????????????????

15.11.3.8 7 - Fun Play, Power Play

Size 128Kb (16 banks of 8Kb modules)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-9FFF (all modules)
       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.

15.11.3.9 8 - Super Games

Size 64Kb (4 banks of 16Kb each)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-BFFF (all modules)
      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.

$DF00 register is as follows:

    bit  meaning
    ---  -------
    0    bank bit 0
    1    bank bit 1
    2    inverted GAME line
    3    inverted EXROM line
    4-7  unused

15.11.3.10 9 - Atomic Power

Size 32Kb (4 banks of 8Kb modules)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-9FFF (all modules)
      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

This cart has 32Kb of ROM and 8Kb of RAM

Writing to I/O-1 will do the following:

    bit  meaning
    ---  -------
    7    extra ROM bank selector (A15) (unused)
    6    1 = resets FREEZE-mode (turns back to normal mode)
    5    1 = enable RAM at ROML ($8000-$9FFF) &
             I/O-2 ($DF00-$DFFF = $9F00-$9FFF)
    4    ROM bank selector high (A14)
    3    ROM bank selector low  (A13)
    2    1 = disable cartridge (turn off $DE00)
    1    1 = /EXROM high
    0    1 = /GAME low

If bit 5 (RAM enable) is 1, bit 0,1 (exrom/game) is == 2 (cart off), bit 2,6,7 (cart disable, freeze clear) are 0, then cart ROM (Bank 0..3) is mapped at 8000-9FFF, and cart RAM (Bank 0) is mapped at A000-BFFF and cart RAM (Bank 0) is is enabled in the I/O-2 area using 16Kb game config.

The cart RAM or ROM is available through a window in the I/O-2 range.

15.11.3.11 10 - Epyx Fastload

Size 8Kb
GAME active (1)
EXROM active (1)
Load address $8000-9FFF
      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?ซ

The Epyx FastLoad cart uses a simple capacitor to toggle the ROM on and off:

the capacitor is discharged, and 8k game config enabled, by either reading ROML or reading I/O-1. If none of those accesses happen the capacitor will charge, and if it is charged (after 512 cycles) then the ROM will get disabled.

15.11.3.12 11 - Westermann Learning

Size 16Kb
GAME inactive (0)
EXROM inactive (0)
Load address $8000-BFFF
      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.?Ž?.?„

Any read from the I/O-2 range will switch the cart off.

15.11.3.13 12 - Rex Utility

Size 8K
GAME active (1)
EXROM inactive (0)
Load address $8000-9FFF
      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•.?ฃ.?

Reading from $DF00-DFBF disables ROM, reading from $DFC0-DFFF enables ROM (8k game config).

15.11.3.14 13 - Final Cartridge I

Size 16Kb
GAME active (1)
EXROM active (1)
Load address $8000-BFFF
      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

Any access to I/O-1 turns cartridge ROM off. Any access to I/O-2 turns cartridge ROM on.

The cart ROM is visible in I/O-1 and I/O-2.

15.11.3.15 14 - Magic Formel

Size 64Kb (8 banks of 8Kb)
GAME Inactive (0)
EXROM Inactive (0)
Load Address $E000-FFFF
      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.11.3.16 15 - C64 Game System, System 3

Size 512Kb (64 banks of 8Kb each)
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF (all modules)
        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 written to. Reading from anywhere in the I/O-1 range will disable the cart.

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 8 kB ROM configuration.

15.11.3.17 16 - Warp Speed

Size 16Kb
GAME inactive (0)
EXROM inactive (0)
Load address $8000-BFFF
      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 is visible at $8000-$BFFF. Additionally, ROM normally located at $9E00-$9FFF is mirrored into I/O-1 and I/O-2 at $DE00-$DFFF. ROM at $8000-$BFFF is disabled by writing into the I/O-2 area (typically $DF00) and may be re-enabled by writing into I/O-1 ($DE00). However, the $DE00-$DFFF (I/O-1/I/O-2) area itself always remains mapped to cartridge ROM.

15.11.3.18 17 - Dinamic

Size 128Kb (16 banks of 8Kb each)
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF (all modules)
        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 8 kB ROM configuration.

15.11.3.19 18 - Zaxxon, Super Zaxxon (SEGA)

$A000-BFFF (banked modules 1 and 2, chip U2)
Size 20Kb (3 banks of different sizes)
GAME active (1)
EXROM active (1)
Load address $8000-8FFF (mirrored in $9000-9FFF, module 0, chip U1)
        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

15.11.3.20 19 - Magic Desk, Domark, HES Australia

Size 32Kb, 64Kb or 128Kb sizes (4 to 16 banks of 8Kb each)
GAME inactive (0)
EXROM active (1)
Load address (banks 00-15) - $8000-9FFF
      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. Deviant 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)

15.11.3.21 20 - Super Snapshot V5

Size 64Kb (4 banks of 16Kb each)
GAME active (1)
EXROM active (1)
Load address $8000-BFFF
      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

The first page of the currently selected ROM bank is mirrored in the I/O-1 range when reading.

The control Register is the I/O-1 range when writing:

    bit  meaning
    ---  -------
    7-5  unused
    4    ROM/RAM bank bit 1
    3    ROM enable
    2    ROM/RAM bank bit 0
    1    RAM enable, EXROM
    0    release freeze, !GAME

15.11.3.22 21 - Comal-80

Size 64Kb (4 banks of 16Kb each)
GAME active (1)
EXROM active (1)
Load address $8000-BFFF
      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

15.11.3.23 22 - Structured Basic

Size 16Kb (2 banks of 8Kb each)
GAME active (0)
EXROM active (1)
Load address $8000-9FFF

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.

15.11.3.24 23 - Ross

Size 16Kb or 32Kb sizes (1 or 2 banks of 16Kb each)
GAME active (1)
EXROM active (1)
Load address $8000-BFFF
      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.

15.11.3.25 24 - Dela EP64

or 1 bank of 8Kb and 1 or 2 banks of 32Kb each)
Size 8Kb to 72kb sizes (1 to 9 banks of 8Kb each,
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF
      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 switch off EXROM.

15.11.3.26 25 - Dela EP7x8

Size 8Kb to 64kb sizes (1 to 8 banks of 8Kb each)
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF
      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 switched off.

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)

15.11.3.27 26 - Dela EP256

Size 8Kb to 262kb sizes (1 to 33 banks of 8Kb each)
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF
      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 switch off EXROM.

15.11.3.28 27 - Rex EP256

8Kb, 16Kb or 32Kb)
Size 8Kb to 262kb sizes (1 bank of 8Kb and 1 to 8 banks of either
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF
      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 switches off the EXROM. Reading from $DFE0 switches on the EXROM.

15.11.3.29 28 - Mikro Assembler

Size 8Kb (1 bank of 8Kb)
GAME inactive (0)
EXROM active (1)
Load address $8000-9FFF
      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 1C 00 01 00 00 00 00 00 00  ???@????????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE CART???????
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: 60 80 FE 80 C3 C2 CD 38 30 4C 07 87 4C CA 82 41  `......80L?.L.‚A

The $9E00-$9EFF range is mirrored at $DE00-$DEFF. The $9F00-$9FFF range is mirrored at $DF00-$DFFF.

15.11.3.30 29 - Final Cartridge Plus

Size 32Kb (1 bank of 32Kb)
GAME active (1)
EXROM active (1)
Load address $0000-$7FFF
      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 1D 00 01 00 00 00 00 00 00  ???@????????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ????????????????
0040: 43 48 49 50 00 00 80 10 00 00 00 00 00 00 80 00  CHIP??.???????.?
0050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ????????????????

This cart has 32Kb of ROM, bank 0 is in the cart image but is unused. The first 8Kb of the cart image is unused, the second 8Kb of the cart image is mapped to $E000-$FFFF, the third 8Kb of the cart image is mapped to $8000-$9FFF and the fourth 8Kb of the cart image is mapped to $A000-$BFFF. An NMI can be triggered by the cart, if address $0001 is written to and the cartridge is enabled. The cart can be disabled by software, by clearing bit 4 when writing to $DF00-$DFFF. Cart ROM at $E000-$FFFF can be disabled by setting bit 5 to 0 when writing to $DF00-$DFFF. Cart ROM at $8000-$BFFF can be disabled by setting bit 6 to 1 when writing to $DF00-$DFFF. Bit 7 of a byte written to $DF00-$DFFF can be read back from the cartridge if enabled (like a memory cell).

15.11.3.31 30 - Action Replay 4

Size 32Kb (4 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 1E 00 01 00 00 00 00 00 00  ???@????????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: EA 78 48 A9 7F 8D 0D DD D0 0E 48 AD 0D DD 10 04  .xP.??..?P?.??
...
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 E9 80 4C 81 81 4C  ?.?....80L?.LL
...
4060: 43 48 49 50 00 00 20 10 00 00 00 02 80 00 20 00  CHIP????????.???
4070: 09 80 0E 80 C3 C2 CD 38 30 A2 00 4C EF FC 20 BC  ?.?....80.?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 70 88 4C 3F 80 4C  ?.?....80LpˆL?.L

The control register is the I/O-1 range:

    bit  meaning
    ---  -------
    0    Eprom banking bit 0 (bank address 13)
    1    Controls the GAME line (0 sets GAME low, 1 sets GAME high)
    2    Freeze-end bit (disables the register and hides any rom bank)
    3    Controls the Exrom line (1 sets EXROM low, 0 sets EXROM high)
    4    Eprom banking bit 1 (bank address 14)
    5-7  Unused

The first page of the currently banked ROM block can be read in the I/O-2 range.

15.11.3.32 31 - Stardos

$E000-$FFFF (bank 1)
Size 16Kb (2 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF (bank 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 1F 00 01 00 00 00 00 00 00  ???@????????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: F9 80 B6 80 C3 C2 CD 38 30 FD 80 89 80 4C 0C 88  ?.ถ....80..‰.L?ˆ
...
2050: 43 48 49 50 00 00 20 10 00 00 00 00 E0 00 20 00  CHIP????????????
2060: 85 56 20 0F BC A5 61 C9 88 90 03 20 D4 BA 20 CC  …V???ฅa.ˆ??.๗?.

This cart has 16Kb of ROM, of which the first 8Kb is mapped in at $8000-$9FFF and the second 8Kb is used as a kernel replacement. The kernel replacement is achieved by a clip that needs to be installed inside the C64.

Reading from I/O-1 causes a capacitor to get charged with every read, once the capacitor is charged enough it switches the cart on.

Reading from I/O-2 causes a different capacitor to get charged with every read, once the capacitor is charged enough it switched the cart off.

15.11.3.33 32 - EasyFlash

Size 1024Kb (64 banks of 2 * 8Kb)
GAME inactive (0)
EXROM active (1)
Load address $8000-$9FFF (ROML), $A000-$BFFF or $E000-$FFFF (ROMH)
      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 20 00 01 00 00 00 00 00 00  ???@????????????
0020: 45 61 73 79 46 6C 61 73 68 20 43 61 72 74 72 69  EasyFlash?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 01 80 00 20 00  CHIP????????.???
0050: 00 85 5E FE C3 C2 CD 38 30 93 0D 2B 2B 2B 20 45  ?…^....80.?+++?E

EasyFlash is a 1 MByte Flash EPROM card with multiple configurations and banks possible, it also has 256 bytes of RAM which is mapped into the I/O-2 range.

There are two control registers, one at $DE00 and one at $DE02.

The register at $DE00 does the following:

    bit  meaning
    ---  -------
    7    LED control
    6-3  Unused
    2    Mode (0/1)
    1    Exrom line control
    0    Game line control

The register at $DE02 controls which bank is mapped into ROMH and ROML.

15.11.3.34 33 - EasyFlash Xbank

Size -
GAME -
EXROM -
Load address -

This CRT type is not actually related to a seperate hardware, it is used by some EasyFlash related tools as a container format. Consequently VICE does (can) not load files of this type.

15.11.3.35 34 - Capture

Size 8Kb (1 bank of 8Kb)
GAME inactive (0)
EXROM inactive (0)
Load address $E000-$FFFF
      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 22 00 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 01 E0 00 20 00  CHIP????????????
0050: 00 0A 0D 8A B4 A1 20 80 00 0A 82 8A 8D 20 9E 20  ???Š?.?.??‚Š?ž?

This cart has 8Kb of ROM which is mapped to $E000, and 8Kb of RAM which is mapped to $6000. The cartridge is disabled after a reset.

When the freeze button is pressed the following happens:

15.11.3.36 35 - Action Replay 3

Size 16Kb (2 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 23 00 01 00 00 00 00 00 00  ???@???#????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: EA A9 E3 48 A9 7B 48 08 4C 1A 80 EA EA EA 48 AD  ...H..H?L?....H
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP????????.???
2060: 09 80 5E FE C3 C2 CD 38 30 78 A2 FB D8 9A A9 27  ?.^....80x.....'

This cart has 16Kb of ROM of which 8Kb is mapped in at both ROML and ROMH. Bank switching and control register is done through the I/O-1 range:

    bit  meaning
    ---  -------
    7-4  unused
    3    Exrom line control
    2    Disable cart
    1    Unused
    0    Bank

15.11.3.37 36 - Retro Replay

Size 32Kb, 64Kb or 128Kb (4, 8 or 16 banks of 8Kb)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-$9FFF
      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 24 00 00 00 00 00 00 00 00  ???@???$????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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 7F 81 4C 87 81 4C  ?.?....80L?L.L

The Retro Replay has three registers: Two write-only ($DE00 & $DE01) and one read-only register ($DE00 & $DE01 giving the same results).

The register at $DE00 is reset to $00 on a hard reset if not in flash mode. If in flash mode, it is set to $02 in order to prevent the computer from starting the normal cartridge. Flash mode is selected with a jumper.

Register at $DE00:

    bit  meaning
    ---  -------
    0    Controls the GAME line: A 1 asserts the line, a 0  will  deassert
         it.
    1    Controls the EXROM line: A 0 will assert it, a  1  will  deassert
         it.
    2    Writing a 1 will disable further write accesses to all  registers
         of the Retro Replay, and  set  the  memory  map  of  the  C64  to
         standard, as if there is no cartridge installed at all.
    3    Controls bank-address 13 for ROM and RAM banking.
    4    Controls bank-address 14 for ROM and RAM banking.
    5    Switches between ROM and RAM: 0=ROM, 1=RAM
    6    Must be written once to "1" after a successful freeze in order to
         set the correct memory map and  enable  bits  0  and  1  of  this
         register. Otherwise no effect.
    7    Controls bank-address 15 for ROM banking.

The register at $DE01 is the extended control register. If not in Flash mode, bits 1, 2 and 6 can only be written once. If in Flash mode, the REUcomp bit cannot be set, but the register will not be disabled by the first write. Bit 5 is always set to 0 if not in Flash mode.

Register at $DE01:

    bit  meaning
    ---  -------
    0    Enable clockport connector.
    1    AllowBank (1 allows banking of RAM in $DF00/$DE02 area)
    2    NoFreeze (1 disables Freeze function)
    3    Bank-address 13 for RAM and ROM (mirror of $DE00)
    4    Bank-address 14 for RAM and ROM (mirror of $DE00)
    5    Bank-address 16 for ROM (only in flash mode)
    6    REU compatibility bit. 0=standard memory map, 1 = REU  compatible
         memory map
    7    Bank-address 15 for ROM (mirror of $DE00)

Reading from the registers at either $DE00 or $DE01 will return the content of the status register.

Status register:

    bit  meaning
    ---  -------
    0    1=Flashmode active (jumper set)
    1    feedback of AllowBank bit
    2    1=Freeze button pressed
    3    feedback of banking bit 13
    4    feedback of banking bit 14
    5    feedback of banking bit 16
    6    1=REU compatible memory map active
    7    feedback of banking bit 15

The following memory maps are available:

15.11.3.38 37 - MMC64

Size 8Kb (1 bank of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 25 00 01 00 00 00 00 00 00  ???@???%????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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 64 97 C3 C2 CD 38 30 78 D8 A2 FF 9A 20 D4  ?.d—...80x..?.?.

The clockport registers of this cart can be switched to either $DE01-$DE0F or $DF21-$DF2F. The control registers are available at $DF10-$DF13.

The register at $DE01 / $DF21 is write only:

    bit  meaning
    ---  -------
    7-1  Unused
    0    0 = disable clock port, 1 = enable clockport

The registers at $DE02-$DE0F / $DF22-$DF2F are for the clock port and are read/write.

The register at $DF10 is the MMC64 SPI transfer register, a byte written to this registers is sent to the card & response from the card is read here.

The register at $DF11 is the MMC64 control register:

    bit  meaning
    ---  -------
    0    0 = MMC64 BIOS active, 1 = external ROM active
    1    0 = card selected, 1 = card not selected
    2    0 = 250khz transfer, 1 = 8mhz transfer
    3    0 = clock port @ $DE00, 1 = clock port @ $DF20
    4    0 = normal Operation, 1 = flash mode (*)
    5    0 = allow external rom when BIOS is disabled,
         1 = disable external ROM
    6    0 = SPI write trigger mode, 1 = SPI read trigger mode
    7    0 = MMC64 is active, 1 = MMC64 is completely disabled (**)

(*) bit can only be programmed when flash jumper is set (**) bit can only be modified after unlocking

The register at $DF12 is the MMC64 status register, which is read-only:

    bit  meaning
    ---  -------
    0    0 = SPI ready, 1 = SPI busy
    1    external GAME line
    2    external EXROM line
    3    0 = card inserted, 1 = no card inserted
    4    0 = card write enabled, 1 = card write disabled
    5    0 = flash jumper not set, 1 = flash jumper set
    6-7  unused

The register at $DF13 is the MMC64 identification register, which when reading from it can have the following values:

$64 when bit 1 of $DF11 is 0. $01 when bit 1 of $DF11 is 1 and REV A hardware is used. $02 when bit 1 of $DF11 is 1 and REV B hardware is used.

when writing to it it can be used to unlock bit 7 of $DF11 or to re-enable the cart:

Write $55 & $AA into this register to unlock bit 7 of $DF11. Write $0A & $1C into this register to re-enable MMC64 hardware.

15.11.3.39 38 - MMC Replay

Size 64Kb or 512Kb (8 or 64 banks of 8Kb)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-$9FFF
      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 26 00 00 00 00 00 00 00 00  ???@???&????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 1A 80 6E 9E C3 C2 CD 38 30 4D 4D 43 52 45 50 4C  ?.nž...80MMCREPL

The cart uses the following registers:

$DE00 - RR control register write

    bit  meaning
    ---  -------
    0    GAME line
    1    EXROM line
    2    1 = disable RR, bit can be reset by setting bit 6 of $DF12
    3    bank address 13
    4    bank address 14
    5    0 = rom enable, 1 = ram enable
    6    1 = exit freeze mode
    7    bank address 15

$DE01 - extended RR control register write

    bit  meaning
    ---  -------
    0    0 = disable clockport, 1 = enable clockport
    1    0 = disable I/O RAM banking, 1 = enable I/O RAM banking
    2    0 = enable freeze, 1 = disable freeze
    3    bank address 13 (mirror of $DE00)
    4    bank address 14 (mirror of $DE00)
    5    0 = enable MMC registers, 1 = disable MMC registers. Can only  be
         written when bit 6 of $DF12 is 1. Register becomes effective when
         bit 0 of $DF11 is 1.
    6    0 = RAM/ROM at $DFxx, 1 = RAM/ROM at $DExx
    7    bank address 15 (mirror of $DE00)

$DE02-$DE0F - Clockport memory area (when enabled)

$DF10 - MMC SPI transfer register, a byte written is sent to the card & response from the card is read here.

$DF11 - MMC control register

    bit  meaning
    ---  -------
    0    0 = MMC BIOS enabled, 1 = MMC BIOS disabled.  Enabling  MMC  BIOS
         sets ROM banking to the last 64Kb bank.
    1    0 = card selected, 1 = card not selected. This bit also  controls
         the green activity LED.
    2    0 = 250khz transfer, 1 = 8mhz transfer
    3    ALWAYS 0
    4    ALWAYS 0
    5    (in RR-Mode:)
          0 = allow RR rom when MMC BIOS disabled , 1 = disable RR ROM
          (in mmcreplay bios mode:)
          RAM banking (0 = $E000 - $FFFF, 1 = $8000 - $9FFF)
          (in 16K mode:)
          enable RAM at $A000 - $BFFF
    6    0 = SPI write trigger mode, 1 = SPI read trigger mode
    7    ALWAYS 0

$DF12 - MMC status register

    bit  meaning
    ---  -------
    0    0 = SPI ready, 1 = SPI busy (read)
                        1 = forbid ROM  write  accesses  (write).  Setting
                        this bit will disable writes  to  ROM  until  next
                        reset
    1  feedback of $DE00 bit 0 (GAME)
    2  feedback of $DE00 bit 1 (EXROM)
    3  0 = card inserted, 1 = no card inserted
    4  0 = card write enabled, 1 = card write disabled
    5  EEPROM DATA line /  DDR  register.  Setting  DATA  to  "1"  enables
       reading data bit from EEPROM at this position.
    6  0 = RR compatibility mode, 1 = Extended mode
       Selecting RR compatibility mode limits RAM  to  32Kb  and  disables
       writes  to  extended  banking  register.  Selecting  Extended  mode
       enables full RAM banking and enables Nordic Power mode in RR mode.
    7  EEPROM CLK line

$DF13 - Extended banking register Can only be read/written to when bit 6 of $DF12 is 1

    bit  meaning
    ---  -------
    0    bank address 16
    1    bank address 17
    2    bank address 18
    3    ALWAYS 0
    4    ALWAYS 0
    5    16K rom mapping
    6    1 = enable  RR  register.  Disabling  RR  register  disables  ALL
         ROM/RAM banking too.
    7    ALWAYS 0

15.11.3.40 39 - IDE64

Size 64Kb or 128Kb (8 or 16 banks of 8Kb)
GAME inactive (0)
EXROM inactive (0)
Load address $8000-$9FFF
      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 26 00 00 00 00 00 00 00 00  ???@???'????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 63 80 5E FE C3 C2 CD 38 30 20 49 44 45 36 34 20  c.^....80?IDE64?

The IDE64 cart uses the following registers:

    $DE20 - $DE27  Primary HDD Registers
    $DE28 - $DE2F  Secondary HDD Registers
    $DE30 - Low Data HDD register
    $DE31 - High Data HDD register

$DE32 register:

    bit  meaning
    ---  -------
    7    unused (0)
    6    unused (0)
    5    unused (0)
    4    version number (1)
    3    romaddr15
    2    romaddr14
    1    game
    0    exrom
    $DE33 - $DE35 = IDE64 ROM bank select registers
    $DE5F         = RTC access (bit 0 only to serial accessed RTC)
    $DE60 - $DEFA = RAM used by software
    $DEFB         = IDE64 clock reset, kill the cartridge
    $DEFC - $DEFF = IDE64 ROM configuration registers

15.11.3.41 40 - Super Snapshot V4

Size 32Kb (4 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 28 00 01 00 00 00 00 00 00  ???@???(????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 80 AD B5 80 C3 C2 CD 38 30 08 48 A9 06 8D 00 DF  .ต....80?P.???
...
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00  CHIP???????? ???
2060: 4C FA A0 A9 07 8D 00 DD 2C 00 DD 50 FB 2C 00 DD  L? .??.,?.P.,?.
...
4060: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP????????.???
4070: 13 80 BC FE C3 C2 CD 38 30 08 48 A9 02 8D 00 DF  ?.?....80?H.???
...
6070: 43 48 49 50 00 00 20 10 00 00 00 01 A0 00 20 00  CHIP???????? ???
6080: F0 8A 48 A9 00 85 22 85 23 8D 53 0F 20 0C A1 B0  ?ŠH.?…"…#S???.ฐ

This cart has 32Kb of ROM and 8Kb of RAM, it uses I/O-1 as a mirror of the last page of cart RAM. It has the following registers in the I/O-2 range:

ROM config register at $DF00 (can only be written to):

    bit  meaning
    ---  -------
    0    ?
    1    ? (write 1 to release freeze mode)
    2    ROM bank select
    3    write 1 to disable cartridge
    4-6  unused
    7    ?

Note: if bit0, bit1, bit7 are all 0, then ultimax mapping is selected and RAM is enabled at ROML, otherwise if bit 0 is 0, then 16Kb mapping is enabled, or if bit 0 is 1, then 8Kb mapping is enabled.

RAM config register at $DF01 (read/write):

If written value == last value - 1, then ultimax mapping is selected and RAM is enabled at ROML, if written value == last value + 1, then ROM is enabled at ROML and exrom is deasserted (switch to either 8k or 16k mapping)

$DF02-$DFFF holds the last page of the first 8kb of the current bank.

15.11.3.42 41 - IEEE-488

Size 4Kb (1 bank of 4Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$8FFF
      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 29 00 01 00 00 00 00 00 00  ???@???)????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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 80 00 10 00  CHIP????????.???
0050: 09 80 7A 80 C3 C2 CD 38 30 8E 16 D0 20 84 FF 20  ?.z....80Ž?.?„??

The cart uses a TPI for the IEEE488 interface/communication in the I/O-2 range:

    $DF00 - Port A Data
    $DF01 - Port B Data
    $DF02 - Port C Data
    $DF03 - Port A Direction
    $DF04 - Port B Direction
    $DF05 - Port C Direction
    $DF06 - Control register
    $DF07 - Active Interrupt register

15.11.3.43 42 - Game Killer

Size 8Kb (1 bank of 8Kb)
GAME inactive (0)
EXROM inactive (0)
Load address $E000-$FFFF
      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 2A 00 00 00 00 00 00 00 00  ???@???*????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 00 25 08 CF 07 9E 32 30 38 38 20 4D 43 2E 43 52  ?%?.?ž2088?MC.CR

When the cartridge is active, ultimax is enabled when the address being accessed is is the $E000-$FFFF range, so the ROM is visible at $E000, below is normal C64 RAM. The cart can be disabled by writing to either I/O-1 or I/O-2 range. When the freezer button is pressed, the cartridge will be enabled and an NMI will be triggered.

15.11.3.44 43 - Prophet64

Size 256Kb (32 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 2B 00 01 00 00 00 00 00 00  ???@???+????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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 09 80 C3 C2 CD 38 30 78 A0 00 84 F8 84 FA  ?.?....80x ?„?„?

The control register is the I/O-2 range:

    bit  meaning
    ---  -------
    7-6  unused
    5    disable cart
    4-0  bank select

15.11.3.45 44 - EXOS

Size 8Kb (1 bank of 8Kb)
GAME inactive (0)
EXROM active (1)
Load address $E000-$FFFF
      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 2C 01 00 00 00 00 00 00 00  ???@???,????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 85 56 20 0F BC A5 61 C9 88 90 03 20 D4 BA 20 CC  …V???ฅa.ˆ??.๗?.

This cart has 8Kb of ROM, mapped in at $E000-$FFFF only when hirom is selected. The cart uses a clip that needs to be installed inside the C64.

15.11.3.46 45 - Freeze Frame

Size 8Kb (1 bank of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 2D 00 01 00 00 00 00 00 00  ???@???-????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 10 80 10 80 C3 C2 CD 38 30 20 00 00 00 00 00 00  ?.?....80???????

When reading from the I/O-1 range the cart is enabled, when reading from the I/O-2 range the cart is disabled. When the freeze button is pressed the ROM is mapped to both $8000-$9FFF and $E000-$FFFF.

15.11.3.47 46 - Freeze Machine

Size 16Kb or 32Kb (2 or 4 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 2E 00 01 00 00 00 00 00 00  ???@???.????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 3A 83 60 80 C3 C2 CD 38 30 20 00 00 40 00 00 00  :ƒ`....80???@???
...
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00  CHIP???????? ???
2060: 78 A9 34 85 01 A0 00 B1 F8 91 F6 E6 F8 D0 02 E6  x.4…? ?ฑ?.?ต?.?ต
...
4060: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP????????.???
4070: 3A 83 60 80 C3 C2 CD 38 30 20 00 00 40 00 00 00  :ƒ`....80???@???
...
6070: 43 48 49 50 00 00 20 10 00 00 00 01 A0 00 20 00  CHIP???????? ???
6080: 78 A9 34 85 01 A0 00 B1 F8 91 F6 E6 F8 D0 02 E6  x.4…? ?ฑ?.?ต?.?ต

Warning, the following information is based on guess-work and might be incorrect, any further information and/or corrections are appreciated.

When reading from the I/O-1 range ROM bank 0(/2) is mapped to $8000-$9FFF and ROM bank 1(/3) is mapped to $A000-$BFFF. When reading from the I/O-2 range the cart is disabled. When a reset happens the ROM banks get switched and ROM bank 0(/2) is mapped to $8000-$9FFF. When a freeze happens ROM bank 0(/2) is mapped to both $8000-$9FFF and $E000-$FFFF.

15.11.3.48 47 - Snapshot 64

Size 4Kb (1 bank of 4Kb)
GAME inactive (0)
EXROM inactive (0)
Load address $E000-$EFFF
      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 2F 00 00 00 00 00 00 00 00  ???@???/????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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 E0 00 10 00  CHIP????????????
0050: 78 D8 48 8A 48 98 48 AC 0D DD 10 03 4C EE F2 AD  x.HŠH˜H??.??L??

Warning, the following information is based on guess-work and might be incorrect, any further information and/or corrections are appreciated.

The cart has a control bit (bit 0) in the I/O-2 range which is used to disable or enable the cart.

15.11.3.49 48 - Super Explode V5.0

Size 16Kb (2 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 30 00 01 00 00 00 00 00 00  ???@???0????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: D7 86 5E FE C3 C2 CD 38 30 A9 00 2C A9 FF 85 FE  .†^....80.?,.?….
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP????????.???
2060: E8 96 5E FE C3 C2 CD 38 30 20 6C 81 A9 09 8D 99  ?–^....80?l.?™

Warning, the following information is based on guess-work and might be incorrect, any further information and/or corrections are appreciated.

The cart has 16Kb of ROM which are used as two banks of 8Kb, they are mapped into $8000-$9FFF and the last page of the current ROM bank is mirrored in $DF00-$DFFF. The cart has a control bit (bit 7) at $DF00, which is used to select what ROM bank is used.

15.11.3.50 49 - Magic Voice

$A000-$BFFF (bank 2)
Size 16Kb (2 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF (bank 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 31 00 01 00 00 00 00 00 00  ???@???1????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: EA 2C 80 DF 50 FB A0 00 8C 80 DF B9 E3 A3 29 0F  .,.?P. ?Œ.?น.ฃ)?
...
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00  CHIP???????? ???
2060: 4A EB C0 49 6A EA BB FB 4E CA 43 1E 75 63 15 97  J?.Ij.ป.N.C?uc?—

This cart has 16Kb of ROM, mapped in at reset at $8000-$BFFF. The cart is controled through a TPI at $DF80-$DF87:

    $DF80 - Port A Data
    $DF81 - Port B Data
    $DF82 - Port C Data
    $DF83 - Port A Direction
    $DF84 - Port B Direction
    $DF85 - Port C Direction
    $DF86 - Control register
    $DF87 - Active Interrupt register

The cart has a pass-through port and does the following at start-up:

15.11.3.51 50 - Action Replay 2

Size 16Kb (2 banks of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 32 00 01 00 00 00 00 00 00  ???@???2????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: EA EA 68 AA 68 85 94 68 85 95 68 85 96 68 85 97  ..hืh…”h…•h…–h…—
...
2050: 43 48 49 50 00 00 20 10 00 00 00 01 80 00 20 00  CHIP????????.???
2060: 30 80 5E FE C3 C2 CD 38 30 20 04 90 4C 38 DF 1A  0.^....80??L8??

Warning, the following information is based on guess-work and might be incorrect, any further information and/or corrections are appreciated.

I/O-1 is somehow used to enable the cart, the exact way in which this is done is unknown. Reading from the I/O-2 range will give you the last page of the current ROM bank, and writing to it will disable the cart.

15.11.3.52 51 - MACH 5

$8000-$9FFF (8Kb)
Size 4Kb or 8Kb (1 bank of 4Kb or 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$8FFF (4Kb),
      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 33 00 01 00 00 00 00 00 00  ???@???3????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: AF 83 5E FE C3 C2 CD 38 30 4D 41 43 48 35 A5 93  ปƒ^....80MACH5ฅ.

This cart has 8Kb ROM mapped at $8000-$9FFF, the $9E00-$9EFF range is mirrored at $DE00-$DEFF and the $9F00-$9FFF range is mirrored at $DF00-$DFFF.

15.11.3.53 52 - Diashow maker

Size 8Kb (1 bank of 8Kb)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF
      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 34 00 01 00 00 00 00 00 00  ???@???4????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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 09 80 C3 C2 CD 38 30 AD 11 D0 29 10 D0 62  ?.?....80?.)?.b

Accessing I/O-1 (the software uses $DE00 only it seems) disables cartridge ROM. A reset enables 8K game mode and the ROM bank is mapped to $8000. A freeze causes ROM to be mapped to $8000.

15.11.3.54 53 - Pagefox

Size 64Kb (4 banks of 16Kb)
GAME active (1)
EXROM active (1)
Load address $8000-$BFFF
      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 35 01 01 00 00 00 00 00 00  ???@???5????????
0020: 56 49 43 45 20 43 41 52 54 00 00 00 00 00 00 00  VICE?CART???????
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: 31 80 BB 0E C3 C2 CD 38 30 50 46 20 56 31 2E 30  1.ป?...80PF?V1.0
...
4050: 43 48 49 50 00 00 40 10 00 00 00 01 80 00 40 00  CHIP??@?????.?@?
4060: A2 FE 9A 20 EC AE 20 82 80 20 74 86 20 A5 8B 4C  ...??ฎ?‚.?t†?ฅ‹L
...
8060: 43 48 49 50 00 00 40 10 00 00 00 02 80 00 40 00  CHIP??@?????.?@?
8070: 5A 01 02 03 04 06 0A 0B 10 14 1E 28 3C 00 00 00  Z??????????(<???
...
C070: 43 48 49 50 00 00 40 10 00 00 00 03 80 00 40 00  CHIP??@?????.?@?
C080: 1E 03 14 82 09 05 09 0F 0C 0D 0F 05 09 09 0B 0A  ???‚????????????

This cart has 64Kb ROM (2 32Kb Eproms, mapped to $8000 and $A000 in 16Kb Game Mode), and 32Kb RAM (mapped to $8000 and $A000 in 16K Game Mode). The cart has 1 (write-only) bank control register which is located at $DE80 and mirrored throughout the $DE80-$DEFF range:

    Bit 0: unused/don't care
    Bit 1: Bank select: 0=upper, 1=lower (not correct ?!)
    Bit 2: chip select 0
    Bit 3: chip select 1
    Bit 4: cartridge enable/disable: 0=enable, 1=disable
    Bits 5-7: unused/don't care

Chip select combinations of 0/1 are:

    00: Eprom "79"
    01: Eprom "ZS3"
    10: Ram
    11: empty space (reading returns VIC-II data)

note: on the original hardware "disabling" the cartridge by setting bit 4 of the control register does NOT prevent write accesses to the cartridge RAM!. So to actually disable the RAM, it is suggested to write $FF to the register.

15.11.3.55 54 - Kingsoft

Size -
GAME -
EXROM -
Load address -

15.11.3.56 55 - Silverrock 128

Size 128k (16 banks of 8k)
GAME active (1)
EXROM inactive (0)
Load address $8000-$9FFF

15.11.3.57 56 - Formel 64

Size 32kb (4 banks of 8k)
GAME inactive (0)
EXROM inactive (0)
Load address $E000-$FFFF


Go to the first, previous, next, last section, table of contents.