I have been tantalisingly close to being able to access the SD card via the internal 1581 DOS for a while, but there always seems to be one more step to cover.
The latest progress has been getting the floppy controller to read sectors from the correct location in the disk images on the SD card.
I had worked out a while back that physical track numbers start at 0, and had taken that into account.
I assumed that sectors also started at zero, since there was no contradictory guidance in the C65 specifications. However, directory headers were not being loaded correctly, indicating that something was amiss. I suspected the SWAP line that swaps halves of the sector buffer around, but couldn't find the point when the directory header sector was actually being loaded.
I added extra debug features to the serial monitor so that I could get the CPU to halt when writing to the floppy controller command register, but even that failed to reveal the reading of a sector 0. At this point I began to suspect that sectors might be numbered from 1, not zero.
Looking through the C65 ROM disassembly I managed to find the routine that prepares to load a sector from disk. After scratching my head over it for a while, I was able to confirm that sectors do in fact start from 1, not zero, and made the change to the FPGA.
This is the routine:
9A34 BD B4 1F LDA $1FB4,X ; Read logical track number (1 - 80)
9A37 3A DEC ; Decrement by one to obtain
; physical track number (0 to 79)
9A38 8D 84 D0 STA $D084 ; Store physical track number in
; FDC register
9A3B BD B5 1F LDA $1FB5,X ; Read logical sector number
; (0 - 39)
9A3E C9 14 CMP #$14 ; Set carry flag if sector number is >=20
9A40 A9 00 LDA #$00
9A42 2A ROL A ; Set A to 1 if sector number >=20,
; or 0 if sector number <20
9A43 8D 86 D0 STA $D086 ; Store physical side number in FDC
9A46 F0 02 BEQ $9A4A ; Take branch if sector is one
; side 0 (A will be $00)
9A48 A9 14 LDA #$14 ; Load A with 20, which will be
; subtracted from logical sector
9A4A 42 NEG ; Calculate 2's complement of A,
; so will be either 0 (front
; sector) or -20 (rear sector)
9A4B 18 CLC ; With C flag, A will be either $00
; if sector is on front side, or
; ($00-20) if on back side
9A4C 7D B5 1F ADC $1FB5,X ; Now add logical sector number.
; Result will be 0 for sector 0,
; through to 19 for sector 39.
9A4F 4A LSR A ; Shift sector number right one bit
; since physical sectors are
; 512 bytes, not 256. Sector
; number will now be 0 through 9
9A50 1A INC ; Add one to sector number, since
; physical sectors apparently
; start at 1, not 0. Result will
; be between 1 and 10.
9A51 8D 85 D0 STA $D085 ; Store sector number into FDC
Armed with this knowledge, I fixed the sector location calculation (and a few other bugs along the way).
The result is that the DOS now works for loading directories and programs.
First, here is the kickstart startup process where -- if you are quick -- you can see it mounting the .D81 file:
Now a couple of screenshots showing part of the (rather long) directory listing of the C64 emulator test suite that lives on the disk I mounted. Even holding CONTROL down, the list flies by very quickly because of the speed that this machine is running.
Finally, in this video you can see me run most of the CPU tests from the C64 emulator test suite in about a minute -- the C65GS is already a very fast C64. The video wasn't appearing in the preview here for me, but hopefully it will appear when I publish this post.