Skip to content

C65 F011 emulation

LGB edited this page Sep 10, 2016 · 20 revisions

Note: I don't emulate the unbuffered operations and it seems DOS doesn't use that either, maybe at some cases only like disk formatting has something to do with this in case of write.

F011 has an 512 bytes SRAM attached for buffered read/write operations. There are two 9 bits (thus the size of cache buffer) pointers maintained in relation of the buffer. It seems they warps around of course, though I couldn't notice this behaviour actually "exploited" by C65 DOS (other than to become zero again). One pointer (let's call that "FDC pointer") is used by the FDC to read a byte from the buffer and write onto the disk in case of a (buffered) write operation or to read one byte from the disk and place into the buffer in case of a (buffered) read operation (that is, FDC pointer is the byte in buffer FDC can access to read/write buffer at). After this task, the FDC's buffer pointer is incremented by one and DRQ but is set to signal, that the F011 was the last who accessed the buffer. It's currently unknown to me, that EQ bit should be altered in case of FDC pointer change only, in my emulation I only do this, if CPU pointer (see below) changes.

CPU can read/write buffer with register 7. Every time it does so, DRQ is cleared to signal, that CPU was the last who accessed the buffer and the other buffer pointer ("CPU pointer", let's say) is incremented. Then after the incrementation, FDC and CPU pointers are compared, if they are the same EQ bit is set, otherwise EQ bit is cleared. I think just before the CPU buffer address if EQ bit was already set, LOST bit set, as it would mean some byte will be lost in the buffer. It seems, EQ is never set at the beginning even not when you would think that the two pointers are equal at the start point. Doing so, would cause DOS to freeze hanging in a tight loop waiting for EQ to clear.

Maybe later ROM versions use the SWAP bit, but the version of ROM I use (and it seems M65 as well) does not use it, at all. In case if DOS needs an odd numbered (logical!) block it simply reads the physical 512 bytes block and does 256 dummy reads (to position the CPU buffer pointer to the second half of the buffer) and then only read and store result in C65 memory for real. That's true for write operations as well, where DOS reads the physical on-disk block (512 bytes block size) then doing 256 dummy reads of buffer to position to the second half, then writing 256 bytes to overwrite the second half of the physical sector in the buffer, if write operation is initiated for an even numbered (logical) block. After that, write block command is issued. As the FDC pointer is at #0 (as it filled 512 bytes on disk read in buffer, thus wrapped around to 0) the next $80 (write) command will write the whole 512 bytes buffer back to the disk, whose lower half is unmodified (the same as it was read) and the higher half was overwritten in the buffer by the DOS code. Thus the result, that we have an on-disk physical block which has the second 256 bytes are modified by the CPU only.

It seems that FDC didn't reset the buffer pointers by its own (even not between commands?), always continue to use bytes where the pointers was. Unless if pointer reset command is sent which DOS do quite often according to my inspections. This is command $14, it causes to set CPU and FDC buffer pointers to zero (but it seems again, EQ bit should not be set then?). As it wouldn't mean sense to have a "reset pointer" command, I have the suspect, that pointers should be reset (to zero, I mean) on $14 command request and never done otherwise.

Moreover, there is important role of RDREQ. In case of a read operation, of course BUSY bit is set, then after some time either the FDC located the block, so RDREQ is set, or eg RFN is set instead, to indicate the failure of locating the needed one. DOS ROM waits for either RDREQ goes high (indicates that block is found and reading into the buffer right now by FDC) or RFN is set, to signal a problem. Interestingly, I haven't emulated WTREQ too much, but it seems DOS doesn't care about that. In theory it would mean, that data is right now written onto the disk from the buffer.

In Xemu, I emulated only a subset of this, ie the one-by-one byte read/write from/to the disk process is done in "one step", that is an "infinite fast drive". But since it seems DOS uses correctly the RDREQ/EQ for reading for example to tell if there is byte in the buffer and how many works in either case, so it doesn't matter. As EQ/DRQ/RDREQ should gives enough information for example read, it's enough to handle any of the cases, whatever amount of bytes and how fast FDC could handle in relation of the physical disk operation, so my primitive emulation is as good as the real one, where only bytes by bytes are transferred between the disk and the buffer by FDC "quite slowly" maybe at least compared to a fast CPU :)

Clone this wiki locally