vdp, some finetuning, cleanup
authorkub <derkub@gmail.com>
Tue, 8 Jun 2021 20:26:24 +0000 (22:26 +0200)
committerkub <derkub@gmail.com>
Tue, 8 Jun 2021 20:26:24 +0000 (22:26 +0200)
pico/videoport.c

index cadf956..44a02fb 100644 (file)
@@ -19,13 +19,24 @@ enum { clkdiv = 2 };    // CPU clock granularity: one of 1,2,4,8
 //     forum/viewtopic.php?f=22&t=851&sid=d5701a71396ee7f700c74fb7cd85cb09\r
 // Thank you very much for the great work, Nemesis!\r
 \r
+// Slot clock is sysclock/20 for h32 and sysclock/16 for h40.\r
+// One scanline is 63.7us/63.5us (h32/h40) long which is 488.6/487.4 68k cycles.\r
+// Assume 488 for everything.\r
 // 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40.\r
+enum { slcpu = 488 };\r
 \r
 // VDP has a slot counter running from 0x00 to 0xff every scanline, but it has\r
 // a gap depending on the video mode. The slot in which a horizontal interrupt\r
 // is generated also depends on the video mode.\r
-enum { hint32 = 0x84, gapstart32 = 0x94, gapend32 = 0xe9 };\r
-enum { hint40 = 0xa4, gapstart40 = 0xb7, gapend40 = 0xe5 };\r
+enum { hint32 = 0x85, gapstart32 = 0x94, gapend32 = 0xe9};\r
+enum { hint40 = 0xa5, gapstart40 = 0xb7, gapend40 = 0xe5};\r
+\r
+// The horizontal sync period (HBLANK) is 30/37 slots (h32/h40):\r
+// h32: 4 slots front porch (1.49us), 13 HSYNC (4.84us), 13 back porch (4.84us)\r
+// h40: 5 slots front porch (1.49us), 16 HSYNC (4.77us), 16 back porch (4.77us)\r
+// HBLANK starts in slot 0x93/0xb4, according to Nemesis' measurements.\r
+enum { hboff32 = 0x93-hint32, hblen32 = 0xf8-(gapend32-gapstart32)-hint32};//30\r
+enum { hboff40 = 0xb4-hint40, hblen40 = 0xf8-(gapend40-gapstart40)-hint40};//37\r
 \r
 // number of slots in a scanline\r
 #define slots32        (0x100-(gapend32-gapstart32)) // 171\r
@@ -46,16 +57,17 @@ static u8 refslots40[] =
     {        250,     26,       58,       90,         122,         154 };\r
 \r
 // table sizes\r
-enum { cycsz = 488/clkdiv };\r
+enum { cycsz = slcpu/clkdiv };\r
 enum { sl32blsz=slots32-sizeof(refslots32)+1, sl32acsz=sizeof(dmaslots32)+1 };\r
 enum { sl40blsz=slots40-sizeof(refslots40)+1, sl40acsz=sizeof(dmaslots40)+1 };\r
 \r
 // Tables must be considerably larger than one scanline, since 68k emulation\r
 // isn't stopping in the middle of an operation. If the last op is a 32 bit\r
-// VDP write 2 slots may need to be taken from the next scanline, which can be\r
+// VDP access 2 slots may need to be taken from the next scanline, which can be\r
 // more than 100 CPU cycles. For safety just cover 2 scanlines.\r
 \r
-// table for mapping hvcounter reads\r
+// table for hvcounter mapping. check: Sonic 3D Blast bonus, Cannon Fodder,\r
+// Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune\r
 static u8  hcounts_32[2*cycsz], hcounts_40[2*cycsz];\r
 // tables mapping cycles to slots\r
 static u16 vdpcyc2sl_32_bl[2*cycsz],vdpcyc2sl_40_bl[2*cycsz];\r
@@ -69,7 +81,7 @@ static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz];
 // calculate timing tables for one mode (H32 or H40)\r
 // NB tables aligned to HINT, since the main loop uses HINT as synchronization\r
 #define INITTABLES(s) { \\r
-  float factor = 488./slots##s;                                                \\r
+  float factor = (float)slcpu/slots##s;                                        \\r
   int ax, bx, rx, ac, bc;                                              \\r
   int i, n;                                                            \\r
                                                                        \\r
