Files
docs/Commodore/vice_15.html

11214 lines
261 KiB
HTML
Raw Blame History

<HTML>
<HEAD>
<!-- This HTML file has been created by texi2html 1.52
from ../../doc/vice.texi on 30 October 2012 -->
<TITLE>VICE Manual - 15 The emulator file formats</TITLE>
</HEAD>
<BODY>
Go to the <A HREF="vice_1.html">first</A>, <A HREF="vice_14.html">previous</A>, <A HREF="vice_16.html">next</A>, <A HREF="vice_20.html">last</A> section, <A HREF="vice_toc.html">table of contents</A>.
<P><HR><P>
<H1><A NAME="SEC266" HREF="vice_toc.html#TOC266">15 The emulator file formats</A></H1>
<P>
This chapter gives a technical description of the various files
supported by the emulators.
</P>
<H2><A NAME="SEC267" HREF="vice_toc.html#TOC267">15.1 The T64 tape image format</A></H2>
<P>
(This section was taken from the C64S distribution.)
</P>
<P>
The <CODE>T64</CODE> File Structure was developed by Miha Peternel for use in
the C64S emulator. It is easy to use and allows future extensions.
</P>
<H3><A NAME="SEC268" HREF="vice_toc.html#TOC268">15.1.1 T64 File structure</A></H3>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Size</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0</TD>
<TD>64</TD>
<TD>tape record</TD>
</TR>
<TR><TD>64</TD>
<TD>32*n</TD>
<TD>file records for n directory entries</TD>
</TR>
<TR><TD>64+32*n</TD>
<TD>varies</TD>
<TD>binary contents of the files</TD>
</TR></TABLE>
<H3><A NAME="SEC269" HREF="vice_toc.html#TOC269">15.1.2 Tape Record</A></H3>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Size</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0</TD>
<TD>32</TD>
<TD>DOS tape description + EOF (for type)</TD>
</TR>
<TR><TD>32</TD>
<TD>2</TD>
<TD>tape version ($0200)</TD>
</TR>
<TR><TD>34</TD>
<TD>2</TD>
<TD>number of directory entries</TD>
</TR>
<TR><TD>36</TD>
<TD>2</TD>
<TD>number of used entries (can be 0 in my loader)</TD>
</TR>
<TR><TD>38</TD>
<TD>2</TD>
<TD>free</TD>
</TR>
<TR><TD>40</TD>
<TD>24</TD>
<TD>user description as displayed in tape menu</TD>
</TR></TABLE>
<H3><A NAME="SEC270" HREF="vice_toc.html#TOC270">15.1.3 File record</A></H3>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Size</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0</TD>
<TD>1</TD>
<TD>entry type (see below)</TD>
</TR>
<TR><TD>1</TD>
<TD>1</TD>
<TD>C64 file type</TD>
</TR>
<TR><TD>2</TD>
<TD>2</TD>
<TD>start address</TD>
</TR>
<TR><TD>4</TD>
<TD>2</TD>
<TD>end address</TD>
</TR>
<TR><TD>6</TD>
<TD>2</TD>
<TD>free</TD>
</TR>
<TR><TD>8</TD>
<TD>4</TD>
<TD>offset of file contents start within T64 file</TD>
</TR>
<TR><TD>12</TD>
<TD>4</TD>
<TD>free</TD>
</TR>
<TR><TD>16</TD>
<TD>16</TD>
<TD>C64 file name</TD>
</TR></TABLE>
<P>
Valid entry types are:
</P>
<TABLE BORDER>
<TR><TD><B>Code</B></TD>
<TD><B>Explanation</B></TD>
</TR>
<TR><TD><CODE>0</CODE></TD>
<TD>free entry</TD>
</TR>
<TR><TD><CODE>1</CODE></TD>
<TD>normal tape file</TD>
</TR>
<TR><TD><CODE>2</CODE></TD>
<TD>tape file with header: header is saved just before file data</TD>
</TR>
<TR><TD><CODE>3</CODE></TD>
<TD>memory snapshot v0.9, uncompressed</TD>
</TR>
<TR><TD><CODE>4</CODE></TD>
<TD>tape block</TD>
</TR>
<TR><TD><CODE>5</CODE></TD>
<TD>digitized stream</TD>
</TR>
<TR><TD><CODE>6</CODE> ... <CODE>255</CODE></TD>
<TD>reserved</TD>
</TR></TABLE>
<P>
Notes:
</P>
<UL>
<LI>VICE only supports file type <CODE>1</CODE>.
<LI>Types <CODE>3</CODE>, <CODE>4</CODE> and <CODE>5</CODE> are subject to change (and
are rarely used).
</UL>
<H2><A NAME="SEC271" HREF="vice_toc.html#TOC271">15.2 The G64 GCR-encoded disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Ettore Perazzoli.)
</P>
<P>
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
<CODE>D64</CODE>.
</P>
<P>
The intention behind <CODE>G64</CODE> is not to replace the widely used
<CODE>D64</CODE> format, as <CODE>D64</CODE> 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 <CODE>D64</CODE> image.
</P>
<P>
<CODE>G64</CODE> 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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<PRE>
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 .. .. .. ..
</PRE>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$0000-0007</TD>
<TD>File signature (<CODE>GCR-1541</CODE>)</TD>
</TR>
<TR><TD>$0008</TD>
<TD><CODE>G64</CODE> version (presently only $00 defined)</TD>
</TR>
<TR><TD>$0009</TD>
<TD>Number of tracks in image (usually $54, decimal 84)</TD>
</TR>
<TR><TD>$000A-000B</TD>
<TD>Size of each stored track in bytes (usually 7928, or $1EF8) in LO/HI format.</TD>
</TR></TABLE>
<P>
An obvious question here is "why are there 84 tracks defined when a
normal <CODE>D64</CODE> 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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Below is a dump of the first section of a <CODE>G64</CODE> 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.
</P>
<PRE>
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 .. .. .. ..
</PRE>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$000C-000F</TD>
<TD>Offset to stored track 1.0 ($000002AC, in LO/HI format, see below for more)</TD>
</TR>
<TR><TD>$0010-0013</TD>
<TD>Offset to stored track 1.5 ($00000000)</TD>
</TR>
<TR><TD>$0014-0017</TD>
<TD>Offset to stored track 2.0 ($000021A6)</TD>
</TR>
<TR><TD>...</TD>
</TR>
<TR><TD>$0154-0157</TD>
<TD>Offset to stored track 42.0 ($0004F8B6)</TD>
</TR>
<TR><TD>$0158-015B</TD>
<TD>Offset to stored track 42.5 ($00000000)</TD>
</TR></TABLE>
<PRE>
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 .. .. .. ..
</PRE>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$015C-015F</TD>
<TD>Speed zone entry for track 1 ($03, in LO/HI format, see below for more)</TD>
</TR>
<TR><TD>$0160-0163</TD>
<TD>Speed zone entry for track 1.5 ($03)</TD>
</TR>
<TR><TD>...</TD>
</TR>
<TR><TD>$02A4-02A7</TD>
<TD>Speed zone entry for track 42 ($00)</TD>
</TR>
<TR><TD>$02A8-02AB</TD>
<TD>Speed zone entry for track 42.5 ($00)</TD>
</TR></TABLE>
<P>
Starting here at $02AC is the first track entry (from above, it is the
first entry for track 1.0)
</P>
<P>
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...
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Offset</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$02AC-02AD</TD>
<TD>Actual size of stored track (7692 or $1E0C, in LO/HI format)</TD>
</TR>
<TR><TD>$02AE-02AE+$1E0C</TD>
<TD>Track data</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<PRE>
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 .. .. .. .. .. .. .. .. .. ..
</PRE>
<P>
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:
</P>
<TABLE BORDER>
<TR><TD><B>Track Range</B></TD>
<TD><B>Speed Zone</B></TD>
</TR>
<TR><TD>1-17</TD>
<TD>3 (highest writing speed)</TD>
</TR>
<TR><TD>18-24</TD>
<TD>2</TD>
</TR>
<TR><TD>25-30</TD>
<TD>1</TD>
</TR>
<TR><TD>31 and up</TD>
<TD>0 (lowest writing speed)</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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:
</P>
<PRE>
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)
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H2><A NAME="SEC272" HREF="vice_toc.html#TOC272">15.3 The P64 NRZI flux pulse disk image format</A></H2>
<P>
This section is taken from "P64 file format specification" by Benjamin 'BeRo'
Rosseaux.
</P>
<P>
All values are in little endian order !
</P>
<H3><A NAME="SEC273" HREF="vice_toc.html#TOC273">15.3.1 P64 Header Layout</A></H3>
<PRE>
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 |
+-------------------------------+
</PRE>
<P>
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
</P>
<H3><A NAME="SEC274" HREF="vice_toc.html#TOC274">15.3.2 P64 Chunk Header Layout</A></H3>
<PRE>
0 1 2 3 4 5 6 7 8 9 A B C D E F
+-----------------------------------------------+
0000: |Chunk Signature| Size | CRC32Checksum |
+-----------------------------------------------+
</PRE>
<P>
Chunk signature: Signature of chunk
Size: Size of the chunk data
CRC32CheckSum: CRC32 checksum of the chunk data
</P>
<H3><A NAME="SEC275" HREF="vice_toc.html#TOC275">15.3.3 P64 Chunk 'HTPx' Layout</A></H3>
<P>
| 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
<PRE>
0 1 2 3 4 5 6 7 8 9 A B C D E F
+---------------------------------------------------------------+
0000: | Count pulses | Size | ..... Range-encoded data .... |
+---------------------------------------------------------------+
</PRE>
<P>
Count pulses: Count of the NRZI transition flux pulses in half track
Size: Size of the range-encoded data
<H3><A NAME="SEC276" HREF="vice_toc.html#TOC276">15.3.4 'HTPx' Range encoded data format</A></H3>
<P>
Hint: For a working C implememtation see p64.c and p64.h
</P>
<P>
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.
</P>
<PRE>
+--------------------------------------------------------------------------+
| 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 |==================|==================|
+--------------------------------------------------------------------------+
</PRE>
<P>
All initial model state values are initialized with zero.
All initial model probability values are initialized with 2048.
</P>
<P>
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.
</P>
<P>
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:
</P>
<P>
Pascal-Style pseudo code:
<PRE>
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;
</PRE>
<P>
And for 1-bit flag values it is much simpler, but also with model probability
shifting of 4 bits, just as:
</P>
<P>
Pascal-Style pseudo code:
<PRE>
procedure WriteBit(Model, Value : longword);
begin
RangeCoderProbabilityStates[Model] :=
RangeCoderEncodeBit(RangeCoderProbabilities[
RangeCoderProbabilityOffsets[Model] +
RangeCoderProbabilityStates[Model]], 4, Value and 1);
end;
</PRE>
<P>
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.
</P>
<P>
Pascal-Style pseudo code:
<PRE>
LastPosition := 0;
PreviousDeltaPosition := 0
LastStrength := 0;
for PulseIndex := 0 to PulseCount - 1 do begin
DeltaPosition := Pulses[PulseIndex].Position - LastPosition;
if PreviousDeltaPosition &#60;&#62; DeltaPosition then begin
PreviousDeltaPosition := DeltaPosition;
WriteBit(ModelPositionFlag, 1)
WriteDWord(ModelPosition, DeltaPosition);
end else begin
WriteBit(ModelPositionFlag, 0);
end;
LastPosition := Pulses[PulseIndex].Position;
if LastStrength &#60;&#62; 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);
</PRE>
<P>
The decoding is simply just in the another direction way.
Pseudo code for a FPAQ0-style carryless range coder:
</P>
<P>
Pascal-Style pseudo code:
<PRE>
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 &#60;&#62; 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 &#60;= 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;
</PRE>
<P>
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 &#60; 1); " in C.
<H3><A NAME="SEC277" HREF="vice_toc.html#TOC277">15.3.5 P64 Chunk 'DONE' Layout</A></H3>
<P>
This is the last empty chunk for to signalize that the correct file end is
reached.
</P>
<H2><A NAME="SEC278" HREF="vice_toc.html#TOC278">15.4 The D64 disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
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.
</P>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>Sectors/track</B></TD>
<TD><B># Sectors</B></TD>
</TR>
<TR><TD>1-17</TD>
<TD>21</TD>
<TD>357</TD>
</TR>
<TR><TD>18-24</TD>
<TD>19</TD>
<TD>133</TD>
</TR>
<TR><TD>25-30</TD>
<TD>18</TD>
<TD>108</TD>
</TR>
<TR><TD>31-35</TD>
<TD>17</TD>
<TD>85</TD>
</TR>
<TR><TD>36-40(*)</TD>
<TD>17</TD>
<TD>85</TD>
</TR></TABLE>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>#Sect</B></TD>
<TD><B>#SectorsIn</B></TD>
<TD><B>D64 Offset</B></TD>
</TR>
<TR><TD>1</TD>
<TD>21</TD>
<TD>0</TD>
<TD>$00000</TD>
</TR>
<TR><TD>2</TD>
<TD>21</TD>
<TD>21</TD>
<TD>$01500</TD>
</TR>
<TR><TD>3</TD>
<TD>21</TD>
<TD>42</TD>
<TD>$02A00</TD>
</TR>
<TR><TD>4</TD>
<TD>21</TD>
<TD>63</TD>
<TD>$03F00</TD>
</TR>
<TR><TD>5</TD>
<TD>21</TD>
<TD>84</TD>
<TD>$05400</TD>
</TR>
<TR><TD>6</TD>
<TD>21</TD>
<TD>105</TD>
<TD>$06900</TD>
</TR>
<TR><TD>7</TD>
<TD>21</TD>
<TD>126</TD>
<TD>$07E00</TD>
</TR>
<TR><TD>8</TD>
<TD>21</TD>
<TD>147</TD>
<TD>$09300</TD>
</TR>
<TR><TD>9</TD>
<TD>21</TD>
<TD>168</TD>
<TD>$0A800</TD>
</TR>
<TR><TD>10</TD>
<TD>21</TD>
<TD>189</TD>
<TD>$0BD00</TD>
</TR>
<TR><TD>11</TD>
<TD>21</TD>
<TD>210</TD>
<TD>$0D200</TD>
</TR>
<TR><TD>12</TD>
<TD>21</TD>
<TD>231</TD>
<TD>$0E700</TD>
</TR>
<TR><TD>13</TD>
<TD>21</TD>
<TD>252</TD>
<TD>$0FC00</TD>
</TR>
<TR><TD>14</TD>
<TD>21</TD>
<TD>273</TD>
<TD>$11100</TD>
</TR>
<TR><TD>15</TD>
<TD>21</TD>
<TD>294</TD>
<TD>$12600</TD>
</TR>
<TR><TD>16</TD>
<TD>21</TD>
<TD>315</TD>
<TD>$13B00</TD>
</TR>
<TR><TD>17</TD>
<TD>21</TD>
<TD>336</TD>
<TD>$15000</TD>
</TR>
<TR><TD>18</TD>
<TD>19</TD>
<TD>357</TD>
<TD>$16500</TD>
</TR>
<TR><TD>19</TD>
<TD>19</TD>
<TD>376</TD>
<TD>$17800</TD>
</TR>
<TR><TD>20</TD>
<TD>19</TD>
<TD>395</TD>
<TD>$18B00</TD>
</TR>
<TR><TD>21</TD>
<TD>19</TD>
<TD>414</TD>
<TD>$19E00</TD>
</TR>
<TR><TD>22</TD>
<TD>19</TD>
<TD>433</TD>
<TD>$1B100</TD>
</TR>
<TR><TD>23</TD>
<TD>19</TD>
<TD>452</TD>
<TD>$1C400</TD>
</TR>
<TR><TD>24</TD>
<TD>19</TD>
<TD>471</TD>
<TD>$1D700</TD>
</TR>
<TR><TD>25</TD>
<TD>18</TD>
<TD>490</TD>
<TD>$1EA00</TD>
</TR>
<TR><TD>26</TD>
<TD>18</TD>
<TD>508</TD>
<TD>$1FC00</TD>
</TR>
<TR><TD>27</TD>
<TD>18</TD>
<TD>526</TD>
<TD>$20E00</TD>
</TR>
<TR><TD>28</TD>
<TD>18</TD>
<TD>544</TD>
<TD>$22000</TD>
</TR>
<TR><TD>29</TD>
<TD>18</TD>
<TD>562</TD>
<TD>$23200</TD>
</TR>
<TR><TD>30</TD>
<TD>18</TD>
<TD>580</TD>
<TD>$24400</TD>
</TR>
<TR><TD>31</TD>
<TD>17</TD>
<TD>598</TD>
<TD>$25600</TD>
</TR>
<TR><TD>32</TD>
<TD>17</TD>
<TD>615</TD>
<TD>$26700</TD>
</TR>
<TR><TD>33</TD>
<TD>17</TD>
<TD>632</TD>
<TD>$27800</TD>
</TR>
<TR><TD>34</TD>
<TD>17</TD>
<TD>649</TD>
<TD>$28900</TD>
</TR>
<TR><TD>35</TD>
<TD>17</TD>
<TD>666</TD>
<TD>$29A00</TD>
</TR>
<TR><TD>36(*)</TD>
<TD>17</TD>
<TD>683</TD>
<TD>$2AB00</TD>
</TR>
<TR><TD>37(*)</TD>
<TD>17</TD>
<TD>700</TD>
<TD>$2BC00</TD>
</TR>
<TR><TD>38(*)</TD>
<TD>17</TD>
<TD>717</TD>
<TD>$2CD00</TD>
</TR>
<TR><TD>39(*)</TD>
<TD>17</TD>
<TD>734</TD>
<TD>$2DE00</TD>
</TR>
<TR><TD>40(*)</TD>
<TD>17</TD>
<TD>751</TD>
<TD>$2EF00</TD>
</TR></TABLE>
<P>
(*) Tracks 36-40 apply to 40-track images only.
</P>
<P>
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.
</P>
<P>
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):
</P>
<PRE>
00: 12 04 81 11 00 4E 41 4D 45 53 20 26 20 50 4F 53 &#60;- notice the T/S link
10: 49 54 A0 A0 A0 00 00 00 00 00 00 00 00 00 15 00 &#60;- to 18/4 ($12/$04)
20: 00 00 84 11 02 41 44 44 49 54 49 4F 4E 41 4C 20 &#60;- and how its not here
30: 49 4E 46 4F A0 11 0C FE 00 00 00 00 00 00 61 01 &#60;- ($00/$00)
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
This is a breakdown of a standard directory sector:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$1F</TD>
<TD>First directory entry</TD>
</TR>
<TR><TD>$20-$3F</TD>
<TD>Second dir entry</TD>
</TR>
<TR><TD>$40-$5F</TD>
<TD>Third dir entry</TD>
</TR>
<TR><TD>$60-$7F</TD>
<TD>Fourth dir entry</TD>
</TR>
<TR><TD>$80-$9F</TD>
<TD>Fifth dir entry</TD>
</TR>
<TR><TD>$A0-$BF</TD>
<TD>Sixth dir entry</TD>
</TR>
<TR><TD>$C0-$DF</TD>
<TD>Seventh dir entry</TD>
</TR>
<TR><TD>$E0-$FF</TD>
<TD>Eighth dir entry</TD>
</TR></TABLE>
<P>
This is a breakdown of a standard directory entry:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector)</TD>
</TR>
<TR><TD>$02</TD>
<TD>File type</TD>
</TR>
<TR><TD>$03-$04</TD>
<TD>Track/sector location of first sector of file</TD>
</TR>
<TR><TD>$05-$14</TD>
<TD>16 character filename (in PETASCII, padded with $A0)</TD>
</TR>
<TR><TD>$15-$16</TD>
<TD>Track/Sector location of first side-sector block (REL file only)</TD>
</TR>
<TR><TD>$17</TD>
<TD>REL file record length (REL file only, max. value 254)</TD>
</TR>
<TR><TD>$18-$1D</TD>
<TD>Unused (except with GEOS disks)</TD>
</TR>
<TR><TD>$1E-$1F</TD>
<TD>File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is &#60;= #sectors * 254</TD>
</TR></TABLE>
<P>
The file type field is used as follows:
</P>
<TABLE BORDER>
<TR><TD><B>Bits</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0-3</TD>
<TD>The actual file type</TD>
</TR>
<TR><TD>4</TD>
<TD>Unused</TD>
</TR>
<TR><TD>5</TD>
<TD>Used only during SAVE-@ replacement</TD>
</TR>
<TR><TD>6</TD>
<TD>Locked flag (Set produces "&#62;" locked files)</TD>
</TR>
<TR><TD>7</TD>
<TD>Closed flag (Not set produces "*", or "splat" files)</TD>
</TR></TABLE>
<P>
The actual file type can be one of the following:
</P>
<TABLE BORDER>
<TR><TD><B>Binary</B></TD>
<TD><B>Decimal</B></TD>
<TD><B>File type</B></TD>
</TR>
<TR><TD>0000</TD>
<TD>0</TD>
<TD>DEL</TD>
</TR>
<TR><TD>0001</TD>
<TD>1</TD>
<TD>SEQ</TD>
</TR>
<TR><TD>0010</TD>
<TD>2</TD>
<TD>PRG</TD>
</TR>
<TR><TD>0011</TD>
<TD>3</TD>
<TD>USR</TD>
</TR>
<TR><TD>0100</TD>
<TD>4</TD>
<TD>REL</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC279" HREF="vice_toc.html#TOC279">15.4.1 Non-Standard &#38; Long Directories</A></H3>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC280" HREF="vice_toc.html#TOC280">15.4.2 BAM layout</A></H3>
<P>
The layout of the BAM area (sector 18/0) is a bit more complicated...
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>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)</TD>
</TR>
<TR><TD>$02</TD>
<TD>Disk DOS version type (see note below) $41 ("A")</TD>
</TR>
<TR><TD>$03</TD>
<TD>Unused</TD>
</TR>
<TR><TD>$04-$8F</TD>
<TD>BAM entries for each track, in groups of four bytes per track, starting on track 1 (see below for more details)</TD>
</TR>
<TR><TD>$90-$9F</TD>
<TD>Disk Name (padded with $A0)</TD>
</TR>
<TR><TD>$A0-$A1</TD>
<TD>Filled with $A0</TD>
</TR>
<TR><TD>$A2-$A3</TD>
<TD>Disk ID</TD>
</TR>
<TR><TD>$A4</TD>
<TD>Usually $A0</TD>
</TR>
<TR><TD>$A5-$A6</TD>
<TD>DOS type, usually "2A"</TD>
</TR>
<TR><TD>$A7-$AA</TD>
<TD>Filled with $A0</TD>
</TR>
<TR><TD>$AB</TD>
<TD>Unused ($00)</TD>
</TR>
<TR><TD>$AC-$BF</TD>
<TD>For DOLPHIN DOS track 36-40 BAM entries, otherwise unused ($00)</TD>
</TR>
<TR><TD>$C0-$D3</TD>
<TD>For SPEED DOS track 36-40 BAM entries, otherwise unused ($00)</TD>
</TR>
<TR><TD>$D4-$FF Unused ($00)</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Data</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$04-$07</TD>
<TD>$12 $FF $F9 $17</TD>
<TD>Track 1 BAM</TD>
</TR>
<TR><TD>$08-$0B</TD>
<TD>$15 $FF $FF $FF</TD>
<TD>Track 2 BAM</TD>
</TR>
<TR><TD>$0C-$0F</TD>
<TD>$15 $FF $FF $1F</TD>
<TD>Track 3 BAM</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$8C-$8F</TD>
<TD>$11 $FF $FF $01</TD>
<TD>Track 35 BAM</TD>
</TR></TABLE>
<P>
These entries must be viewed in binary to make any sense. We will
use the first entry (track 1) at bytes 04-07:
</P>
<PRE>
FF=11111111, F9=11111001, 17=00010111
</PRE>
<P>
In order to make any sense from the binary notation, flip the
bits around.
</P>
<PRE>
111111 11112222
01234567 89012345 67890123
--------------------------
11111111 10011111 11101000
^ ^
sector 0 sector 20
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<TABLE BORDER>
<TR><TD>1</TD>
<TD>2</TD>
<TD>3</TD>
<TD>4</TD>
<TD>5</TD>
<TD>6</TD>
</TR>
<TR><TD>----</TD>
<TD>----</TD>
<TD>----</TD>
<TD>----</TD>
<TD>----</TD>
<TD>----</TD>
</TR>
<TR><TD>17/0</TD>
<TD>17/10</TD>
<TD>17/20</TD>
<TD>17/1</TD>
<TD>17/11</TD>
<TD>0/52</TD>
</TR>
<TR><TD>(11/00)</TD>
<TD>(11/0A)</TD>
<TD>(11/14)</TD>
<TD>(11/01)</TD>
<TD>(11/0B)</TD>
<TD>(0/34)</TD>
</TR></TABLE>
<H3><A NAME="SEC281" HREF="vice_toc.html#TOC281">15.4.3 Variations on the D64 layout</A></H3>
<P>
These are some variations of the D64 layout:
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Below is a small chart detailing the standard file sizes of
D64 images, 35 or 40 tracks, with or without error bytes.
</P>
<TABLE BORDER>
<TR><TD><B>Disk type</B></TD>
<TD><B>Size</B></TD>
</TR>
<TR><TD>35 track, no errors</TD>
<TD>174848</TD>
</TR>
<TR><TD>35 track, 683 error bytes</TD>
<TD>175531</TD>
</TR>
<TR><TD>40 track, no errors</TD>
<TD>196608</TD>
</TR>
<TR><TD>40 track, 768 error bytes</TD>
<TD>197376</TD>
</TR></TABLE>
<P>
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.
</P>
<TABLE BORDER>
<TR><TD><B>Disk format</B></TD>
<TD><B>tracks</B></TD>
<TD><B>header 7/8</B></TD>
<TD><B>Dos type</B></TD>
<TD><B>Diskdos vs. type</B></TD>
</TR>
<TR><TD>Original CBM DOS v2.6</TD>
<TD>35</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>*SpeedDOS+</TD>
<TD>40</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>Professional DOS Initial</TD>
<TD>35</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>Professional DOS Version 1/Prototype</TD>
<TD>40</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>ProfDOS Release</TD>
<TD>40</TD>
<TD>$0f $0f</TD>
<TD>"4A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>Dolphin-DOS 2.0/3.0</TD>
<TD>35</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>Dolphin-DOS 2.0/3.0</TD>
<TD>40</TD>
<TD>$0d $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>PrologicDOS 1541</TD>
<TD>35</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>PrologicDOS 1541</TD>
<TD>40</TD>
<TD>$0f $0f</TD>
<TD>"2P"</TD>
<TD>$50/'P'</TD>
</TR>
<TR><TD>ProSpeed 1571 2.0</TD>
<TD>35</TD>
<TD>$0f $0f</TD>
<TD>"2A"</TD>
<TD>$41/'A'</TD>
</TR>
<TR><TD>ProSpeed 1571 2.0</TD>
<TD>40</TD>
<TD>$0f $0f</TD>
<TD>"2P"</TD>
<TD>$50/'P'</TD>
</TR></TABLE>
<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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Below is a HEX dump of a Speed DOS BAM sector. Note the
location of the extra BAM info from $C0-D3.
</P>
<PRE>
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
</PRE>
<P>
Below is a HEX dump of a Dolphin DOS BAM sector. Note
the location of the extra BAM info from $AC-BF.
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<PRE>
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
</PRE>
<H3><A NAME="SEC282" HREF="vice_toc.html#TOC282">15.4.4 Error codes</A></H3>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Code : $03
Error : 21
Type : Seek
Message : No SYNC sequence found.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Code : $02
Error : 20
Type : Seek
Message : Header descriptor byte not found (HEX $08, GCR $52)
</P>
<P>
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.
</P>
<P>
Basically, what a track has is SYNC marks, and possibly valid
data blocks, but no valid header descriptors.
</P>
<P>
Code : $09
Error : 27
Type : Seek
Message : Checksum error in header block
</P>
<P>
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.
</P>
<P>
Code : $0B
Error : 29
Type : Seek
Message : Disk sector ID mismatch
</P>
<P>
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.
</P>
<P>
Code : $02
Error : 20
Type : Seek
Message : Header block not found
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Note that the entire sector is read before these errors are
detected. Therefore the data, checksum and off bytes are
available.
</P>
<P>
Code : $04
Error : 22
Type : Read
Message : Data descriptor byte not found (HEX $07, GCR $55)
</P>
<P>
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.
</P>
<P>
Code : $05
Error : 23
Type : Read
Message : Checksum error in data block
</P>
<P>
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.
</P>
<P>
Code : $0F
Error : 74
Type : Read
Message : Drive Not Ready (no disk in drive or no device 1)
</P>
<P>
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.
</P>
<P>
Code : $06
Error : 24
Type : Write
Message : Write verify (on format)
</P>
<P>
Code : $07
Error : 25
Type : Write
Message : Write verify error
</P>
<P>
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.
</P>
<P>
Code : $08
Error : 26
Type : Write
Message : Write protect on
</P>
<P>
Self explanatory. Remove the write-protect tab, and try again.
</P>
<P>
Code : $0A
Error : 28
Type : Write
Message : Write error
</P>
<P>
In actual fact, this error never occurs, but it is included
for completeness.
</P>
<P>
This is not an error at all, but it gets reported when the
read of a sector is ok.
</P>
<P>
Code : $01
Error : 00
Type : N/A
Message : No error.
</P>
<P>
Self explanatory. No errors were detected in the reading
and decoding of the sector.
</P>
<P>
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.
</P>
<H2><A NAME="SEC283" HREF="vice_toc.html#TOC283">15.5 The X64 disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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:
</P>
<PRE>
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 &#60;- standard C64 image starts here....
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$03</TD>
<TD>This is the "Magic header" ($43 $15 $41 $64)</TD>
</TR>
<TR><TD>$04</TD>
<TD>Header version major ($01)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Header version minor ($01, now its up to $02)</TD>
</TR>
<TR><TD>$06</TD>
<TD>Device type represented</TD>
</TR>
<TR><TD>$07</TD>
<TD>Maximum tracks in image (only in version 1.02 or greater) 1540/41/70: 35 1571: 35 1581: 80 (Logical single-sided disk)</TD>
</TR>
<TR><TD>$08</TD>
<TD>Number of disk sides in image. This value must be $00 for all 1541 and 1581 formats. $00=No second side $01=Second side</TD>
</TR>
<TR><TD>$09</TD>
<TD>Error data flag.</TD>
</TR>
<TR><TD>$0A-$1F</TD>
<TD>Unused, set to $00</TD>
</TR>
<TR><TD>$20-$3E</TD>
<TD>Disk image description (in ASCII or ISO Latin/1)</TD>
</TR>
<TR><TD>$3F</TD>
<TD>Always set to $00</TD>
</TR>
<TR><TD>$40-</TD>
<TD>Standard C64 file begins here.</TD>
</TR></TABLE>
<P>
The device types are:
</P>
<TABLE BORDER>
<TR><TD><B>Value</B></TD>
<TD><B>Drive type</B></TD>
</TR>
<TR><TD>$00</TD>
<TD>1540 See note below...</TD>
</TR>
<TR><TD>$01</TD>
<TD>1541 (Default)</TD>
</TR>
<TR><TD>$02</TD>
<TD>1542</TD>
</TR>
<TR><TD>$03</TD>
<TD>1551</TD>
</TR>
<TR><TD>$04</TD>
<TD>1570</TD>
</TR>
<TR><TD>$05</TD>
<TD>1571</TD>
</TR>
<TR><TD>$06</TD>
<TD>1572</TD>
</TR>
<TR><TD>$08</TD>
<TD>1581</TD>
</TR>
<TR><TD>$10</TD>
<TD>2031 or 4031</TD>
</TR>
<TR><TD>$11</TD>
<TD>2040 or 3040</TD>
</TR>
<TR><TD>$12</TD>
<TD>2041</TD>
</TR>
<TR><TD>$18</TD>
<TD>4040</TD>
</TR>
<TR><TD>$20</TD>
<TD>8050</TD>
</TR>
<TR><TD>$21</TD>
<TD>8060</TD>
</TR>
<TR><TD>$22</TD>
<TD>8061</TD>
</TR>
<TR><TD>$30</TD>
<TD>SFD-1001</TD>
</TR>
<TR><TD>$31</TD>
<TD>8250</TD>
</TR>
<TR><TD>$32</TD>
<TD>8280</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<H2><A NAME="SEC284" HREF="vice_toc.html#TOC284">15.6 The D71 disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
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:
</P>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>Sec/trk</B></TD>
<TD><B># Sectors</B></TD>
</TR>
<TR><TD>1-17 (side 0)</TD>
<TD>21</TD>
<TD>357</TD>
</TR>
<TR><TD>18-24 (side 0)</TD>
<TD>19</TD>
<TD>133</TD>
</TR>
<TR><TD>25-30 (side 0)</TD>
<TD>18</TD>
<TD>108</TD>
</TR>
<TR><TD>31-35 (side 0)</TD>
<TD>17</TD>
<TD>85</TD>
</TR>
<TR><TD>36-52 (side 1)</TD>
<TD>21</TD>
<TD>357</TD>
</TR>
<TR><TD>53-59 (side 1)</TD>
<TD>19</TD>
<TD>133</TD>
</TR>
<TR><TD>60-65 (side 1)</TD>
<TD>18</TD>
<TD>108</TD>
</TR>
<TR><TD>66-70 (side 1)</TD>
<TD>17</TD>
<TD>85</TD>
</TR></TABLE>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>#Sect</B></TD>
<TD><B>#SectorsIn</B></TD>
<TD><B>D71 Offset</B></TD>
</TR>
<TR><TD>1</TD>
<TD>21</TD>
<TD>0</TD>
<TD>$00000</TD>
</TR>
<TR><TD>2</TD>
<TD>21</TD>
<TD>21</TD>
<TD>$01500</TD>
</TR>
<TR><TD>3</TD>
<TD>21</TD>
<TD>42</TD>
<TD>$02A00</TD>
</TR>
<TR><TD>4</TD>
<TD>21</TD>
<TD>63</TD>
<TD>$03F00</TD>
</TR>
<TR><TD>5</TD>
<TD>21</TD>
<TD>84</TD>
<TD>$05400</TD>
</TR>
<TR><TD>6</TD>
<TD>21</TD>
<TD>105</TD>
<TD>$06900</TD>
</TR>
<TR><TD>7</TD>
<TD>21</TD>
<TD>126</TD>
<TD>$07E00</TD>
</TR>
<TR><TD>8</TD>
<TD>21</TD>
<TD>147</TD>
<TD>$09300</TD>
</TR>
<TR><TD>9</TD>
<TD>21</TD>
<TD>168</TD>
<TD>$0A800</TD>
</TR>
<TR><TD>10</TD>
<TD>21</TD>
<TD>189</TD>
<TD>$0BD00</TD>
</TR>
<TR><TD>11</TD>
<TD>21</TD>
<TD>210</TD>
<TD>$0D200</TD>
</TR>
<TR><TD>12</TD>
<TD>21</TD>
<TD>231</TD>
<TD>$0E700</TD>
</TR>
<TR><TD>13</TD>
<TD>21</TD>
<TD>252</TD>
<TD>$0FC00</TD>
</TR>
<TR><TD>14</TD>
<TD>21</TD>
<TD>273</TD>
<TD>$11100</TD>
</TR>
<TR><TD>15</TD>
<TD>21</TD>
<TD>294</TD>
<TD>$12600</TD>
</TR>
<TR><TD>16</TD>
<TD>21</TD>
<TD>315</TD>
<TD>$13B00</TD>
</TR>
<TR><TD>17</TD>
<TD>21</TD>
<TD>336</TD>
<TD>$15000</TD>
</TR>
<TR><TD>18</TD>
<TD>19</TD>
<TD>357</TD>
<TD>$16500</TD>
</TR>
<TR><TD>19</TD>
<TD>19</TD>
<TD>376</TD>
<TD>$17800</TD>
</TR>
<TR><TD>20</TD>
<TD>19</TD>
<TD>395</TD>
<TD>$18B00</TD>
</TR>
<TR><TD>21</TD>
<TD>19</TD>
<TD>414</TD>
<TD>$19E00</TD>
</TR>
<TR><TD>22</TD>
<TD>19</TD>
<TD>433</TD>
<TD>$1B100</TD>
</TR>
<TR><TD>23</TD>
<TD>19</TD>
<TD>452</TD>
<TD>$1C400</TD>
</TR>
<TR><TD>24</TD>
<TD>19</TD>
<TD>471</TD>
<TD>$1D700</TD>
</TR>
<TR><TD>25</TD>
<TD>18</TD>
<TD>490</TD>
<TD>$1EA00</TD>
</TR>
<TR><TD>26</TD>
<TD>18</TD>
<TD>508</TD>
<TD>$1FC00</TD>
</TR>
<TR><TD>27</TD>
<TD>18</TD>
<TD>526</TD>
<TD>$20E00</TD>
</TR>
<TR><TD>28</TD>
<TD>18</TD>
<TD>544</TD>
<TD>$22000</TD>
</TR>
<TR><TD>29</TD>
<TD>18</TD>
<TD>562</TD>
<TD>$23200</TD>
</TR>
<TR><TD>30</TD>
<TD>18</TD>
<TD>580</TD>
<TD>$24400</TD>
</TR>
<TR><TD>31</TD>
<TD>17</TD>
<TD>598</TD>
<TD>$25600</TD>
</TR>
<TR><TD>32</TD>
<TD>17</TD>
<TD>615</TD>
<TD>$26700</TD>
</TR>
<TR><TD>33</TD>
<TD>17</TD>
<TD>632</TD>
<TD>$27800</TD>
</TR>
<TR><TD>34</TD>
<TD>17</TD>
<TD>649</TD>
<TD>$28900</TD>
</TR>
<TR><TD>35</TD>
<TD>17</TD>
<TD>666</TD>
<TD>$29A00</TD>
</TR>
<TR><TD>36</TD>
<TD>21</TD>
<TD>683</TD>
<TD>$2AB00</TD>
</TR>
<TR><TD>37</TD>
<TD>21</TD>
<TD>704</TD>
<TD>$2C000</TD>
</TR>
<TR><TD>38</TD>
<TD>21</TD>
<TD>725</TD>
<TD>$2D500</TD>
</TR>
<TR><TD>39</TD>
<TD>21</TD>
<TD>746</TD>
<TD>$2EA00</TD>
</TR>
<TR><TD>40</TD>
<TD>21</TD>
<TD>767</TD>
<TD>$2FF00</TD>
</TR>
<TR><TD>41</TD>
<TD>21</TD>
<TD>788</TD>
<TD>$31400</TD>
</TR>
<TR><TD>42</TD>
<TD>21</TD>
<TD>809</TD>
<TD>$32900</TD>
</TR>
<TR><TD>43</TD>
<TD>21</TD>
<TD>830</TD>
<TD>$33E00</TD>
</TR>
<TR><TD>44</TD>
<TD>21</TD>
<TD>851</TD>
<TD>$35300</TD>
</TR>
<TR><TD>45</TD>
<TD>21</TD>
<TD>872</TD>
<TD>$36800</TD>
</TR>
<TR><TD>46</TD>
<TD>21</TD>
<TD>893</TD>
<TD>$37D00</TD>
</TR>
<TR><TD>47</TD>
<TD>21</TD>
<TD>914</TD>
<TD>$39200</TD>
</TR>
<TR><TD>48</TD>
<TD>21</TD>
<TD>935</TD>
<TD>$3A700</TD>
</TR>
<TR><TD>49</TD>
<TD>21</TD>
<TD>956</TD>
<TD>$3BC00</TD>
</TR>
<TR><TD>50</TD>
<TD>21</TD>
<TD>977</TD>
<TD>$3D100</TD>
</TR>
<TR><TD>51</TD>
<TD>21</TD>
<TD>998</TD>
<TD>$3E600</TD>
</TR>
<TR><TD>52</TD>
<TD>21</TD>
<TD>1019</TD>
<TD>$3FB00</TD>
</TR>
<TR><TD>53</TD>
<TD>19</TD>
<TD>1040</TD>
<TD>$41000</TD>
</TR>
<TR><TD>54</TD>
<TD>19</TD>
<TD>1059</TD>
<TD>$42300</TD>
</TR>
<TR><TD>55</TD>
<TD>19</TD>
<TD>1078</TD>
<TD>$43600</TD>
</TR>
<TR><TD>56</TD>
<TD>19</TD>
<TD>1097</TD>
<TD>$44900</TD>
</TR>
<TR><TD>57</TD>
<TD>19</TD>
<TD>1116</TD>
<TD>$45C00</TD>
</TR>
<TR><TD>58</TD>
<TD>19</TD>
<TD>1135</TD>
<TD>$46F00</TD>
</TR>
<TR><TD>59</TD>
<TD>19</TD>
<TD>1154</TD>
<TD>$48200</TD>
</TR>
<TR><TD>60</TD>
<TD>18</TD>
<TD>1173</TD>
<TD>$49500</TD>
</TR>
<TR><TD>61</TD>
<TD>18</TD>
<TD>1191</TD>
<TD>$4A700</TD>
</TR>
<TR><TD>62</TD>
<TD>18</TD>
<TD>1209</TD>
<TD>$4B900</TD>
</TR>
<TR><TD>63</TD>
<TD>18</TD>
<TD>1227</TD>
<TD>$4CB00</TD>
</TR>
<TR><TD>64</TD>
<TD>18</TD>
<TD>1245</TD>
<TD>$4DD00</TD>
</TR>
<TR><TD>65</TD>
<TD>18</TD>
<TD>1263</TD>
<TD>$4EF00</TD>
</TR>
<TR><TD>66</TD>
<TD>17</TD>
<TD>1281</TD>
<TD>$50100</TD>
</TR>
<TR><TD>67</TD>
<TD>17</TD>
<TD>1298</TD>
<TD>$51200</TD>
</TR>
<TR><TD>68</TD>
<TD>17</TD>
<TD>1315</TD>
<TD>$52300</TD>
</TR>
<TR><TD>69</TD>
<TD>17</TD>
<TD>1332</TD>
<TD>$53400</TD>
</TR>
<TR><TD>70</TD>
<TD>17</TD>
<TD>1349</TD>
<TD>$54500</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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:
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$1F</TD>
<TD>First directory entry</TD>
</TR>
<TR><TD>$20-$3F</TD>
<TD>Second dir entry</TD>
</TR>
<TR><TD>$40-$5F</TD>
<TD>Third dir entry</TD>
</TR>
<TR><TD>$60-$7F</TD>
<TD>Fourth dir entry</TD>
</TR>
<TR><TD>$80-$9F</TD>
<TD>Fifth dir entry</TD>
</TR>
<TR><TD>$A0-$BF</TD>
<TD>Sixth dir entry</TD>
</TR>
<TR><TD>$C0-$DF</TD>
<TD>Seventh dir entry</TD>
</TR>
<TR><TD>$E0-$FF</TD>
<TD>Eighth dir entry</TD>
</TR></TABLE>
<P>
This is a breakdown of a standard directory entry:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>Track/Sector location of next directory sector ($00/$FF if its the last sector)</TD>
</TR>
<TR><TD>$02</TD>
<TD>File type</TD>
</TR>
<TR><TD>$03-$04</TD>
<TD>Track/sector location of first sector of file</TD>
</TR>
<TR><TD>$05-$14</TD>
<TD>16 character filename (in PETASCII, padded with $A0)</TD>
</TR>
<TR><TD>$15-$16</TD>
<TD>Track/Sector location of first side-sector block (REL file only)</TD>
</TR>
<TR><TD>$17</TD>
<TD>REL file record length (REL file only, max. value 254)</TD>
</TR>
<TR><TD>$18-$1D</TD>
<TD>Unused (except with GEOS disks)</TD>
</TR>
<TR><TD>$1E-$1F</TD>
<TD>File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is &#60;= #sectors * 254</TD>
</TR></TABLE>
<P>
The file type field is used as follows:
</P>
<TABLE BORDER>
<TR><TD><B>Bits</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0-3</TD>
<TD>The actual file type</TD>
</TR>
<TR><TD>4</TD>
<TD>Unused</TD>
</TR>
<TR><TD>5</TD>
<TD>Used only during SAVE-@ replacement</TD>
</TR>
<TR><TD>6</TD>
<TD>Locked flag (Set produces "&#62;" locked files)</TD>
</TR>
<TR><TD>7</TD>
<TD>Closed flag (Not set produces "*", or "splat" files)</TD>
</TR></TABLE>
<P>
The actual file type can be one of the following:
</P>
<TABLE BORDER>
<TR><TD><B>Binary</B></TD>
<TD><B>Decimal</B></TD>
<TD><B>File type</B></TD>
</TR>
<TR><TD>0000</TD>
<TD>0</TD>
<TD>DEL</TD>
</TR>
<TR><TD>0001</TD>
<TD>1</TD>
<TD>SEQ</TD>
</TR>
<TR><TD>0010</TD>
<TD>2</TD>
<TD>PRG</TD>
</TR>
<TR><TD>0011</TD>
<TD>3</TD>
<TD>USR</TD>
</TR>
<TR><TD>0100</TD>
<TD>4</TD>
<TD>REL</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC285" HREF="vice_toc.html#TOC285">15.6.1 Non-Standard &#38; Long Directories</A></H3>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC286" HREF="vice_toc.html#TOC286">15.6.2 Bam layout The BAM is somewhat different as it now has to</A></H3>
<P>
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...
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>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)</TD>
</TR>
<TR><TD>$02</TD>
<TD>Disk DOS version type (see note below) $41 ('A') = 1541</TD>
</TR>
<TR><TD>$03</TD>
<TD>Double-sided flag $00 - Single sided disk $80 - Double sided disk</TD>
</TR>
<TR><TD>$04-8F</TD>
<TD>BAM entries for each track, in groups of four bytes per track, starting on track 1.</TD>
</TR>
<TR><TD>$90-$9F</TD>
<TD>Disk Name (padded with $A0)</TD>
</TR>
<TR><TD>$A0-$A1</TD>
<TD>Filled with $A0</TD>
</TR>
<TR><TD>$A2-$A3</TD>
<TD>Disk ID</TD>
</TR>
<TR><TD>$A4</TD>
<TD>Usually $A0</TD>
</TR>
<TR><TD>$A5-$A6</TD>
<TD>DOS type, usually "2A"</TD>
</TR>
<TR><TD>$A7-$AA</TD>
<TD>Filled with $A0</TD>
</TR>
<TR><TD>$AB-$DC</TD>
<TD>Not used ($00's)</TD>
</TR>
<TR><TD>$DD-$FF</TD>
<TD>Free sector count for tracks 36-70 (1 byte/track).</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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:
</P>
<PRE>
FF=11111111, F9=11111001, 17=00010111
</PRE>
<P>
In order to make any sense from the binary notation, flip the
bits around.
</P>
<PRE>
111111 11112222
01234567 89012345 67890123
--------------------------
11111111 10011111 11101000
^ ^
sector 0 sector 20
</PRE>
<P>
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.
</P>
<P>
In order to complete the BAM, we must check 53/0.
</P>
<PRE>
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
</PRE>
<P>
Each track from 36-70 has 3 byte entries, starting at
address $00.
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H2><A NAME="SEC287" HREF="vice_toc.html#TOC287">15.7 The D81 disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
The track range and offsets into the D81 files are as follows:
</P>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>#Sect</B></TD>
<TD><B>#SectorsIn</B></TD>
<TD><B>D81 Offset</B></TD>
</TR>
<TR><TD>1</TD>
<TD>40</TD>
<TD>0</TD>
<TD>$00000</TD>
</TR>
<TR><TD>2</TD>
<TD>40</TD>
<TD>40</TD>
<TD>$02800</TD>
</TR>
<TR><TD>3</TD>
<TD>40</TD>
<TD>80</TD>
<TD>$05000</TD>
</TR>
<TR><TD>4</TD>
<TD>40</TD>
<TD>120</TD>
<TD>$07800</TD>
</TR>
<TR><TD>5</TD>
<TD>40</TD>
<TD>160</TD>
<TD>$0A000</TD>
</TR>
<TR><TD>6</TD>
<TD>40</TD>
<TD>200</TD>
<TD>$0C800</TD>
</TR>
<TR><TD>7</TD>
<TD>40</TD>
<TD>240</TD>
<TD>$0F000</TD>
</TR>
<TR><TD>8</TD>
<TD>40</TD>
<TD>280</TD>
<TD>$11800</TD>
</TR>
<TR><TD>9</TD>
<TD>40</TD>
<TD>320</TD>
<TD>$14000</TD>
</TR>
<TR><TD>10</TD>
<TD>40</TD>
<TD>360</TD>
<TD>$16800</TD>
</TR>
<TR><TD>11</TD>
<TD>40</TD>
<TD>400</TD>
<TD>$19000</TD>
</TR>
<TR><TD>12</TD>
<TD>40</TD>
<TD>440</TD>
<TD>$1B800</TD>
</TR>
<TR><TD>13</TD>
<TD>40</TD>
<TD>480</TD>
<TD>$1E000</TD>
</TR>
<TR><TD>14</TD>
<TD>40</TD>
<TD>520</TD>
<TD>$20800</TD>
</TR>
<TR><TD>15</TD>
<TD>40</TD>
<TD>560</TD>
<TD>$23000</TD>
</TR>
<TR><TD>16</TD>
<TD>40</TD>
<TD>600</TD>
<TD>$25800</TD>
</TR>
<TR><TD>17</TD>
<TD>40</TD>
<TD>640</TD>
<TD>$28000</TD>
</TR>
<TR><TD>18</TD>
<TD>40</TD>
<TD>680</TD>
<TD>$2A800</TD>
</TR>
<TR><TD>19</TD>
<TD>40</TD>
<TD>720</TD>
<TD>$2D000</TD>
</TR>
<TR><TD>20</TD>
<TD>40</TD>
<TD>760</TD>
<TD>$2F800</TD>
</TR>
<TR><TD>21</TD>
<TD>40</TD>
<TD>800</TD>
<TD>$32000</TD>
</TR>
<TR><TD>22</TD>
<TD>40</TD>
<TD>840</TD>
<TD>$34800</TD>
</TR>
<TR><TD>23</TD>
<TD>40</TD>
<TD>880</TD>
<TD>$37000</TD>
</TR>
<TR><TD>24</TD>
<TD>40</TD>
<TD>920</TD>
<TD>$39800</TD>
</TR>
<TR><TD>25</TD>
<TD>40</TD>
<TD>960</TD>
<TD>$3C000</TD>
</TR>
<TR><TD>26</TD>
<TD>40</TD>
<TD>1000</TD>
<TD>$3E800</TD>
</TR>
<TR><TD>27</TD>
<TD>40</TD>
<TD>1040</TD>
<TD>$41000</TD>
</TR>
<TR><TD>28</TD>
<TD>40</TD>
<TD>1080</TD>
<TD>$43800</TD>
</TR>
<TR><TD>29</TD>
<TD>40</TD>
<TD>1120</TD>
<TD>$46000</TD>
</TR>
<TR><TD>30</TD>
<TD>40</TD>
<TD>1160</TD>
<TD>$48800</TD>
</TR>
<TR><TD>31</TD>
<TD>40</TD>
<TD>1200</TD>
<TD>$4B000</TD>
</TR>
<TR><TD>32</TD>
<TD>40</TD>
<TD>1240</TD>
<TD>$4D800</TD>
</TR>
<TR><TD>33</TD>
<TD>40</TD>
<TD>1280</TD>
<TD>$50000</TD>
</TR>
<TR><TD>34</TD>
<TD>40</TD>
<TD>1320</TD>
<TD>$52800</TD>
</TR>
<TR><TD>35</TD>
<TD>40</TD>
<TD>1360</TD>
<TD>$55000</TD>
</TR>
<TR><TD>36</TD>
<TD>40</TD>
<TD>1400</TD>
<TD>$57800</TD>
</TR>
<TR><TD>37</TD>
<TD>40</TD>
<TD>1440</TD>
<TD>$5A000</TD>
</TR>
<TR><TD>38</TD>
<TD>40</TD>
<TD>1480</TD>
<TD>$5C800</TD>
</TR>
<TR><TD>39</TD>
<TD>40</TD>
<TD>1520</TD>
<TD>$5F000</TD>
</TR>
<TR><TD>40</TD>
<TD>40</TD>
<TD>1560</TD>
<TD>$61800</TD>
</TR>
<TR><TD>41</TD>
<TD>40</TD>
<TD>1600</TD>
<TD>$64000</TD>
</TR>
<TR><TD>42</TD>
<TD>40</TD>
<TD>1640</TD>
<TD>$66800</TD>
</TR>
<TR><TD>43</TD>
<TD>40</TD>
<TD>1680</TD>
<TD>$69000</TD>
</TR>
<TR><TD>44</TD>
<TD>40</TD>
<TD>1720</TD>
<TD>$6B800</TD>
</TR>
<TR><TD>45</TD>
<TD>40</TD>
<TD>1760</TD>
<TD>$6E000</TD>
</TR>
<TR><TD>46</TD>
<TD>40</TD>
<TD>1800</TD>
<TD>$70800</TD>
</TR>
<TR><TD>47</TD>
<TD>40</TD>
<TD>1840</TD>
<TD>$73000</TD>
</TR>
<TR><TD>48</TD>
<TD>40</TD>
<TD>1880</TD>
<TD>$75800</TD>
</TR>
<TR><TD>49</TD>
<TD>40</TD>
<TD>1920</TD>
<TD>$78000</TD>
</TR>
<TR><TD>50</TD>
<TD>40</TD>
<TD>1960</TD>
<TD>$7A800</TD>
</TR>
<TR><TD>51</TD>
<TD>40</TD>
<TD>2000</TD>
<TD>$7D000</TD>
</TR>
<TR><TD>52</TD>
<TD>40</TD>
<TD>2040</TD>
<TD>$7F800</TD>
</TR>
<TR><TD>53</TD>
<TD>40</TD>
<TD>2080</TD>
<TD>$82000</TD>
</TR>
<TR><TD>54</TD>
<TD>40</TD>
<TD>2120</TD>
<TD>$84800</TD>
</TR>
<TR><TD>55</TD>
<TD>40</TD>
<TD>2160</TD>
<TD>$87000</TD>
</TR>
<TR><TD>56</TD>
<TD>40</TD>
<TD>2200</TD>
<TD>$89800</TD>
</TR>
<TR><TD>57</TD>
<TD>40</TD>
<TD>2240</TD>
<TD>$8C000</TD>
</TR>
<TR><TD>58</TD>
<TD>40</TD>
<TD>2280</TD>
<TD>$8E800</TD>
</TR>
<TR><TD>59</TD>
<TD>40</TD>
<TD>2320</TD>
<TD>$91000</TD>
</TR>
<TR><TD>60</TD>
<TD>40</TD>
<TD>2360</TD>
<TD>$93800</TD>
</TR>
<TR><TD>61</TD>
<TD>40</TD>
<TD>2400</TD>
<TD>$96000</TD>
</TR>
<TR><TD>62</TD>
<TD>40</TD>
<TD>2440</TD>
<TD>$98800</TD>
</TR>
<TR><TD>63</TD>
<TD>40</TD>
<TD>2480</TD>
<TD>$9B000</TD>
</TR>
<TR><TD>64</TD>
<TD>40</TD>
<TD>2520</TD>
<TD>$9D800</TD>
</TR>
<TR><TD>65</TD>
<TD>40</TD>
<TD>2560</TD>
<TD>$A0000</TD>
</TR>
<TR><TD>66</TD>
<TD>40</TD>
<TD>2600</TD>
<TD>$A2800</TD>
</TR>
<TR><TD>67</TD>
<TD>40</TD>
<TD>2640</TD>
<TD>$A5000</TD>
</TR>
<TR><TD>68</TD>
<TD>40</TD>
<TD>2680</TD>
<TD>$A7800</TD>
</TR>
<TR><TD>69</TD>
<TD>40</TD>
<TD>2720</TD>
<TD>$AA000</TD>
</TR>
<TR><TD>70</TD>
<TD>40</TD>
<TD>2760</TD>
<TD>$AC800</TD>
</TR>
<TR><TD>71</TD>
<TD>40</TD>
<TD>2800</TD>
<TD>$AF000</TD>
</TR>
<TR><TD>72</TD>
<TD>40</TD>
<TD>2840</TD>
<TD>$B1800</TD>
</TR>
<TR><TD>73</TD>
<TD>40</TD>
<TD>2880</TD>
<TD>$B4000</TD>
</TR>
<TR><TD>74</TD>
<TD>40</TD>
<TD>2920</TD>
<TD>$B6800</TD>
</TR>
<TR><TD>75</TD>
<TD>40</TD>
<TD>2960</TD>
<TD>$B9000</TD>
</TR>
<TR><TD>76</TD>
<TD>40</TD>
<TD>3000</TD>
<TD>$BB800</TD>
</TR>
<TR><TD>77</TD>
<TD>40</TD>
<TD>3040</TD>
<TD>$BE000</TD>
</TR>
<TR><TD>78</TD>
<TD>40</TD>
<TD>3080</TD>
<TD>$C0800</TD>
</TR>
<TR><TD>79</TD>
<TD>40</TD>
<TD>3120</TD>
<TD>$C3000</TD>
</TR>
<TR><TD>80</TD>
<TD>40</TD>
<TD>3160</TD>
<TD>$C5800</TD>
</TR></TABLE>
<P>
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).
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>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)</TD>
</TR>
<TR><TD>$02</TD>
<TD>Disk DOS version type (see note below) $44 ('D')=1581</TD>
</TR>
<TR><TD>$03</TD>
<TD>$00</TD>
</TR>
<TR><TD>$04-$13</TD>
<TD>16 character Disk Name (padded with $A0)</TD>
</TR>
<TR><TD>$14-$15</TD>
<TD>$A0</TD>
</TR>
<TR><TD>$16-$17</TD>
<TD>Disk ID</TD>
</TR>
<TR><TD>$18</TD>
<TD>$A0</TD>
</TR>
<TR><TD>$19</TD>
<TD>DOS Version ("3")</TD>
</TR>
<TR><TD>$1A</TD>
<TD>Disk version ("D")</TD>
</TR>
<TR><TD>$1B-$1C</TD>
<TD>$A0</TD>
</TR>
<TR><TD>$1D-$FF</TD>
<TD>Unused (usually $00)</TD>
</TR></TABLE>
<P>
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)
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$AB-$AC</TD>
<TD>Border sector (GEOS only, else set to $00)</TD>
</TR>
<TR><TD>$AD-$BC</TD>
<TD>GEOS ID string ("geos FORMAT V1.x" GEOS only, else $00)</TD>
</TR>
<TR><TD>$BD-$FF</TD>
<TD>Unused (usually $00)</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
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:
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$1F</TD>
<TD>First directory entry</TD>
</TR>
<TR><TD>$20-$3F</TD>
<TD>Second dir entry</TD>
</TR>
<TR><TD>$40-$5F</TD>
<TD>Third dir entry</TD>
</TR>
<TR><TD>$60-$7F</TD>
<TD>Fourth dir entry</TD>
</TR>
<TR><TD>$80-$9F</TD>
<TD>Fifth dir entry</TD>
</TR>
<TR><TD>$A0-$BF</TD>
<TD>Sixth dir entry</TD>
</TR>
<TR><TD>$C0-$DF</TD>
<TD>Seventh dir entry</TD>
</TR>
<TR><TD>$E0-$FF</TD>
<TD>Eighth dir entry</TD>
</TR></TABLE>
<P>
This is a breakdown of a standard directory entry:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>Track/Sector location of next directory sector</TD>
</TR>
<TR><TD>$02</TD>
<TD>File type</TD>
</TR>
<TR><TD>$03-$04</TD>
<TD>Track/sector location of first sector of file or partition</TD>
</TR>
<TR><TD>$05-$14</TD>
<TD>16 character filename (in PETASCII, padded with $A0)</TD>
</TR>
<TR><TD>$15-$16</TD>
<TD>Track/Sector location of first SUPER SIDE SECTOR block (REL file only)</TD>
</TR>
<TR><TD>$17</TD>
<TD>REL file record length (REL file only)</TD>
</TR>
<TR><TD>$18-$1B</TD>
<TD>Unused (except with GEOS disks)</TD>
</TR>
<TR><TD>$1C-$1D</TD>
<TD>(Used during an SAVE or OPEN, holds the new t/s link)</TD>
</TR>
<TR><TD>$1E-$1F</TD>
<TD>File or partition size in sectors, low/high byte order ($1E+$1F*256). The approx. file size in bytes is &#60;= #sectors * 254</TD>
</TR></TABLE>
<P>
The file type field is used as follows:
</P>
<TABLE BORDER>
<TR><TD><B>Bits</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0-3</TD>
<TD>The actual file type</TD>
</TR>
<TR><TD>4</TD>
<TD>Unused</TD>
</TR>
<TR><TD>5</TD>
<TD>Used only during SAVE-@ replacement</TD>
</TR>
<TR><TD>6</TD>
<TD>Locked flag (Set produces "&#62;" locked files)</TD>
</TR>
<TR><TD>7</TD>
<TD>Closed flag (Not set produces "*", or "splat" files)</TD>
</TR></TABLE>
<P>
The actual file type can be one of the following:
</P>
<TABLE BORDER>
<TR><TD><B>Binary</B></TD>
<TD><B>Decimal</B></TD>
<TD><B>File type</B></TD>
</TR>
<TR><TD>0000</TD>
<TD>0</TD>
<TD>DEL</TD>
</TR>
<TR><TD>0001</TD>
<TD>1</TD>
<TD>SEQ</TD>
</TR>
<TR><TD>0010</TD>
<TD>2</TD>
<TD>PRG</TD>
</TR>
<TR><TD>0011</TD>
<TD>3</TD>
<TD>USR</TD>
</TR>
<TR><TD>0100</TD>
<TD>4</TD>
<TD>REL</TD>
</TR>
<TR><TD>0101</TD>
<TD>5</TD>
<TD>CBM (partition or sub-directory)</TD>
</TR></TABLE>
<P>
Values 6-15 are illegal, but if used will produce very strange results.
</P>
<H3><A NAME="SEC288" HREF="vice_toc.html#TOC288">15.7.1 Non-Standard &#38; Long Directories</A></H3>
<P>
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.
</P>
<H3><A NAME="SEC289" HREF="vice_toc.html#TOC289">15.7.2 BAM layout</A></H3>
<P>
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.
</P>
<PRE>
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
</PRE>
<PRE>
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)
</PRE>
<P>
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.
</P>
<PRE>
F0: .. .. .. .. .. .. .. .. .. .. 24 F0 FF 2D FF FE
</PRE>
<P>
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:
</P>
<PRE>
F0=11110000, FF=11111111, 2D=00101101, FF=11111111, FE=11111110
</PRE>
<P>
In order to make any sense from the binary notation, flip the
bits around.
</P>
<PRE>
111111 11112222 22222233 33333333
Sector 01234567 89012345 67890123 45678901 23456789
-------------------------- -------- --------
00001111 11111111 10110100 11111111 01111111
</PRE>
<P>
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.
</P>
<P>
The second BAM (for side 1) contains the entries for tracks
41-80.
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<H3><A NAME="SEC290" HREF="vice_toc.html#TOC290">15.7.3 REL files The REL filetype requires some extra explaining.</A></H3>
<P>
It was designed to make access to data *anywhere* on the disk
very fast. Take a look at this directory entry...
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<P>
Here is a dump of the beginning of the SUPER SIDE SECTOR...
</P>
<PRE>
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
</PRE>
<PRE>
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)
</PRE>
<P>
The side sector layout is the same as the D64/1571.
</P>
<PRE>
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
</PRE>
<PRE>
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.
</PRE>
<H3><A NAME="SEC291" HREF="vice_toc.html#TOC291">15.7.4 1581 Partitions and Sub-directories</A></H3>
<P>
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.
</P>
<P>
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.
</P>
<P>
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".
</P>
<P>
In order to use a partition as a sub-directory, it must adhere
to the following four rules:
</P>
<PRE>
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).
</PRE>
<P>
This is a dump of a sub-directory entry:
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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...
</P>
<PRE>
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
</PRE>
<P>
The master BAM shows the entry for this partition on track 5...
</P>
<PRE>
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
^^^^^^^^^^^^^^^^^
</PRE>
<P>
The breakdown of the BAM shows the allocation for this track,
with sectors 1-10 allocated, as it should be.
</P>
<PRE>
10000000 00011111 11111111 11111111 11111111
^ ^ ^ ^ ^
0 10 20 30 39
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC292" HREF="vice_toc.html#TOC292">15.7.5 AUTO-BOOT LOADER</A></H3>
<P>
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.
</P>
<P>
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.
</P>
<PRE>
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
</PRE>
<H2><A NAME="SEC293" HREF="vice_toc.html#TOC293">15.8 The D80 disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
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.
</P>
<TABLE BORDER>
<TR><TD><B>Track Range</B></TD>
<TD><B>Sectors/track</B></TD>
<TD><B># Sectors</B></TD>
</TR>
<TR><TD>1-39</TD>
<TD>29</TD>
<TD>1131</TD>
</TR>
<TR><TD>40-53</TD>
<TD>27</TD>
<TD>378</TD>
</TR>
<TR><TD>54-64</TD>
<TD>25</TD>
<TD>275</TD>
</TR>
<TR><TD>65-77</TD>
<TD>23</TD>
<TD>299</TD>
</TR></TABLE>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>#Sect</B></TD>
<TD><B>#SectorsIn</B></TD>
<TD><B>D8x Offset</B></TD>
</TR>
<TR><TD>1</TD>
<TD>29</TD>
<TD>0</TD>
<TD>$00000</TD>
</TR>
<TR><TD>2</TD>
<TD>29</TD>
<TD>29</TD>
<TD>$01D00</TD>
</TR>
<TR><TD>3</TD>
<TD>29</TD>
<TD>58</TD>
<TD>$03A00</TD>
</TR>
<TR><TD>4</TD>
<TD>29</TD>
<TD>87</TD>
<TD>$05700</TD>
</TR>
<TR><TD>5</TD>
<TD>29</TD>
<TD>116</TD>
<TD>$07400</TD>
</TR>
<TR><TD>6</TD>
<TD>29</TD>
<TD>145</TD>
<TD>$09100</TD>
</TR>
<TR><TD>7</TD>
<TD>29</TD>
<TD>174</TD>
<TD>$0AE00</TD>
</TR>
<TR><TD>8</TD>
<TD>29</TD>
<TD>203</TD>
<TD>$0CB00</TD>
</TR>
<TR><TD>9</TD>
<TD>29</TD>
<TD>232</TD>
<TD>$0E800</TD>
</TR>
<TR><TD>10</TD>
<TD>29</TD>
<TD>261</TD>
<TD>$10500</TD>
</TR>
<TR><TD>11</TD>
<TD>29</TD>
<TD>290</TD>
<TD>$12200</TD>
</TR>
<TR><TD>12</TD>
<TD>29</TD>
<TD>319</TD>
<TD>$13F00</TD>
</TR>
<TR><TD>13</TD>
<TD>29</TD>
<TD>348</TD>
<TD>$15C00</TD>
</TR>
<TR><TD>14</TD>
<TD>29</TD>
<TD>377</TD>
<TD>$17900</TD>
</TR>
<TR><TD>15</TD>
<TD>29</TD>
<TD>406</TD>
<TD>$19600</TD>
</TR>
<TR><TD>16</TD>
<TD>29</TD>
<TD>435</TD>
<TD>$1B300</TD>
</TR>
<TR><TD>17</TD>
<TD>29</TD>
<TD>464</TD>
<TD>$1D000</TD>
</TR>
<TR><TD>18</TD>
<TD>29</TD>
<TD>493</TD>
<TD>$1ED00</TD>
</TR>
<TR><TD>19</TD>
<TD>29</TD>
<TD>522</TD>
<TD>$20A00</TD>
</TR>
<TR><TD>20</TD>
<TD>29</TD>
<TD>551</TD>
<TD>$22700</TD>
</TR>
<TR><TD>21</TD>
<TD>29</TD>
<TD>580</TD>
<TD>$24400</TD>
</TR>
<TR><TD>22</TD>
<TD>29</TD>
<TD>609</TD>
<TD>$26100</TD>
</TR>
<TR><TD>23</TD>
<TD>29</TD>
<TD>638</TD>
<TD>$27E00</TD>
</TR>
<TR><TD>24</TD>
<TD>29</TD>
<TD>667</TD>
<TD>$29B00</TD>
</TR>
<TR><TD>25</TD>
<TD>29</TD>
<TD>696</TD>
<TD>$2B800</TD>
</TR>
<TR><TD>26</TD>
<TD>29</TD>
<TD>725</TD>
<TD>$2D500</TD>
</TR>
<TR><TD>27</TD>
<TD>29</TD>
<TD>754</TD>
<TD>$2F200</TD>
</TR>
<TR><TD>28</TD>
<TD>29</TD>
<TD>783</TD>
<TD>$30F00</TD>
</TR>
<TR><TD>29</TD>
<TD>29</TD>
<TD>812</TD>
<TD>$32C00</TD>
</TR>
<TR><TD>30</TD>
<TD>29</TD>
<TD>841</TD>
<TD>$34900</TD>
</TR>
<TR><TD>31</TD>
<TD>29</TD>
<TD>870</TD>
<TD>$36600</TD>
</TR>
<TR><TD>32</TD>
<TD>29</TD>
<TD>899</TD>
<TD>$38300</TD>
</TR>
<TR><TD>33</TD>
<TD>29</TD>
<TD>928</TD>
<TD>$3A000</TD>
</TR>
<TR><TD>34</TD>
<TD>29</TD>
<TD>957</TD>
<TD>$3BD00</TD>
</TR>
<TR><TD>35</TD>
<TD>29</TD>
<TD>986</TD>
<TD>$3DA00</TD>
</TR>
<TR><TD>36</TD>
<TD>29</TD>
<TD>1015</TD>
<TD>$3F700</TD>
</TR>
<TR><TD>37</TD>
<TD>29</TD>
<TD>1044</TD>
<TD>$41400</TD>
</TR>
<TR><TD>38</TD>
<TD>29</TD>
<TD>1073</TD>
<TD>$43100</TD>
</TR>
<TR><TD>39</TD>
<TD>29</TD>
<TD>1102</TD>
<TD>$44E00</TD>
</TR>
<TR><TD>40</TD>
<TD>27</TD>
<TD>1131</TD>
<TD>$46B00</TD>
</TR>
<TR><TD>41</TD>
<TD>27</TD>
<TD>1158</TD>
<TD>$48600</TD>
</TR>
<TR><TD>42</TD>
<TD>27</TD>
<TD>1185</TD>
<TD>$4A100</TD>
</TR>
<TR><TD>43</TD>
<TD>27</TD>
<TD>1212</TD>
<TD>$4BC00</TD>
</TR>
<TR><TD>44</TD>
<TD>27</TD>
<TD>1239</TD>
<TD>$4D700</TD>
</TR>
<TR><TD>45</TD>
<TD>27</TD>
<TD>1266</TD>
<TD>$4F200</TD>
</TR>
<TR><TD>46</TD>
<TD>27</TD>
<TD>1293</TD>
<TD>$50D00</TD>
</TR>
<TR><TD>47</TD>
<TD>27</TD>
<TD>1320</TD>
<TD>$52800</TD>
</TR>
<TR><TD>48</TD>
<TD>27</TD>
<TD>1347</TD>
<TD>$54300</TD>
</TR>
<TR><TD>49</TD>
<TD>27</TD>
<TD>1374</TD>
<TD>$55E00</TD>
</TR>
<TR><TD>50</TD>
<TD>27</TD>
<TD>1401</TD>
<TD>$57900</TD>
</TR>
<TR><TD>51</TD>
<TD>27</TD>
<TD>1428</TD>
<TD>$59400</TD>
</TR>
<TR><TD>52</TD>
<TD>27</TD>
<TD>1455</TD>
<TD>$5AF00</TD>
</TR>
<TR><TD>53</TD>
<TD>27</TD>
<TD>1482</TD>
<TD>$5CA00</TD>
</TR>
<TR><TD>54</TD>
<TD>25</TD>
<TD>1509</TD>
<TD>$5E500</TD>
</TR>
<TR><TD>55</TD>
<TD>25</TD>
<TD>1534</TD>
<TD>$5FE00</TD>
</TR>
<TR><TD>56</TD>
<TD>25</TD>
<TD>1559</TD>
<TD>$61700</TD>
</TR>
<TR><TD>57</TD>
<TD>25</TD>
<TD>1584</TD>
<TD>$63000</TD>
</TR>
<TR><TD>58</TD>
<TD>25</TD>
<TD>1609</TD>
<TD>$64900</TD>
</TR>
<TR><TD>59</TD>
<TD>25</TD>
<TD>1634</TD>
<TD>$66200</TD>
</TR>
<TR><TD>60</TD>
<TD>25</TD>
<TD>1659</TD>
<TD>$67B00</TD>
</TR>
<TR><TD>61</TD>
<TD>25</TD>
<TD>1684</TD>
<TD>$69400</TD>
</TR>
<TR><TD>62</TD>
<TD>25</TD>
<TD>1709</TD>
<TD>$6AD00</TD>
</TR>
<TR><TD>63</TD>
<TD>25</TD>
<TD>1734</TD>
<TD>$6C600</TD>
</TR>
<TR><TD>64</TD>
<TD>25</TD>
<TD>1759</TD>
<TD>$6DF00</TD>
</TR>
<TR><TD>65</TD>
<TD>23</TD>
<TD>1784</TD>
<TD>$6F800</TD>
</TR>
<TR><TD>66</TD>
<TD>23</TD>
<TD>1807</TD>
<TD>$70F00</TD>
</TR>
<TR><TD>67</TD>
<TD>23</TD>
<TD>1830</TD>
<TD>$72600</TD>
</TR>
<TR><TD>68</TD>
<TD>23</TD>
<TD>1853</TD>
<TD>$73D00</TD>
</TR>
<TR><TD>69</TD>
<TD>23</TD>
<TD>1876</TD>
<TD>$75400</TD>
</TR>
<TR><TD>70</TD>
<TD>23</TD>
<TD>1899</TD>
<TD>$76B00</TD>
</TR>
<TR><TD>71</TD>
<TD>23</TD>
<TD>1922</TD>
<TD>$78200</TD>
</TR>
<TR><TD>72</TD>
<TD>23</TD>
<TD>1945</TD>
<TD>$79900</TD>
</TR>
<TR><TD>73</TD>
<TD>23</TD>
<TD>1968</TD>
<TD>$7B000</TD>
</TR>
<TR><TD>74</TD>
<TD>23</TD>
<TD>1991</TD>
<TD>$7C700</TD>
</TR>
<TR><TD>75</TD>
<TD>23</TD>
<TD>2014</TD>
<TD>$7DE00</TD>
</TR>
<TR><TD>76</TD>
<TD>23</TD>
<TD>2037</TD>
<TD>$7F500</TD>
</TR>
<TR><TD>77</TD>
<TD>23</TD>
<TD>2060</TD>
<TD>$80C00</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Below is a dump of the header sector 39/0:
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to first BAM sector (38/0)</TD>
</TR>
<TR><TD>$02</TD>
<TD>$43 'C' is for DOS format version</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04-$05</TD>
<TD>Unused</TD>
</TR>
<TR><TD>$06-$16</TD>
<TD>Disk name, padded with 0xA0 ("sample d80")</TD>
</TR>
<TR><TD>$17</TD>
<TD>0xA0</TD>
</TR>
<TR><TD>$18-$19</TD>
<TD>Disk ID bytes "er"</TD>
</TR>
<TR><TD>$1A</TD>
<TD>0xA0</TD>
</TR>
<TR><TD>$1B-$1C</TD>
<TD>DOS version bytes "2C"</TD>
</TR>
<TR><TD>$1D-$20</TD>
<TD>0xA0</TD>
</TR>
<TR><TD>$21-$FF</TD>
<TD>Unused</TD>
</TR></TABLE>
<P>
Below is a dump of the first directory sector, 39/1
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<P>
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:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$1F</TD>
<TD>First directory entry</TD>
</TR>
<TR><TD>$20-$3F</TD>
<TD>Second dir entry</TD>
</TR>
<TR><TD>$40-$5F</TD>
<TD>Third dir entry</TD>
</TR>
<TR><TD>$60-$7F</TD>
<TD>Fourth dir entry</TD>
</TR>
<TR><TD>$80-$9F</TD>
<TD>Fifth dir entry</TD>
</TR>
<TR><TD>$A0-$BF</TD>
<TD>Sixth dir entry</TD>
</TR>
<TR><TD>$C0-$DF</TD>
<TD>Seventh dir entry</TD>
</TR>
<TR><TD>$E0-$FF</TD>
<TD>Eighth dir entry</TD>
</TR></TABLE>
<P>
This is a breakdown of a standard directory entry:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector)</TD>
</TR>
<TR><TD>$02</TD>
<TD>File type</TD>
</TR>
<TR><TD>$03-$04</TD>
<TD>Track/sector location of first sector of file</TD>
</TR>
<TR><TD>$05-$14</TD>
<TD>16 character filename (in PETASCII, padded with $A0)</TD>
</TR>
<TR><TD>$15-$16</TD>
<TD>Track/Sector location of first side-sector block (REL file only)</TD>
</TR>
<TR><TD>$17</TD>
<TD>REL file record length (REL file only, max. value 254)</TD>
</TR>
<TR><TD>$18-$1D</TD>
<TD>Unused</TD>
</TR>
<TR><TD>$1E-$1F</TD>
<TD>File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is &#60;= #sectors * 254</TD>
</TR></TABLE>
<P>
The file type field is used as follows:
</P>
<TABLE BORDER>
<TR><TD><B>Bits</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0-3</TD>
<TD>The actual file type</TD>
</TR>
<TR><TD>4</TD>
<TD>Unused</TD>
</TR>
<TR><TD>5</TD>
<TD>Used only during SAVE-@ replacement</TD>
</TR>
<TR><TD>6</TD>
<TD>Locked flag (Set produces "&#62;" locked files)</TD>
</TR>
<TR><TD>7</TD>
<TD>Closed flag (Not set produces "*", or "splat" files)</TD>
</TR></TABLE>
<P>
The actual file type can be one of the following:
</P>
<TABLE BORDER>
<TR><TD><B>Binary</B></TD>
<TD><B>Decimal</B></TD>
<TD><B>File type</B></TD>
</TR>
<TR><TD>0000</TD>
<TD>0</TD>
<TD>DEL</TD>
</TR>
<TR><TD>0001</TD>
<TD>1</TD>
<TD>SEQ</TD>
</TR>
<TR><TD>0010</TD>
<TD>2</TD>
<TD>PRG</TD>
</TR>
<TR><TD>0011</TD>
<TD>3</TD>
<TD>USR</TD>
</TR>
<TR><TD>0100</TD>
<TD>4</TD>
<TD>REL</TD>
</TR></TABLE>
<P>
Values 5-15 are illegal, but if used will produce very strange results.
</P>
<H3><A NAME="SEC294" HREF="vice_toc.html#TOC294">15.8.1 Non-Standard &#38; Long Directories</A></H3>
<P>
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.
</P>
<H3><A NAME="SEC295" HREF="vice_toc.html#TOC295">15.8.2 BAM layout</A></H3>
<P>
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.
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to second BAM sector (38/3)</TD>
</TR>
<TR><TD>$02</TD>
<TD>DOS version byte (0x43='C')</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04</TD>
<TD>Lowest track covered by this BAM (0x01=1)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Highest+1 track covered by this BAM (0x33=51)</TD>
</TR>
<TR><TD>$06-$0A</TD>
<TD>BAM for track 1. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track.</TD>
</TR>
<TR><TD>$0B-$0F</TD>
<TD>BAM for track 2</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$FB-$FF</TD>
<TD>BAM for track 50</TD>
</TR></TABLE>
<P>
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:
</P>
<PRE>
FF=11111111, FF=11111111, FF=11111111, 1F=00011111
</PRE>
<P>
In order to make any sense from the binary notation, flip the
bits around.
</P>
<PRE>
111111 11112222 222222
01234567 89012345 67890123 456789...
-------------------------- ---------
11111111 11111111 11111111 11111000
^ ^
sector 0 sector 28
</PRE>
<P>
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.
</P>
<P>
Second BAM block 38/3.
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to second BAM sector (39/1)</TD>
</TR>
<TR><TD>$02</TD>
<TD>DOS version byte (0x43='C')</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04</TD>
<TD>Lowest track covered by this BAM (0x33=51)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Highest+1 track covered by this BAM (0x43=78)</TD>
</TR>
<TR><TD>$06-$0A</TD>
<TD>BAM for track 51. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track.</TD>
</TR>
<TR><TD>$0B-$0F</TD>
<TD>BAM for track 52</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$88-$8C</TD>
<TD>BAM for track 77</TD>
</TR>
<TR><TD>$8D-$FF</TD>
<TD>Not used</TD>
</TR></TABLE>
<H2><A NAME="SEC296" HREF="vice_toc.html#TOC296">15.9 The D82 disk image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
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.
</P>
<TABLE BORDER>
<TR><TD><B>Track Range</B></TD>
<TD><B>Sectors/track</B></TD>
<TD><B># Sectors</B></TD>
</TR>
<TR><TD>1-39</TD>
<TD>29</TD>
<TD>1131</TD>
</TR>
<TR><TD>40-53</TD>
<TD>27</TD>
<TD>378</TD>
</TR>
<TR><TD>55-64</TD>
<TD>25</TD>
<TD>275</TD>
</TR>
<TR><TD>65-77</TD>
<TD>23</TD>
<TD>299</TD>
</TR>
<TR><TD>78-116</TD>
<TD>29</TD>
<TD>1131</TD>
</TR>
<TR><TD>117-130</TD>
<TD>27</TD>
<TD>378</TD>
</TR>
<TR><TD>131-141</TD>
<TD>25</TD>
<TD>275</TD>
</TR>
<TR><TD>142-154</TD>
<TD>23</TD>
<TD>299</TD>
</TR></TABLE>
<TABLE BORDER>
<TR><TD><B>Track</B></TD>
<TD><B>#Sect</B></TD>
<TD><B>#SectorsIn</B></TD>
<TD><B>D82 Offset</B></TD>
</TR>
<TR><TD>1</TD>
<TD>29</TD>
<TD>0</TD>
<TD>$000000</TD>
</TR>
<TR><TD>2</TD>
<TD>29</TD>
<TD>29</TD>
<TD>$001D00</TD>
</TR>
<TR><TD>3</TD>
<TD>29</TD>
<TD>58</TD>
<TD>$003A00</TD>
</TR>
<TR><TD>4</TD>
<TD>29</TD>
<TD>87</TD>
<TD>$005700</TD>
</TR>
<TR><TD>5</TD>
<TD>29</TD>
<TD>116</TD>
<TD>$007400</TD>
</TR>
<TR><TD>6</TD>
<TD>29</TD>
<TD>145</TD>
<TD>$009100</TD>
</TR>
<TR><TD>7</TD>
<TD>29</TD>
<TD>174</TD>
<TD>$00AE00</TD>
</TR>
<TR><TD>8</TD>
<TD>29</TD>
<TD>203</TD>
<TD>$00CB00</TD>
</TR>
<TR><TD>9</TD>
<TD>29</TD>
<TD>232</TD>
<TD>$00E800</TD>
</TR>
<TR><TD>10</TD>
<TD>29</TD>
<TD>261</TD>
<TD>$010500</TD>
</TR>
<TR><TD>11</TD>
<TD>29</TD>
<TD>290</TD>
<TD>$012200</TD>
</TR>
<TR><TD>12</TD>
<TD>29</TD>
<TD>319</TD>
<TD>$013F00</TD>
</TR>
<TR><TD>13</TD>
<TD>29</TD>
<TD>348</TD>
<TD>$015C00</TD>
</TR>
<TR><TD>14</TD>
<TD>29</TD>
<TD>377</TD>
<TD>$017900</TD>
</TR>
<TR><TD>15</TD>
<TD>29</TD>
<TD>406</TD>
<TD>$019600</TD>
</TR>
<TR><TD>16</TD>
<TD>29</TD>
<TD>435</TD>
<TD>$01B300</TD>
</TR>
<TR><TD>17</TD>
<TD>29</TD>
<TD>464</TD>
<TD>$01D000</TD>
</TR>
<TR><TD>18</TD>
<TD>29</TD>
<TD>493</TD>
<TD>$01ED00</TD>
</TR>
<TR><TD>19</TD>
<TD>29</TD>
<TD>522</TD>
<TD>$020A00</TD>
</TR>
<TR><TD>20</TD>
<TD>29</TD>
<TD>551</TD>
<TD>$022700</TD>
</TR>
<TR><TD>21</TD>
<TD>29</TD>
<TD>580</TD>
<TD>$024400</TD>
</TR>
<TR><TD>22</TD>
<TD>29</TD>
<TD>609</TD>
<TD>$026100</TD>
</TR>
<TR><TD>23</TD>
<TD>29</TD>
<TD>638</TD>
<TD>$027E00</TD>
</TR>
<TR><TD>24</TD>
<TD>29</TD>
<TD>667</TD>
<TD>$029B00</TD>
</TR>
<TR><TD>25</TD>
<TD>29</TD>
<TD>696</TD>
<TD>$02B800</TD>
</TR>
<TR><TD>26</TD>
<TD>29</TD>
<TD>725</TD>
<TD>$02D500</TD>
</TR>
<TR><TD>27</TD>
<TD>29</TD>
<TD>754</TD>
<TD>$02F200</TD>
</TR>
<TR><TD>28</TD>
<TD>29</TD>
<TD>783</TD>
<TD>$030F00</TD>
</TR>
<TR><TD>29</TD>
<TD>29</TD>
<TD>812</TD>
<TD>$032C00</TD>
</TR>
<TR><TD>30</TD>
<TD>29</TD>
<TD>841</TD>
<TD>$034900</TD>
</TR>
<TR><TD>31</TD>
<TD>29</TD>
<TD>870</TD>
<TD>$036600</TD>
</TR>
<TR><TD>32</TD>
<TD>29</TD>
<TD>899</TD>
<TD>$038300</TD>
</TR>
<TR><TD>33</TD>
<TD>29</TD>
<TD>928</TD>
<TD>$03A000</TD>
</TR>
<TR><TD>34</TD>
<TD>29</TD>
<TD>957</TD>
<TD>$03BD00</TD>
</TR>
<TR><TD>35</TD>
<TD>29</TD>
<TD>986</TD>
<TD>$03DA00</TD>
</TR>
<TR><TD>36</TD>
<TD>29</TD>
<TD>1015</TD>
<TD>$03F700</TD>
</TR>
<TR><TD>37</TD>
<TD>29</TD>
<TD>1044</TD>
<TD>$041400</TD>
</TR>
<TR><TD>38</TD>
<TD>29</TD>
<TD>1073</TD>
<TD>$043100</TD>
</TR>
<TR><TD>39</TD>
<TD>29</TD>
<TD>1102</TD>
<TD>$044E00</TD>
</TR>
<TR><TD>40</TD>
<TD>27</TD>
<TD>1131</TD>
<TD>$046B00</TD>
</TR>
<TR><TD>41</TD>
<TD>27</TD>
<TD>1158</TD>
<TD>$048600</TD>
</TR>
<TR><TD>42</TD>
<TD>27</TD>
<TD>1185</TD>
<TD>$04A100</TD>
</TR>
<TR><TD>43</TD>
<TD>27</TD>
<TD>1212</TD>
<TD>$04BC00</TD>
</TR>
<TR><TD>44</TD>
<TD>27</TD>
<TD>1239</TD>
<TD>$04D700</TD>
</TR>
<TR><TD>45</TD>
<TD>27</TD>
<TD>1266</TD>
<TD>$04F200</TD>
</TR>
<TR><TD>46</TD>
<TD>27</TD>
<TD>1293</TD>
<TD>$050D00</TD>
</TR>
<TR><TD>47</TD>
<TD>27</TD>
<TD>1320</TD>
<TD>$052800</TD>
</TR>
<TR><TD>48</TD>
<TD>27</TD>
<TD>1347</TD>
<TD>$054300</TD>
</TR>
<TR><TD>49</TD>
<TD>27</TD>
<TD>1374</TD>
<TD>$055E00</TD>
</TR>
<TR><TD>50</TD>
<TD>27</TD>
<TD>1401</TD>
<TD>$057900</TD>
</TR>
<TR><TD>51</TD>
<TD>27</TD>
<TD>1428</TD>
<TD>$059400</TD>
</TR>
<TR><TD>52</TD>
<TD>27</TD>
<TD>1455</TD>
<TD>$05AF00</TD>
</TR>
<TR><TD>53</TD>
<TD>27</TD>
<TD>1482</TD>
<TD>$05CA00</TD>
</TR>
<TR><TD>54</TD>
<TD>25</TD>
<TD>1509</TD>
<TD>$05E500</TD>
</TR>
<TR><TD>55</TD>
<TD>25</TD>
<TD>1534</TD>
<TD>$05FE00</TD>
</TR>
<TR><TD>56</TD>
<TD>25</TD>
<TD>1559</TD>
<TD>$061700</TD>
</TR>
<TR><TD>57</TD>
<TD>25</TD>
<TD>1584</TD>
<TD>$063000</TD>
</TR>
<TR><TD>58</TD>
<TD>25</TD>
<TD>1609</TD>
<TD>$064900</TD>
</TR>
<TR><TD>59</TD>
<TD>25</TD>
<TD>1634</TD>
<TD>$066200</TD>
</TR>
<TR><TD>60</TD>
<TD>25</TD>
<TD>1659</TD>
<TD>$067B00</TD>
</TR>
<TR><TD>61</TD>
<TD>25</TD>
<TD>1684</TD>
<TD>$069400</TD>
</TR>
<TR><TD>62</TD>
<TD>25</TD>
<TD>1709</TD>
<TD>$06AD00</TD>
</TR>
<TR><TD>63</TD>
<TD>25</TD>
<TD>1734</TD>
<TD>$06C600</TD>
</TR>
<TR><TD>64</TD>
<TD>25</TD>
<TD>1759</TD>
<TD>$06DF00</TD>
</TR>
<TR><TD>65</TD>
<TD>23</TD>
<TD>1784</TD>
<TD>$06F800</TD>
</TR>
<TR><TD>66</TD>
<TD>23</TD>
<TD>1807</TD>
<TD>$070F00</TD>
</TR>
<TR><TD>67</TD>
<TD>23</TD>
<TD>1830</TD>
<TD>$072600</TD>
</TR>
<TR><TD>68</TD>
<TD>23</TD>
<TD>1853</TD>
<TD>$073D00</TD>
</TR>
<TR><TD>69</TD>
<TD>23</TD>
<TD>1876</TD>
<TD>$075400</TD>
</TR>
<TR><TD>70</TD>
<TD>23</TD>
<TD>1899</TD>
<TD>$076B00</TD>
</TR>
<TR><TD>71</TD>
<TD>23</TD>
<TD>1922</TD>
<TD>$078200</TD>
</TR>
<TR><TD>72</TD>
<TD>23</TD>
<TD>1945</TD>
<TD>$079900</TD>
</TR>
<TR><TD>73</TD>
<TD>23</TD>
<TD>1968</TD>
<TD>$07B000</TD>
</TR>
<TR><TD>74</TD>
<TD>23</TD>
<TD>1991</TD>
<TD>$07C700</TD>
</TR>
<TR><TD>75</TD>
<TD>23</TD>
<TD>2014</TD>
<TD>$07DE00</TD>
</TR>
<TR><TD>76</TD>
<TD>23</TD>
<TD>2037</TD>
<TD>$07F500</TD>
</TR>
<TR><TD>77</TD>
<TD>23</TD>
<TD>2060</TD>
<TD>$080C00</TD>
</TR>
<TR><TD>78</TD>
<TD>29</TD>
<TD>2083</TD>
<TD>$082300</TD>
</TR>
<TR><TD>79</TD>
<TD>29</TD>
<TD>2112</TD>
<TD>$084000</TD>
</TR>
<TR><TD>80</TD>
<TD>29</TD>
<TD>2141</TD>
<TD>$085D00</TD>
</TR>
<TR><TD>81</TD>
<TD>29</TD>
<TD>2170</TD>
<TD>$087A00</TD>
</TR>
<TR><TD>82</TD>
<TD>29</TD>
<TD>2199</TD>
<TD>$089700</TD>
</TR>
<TR><TD>83</TD>
<TD>29</TD>
<TD>2228</TD>
<TD>$08B400</TD>
</TR>
<TR><TD>84</TD>
<TD>29</TD>
<TD>2257</TD>
<TD>$08D100</TD>
</TR>
<TR><TD>85</TD>
<TD>29</TD>
<TD>2286</TD>
<TD>$08EE00</TD>
</TR>
<TR><TD>86</TD>
<TD>29</TD>
<TD>2315</TD>
<TD>$090600</TD>
</TR>
<TR><TD>87</TD>
<TD>29</TD>
<TD>2344</TD>
<TD>$092800</TD>
</TR>
<TR><TD>88</TD>
<TD>29</TD>
<TD>2373</TD>
<TD>$094500</TD>
</TR>
<TR><TD>89</TD>
<TD>29</TD>
<TD>2402</TD>
<TD>$096200</TD>
</TR>
<TR><TD>90</TD>
<TD>29</TD>
<TD>2431</TD>
<TD>$097F00</TD>
</TR>
<TR><TD>91</TD>
<TD>29</TD>
<TD>2460</TD>
<TD>$099C00</TD>
</TR>
<TR><TD>92</TD>
<TD>29</TD>
<TD>2489</TD>
<TD>$09B900</TD>
</TR>
<TR><TD>93</TD>
<TD>29</TD>
<TD>2518</TD>
<TD>$09D600</TD>
</TR>
<TR><TD>94</TD>
<TD>29</TD>
<TD>2547</TD>
<TD>$09F300</TD>
</TR>
<TR><TD>95</TD>
<TD>29</TD>
<TD>2576</TD>
<TD>$0A1000</TD>
</TR>
<TR><TD>96</TD>
<TD>29</TD>
<TD>2605</TD>
<TD>$0A2D00</TD>
</TR>
<TR><TD>97</TD>
<TD>29</TD>
<TD>2634</TD>
<TD>$0A4A00</TD>
</TR>
<TR><TD>98</TD>
<TD>29</TD>
<TD>2663</TD>
<TD>$0A6700</TD>
</TR>
<TR><TD>99</TD>
<TD>29</TD>
<TD>2692</TD>
<TD>$0A8400</TD>
</TR>
<TR><TD>100</TD>
<TD>29</TD>
<TD>2721</TD>
<TD>$0AA100</TD>
</TR>
<TR><TD>101</TD>
<TD>29</TD>
<TD>2750</TD>
<TD>$0ABE00</TD>
</TR>
<TR><TD>102</TD>
<TD>29</TD>
<TD>2779</TD>
<TD>$0ADB00</TD>
</TR>
<TR><TD>103</TD>
<TD>29</TD>
<TD>2808</TD>
<TD>$0AF800</TD>
</TR>
<TR><TD>104</TD>
<TD>29</TD>
<TD>2837</TD>
<TD>$0B1500</TD>
</TR>
<TR><TD>105</TD>
<TD>29</TD>
<TD>2866</TD>
<TD>$0B3200</TD>
</TR>
<TR><TD>106</TD>
<TD>29</TD>
<TD>2895</TD>
<TD>$0B4F00</TD>
</TR>
<TR><TD>107</TD>
<TD>29</TD>
<TD>2924</TD>
<TD>$0B6C00</TD>
</TR>
<TR><TD>108</TD>
<TD>29</TD>
<TD>2953</TD>
<TD>$0B8900</TD>
</TR>
<TR><TD>109</TD>
<TD>29</TD>
<TD>2982</TD>
<TD>$0BA600</TD>
</TR>
<TR><TD>110</TD>
<TD>29</TD>
<TD>3011</TD>
<TD>$0BC300</TD>
</TR>
<TR><TD>111</TD>
<TD>29</TD>
<TD>3040</TD>
<TD>$0BE000</TD>
</TR>
<TR><TD>112</TD>
<TD>29</TD>
<TD>3069</TD>
<TD>$0BFD00</TD>
</TR>
<TR><TD>113</TD>
<TD>29</TD>
<TD>3098</TD>
<TD>$0C1A00</TD>
</TR>
<TR><TD>114</TD>
<TD>29</TD>
<TD>3137</TD>
<TD>$0C3700</TD>
</TR>
<TR><TD>115</TD>
<TD>29</TD>
<TD>3156</TD>
<TD>$0C5400</TD>
</TR>
<TR><TD>116</TD>
<TD>29</TD>
<TD>3185</TD>
<TD>$0C7100</TD>
</TR>
<TR><TD>117</TD>
<TD>27</TD>
<TD>3214</TD>
<TD>$0C8E00</TD>
</TR>
<TR><TD>118</TD>
<TD>27</TD>
<TD>3241</TD>
<TD>$0CA900</TD>
</TR>
<TR><TD>119</TD>
<TD>27</TD>
<TD>3268</TD>
<TD>$0CC400</TD>
</TR>
<TR><TD>120</TD>
<TD>27</TD>
<TD>3295</TD>
<TD>$0CDF00</TD>
</TR>
<TR><TD>121</TD>
<TD>27</TD>
<TD>3322</TD>
<TD>$0CFA00</TD>
</TR>
<TR><TD>122</TD>
<TD>27</TD>
<TD>3349</TD>
<TD>$0D1500</TD>
</TR>
<TR><TD>123</TD>
<TD>27</TD>
<TD>3376</TD>
<TD>$0D3000</TD>
</TR>
<TR><TD>124</TD>
<TD>27</TD>
<TD>3403</TD>
<TD>$0D4B00</TD>
</TR>
<TR><TD>125</TD>
<TD>27</TD>
<TD>3430</TD>
<TD>$0D6600</TD>
</TR>
<TR><TD>126</TD>
<TD>27</TD>
<TD>3457</TD>
<TD>$0D8100</TD>
</TR>
<TR><TD>127</TD>
<TD>27</TD>
<TD>3484</TD>
<TD>$0D9C00</TD>
</TR>
<TR><TD>128</TD>
<TD>27</TD>
<TD>3511</TD>
<TD>$0DB700</TD>
</TR>
<TR><TD>129</TD>
<TD>27</TD>
<TD>3538</TD>
<TD>$0DD200</TD>
</TR>
<TR><TD>130</TD>
<TD>27</TD>
<TD>3565</TD>
<TD>$0DED00</TD>
</TR>
<TR><TD>131</TD>
<TD>25</TD>
<TD>3592</TD>
<TD>$0E0800</TD>
</TR>
<TR><TD>132</TD>
<TD>25</TD>
<TD>3617</TD>
<TD>$0E2100</TD>
</TR>
<TR><TD>133</TD>
<TD>25</TD>
<TD>3642</TD>
<TD>$0E3A00</TD>
</TR>
<TR><TD>134</TD>
<TD>25</TD>
<TD>3667</TD>
<TD>$0E5300</TD>
</TR>
<TR><TD>135</TD>
<TD>25</TD>
<TD>3692</TD>
<TD>$0E6C00</TD>
</TR>
<TR><TD>136</TD>
<TD>25</TD>
<TD>3717</TD>
<TD>$0E8500</TD>
</TR>
<TR><TD>137</TD>
<TD>25</TD>
<TD>3742</TD>
<TD>$0E9E00</TD>
</TR>
<TR><TD>138</TD>
<TD>25</TD>
<TD>3767</TD>
<TD>$0EB700</TD>
</TR>
<TR><TD>139</TD>
<TD>25</TD>
<TD>3792</TD>
<TD>$0ED000</TD>
</TR>
<TR><TD>140</TD>
<TD>25</TD>
<TD>3817</TD>
<TD>$0EE900</TD>
</TR>
<TR><TD>141</TD>
<TD>25</TD>
<TD>3842</TD>
<TD>$0F0200</TD>
</TR>
<TR><TD>142</TD>
<TD>23</TD>
<TD>3867</TD>
<TD>$0F1B00</TD>
</TR>
<TR><TD>143</TD>
<TD>23</TD>
<TD>3890</TD>
<TD>$0F3200</TD>
</TR>
<TR><TD>144</TD>
<TD>23</TD>
<TD>3913</TD>
<TD>$0F4900</TD>
</TR>
<TR><TD>145</TD>
<TD>23</TD>
<TD>3936</TD>
<TD>$0F6000</TD>
</TR>
<TR><TD>146</TD>
<TD>23</TD>
<TD>3959</TD>
<TD>$0F7700</TD>
</TR>
<TR><TD>147</TD>
<TD>23</TD>
<TD>3982</TD>
<TD>$0F8E00</TD>
</TR>
<TR><TD>148</TD>
<TD>23</TD>
<TD>4005</TD>
<TD>$0FA500</TD>
</TR>
<TR><TD>149</TD>
<TD>23</TD>
<TD>4028</TD>
<TD>$0FBC00</TD>
</TR>
<TR><TD>150</TD>
<TD>23</TD>
<TD>4051</TD>
<TD>$0FD300</TD>
</TR>
<TR><TD>151</TD>
<TD>23</TD>
<TD>4074</TD>
<TD>$0FEA00</TD>
</TR>
<TR><TD>152</TD>
<TD>23</TD>
<TD>4097</TD>
<TD>$100100</TD>
</TR>
<TR><TD>153</TD>
<TD>23</TD>
<TD>4120</TD>
<TD>$101800</TD>
</TR>
<TR><TD>154</TD>
<TD>23</TD>
<TD>4143</TD>
<TD>$102F00</TD>
</TR></TABLE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<P>
Below is a dump of the header sector 39/0:
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to first BAM sector (38/0)</TD>
</TR>
<TR><TD>$02</TD>
<TD>$43 'C' is for DOS format version</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04-$05</TD>
<TD>Unused</TD>
</TR>
<TR><TD>$06-$16</TD>
<TD>Disk name, padded with 0xA0 ("sample d82")</TD>
</TR>
<TR><TD>$17</TD>
<TD>0xA0</TD>
</TR>
<TR><TD>$18-$19</TD>
<TD>Disk ID bytes "er"</TD>
</TR>
<TR><TD>$1A</TD>
<TD>0xA0</TD>
</TR>
<TR><TD>$1B-$1C</TD>
<TD>DOS version bytes "2C"</TD>
</TR>
<TR><TD>$1D-$20</TD>
<TD>0xA0</TD>
</TR>
<TR><TD>$21-$FF</TD>
<TD>Unused</TD>
</TR></TABLE>
<P>
Below is a dump of the first directory sector, 39/1
</P>
<PRE>
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
</PRE>
<P>
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.
</P>
<P>
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:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$1F</TD>
<TD>First directory entry</TD>
</TR>
<TR><TD>$20-$3F</TD>
<TD>Second dir entry</TD>
</TR>
<TR><TD>$40-$5F</TD>
<TD>Third dir entry</TD>
</TR>
<TR><TD>$60-$7F</TD>
<TD>Fourth dir entry</TD>
</TR>
<TR><TD>$80-$9F</TD>
<TD>Fifth dir entry</TD>
</TR>
<TR><TD>$A0-$BF</TD>
<TD>Sixth dir entry</TD>
</TR>
<TR><TD>$C0-$DF</TD>
<TD>Seventh dir entry</TD>
</TR>
<TR><TD>$E0-$FF</TD>
<TD>Eighth dir entry</TD>
</TR></TABLE>
<P>
This is a breakdown of a standard directory entry:
</P>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector)</TD>
</TR>
<TR><TD>$02</TD>
<TD>File type</TD>
</TR>
<TR><TD>$03-$04</TD>
<TD>Track/sector location of first sector of file</TD>
</TR>
<TR><TD>$05-$14</TD>
<TD>16 character filename (in PETASCII, padded with $A0)</TD>
</TR>
<TR><TD>$15-$16</TD>
<TD>Track/Sector location of first side-sector block (REL file only)</TD>
</TR>
<TR><TD>$17</TD>
<TD>REL file record length (REL file only, max. value 254)</TD>
</TR>
<TR><TD>$18-$1D</TD>
<TD>Unused</TD>
</TR>
<TR><TD>$1E-$1F</TD>
<TD>File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is &#60;= #sectors * 254</TD>
</TR></TABLE>
<P>
The file type field is used as follows:
</P>
<TABLE BORDER>
<TR><TD><B>Bits</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>0-3</TD>
<TD>The actual file type</TD>
</TR>
<TR><TD>4</TD>
<TD>Unused</TD>
</TR>
<TR><TD>5</TD>
<TD>Used only during SAVE-@ replacement</TD>
</TR>
<TR><TD>6</TD>
<TD>Locked flag (Set produces "&#62;" locked files)</TD>
</TR>
<TR><TD>7</TD>
<TD>Closed flag (Not set produces "*", or "splat" files)</TD>
</TR></TABLE>
<P>
The actual file type can be one of the following:
</P>
<TABLE BORDER>
<TR><TD><B>Binary</B></TD>
<TD><B>Decimal</B></TD>
<TD><B>File type</B></TD>
</TR>
<TR><TD>0000</TD>
<TD>0</TD>
<TD>DEL</TD>
</TR>
<TR><TD>0001</TD>
<TD>1</TD>
<TD>SEQ</TD>
</TR>
<TR><TD>0010</TD>
<TD>2</TD>
<TD>PRG</TD>
</TR>
<TR><TD>0011</TD>
<TD>3</TD>
<TD>USR</TD>
</TR>
<TR><TD>0100</TD>
<TD>4</TD>
<TD>REL</TD>
</TR></TABLE>
<P>
Values 5-15 are illegal, but if used will produce very strange results.
</P>
<H3><A NAME="SEC297" HREF="vice_toc.html#TOC297">15.9.1 Non-Standard &#38; Long Directories</A></H3>
<P>
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.
</P>
<H3><A NAME="SEC298" HREF="vice_toc.html#TOC298">15.9.2 BAM layout</A></H3>
<P>
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.
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to second BAM sector (38/3)</TD>
</TR>
<TR><TD>$02</TD>
<TD>DOS version byte (0x43='C')</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04</TD>
<TD>Lowest track covered by this BAM (0x01=1)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Highest+1 track covered by this BAM (0x33=51)</TD>
</TR>
<TR><TD>$06-$0A</TD>
<TD>BAM for track 1. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track.</TD>
</TR>
<TR><TD>$0B-$0F</TD>
<TD>BAM for track 2</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$FB-$FF</TD>
<TD>BAM for track 50</TD>
</TR></TABLE>
<P>
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:
</P>
<PRE>
FF=11111111, FF=11111111, FF=11111111, 1F=00011111
</PRE>
<P>
In order to make any sense from the binary notation, flip the
bits around.
</P>
<PRE>
111111 11112222 222222
01234567 89012345 67890123 456789...
-------------------------- ---------
11111111 11111111 11111111 11111000
^ ^
sector 0 sector 28
</PRE>
<P>
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.
</P>
<P>
Second BAM block 38/3
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to third BAM sector (38/6)</TD>
</TR>
<TR><TD>$02</TD>
<TD>DOS version byte (0x43='C')</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04</TD>
<TD>Lowest track covered by this BAM (0x33=51)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Highest+1 track covered by this BAM (0x65=101)</TD>
</TR>
<TR><TD>$06-$0A</TD>
<TD>BAM for track 51. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track.</TD>
</TR>
<TR><TD>$0B-$0F</TD>
<TD>BAM for track 52</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$FB-$FF</TD>
<TD>BAM for track 100</TD>
</TR></TABLE>
<P>
Third BAM block 38/6
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to fourth BAM sector (38/9)</TD>
</TR>
<TR><TD>$02</TD>
<TD>DOS version byte (0x43='C')</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04</TD>
<TD>Lowest track covered by this BAM (0x65=101)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Highest+1 track covered by this BAM (0x97=151)</TD>
</TR>
<TR><TD>$06-$0A</TD>
<TD>BAM for track 101. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track.</TD>
</TR>
<TR><TD>$0B-$0F</TD>
<TD>BAM for track 102</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$FB-$FF</TD>
<TD>BAM for track 150</TD>
</TR></TABLE>
<P>
Fourth BAM block 38/9
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$01</TD>
<TD>T/S pointer to first directory sector (39/1)</TD>
</TR>
<TR><TD>$02</TD>
<TD>DOS version byte (0x43='C')</TD>
</TR>
<TR><TD>$03</TD>
<TD>Reserved</TD>
</TR>
<TR><TD>$04</TD>
<TD>Lowest track covered by this BAM (0x97=151)</TD>
</TR>
<TR><TD>$05</TD>
<TD>Highest+1 track covered by this BAM (0x9B=155)</TD>
</TR>
<TR><TD>$06-$0A</TD>
<TD>BAM for track 151. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track.</TD>
</TR>
<TR><TD>$0B-$0F</TD>
<TD>BAM for track 152</TD>
</TR>
<TR><TD>...</TD>
<TD>...</TD>
</TR>
<TR><TD>$15-$19</TD>
<TD>BAM for track 154</TD>
</TR>
<TR><TD>$1A-$FF</TD>
<TD>Not used</TD>
</TR></TABLE>
<H2><A NAME="SEC299" HREF="vice_toc.html#TOC299">15.10 The P00 image format</A></H2>
<P>
(This section was contributed by Peter Schepers and slightly edited by
Marco van den Heuvel.)
</P>
<P>
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.
</P>
<P>
This is a dump of a Pxx file (PRG)...
</P>
<PRE>
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
</PRE>
<TABLE BORDER>
<TR><TD><B>Bytes</B></TD>
<TD><B>Description</B></TD>
</TR>
<TR><TD>$00-$06</TD>
<TD>ASCII string "C64File"</TD>
</TR>
<TR><TD>$07</TD>
<TD>Always $00</TD>
</TR>
<TR><TD>$08-$17</TD>
<TD>Filename in PETASCII, padded with $00 (not $A0, like a D64)</TD>
</TR>
<TR><TD>$18</TD>
<TD>Always $00</TD>
</TR>
<TR><TD>$19</TD>
<TD>REL file record size ($00 if not a REL file)</TD>
</TR>
<TR><TD>$1A-??</TD>
<TD>Program data</TD>
</TR></TABLE>
<P>
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).
</P>
<P>
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.
</P>
<H2><A NAME="SEC300" HREF="vice_toc.html#TOC300">15.11 The CRT cartridge image format</A></H2>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC301" HREF="vice_toc.html#TOC301">15.11.1 Header contents</A></H3>
<P>
Here is a dump of a sample 8K normal cartridge, "Attack Of The Mutant
Camels"...
</P>
<PRE>
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 .<2E>?....80....?<3F>?
0060: 4C B3 9B A9 08 85 5A 88 D0 FD C6 5A D0 F9 60 D0 L<><4C>.?<3F>Z<EFBFBD>...Z.?`.
</PRE>
<PRE>
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.
</PRE>
<P>
(*Note: Ocean type 1 includes Navy Seals, Robocop 2 &#38; 3, Shadow of the
Beast, Toki, Terminator 2 and more)
</P>
<P>
(**Note: Dinamic includes Narco Police and more)
</P>
<H3><A NAME="SEC302" HREF="vice_toc.html#TOC302">15.11.2 CHIP Contents</A></H3>
<P>
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.
</P>
<PRE>
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 .<2E>?....80....?<3F>?
0020: 4C B3 9B A9 08 85 5A 88 D0 FD C6 5A D0 F9 60 D0 L<><4C>.?<3F>Z<EFBFBD>...Z.?`.
0030: F2 60 A9 04 85 49 A9 00 85 48 A2 00 A5 48 9D 40 ?`.?<3F>I.?<3F>H.?<3F>H<EFBFBD>@
0040: 03 A5 49 9D 60 03 A5 48 18 69 28 85 48 A5 49 69 ?<3F>I<EFBFBD>`?<3F>H?i(<28>H<EFBFBD>Ii
0050: 00 85 49 E8 E0 18 D0 E4 60 A6 03 A4 02 BD 40 03 ?<3F>I???.?`?????@?
</PRE>
<PRE>
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
</PRE>
<P>
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.
</P>
<P>
Legend:
L - ROML (low)
H - ROMH (high)
G - GAME
E - EXROM
</P>
<PRE>
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
</PRE>
<P>
(*) Internal memory does not respond to write accesses in these areas
</P>
<P>
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.
</P>
<PRE>
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 ----
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H3><A NAME="SEC303" HREF="vice_toc.html#TOC303">15.11.3 Cartridge Specifics</A></H3>
<H4><A NAME="SEC304" HREF="vice_toc.html#TOC304">15.11.3.1 0 - Normal cartridge</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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 .<2E>?....80....?<3F>?
</PRE>
<P>
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.
</P>
<P>
Normal cartridge
</P>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>4Kb (ULTIMAX mode)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$F000-F7FF</TD>
</TR></TABLE>
<PRE>
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 &#60;f..f&#60;???&#60;f~fff?
</PRE>
<P>
The third sample is a dump of "Adventure Creator", a 16Kb standard
cartridge.
</P>
<P>
Normal cartridge
</P>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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 ?.<2E>....80.?x.<2E>?.
</PRE>
<H4><A NAME="SEC305" HREF="vice_toc.html#TOC305">15.11.3.2 1 - Action Replay</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb (4 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF (all modules)</TD>
</TR></TABLE>
<PRE>
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
</PRE>
<P>
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:
</P>
<PRE>
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) &#38;
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
</PRE>
<P>
Additionally the RAM or ROM can be available through a window in the
I/O-2 range.
</P>
<H4><A NAME="SEC306" HREF="vice_toc.html#TOC306">15.11.3.3 2 - KCS Power Cartridge</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8K each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>module #1 - $8000-9FFF</TD>
module #2 - $A000-BFFF
</TR></TABLE>
<PRE>
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????????<3F>???
2060: 97 E3 16 A1 FF FF FF 20 13 A0 A5 01 09 01 85 01 <20>.?.?????<3F><>???<3F>?
</PRE>
<H4><A NAME="SEC307" HREF="vice_toc.html#TOC307">15.11.3.4 3 - Final Cartridge III</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb (4 banks of 16Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF (all modules)</TD>
</TR></TABLE>
<PRE>
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<4C>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 ???<3F>]<5D>a<EFBFBD><61><EFBFBD>.<2E>?<3F>3<EFBFBD>
...
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??.?..<2E>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 .??.<2E><>?.??<3F><>???.
</PRE>
<P>
A total of 64 kB of ROM memory is organized into four $4000 banks
located at $8000-$BFFF.
</P>
<P>
The banks are arranged in the following way:
</P>
<PRE>
Bank 0: BASIC, Monitor, Disk-Turbo
Bank 1: Notepad, BASIC (Menu Bar)
Bank 2: Desktop, Freezer/Print
Bank 3: Freezer, Compression
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
The registers are arranged in the following way:
</P>
<P>
One register at $DFFF:
</P>
<PRE>
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
</PRE>
<P>
1) if either the freezer button is pressed, or bit 6 is 0, then an NMI
is generated
</P>
<P>
2) if the freezer button is pressed, GAME is also forced low
</P>
<P>
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)
</P>
<H4><A NAME="SEC308" HREF="vice_toc.html#TOC308">15.11.3.5 4 - Simons' Basic</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>module #1 - $8000-9FFF</TD>
module #2 - $A000-BFFF
</TR></TABLE>
<PRE>
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<EFBFBD>...80ALR<EFBFBD>?,<2C>
...
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00 CHIP????????<3F>???
2060: 20 A4 A6 99 9E CB A0 05 A5 A8 91 20 A4 A6 99 A2 ???<3F><>.<2E>?<3F>?.???<3F>.
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H4><A NAME="SEC309" HREF="vice_toc.html#TOC309">15.11.3.6 5 - Ocean type 1</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb, 128Kb, 256Kb or 512Kb sizes (4, 16, 32 or 64 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>Banks 00-15 - $8000-9FFF</TD>
Banks 16-31 - $A000-BFFF (except Terminator 2)
</TR></TABLE>
<PRE>
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 ?.<2E><>...80L<EFBFBD><EFBFBD>Lv<EFBFBD>.
...
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<>???<3F>.???
...
20140: 43 48 49 50 00 00 20 10 00 00 00 10 A0 00 20 00 CHIP????????<3F>???
20150: 0A 9A 55 FF 9B 69 57 FE AA 65 96 FE 65 0F D6 D9 ?.U?<3F>iW.<2E>e<EFBFBD>.e?..
</PRE>
<P>
Here is a list of the known OCEAN cartridges:
</P>
<PRE>
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)
</PRE>
<P>
The 32Kb type of cart has 4 banks of 8Kb ($2000), banked in at
$8000-$9FFF.
</P>
<P>
The 128Kb type of cart has 16 banks of 8Kb ($2000), banked in at
$8000-$9FFF.
</P>
<P>
The 256Kb type of cart has 32 banks of 8Kb ($2000), 16 banked in at
$8000-$9FFF, and 16 banked in at $A000-$BFFF.
</P>
<P>
The 512Kb type of cart has 64 banks of 8Kb ($2000), banked in at
$8000-$9FFF.
</P>
<P>
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.
</P>
<H4><A NAME="SEC310" HREF="vice_toc.html#TOC310">15.11.3.7 6 - Expert Cartridge</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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 ????????????????
</PRE>
<H4><A NAME="SEC311" HREF="vice_toc.html#TOC311">15.11.3.8 7 - Fun Play, Power Play</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>128Kb (16 banks of 8Kb modules)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF (all modules)</TD>
</TR></TABLE>
<PRE>
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 ?.<2E>....80??<3F>??.?
...
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.?<3F>????<3F>??..?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<>?<3F>?'??.?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 <20>?A.<2E>???.????.??
</PRE>
<P>
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:
</P>
<PRE>
$00 -&#62; Bank 0
$08 -&#62; Bank 1
$10 -&#62; Bank 2
$18 -&#62; Bank 3
$20 -&#62; Bank 4
$28 -&#62; Bank 5
$30 -&#62; Bank 6
$38 -&#62; Bank 7
$01 -&#62; Bank 8
$09 -&#62; Bank 9
$11 -&#62; Bank 10
$19 -&#62; Bank 11
$21 -&#62; Bank 12
$29 -&#62; Bank 13
$31 -&#62; Bank 14
$39 -&#62; Bank 15
</PRE>
<P>
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).
</P>
<PRE>
Bit# 76543210
xx210xx3
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC312" HREF="vice_toc.html#TOC312">15.11.3.9 8 - Super Games</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb (4 banks of 16Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF (all modules)</TD>
</TR></TABLE>
<PRE>
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?..<2E>?<3F>.
...
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 .??..????<3F>??..?0
</PRE>
<P>
The Super Games cartridge uses 4 16Kb banks ($8000-$BFFF) of ROM
memory. Bank selecting is done by writing to $DF00.
</P>
<P>
$DF00 register is as follows:
</P>
<PRE>
bit meaning
--- -------
0 bank bit 0
1 bank bit 1
2 inverted GAME line
3 inverted EXROM line
4-7 unused
</PRE>
<H4><A NAME="SEC313" HREF="vice_toc.html#TOC313">15.11.3.10 9 - Atomic Power</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb (4 banks of 8Kb modules)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF (all modules)</TD>
</TR></TABLE>
<PRE>
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.<2E>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<EFBFBD>L0.L
</PRE>
<P>
This cart has 32Kb of ROM and 8Kb of RAM
</P>
<P>
Writing to I/O-1 will do the following:
</P>
<PRE>
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) &#38;
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
</PRE>
<P>
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.
</P>
<P>
The cart RAM or ROM is available through a window in the I/O-2 range.
</P>
<H4><A NAME="SEC314" HREF="vice_toc.html#TOC314">15.11.3.11 10 - Epyx Fastload</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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??<3F>L8?<3F>
</PRE>
<P>
The Epyx FastLoad cart uses a simple capacitor to toggle the ROM on
and off:
</P>
<P>
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.
</P>
<H4><A NAME="SEC315" HREF="vice_toc.html#TOC315">15.11.3.12 11 - Westermann Learning</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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 ?.<2E>....80.?<3F>?.?<3F>
</PRE>
<P>
Any read from the I/O-2 range will switch the cart off.
</P>
<H4><A NAME="SEC316" HREF="vice_toc.html#TOC316">15.11.3.13 12 - Rex Utility</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8K</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD>.?<3F>.?
</PRE>
<P>
Reading from $DF00-DFBF disables ROM, reading from $DFC0-DFFF enables
ROM (8k game config).
</P>
<H4><A NAME="SEC317" HREF="vice_toc.html#TOC317">15.11.3.14 13 - Final Cartridge I</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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 .<2E>^....80?<3F><>?-.X
</PRE>
<P>
Any access to I/O-1 turns cartridge ROM off. Any access to I/O-2 turns
cartridge ROM on.
</P>
<P>
The cart ROM is visible in I/O-1 and I/O-2.
</P>
<H4><A NAME="SEC318" HREF="vice_toc.html#TOC318">15.11.3.15 14 - Magic Formel</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb (8 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>Inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>Inactive (0)</TD>
</TR>
<TR><TD>Load Address</TD>
<TD>$E000-FFFF</TD>
</TR></TABLE>
<PRE>
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<46>??`<60>??`<60>??`<60>
...
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_?<3F>??`<60>??`<60>??`<60>
...
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<46>??`<60>??`<60>??`<60>
...
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<46>??`<60>??`<60>??`<60>
...
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<46>??`<60>??`<60>??`<60>
...
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<46>??`<60>??`<60>??`<60>
...
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<46>??`<60>??`<60>??`<60>
..
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<46>??`<60>??`<60>??`<60>
</PRE>
<H4><A NAME="SEC319" HREF="vice_toc.html#TOC319">15.11.3.16 15 - C64 Game System, System 3</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>512Kb (64 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF (all modules)</TD>
</TR></TABLE>
<PRE>
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<4C>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 ?..?<3F>?.<2E>?.<2E>?..?.
...
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<EFBFBD><52>.<2E>!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 .???<3F>.??.<2E>?.??@.
...
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
</PRE>
<P>
Here is a list of the known cartridges:
</P>
<PRE>
C64GS 4-in-1 (Commodore) (512 kB)
Last Ninja Remix (System 3) (512 kB)
Myth (System 3) (512 kB)
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H4><A NAME="SEC320" HREF="vice_toc.html#TOC320">15.11.3.17 16 - Warp Speed</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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????
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC321" HREF="vice_toc.html#TOC321">15.11.3.18 17 - Dinamic</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>128Kb (16 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF (all modules)</TD>
</TR></TABLE>
<PRE>
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 ?<3F>?<3F>??<3F>??<3F>??<3F>??<3F>
..
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 <20>????????<3F>??????
..
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
</PRE>
<P>
Here is a list of the known DINAMIC cartridges:
</P>
<PRE>
Narco Police (128 kB)
Satan (128 kB)
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<H4><A NAME="SEC322" HREF="vice_toc.html#TOC322">15.11.3.19 18 - Zaxxon, Super Zaxxon (SEGA)</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>20Kb (3 banks of different sizes)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-8FFF (mirrored in $9000-9FFF, module 0, chip U1)</TD>
$A000-BFFF (banked modules 1 and 2, chip U2)
</TR></TABLE>
<PRE>
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????????<3F>???
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????????<3F>???
003070: 65 A2 36 A3 E7 A3 CB A4 94 A5 86 A6 5E A7 35 A8 e.6<EFBFBD>?<3F>.?<3F><><EFBFBD>?^<5E>5?
</PRE>
<P>
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.
</P>
<P>
The CRT file includes three CHIP blocks:
<PRE>
a) bank = 0, load address = $8000, size = $1000
b) bank = 0, load address = $A000, size = $2000
c) bank = 1, load address = $A000, size = $2000
</PRE>
<H4><A NAME="SEC323" HREF="vice_toc.html#TOC323">15.11.3.20 19 - Magic Desk, Domark, HES Australia</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb, 64Kb or 128Kb sizes (4 to 16 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>(banks 00-15) - $8000-9FFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD>?.?<3F>.?
..
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 ?????<3F>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 ?<3F>.(N$,1)<29><>"?"<22>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 <20>?<3F>3,7,"2)?DEL?K
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
Here is a list of the known cartridges:
</P>
<PRE>
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)
</PRE>
<H4><A NAME="SEC324" HREF="vice_toc.html#TOC324">15.11.3.21 20 - Super Snapshot V5</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb (4 banks of 16Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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??<3F>????
...
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.?<3F>?.<2E>!
...
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.?<3F>j.?<3F>
...
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<EFBFBD>???<3F><>v
</PRE>
<P>
The first page of the currently selected ROM bank is mirrored in the
I/O-1 range when reading.
</P>
<P>
The control Register is the I/O-1 range when writing:
</P>
<PRE>
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
</PRE>
<H4><A NAME="SEC325" HREF="vice_toc.html#TOC325">15.11.3.22 21 - Comal-80</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb (4 banks of 16Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD>.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 <20>.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 <20>.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..
</PRE>
<P>
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:
</P>
<PRE>
$80 -&#62; Bank 0
$81 -&#62; Bank 1
$82 -&#62; Bank 2
$83 -&#62; Bank 3
</PRE>
<H4><A NAME="SEC326" HREF="vice_toc.html#TOC326">15.11.3.23 22 - Structured Basic</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<P>
No sample data/file available.
</P>
<P>
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.
</P>
<H4><A NAME="SEC327" HREF="vice_toc.html#TOC327">15.11.3.24 23 - Ross</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb or 32Kb sizes (1 or 2 banks of 16Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-BFFF</TD>
</TR></TABLE>
<PRE>
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<50>%???w?.??
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC328" HREF="vice_toc.html#TOC328">15.11.3.25 24 - Dela EP64</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb to 72kb sizes (1 to 9 banks of 8Kb each,</TD>
or 1 bank of 8Kb and 1 or 2 banks
of 32Kb each)
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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 ?<3F>^....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????
</PRE>
<P>
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.
</P>
<P>
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).
</P>
<PRE>
Bit# 76543210
xx10xx32
</PRE>
<P>
Any bank value below 4 or above 11 switches in the base bank (bank 0).
</P>
<P>
The bit values for each eprom bank are :
</P>
<PRE>
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
</PRE>
<P>
Setting bit 7 high will switch off EXROM.
</P>
<H4><A NAME="SEC329" HREF="vice_toc.html#TOC329">15.11.3.26 25 - Dela EP7x8</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb to 64kb sizes (1 to 8 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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.?..<2E>?
...
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 <20><><EFBFBD><EFBFBD>...80?<3F>Z0_?=
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
The bit values for each eprom bank is:
</P>
<PRE>
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)
</PRE>
<H4><A NAME="SEC330" HREF="vice_toc.html#TOC330">15.11.3.27 26 - Dela EP256</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb to 262kb sizes (1 to 33 banks of 8Kb each)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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 ?<3F>^....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.?<3F>?.?
...
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.?<3F>?.?.
...
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 .. ?.?<3F>...80..<2E>?.?.
...
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 <20><><EFBFBD><EFBFBD>...80?<3F>Z0_?=
</PRE>
<P>
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.
</P>
<P>
The bank selecting is done by writing to $DE00.
</P>
<P>
The values for the (extra) eprom banks are:
</P>
<PRE>
eprom banks 1- 8 : $38-3F
eprom banks 9-16 : $28-2F
eprom banks 17-24 : $18-1F
eprom banks 25-32 : $08-0F
</PRE>
<P>
Setting bit 7 high will switch off EXROM.
</P>
<H4><A NAME="SEC331" HREF="vice_toc.html#TOC331">15.11.3.28 27 - Rex EP256</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb to 262kb sizes (1 bank of 8Kb and 1 to 8 banks of either</TD>
8Kb, 16Kb or 32Kb)
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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?<3F>.?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 ?.?<3F>...80..<2E>?.?<3F>
...
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.?<3F>??<3F>
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
The possible values for bits 5 and 4 for the (extra) eprom banks are:
</P>
<PRE>
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
</PRE>
<P>
Reading from $DFC0 switches off the EXROM.
Reading from $DFE0 switches on the EXROM.
</P>
<H4><A NAME="SEC332" HREF="vice_toc.html#TOC332">15.11.3.29 28 - Mikro Assembler</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-9FFF</TD>
</TR></TABLE>
<PRE>
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.<2E>A
</PRE>
<P>
The $9E00-$9EFF range is mirrored at $DE00-$DEFF. The $9F00-$9FFF range
is mirrored at $DF00-$DFFF.
</P>
<H4><A NAME="SEC333" HREF="vice_toc.html#TOC333">15.11.3.30 29 - Final Cartridge Plus</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb (1 bank of 32Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$0000-$7FFF</TD>
</TR></TABLE>
<PRE>
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 ????????????????
</PRE>
<P>
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).
</P>
<H4><A NAME="SEC334" HREF="vice_toc.html#TOC334">15.11.3.31 30 - Action Replay 4</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb (4 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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.?<3F>?..?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<><4C>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<EFBFBD>L?.L
</PRE>
<P>
The control register is the I/O-1 range:
</P>
<PRE>
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
</PRE>
<P>
The first page of the currently banked ROM block can be read in the
I/O-2 range.
</P>
<H4><A NAME="SEC335" HREF="vice_toc.html#TOC335">15.11.3.32 31 - Stardos</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF (bank 0),</TD>
$E000-$FFFF (bank 1)
</TR></TABLE>
<PRE>
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 ?.<2E>....80..<2E>.L?<3F>
...
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 <20>V???<3F>a.<2E><>??.<2E>?.
</PRE>
<P>
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.
</P>
<P>
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.
</P>
<P>
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.
</P>
<H4><A NAME="SEC336" HREF="vice_toc.html#TOC336">15.11.3.33 32 - EasyFlash</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>1024Kb (64 banks of 2 * 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF (ROML), $A000-$BFFF or $E000-$FFFF (ROMH)</TD>
</TR></TABLE>
<PRE>
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 ?<3F>^....80.?+++?E
</PRE>
<P>
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.
</P>
<P>
There are two control registers, one at $DE00 and one at $DE02.
</P>
<P>
The register at $DE00 does the following:
</P>
<PRE>
bit meaning
--- -------
7 LED control
6-3 Unused
2 Mode (0/1)
1 Exrom line control
0 Game line control
</PRE>
<P>
The register at $DE02 controls which bank is mapped into ROMH and
ROML.
</P>
<H4><A NAME="SEC337" HREF="vice_toc.html#TOC337">15.11.3.34 33 - EasyFlash Xbank</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>-</TD>
</TR>
<TR><TD>GAME</TD>
<TD>-</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>-</TD>
</TR>
<TR><TD>Load address</TD>
<TD>-</TD>
</TR></TABLE>
<P>
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.
</P>
<H4><A NAME="SEC338" HREF="vice_toc.html#TOC338">15.11.3.35 34 - Capture</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$E000-$FFFF</TD>
</TR></TABLE>
<PRE>
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 ???<3F>?.?.??<3F><><EFBFBD>?<3F>?
</PRE>
<P>
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.
</P>
<P>
When the freeze button is pressed the following happens:
</P>
<UL>
<LI>an NMI is generated
<LI>as soon as the current adress is in bank 0xfe the cart switches to
ultimax mode. The cart ROM then contains one page full of
"jmp $eaea", which ultimately calls the freezer code.
<LI>the $FFF7/$FFF8 "register" logic is enabled and any access (read or
write) to $FFF7 will turn the cart_enabled off (leave ultimax mode),
and an access to $FFF8 will turn the cart back on (enter ultimax
mode). the "register logic" that causes this can only be disabled
again by a hardware reset.
</UL>
<H4><A NAME="SEC339" HREF="vice_toc.html#TOC339">15.11.3.36 35 - Action Replay 3</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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.....'
</PRE>
<P>
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:
</P>
<PRE>
bit meaning
--- -------
7-4 unused
3 Exrom line control
2 Disable cart
1 Unused
0 Bank
</PRE>
<H4><A NAME="SEC340" HREF="vice_toc.html#TOC340">15.11.3.37 36 - Retro Replay</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb, 64Kb or 128Kb (4, 8 or 16 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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?<3F>L.<2E>L
</PRE>
<P>
The Retro Replay has three registers: Two write-only ($DE00 &#38; $DE01)
and one read-only register ($DE00 &#38; $DE01 giving the same results).
</P>
<P>
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.
</P>
<P>
Register at $DE00:
</P>
<PRE>
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.
</PRE>
<P>
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.
</P>
<P>
Register at $DE01:
</P>
<PRE>
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)
</PRE>
<P>
Reading from the registers at either $DE00 or $DE01 will return the
content of the status register.
</P>
<P>
Status register:
</P>
<PRE>
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
</PRE>
<P>
The following memory maps are available:
</P>
<UL>
<LI>standard -
$DE00 and $DE01 registers are active, $DF00-$DFFF contain the last
page of the selected 8Kb bank of either ROM or RAM, whatever is
selected. RAM can only be accessed in $8000-$9FFF. ROM can be mapped
to $8000, $A000 or $E000 with the corresponding status on GAME and
EXROM.
Note: If the AllowBank bit is not set, the $DF00-$DFFF area will
always access bank 0 of the RAM, so the older cartridge images will
work. The AllowBank bit does not have any effect on the ROM mirror in
that area.
<LI>Freeze -
ROM is mapped to $E000-$FFFF, bank 0 is active directly after Freeze.
Writing to bits 0 and 1 of the $DE00 register will have no effect on
GAME and EXROM. RAM can be selected and used in $DF00 or $DE02,
respectively, but not in $8000. Banking bits work, so you have full
read access to the ROM, and access to up to four RAM pages with the
AllowBank bit set (minus 2 bytes if REU compatible bit is set). You
should leave this memory map ASAP by setting bit 6 of $DE00, because
C64 RAM in the $E000 area is not available, and you don't have control
of the GAME and EXROM lines.
<LI>REU compatible -
$DE00 and $DE01 registers are active, $DE02-$DEFF contain a mirror of
$9E02-$9EFF of the selected 8K-bank of either ROM or RAM, whatever is
selected. RAM can only be accessed in $8000-$9FFF. ROM can be mapped
to $8000, $A000 or $E000 with the corresponding status on GAME and
EXROM. The $DF00 stays free for use with the 1764 Ram Expansion Unit
(REU).
Note: If the AllowBank bit is not set, the $DE02-$DEFF area will
always access bank 0 of the RAM, so the older cartridge images will
work. The AllowBank bit does not have any effect on the ROM mirror in
that area.
</UL>
<H4><A NAME="SEC341" HREF="vice_toc.html#TOC341">15.11.3.38 37 - MMC64</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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..?.?.
</PRE>
<P>
The clockport registers of this cart can be switched to either
$DE01-$DE0F or $DF21-$DF2F. The control registers are available at
$DF10-$DF13.
</P>
<P>
The register at $DE01 / $DF21 is write only:
</P>
<PRE>
bit meaning
--- -------
7-1 Unused
0 0 = disable clock port, 1 = enable clockport
</PRE>
<P>
The registers at $DE02-$DE0F / $DF22-$DF2F are for the clock port and
are read/write.
</P>
<P>
The register at $DF10 is the MMC64 SPI transfer register, a byte
written to this registers is sent to the card &#38; response from the card
is read here.
</P>
<P>
The register at $DF11 is the MMC64 control register:
</P>
<PRE>
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 (**)
</PRE>
<P>
(*) bit can only be programmed when flash jumper is set
(**) bit can only be modified after unlocking
</P>
<P>
The register at $DF12 is the MMC64 status register, which is
read-only:
</P>
<PRE>
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
</PRE>
<P>
The register at $DF13 is the MMC64 identification register, which when
reading from it can have the following values:
</P>
<P>
$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.
</P>
<P>
when writing to it it can be used to unlock bit 7 of $DF11 or to
re-enable the cart:
</P>
<P>
Write $55 &#38; $AA into this register to unlock bit 7 of $DF11.
Write $0A &#38; $1C into this register to re-enable MMC64 hardware.
</P>
<H4><A NAME="SEC342" HREF="vice_toc.html#TOC342">15.11.3.39 38 - MMC Replay</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb or 512Kb (8 or 64 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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 ???@???&#38;????????
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
</PRE>
<P>
The cart uses the following registers:
</P>
<P>
$DE00 - RR control register write
</P>
<PRE>
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
</PRE>
<P>
$DE01 - extended RR control register write
</P>
<PRE>
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)
</PRE>
<P>
$DE02-$DE0F - Clockport memory area (when enabled)
</P>
<P>
$DF10 - MMC SPI transfer register, a byte written is sent to the card
&#38; response from the card is read here.
</P>
<P>
$DF11 - MMC control register
</P>
<PRE>
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
</PRE>
<P>
$DF12 - MMC status register
</P>
<PRE>
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
</PRE>
<P>
$DF13 - Extended banking register
Can only be read/written to when bit 6 of $DF12 is 1
</P>
<PRE>
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
</PRE>
<H4><A NAME="SEC343" HREF="vice_toc.html#TOC343">15.11.3.40 39 - IDE64</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb or 128Kb (8 or 16 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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?
</PRE>
<P>
The IDE64 cart uses the following registers:
</P>
<PRE>
$DE20 - $DE27 Primary HDD Registers
$DE28 - $DE2F Secondary HDD Registers
$DE30 - Low Data HDD register
$DE31 - High Data HDD register
</PRE>
<P>
$DE32 register:
</P>
<PRE>
bit meaning
--- -------
7 unused (0)
6 unused (0)
5 unused (0)
4 version number (1)
3 romaddr15
2 romaddr14
1 game
0 exrom
</PRE>
<PRE>
$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
</PRE>
<H4><A NAME="SEC344" HREF="vice_toc.html#TOC344">15.11.3.41 40 - Super Snapshot V4</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32Kb (4 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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 .<2E>....80?P.?<3F>??
...
2050: 43 48 49 50 00 00 20 10 00 00 00 00 A0 00 20 00 CHIP????????<3F>???
2060: 4C FA A0 A9 07 8D 00 DD 2C 00 DD 50 FB 2C 00 DD L?<3F>.?<3F>?.,?.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.?<3F>??
...
6070: 43 48 49 50 00 00 20 10 00 00 00 01 A0 00 20 00 CHIP????????<3F>???
6080: F0 8A 48 A9 00 85 22 85 23 8D 53 0F 20 0C A1 B0 ?<3F>H.?<3F>"<22>#<23>S???.<2E>
</PRE>
<P>
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:
</P>
<P>
ROM config register at $DF00 (can only be written to):
</P>
<PRE>
bit meaning
--- -------
0 ?
1 ? (write 1 to release freeze mode)
2 ROM bank select
3 write 1 to disable cartridge
4-6 unused
7 ?
</PRE>
<P>
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.
</P>
<P>
RAM config register at $DF01 (read/write):
</P>
<P>
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)
</P>
<P>
$DF02-$DFFF holds the last page of the first 8kb of the current bank.
</P>
<H4><A NAME="SEC345" HREF="vice_toc.html#TOC345">15.11.3.42 41 - IEEE-488</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>4Kb (1 bank of 4Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$8FFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD>?.?<3F>??
</PRE>
<P>
The cart uses a TPI for the IEEE488 interface/communication in the
I/O-2 range:
</P>
<PRE>
$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
</PRE>
<H4><A NAME="SEC346" HREF="vice_toc.html#TOC346">15.11.3.43 42 - Game Killer</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$E000-$FFFF</TD>
</TR></TABLE>
<PRE>
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 ?%?.?<3F>2088?MC.CR
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC347" HREF="vice_toc.html#TOC347">15.11.3.44 43 - Prophet64</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>256Kb (32 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD>?<3F>?<3F>?
</PRE>
<P>
The control register is the I/O-2 range:
</P>
<PRE>
bit meaning
--- -------
7-6 unused
5 disable cart
4-0 bank select
</PRE>
<H4><A NAME="SEC348" HREF="vice_toc.html#TOC348">15.11.3.45 44 - EXOS</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$E000-$FFFF</TD>
</TR></TABLE>
<PRE>
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 <20>V???<3F>a.<2E><>??.<2E>?.
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC349" HREF="vice_toc.html#TOC349">15.11.3.46 45 - Freeze Frame</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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???????
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC350" HREF="vice_toc.html#TOC350">15.11.3.47 46 - Freeze Machine</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb or 32Kb (2 or 4 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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 :<3A>`....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<EFBFBD>?<3F>?<3F>?.?<3F>?.?<3F>
...
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 :<3A>`....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<EFBFBD>?<3F>?<3F>?.?<3F>?.?<3F>
</PRE>
<P>
Warning, the following information is based on guess-work and might be
incorrect, any further information and/or corrections are appreciated.
</P>
<P>
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.
</P>
<H4><A NAME="SEC351" HREF="vice_toc.html#TOC351">15.11.3.48 47 - Snapshot 64</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>4Kb (1 bank of 4Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$E000-$EFFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD>H??.??L??
</PRE>
<P>
Warning, the following information is based on guess-work and might be
incorrect, any further information and/or corrections are appreciated.
</P>
<P>
The cart has a control bit (bit 0) in the I/O-2 range which is used to
disable or enable the cart.
</P>
<H4><A NAME="SEC352" HREF="vice_toc.html#TOC352">15.11.3.49 48 - Super Explode V5.0</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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 .<2E>^....80.?,.?<3F>.
...
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 ?<3F>^....80?l<>.?<3F><>
</PRE>
<P>
Warning, the following information is based on guess-work and might be
incorrect, any further information and/or corrections are appreciated.
</P>
<P>
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.
</P>
<H4><A NAME="SEC353" HREF="vice_toc.html#TOC353">15.11.3.50 49 - Magic Voice</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF (bank 1),</TD>
$A000-$BFFF (bank 2)
</TR></TABLE>
<PRE>
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. ?<3F>.?<3F>.<2E>)?
...
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.<2E>.N.C?uc?<3F>
</PRE>
<P>
This cart has 16Kb of ROM, mapped in at reset at $8000-$BFFF. The cart
is controled through a TPI at $DF80-$DF87:
</P>
<PRE>
$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
</PRE>
<P>
The cart has a pass-through port and does the following at start-up:
</P>
<UL>
<LI>Program starts after reset at $FFD3, and copies code from
$FF36-$FFD2 to $0200-$029C (157 bytes)
<LI>Program continues at $021A, copies $A000-$BFFF from EPROM to RAM at
$A000-$BFFF (8Kb), copies $E000-$FFFF from EPROM to RAM at
$E000-$FFFF (8Kb), copies $AE62-$B461 from RAM to RAM at $C000-$C5FF
(Magic Voice Code)
<LI>Jump to beginning of Magic Voice code at $C000
</UL>
<H4><A NAME="SEC354" HREF="vice_toc.html#TOC354">15.11.3.51 50 - Action Replay 2</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>16Kb (2 banks of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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<EFBFBD><68>h<EFBFBD><68>h<EFBFBD><68>h<EFBFBD><68>
...
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??<3F>L8??
</PRE>
<P>
Warning, the following information is based on guess-work and might be
incorrect, any further information and/or corrections are appreciated.
</P>
<P>
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.
</P>
<H4><A NAME="SEC355" HREF="vice_toc.html#TOC355">15.11.3.52 51 - MACH 5</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>4Kb or 8Kb (1 bank of 4Kb or 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$8FFF (4Kb),</TD>
$8000-$9FFF (8Kb)
</TR></TABLE>
<PRE>
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 <20><>^....80MACH5<EFBFBD>.
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC356" HREF="vice_toc.html#TOC356">15.11.3.53 52 - Diashow maker</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>8Kb (1 bank of 8Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<PRE>
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
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC357" HREF="vice_toc.html#TOC357">15.11.3.54 53 - Pagefox</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>64Kb (4 banks of 16Kb)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$BFFF</TD>
</TR></TABLE>
<PRE>
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.<2E>?...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 ...??<3F>?<3F>.?t<>?<3F><>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??????????(&#60;???
...
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 ???<3F>????????????
</PRE>
<P>
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:
</P>
<PRE>
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
</PRE>
<P>
Chip select combinations of 0/1 are:
<PRE>
00: Eprom "79"
01: Eprom "ZS3"
10: Ram
11: empty space (reading returns VIC-II data)
</PRE>
<P>
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.
</P>
<H4><A NAME="SEC358" HREF="vice_toc.html#TOC358">15.11.3.55 54 - Kingsoft</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>-</TD>
</TR>
<TR><TD>GAME</TD>
<TD>-</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>-</TD>
</TR>
<TR><TD>Load address</TD>
<TD>-</TD>
</TR></TABLE>
<H4><A NAME="SEC359" HREF="vice_toc.html#TOC359">15.11.3.56 55 - Silverrock 128</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>128k (16 banks of 8k)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>active (1)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$8000-$9FFF</TD>
</TR></TABLE>
<H4><A NAME="SEC360" HREF="vice_toc.html#TOC360">15.11.3.57 56 - Formel 64</A></H4>
<TABLE BORDER>
<TR><TD>Size</TD>
<TD>32kb (4 banks of 8k)</TD>
</TR>
<TR><TD>GAME</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>EXROM</TD>
<TD>inactive (0)</TD>
</TR>
<TR><TD>Load address</TD>
<TD>$E000-$FFFF</TD>
</TR></TABLE>
<P><HR><P>
Go to the <A HREF="vice_1.html">first</A>, <A HREF="vice_14.html">previous</A>, <A HREF="vice_16.html">next</A>, <A HREF="vice_20.html">last</A> section, <A HREF="vice_toc.html">table of contents</A>.
</BODY>
</HTML>