FDS Woes

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
FDS Woes
by on (#6365)
For two days I've been putzing around trying to get FDS to work. I've read the docs I could find over and over and I thought I had a decent understanding of how it works, but when I impliment it, it just ain't working. I constantly get various Disk errors when the BIOS is trying to read the disk header. In my latest attempt, I get no error, but the BIOS simply locks up and forever loops at a "now loading" screen.

I've been using BT's doc as my primary reference, with other docs to mainly fill in the gaps (IRQ timer mainly, even though that's low on my priority list right now -- i just want to get the games loaded and running).

Here's my current understanding. If ANYONE can clarify the grey areas, make any kind of correction, or throw any ideas out on the table... it'd be GREATLY appreciated:

- BIOS at $E000-FFFF. Always -- no exceptions.

- 32k RAM (flushed on hard reset) at $6000-$DFFF. Always. No swapping, no banks -- just a flat out big hunk of RAM.

- Each Disk side is 65500 bytes, starting immediately after the 16-byte .fds header. ie: Disk 1- Side A @ 0x00010, Disk 1- Side B @ 0x0FFEC, Disk 2- Side A @ 0x1FFC8, etc

- Two seperate and completely independent IRQ generators on the FDS -- one for use by the game (16-bit decrementing CPU cycle counter set by $4020/1/2) -- and one which is used to be alerted when the drive is ready for another transfer (enabled by $4025.7)

- $4024 and $4031 do not write/read the disk directly -- rather they act as a buffer to hold the next byte to be written/read


now this is where it gets hairy -- since docs have conflicting info... and BT's doc isn't exactly crystal clear:

- Clearing $4025.0 will turn off the drive motor. It can't be turned on again until this bit is set again.

- Clearing $4025.1 will turn ON the drive motor, unless $4025.0 is clear. Setting $4025.1 will not turn off the motor if it's already on (you must clear $4025.0 to turn it off). To quote BT's doc: "When deactivated, disk drive motor stays on until disk head reaches most inner track of disk". Considering he said a value of 0 is "activated", I'd assume "deactivated" means 1.

- However, setting $4025.1 will disrupt disk I/O somehow. No doc gives any explaination as to how/why... and I don't really understand this part at all.

- If the drive motor is off, it resets to the start of the disk -- ie when turned back on, the next byte to be transfered will be at offset $0000 on the disk.

- $4030.1 returns the value of the byte transfer flag.

- $4032.1 is cleared only when the drive position is reset to 0 (motor turned off?). It is set when the drive reaches the end of the disk. ??? Or when $4025.1 is set???

- If the drive motor is on and disk IO is enabled (and of course if a disk is in the drive), the following happens: a) every ?100? CPU cycles and b) if the byte transfer flag is clear:

1) If in write mode, value in $4024 gets written to disk. Else if in read mode, value gets read from disk and gets put in $4031.

2) Byte Transfer flag gets set (IRQ tripped if enabled). This is the only way to set the Xfer flag?

- Only way to clear byte transfer flag (so that another byte can be read/written) is to read $4031, $4030, or write to $4024. (and maybe turn the motor off? although no doc says that)


That's about it! That's the most sense I could make out of BTs doc. The biggest concern of mine (and I'm willing to bet the source of all my troubles) is $4032.1. When exactly is this bit set/clear?

Anyway, like I said, any sort help would be greatly appreciated. Thanks in advance.

by on (#7109)
Well, I haven't implemented the FDS so I can't pretend to be an expert, but I did read BT's doc, studied the BIOS disassembly, and also took a peek at Nestopia's source code (although it didn't sync perfectly with BT's doc). Here are a couple of notes:

$4032.1 is set by default. It remains set until the motor is on ($4025.0 set and $4025.1 clear) and the disk head reaches the beginning of the disk (supposedly takes about 0.15 seconds, though Nestopia didn't put in any delay). The flag is then clear until either $4025.1 is set or the disk head reaches the end of the disk. Basically, the flag is clear while the drive is ready for transfer and set when transfer is over.

I believe the byte transfer flag is only set if $4025.6 is 1. During reads, it will be set for the first time once the first byte of a block has been read from disk (Nestopia assumes a delay of 200 cycles before this happens, although in reality the delay would be quite longer). At this time, $4031 should have the first byte of the block (which is the block ID). Subsequent byte transfers occur about 150 cycles apart.

During writes, the byte transfer flag should be set immediately when $4025.6 is set. The value in $4024 (which the BIOS will have set to zero) is transfered to disk. The BIOS then enables interrupts, which should trip immediately since the transfer flag is raised, and then writes $80 (the block start mark) to $4024. The next time the transfer flag raises (150 cycles later), this value will get written, thereby officially starting the new block of data. Note that .fds files do NOT contain block start marks, so emulators should ignore these writes (Nestopia does this by explicitly ignoring the first 2 writes, although perhaps a better solution would be to wait for $80 to be transfered and then to start accepting data following it).

At the end of a block read, the BIOS will read and discard two bytes before turning off $4025.6 (this is for the CRC analysis). These two bytes, however, do not appear in .fds images, so when $4025.6 is cleared, you will need to subtract two from the file pointer (or else you'll get an error when the BIOS starts reading the next block because the block ID won't match).

At the end of a block write, the BIOS will wait for the last value in $4024 to get written to disk, then it sets $4025.4 to force the CRC to get written. Again, this is not in the .fds image, so you should stop writing as soon as this flag is set (stop raising the transfer flag as well, for an interrupt during this time will screw up the BIOS I believe). The BIOS will wait a certain number of cycles, then turn off $4025.6 (do not subtract 2 from the file pointer - you didn't write anything for CRC, so there's nothing to subtract).

There are no gaps between blocks in .fds images, so do not advance the file pointer unless the transfer flag raises. It should raise only when $4025.6 is set (and also if $4025.4 is clear, if in write mode).

I hope this helps. I can't guarantee I have enerything right, as I never implemented this myself. I'm merely saying what I can given the information I've seen.

by on (#7121)
Awesome. Awesome to the max.

That "subtract 2 for the CRC" thing is probably what was throwing me off. I'll have to go back and work on FDS again.

Thanks a bunch.

by on (#7139)
I had a very odd problem when I got a FDS. The LH2833 chip (supposedly a DRAM chip) had gone flakey on me. After the FDS screen would load the screen would just go black and I got nothing.

I ordered some surpluss Sharp LH2833-15 chips online (the place is all out now), and gave it a shot, of course the FDS adapter worked again.

I have just a couple spare's I'd be willing to sell, if anyone needs one.

by on (#7156)
Quote:
I have just a couple spare's I'd be willing to sell, if anyone needs one.


Got any virtual ones for an FDS emulator? :)