fix DrawSpritesHiAS
authornotaz <notasas@gmail.com>
Sat, 27 Jan 2018 21:46:37 +0000 (23:46 +0200)
committernotaz <notasas@gmail.com>
Sat, 27 Jan 2018 21:46:37 +0000 (23:46 +0200)
pico/draw.c
pico/pico.h
platform/psp/emu.c

index 0939f3f..680de3d 100644 (file)
  * - "sonic mode" for midline palette changes (8bit mode only)\r
  * - accurate sprites (AS) [+ s/h]\r
  *\r
- * AS and s/h both use upper bits for both priority and shadow/hilight flags.\r
+ * s/h uses upper bits for both priority and shadow/hilight flags.\r
  * "sonic mode" is autodetected, shadow/hilight is enabled by emulated game.\r
  * AS is enabled by user and takes priority over "sonic mode".\r
  *\r
  * since renderer always draws line in 8bit mode, there are 2 spare bits:\r
- * b \ mode: s/h             as        sonic\r
- * 00        normal          -         pal index\r
- * 01        shadow          -         pal index\r
- * 10        hilight+op spr  spr       pal index\r
- * 11        shadow +op spr  -         pal index\r
+ * b \ mode: s/h             sonic\r
+ * 00        normal          pal index\r
+ * 01        shadow          pal index\r
+ * 10        hilight+op spr  pal index\r
+ * 11        shadow +op spr  pal index\r
  *\r
  * not handled properly:\r
  * - hilight op on shadow tile\r
- * - AS + s/h (s/h sprite flag interferes with and cleared by AS code)\r
  */\r
 \r
 #include "pico_int.h"\r
@@ -95,11 +94,8 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
 #define blockcpy memcpy\r
 #endif\r
 \r
-\r
-#define TileNormMaker(funcname,pix_func)                     \\r
-static void funcname(int sx, unsigned int pack, int pal)     \\r
+#define TileNormMaker_(pix_func)                             \\r
 {                                                            \\r
-  unsigned char *pd = Pico.est.HighCol + sx;                 \\r
   unsigned int t;                                            \\r
                                                              \\r
   t = (pack&0x0000f000)>>12; pix_func(0);                    \\r
@@ -112,10 +108,8 @@ static void funcname(int sx, unsigned int pack, int pal)     \
   t = (pack&0x000f0000)>>16; pix_func(7);                    \\r
 }\r
 \r
-#define TileFlipMaker(funcname,pix_func)                     \\r
-static void funcname(int sx, unsigned int pack, int pal)     \\r
+#define TileFlipMaker_(pix_func)                             \\r
 {                                                            \\r
-  unsigned char *pd = Pico.est.HighCol + sx;                 \\r
   unsigned int t;                                            \\r
                                                              \\r
   t = (pack&0x000f0000)>>16; pix_func(0);                    \\r
@@ -128,6 +122,21 @@ static void funcname(int sx, unsigned int pack, int pal)     \
   t = (pack&0x0000f000)>>12; pix_func(7);                    \\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
+\r
+#define TileFlipMaker(funcname, pix_func) \\r
+static void funcname(unsigned char *pd, unsigned int pack, int pal) \\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
+\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
 \r
 #define pix_just_write(x) \\r
   if (t) pd[x]=pal|t\r
@@ -155,11 +164,15 @@ TileFlipMaker(TileFlipSH, pix_sh)
 TileNormMaker(TileNormSH_markop, pix_sh_markop)\r
 TileFlipMaker(TileFlipSH_markop, pix_sh_markop)\r
 \r
+#endif\r
+\r
 // process operator pixels only, apply only on low pri tiles and other op pixels\r
 #define pix_sh_onlyop(x) \\r
   if (t>=0xe && (pd[x]&0xc0)) \\r
     pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
 \r
+#ifndef _ASM_DRAW_C\r
+\r
 TileNormMaker(TileNormSH_onlyop_lp, pix_sh_onlyop)\r
 TileFlipMaker(TileFlipSH_onlyop_lp, pix_sh_onlyop)\r
 \r
@@ -167,26 +180,39 @@ TileFlipMaker(TileFlipSH_onlyop_lp, pix_sh_onlyop)
 \r
 // draw a sprite pixel (AS)\r
 #define pix_as(x) \\r
-  if (t && !(pd[x]&0x80)) pd[x]=pal|t\r
+  if (t & mb[x]) mb[x] = 0, pd[x] = pal | t\r
 \r
-TileNormMaker(TileNormAS, pix_as)\r
-TileFlipMaker(TileFlipAS, pix_as)\r
+TileNormMakerAS(TileNormAS, pix_as)\r
+TileFlipMakerAS(TileFlipAS, pix_as)\r
 \r
-// draw a sprite pixel, skip operator colors (AS)\r
-#define pix_sh_as_noop(x) \\r
-  if (t && t < 0xe && !(pd[x]&0x80)) pd[x]=pal|t\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>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
+    else pd[x] = pal | t; \\r
+  }\r
+\r
+TileNormMakerAS(TileNormSH_AS, pix_sh_as)\r
+TileFlipMakerAS(TileFlipSH_AS, pix_sh_as)\r
+\r
+#define pix_sh_as_onlyop(x) \\r
+  if (t & mb[x]) { \\r
+    mb[x] = 0; \\r
+    pix_sh_onlyop(x); \\r
+  }\r
 \r
