\r
static u32 HighCacheA[41*2+1]; // caches for high layers\r
static u32 HighCacheB[41*2+1];\r
-static s32 HighPreSpr[80*2+1]; // slightly preprocessed sprites\r
+static s32 HighPreSpr[128*2*2]; // slightly preprocessed sprites (2 banks a 128)\r
+static int HighPreSprBank;\r
\r
u32 VdpSATCache[2*128]; // VDP sprite cache (1st 32 sprite attr bits)\r
\r
/* if (!t) pd[x] |= 0x40; as per titan hw notes? */ \\r
pd[x] &= pal|t; \\r
}\r
- \r
+\r
TileNormMakerAS(TileNormSH_AS_and, pix_sh_as_and)\r
TileFlipMakerAS(TileFlipSH_AS_and, pix_sh_as_and)\r
#endif\r
sx=code>>16; // X\r
width=sy>>28;\r
height=(sy>>24)&7; // Width and height in tiles\r
- sy=(sy<<16)>>16; // Y\r
+ sy=(s16)sy; // Y\r
\r
row=Pico.est.DrawScanline-sy; // Row of the sprite we are on\r
\r
unsigned char *p;\r
int cnt, w;\r
\r
- cnt = sprited[0];\r
+ cnt = sprited[0] & 0x7f;\r
if (cnt == 0) return;\r
\r
p = &sprited[4];\r
sx=code>>16; // X\r
width=sy>>28;\r
height=(sy>>24)&7; // Width and height in tiles\r
- sy=(sy<<16)>>16; // Y\r
+ sy=(s16)sy; // Y\r
\r
row=est->DrawScanline-sy; // Row of the sprite we are on\r
\r
unsigned m;\r
int entry, cnt;\r
\r
- cnt = sprited[0];\r
+ cnt = sprited[0] & 0x7f;\r
if (cnt == 0) return;\r
\r
memset(mb, 0xff, sizeof(mb));\r
int offs, delta, width, height, row;\r
\r
offs = (p[entry] & 0x7f) * 2;\r
- sprite = HighPreSpr + offs;\r
+ sprite = Pico.est.HighPreSpr + offs;\r
code = sprite[1];\r
pal = (code>>9)&0x30;\r
\r
sx=code>>16; // X\r
width=sy>>28;\r
height=(sy>>24)&7; // Width and height in tiles\r
- sy=(sy<<16)>>16; // Y\r
+ sy=(s16)sy; // Y\r
\r
row=Pico.est.DrawScanline-sy; // Row of the sprite we are on\r
\r
unsigned m;\r
int entry, cnt;\r
\r
- cnt = sprited[0];\r
+ cnt = sprited[0] & 0x7f;\r
if (cnt == 0) { memset(pd, 0, sizeof(DefHighCol)); return; }\r
- \r
+\r
memset(mb, 0xff, sizeof(mb));\r
p = &sprited[4];\r
if ((sprited[1] & (SPRL_TILE_OVFL|SPRL_HAVE_MASK0)) == (SPRL_TILE_OVFL|SPRL_HAVE_MASK0))\r
int offs, delta, width, height, row;\r
\r
offs = (p[entry] & 0x7f) * 2;\r
- sprite = HighPreSpr + offs;\r
+ sprite = Pico.est.HighPreSpr + offs;\r
code = sprite[1];\r
pal = (code>>9)&0x30;\r
\r
sx=code>>16; // X\r
width=sy>>28;\r
height=(sy>>24)&7; // Width and height in tiles\r
- sy=(sy<<16)>>16; // Y\r
+ sy=(s16)sy; // Y\r
\r
row=Pico.est.DrawScanline-sy; // Row of the sprite we are on\r
\r
#endif\r
\r
\r
+// sprite info in SAT:\r
// Index + 0 : ----hhvv -lllllll -------y yyyyyyyy\r
// Index + 4 : -------x xxxxxxxx pccvhnnn nnnnnnnn\r
-// v\r
-// Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size\r
-// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
+// sprite info in HighPreSpr:\r
+// Index + 0 : hhhhvvvv -lllllll yyyyyyyy yyyyyyyy // v/h size, link, y\r
+// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x+8, prio, palette, flip, tile\r
\r
+// Sprite parsing 1 line in advance: determine sprites on line by Y pos\r
static NOINLINE void ParseSprites(int max_lines, int limit)\r
{\r
const struct PicoVideo *pvid=&Pico.video;\r
const struct PicoEState *est=&Pico.est;\r
int u,link=0,sh;\r
int table=0;\r
- s32 *pd = HighPreSpr;\r
+ s32 *pd = HighPreSpr + HighPreSprBank*2;\r
int max_sprites = 80, max_width = 328;\r
int max_line_sprites = 20; // 20 sprites, 40 tiles\r
\r
if (sh && (code2 & 0x6000) == 0x6000)\r
maybe_op = SPRL_MAY_HAVE_OP;\r
\r
- entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);\r
+ entry = (((pd - HighPreSpr) / 2) & 0x7f) | ((code2>>8)&0x80);\r
y = (sy >= first_line) ? sy : first_line;\r
for (; y < sy + (height<<3) && y <= last_line; y++)\r
{\r
unsigned char *p = &HighLnSpr[y][0];\r
- int cnt = p[0];\r
+ int cnt = p[0] & 0x7f;\r
if (p[1] & SPRL_MASKED) continue; // masked?\r
\r
if (p[3] >= max_line_sprites) continue; // sprite limit?\r
\r
p[4+cnt] = entry;\r
p[5+cnt] = w; // width clipped by tile limit for sprite renderer\r
- p[0] = cnt + 1;\r
+ p[0] = (cnt + 1) | HighPreSprBank;\r
}\r
}\r
\r
- *pd++ = (width<<28)|(height<<24)|(hv<<16)|((unsigned short)sy);\r
- *pd++ = (sx<<16)|((unsigned short)code2);\r
+ *pd++ = (width<<28)|(height<<24)|(link<<16)|((u16)sy);\r
+ *pd++ = (sx<<16)|((u16)code2);\r
\r
// Find next sprite\r
link=(code>>16)&0x7f;\r
int w = 0;\r
unsigned char *sprited = &HighLnSpr[max_lines-1][0]; // current render line\r
\r
- for (u = 0; u < sprited[0]; u++) {\r
- s32 *sp = HighPreSpr + (sprited[4+u] & 0x7f) * 2;\r
+ for (u = 0; u < (sprited[0] & 0x7f); u++) {\r
+ s32 *sp = HighPreSpr + (sprited[4+u] & 0x7f) * 2 + HighPreSprBank*2;\r
int sw = sp[0] >> 28;\r
if (w + sw > limit) {\r
- sprited[0] = u;\r
+ sprited[0] = u | HighPreSprBank;\r
sprited[4+u] = limit-w;\r
break;\r
}\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
- HighLnSpr[u][0], HighLnSpr[u][3], HighLnSpr[u][2]);\r
- for (y = 0; y < HighLnSpr[u][0]; y++) {\r
- s32 *sp = HighPreSpr + (HighLnSpr[u][y+4]&0x7f) * 2;\r
+ printf("c%03i b%d: f %x c %2i/%2i w %2i: ", u, !!HighPreSprBank, HighLnSpr[u][1],\r
+ HighLnSpr[u][0] & 0x7f, HighLnSpr[u][3], HighLnSpr[u][2]);\r
+ for (y = 0; y < (HighLnSpr[u][0] & 0x7f); y++) {\r
+ s32 *sp = HighPreSpr + (HighLnSpr[u][y+4]&0x7f) * 2 + HighPreSprBank*2;\r
printf(" %i(%x/%x)", HighLnSpr[u][y+4],sp[0],sp[1]);\r
}\r
printf("\n");\r
}\r
#endif\r
+\r
+ HighPreSprBank ^= 0x80;\r
}\r
\r
#ifndef _ASM_DRAW_C\r
unsigned char *p;\r
int cnt, w;\r
\r
- cnt = sprited[0];\r
+ cnt = sprited[0] & 0x7f;\r
if (cnt == 0) return;\r
\r
p = &sprited[4];\r
w = p[cnt]; // possibly clipped width of last sprite\r
for (cnt--; cnt >= 0; cnt--, w = 0)\r
{\r
- s32 *sp = HighPreSpr + (p[cnt]&0x7f) * 2;\r
+ s32 *sp = est->HighPreSpr + (p[cnt]&0x7f) * 2;\r
if ((p[cnt] >> 7) != prio) continue;\r
DrawSprite(sp, sh, w);\r
}\r
int maxw, maxcells;\r
\r
est->rendstatus &= ~(PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO|PDRAW_WND_DIFF_PRIO);\r
+ est->HighPreSpr = HighPreSpr + (sprited[0]&0x80)*2;\r
\r
if (pvid->reg[12]&1) {\r
maxw = 328; maxcells = 40;\r
pprof_end(draw);\r
}\r
\r
+void PicoDrawRefreshSprites()\r
+{\r
+ unsigned char *sprited = &HighLnSpr[Pico.est.DrawScanline][0];\r
+ int i;\r
+\r
+ if (Pico.est.DrawScanline == 0 || Pico.est.DrawScanline >= rendlines) return;\r
+\r
+ // compute sprite row. The VDP does this by subtracting the sprite y pos from\r
+ // the current line and treating the lower 5 bits as the row number. Y pos\r
+ // is reread from SAT cache, which may have changed by now (Overdrive 2).\r
+ for (i = 0; i < (sprited[0] & 0x7f); i++) {\r
+ int num = sprited[4+i] & 0x7f;\r
+ s32 *sp = HighPreSpr + 2*num + (sprited[0] & 0x80)*2;\r
+ int link = (sp[0]>>16) & 0x7f;\r
+ int sy = (CPU_LE2(VdpSATCache[2*link]) & 0x1ff) - 0x80;\r
+ if (sy != (s16)sp[0]) {\r
+ // Y info in SAT cache has really changed\r
+ sy = Pico.est.DrawScanline - ((Pico.est.DrawScanline - sy) & 0x1f);\r
+ sp[0] = (sp[0] & 0xffff0000) | (u16)sy;\r
+ }\r
+ }\r
+}\r
+\r
// also works for fast renderer\r
void PicoDrawUpdateHighPal(void)\r
{\r
{\r
Pico.est.DrawLineDest = DefOutBuff;\r
Pico.est.HighCol = HighColBase;\r
- Pico.est.HighPreSpr = HighPreSpr;\r
rendstatus_old = -1;\r
}\r
\r