sms, improve cycle counting, fix vcounter for 224/240 lines
authorkub <derkub@gmail.com>
Fri, 29 Oct 2021 20:06:52 +0000 (22:06 +0200)
committerkub <derkub@gmail.com>
Fri, 29 Oct 2021 20:09:15 +0000 (22:09 +0200)
pico/pico_int.h
pico/sms.c

index 216138f..e6da518 100644 (file)
@@ -199,7 +199,7 @@ extern struct DrZ80 drZ80;
 #define Z80_STATE_SIZE 0x60\r
 \r
 #define z80_resetCycles() \\r
-  Pico.t.z80c_cnt = Pico.t.z80c_aim = Pico.t.z80_scanline = 0\r
+  Pico.t.z80c_cnt -= Pico.t.z80c_aim, Pico.t.z80c_aim = Pico.t.z80_scanline = 0\r
 \r
 #define z80_cyclesDone() \\r
   (Pico.t.z80c_aim - z80_cyclesLeft)\r
@@ -437,6 +437,7 @@ struct PicoTiming
 \r
   unsigned int z80c_cnt;                // z80 cycles done (this frame)\r
   unsigned int z80c_aim;\r
+  unsigned int z80c_line_start;\r
   int z80_scanline;\r
 \r
   int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
index 90b3007..4332144 100644 (file)
@@ -239,7 +239,7 @@ static void z80_sms_out(unsigned short a, unsigned char d)
         } else {
           // pad. latch hcounter if one of the TH lines is switched to 1
           if ((Pico.ms.io_ctl ^ d) & d & 0xa0)
-            Pico.ms.vdp_hlatch = vdp_hcounter(228 - z80_cyclesLeft);
+            Pico.ms.vdp_hlatch = vdp_hcounter(z80_cyclesDone() - Pico.t.z80c_line_start);
           Pico.ms.io_ctl = d;
         }
         break;
@@ -261,6 +261,12 @@ static void z80_sms_out(unsigned short a, unsigned char d)
   }
 }
 
+static void z80_exec(int aim)
+{
+  Pico.t.z80c_aim = aim;
+  Pico.t.z80c_cnt += z80_run(Pico.t.z80c_aim - Pico.t.z80c_cnt);
+}
+
 
 // ROM/SRAM bank mapping, see https://www.smspower.org/Development/Mappers
 
@@ -639,13 +645,13 @@ void PicoFrameMS(void)
   int is_pal = Pico.m.pal;
   int lines = is_pal ? 313 : 262;
   int cycles_line = 228;
-  int cycles_done = 0, cycles_aim = 0;
   int skip = PicoIn.skipFrame;
   int lines_vis = 192;
   int hint; // Hint counter
   int nmi;
   int y;
 
+  z80_resetCycles();
   PsndStartFrame();
 
   nmi = (PicoIn.pad[0] >> 7) & 1;
@@ -661,12 +667,19 @@ void PicoFrameMS(void)
   for (y = 0; y < lines; y++)
   {
     pv->v_counter = Pico.m.scanline = y;
-    if (y > 218)
-      pv->v_counter = y - 6;
+    switch (is_pal ? -lines_vis : lines_vis) {
+    case  192: if (y > 218) pv->v_counter = y - (lines-256); break;
+    case  224: if (y > 234) pv->v_counter = y - (lines-256); break;
+    case -192: if (y > 242) pv->v_counter = y - (lines-256); break;
+    case -224: if (y > 258) pv->v_counter = y - (lines-256); break;
+    case -240: if (y > 266) pv->v_counter = y - (lines-256); break;
+    }
 
     if (y < lines_vis && !skip)
       PicoLineSMS(y);
 
+    Pico.t.z80c_line_start = Pico.t.z80c_aim;
+
     // 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)
@@ -676,18 +689,19 @@ void PicoFrameMS(void)
       {
         hint = pv->reg[0x0a];
         pv->pending_ints |= 2;
-        cycles_done += z80_run(1);
+        z80_exec(Pico.t.z80c_cnt + 1);
+
         if ((pv->reg[0] & 0x10) && (pv->pending_ints & 2)) {
           elprintf(EL_INTS, "hint");
           z80_int_assert(1);
         }
-        pv->pending_ints &= ~2;
+        pv->pending_ints &= ~2; // lost if not caught immediately
       }
     }
     else if (y == lines_vis + 1) {
       pv->pending_ints &= ~2;
       pv->pending_ints |= 1;
-      cycles_done += z80_run(1);
+      z80_exec(Pico.t.z80c_cnt + 1);
 
       if ((pv->reg[1] & 0x20) && (pv->pending_ints & 1)) {
         elprintf(EL_INTS, "vint");
@@ -695,9 +709,7 @@ void PicoFrameMS(void)
       }
     }
 
-    cycles_aim += cycles_line;
-    Pico.t.z80c_aim = cycles_aim;
-    cycles_done += z80_run(cycles_aim - cycles_done);
+    z80_exec(Pico.t.z80c_line_start + cycles_line);
   }
 
   if (PicoIn.sndOut)