I would argue that that feature really is important, but this is based on speculation, not hard facts.
Games can lie to the BIOS about how many files are on the disk as an anti-piracy measure. The ones that do this have their own copies of the loading routine that hard-codes the actual number of files, making the file amount block unreliable for its intended purpose. I don't know this for certain, but I suspect that those very same loading routines can also ignore checksum errors reported by the RAM adapter, meaning that any number of files can deliberately include invalid checksums to trick pirates. It may even be possible that a disk loading routine will err out if the checksum really is correct.
And the .fds format took those checksums out, so that emulators would never know.
Nintendo's .qd format is better because it includes checksums, but not only does it omit the 00 padding between blocks, it also has one flaw not in the .fds format: it can take 65,536 bytes per side instead of the 65,500 that actual disks could hold!
So I'm wondering if it is possible to expand the .fds format to make checksums optional instead of forbidden. I'd rather not have the header modified to indicate the presence of checksums; most emulators support leaving out the header entirely because it's practically useless right now, just like Super Famicom and PC Engine copier headers. So I'll argue for heuristic detection.
Block types 1, 2, and 3, which are the disk info block, file amount block, and the file header block respectively, always have fixed sizes of 56, 2, and 16 when counting the block ID and omitting the checksum. This means that, no matter what, $0000 will always hold the byte 0x01, $0038 will always hold the byte 0x02, $003A will always hold the byte 0x03, and $004A will always hold the byte 0x04.
If checksums are included, the block sizes above change to 58, 4, and 18 respectively, changing the locations of bytes 0x01, 0x02, 0x03, and 0x04 to $0000, $003A, $003E, and $0050 respectively.
Thus, in order to detect whether a .fds file includes checksums, the emulator needs to verify the following:
No checksums (all current .fds files)
- The addresses $0038, $003A, and $004A hold the byte values 0x02, 0x03, and 0x04.
- The addresses $003A, $003E, and $0050 hold the byte values 0x02, 0x03, and 0x04.
- The address $0038 holds the 16-bit checksum of the disk info block ($0000-$0037), and said checksum is correct.
- The address $003C holds the 16-bit checksum of the file amount block ($003A-$003B), and said checksum is correct.
- The address $004E holds the 16-bit checksum of the first file's header block ($003E-$004D), and said checksum is correct.
================================================
By the way, the NesDev wiki does not include the formula for calculating checksums. The Famicom Disk System technical reference by Brad Taylor includes a formula, but it's in x86 assembly. By comparing the checksums I am getting with those from Nintendo's .qd images, I have found that this C-like pseudocode converted from that x86 formula produces the correct checksum:
Code: Select all
uint16_t fds_crc(uint8_t* data, unsigned size) {
//Do not include any existing checksum, not even the blank checksums 00 00 or FF FF.
//The formula will automatically count 2 0x00 bytes without the programmer adding them manually.
//Also, do not include the gap terminator (0x80) in the data.
//If you wish to do so, change sum to 0x0000.
uint16_t sum = 0x8000;
for(unsigned byte_index = 0; byte_index < size + 2; byte_index++) {
uint8_t byte = byte_index < size ? data[byte_index] : 0x00;
for(unsigned bit_index = 0; bit_index < 8; bit_index++) {
bool bit = (byte >> bit_index) & 1;
bool carry = sum & 1;
sum = (sum >> 1) | (bit << 15);
if(carry) sum ^= 0x8408;
}
}
return sum;
}