sms, fix irq cleared in same instruction as asserted

This commit is contained in:
kub 2021-10-23 15:10:12 +02:00
parent 3039d6d852
commit 985bbf1c03

View file

@ -20,8 +20,6 @@ extern void YM2413_regWrite(unsigned reg);
extern void YM2413_dataWrite(unsigned data); extern void YM2413_dataWrite(unsigned data);
static int vdp_lastline;
static unsigned char vdp_data_read(void) static unsigned char vdp_data_read(void)
{ {
struct PicoVideo *pv = &Pico.video; struct PicoVideo *pv = &Pico.video;
@ -47,11 +45,6 @@ static unsigned char vdp_ctl_read(void)
if (pv->reg[0] & 0x04) if (pv->reg[0] & 0x04)
d |= 0x1f; // unused bits in mode 4 read as 1 d |= 0x1f; // unused bits in mode 4 read as 1
// the vint state must be set one instruction in advance, else reading status
// would never report vint before the irq handler, which it does on a real SMS
if (vdp_lastline && z80_cyclesLeft < 10) // e.g. Chicago GG
d |= 0x80;
elprintf(EL_SR, "VDP sr: %02x", d); elprintf(EL_SR, "VDP sr: %02x", d);
return d; return d;
} }
@ -481,7 +474,6 @@ void PicoFrameMS(void)
for (y = 0; y < lines; y++) for (y = 0; y < lines; y++)
{ {
vdp_lastline = lines_vis == y;
pv->v_counter = Pico.m.scanline = y; pv->v_counter = Pico.m.scanline = y;
if (y > 218) if (y > 218)
pv->v_counter = y - 6; pv->v_counter = y - 6;
@ -489,29 +481,32 @@ void PicoFrameMS(void)
if (y < lines_vis && !skip) if (y < lines_vis && !skip)
PicoLineSMS(y); PicoLineSMS(y);
// Interrupt handling. Simulate interrupt flagged and immediately reset in
// same insn by flagging the irq, execute for 1 insn, then checking if the
// irq is still pending. (GG Chicago, SMS Back to the Future III)
if (y <= lines_vis) if (y <= lines_vis)
{ {
if (--hint < 0) if (--hint < 0)
{ {
hint = pv->reg[0x0a]; hint = pv->reg[0x0a];
pv->pending_ints |= 2; pv->pending_ints |= 2;
if (pv->reg[0] & 0x10) { cycles_done += z80_run(1);
if ((pv->reg[0] & 0x10) && (pv->pending_ints & 2)) {
elprintf(EL_INTS, "hint"); elprintf(EL_INTS, "hint");
z80_int_assert(1); z80_int_assert(1);
} }
} else if (pv->pending_ints & 2) {
pv->pending_ints &= ~2; pv->pending_ints &= ~2;
z80_int_assert(0);
} }
} }
else if (y == lines_vis + 1) { else if (y == lines_vis + 1) {
pv->pending_ints &= ~2; pv->pending_ints &= ~2;
pv->pending_ints |= 1; pv->pending_ints |= 1;
if (pv->reg[1] & 0x20) { cycles_done += z80_run(1);
if ((pv->reg[1] & 0x20) && (pv->pending_ints & 1)) {
elprintf(EL_INTS, "vint"); elprintf(EL_INTS, "vint");
z80_int_assert(1); z80_int_assert(1);
} else }
z80_int_assert(0);
} }
cycles_aim += cycles_line; cycles_aim += cycles_line;