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
This commit is contained in:
notaz 2017-10-07 00:08:05 +03:00
parent e015ad3c1b
commit 22814963cc
5 changed files with 39 additions and 38 deletions

View file

@ -178,10 +178,8 @@ PICO_INTERNAL int SekInterruptS68k(int irq)
PicoCpuCS68k.irq=real_irq; PicoCpuCS68k.irq=real_irq;
#endif #endif
#ifdef EMU_M68K #ifdef EMU_M68K
void *oldcontext = m68ki_cpu_p; // avoid m68k_set_irq() for delaying to work
m68k_set_context(&PicoCpuMS68k); PicoCpuMS68k.int_level = real_irq << 8;
m68k_set_irq(real_irq);
m68k_set_context(oldcontext);
#endif #endif
#ifdef EMU_F68K #ifdef EMU_F68K
PicoCpuFS68k.interrupts[0]=real_irq; PicoCpuFS68k.interrupts[0]=real_irq;

View file

@ -7,7 +7,7 @@
*/ */
#define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC #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) // pad delay (for 6 button pads)
#define PAD_DELAY() { \ #define PAD_DELAY() { \
@ -206,7 +206,6 @@ static int PicoFrameHints(void)
} }
pv->status |= SR_VB; // go into vblank pv->status |= SR_VB; // go into vblank
pv->pending_ints |= 0x20;
// the following SekRun is there for several reasons: // the following SekRun is there for several reasons:
// there must be a delay after vblank bit is set and irq is asserted (Mazin Saga) // 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(); do_timing_hacks_vb();
CPUS_RUN(CYCLES_M68K_VINT_LAG); CPUS_RUN(CYCLES_M68K_VINT_LAG);
pv->pending_ints |= 0x20;
if (pv->reg[1] & 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()); elprintf(EL_INTS, "vint: @ %06x [%u]", SekPc, SekCyclesDone());
SekInterrupt(6); SekInterrupt(6);
} }

View file

@ -117,12 +117,8 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
#define SekNotPolling PicoCpuMM68k.not_polling #define SekNotPolling PicoCpuMM68k.not_polling
#define SekNotPollingS68k PicoCpuMS68k.not_polling #define SekNotPollingS68k PicoCpuMS68k.not_polling
#define SekInterrupt(irq) { \ // avoid m68k_set_irq() for delaying to work
void *oldcontext = m68ki_cpu_p; \ #define SekInterrupt(irq) PicoCpuMM68k.int_level = (irq) << 8
m68k_set_context(&PicoCpuMM68k); \
m68k_set_irq(irq); \
m68k_set_context(oldcontext); \
}
#define SekIrqLevel (PicoCpuMM68k.int_level >> 8) #define SekIrqLevel (PicoCpuMM68k.int_level >> 8)
#endif #endif

View file

@ -25,15 +25,29 @@ M68K_CONTEXT PicoCpuFM68k;
#endif #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 */ /* callbacks */
#ifdef EMU_C68K #ifdef EMU_C68K
// interrupt acknowledgment // interrupt acknowledgment
static int SekIntAck(int level) static int SekIntAck(int level)
{ {
// try to emulate VDP's reaction to 68000 int ack PicoCpuCM68k.irq = do_ack(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); }
PicoCpuCM68k.irq = 0;
return CYCLONE_INT_ACK_AUTOVECTOR; return CYCLONE_INT_ACK_AUTOVECTOR;
} }
@ -71,9 +85,7 @@ static int SekUnrecognizedOpcode()
#ifdef EMU_M68K #ifdef EMU_M68K
static int SekIntAckM68K(int level) static int SekIntAckM68K(int level)
{ {
if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); } CPU_INT_LEVEL = do_ack(level) << 8;
else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); }
CPU_INT_LEVEL = 0;
return M68K_INT_ACK_AUTOVECTOR; return M68K_INT_ACK_AUTOVECTOR;
} }
@ -87,15 +99,7 @@ static int SekTasCallback(void)
#ifdef EMU_F68K #ifdef EMU_F68K
static void SekIntAckF68K(unsigned level) static void SekIntAckF68K(unsigned level)
{ {
if (level == 4) { PicoCpuFM68k.interrupts[0] = do_ack(level);
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;
} }
#endif #endif

View file

@ -357,10 +357,10 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
{ {
struct PicoVideo *pvid=&Pico.video; struct PicoVideo *pvid=&Pico.video;
//if (Pico.m.scanline < 224) //elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x [%u] @ %06x",
// elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d); // a, d, SekCyclesDone(), SekPc);
a&=0x1c;
a &= 0x1c;
switch (a) switch (a)
{ {
case 0x00: // Data port 0 or 2 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; pvid->lwrite_cnt -= use;
if (pvid->lwrite_cnt < 0) if (pvid->lwrite_cnt < 0)
SekCyclesLeft = 0; SekCyclesLeft = 0;
elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr, elprintf(EL_ASVDP, "VDP data write: [%04x] %04x [%u] {%i} #%i @ %06x",
Pico.video.type, pvid->lwrite_cnt, SekPc); Pico.video.addr, d, SekCyclesDone(), Pico.video.type, pvid->lwrite_cnt, SekPc);
} }
VideoWrite(d); VideoWrite(d);
@ -453,12 +453,13 @@ update_irq:
{ {
int lines, pints, irq = 0; int lines, pints, irq = 0;
lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10);
pints = (pvid->pending_ints&lines); pints = pvid->pending_ints & lines;
if (pints & 0x20) irq = 6; if (pints & 0x20) irq = 6;
else if (pints & 0x10) irq = 4; else if (pints & 0x10) irq = 4;
SekInterrupt(irq); // update line 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 #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) 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; return d;
} }