@@ -77,9 +89,8 @@ static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz];
   for (i = 0; i < cycsz; i++) {                                                \\r
     n = hint##s + i*clkdiv/factor;                                     \\r
     if (n >= gapstart##s) n += gapend##s-gapstart##s;                  \\r
-       hcounts_##s[i] = n % 256;                                       \\r
+    hcounts_##s[i] = n % 256;                                          \\r
   }                                                                    \\r
-  memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\\r
                                                                        \\r
   ax = bx = ac = bc = rx = 0;                                          \\r
   for (i = 0; i < cycsz; i++) {                                                \\r
@@ -103,12 +114,14 @@ static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz];
     vdpcyc2sl_##s##_ac[ac] = ARRAY_SIZE(dmaslots##s),          ac++;   \\r
   while (bc < cycsz)                                                   \\r
     vdpcyc2sl_##s##_bl[bc] = slots##s-ARRAY_SIZE(refslots##s), bc++;   \\r
+                                                                       \\r
   /* extend tables for 2nd scanline */                                 \\r
+  memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\\r
   i = ARRAY_SIZE(dmaslots##s);                                         \\r
   while (ac < ARRAY_SIZE(vdpcyc2sl_##s##_ac))                          \\r
     vdpcyc2sl_##s##_ac[ac] = vdpcyc2sl_##s##_ac[ac-cycsz]+i,   ac++;   \\r
   while (ax < ARRAY_SIZE(vdpsl2cyc_##s##_ac)-1)                        ax++,   \\r
-    vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz;\\r
+    vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz;           \\r
   i = slots##s - ARRAY_SIZE(refslots##s);                              \\r
   while (bc < ARRAY_SIZE(vdpcyc2sl_##s##_bl))                          \\r
     vdpcyc2sl_##s##_bl[bc] = vdpcyc2sl_##s##_bl[bc-cycsz]+i,   bc++;   \\r
@@ -198,7 +211,8 @@ static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, i
   if (l > cnt)\r
     l = cnt;\r
   if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA))\r
-    if ((vf->fifo_total -= ((cnt & b) + l) >> b) < 0) vf->fifo_total = 0;\r
+    vf->fifo_total -= ((cnt & b) + l) >> b;\r
+  if (vf->fifo_total < 0) vf->fifo_total = 0;\r
   cnt -= l;\r
 \r
   // if entry has been processed...\r
@@ -371,7 +385,7 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags)
 \r
     // update FIFO state if it was empty\r
     if (!(pv->status & PVS_FIFORUN)) {\r
-      vf->fifo_slot = Cyc2Sl(vf, lc+5); // FIFO latency ~3 vdp slots\r
+      vf->fifo_slot = Cyc2Sl(vf, lc+7); // FIFO latency ~3 vdp slots\r
       pv->status |= PVS_FIFORUN;\r
       pv->fifo_cnt = count << (flags & FQ_BYTE);\r
     }\r
@@ -829,8 +843,8 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
   case 0x00: // Data port 0 or 2\r
     // try avoiding the sync..\r
     if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) &&\r
-        !(!pvid->pending &&\r
-          ((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == (d & 0x7ff)))\r
+        !(!pvid->pending && ((pvid->command & 0xc00000f0) == 0x40000010 &&\r
+                        PicoMem.vsram[(pvid->addr>>1) & 0x3f] == (d & 0x7ff)))\r
        )\r
       DrawSync(0); // XXX  it's unclear when vscroll data is fetched from vsram?\r
 \r
@@ -988,10 +1002,10 @@ update_irq:
 \r
 static u32 VideoSr(const struct PicoVideo *pv)\r
 {\r
-  unsigned int hp = pv->reg[12]&1 ? 15*488/210+1 : 15*488/171+1; // HBLANK start\r
-  unsigned int hl = pv->reg[12]&1 ? 37*488/210+1 : 28*488/171+1; // HBLANK len\r
+  unsigned int hp = pv->reg[12]&1 ? hboff40*488/slots40 : hboff32*488/slots32;\r
+  unsigned int hl = pv->reg[12]&1 ? hblen40*488/slots40 : hblen32*488/slots32;\r
   unsigned int c;\r
-  u32 d = pv->status;\r
+  u32 d = (u16)pv->status;\r
 \r
   c = SekCyclesDone() - Pico.t.m68c_line_start;\r
   if (c - hp < hl)\r
@@ -1021,32 +1035,17 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a)
     return d;\r
   }\r
 \r
-  // H-counter info (based on Generator):\r
-  // frame:\r
-  //                       |       <- hblank? ->      |\r
-  // start    <416>       hint  <36> hdisplay <38>  end // CPU cycles\r
-  // |---------...---------|------------|-------------|\r
-  // 0                   B6 E4                       FF // 40 cells\r
-  // 0                   93 E8                       FF // 32 cells\r
-\r
-  // Gens (?)              v-render\r
-  // start  <hblank=84>   hint    hdisplay <404>      |\r
-  // |---------------------|--------------------------|\r
-  // E4  (hc[0x43]==0)    07                         B1 // 40\r
-  // E8  (hc[0x45]==0)    05                         91 // 32\r
-\r
-  // check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune\r
   if ((a&0x1c)==0x08)\r
   {\r
     unsigned int c;\r
     u32 d;\r
 \r
-    c = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME\r
+    c = SekCyclesDone() - Pico.t.m68c_line_start;\r
     if (Pico.video.reg[0]&2)\r
          d = Pico.video.hv_latch;\r
     else if (Pico.video.reg[12]&1)\r
-         d = hcounts_40[c/2] | (Pico.video.v_counter << 8);\r
-    else d = hcounts_32[c/2] | (Pico.video.v_counter << 8);\r
+         d = hcounts_40[c/clkdiv] | (Pico.video.v_counter << 8);\r
+    else d = hcounts_32[c/clkdiv] | (Pico.video.v_counter << 8);\r
 \r
     elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);\r
     return d;\r
@@ -1103,12 +1102,12 @@ unsigned char PicoVideoRead8HV_H(int is_from_z80)
 // FIXME: broken\r
 unsigned char PicoVideoRead8HV_L(int is_from_z80)\r
 {\r
-  u32 d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME\r
+  u32 d = SekCyclesDone() - Pico.t.m68c_line_start;\r
   if (Pico.video.reg[0]&2)\r
        d = Pico.video.hv_latch;\r
   else if (Pico.video.reg[12]&1)\r
-       d = hcounts_40[d/2];\r
-  else d = hcounts_32[d/2];\r
+       d = hcounts_40[d/clkdiv];\r
+  else d = hcounts_32[d/clkdiv];\r
   elprintf(EL_HVCNT, "hcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc);\r
   return d;\r
 }\r