Good day everyone, I thought I'd share a new project I've been working on since
it is somewhat relevant to old and obscure computing stuff that hasn't gotten a lot
of light shed on it.
https://gitlab.com/segaloco/doki
After the link is an in-progress disassembly of Yume Kojo: Doki Doki Panic for the Famicom
Disk System, known better in the west as the engine basis for Super Mario Bros. 2 for the
NES (the one with 4 playable characters, pick-and-throw radishes, etc.)
What inspired me to start on this project is the Famicom Disk System is painfully
under-documented, and what is out there is pretty patchy. Unlike with its parent console,
no 1st party development documentation has been archived concerning the Disk System, so
all that is known about its programming interfaces have been determined from disassemblies
of boot ROMs and bits and pieces of titles over the years. The system is just that, a
disk drive that connects to the Famicom via a special adapter that provides some RAM,
additional sound functionality, and some handling for matters typically controlled by the
cartridge (background scroll-plane mirroring and saving particularly.) The physical disk
format is based on Mitsumi's QuickDisk format, albeit with the casing extended in one
dimension as to provide physical security grooves that, if not present, will prevent the
inserted disk from booting. The hardware includes a permanently-resident boot ROM which
maps to 0xE000-0xFFFF (and therefore provides the 6502 vectors). This boot ROM in turn
loads any files from the disk that match a specified pattern in the header to
header-defined memory ranges and then acts on a secondary vector table at 0xDFFA (really
0xDFF6, the disk system allows three separate NMI vectors which are selected from by a
device register.) The whole of the standard Famicom programming environment applies,
although the Disk System adds an additional bank of device registers in a reserved memory
area and exposes a number of "syscalls" (really just endpoints in the
0xE000-0xFFFF range, it's unknown at present to what degree these entries/addresses
were documented to developers.)
I had to solve a few interesting challenges in this process since this particular area
gets so little attention. First, I put together a utility and supporting library to
extrapolate info from the disk format. Luckily the header has been (mostly) documented,
and I was able to document a few consistencies between disks to fill in a few of the parts
that weren't as well documented. In any case, the results of that exercise are here:
https://gitlab.com/segaloco/fdschunk. One of the more interesting matters is that the
disk creation and write dates are stored not only in BCD, but the year is not always
Gregorian. Rather, many titles reflect instead the Japanese period at the time the title
was released. For instance, the Doki Doki Panic image I'm using as a reference is
dated (YY/MM/DD) "61/11/26" which is preposterous, the Famicom was launched in
1983, but applying this knowledge of the Showa period, the date is really
"86/11/26" which makes much more sense. This is one of those things I run into
studying Japanese computing history time to time, I'm sure the same applies to
earlier computing in other non-western countries. We're actually headed for a
"2025-problem" with this time-keeping as that is when the Showa calendar rolls
over. No ROMs have been recovered from disk writer kiosks employed by Nintendo in the
80s, so it is unknown what official hardware which applies these timestamps does when that
counter rolls over. I've just made the assumption that it should roll back to 00,
but there is no present way to prove this. The 6502 implementation in the Famicom (the
Ricoh 2A03) omitted the 6502 BCD mode, so this was likely handled either in software or
perhaps a microcontroller ROM down inside the disk drives themselves.
I then had to solve the complementary problem, how do I put a disk image back together
according to specs that aren't currently accessible. Well, to do that, I first
chopped the headers off of every first-party Nintendo image I had in my archive and
compared them in a table. I diverted them into two groups: pristine images that represent
original pressings in a Nintendo facility and "dirty" images that represent a
rewrite of a disk at one of the disk kiosks (mind you, Nintendo distributed games both
ways, you could buy a packaged copy or you could bring a rewritable disk to a kiosk and
"download" a new game.) My criterion for categorization was whether the disk
create and modify times were equal or not. This allowed me to get a pretty good picture
of what headers getting pumped out of the factory look like, and how they change when the
disk is touched by a writer kiosk. I then took the former configuration and wrote a
couple tools to consume a very spartan description of the variable pieces and produce the
necessary images:
https://gitlab.com/segaloco/misc/-/tree/master/fds. These tools,
bintofdf and fdtc, apply a single file header to a disk file and create a
"superblock" for a disk side respectively. I don't know what the formal
terms are, they may be lost to time, but superblock hopefully gets the point across,
albeit it's not an exact analog to UNIX filesystems. Frankly I can't find
anything regarding what filesystem this might be based on, if at all, or if it is an
entirely Nintendo-derived format. In any case, luckily the header describing a file is
self-contained on that file, and then the superblock only needs to know how many files are
present, so the two steps can be done independently. The result is a disk image, stamped
with the current Showa BCD date, that is capable of booting on the system. The only thing
I don't add that "pure" disks contain are CRCs of the files. On a physical
disk, these header blocks also contain CRCs of the data they describe, these, by
convention, are omitted from disk dumps. I'm actually not entirely sure why, but I
imagine emulator writers just omit the CRC check as well, so it doesn't matter to
folks just looking to play a game.
Finally, there's the matter of disparate files which may or may not necessarily be
sitting in memory at runtime. Luckily the linker script setup in cc65 (the compiler suite
I'm using) is pretty robust, and just like my Dragon Quest disassembly (which is made
up of swappable banks) I was able to use the linker system to produce all of the necessary
files in isolation, rather than having to get creative with orgs and compilation order to
clobber something together that worked. This allows the code to be broken down into its
logical structure rather than just treating a whole disk side as if it was one big binary
with .org commands all over the place.
Anywho, I don't intend on a rolling update to this email or anything, but if this is
something that piques anyone's interest and you'd like to know more, feel free
to shoot me a direct reply. I'd be especially interested in any stories or info
regarding Mitsumi QuickDisk, as one possibility is that Nintendo's format is derived
from something of their own, with reserved/undefined fields redefined for Nintendo's
purposes. That said, it's just a magnetic disk, I would be surprised if a single
filesystem was enforced in all implementations.
Thanks for following along!
- Matt G.
P.S. As always contributions to anything I'm working on are welcome and encouraged,
so if you have any input and have a GitLab account, feel free to open an issue, fork and
raise a PR, etc.