-TileNormMaker(TileNormAS_noop, pix_sh_as_noop)\r
-TileFlipMaker(TileFlipAS_noop, pix_sh_as_noop)\r
+TileNormMakerAS(TileNormSH_AS_onlyop_lp, pix_sh_as_onlyop)\r
+TileFlipMakerAS(TileFlipSH_AS_onlyop_lp, pix_sh_as_onlyop)\r
 \r
 // mark pixel as sprite pixel (AS)\r
 #define pix_sh_as_onlymark(x) \\r
-  if (t) pd[x]|=0x80\r
+  if (t) mb[x] = 0\r
 \r
-TileNormMaker(TileNormAS_onlymark, pix_sh_as_onlymark)\r
-TileFlipMaker(TileFlipAS_onlymark, pix_sh_as_onlymark)\r
+TileNormMakerAS(TileNormAS_onlymark, pix_sh_as_onlymark)\r
+TileFlipMakerAS(TileFlipAS_onlymark, pix_sh_as_onlymark)\r
 \r
-// mark pixel as sprite pixel (AS)\r
+// forced both layer draw (through debug reg)\r
 #define pix_and(x) \\r
   pd[x] = (pd[x] & 0xc0) | (pd[x] & (pal | t))\r
 \r
@@ -198,6 +224,7 @@ TileFlipMaker(TileFlip_and, pix_and)
 #ifndef _ASM_DRAW_C\r
 static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip)\r
 {\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int tilex,dx,ty,code=0,addr=0,cells;\r
   int oldcode=-1,blank=-1; // The tile we know is blank\r
   int pal=0,sh;\r
@@ -241,8 +268,8 @@ static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip)
       continue;\r
     }\r
 \r
-    if (code & 0x0800) TileFlip(dx, pack, pal);\r
-    else               TileNorm(dx, pack, pal);\r
+    if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+    else               TileNorm(pd + dx, pack, pal);\r
   }\r
 \r
   // terminate the cache list\r
@@ -254,6 +281,7 @@ static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip)
 // this is messy\r
 static void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip)\r
 {\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int tilex,dx,code=0,addr=0,cell=0;\r
   int oldcode=-1,blank=-1; // The tile we know is blank\r
   int pal=0,scan=Pico.est.DrawScanline;\r
@@ -310,8 +338,8 @@ static void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip)
       continue;\r
     }\r
 \r
-    if (code & 0x0800) TileFlip(dx, pack, pal);\r
-    else               TileNorm(dx, pack, pal);\r
+    if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+    else               TileNorm(pd + dx, pack, pal);\r
   }\r
 \r
   // terminate the cache list\r
@@ -325,6 +353,7 @@ static
 #endif\r
 void DrawStripInterlace(struct TileStrip *ts)\r
 {\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int tilex=0,dx=0,ty=0,code=0,addr=0,cells;\r
   int oldcode=-1,blank=-1; // The tile we know is blank\r
   int pal=0;\r
@@ -366,8 +395,8 @@ void DrawStripInterlace(struct TileStrip *ts)
       continue;\r
     }\r
 \r
