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
// 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
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
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
\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
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
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
*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
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
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
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