mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-25 18:51:49 +01:00
[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:
parent
7717557cb8
commit
a6002bb254
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 |
163
core/cd_hw/cdd.c
163
core/cd_hw/cdd.c
@ -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,86 +1828,86 @@ 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)
|
||||||
{
|
|
||||||
/* current track index */
|
|
||||||
int index = cdd.index;
|
|
||||||
|
|
||||||
/* fast-forward or fast-rewind */
|
|
||||||
cdd.lba += cdd.scanOffset;
|
|
||||||
|
|
||||||
/* check current track limits */
|
|
||||||
if (cdd.lba >= cdd.toc.tracks[index].end)
|
|
||||||
{
|
{
|
||||||
/* next track */
|
/* current track index */
|
||||||
index++;
|
int index = cdd.index;
|
||||||
|
|
||||||
/* check disc limits */
|
/* fast-forward or fast-rewind */
|
||||||
if (index < cdd.toc.last)
|
cdd.lba += cdd.scanOffset;
|
||||||
|
|
||||||
|
/* check current track limits */
|
||||||
|
if (cdd.lba >= cdd.toc.tracks[index].end)
|
||||||
{
|
{
|
||||||
/* skip directly to next track start position */
|
/* next track */
|
||||||
cdd.lba = cdd.toc.tracks[index].start;
|
index++;
|
||||||
|
|
||||||
|
/* check disc limits */
|
||||||
|
if (index < cdd.toc.last)
|
||||||
|
{
|
||||||
|
/* skip directly to next track start position */
|
||||||
|
cdd.lba = cdd.toc.tracks[index].start;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* end of disc */
|
||||||
|
cdd.lba = cdd.toc.end;
|
||||||
|
cdd.index = cdd.toc.last;
|
||||||
|
cdd.status = CD_END;
|
||||||
|
|
||||||
|
/* no audio track playing */
|
||||||
|
scd.regs[0x36>>1].byte.h = 0x01;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cdd.lba < cdd.toc.tracks[index].start)
|
||||||
|
{
|
||||||
|
/* check disc limits */
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
/* previous track */
|
||||||
|
index--;
|
||||||
|
|
||||||
|
/* skip directly to previous track end position */
|
||||||
|
cdd.lba = cdd.toc.tracks[index].end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* start of first track */
|
||||||
|
cdd.lba = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* seek to current subcode position */
|
||||||
|
if (cdd.toc.sub)
|
||||||
|
{
|
||||||
|
cdStreamSeek(cdd.toc.sub, cdd.lba * 96, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* current track is an audio track ? */
|
||||||
|
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
|
||||||
|
{
|
||||||
|
/* seek to current track sector */
|
||||||
|
cdd_seek_audio(index, cdd.lba);
|
||||||
|
|
||||||
|
/* audio track playing */
|
||||||
|
scd.regs[0x36>>1].byte.h = 0x00;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* end of disc */
|
|
||||||
cdd.lba = cdd.toc.end;
|
|
||||||
cdd.index = cdd.toc.last;
|
|
||||||
cdd.status = CD_END;
|
|
||||||
|
|
||||||
/* no audio track playing */
|
/* no audio track playing */
|
||||||
scd.regs[0x36>>1].byte.h = 0x01;
|
scd.regs[0x36>>1].byte.h = 0x01;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (cdd.lba < cdd.toc.tracks[index].start)
|
|
||||||
{
|
|
||||||
/* check disc limits */
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
/* previous track */
|
|
||||||
index--;
|
|
||||||
|
|
||||||
/* skip directly to previous track end position */
|
/* udpate current track index */
|
||||||
cdd.lba = cdd.toc.tracks[index].end;
|
cdd.index = index;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* start of first track */
|
|
||||||
cdd.lba = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seek to current subcode position */
|
|
||||||
if (cdd.toc.sub)
|
|
||||||
{
|
|
||||||
cdStreamSeek(cdd.toc.sub, cdd.lba * 96, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* current track is an audio track ? */
|
|
||||||
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
|
|
||||||
{
|
|
||||||
/* seek to current track sector */
|
|
||||||
cdd_seek_audio(index, cdd.lba);
|
|
||||||
|
|
||||||
/* audio track playing */
|
|
||||||
scd.regs[0x36>>1].byte.h = 0x00;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no audio track playing */
|
|
||||||
scd.regs[0x36>>1].byte.h = 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* udpate current track 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user