-    if (code & 0x0800) TileFlip(dx, pack, pal);\r
-    else               TileNorm(dx, pack, pal);\r
+    if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+    else               TileNorm(pd + dx, pack, pal);\r
   }\r
 \r
   // terminate the cache list\r
@@ -447,7 +476,8 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells,
 static void DrawWindow(int tstart, int tend, int prio, int sh,\r
                        struct PicoEState *est)\r
 {\r
-  struct PicoVideo *pvid=&Pico.video;\r
+  unsigned char *pd = Pico.est.HighCol;\r
+  struct PicoVideo *pvid = &Pico.video;\r
   int tilex,ty,nametab,code=0;\r
   int blank=-1; // The tile we know is blank\r
 \r
@@ -504,8 +534,8 @@ static void DrawWindow(int tstart, int tend, int prio, int sh,
       pal = ((code >> 9) & 0x30);\r
       dx = 8 + (tilex << 3);\r
 \r
-      if (code & 0x0800) TileFlip(dx, pack, pal);\r
-      else               TileNorm(dx, pack, pal);\r
+      if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+      else               TileNorm(pd + dx, pack, pal);\r
     }\r
   }\r
   else\r
@@ -545,8 +575,8 @@ static void DrawWindow(int tstart, int tend, int prio, int sh,
 \r
       dx = 8 + (tilex << 3);\r
 \r
-      if (code & 0x0800) TileFlip(dx, pack, pal);\r
-      else               TileNorm(dx, pack, pal);\r
+      if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+      else               TileNorm(pd + dx, pack, pal);\r
     }\r
   }\r
 }\r
@@ -568,6 +598,7 @@ static void DrawTilesFromCacheShPrep(void)
 \r
 static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est)\r
 {\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int code, addr, dx;\r
   unsigned int pack;\r
   int pal;\r
@@ -602,8 +633,8 @@ static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est
       if (rlim-dx < 0)\r
         goto last_cut_tile;\r
 \r
-      if (code & 0x0800) TileFlip(dx, pack, pal);\r
-      else               TileNorm(dx, pack, pal);\r
+      if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+      else               TileNorm(pd + dx, pack, pal);\r
     }\r
   }\r
   else\r
@@ -627,8 +658,8 @@ static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est
       if (rlim - dx < 0)\r
         goto last_cut_tile;\r
 \r
-      if (code & 0x0800) TileFlip(dx, pack, pal);\r
-      else               TileNorm(dx, pack, pal);\r
+      if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
+      else               TileNorm(pd + dx, pack, pal);\r
     }\r
   }\r
   return;\r
@@ -636,9 +667,9 @@ static void DrawTilesFromCache(int *hc, int sh, int rlim, struct PicoEState *est
 last_cut_tile:\r
   // for vertical window cutoff\r
   {\r
-    unsigned char *pd = est->HighCol + dx;\r
     unsigned int t;\r
 \r
+    pd += dx;\r
     if (code&0x0800)\r
     {\r
       switch (rlim-dx+8)\r
@@ -677,12 +708,13 @@ last_cut_tile:
 \r
 static void DrawSprite(int *sprite, int sh)\r
 {\r
+  void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal);\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int width=0,height=0;\r
   int row=0,code=0;\r
   int pal;\r
   int tile=0,delta=0;\r
   int sx, sy;\r
-  void (*fTileFunc)(int sx, unsigned int pack, int pal);\r
 \r
   // parse the sprite data\r
   sy=sprite[0];\r
@@ -722,13 +754,14 @@ static void DrawSprite(int *sprite, int sh)
     if(sx>=328) break; // Offscreen\r
 \r
     pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff));\r
-    fTileFunc(sx, pack, pal);\r
+    fTileFunc(pd + sx, pack, pal);\r
   }\r
 }\r
 #endif\r
 \r
 static NOINLINE void DrawTilesFromCacheForced(const int *hc)\r
 {\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int code, addr, dx;\r
   unsigned int pack;\r
   int pal;\r
@@ -743,13 +776,14 @@ static NOINLINE void DrawTilesFromCacheForced(const int *hc)
     pal = ((code >> 9) & 0x30);\r
     pack = *(unsigned int *)(PicoMem.vram + addr);\r
 \r
-    if (code & 0x0800) TileFlip_and(dx, pack, pal);\r
-    else               TileNorm_and(dx, pack, pal);\r
+    if (code & 0x0800) TileFlip_and(pd + dx, pack, pal);\r
+    else               TileNorm_and(pd + dx, pack, pal);\r
   }\r
 }\r
 \r
 static void DrawSpriteInterlace(unsigned int *sprite)\r
 {\r
+  unsigned char *pd = Pico.est.HighCol;\r
   int width=0,height=0;\r
   int row=0,code=0;\r
   int pal;\r
@@ -788,8 +822,8 @@ static void DrawSpriteInterlace(unsigned int *sprite)
     if(sx>=328) break; // Offscreen\r
 \r
     pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff));\r
