[SCD] improved CDD emulation (fixes Snatcher freezing at the end of Act 2)

This commit is contained in:
EkeEke 2012-10-22 16:08:21 +02:00
parent 4a41ee1525
commit ba4613df57
2 changed files with 28 additions and 9 deletions

View File

@ -357,7 +357,7 @@ int cdd_load(char *filename, char *header)
if (!(memcmp(lptr, "FILE", 4))) if (!(memcmp(lptr, "FILE", 4)))
{ {
/* check supported file types */ /* check supported file types */
if (!strstr(lptr," BINARY") && !strstr(lptr," WAVE")) if (!strstr(lptr," BINARY") && !strstr(lptr," WAV"))
{ {
/* unsupported file type */ /* unsupported file type */
break; break;
@ -375,7 +375,7 @@ int cdd_load(char *filename, char *header)
if (ptr - fname) ptr++; if (ptr - fname) ptr++;
/* append filename characters after filepath */ /* append filename characters after filepath */
while ((*lptr != '\"') && memcmp(lptr, " BINARY", 7) && memcmp(lptr, " WAVE", 5)) while ((*lptr != '\"') && memcmp(lptr, " BINARY", 7) && memcmp(lptr, " WAV", 4))
{ {
*ptr++ = *lptr++; *ptr++ = *lptr++;
} }
@ -636,6 +636,9 @@ int cdd_load(char *filename, char *header)
} }
} }
/* Lead-out */
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
/* CD loaded */ /* CD loaded */
cdd.loaded = 1; cdd.loaded = 1;
return 1; return 1;
@ -839,6 +842,7 @@ void cdd_update(void)
} }
else else
{ {
cdd.status = CD_END;
return; return;
} }
@ -898,6 +902,10 @@ void cdd_update(void)
} }
else if (cdd.index >= cdd.toc.last) else if (cdd.index >= cdd.toc.last)
{ {
/* no AUDIO track playing */
scd.regs[0x36>>1].byte.h = 0x01;
/* end of disc */
cdd.index = cdd.toc.last; cdd.index = cdd.toc.last;
cdd.lba = cdd.toc.end; cdd.lba = cdd.toc.end;
} }
@ -905,6 +913,9 @@ void cdd_update(void)
/* seek to current block */ /* seek to current block */
if (!cdd.index) if (!cdd.index)
{ {
/* no AUDIO track playing */
scd.regs[0x36>>1].byte.h = 0x01;
fseek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET); fseek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
} }
else if (cdd.toc.tracks[cdd.index].fd) else if (cdd.toc.tracks[cdd.index].fd)
@ -961,7 +972,7 @@ void cdd_process(void)
scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60];
scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60];
scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)];
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00; /* TODO: check what is returned in RS8 (note: bit 1 is checked by BIOS) */
break; break;
} }
@ -972,7 +983,7 @@ void cdd_process(void)
scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60];
scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60];
scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)];
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00; /* TODO: check what is returned in RS8 */
break; break;
} }
@ -981,7 +992,7 @@ void cdd_process(void)
scd.regs[0x38>>1].w = (cdd.status << 8) | 0x02; scd.regs[0x38>>1].w = (cdd.status << 8) | 0x02;
scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A; scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A;
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000; /* TODO: check what is returned in RS6 */
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00;
break; break;
} }
@ -1002,8 +1013,8 @@ void cdd_process(void)
scd.regs[0x38>>1].w = (cdd.status << 8) | 0x04; scd.regs[0x38>>1].w = (cdd.status << 8) | 0x04;
scd.regs[0x3a>>1].w = 0x0001; scd.regs[0x3a>>1].w = 0x0001;
scd.regs[0x3c>>1].w = lut_BCD_16[cdd.toc.last]; scd.regs[0x3c>>1].w = lut_BCD_16[cdd.toc.last];
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000; /* TODO: check what is returned in RS6-RS7 */
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00; /* TODO: check what is returned in RS8 */
break; break;
} }
@ -1018,7 +1029,7 @@ void cdd_process(void)
scd.regs[0x40>>1].byte.h = track % 10; scd.regs[0x40>>1].byte.h = track % 10;
if (track == 1) if (track == 1)
{ {
/* data track */ /* RS6 bit 3 is set for DATA track */
scd.regs[0x3e>>1].byte.h |= 0x08; scd.regs[0x3e>>1].byte.h |= 0x08;
} }
break; break;
@ -1081,7 +1092,14 @@ void cdd_process(void)
/* Some delay is also needed when playing AUDIO tracks located at the end of the disc (ex: Sonic CD intro) */ /* Some delay is also needed when playing AUDIO tracks located at the end of the disc (ex: Sonic CD intro) */
/* max. seek time = 1.5s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc */ /* max. seek time = 1.5s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc */
/* Note: this is only a rough approximation, on real hardware, drive seek time is much likely not linear */ /* Note: this is only a rough approximation, on real hardware, drive seek time is much likely not linear */
cdd.latency += ((abs(lba - cdd.lba) * 120) / 270000); if (lba < cdd.lba)
{
cdd.latency += (((cdd.lba - lba) * 120) / 270000);
}
else
{
cdd.latency += (((lba - cdd.lba) * 120) / 270000);
}
/* seek AUDIO track */ /* seek AUDIO track */
if (lba < cdd.toc.tracks[index].start) if (lba < cdd.toc.tracks[index].start)

View File

@ -50,6 +50,7 @@
#define CD_READY 0x04 #define CD_READY 0x04
#define CD_OPEN 0x05 #define CD_OPEN 0x05
#define CD_STOP 0x09 #define CD_STOP 0x09
#define CD_END 0x0C
/* CD blocks scanning speed */ /* CD blocks scanning speed */
#define CD_SCAN_SPEED 10 #define CD_SCAN_SPEED 10