some irq hacks
authornotaz <notasas@gmail.com>
Fri, 6 Oct 2017 21:08:05 +0000 (00:08 +0300)
committernotaz <notasas@gmail.com>
Fri, 13 Oct 2017 21:53:08 +0000 (00:53 +0300)
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
pico/pico_cmn.c
pico/pico_int.h
pico/sek.c
pico/videoport.c

index d491490..42fea93 100644 (file)
@@ -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;
index a450757..509c877 100644 (file)
@@ -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);
   }
index 765afaf..bbfc5cb 100644 (file)
@@ -117,13 +117,9 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
 #define SekNotPolling     PicoCpuMM68k.not_polling\r
 #define SekNotPollingS68k PicoCpuMS68k.not_polling\r
 \r
-#define SekInterrupt(irq) { \\r
-       void *oldcontext = m68ki_cpu_p; \\r
-       m68k_set_context(&PicoCpuMM68k); \\r
-       m68k_set_irq(irq); \\r
-       m68k_set_context(oldcontext); \\r
-}\r
-#define SekIrqLevel (PicoCpuMM68k.int_level >> 8)\r
+// avoid m68k_set_irq() for delaying to work\r
+#define SekInterrupt(irq)  PicoCpuMM68k.int_level = (irq) << 8\r
+#define SekIrqLevel        (PicoCpuMM68k.int_level >> 8)\r
 \r
 #endif\r
 #endif // EMU_M68K\r
index f599d9b..031c549 100644 (file)
@@ -25,15 +25,29 @@ M68K_CONTEXT PicoCpuFM68k;
 #endif\r
 \r
 \r
+static int do_ack(int level)\r
+{\r
+  struct PicoVideo *pv = &Pico.video;\r
+\r
+  elprintf(EL_INTS, "%cack: @ %06x [%u], p=%02x",\r
+    level == 6 ? 'v' : 'h', SekPc, SekCyclesDone(), pv->pending_ints);\r
+  // the VDP doesn't look at the 68k level\r
+  if (pv->pending_ints & pv->reg[1] & 0x20) {\r
+    pv->pending_ints &= ~0x20;\r
+    return (pv->reg[0] & pv->pending_ints & 0x10) >> 2;\r
+  }\r
+  else if (pv->pending_ints & pv->reg[0] & 0x10)\r
+    pv->pending_ints &= ~0x10;\r
+\r
+  return 0;\r
+}\r
+\r
 /* callbacks */\r
 #ifdef EMU_C68K\r
 // interrupt acknowledgment\r
 static int SekIntAck(int level)\r
 {\r
-  // try to emulate VDP's reaction to 68000 int ack\r
-  if     (level == 4) { Pico.video.pending_ints  =  0;    elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); }\r
-  else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); }\r
-  PicoCpuCM68k.irq = 0;\r
+  PicoCpuCM68k.irq = do_ack(level);\r
   return CYCLONE_INT_ACK_AUTOVECTOR;\r
 }\r
 \r
@@ -71,9 +85,7 @@ static int SekUnrecognizedOpcode()
 #ifdef EMU_M68K\r
 static int SekIntAckM68K(int level)\r
 {\r
-  if     (level == 4) { Pico.video.pending_ints  =  0;    elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); }\r
-  else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, Pico.t.m68c_cnt); }\r
-  CPU_INT_LEVEL = 0;\r
+  CPU_INT_LEVEL = do_ack(level) << 8;\r
   return M68K_INT_ACK_AUTOVECTOR;\r
 }\r
 \r
@@ -87,15 +99,7 @@ static int SekTasCallback(void)
 #ifdef EMU_F68K\r
 static void SekIntAckF68K(unsigned level)\r
 {\r
-  if     (level == 4) {\r
-    Pico.video.pending_ints = 0;\r
-    elprintf(EL_INTS, "hack: @ %06x [%u]", SekPc, SekCyclesDone());\r
-  }\r
-  else if(level == 6) {\r
-    Pico.video.pending_ints &= ~0x20;\r
-    elprintf(EL_INTS, "vack: @ %06x [%u]", SekPc, SekCyclesDone());\r
-  }\r
-  PicoCpuFM68k.interrupts[0] = 0;\r
+  PicoCpuFM68k.interrupts[0] = do_ack(level);\r
 }\r
 #endif\r
 \r
index 072a941..22b8385 100644 (file)
@@ -357,10 +357,10 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
 {\r
   struct PicoVideo *pvid=&Pico.video;\r
 \r
-  //if (Pico.m.scanline < 224)\r
-  //  elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d);\r
-  a&=0x1c;\r
+  //elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x [%u] @ %06x",\r
+  //  a, d, SekCyclesDone(), SekPc);\r
 \r
+  a &= 0x1c;\r
   switch (a)\r
   {\r
   case 0x00: // Data port 0 or 2\r
@@ -383,8 +383,8 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
       pvid->lwrite_cnt -= use;\r
       if (pvid->lwrite_cnt < 0)\r
         SekCyclesLeft = 0;\r
-      elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr,\r
-               Pico.video.type, pvid->lwrite_cnt, SekPc);\r
+      elprintf(EL_ASVDP, "VDP data write: [%04x] %04x [%u] {%i} #%i @ %06x",\r
+        Pico.video.addr, d, SekCyclesDone(), Pico.video.type, pvid->lwrite_cnt, SekPc);\r
     }\r
     VideoWrite(d);\r
 \r
@@ -451,14 +451,15 @@ update_irq:
         // update IRQ level\r
         if (!SekShouldInterrupt()) // hack\r
         {\r
-          int lines, pints, irq=0;\r
+          int lines, pints, irq = 0;\r
           lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10);\r
-          pints = (pvid->pending_ints&lines);\r
+          pints = pvid->pending_ints & lines;\r
                if (pints & 0x20) irq = 6;\r
           else if (pints & 0x10) irq = 4;\r
           SekInterrupt(irq); // update line\r
 \r
-          if (irq) SekEndRun(24); // make it delayed\r
+          // this is broken because cost of current insn isn't known here\r
+          if (irq) SekEndRun(21); // make it delayed\r
         }\r
 #endif\r
       }\r
@@ -521,7 +522,7 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
 \r
     pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald)\r
 \r
-    elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc);\r
+    elprintf(EL_SR, "SR read: %04x [%u] @ %06x", d, SekCyclesDone(), SekPc);\r
     return d;\r
   }\r
 \r