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