[Core/CD] fixed CDD seeking start delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro)

This commit is contained in:
ekeeke 2024-04-20 18:48:25 +02:00
parent 351d052e84
commit dd619513a4
5 changed files with 76 additions and 123 deletions

View File

@ -58,9 +58,10 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
* fixed byte access to font data registers * fixed byte access to font data registers
* fixed memory mode register bits masking when read from MAIN-CPU and SUB-CPU (verified on real hardware, cf. Krikzz's mcd-verificator) * fixed memory mode register bits masking when read from MAIN-CPU and SUB-CPU (verified on real hardware, cf. Krikzz's mcd-verificator)
* fixed pending level 1 interrupts when GFX interrupt is disabled (fixes random freezes when exiting "Batman Returns" option menu) * fixed pending level 1 interrupts when GFX interrupt is disabled (fixes random freezes when exiting "Batman Returns" option menu)
* fixed CDD seek command again (Final Fight CD freeze with model 2 BIOS) * fixed CDD seek command again (fixes Final Fight CD freeze with model 2 BIOS)
* fixed CDD status reported during seek/access time (fixes sound effect synchronization issue in Bari Arm) * fixed CDD status reported during seek/access time (fixes sound effect synchronization issue in Bari Arm)
* fixed CDD position reset when disc is stopped (fixes random freezes in Spiderman vs Kingpin when switching between audio tracks) * fixed CDD position reset when disc is stopped (fixes random freezes in Spiderman vs Kingpin when switching between audio tracks)
* fixed CDD seeking start delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
* fixed word access to CDD control register (fixes spurious audio track playback on startup with Mode 1 patched games using MSU-MD driver) * fixed word access to CDD control register (fixes spurious audio track playback on startup with Mode 1 patched games using MSU-MD driver)
* fixed CD communication registers state on peripheral reset (fixes SUB-CPU side initialization in MSU-MD sample demo and some Mode 1 patched games using MSU-MD driver) * fixed CD communication registers state on peripheral reset (fixes SUB-CPU side initialization in MSU-MD sample demo and some Mode 1 patched games using MSU-MD driver)
* fixed 32x32 pixels stamp index masking during GFX operation (fixes graphics rotation/scaling effects in "Chuck Rock II - Son of Chuck") * fixed 32x32 pixels stamp index masking during GFX operation (fixes graphics rotation/scaling effects in "Chuck Rock II - Son of Chuck")

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 4.0 MiB

View File

