I wanted to share the process I've gone through over the last two days trying to understand why the CDDA background music in my game HarleQuest! refused to loop. I came from knowing next to nothing about CDDA or CD layouts and everything I've learned about it has been over the past couple of days, so if I get something wrong please bear with me (and correct me!).
First, I always test HarleQuest! on a Dreamcast that's fitted with a GDEMU clone. This time, I happened not to test it for long enough to hear the music loop on real hardware. I did test that the music loops in an emulator which worked fine.
After releasing a new demo build, multiple people got in touch saying that the music was either stopping or hanging on a single tone after the first playthrough. I tested this on my DC with GDEMU and yep, it didn't loop - just silence.
I'm using the cdrom_cdda_play() KallistiOS function as follows:
Code: Select all
// Start at track 1, stop after track 1, loop 15 times (infinite):
result = cdrom_cdda_play(1, 1, 15, CDDA_TRACKS);
I built the disc image with the mkdcdisc tool: https://gitlab.com/simulant/mkdcdisc
Here is the command I used:
Code: Select all
./build/mkdcdisc -a "Kilgariff Technologies Limited" --cdda bgm.wav -e harlequest.elf -n "harlequest" -o /home/ross/harlequest.cdi
At first I thought it was a bug in KallistiOS, so I looked into the implementation of cdrom_cdda_play:
https://github.com/KallistiOS/KallistiO ... rom.c#L388
Code: Select all
int cdrom_cdda_play(uint32 start, uint32 end, uint32 repeat, int mode) {
struct {
int start;
int end;
int repeat;
} params;
int rv = ERR_OK;
/* Limit to 0-15 */
if(repeat > 15)
repeat = 15;
params.start = start;
params.end = end;
params.repeat = repeat;
mutex_lock(&_g1_ata_mutex);
if(mode == CDDA_TRACKS)
rv = cdrom_exec_cmd(CMD_PLAY, ¶ms);
else if(mode == CDDA_SECTORS)
rv = cdrom_exec_cmd(CMD_PLAY2, ¶ms);
mutex_unlock(&_g1_ata_mutex);
return rv;
}
I noticed there was a second option to play using sector ranges instead of tracks (CDDA_SECTORS) and a KOS function to get the TOC (Table of Contents) via a syscall, so I wrote a small piece of code to display all the tracks in the TOC:
Code: Select all
// Check our CD's table of contents:
{
CDROM_TOC toc;
result = cdrom_read_toc(&toc, 0);
if (result == ERR_OK)
{
for (int track = TOC_TRACK(toc.first); track <= TOC_TRACK(toc.last); ++track)
{
int idx = track - 1;
uint32_t entry = toc.entry[idx];
printf("========= TOC Entry %d\n", idx);
printf("Entry LBA: %d\n", (int) TOC_LBA(entry));
printf("Entry ADR: %d\n", (int) TOC_ADR(entry));
printf("Entry CTRL: %d\n", (int) TOC_CTRL(entry));
printf("Entry TRACK: %d\n", (int) TOC_TRACK(entry));
if (TOC_CTRL(entry) == 0)
{
printf("This is an audio track\n");
}
}
}
}
Code: Select all
========= Entry 0
Entry LBA: 150
Entry ADR: 1
Entry CTRL: 0
Entry TRACK: 0
This is an audio track
========= Entry 1
Entry LBA: 22600
Entry ADR: 1
Entry CTRL: 4
Entry TRACK: 0
On a whim I tried adding a second audio track, and lo and behold, that allowed the first track to loop successfully. It was now the second audio track that wouldn't loop.
Next I thought it might be a bug with mkdcdisc, but it was clearly a valid .CDI image that ImgBurn could parse and display. I went through the mkdcdisc code and there were a couple red herrings due to my own lack of understanding, but in the end it all looked fine. To help with this, Kazade (author of mkdcdisc) booted up Driving Strikers and checked whether the last track looped - it did! So that implied something strange with my setup. He sent me a .CDI of the game to test, but for me the last track did not loop and was just followed by silence.
The only difference between our setups is that I am using a GDEMU clone and he is using a real GDROM drive. So I burnt a HarleQuest! test disc and tried it on a Dreamcast with a real GDROM drive - and the music loops fine.
After looking around, I then found a reddit post in which a user mentions background music not looping on their GDEMU clone: https://www.reddit.com/r/dreamcast/comm ... emu_clone/
All the reports of music not looping had come from people either with GDEMU or MODE installed, so it seems to be issue with both of these. It hasn't been tested on an official GDEMU yet.
If anyone can shed light on why this might be that would be awesome. In the meantime, I'm just going to add an extra blank track to the end of the audio session and move on to other things.
Thanks,
Ross