[Core/CD] improved robustness of CDD seeking delay emulation (fixes Krikzz's mcd-verificator CDC INIT endless loop following dd619513a4)

This commit is contained in:
ekeeke 2024-09-01 14:39:09 +02:00
parent 7717557cb8
commit a6002bb254
5 changed files with 94 additions and 70 deletions

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

@ -207,6 +207,9 @@ void cdd_reset(void)
/* reset status */ /* reset status */
cdd.status = cdd.loaded ? CD_TOC : NO_DISC; cdd.status = cdd.loaded ? CD_TOC : NO_DISC;
/* reset pending flag */
cdd.pending = 0;
/* reset CD-DA fader (full volume) */ /* reset CD-DA fader (full volume) */
cdd.fader[0] = cdd.fader[1] = 0x400; cdd.fader[0] = cdd.fader[1] = 0x400;
@ -218,6 +221,7 @@ int cdd_context_save(uint8 *state)
{ {
int bufferptr = 0; int bufferptr = 0;
unsigned int offset = 0; unsigned int offset = 0;
uint8 tmp8;
save_param(&cdd.cycles, sizeof(cdd.cycles)); save_param(&cdd.cycles, sizeof(cdd.cycles));
save_param(&cdd.latency, sizeof(cdd.latency)); save_param(&cdd.latency, sizeof(cdd.latency));
@ -225,7 +229,10 @@ int cdd_context_save(uint8 *state)
save_param(&cdd.lba, sizeof(cdd.lba)); save_param(&cdd.lba, sizeof(cdd.lba));
save_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
save_param(&cdd.fader, sizeof(cdd.fader)); save_param(&cdd.fader, sizeof(cdd.fader));
save_param(&cdd.status, sizeof(cdd.status));
/* 4-bit pending flag and 4-bit CDD status are saved together (to maintain backward savestate compatibility) */
tmp8 = cdd.status | (cdd.pending << 4);
save_param(&tmp8, sizeof(tmp8));
/* current track is an audio track ? */ /* current track is an audio track ? */
if (cdd.toc.tracks[cdd.index].type == TYPE_AUDIO) if (cdd.toc.tracks[cdd.index].type == TYPE_AUDIO)
@ -264,6 +271,7 @@ int cdd_context_load(uint8 *state, char *version)
{ {
unsigned int offset, lba, index; unsigned int offset, lba, index;
int bufferptr = 0; int bufferptr = 0;
uint8 tmp8;
load_param(&cdd.cycles, sizeof(cdd.cycles)); load_param(&cdd.cycles, sizeof(cdd.cycles));
load_param(&cdd.latency, sizeof(cdd.latency)); load_param(&cdd.latency, sizeof(cdd.latency));
@ -271,7 +279,11 @@ int cdd_context_load(uint8 *state, char *version)
load_param(&lba, sizeof(cdd.lba)); load_param(&lba, sizeof(cdd.lba));
load_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
load_param(&cdd.fader, sizeof(cdd.fader)); load_param(&cdd.fader, sizeof(cdd.fader));
load_param(&cdd.status, sizeof(cdd.status));
/* 4-bit pending flag and 4-bit CDD status are saved together (to maintain backward savestate compatibility) */
load_param(&tmp8, sizeof(tmp8));
cdd.status = tmp8 & 0xf;
cdd.pending = tmp8 >> 4;
/* update current sector */ /* update current sector */
cdd.lba = lba; cdd.lba = lba;
@ -1816,7 +1828,6 @@ void cdd_update(void)
{ {
/* CDC decoder is still running while disc is not being read (fixes MCD-verificator CDC Flags Test #30) */ /* CDC decoder is still running while disc is not being read (fixes MCD-verificator CDC Flags Test #30) */
cdc_decoder_update(0); cdc_decoder_update(0);
}
/* scanning disc */ /* scanning disc */
if (cdd.status == CD_SCAN) if (cdd.status == CD_SCAN)
@ -1893,9 +1904,10 @@ 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) */ /* check if seeking is pending */
if (scd.regs[0x38>>1].byte.h == CD_SEEK) if (cdd.pending)
{ {
/* reset track index */ /* reset track index */
int index = 0; int index = 0;
@ -1963,8 +1975,11 @@ void cdd_update(void)
/* no audio track playing (yet) */ /* no audio track playing (yet) */
scd.regs[0x36>>1].byte.h = 0x01; 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) */ /* update CDD status with pending end status (will be reported to host once seeking has ended) */
cdd.status = scd.regs[0x42>>1].byte.h & 0x05; cdd.status = cdd.pending;
/* clear pending flag */
cdd.pending = 0;
} }
} }
@ -2149,6 +2164,10 @@ void cdd_process(void)
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].w = ~(CD_SEEK + 0x0f) & 0x0f; scd.regs[0x40>>1].w = ~(CD_SEEK + 0x0f) & 0x0f;
/* seeking should start with at least one interrupt delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
/* so pending flag is set (with CDD end status) to indicate seeking is pending */
cdd.pending = CD_PLAY;
return; return;
} }
@ -2160,6 +2179,10 @@ void cdd_process(void)
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].w = ~(CD_SEEK + 0x0f) & 0x0f; scd.regs[0x40>>1].w = ~(CD_SEEK + 0x0f) & 0x0f;
/* seeking should start with at least one interrupt delay (same as 'Play' command) */
/* so pending flag is set (with CDD end status) to indicate seeking is pending */
cdd.pending = CD_PAUSE;
return; return;
} }

View File

@ -117,6 +117,7 @@ typedef struct
int scanOffset; int scanOffset;
uint16 fader[2]; uint16 fader[2];
uint8 status; uint8 status;
uint8 pending;
uint16 sectorSize; uint16 sectorSize;
toc_t toc; toc_t toc;
#if defined(USE_LIBCHDR) #if defined(USE_LIBCHDR)