@ -1893,6 +1893,79 @@ void cdd_update(void)
/* udpate current track index */ /* udpate current track index */
cdd.index = index; cdd.index = index;
} }
/* seeking should start with at least one interrupt delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
if (scd.regs[0x38>>1].byte.h == CD_SEEK)
{
/* reset track index */
int index = 0;
/* new LBA position */
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
/* CD drive latency */
if (!cdd.latency)
{
/* Fixes a few games hanging because they expect data to be read with some delay */
/* Wolf Team games (Annet Futatabi, Aisle Lord, Cobra Command, Earnest Evans, Road Avenger & Time Gal) need at least 11 interrupts delay */
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 11 is OK) */
/* By default, at least two interrupts latency is required by current emulation model (BIOS hangs otherwise) */
cdd.latency = 2 + 9*config.cd_latency;
}
/* CD drive seek time */
/* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
/* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
/* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
/* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
/* It also works fine for Switch/Panic! intro (at least 30 interrupts are needed while seeking from 00:05:63 */
/* to 24:03:19 in Switch or when seeking from 00:05:60 to 24:06:07 in Panic!). */
if (lba > cdd.lba)
{
cdd.latency += (((lba - cdd.lba) * 120 * config.cd_latency) / 270000);
}
else
{
cdd.latency += (((cdd.lba - lba) * 120 * config.cd_latency) / 270000);
}
/* update current LBA */
cdd.lba = lba;
/* get track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last))
index++;
/* audio track ? */
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
{
/* stay within track limits when seeking files */
if (lba < cdd.toc.tracks[index].start)
{
lba = cdd.toc.tracks[index].start;
}
/* seek to current track sector */
cdd_seek_audio(index, lba);
}
/* update current track index */
cdd.index = index;
/* seek to current subcode position */
if (cdd.toc.sub)
{
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
}
/* no audio track playing (yet) */
scd.regs[0x36>>1].byte.h = 0x01;
/* update CDD status to either PLAY or PAUSE depending on host command (will be reported to host once seeking has ended) */
cdd.status = scd.regs[0x42>>1].byte.h & 0x05;
}
} }
void cdd_process(void) void cdd_process(void)
@ -2069,73 +2142,7 @@ void cdd_process(void)
case 0x03: /* Play */ case 0x03: /* Play */
{ {
/* reset track index */ /* RS0 should indicate seeking until drive is ready (fixes audio delay in Bari Arm) */
int index = 0;
/* new LBA position */
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
/* CD drive latency */
if (!cdd.latency)
{
/* Fixes a few games hanging because they expect data to be read with some delay */
/* Wolf Team games (Annet Futatabi, Aisle Lord, Cobra Command, Earnest Evans, Road Avenger & Time Gal) need at least 11 interrupts delay */
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 11 is OK) */
/* By default, at least two interrupts latency is required by current emulation model (BIOS hangs otherwise) */
cdd.latency = 2 + 9*config.cd_latency;
}
/* CD drive seek time */
/* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
/* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
/* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
/* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
if (lba > cdd.lba)
{
cdd.latency += (((lba - cdd.lba) * 120 * config.cd_latency) / 270000);
}
else
{
cdd.latency += (((cdd.lba - lba) * 120 * config.cd_latency) / 270000);
}
/* update current LBA */
cdd.lba = lba;
/* get track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
/* audio track ? */
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
{
/* stay within track limits when seeking files */
if (lba < cdd.toc.tracks[index].start)
{
lba = cdd.toc.tracks[index].start;
}
/* seek to current track sector */
cdd_seek_audio(index, lba);
}
/* update current track index */
cdd.index = index;
/* seek to current subcode position */
if (cdd.toc.sub)
{
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
}
/* no audio track playing (yet) */
scd.regs[0x36>>1].byte.h = 0x01;
/* update status (reported to host once seeking has ended) */
cdd.status = CD_PLAY;
/* RS0 should indicates seeking until drive is ready (fixes audio delay in Bari Arm) */
/* RS1=0xf to invalidate track infos in RS2-RS8 until drive is ready (fixes Snatcher Act 2 start cutscene) */ /* RS1=0xf to invalidate track infos in RS2-RS8 until drive is ready (fixes Snatcher Act 2 start cutscene) */
scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f; scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
scd.regs[0x3a>>1].w = 0x0000; scd.regs[0x3a>>1].w = 0x0000;
@ -2147,61 +2154,6 @@ void cdd_process(void)
case 0x04: /* Seek */ case 0x04: /* Seek */
{ {
/* reset track index */
int index = 0;
/* new LBA position */
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
/* CD drive seek time */
/* We are using similar linear model as above, although still not exactly accurate, */
/* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
/* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
if (lba > cdd.lba)
{
cdd.latency = ((lba - cdd.lba) * 120 * config.cd_latency) / 270000;
}
else
{
cdd.latency = ((cdd.lba - lba) * 120 * config.cd_latency) / 270000;
}
/* update current LBA */
cdd.lba = lba;
/* get current track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
/* audio track ? */
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
{
/* stay within track limits when seeking files */
if (lba < cdd.toc.tracks[index].start)
{
lba = cdd.toc.tracks[index].start;
}
/* seek to current track sector */
cdd_seek_audio(index, lba);
}
/* update current track index */
cdd.index = index;
/* seek to current subcode position */
if (cdd.toc.sub)
{
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
}
/* no audio track playing */
scd.regs[0x36>>1].byte.h = 0x01;
/* update status (reported to host once seeking has ended) */
cdd.status = CD_PAUSE;
/* RS1=0xf to invalidate track infos in RS2-RS8 while seeking (fixes Final Fight CD intro when seek time is emulated) */ /* RS1=0xf to invalidate track infos in RS2-RS8 while seeking (fixes Final Fight CD intro when seek time is emulated) */
scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f; scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
scd.regs[0x3a>>1].w = 0x0000; scd.regs[0x3a>>1].w = 0x0000;