improved hi prio sprite rendering speed
authorkub <derkub@gmail.com>
Sat, 29 Feb 2020 22:45:23 +0000 (23:45 +0100)
committerkub <derkub@gmail.com>
Sat, 29 Feb 2020 22:45:23 +0000 (23:45 +0100)
pico/draw.c

index e654501..9ce727d 100644 (file)
@@ -100,7 +100,7 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
 #define blockcpy memcpy\r
 #endif\r
 \r
-#define TileNormMaker_(pix_func)                             \\r
+#define TileNormMaker_(pix_func,ret)                         \\r
 {                                                            \\r
   unsigned int t;                                            \\r
                                                              \\r
@@ -112,9 +112,10 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
   t = (pack&0x0f000000)>>24; pix_func(5);                    \\r
   t = (pack&0x00f00000)>>20; pix_func(6);                    \\r
   t = (pack&0x000f0000)>>16; pix_func(7);                    \\r
+  return ret;                                                \\r
 }\r
 \r
-#define TileFlipMaker_(pix_func)                             \\r
+#define TileFlipMaker_(pix_func,ret)                         \\r
 {                                                            \\r
   unsigned int t;                                            \\r
                                                              \\r
@@ -126,23 +127,24 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
   t = (pack&0x000000f0)>> 4; pix_func(5);                    \\r
   t = (pack&0x00000f00)>> 8; pix_func(6);                    \\r
   t = (pack&0x0000f000)>>12; pix_func(7);                    \\r
+  return ret;                                                \\r
 }\r
 \r
 #define TileNormMaker(funcname, pix_func) \\r
 static void funcname(unsigned char *pd, unsigned int pack, int pal) \\r
-TileNormMaker_(pix_func)\r
+TileNormMaker_(pix_func,)\r
 \r
 #define TileFlipMaker(funcname, pix_func) \\r
 static void funcname(unsigned char *pd, unsigned int pack, int pal) \\r
-TileFlipMaker_(pix_func)\r
+TileFlipMaker_(pix_func,)\r
 \r
 #define TileNormMakerAS(funcname, pix_func) \\r
-static void funcname(unsigned char *pd, unsigned char *mb, unsigned int pack, int pal) \\r
-TileNormMaker_(pix_func)\r
+static unsigned funcname(unsigned char *pd, unsigned m, unsigned int pack, int pal) \\r
+TileNormMaker_(pix_func,m)\r
 \r
 #define TileFlipMakerAS(funcname, pix_func) \\r
-static void funcname(unsigned char *pd, unsigned char *mb, unsigned int pack, int pal) \\r
-TileFlipMaker_(pix_func)\r
+static unsigned funcname(unsigned char *pd, unsigned m, unsigned int pack, int pal) \\r
+TileFlipMaker_(pix_func,m)\r
 \r
 #define pix_just_write(x) \\r
   if (t) pd[x]=pal|t\r
@@ -184,17 +186,19 @@ TileFlipMaker(TileFlipSH_onlyop_lp, pix_sh_onlyop)
 \r
 #endif\r
 \r
+// AS: sprite mask bits in m shifted to bits 8-15, see DrawSpritesHiAS\r
+\r
 // draw a sprite pixel (AS)\r
 #define pix_as(x) \\r
-  if (t & mb[x]) mb[x] = 0, pd[x] = pal | t\r
+  if (t && (m & (1<<(x+8)))) m &= ~(1<<(x+8)), pd[x] = pal | t\r
 \r
 TileNormMakerAS(TileNormAS, pix_as)\r
 TileFlipMakerAS(TileFlipAS, pix_as)\r
 \r
 // draw a sprite pixel, process operator colors (AS)\r
 #define pix_sh_as(x) \\r
-  if (t & mb[x]) { \\r
-    mb[x] = 0; \\r
+  if (t && (m & (1<<(x+8)))) { \\r
+    m &= ~(1<<(x+8)); \\r
     if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
     else pd[x] = pal | t; \\r
   }\r
@@ -203,8 +207,8 @@ TileNormMakerAS(TileNormSH_AS, pix_sh_as)
 TileFlipMakerAS(TileFlipSH_AS, pix_sh_as)\r
 \r
 #define pix_sh_as_onlyop(x) \\r
-  if (t & mb[x]) { \\r
-    mb[x] = 0; \\r
+  if (t && (m & (1<<(x+8)))) { \\r
+    m &= ~(1<<(x+8)); \\r
     pix_sh_onlyop(x); \\r
   }\r
 \r
@@ -213,7 +217,7 @@ TileFlipMakerAS(TileFlipSH_AS_onlyop_lp, pix_sh_as_onlyop)
 \r
 // mark pixel as sprite pixel (AS)\r
 #define pix_sh_as_onlymark(x) \\r
-  if (t) mb[x] = 0\r
+  if (t) m &= ~(1<<(x+8))\r
 \r
 TileNormMakerAS(TileNormAS_onlymark, pix_sh_as_onlymark)\r
 TileFlipMakerAS(TileFlipAS_onlymark, pix_sh_as_onlymark)\r
@@ -905,6 +909,10 @@ static NOINLINE void DrawAllSpritesInterlace(int pri, int sh)
  */\r
 static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)\r
 {\r
+  static void (*tilefuncs[2][2][2])(unsigned char *, unsigned, int) = {\r
+    { {NULL,                 NULL},                 {TileNorm,   TileFlip} },\r
+    { {TileNormSH_onlyop_lp, TileFlipSH_onlyop_lp}, {TileNormSH, TileFlipSH} }\r
+  }; // [sh?][hi?][flip?]\r
   void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal);\r
   unsigned char *pd = Pico.est.HighCol;\r
   unsigned char *p;\r
@@ -929,21 +937,8 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)
     code = sprite[1];\r
     pal = (code>>9)&0x30;\r
 \r
