Computer Old Farts Forum
 help / color / mirror / Atom feed
* [COFF] Famicom Disk System Software Disassembly (Doki Doki Panic)
@ 2023-10-17 22:41 segaloco via COFF
  0 siblings, 0 replies; only message in thread
From: segaloco via COFF @ 2023-10-17 22:41 UTC (permalink / raw)
  To: COFF

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.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-10-17 22:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-17 22:41 [COFF] Famicom Disk System Software Disassembly (Doki Doki Panic) segaloco via COFF

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).