-
Notifications
You must be signed in to change notification settings - Fork 32
C65 F011 emulation
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. One 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. 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.
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. In case if DOS needs an odd numbered block it simply 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 reads of buffer to position to the second half, then writing 256 bytes to overwrite the second half of the physical sector, 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 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 and the higher half was overwritten in the buffer by the DOS code.
It seems that FDC didn't reset the buffer pointers by its own, 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?).
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 locationg 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.