-    if (pal == 0x30)\r
-    {\r
-      if (code & 0x8000) // hi priority\r
-      {\r
-        if (code&0x800) fTileFunc=TileFlipSH;\r
-        else            fTileFunc=TileNormSH;\r
-      } else {\r
-        if (code&0x800) fTileFunc=TileFlipSH_onlyop_lp;\r
-        else            fTileFunc=TileNormSH_onlyop_lp;\r
-      }\r
-    } else {\r
-      if (!(code & 0x8000)) continue; // non-operator low sprite, already drawn\r
-      if (code&0x800) fTileFunc=TileFlip;\r
-      else            fTileFunc=TileNorm;\r
-    }\r
+    fTileFunc = tilefuncs[pal == 0x30][!!(code & 0x8000)][!!(code & 0x800)];\r
+    if (fTileFunc == NULL) continue; // non-operator low sprite, already drawn\r
 \r
     // parse remaining sprite data\r
     sy=sprite[0];\r
@@ -980,11 +975,15 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)
 \r
 static void DrawSpritesHiAS(unsigned char *sprited, int sh)\r
 {\r
-  void (*fTileFunc)(unsigned char *pd, unsigned char *mb,\r
-                    unsigned int pack, int pal);\r
+  static unsigned (*tilefuncs[2][2][2])(unsigned char *, unsigned, unsigned, int) = {\r
+    { {TileNormAS_onlymark,     TileFlipAS_onlymark},     {TileNormAS,    TileFlipAS} },\r
+    { {TileNormSH_AS_onlyop_lp, TileFlipSH_AS_onlyop_lp}, {TileNormSH_AS, TileFlipSH_AS} }\r
+  }; // [sh?][hi?][flip?]\r
+  unsigned (*fTileFunc)(unsigned char *pd, unsigned m, unsigned int pack, int pal);\r
   unsigned char *pd = Pico.est.HighCol;\r
-  unsigned char mb[8+320+8];\r
-  unsigned char *p;\r
+  unsigned char mb[1+320/8+1];\r
+  unsigned char *p, *mp;\r
+  unsigned m;\r
   int entry, cnt;\r
 \r
   cnt = sprited[0] & 0x7f;\r
@@ -1006,26 +1005,7 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
     code = sprite[1];\r
     pal = (code>>9)&0x30;\r
 \r
-    if (sh && pal == 0x30)\r
-    {\r
-      if (code & 0x8000) // hi priority\r
-      {\r
-        if (code&0x800) fTileFunc = TileFlipSH_AS;\r
-        else            fTileFunc = TileNormSH_AS;\r
-      } else {\r
-        if (code&0x800) fTileFunc = TileFlipSH_AS_onlyop_lp;\r
-        else            fTileFunc = TileNormSH_AS_onlyop_lp;\r
-      }\r
-    } else {\r
-      if (code & 0x8000) // hi priority\r
-      {\r
-        if (code&0x800) fTileFunc = TileFlipAS;\r
-        else            fTileFunc = TileNormAS;\r
-      } else {\r
-        if (code&0x800) fTileFunc = TileFlipAS_onlymark;\r
-        else            fTileFunc = TileNormAS_onlymark;\r
-      }\r
-    }\r
+    fTileFunc = tilefuncs[(sh && pal == 0x30)][!!(code&0x8000)][!!(code&0x800)];\r
 \r
     // parse remaining sprite data\r
     sy=sprite[0];\r
@@ -1054,8 +1034,12 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
       if(sx>=328) break; // Offscreen\r
 \r
       pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff));\r
-      fTileFunc(pd + sx, mb + sx, pack, pal);\r
-    }\r
+\r
+      m = (m >> 8) | mp[1] << 8; // next mask byte\r
+      // shift mask bits to bits 8-15 for easier load/store handling\r
+      m = fTileFunc(pd + sx, m << (8-(sx&0x7)), pack, pal) >> (8-(sx&0x7));\r
+    } \r
+    *mp = m >> 8; // write last mask byte\r
   }\r
 }\r
 \r
@@ -1106,7 +1090,8 @@ static void DrawSpritesForced(unsigned char *sprited)
     delta<<=4; // Delta of address\r
 \r
     if (entry+1 == cnt) width = p[entry+1]; // last sprite width limited?\r
-    for (; width; width--,sx+=8,tile+=delta)\r
+    mp = mb+(sx>>3);\r
+    for (m = *mp << 8; width; width--, sx+=8, *mp++ = m, tile+=delta)\r
     {\r
       unsigned int pack;\r
 \r