-    if (code & 0x0800) TileFlip(sx, pack, pal);\r
-    else               TileNorm(sx, pack, pal);\r
+    if (code & 0x0800) TileFlip(pd + sx, pack, pal);\r
+    else               TileNorm(pd + sx, pack, pal);\r
   }\r
 }\r
 \r
@@ -851,7 +885,8 @@ static NOINLINE void DrawAllSpritesInterlace(int pri, int sh)
  */\r
 static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)\r
 {\r
-  void (*fTileFunc)(int sx, unsigned int pack, int pal);\r
+  void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal);\r
+  unsigned char *pd = Pico.est.HighCol;\r
   unsigned char *p;\r
   int cnt;\r
 \r
@@ -913,7 +948,7 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)
       if(sx>=328) break; // Offscreen\r
 \r
       pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff));\r
-      fTileFunc(sx, pack, pal);\r
+      fTileFunc(pd + sx, pack, pal);\r
     }\r
   }\r
 }\r
@@ -921,15 +956,17 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)
 \r
 static void DrawSpritesHiAS(unsigned char *sprited, int sh)\r
 {\r
-  void (*fTileFunc)(int sx, unsigned int pack, int pal);\r
+  void (*fTileFunc)(unsigned char *pd, unsigned char *mb,\r
+                    unsigned int pack, int pal);\r
+  unsigned char *pd = Pico.est.HighCol;\r
+  unsigned char mb[8+320+8];\r
   unsigned char *p;\r
-  int entry, cnt, sh_cnt = 0;\r
+  int entry, cnt;\r
 \r
   cnt = sprited[0] & 0x7f;\r
   if (cnt == 0) return;\r
 \r
-  Pico.est.rendstatus |= PDRAW_SPR_LO_ON_HI;\r
-\r
+  memset(mb, 0xff, sizeof(mb));\r
   p = &sprited[3];\r
 \r
   // Go through sprites:\r
@@ -943,22 +980,26 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
     code = sprite[1];\r
     pal = (code>>9)&0x30;\r
 \r
-    if (code & 0x8000) // hi priority\r
+    if (sh && pal == 0x30)\r
     {\r
-      if (sh && pal == 0x30)\r
+      if (code & 0x8000) // hi priority\r
       {\r
-        if (code&0x800) fTileFunc=TileFlipAS_noop;\r
-        else            fTileFunc=TileNormAS_noop;\r
+        if (code&0x800) fTileFunc = TileFlipSH_AS;\r
+        else            fTileFunc = TileNormSH_AS;\r
       } else {\r
-        if (code&0x800) fTileFunc=TileFlipAS;\r
-        else            fTileFunc=TileNormAS;\r
+        if (code&0x800) fTileFunc = TileFlipSH_AS_onlyop_lp;\r
+        else            fTileFunc = TileNormSH_AS_onlyop_lp;\r
       }\r
     } else {\r
-      if (code&0x800) fTileFunc=TileFlipAS_onlymark;\r
-      else            fTileFunc=TileNormAS_onlymark;\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
-    if (sh && pal == 0x30)\r
-      p[sh_cnt++] = offs / 2; // re-save for sh/hi pass\r
 \r
     // parse remaining sprite data\r
     sy=sprite[0];\r
@@ -978,7 +1019,6 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
     tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address\r
     delta<<=4; // Delta of address\r
 \r
-    pal |= 0x80;\r
     for (; width; width--,sx+=8,tile+=delta)\r
     {\r
       unsigned int pack;\r
@@ -987,25 +1027,9 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
       if(sx>=328) break; // Offscreen\r
 \r
       pack = *(unsigned int *)(PicoMem.vram + (tile & 0x7fff));\r
-      fTileFunc(sx, pack, pal);\r
+      fTileFunc(pd + sx, mb + sx, pack, pal);\r
     }\r
   }\r
-\r
-  if (!sh || !(sprited[1]&SPRL_MAY_HAVE_OP)) return;\r
-\r
-  /* nasty 1: remove 'sprite' flags */\r
-  {\r
-    int c = 320/4/4, *zb = (int *)(Pico.est.HighCol+8);\r
-    while (c--)\r
-    {\r
-      *zb++ &= 0x7f7f7f7f; *zb++ &= 0x7f7f7f7f;\r
-      *zb++ &= 0x7f7f7f7f; *zb++ &= 0x7f7f7f7f;\r
-    }\r
-  }\r
-\r
-  /* nasty 2: sh operator pass */\r
-  sprited[0] = sh_cnt;\r
-  DrawSpritesSHi(sprited, &Pico.est);\r
 }\r
 \r
 \r
