Ok, I could really use some help here again. To recap, at this stage I have two goals:
1. Read 2352-byte CD sector data out (CD-DA mode)
2. Read subcode data for each sector
Here's my current working CD sector reading routines. This is the code I use for reading a block of normal 2048-byte CD sectors:
Code: Select all
;----------------------------------------------------------------------------------------
;Reads the specified number of sectors from a disk
;Input:
;-a5 - Pointer to params struct
;struct Params
;{
; long startSectorNumber - Logical sector number to start read from
; long sectorCopyCount - Number of sectors to transfer
; long dataDestination - Destination address to write sector data to
; long headerDestination - Destination address to write header data to
;}
;----------------------------------------------------------------------------------------
ReadCDData:
BIOS_CDCSTOP ;Ensure that no other CD data transfer is currently occurring
move.b #$03, $FF8004 ;Set the CDC device destination to subcpu read. Required before calling BIOS_CDCREAD below.
movea.l a5, a0 ;Set the initial sector number and count of sectors to transfer
BIOS_ROMREADN ;Start the read operation
ReadCDDataReadLoop:
move.w #$8000,d5
ReadCDDataCheck_CDCSTAT:
BIOS_CDCSTAT ;Check if more data is ready to read
bcc ReadCDDataCheckExit_CDCSTAT
dbf d5,ReadCDDataCheck_CDCSTAT
bra ReadCDDataFailed
ReadCDDataCheckExit_CDCSTAT:
move.w #$8000,d5
ReadCDDataCheck_CDCREAD:
BIOS_CDCREAD ;Prepare for a data read from the CDC buffer
bcc ReadCDDataCheckExit_CDCREAD
dbf d5,ReadCDDataCheck_CDCREAD
bra ReadCDDataFailed
ReadCDDataCheckExit_CDCREAD:
move.w #$8000,d5
ReadCDDataCheck_CDCTRN:
movea.l 8(a5), a0 ;Set the destination for the sector data (should be 0x800 bytes)
lea 12(a5), a1 ;Set the destination for the header data (4 bytes)
BIOS_CDCTRN
bcc ReadCDDataCheckExit_CDCTRN
dbf d5,ReadCDDataCheck_CDCTRN
bra ReadCDDataFailed
ReadCDDataCheckExit_CDCTRN:
;Acknowledge the read has been completed
BIOS_CDCACK
;Update the target address, starting sector, and remaining sector count, and
;repeat the loop if more sectors are remaining.
addi.l #$800, 8(a5)
addq.l #1, (a5)
subq.l #1, 4(a5)
bne ReadCDDataReadLoop
ReadCDDataFailed:
rts
And here's the code I use for reading 2353-byte CD-DA sector data:
Code: Select all
;----------------------------------------------------------------------------------------
;Reads the specified number of sectors from a disk in raw mode
;Input:
;-a5 - Pointer to params struct
;struct Params
;{
; long startSectorNumber - Logical sector number to start read from
; long sectorCopyCount - Number of sectors to transfer. Each raw sector is 2352 (0x930) bytes
; long rawDestination - Destination address to write raw sector data to
;}
;----------------------------------------------------------------------------------------
ReadCDDataRaw:
BIOS_CDCSTOP ;Ensure that no other CD data transfer is currently occurring
move.b #$03, $FF8004 ;Set the CDC device destination to subcpu read. Required before calling BIOS_CDCREAD below.
movea.l a5, a0 ;Set the initial sector number and count of sectors to transfer
BIOS_ROMREADN ;Start the read operation
ReadCDDataRawReadLoop:
move.w #$8000,d5
ReadCDDataRawCheck_CDCSTAT:
BIOS_CDCSTAT ;Check if more data is ready to read
bcc ReadCDDataRawCheckExit_CDCSTAT
dbf d5,ReadCDDataRawCheck_CDCSTAT
bra ReadCDDataRawFailed
ReadCDDataRawCheckExit_CDCSTAT:
;Set the CDC read mode to CD-DA mode, to obtain the full 2352 bytes of sector data.
move.w #$0002, d1
BIOS_CDCSETMODE
move.w #$8000,d5
ReadCDDataRawCheck_CDCREAD:
BIOS_CDCREAD ;Prepare for a data read from the CDC buffer
bcc ReadCDDataRawCheckExit_CDCREAD
dbf d5,ReadCDDataRawCheck_CDCREAD
bra ReadCDDataRawFailed
ReadCDDataRawCheckExit_CDCREAD:
;Read the address to write the next raw sector data to
movea.l 8(a5), a0
;Set the header target location to be the same as the sector target location. This is
;safe, since the CDCTRN function writes data to the header target before writing data
;to the sector data target.
movea.l a0, a1
;Read the sector
move.w #$8000,d5
ReadCDDataRawCheck_CDCTRN:
BIOS_CDCTRN
bcc ReadCDDataRawCheckExit_CDCTRN
dbf d5,ReadCDDataRawCheck_CDCTRN
bra ReadCDDataRawFailed
ReadCDDataRawCheckExit_CDCTRN:
;Acknowledge the read has been completed
BIOS_CDCACK
;Update the target address, starting sector, and remaining sector count, and
;repeat the loop if more sectors are remaining.
addi.l #$930, 8(a5)
addq.l #1, (a5)
subq.l #1, 4(a5)
bne ReadCDDataRawReadLoop
ReadCDDataRawFailed:
rts
All this is written based on the manual and hardware experimentation. Now the first routine is fairly standard. The second one is where things go a bit off the rails. There's no documentation on exactly when you should call the CDCSETMODE routine. I found the only time I could get it to do anything useful was if I called it for each sector, after CDCSTAT reported that a sector was available. I have no idea if this is how this routine is supposed to be used, but I found if I called it here, I did get returned 2352 bytes of sector data when I called CDCTRN afterwards. That said, the output from CDCTRN isn't entirely correct. I seem to get returned the current sector from the sector header, after the sync data, then for the last 12 bytes of the 2352 bytes of returned sector data, I get returned what appears to be the sync data of the following sector. The sync data being messed up isn't a huge problem, since the sync data is known and needs to be present in order for the drive to be able to locate the sector at all, so I can just insert what I know the sync data should be for the first sector and chop off the trailing 12 bytes, but I'm wondering if there's something else I should be doing in order to read 2352 byte sector data which will avoid this problem.
I'm also completely unsure about the state of the actual hardware error correction in my attempts. Even though I'm reading out 2352 bytes of data, is the hardware still thinking it's reading mode 1 CD data, and will it therefore attempt to use EDC/ECC data to perform error correction on the data if I actually attempt to read mode 2 CD sectors?
There's also the whole issue of reading out subcode data. The BIOS routines don't seem to expose the full subcode data out, so in order to capture the data, I need to snag them from the subcode buffer directly from the hardware. How and when can I do this though? There's a level 6 interrupt fired when the subcode data is buffered I believe, but when does this actually occur in relation to my read calls? What's a real example in code of how and when I can read the subcode data out?
I get the feeling I need to perform reading at a lower level to get the results I want. I'm currently using ROMREADN, which is a high-level bios CD reading routine, but so far it's the only way I've been able to successfully read data. Do I need to go a level deeper? CDBIOS.INC states that ROMREAD calls CDCSTART to begin a read operation, and TascoDLX indicated I should use CDCSTARTP, which accepts the CDC mode as a parameter, but I couldn't find any examples of how and where to actually use this lower level function to read CD data, and all my attempts to figure out how to use it through experimentation have failed.
I also basically don't understand the way the BIOS reads, buffers, and sends sector data to my code, which doesn't help matters. What do CDCSTAT, CDCREAD, and CDCTRN actually do, in a nutshell, and where is the actual data at each stage of the process? It seems to me that the data has already been buffered somewhere by the BIOS by the time CDCSTAT returns "true", is that correct?
So, at this stage, I have a few questions:
1. What is the "correct" sequence of BIOS calls to read CD-DA data using the ROMREAD bios functions?
2. What is a working sequence of BIOS calls to read CD data without using ROMREAD?
3. How, where, and when can the raw subcode buffer be read in this process?