mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-04 18:05:06 +01:00
[Core/CD]
.added build-in TOC support for a few games that hang if no audio tracks are found or used .modified CD access/seek time emulation .improved CPU polling detection .improved SUB & MAIN-CPU synchronization (fixes Dracula Unleashed when using Model 2 US BIOS) .added missing reinitialization of MAIN-CPU PRG-RAM bank on reset
This commit is contained in:
parent
c9fb127730
commit
325f6dd5a7
@ -90,6 +90,26 @@ static const uint32 toc_shadow[15] =
|
|||||||
11637, 2547, 2521, 3856, 900
|
11637, 2547, 2521, 3856, 900
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint32 toc_dungeon[13] =
|
||||||
|
{
|
||||||
|
2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
|
||||||
|
3325, 6825, 25275
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32 toc_ffight[26] =
|
||||||
|
{
|
||||||
|
11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764,
|
||||||
|
9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024,
|
||||||
|
14562, 10320, 8627, 3795, 3047
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32 toc_ffightj[29] =
|
||||||
|
{
|
||||||
|
11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763,
|
||||||
|
9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026,
|
||||||
|
14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052
|
||||||
|
};
|
||||||
|
|
||||||
/* supported WAVE file header (16-bit stereo samples @44.1kHz) */
|
/* supported WAVE file header (16-bit stereo samples @44.1kHz) */
|
||||||
static const unsigned char waveHeader[32] =
|
static const unsigned char waveHeader[32] =
|
||||||
{
|
{
|
||||||
@ -641,6 +661,45 @@ int cdd_load(char *filename, char *header)
|
|||||||
}
|
}
|
||||||
while (cdd.toc.last < 15);
|
while (cdd.toc.last < 15);
|
||||||
}
|
}
|
||||||
|
else if (strstr(header + 0x180,"T-143025") != NULL)
|
||||||
|
{
|
||||||
|
/* Dungeon Explorer */
|
||||||
|
cdd.toc.last = cdd.toc.end = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||||
|
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
|
||||||
|
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||||
|
cdd.toc.last++;
|
||||||
|
}
|
||||||
|
while (cdd.toc.last < 13);
|
||||||
|
}
|
||||||
|
else if (strstr(header + 0x180,"MK-4410") != NULL)
|
||||||
|
{
|
||||||
|
/* Final Fight CD (USA, Europe) */
|
||||||
|
cdd.toc.last = cdd.toc.end = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||||
|
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
|
||||||
|
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||||
|
cdd.toc.last++;
|
||||||
|
}
|
||||||
|
while (cdd.toc.last < 26);
|
||||||
|
}
|
||||||
|
else if (strstr(header + 0x180,"G-6013") != NULL)
|
||||||
|
{
|
||||||
|
/* Final Fight CD (Japan) */
|
||||||
|
cdd.toc.last = cdd.toc.end = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||||
|
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
|
||||||
|
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||||
|
cdd.toc.last++;
|
||||||
|
}
|
||||||
|
while (cdd.toc.last < 29);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* default TOC (99 tracks & 2s per audio tracks) */
|
/* default TOC (99 tracks & 2s per audio tracks) */
|
||||||
@ -1081,11 +1140,24 @@ void cdd_process(void)
|
|||||||
if (!cdd.latency)
|
if (!cdd.latency)
|
||||||
{
|
{
|
||||||
/* Fixes a few games hanging during intro because they expect data to be read with some delay */
|
/* Fixes a few games hanging during intro because they expect data to be read with some delay */
|
||||||
/* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
|
|
||||||
/* Radical Rex needs at least one interrupt delay */
|
/* Radical Rex needs at least one interrupt delay */
|
||||||
/* Jeopardy needs at least 9 interrupts delay */
|
/* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
|
||||||
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay */
|
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 here is OK) */
|
||||||
cdd.latency = 13;
|
/* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 7 interrupts delay (+ seek time) seems OK */
|
||||||
|
cdd.latency = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CD drive seek time */
|
||||||
|
/* Some delay is especially 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 */
|
||||||
|
/* Note: this is only a rough approximation, on real hardware, drive seek time is much likely not linear */
|
||||||
|
if (lba < cdd.lba)
|
||||||
|
{
|
||||||
|
cdd.latency += (((cdd.lba - lba) * 120) / 270000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cdd.latency += (((lba - cdd.lba) * 120) / 270000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update current track index */
|
/* update current track index */
|
||||||
@ -1110,19 +1182,6 @@ void cdd_process(void)
|
|||||||
}
|
}
|
||||||
else if (cdd.toc.tracks[index].fd)
|
else if (cdd.toc.tracks[index].fd)
|
||||||
{
|
{
|
||||||
/* CD drive seek time */
|
|
||||||
/* 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 */
|
|
||||||
/* Note: this is only a rough approximation, on real hardware, drive seek time is much likely not linear */
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +212,7 @@ static void s68k_poll_detect(reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* restart SUB-CPU polling detection */
|
/* restart SUB-CPU polling detection */
|
||||||
s68k.poll.cycle = s68k.cycles + 320;
|
s68k.poll.cycle = s68k.cycles + 392;
|
||||||
s68k.poll.pc = s68k.pc;
|
s68k.poll.pc = s68k.pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ static unsigned int scd_read_word(unsigned int address)
|
|||||||
/* relative MAIN-CPU cycle counter */
|
/* relative MAIN-CPU cycle counter */
|
||||||
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
|
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
|
||||||
|
|
||||||
/* sync MAIN-CPU with SUB-CPU */
|
/* sync MAIN-CPU with SUB-CPU (Mighty Morphin Power Rangers) */
|
||||||
if (!m68k.stopped && (m68k.cycles < cycles))
|
if (!m68k.stopped && (m68k.cycles < cycles))
|
||||||
{
|
{
|
||||||
m68k_run(cycles);
|
m68k_run(cycles);
|
||||||
@ -1062,7 +1062,7 @@ void scd_init(void)
|
|||||||
{
|
{
|
||||||
if (i & 2)
|
if (i & 2)
|
||||||
{
|
{
|
||||||
/* PRG-RAM (first 128KB bank, mirrored) */
|
/* $020000-$03FFFF (resp. $420000-$43FFFF): PRG-RAM (first 128KB bank, mirrored each 256KB) */
|
||||||
m68k.memory_map[i].base = scd.prg_ram + ((i & 1) << 16);
|
m68k.memory_map[i].base = scd.prg_ram + ((i & 1) << 16);
|
||||||
m68k.memory_map[i].read8 = NULL;
|
m68k.memory_map[i].read8 = NULL;
|
||||||
m68k.memory_map[i].read16 = NULL;
|
m68k.memory_map[i].read16 = NULL;
|
||||||
@ -1074,7 +1074,8 @@ void scd_init(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* internal ROM (128KB mirrored) (Flux expects it to be mapped at $440000-$45FFFF) */
|
/* $000000-$01FFFF (resp. $400000-$41FFFF): internal ROM (128KB, mirrored each 256KB) */
|
||||||
|
/* NB: Flux expects it to be mapped at $440000-$45FFFF */
|
||||||
m68k.memory_map[i].base = scd.bootrom + ((i & 1) << 16);
|
m68k.memory_map[i].base = scd.bootrom + ((i & 1) << 16);
|
||||||
m68k.memory_map[i].read8 = NULL;
|
m68k.memory_map[i].read8 = NULL;
|
||||||
m68k.memory_map[i].read16 = NULL;
|
m68k.memory_map[i].read16 = NULL;
|
||||||
@ -1116,7 +1117,6 @@ void scd_init(void)
|
|||||||
/* $080000-$0BFFFF: Word-RAM in 2M mode (256KB)*/
|
/* $080000-$0BFFFF: Word-RAM in 2M mode (256KB)*/
|
||||||
for (i=0x08; i<0x0c; i++)
|
for (i=0x08; i<0x0c; i++)
|
||||||
{
|
{
|
||||||
/* allow Word-RAM access from both CPU in 2M mode (fixes sync issues in Mortal Kombat) */
|
|
||||||
s68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
|
s68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
|
||||||
s68k.memory_map[i].read8 = NULL;
|
s68k.memory_map[i].read8 = NULL;
|
||||||
s68k.memory_map[i].read16 = NULL;
|
s68k.memory_map[i].read16 = NULL;
|
||||||
@ -1167,6 +1167,8 @@ void scd_reset(int hard)
|
|||||||
/* TODO: figure what exactly is resetted when RESET bit is cleared by SUB-CPU */
|
/* TODO: figure what exactly is resetted when RESET bit is cleared by SUB-CPU */
|
||||||
if (hard)
|
if (hard)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Clear all ASIC registers by default */
|
/* Clear all ASIC registers by default */
|
||||||
memset(scd.regs, 0, sizeof(scd.regs));
|
memset(scd.regs, 0, sizeof(scd.regs));
|
||||||
|
|
||||||
@ -1183,6 +1185,14 @@ void scd_reset(int hard)
|
|||||||
|
|
||||||
/* 2M mode */
|
/* 2M mode */
|
||||||
word_ram_switch(0);
|
word_ram_switch(0);
|
||||||
|
|
||||||
|
/* reset PRG-RAM banking on MAIN-CPU side */
|
||||||
|
for (i=scd.cartridge.boot+0x02; i<scd.cartridge.boot+0x20; i+=4)
|
||||||
|
{
|
||||||
|
/* MAIN-CPU: $020000-$03FFFF (resp. $420000-$43FFFF) mapped to first 128KB PRG-RAM bank (mirrored each 256KB) */
|
||||||
|
m68k.memory_map[i].base = scd.prg_ram;
|
||||||
|
m68k.memory_map[i+1].base = scd.prg_ram + 0x10000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -238,6 +238,13 @@ static void m68k_poll_detect(reg)
|
|||||||
#endif
|
#endif
|
||||||
m68k.cycles = m68k.cycle_end;
|
m68k.cycles = m68k.cycle_end;
|
||||||
m68k.stopped = 1 << reg;
|
m68k.stopped = 1 << reg;
|
||||||
|
|
||||||
|
/* return to current instruction */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m68k.pc -= 2;
|
||||||
|
}
|
||||||
|
while (m68k.ir != *(uint16 *)(m68k.memory_map[(m68k.pc>>16)&0xff].base + (m68k.pc & 0xffff)));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -249,7 +256,7 @@ static void m68k_poll_detect(reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* restart MAIN-CPU polling detection */
|
/* restart MAIN-CPU polling detection */
|
||||||
m68k.poll.cycle = m68k.cycles + 280;
|
m68k.poll.cycle = m68k.cycles + 840;
|
||||||
m68k.poll.pc = m68k.pc;
|
m68k.poll.pc = m68k.pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +342,15 @@ unsigned int ctrl_io_read_byte(unsigned int address)
|
|||||||
/* SUB-CPU communication flags */
|
/* SUB-CPU communication flags */
|
||||||
if (index == 0x0f)
|
if (index == 0x0f)
|
||||||
{
|
{
|
||||||
|
/* relative SUB-CPU cycle counter */
|
||||||
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
|
/* sync SUB-CPU with MAIN-CPU (Dracula Unleashed w/ Sega CD Model 2 OS ROM) */
|
||||||
|
if (!s68k.stopped && (s68k.cycles < cycles))
|
||||||
|
{
|
||||||
|
s68k_run(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
m68k_poll_detect(0x0f);
|
m68k_poll_detect(0x0f);
|
||||||
return scd.regs[0x0f>>1].byte.l;
|
return scd.regs[0x0f>>1].byte.l;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user