VU Meter & CD player interface in general
Moderator: Mask of Destiny
VU Meter & CD player interface in general
While implementing audio track support and debugging it with the CD player interface, i was wondering about the VU meter that got displayed when tracks are played. Anyone knows how this is being handled by the SUB-CPU BIOS or MAIN-CPU BOOTROM ?
Especially, i am curious to know why, in my emulator, it is still displayed when playing the DATA track. Kega for example only shows it for AUDIO tracks , which, from what i remember, is the correct behavior. I am correctly handling the DATA/AUDIO bit in CDD register so it must be something else. Subcodes maybe (which i think only Kega is handling) ?
Especially, i am curious to know why, in my emulator, it is still displayed when playing the DATA track. Kega for example only shows it for AUDIO tracks , which, from what i remember, is the correct behavior. I am correctly handling the DATA/AUDIO bit in CDD register so it must be something else. Subcodes maybe (which i think only Kega is handling) ?
Last edited by Eke on Sat Oct 20, 2012 2:08 pm, edited 2 times in total.
You may be right, according to Red Book, there is one bit in the 96-bits Q-Channel subcode that indicates if the current block is digital audio or data...
http://www.chipchapin.com/CDMedia/cdda9.php3
I tried to trigger Subcode (level 6) interrupt and fill the subcode buffer area with 0x40 (so all Q-Channel bits are set 1) but it seems like it's not enough. I guess subcode address register and maybe Q-channel CRC field should also be properly emulated
http://www.chipchapin.com/CDMedia/cdda9.php3
I tried to trigger Subcode (level 6) interrupt and fill the subcode buffer area with 0x40 (so all Q-Channel bits are set 1) but it seems like it's not enough. I guess subcode address register and maybe Q-channel CRC field should also be properly emulated
a (maybe) similar issue is related to how cd player interface handles the end of the last track: on real hardware and in Kega, when the last track plays the last block of audio, playback ends and disc is automatically stopped. In Gens, it seems it goes back to track 2 (?) and in Genesis Plus GX, audio playback and time counters stop ( because i don't allow reading past the end of disc image) but the disc is not stopped and status keeps displaying "playing".
I handle the lead-out area (anything beyond the last track) by returning AA as track index and locking the block counter to the last block, but i tried different things (keep returning last track number, continue to increment block counter, etc) and nothing worked, the bios does not detect the end of the disc and does not stop it.
Again, you might say it's not a big deal since it only affects the cd player interface and you can still stop it manually but i suspect this unemulated behavior is the cause of some freeze in Snatcher, specifically at the end of a long cutscene which involves playing the last track of the disc ! I know this part (explosion of the morgue, when Gillian and some guy have been captured) has been causing issues to emulator users from the start of Sega CD emulation and i thought it was caused by using a bad image, but it appears the image i have work fine in Kega but not in my emulator (could not test in Gens).
I somehow feel that fixing the "end of disc detection" might fix this issue as well but unfortunately i could not figure from BIOS analysis what it is waiting for. Like the VU meter, i am finally not so sure it is using subcode interrupt and buffer (which seems to be used only with CD-G discs, while P- and Q- subchannel are always decoded directly by CDD microprocessor and infos returned to BIOS through CDD communication status words) but rather using some undocumented fields in CDD communication status words, which Steve Snake only would have figured.
I handle the lead-out area (anything beyond the last track) by returning AA as track index and locking the block counter to the last block, but i tried different things (keep returning last track number, continue to increment block counter, etc) and nothing worked, the bios does not detect the end of the disc and does not stop it.
Again, you might say it's not a big deal since it only affects the cd player interface and you can still stop it manually but i suspect this unemulated behavior is the cause of some freeze in Snatcher, specifically at the end of a long cutscene which involves playing the last track of the disc ! I know this part (explosion of the morgue, when Gillian and some guy have been captured) has been causing issues to emulator users from the start of Sega CD emulation and i thought it was caused by using a bad image, but it appears the image i have work fine in Kega but not in my emulator (could not test in Gens).
I somehow feel that fixing the "end of disc detection" might fix this issue as well but unfortunately i could not figure from BIOS analysis what it is waiting for. Like the VU meter, i am finally not so sure it is using subcode interrupt and buffer (which seems to be used only with CD-G discs, while P- and Q- subchannel are always decoded directly by CDD microprocessor and infos returned to BIOS through CDD communication status words) but rather using some undocumented fields in CDD communication status words, which Steve Snake only would have figured.
He he, I figured it out
By analyzing the BIOS, I figured there were a bunch of undocumented CDD status (returned in RS0) and I ended up testing the ones that were not known yet.
It appears that returning 0xC when the end of the disc (lead out) is reached makes the CD player now behave correctly and automatically stop CD playback at the end of the last track.
And as expected, it also fixes the issue in Snatcher I mentioned !
Other undocumented status (namely $06, $07, $08, $0A, $B, $D, $E, $F) seem to indicate an error and will make the CD player to clear disc infos and either send a Tray Open command or indicates Tray is open.
By analyzing the BIOS, I figured there were a bunch of undocumented CDD status (returned in RS0) and I ended up testing the ones that were not known yet.
It appears that returning 0xC when the end of the disc (lead out) is reached makes the CD player now behave correctly and automatically stop CD playback at the end of the last track.
And as expected, it also fixes the issue in Snatcher I mentioned !
Other undocumented status (namely $06, $07, $08, $0A, $B, $D, $E, $F) seem to indicate an error and will make the CD player to clear disc infos and either send a Tray Open command or indicates Tray is open.
Ok, I figured the VU meter trick as well, it appears that like for Lead Out detection, subcode emulation is not required and CDD returns all the needed infos in undocumented Receive Status (RSx) bytes.
Actually, I figured it by analyzing the BIOS and data returned by the CDBSTAT command. If you look at the available BIOS manual, you will notice that this command returns a bunch of informations about the CDD status, which include current track absolute time, relative time, etc... and some "flags" detailed as below:
BIT3: unused (0)
BIT2: digital audio (0) or data (1)
BIT1: track encoded with pre-emphasis OFF (0) or ON(1)
BIT0: Mute OFF (0) or ON,-12dB (1)
BIT1 & BIT2 are most likely retrieved from Q-channel subcode control field
BIT0 might be related to the CD DSP (CXD1167Q), I'm not sure, there is no field in subcode channels related to audio mute. It seems to have some effect on VU meter peak levels.
The interesting thing is that these "flag" bytes are the EXACT copy of the RS8 bytes that are returned by CDD when the Report Code (associated to RS1 value, RS0 being the Status Code) is $00 (RS2-RS7 = absolute time), $01 (RS2-RS7 = relative time infos) and $04 (RS2-RS5 = first & last track numbers).
And as you would expect, returning $04 in RS8 when RS1 is set to $00 or $01 and current track is the data track actually makes the CD player not displaying the VU meter for track 01. When RS1 is set to $02, the flags correspond to Lead In so RS8 is most likely fixed to $00.
On a side note, here are the others undocumented fields (in bold) I figured from looking at CDBSTAT:
- when RS1 is set to $02, RS2-RS3 returns current track and RS6 returns Disk Control code (no idea what this is), other bytes are undefined
- when RS1 is set to $04, RS2-RS5 return first & last track numbers, RS8 returns Lead In flags and RS6-RS7 return the Drive Version (in BCD format)
NB: it is already documented but, as a reminder, report code (RS1) is changed by sending a 0x02 command to CDD with the report code being set in TC1 byte.
Actually, I figured it by analyzing the BIOS and data returned by the CDBSTAT command. If you look at the available BIOS manual, you will notice that this command returns a bunch of informations about the CDD status, which include current track absolute time, relative time, etc... and some "flags" detailed as below:
BIT3: unused (0)
BIT2: digital audio (0) or data (1)
BIT1: track encoded with pre-emphasis OFF (0) or ON(1)
BIT0: Mute OFF (0) or ON,-12dB (1)
BIT1 & BIT2 are most likely retrieved from Q-channel subcode control field
BIT0 might be related to the CD DSP (CXD1167Q), I'm not sure, there is no field in subcode channels related to audio mute. It seems to have some effect on VU meter peak levels.
The interesting thing is that these "flag" bytes are the EXACT copy of the RS8 bytes that are returned by CDD when the Report Code (associated to RS1 value, RS0 being the Status Code) is $00 (RS2-RS7 = absolute time), $01 (RS2-RS7 = relative time infos) and $04 (RS2-RS5 = first & last track numbers).
And as you would expect, returning $04 in RS8 when RS1 is set to $00 or $01 and current track is the data track actually makes the CD player not displaying the VU meter for track 01. When RS1 is set to $02, the flags correspond to Lead In so RS8 is most likely fixed to $00.
On a side note, here are the others undocumented fields (in bold) I figured from looking at CDBSTAT:
- when RS1 is set to $02, RS2-RS3 returns current track and RS6 returns Disk Control code (no idea what this is), other bytes are undefined
- when RS1 is set to $04, RS2-RS5 return first & last track numbers, RS8 returns Lead In flags and RS6-RS7 return the Drive Version (in BCD format)
NB: it is already documented but, as a reminder, report code (RS1) is changed by sending a 0x02 command to CDD with the report code being set in TC1 byte.