[Core/MCD] improved Main-CPU & Sub-CPU idle loop detection (fixes "Super League CD")

This commit is contained in:
EkeEke 2013-10-21 00:09:50 +02:00
parent e14330e01c
commit 2236072ce9
3 changed files with 117 additions and 62 deletions

View File

@ -186,21 +186,31 @@ static void bram_write_word(unsigned int address, unsigned int data)
/* PCM chip & Gate-Array area */
/*--------------------------------------------------------------------------*/
static void s68k_poll_detect(reg)
static void s68k_poll_detect(unsigned int reg_mask)
{
/* detect SUB-CPU register polling */
if (s68k.poll.detected == (1 << reg))
if (s68k.poll.detected & reg_mask)
{
if (s68k.cycles <= s68k.poll.cycle)
{
if (s68k.pc == s68k.poll.pc)
{
/* stop SUB-CPU until register is modified by MAIN-CPU */
/* SUB-CPU polling confirmed ? */
if (s68k.poll.detected & 1)
{
/* idle SUB-CPU until register is modified */
s68k.cycles = s68k.cycle_end;
s68k.stopped = reg_mask;
#ifdef LOG_SCD
error("s68k stopped from %d cycles\n", s68k.cycles);
error("s68k stopped from %d cycles\n", s68k.cycles);
#endif
s68k.cycles = s68k.cycle_end;
s68k.stopped = 1 << reg;
}
else
{
/* confirm SUB-CPU polling */
s68k.poll.detected |= 1;
s68k.poll.cycle = s68k.cycles + 392;
}
}
return;
}
@ -208,15 +218,15 @@ static void s68k_poll_detect(reg)
else
{
/* set SUB-CPU register access flag */
s68k.poll.detected = 1 << reg;
s68k.poll.detected = reg_mask;
}
/* restart SUB-CPU polling detection */
/* reset SUB-CPU polling detection */
s68k.poll.cycle = s68k.cycles + 392;
s68k.poll.pc = s68k.pc;
}
static void s68k_poll_sync(reg)
static void s68k_poll_sync(unsigned int reg_mask)
{
/* relative MAIN-CPU cycle counter */
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
@ -227,8 +237,8 @@ static void s68k_poll_sync(reg)
m68k_run(cycles);
}
/* MAIN-CPU stopped on register polling ? */
if (m68k.stopped & (3 << reg))
/* MAIN-CPU idle on register polling ? */
if (m68k.stopped & reg_mask)
{
/* sync MAIN-CPU with SUB-CPU */
m68k.cycles = cycles;
@ -240,9 +250,9 @@ static void s68k_poll_sync(reg)
#endif
}
/* clear CPU register(s) access flags */
m68k.poll.detected &= ~(3 << reg);
s68k.poll.detected &= ~(3 << reg);
/* clear CPU register access flags */
s68k.poll.detected &= ~reg_mask;
m68k.poll.detected &= ~reg_mask;
}
static unsigned int scd_read_byte(unsigned int address)
@ -266,14 +276,14 @@ static unsigned int scd_read_byte(unsigned int address)
/* Memory Mode */
if (address == 0xff8003)
{
s68k_poll_detect(0x03);
s68k_poll_detect(1<<0x03);
return scd.regs[0x03>>1].byte.l;
}
/* MAIN-CPU communication flags */
if (address == 0xff800e)
{
s68k_poll_detect(0x0e);
s68k_poll_detect(1<<0x0e);
return scd.regs[0x0e>>1].byte.h;
}
@ -328,7 +338,7 @@ static unsigned int scd_read_byte(unsigned int address)
/* MAIN-CPU communication words */
if ((address & 0x1f0) == 0x10)
{
s68k_poll_detect(address & 0x1f);
s68k_poll_detect(1 << (address & 0x1f));
}
/* default registers */
@ -358,7 +368,7 @@ static unsigned int scd_read_word(unsigned int address)
/* Memory Mode */
if (address == 0xff8002)
{
s68k_poll_detect(0x03);
s68k_poll_detect(1<<0x03);
return scd.regs[0x03>>1].w;
}
@ -418,7 +428,7 @@ static unsigned int scd_read_word(unsigned int address)
m68k_run(cycles);
}
s68k_poll_detect(address & 0x1e);
s68k_poll_detect(3 << (address & 0x1e));
}
/* default registers */
@ -526,7 +536,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
case 0x03: /* Memory Mode */
{
s68k_poll_sync(0x02);
s68k_poll_sync(1<<0x03);
/* detect MODE & RET bits modifications */
if ((data ^ scd.regs[0x03 >> 1].byte.l) & 0x05)
@ -687,7 +697,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
case 0x0f: /* SUB-CPU communication flags */
{
s68k_poll_sync(0x0e);
s68k_poll_sync(1<<0x0f);
scd.regs[0x0f>>1].byte.l = data;
return;
}
@ -748,7 +758,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
/* SUB-CPU communication words */
if ((address & 0xf0) == 0x20)
{
s68k_poll_sync((address - 0x10) & 0x1e);
s68k_poll_sync(1 << ((address - 0x10) & 0x1f));
}
/* default registers */
@ -799,7 +809,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
case 0x02: /* Memory Mode */
{
s68k_poll_sync(0x02);
s68k_poll_sync(1<<0x03);
/* detect MODE & RET bits modifications */
if ((data ^ scd.regs[0x03>>1].byte.l) & 0x05)
@ -965,7 +975,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
case 0x0e: /* SUB-CPU communication flags */
{
s68k_poll_sync(0x0e);
s68k_poll_sync(1<<0x0f);
/* MSB is read-only */
scd.regs[0x0f>>1].byte.l = data;
@ -1032,7 +1042,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
/* SUB-CPU communication words */
if ((address & 0xf0) == 0x20)
{
s68k_poll_sync((address - 0x10) & 0x1e);
s68k_poll_sync(3 << ((address - 0x10) & 0x1e));
}
/* default registers */

View File

@ -7220,15 +7220,15 @@ static void m68k_op_dbf_16(void)
uint res = MASK_OUT_ABOVE_16(*r_dst - 1);
*r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
if(res != 0xffff)
{
uint offset = OPER_I_16();
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7250,6 +7250,9 @@ static void m68k_op_dbhi_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7274,6 +7277,9 @@ static void m68k_op_dbls_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7298,6 +7304,9 @@ static void m68k_op_dbcc_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7322,6 +7331,9 @@ static void m68k_op_dbcs_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7346,6 +7358,9 @@ static void m68k_op_dbne_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7370,6 +7385,9 @@ static void m68k_op_dbeq_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7394,6 +7412,9 @@ static void m68k_op_dbvc_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7418,6 +7439,9 @@ static void m68k_op_dbvs_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7442,6 +7466,9 @@ static void m68k_op_dbpl_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7466,6 +7493,9 @@ static void m68k_op_dbmi_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7490,6 +7520,9 @@ static void m68k_op_dbge_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7514,6 +7547,9 @@ static void m68k_op_dblt_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7538,6 +7574,9 @@ static void m68k_op_dbgt_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;
@ -7562,6 +7601,9 @@ static void m68k_op_dble_16(void)
REG_PC -= 2;
m68ki_branch_16(offset);
USE_CYCLES(CYC_DBCC_F_NOEXP);
/* reset idle loop detection */
m68ki_cpu.poll.detected = 0;
return;
}
REG_PC += 2;

View File

@ -223,28 +223,31 @@ void z80_write_word(unsigned int address, unsigned int data)
/* I/O Control */
/*--------------------------------------------------------------------------*/
static void m68k_poll_detect(reg)
static void m68k_poll_detect(unsigned int reg_mask)
{
/* detect MAIN-CPU register polling */
if (m68k.poll.detected == (1 << reg))
if (m68k.poll.detected & reg_mask)
{
if (m68k.cycles <= m68k.poll.cycle)
{
if (m68k.pc == m68k.poll.pc)
{
/* stop MAIN-CPU until register is modified by SUB-CPU */
#ifdef LOG_SCD
error("m68k stopped from %d cycles\n", m68k.cycles);
#endif
m68k.cycles = m68k.cycle_end;
m68k.stopped = 1 << reg;
/* return to current instruction */
do
/* MAIN-CPU polling confirmed ? */
if (m68k.poll.detected & 1)
{
m68k.pc -= 2;
/* idle MAIN-CPU until register is modified */
m68k.cycles = m68k.cycle_end;
m68k.stopped = reg_mask;
#ifdef LOG_SCD
error("m68k stopped from %d cycles\n", m68k.cycles);
#endif
}
else
{
/* confirm MAIN-CPU polling */
m68k.poll.detected |= 1;
m68k.poll.cycle = m68k.cycles + 840;
}
while (m68k.ir != *(uint16 *)(m68k.memory_map[(m68k.pc>>16)&0xff].base + (m68k.pc & 0xffff)));
}
return;
}
@ -252,15 +255,15 @@ static void m68k_poll_detect(reg)
else
{
/* set MAIN-CPU register access flag */
m68k.poll.detected = 1 << reg;
m68k.poll.detected = reg_mask;
}
/* restart MAIN-CPU polling detection */
/* reset MAIN-CPU polling detection */
m68k.poll.cycle = m68k.cycles + 840;
m68k.poll.pc = m68k.pc;
}
static void m68k_poll_sync(reg)
static void m68k_poll_sync(unsigned int reg_mask)
{
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
@ -271,8 +274,8 @@ static void m68k_poll_sync(reg)
s68k_run(cycles);
}
/* SUB-CPU stopped on register polling ? */
if (s68k.stopped & (3 << reg))
/* SUB-CPU idle on register polling ? */
if (s68k.stopped & reg_mask)
{
/* sync SUB-CPU with MAIN-CPU */
s68k.cycles = cycles;
@ -284,9 +287,9 @@ static void m68k_poll_sync(reg)
#endif
}
/* clear CPU register(s) access flags */
m68k.poll.detected &= ~(3 << reg);
s68k.poll.detected &= ~(3 << reg);
/* clear CPU register access flags */
s68k.poll.detected &= ~reg_mask;
m68k.poll.detected &= ~reg_mask;
}
unsigned int ctrl_io_read_byte(unsigned int address)
@ -335,7 +338,7 @@ unsigned int ctrl_io_read_byte(unsigned int address)
/* Memory Mode */
if (index == 0x03)
{
m68k_poll_detect(0x03);
m68k_poll_detect(1<<0x03);
return scd.regs[0x03>>1].byte.l;
}
@ -345,13 +348,13 @@ unsigned int ctrl_io_read_byte(unsigned int address)
/* 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) */
/* sync SUB-CPU with MAIN-CPU (Dracula Unleashed w/ Sega CD Model 2 Boot ROM) */
if (!s68k.stopped && (s68k.cycles < cycles))
{
s68k_run(cycles);
}
m68k_poll_detect(0x0f);
m68k_poll_detect(1<<0x0f);
return scd.regs[0x0f>>1].byte.l;
}
@ -361,7 +364,7 @@ unsigned int ctrl_io_read_byte(unsigned int address)
/* SUB-CPU communication words */
if (index >= 0x20)
{
m68k_poll_detect(index - 0x10);
m68k_poll_detect(1 << (index - 0x10));
}
/* register LSB */
@ -466,7 +469,7 @@ unsigned int ctrl_io_read_word(unsigned int address)
/* Memory Mode */
if (index == 0x02)
{
m68k_poll_detect(0x03);
m68k_poll_detect(1<<0x03);
return scd.regs[0x03>>1].w;
}
@ -498,7 +501,7 @@ unsigned int ctrl_io_read_word(unsigned int address)
/* SUB-CPU communication words */
if (index >= 0x20)
{
m68k_poll_detect(index - 0x10);
m68k_poll_detect(3 << (index - 0x10));
}
return scd.regs[index >> 1].w;
@ -611,7 +614,7 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
/* relative SUB-CPU cycle counter */
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
/* sync SUB-CPU with MAIN-CPU */
/* sync SUB-CPU with MAIN-CPU (Earnest Evans, Fhey Area) */
if (!s68k.stopped && (s68k.cycles < cycles))
{
s68k_run(cycles);
@ -674,7 +677,7 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
case 0x03: /* Memory mode */
{
m68k_poll_sync(0x02);
m68k_poll_sync(1<<0x03);
/* PRG-RAM 128k bank mapped to $020000-$03FFFF (resp. $420000-$43FFFF) */
m68k.memory_map[scd.cartridge.boot + 0x02].base = scd.prg_ram + ((data & 0xc0) << 11);
@ -726,7 +729,7 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
case 0x0e: /* MAIN-CPU communication flags */
{
m68k_poll_sync(0x0e);
m68k_poll_sync(1<<0x0e);
scd.regs[0x0e>>1].byte.h = data;
return;
}
@ -736,7 +739,7 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
/* MAIN-CPU communication words */
if ((address & 0x30) == 0x10)
{
m68k_poll_sync(address & 0x1e);
m68k_poll_sync(1 << (address & 0x1f));
/* register LSB */
if (address & 1)
@ -887,7 +890,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
case 0x02: /* Memory Mode */
{
m68k_poll_sync(0x02);
m68k_poll_sync(1<<0x03);
/* PRG-RAM 128k bank mapped to $020000-$03FFFF (resp. $420000-$43FFFF) */
m68k.memory_map[scd.cartridge.boot + 0x02].base = scd.prg_ram + ((data & 0xc0) << 11);
@ -939,7 +942,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
case 0x0e: /* MAIN-CPU communication flags */
{
m68k_poll_sync(0x0e);
m68k_poll_sync(1<<0x0e);
/* LSB is read-only (Mortal Kombat) */
scd.regs[0x0e>>1].byte.h = data;
@ -951,7 +954,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
/* MAIN-CPU communication words */
if ((address & 0x30) == 0x10)
{
m68k_poll_sync(address & 0x1e);
m68k_poll_sync(3 << (address & 0x1e));
scd.regs[(address >> 1) & 0xff].w = data;
return;
}