md vdp, fix sprite parsing (done on previous line)

This commit is contained in:
kub 2023-03-26 10:33:29 +00:00
parent e5a1d4c5f1
commit ac89144969
3 changed files with 20 additions and 16 deletions

View file

@ -63,7 +63,7 @@ static u32 HighCacheA[41*2+1]; // caches for high layers
static u32 HighCacheB[41*2+1]; static u32 HighCacheB[41*2+1];
static s32 HighPreSpr[80*2+1]; // slightly preprocessed sprites static s32 HighPreSpr[80*2+1]; // slightly preprocessed sprites
u32 VdpSATCache[128]; // VDP sprite cache (1st 32 sprite attr bits) u32 VdpSATCache[2*128]; // VDP sprite cache (1st 32 sprite attr bits)
// NB don't change any defines without checking their usage in ASM // NB don't change any defines without checking their usage in ASM
@ -1401,7 +1401,7 @@ static void DrawSpritesForced(unsigned char *sprited)
// Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size // Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size
// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 // Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
static NOINLINE void PrepareSprites(int max_lines) static NOINLINE void ParseSprites(int max_lines)
{ {
const struct PicoVideo *pvid=&Pico.video; const struct PicoVideo *pvid=&Pico.video;
const struct PicoEState *est=&Pico.est; const struct PicoEState *est=&Pico.est;
@ -1411,6 +1411,12 @@ static NOINLINE void PrepareSprites(int max_lines)
int max_sprites = 80, max_width = 328; int max_sprites = 80, max_width = 328;
int max_line_sprites = 20; // 20 sprites, 40 tiles int max_line_sprites = 20; // 20 sprites, 40 tiles
// SAT scanning is one line ahead, but don't overshoot. Technically, SAT
// parsing for line 0 is on the last line of the previous frame.
int first_line = Pico.est.DrawScanline + !!Pico.est.DrawScanline;
if (max_lines > rendlines-1)
max_lines = rendlines-1;
if (!(Pico.video.reg[12]&1)) if (!(Pico.video.reg[12]&1))
max_sprites = 64, max_line_sprites = 16, max_width = 264; max_sprites = 64, max_line_sprites = 16, max_width = 264;
if (*est->PicoOpt & POPT_DIS_SPRITE_LIM) if (*est->PicoOpt & POPT_DIS_SPRITE_LIM)
@ -1422,7 +1428,7 @@ static NOINLINE void PrepareSprites(int max_lines)
if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode
table<<=8; // Get sprite table address/2 table<<=8; // Get sprite table address/2
for (u = est->DrawScanline; u < max_lines; u++) for (u = first_line; u <= max_lines; u++)
*((int *)&HighLnSpr[u][0]) = 0; *((int *)&HighLnSpr[u][0]) = 0;
for (u = 0; u < max_sprites && link < max_sprites; u++) for (u = 0; u < max_sprites && link < max_sprites; u++)
@ -1434,7 +1440,7 @@ static NOINLINE void PrepareSprites(int max_lines)
// parse sprite info. the 1st half comes from the VDPs internal cache, // parse sprite info. the 1st half comes from the VDPs internal cache,
// the 2nd half is read from VRAM // the 2nd half is read from VRAM
code = CPU_LE2(VdpSATCache[link]); // normally same as sprite[0] code = CPU_LE2(VdpSATCache[2*link]); // normally same as sprite[0]
sy = (code&0x1ff)-0x80; sy = (code&0x1ff)-0x80;
hv = (code>>24)&0xf; hv = (code>>24)&0xf;
height = (hv&3)+1; height = (hv&3)+1;
@ -1444,7 +1450,7 @@ static NOINLINE void PrepareSprites(int max_lines)
sx = (code2>>16)&0x1ff; sx = (code2>>16)&0x1ff;
sx -= 0x78; // Get X coordinate + 8 sx -= 0x78; // Get X coordinate + 8
if (sy < max_lines && sy + (height<<3) >= est->DrawScanline) // sprite onscreen (y)? if (sy <= max_lines && sy + (height<<3) >= first_line) // sprite onscreen (y)?
{ {
int entry, y, w, sx_min, onscr_x, maybe_op = 0; int entry, y, w, sx_min, onscr_x, maybe_op = 0;
@ -1454,8 +1460,8 @@ static NOINLINE void PrepareSprites(int max_lines)
maybe_op = SPRL_MAY_HAVE_OP; maybe_op = SPRL_MAY_HAVE_OP;
entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80); entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);
y = (sy >= est->DrawScanline) ? sy : est->DrawScanline; y = (sy >= first_line) ? sy : first_line;
for (; y < sy + (height<<3) && y < max_lines; y++) for (; y < sy + (height<<3) && y <= max_lines; y++)
{ {
unsigned char *p = &HighLnSpr[y][0]; unsigned char *p = &HighLnSpr[y][0];
int cnt = p[0]; int cnt = p[0];
@ -1501,7 +1507,7 @@ static NOINLINE void PrepareSprites(int max_lines)
*pd = 0; *pd = 0;
#if 0 #if 0
for (u = 0; u < max_lines; u++) for (u = first_line; u <= max_lines; u++)
{ {
int y; int y;
printf("c%03i: f %x c %2i/%2i w %2i: ", u, HighLnSpr[u][1], printf("c%03i: f %x c %2i/%2i w %2i: ", u, HighLnSpr[u][1],
@ -1982,9 +1988,9 @@ void PicoDrawSync(int to, int blank_last_line)
if (to > 223) if (to > 223)
to = 223; to = 223;
} }
if (est->DrawScanline <= to - blank_last_line && (est->rendstatus & if (est->DrawScanline <= to && (est->rendstatus &
(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES))) (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))
PrepareSprites(to - blank_last_line + 1); ParseSprites(to + 1);
for (line = est->DrawScanline; line < to; line++) for (line = est->DrawScanline; line < to; line++)
PicoLine(line, offs, sh, bgc); PicoLine(line, offs, sh, bgc);

View file

@ -705,7 +705,7 @@ extern unsigned char *HighColBase;
extern int HighColIncrement; extern int HighColIncrement;
extern void *DrawLineDestBase; extern void *DrawLineDestBase;
extern int DrawLineDestIncrement; extern int DrawLineDestIncrement;
extern u32 VdpSATCache[128]; extern u32 VdpSATCache[2*128];
// draw2.c // draw2.c
void PicoDraw2SetOutBuf(void *dest, int incr); void PicoDraw2SetOutBuf(void *dest, int incr);
@ -890,9 +890,7 @@ static __inline void UpdateSAT(u32 a, u32 d)
unsigned num = (a^SATaddr) >> 3; unsigned num = (a^SATaddr) >> 3;
Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES; Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
if (!(a & 4) && num < 128) { ((u16 *)&VdpSATCache[2*num])[(a&7) >> 1] = d;
((u16 *)&VdpSATCache[num])[(a&3) >> 1] = d;
}
} }
static __inline void VideoWriteVRAM(u32 a, u16 d) static __inline void VideoWriteVRAM(u32 a, u16 d)
{ {

View file

@ -1104,8 +1104,8 @@ void PicoVideoCacheSAT(int load)
SATaddr &= ~0x200, SATmask &= ~0x200; // H40, zero lowest SAT bit SATaddr &= ~0x200, SATmask &= ~0x200; // H40, zero lowest SAT bit
// rebuild SAT cache XXX wrong since cache and memory can differ // rebuild SAT cache XXX wrong since cache and memory can differ
for (l = 0; load && l < 80; l++) { for (l = 0; load && l < 2*80; l ++) {
u16 addr = SATaddr + l*8; u16 addr = SATaddr + l*4;
((u16 *)VdpSATCache)[l*2 ] = PicoMem.vram[(addr>>1) ]; ((u16 *)VdpSATCache)[l*2 ] = PicoMem.vram[(addr>>1) ];
((u16 *)VdpSATCache)[l*2 + 1] = PicoMem.vram[(addr>>1) + 1]; ((u16 *)VdpSATCache)[l*2 + 1] = PicoMem.vram[(addr>>1) + 1];
} }