From cf83610baa16d21842e8097a7e87f284e2519584 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 27 Jan 2018 19:41:57 +0200 Subject: [PATCH] sms: improve irq handling --- pico/pico_int.h | 4 +++- pico/sms.c | 29 +++++++++++++++++++++++++---- pico/z80if.c | 7 ++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pico/pico_int.h b/pico/pico_int.h index cb1c21d2..7225cab8 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -169,7 +169,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) ((cycles) - DrZ80Run(&drZ80, cycles)) #define z80_run_nr(cycles) DrZ80Run(&drZ80, cycles) #define z80_int() drZ80.Z80_IRQ = 1 -#define z80_int() drZ80.Z80_IRQ = 1 +#define z80_int_assert(a) drZ80.Z80_IRQ = (a) #define z80_nmi() drZ80.Z80IF |= 8 #define z80_cyclesLeft drZ80.cycles @@ -182,6 +182,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) Cz80_Exec(&CZ80, cycles) #define z80_run_nr(cycles) Cz80_Exec(&CZ80, cycles) #define z80_int() Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE) +#define z80_int_assert(a) Cz80_Set_IRQ(&CZ80, 0, (a) ? ASSERT_LINE : CLEAR_LINE) #define z80_nmi() Cz80_Set_IRQ(&CZ80, IRQ_LINE_NMI, 0) #define z80_cyclesLeft (CZ80.ICount - CZ80.ExtraCycles) @@ -193,6 +194,7 @@ extern struct DrZ80 drZ80; #define z80_run(cycles) (cycles) #define z80_run_nr(cycles) #define z80_int() +#define z80_int_assert(a) #define z80_nmi() #endif diff --git a/pico/sms.c b/pico/sms.c index ac81c2b2..286b8bf1 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -32,6 +32,7 @@ static unsigned char vdp_ctl_read(void) struct PicoVideo *pv = &Pico.video; unsigned char d; + z80_int_assert(0); d = pv->status | (pv->pending_ints << 7); pv->pending = pv->pending_ints = 0; pv->status = 0; @@ -55,14 +56,34 @@ static void vdp_data_write(unsigned char d) pv->pending = 0; } -static void vdp_ctl_write(unsigned char d) +static NOINLINE void vdp_reg_write(struct PicoVideo *pv, u8 a, u8 d) +{ + int l; + + pv->reg[a] = d; + switch (a) { + case 0: + l = pv->pending_ints & (d >> 3) & 2; + elprintf(EL_INTS, "hint %d", l); + z80_int_assert(l); + break; + case 1: + l = pv->pending_ints & (d >> 5) & 1; + elprintf(EL_INTS, "vint %d", l); + z80_int_assert(l); + break; + } +} + +static void vdp_ctl_write(u8 d) { struct PicoVideo *pv = &Pico.video; if (pv->pending) { if ((d >> 6) == 2) { - pv->reg[d & 0x0f] = pv->addr; elprintf(EL_IO, " VDP r%02x=%02x", d & 0x0f, pv->addr & 0xff); + if (pv->reg[d & 0x0f] != (u8)pv->addr) + vdp_reg_write(pv, d & 0x0f, pv->addr); } pv->type = d >> 6; pv->addr &= 0x00ff; @@ -287,7 +308,7 @@ void PicoFrameMS(void) pv->pending_ints |= 2; if (pv->reg[0] & 0x10) { elprintf(EL_INTS, "hint"); - z80_int(); + z80_int_assert(1); } } } @@ -295,7 +316,7 @@ void PicoFrameMS(void) pv->pending_ints |= 1; if (pv->reg[1] & 0x20) { elprintf(EL_INTS, "vint"); - z80_int(); + z80_int_assert(1); } } diff --git a/pico/z80if.c b/pico/z80if.c index da2043e4..419d061f 100644 --- a/pico/z80if.c +++ b/pico/z80if.c @@ -52,6 +52,8 @@ static unsigned int dz80_rebase_pc(unsigned short pc) return drZ80.Z80PC_BASE; } +static void dz80_noop_irq_ack(void) {} + #ifdef FAST_Z80SP static u32 drz80_sp_base; @@ -107,8 +109,11 @@ void z80_reset(void) drz80_sp_base = (PicoIn.AHW & PAHW_SMS) ? 0xc000 : 0x0000; drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1; #endif - if (PicoIn.AHW & PAHW_SMS) + drZ80.z80_irq_callback = NULL; // use auto-clear + if (PicoIn.AHW & PAHW_SMS) { drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS + drZ80.z80_irq_callback = dz80_noop_irq_ack; + } // XXX: since we use direct SP pointer, it might make sense to force it to RAM, // but we'll rely on built-in stack protection for now #endif -- 2.39.5