From 22814963ccbcba3a08ca49656fd80dc40de64710 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 7 Oct 2017 00:08:05 +0300 Subject: [PATCH] some irq hacks notes to self (derived from Nemesis): H32: 0x10A .. 0x127 0x1D2 .. 0x1FF 0x000 0x001 pclk 30 46 1 |0x109 mclk 770 | 2650 = 3420 68kclk 110 378.5 ~= 488.5 H40: 0x14A .. 0x16C 0x1C9 .. 0x1FF 0x000 0x001 pclk 35 55 1 mclk 35*8 4*8+314+10+19*8 |0x149*8 788 | 2632 = 3420 68kclk 112.5 376 ~= 488.5 --- pico/cd/sek.c | 6 ++---- pico/pico_cmn.c | 6 ++++-- pico/pico_int.h | 10 +++------- pico/sek.c | 36 ++++++++++++++++++++---------------- pico/videoport.c | 19 ++++++++++--------- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/pico/cd/sek.c b/pico/cd/sek.c index d491490..42fea93 100644 --- a/pico/cd/sek.c +++ b/pico/cd/sek.c @@ -178,10 +178,8 @@ PICO_INTERNAL int SekInterruptS68k(int irq) PicoCpuCS68k.irq=real_irq; #endif #ifdef EMU_M68K - void *oldcontext = m68ki_cpu_p; - m68k_set_context(&PicoCpuMS68k); - m68k_set_irq(real_irq); - m68k_set_context(oldcontext); + // avoid m68k_set_irq() for delaying to work + PicoCpuMS68k.int_level = real_irq << 8; #endif #ifdef EMU_F68K PicoCpuFS68k.interrupts[0]=real_irq; diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index a450757..509c877 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -7,7 +7,7 @@ */ #define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC -#define CYCLES_M68K_VINT_LAG 68 +#define CYCLES_M68K_VINT_LAG 112 // pad delay (for 6 button pads) #define PAD_DELAY() { \ @@ -206,7 +206,6 @@ static int PicoFrameHints(void) } pv->status |= SR_VB; // go into vblank - pv->pending_ints |= 0x20; // the following SekRun is there for several reasons: // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga) @@ -216,7 +215,10 @@ static int PicoFrameHints(void) do_timing_hacks_vb(); CPUS_RUN(CYCLES_M68K_VINT_LAG); + pv->pending_ints |= 0x20; if (pv->reg[1] & 0x20) { + Pico.t.m68c_aim = Pico.t.m68c_cnt + 11; // HACK + SekSyncM68k(); elprintf(EL_INTS, "vint: @ %06x [%u]", SekPc, SekCyclesDone()); SekInterrupt(6); } diff --git a/pico/pico_int.h b/pico/pico_int.h index 765afaf..bbfc5cb 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -117,13 +117,9 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #define SekNotPolling PicoCpuMM68k.not_polling #define SekNotPollingS68k PicoCpuMS68k.not_polling -#define SekInterrupt(irq) { \ - void *oldcontext = m68ki_cpu_p; \ - m68k_set_context(&PicoCpuMM68k); \ - m68k_set_irq(irq); \ - m68k_set_context(oldcontext); \ -} -#define SekIrqLevel (PicoCpuMM68k.int_level >> 8) +// avoid m68k_set_irq() for delaying to work +#define SekInterrupt(irq) PicoCpuMM68k.int_level = (irq) << 8 +#define SekIrqLevel (PicoCpuMM68k.int_level >> 8) #endif #endif // EMU_M68K diff --git a/pico/sek.c b/pico/sek.c index f599d9b..031c549 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -25,15 +25,29 @@ M68K_CONTEXT PicoCpuFM68k; #endif +static int do_ack(int level) +{ + struct PicoVideo *pv = &Pico.video; + + elprintf(EL_INTS, "%cack: @ %06x [%u], p=%02x", + level == 6 ? 'v' : 'h', SekPc, SekCyclesDone(), pv->pending_ints); + // the VDP doesn't look at the 68k level + if (pv->pending_ints & pv->reg[1] & 0x20) { + pv->pending_ints &= ~0x20; + return (pv->reg[0] & pv->pending_ints & 0x10) >> 2; + } + else if (pv->pending_ints & pv->reg[0] & 0x10) + pv->pending_ints &= ~0x10; + + return 0; +} + /* callbacks */ #ifdef EMU_C68K // interrupt acknowledgment static int SekIntAck(int level) { - // try to emulate VDP's reaction to 68000 int ack - if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); } - else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); } - PicoCpuCM68k.irq = 0; + PicoCpuCM68k.irq = do_ack(level); return CYCLONE_INT_ACK_AUTOVECTOR; } @@ -71,9 +85,7 @@ static int SekUnrecognizedOpcode() #ifdef EMU_M68K static int SekIntAckM68K(int level) { - if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); } - else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); } - CPU_INT_LEVEL = 0; + CPU_INT_LEVEL = do_ack(level) << 8; return M68K_INT_ACK_AUTOVECTOR; } @@ -87,15 +99,7 @@ static int SekTasCallback(void) #ifdef EMU_F68K static void SekIntAckF68K(unsigned level) { - if (level == 4) { - Pico.video.pending_ints = 0; - elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, SekCyclesDone()); - } - else if(level == 6) { - Pico.video.pending_ints &= ~0x20; - elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, SekCyclesDone()); - } - PicoCpuFM68k.interrupts[0] = 0; + PicoCpuFM68k.interrupts[0] = do_ack(level); } #endif diff --git a/pico/videoport.c b/pico/videoport.c index 072a941..22b8385 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -357,10 +357,10 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) { struct PicoVideo *pvid=&Pico.video; - //if (Pico.m.scanline < 224) - // elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d); - a&=0x1c; + //elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x [%u] @ %06x", + // a, d, SekCyclesDone(), SekPc); + a &= 0x1c; switch (a) { case 0x00: // Data port 0 or 2 @@ -383,8 +383,8 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) pvid->lwrite_cnt -= use; if (pvid->lwrite_cnt < 0) SekCyclesLeft = 0; - elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr, - Pico.video.type, pvid->lwrite_cnt, SekPc); + elprintf(EL_ASVDP, "VDP data write: [%04x] %04x [%u] {%i} #%i @ %06x", + Pico.video.addr, d, SekCyclesDone(), Pico.video.type, pvid->lwrite_cnt, SekPc); } VideoWrite(d); @@ -451,14 +451,15 @@ update_irq: // update IRQ level if (!SekShouldInterrupt()) // hack { - int lines, pints, irq=0; + int lines, pints, irq = 0; lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); - pints = (pvid->pending_ints&lines); + pints = pvid->pending_ints & lines; if (pints & 0x20) irq = 6; else if (pints & 0x10) irq = 4; SekInterrupt(irq); // update line - if (irq) SekEndRun(24); // make it delayed + // this is broken because cost of current insn isn't known here + if (irq) SekEndRun(21); // make it delayed } #endif } @@ -521,7 +522,7 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald) - elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc); + elprintf(EL_SR, "SR read: %04x [%u] @ %06x", d, SekCyclesDone(), SekPc); return d; } -- 2.39.2