@@ -1272,17 +1296,15 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
   }\r
 \r
   {\r
-#ifndef PSP\r
-    int i, mask=0xff;\r
-    if (!sh && (est->rendstatus & PDRAW_SPR_LO_ON_HI))\r
-      mask=0x3f; // accurate sprites, upper bits are priority stuff\r
+#if 1\r
+    int i;\r
 \r
     for (i = 0; i < len; i++)\r
-      pd[i] = pal[ps[i] & mask];\r
+      pd[i] = pal[ps[i]];\r
 #else\r
     extern void amips_clut(unsigned short *dst, unsigned char *src, unsigned short *pal, int count);\r
     extern void amips_clut_6bit(unsigned short *dst, unsigned char *src, unsigned short *pal, int count);\r
-    if (!sh && (est->rendstatus & PDRAW_SPR_LO_ON_HI))\r
+    if (!sh)\r
          amips_clut_6bit(pd, ps, pal, len);\r
     else amips_clut(pd, ps, pal, len);\r
 #endif\r
index f22ef60..ac1550d 100644 (file)
@@ -197,7 +197,6 @@ void PicoDoHighPal555(int sh, int line, struct PicoEState *est);
 // internals\r
 #define PDRAW_SPRITES_MOVED (1<<0) // (asm)\r
 #define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority\r
-#define PDRAW_SPR_LO_ON_HI  (1<<2) // seen sprites without layer pri bit ontop spr. with that bit\r
 #define PDRAW_INTERLACE     (1<<3)\r
 #define PDRAW_DIRTY_SPRITES (1<<4) // (asm)\r
 #define PDRAW_SONIC_MODE    (1<<5) // mid-frame palette changes for 8bit renderer\r
index 0656f58..5c0cb57 100644 (file)
@@ -223,10 +223,6 @@ static void do_pal_update(int allow_sh, int allow_as)
                localPal[0xe0] = 0;
                localPal[0xf0] = 0x001f;
        }
-       else if (allow_as && (Pico.est.rendstatus & PDRAW_SPR_LO_ON_HI))
-       {
-               memcpy(dpal + 0x80/2, localPal, 0x40*2);
-       }
 }
 
 static void do_slowmode_lines(int line_to)
@@ -250,7 +246,7 @@ static void EmuScanPrepare(void)
 
        if (Pico.m.dirtyPal)
                do_pal_update(1, 1);
-       if ((Pico.est.rendstatus & PDRAW_SPR_LO_ON_HI) && !(Pico.video.reg[0xC]&8))
+       if (!(Pico.video.reg[0xC] & 8))
             amips_clut_f = amips_clut_6bit;
        else amips_clut_f = amips_clut;
 }