diff --git a/core/cd_hw/scd.c b/core/cd_hw/scd.c index 47ed230..c36c0d4 100644 --- a/core/cd_hw/scd.c +++ b/core/cd_hw/scd.c @@ -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 */ diff --git a/core/m68k/m68kops.h b/core/m68k/m68kops.h index 57ca5ce..fd5110e 100644 --- a/core/m68k/m68kops.h +++ b/core/m68k/m68kops.h @@ -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; diff --git a/core/mem68k.c b/core/mem68k.c index 3f1f29a..0004d03 100644 --- a/core/mem68k.c +++ b/core/mem68k.c @@ -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; }