md vdp, fix sprite parsing (done on previous line)
authorkub <derkub@gmail.com>
Sun, 26 Mar 2023 10:33:29 +0000 (10:33 +0000)
committerkub <derkub@gmail.com>
Sun, 26 Mar 2023 10:33:29 +0000 (10:33 +0000)
pico/draw.c
pico/pico_int.h
pico/videoport.c

index c1e8c4d..011a1a3 100644 (file)
@@ -63,7 +63,7 @@ static u32 HighCacheA[41*2+1]; // caches for high layers
 static u32 HighCacheB[41*2+1];\r
 static s32 HighPreSpr[80*2+1]; // slightly preprocessed sprites\r
 \r
-u32 VdpSATCache[128];  // VDP sprite cache (1st 32 sprite attr bits)\r
+u32 VdpSATCache[2*128];  // VDP sprite cache (1st 32 sprite attr bits)\r
 \r
 // NB don't change any defines without checking their usage in ASM\r
 \r
@@ -1401,7 +1401,7 @@ static void DrawSpritesForced(unsigned char *sprited)
 // Index + 0  :    hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size\r
 // Index + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
 \r
-static NOINLINE void PrepareSprites(int max_lines)\r
+static NOINLINE void ParseSprites(int max_lines)\r
 {\r
   const struct PicoVideo *pvid=&Pico.video;\r
   const struct PicoEState *est=&Pico.est;\r
@@ -1411,6 +1411,12 @@ static NOINLINE void PrepareSprites(int max_lines)
   int max_sprites = 80, max_width = 328;\r
   int max_line_sprites = 20; // 20 sprites, 40 tiles\r
 \r
+  // SAT scanning is one line ahead, but don't overshoot. Technically, SAT\r
+  // parsing for line 0 is on the last line of the previous frame.\r
+  int first_line = Pico.est.DrawScanline + !!Pico.est.DrawScanline;\r
+  if (max_lines > rendlines-1)\r
+    max_lines = rendlines-1;\r
+\r
   if (!(Pico.video.reg[12]&1))\r
     max_sprites = 64, max_line_sprites = 16, max_width = 264;\r
   if (*est->PicoOpt & POPT_DIS_SPRITE_LIM)\r
@@ -1422,7 +1428,7 @@ static NOINLINE void PrepareSprites(int max_lines)
   if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode\r
   table<<=8; // Get sprite table address/2\r
 \r
-  for (u = est->DrawScanline; u < max_lines; u++)\r
+  for (u = first_line; u <= max_lines; u++)\r
     *((int *)&HighLnSpr[u][0]) = 0;\r
 \r
   for (u = 0; u < max_sprites && link < max_sprites; u++)\r
@@ -1434,7 +1440,7 @@ static NOINLINE void PrepareSprites(int max_lines)
 \r
     // parse sprite info. the 1st half comes from the VDPs internal cache,\r
     // the 2nd half is read from VRAM\r
-    code = CPU_LE2(VdpSATCache[link]); // normally same as sprite[0]\r
+    code = CPU_LE2(VdpSATCache[2*link]); // normally same as sprite[0]\r
     sy = (code&0x1ff)-0x80;\r
     hv = (code>>24)&0xf;\r
     height = (hv&3)+1;\r
@@ -1444,7 +1450,7 @@ static NOINLINE void PrepareSprites(int max_lines)
     sx = (code2>>16)&0x1ff;\r
     sx -= 0x78; // Get X coordinate + 8\r
 \r
-    if (sy < max_lines && sy + (height<<3) >= est->DrawScanline) // sprite onscreen (y)?\r
+    if (sy <= max_lines && sy + (height<<3) >= first_line) // sprite onscreen (y)?\r
     {\r
       int entry, y, w, sx_min, onscr_x, maybe_op = 0;\r
 \r
@@ -1454,8 +1460,8 @@ static NOINLINE void PrepareSprites(int max_lines)
         maybe_op = SPRL_MAY_HAVE_OP;\r
 \r
       entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);\r
-      y = (sy >= est->DrawScanline) ? sy : est->DrawScanline;\r
-      for (; y < sy + (height<<3) && y < max_lines; y++)\r
+      y = (sy >= first_line) ? sy : first_line;\r
+      for (; y < sy + (height<<3) && y <= max_lines; y++)\r
       {\r
         unsigned char *p = &HighLnSpr[y][0];\r
         int cnt = p[0];\r
@@ -1501,7 +1507,7 @@ static NOINLINE void PrepareSprites(int max_lines)
   *pd = 0;\r
 \r
 #if 0\r
-  for (u = 0; u < max_lines; u++)\r
+  for (u = first_line; u <= max_lines; u++)\r
   {\r
     int y;\r
     printf("c%03i: f %x c %2i/%2i w %2i: ", u, HighLnSpr[u][1],\r
@@ -1982,9 +1988,9 @@ void PicoDrawSync(int to, int blank_last_line)
     if (to > 223)\r
       to = 223;\r
   }\r
-  if (est->DrawScanline <= to - blank_last_line && (est->rendstatus &\r
+  if (est->DrawScanline <= to && (est->rendstatus &\r
                 (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))\r
-    PrepareSprites(to - blank_last_line + 1);\r
+    ParseSprites(to + 1);\r
 \r
   for (line = est->DrawScanline; line < to; line++)\r
     PicoLine(line, offs, sh, bgc);\r
index 1bb7b25..e330413 100644 (file)
@@ -705,7 +705,7 @@ extern unsigned char *HighColBase;
 extern int HighColIncrement;\r
 extern void *DrawLineDestBase;\r
 extern int DrawLineDestIncrement;\r
-extern u32 VdpSATCache[128];\r
+extern u32 VdpSATCache[2*128];\r
 \r
 // draw2.c\r
 void PicoDraw2SetOutBuf(void *dest, int incr);\r
@@ -890,9 +890,7 @@ static __inline void UpdateSAT(u32 a, u32 d)
   unsigned num = (a^SATaddr) >> 3;\r
 \r
   Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
-  if (!(a & 4) && num < 128) {\r
-    ((u16 *)&VdpSATCache[num])[(a&3) >> 1] = d;\r
-  }\r
+  ((u16 *)&VdpSATCache[2*num])[(a&7) >> 1] = d;\r
 }\r
 static __inline void VideoWriteVRAM(u32 a, u16 d)\r
 {\r
index 7f567f1..ce356f6 100644 (file)
@@ -1104,8 +1104,8 @@ void PicoVideoCacheSAT(int load)
     SATaddr &= ~0x200, SATmask &= ~0x200; // H40, zero lowest SAT bit\r
 \r
   // rebuild SAT cache XXX wrong since cache and memory can differ\r
-  for (l = 0; load && l < 80; l++) {\r
-    u16 addr = SATaddr + l*8;\r
+  for (l = 0; load && l < 2*80; l ++) {\r
+    u16 addr = SATaddr + l*4;\r
     ((u16 *)VdpSATCache)[l*2    ] = PicoMem.vram[(addr>>1)    ];\r
     ((u16 *)VdpSATCache)[l*2 + 1] = PicoMem.vram[(addr>>1) + 1];\r
   }\r