sprite rendering improvements for masking and limit edge cases

This commit is contained in:
kub 2020-01-26 20:40:07 +01:00
parent 7aab476859
commit 5f0d224e18
5 changed files with 117 additions and 65 deletions

View file

@ -53,7 +53,11 @@ static int HighPreSpr[80*2+1]; // slightly preprocessed sprites
#define SPRL_HAVE_LO 0x40 // *lo* #define SPRL_HAVE_LO 0x40 // *lo*
#define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line #define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line
#define SPRL_LO_ABOVE_HI 0x10 // low priority sprites may be on top of hi #define SPRL_LO_ABOVE_HI 0x10 // low priority sprites may be on top of hi
unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; // sprite_count, ^flags, tile_count, [spritep]... #define SPRL_HAVE_X 0x08 // have sprites with x != 0
#define SPRL_TILE_OVFL 0x04 // tile limit exceeded on previous line
#define SPRL_HAVE_MASK0 0x02 // have sprite with x == 0 in 1st slot
#define SPRL_MASKED 0x01 // lo prio masking by sprite with x == 0 active
unsigned char HighLnSpr[240][4+MAX_LINE_SPRITES+1]; // sprite_count, ^flags, tile_count, sprites_total, [spritep]..., last_width
int rendstatus_old; int rendstatus_old;
int rendlines; int rendlines;
@ -706,7 +710,7 @@ last_cut_tile:
// Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size // Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size
// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 // Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
static void DrawSprite(int *sprite, int sh) static void DrawSprite(int *sprite, int sh, int w)
{ {
void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal); void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal);
unsigned char *pd = Pico.est.HighCol; unsigned char *pd = Pico.est.HighCol;
@ -746,6 +750,7 @@ static void DrawSprite(int *sprite, int sh)
else fTileFunc=TileNorm; else fTileFunc=TileNorm;
} }
if (w) width = w; // tile limit
for (; width; width--,sx+=8,tile+=delta) for (; width; width--,sx+=8,tile+=delta)
{ {
unsigned int pack; unsigned int pack;
@ -833,12 +838,13 @@ static NOINLINE void DrawAllSpritesInterlace(int pri, int sh)
struct PicoVideo *pvid=&Pico.video; struct PicoVideo *pvid=&Pico.video;
int i,u,table,link=0,sline=Pico.est.DrawScanline<<1; int i,u,table,link=0,sline=Pico.est.DrawScanline<<1;
unsigned int *sprites[80]; // Sprite index unsigned int *sprites[80]; // Sprite index
int max_sprites = Pico.video.reg[12]&1 ? 80 : 64;
table=pvid->reg[5]&0x7f; table=pvid->reg[5]&0x7f;
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 (i=u=0; u < 80 && i < 21; u++) for (i = u = 0; u < max_sprites && link < max_sprites; u++)
{ {
unsigned int *sprite; unsigned int *sprite;
int code, sx, sy, height; int code, sx, sy, height;
@ -888,15 +894,18 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)
void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal); void (*fTileFunc)(unsigned char *pd, unsigned int pack, int pal);
unsigned char *pd = Pico.est.HighCol; unsigned char *pd = Pico.est.HighCol;
unsigned char *p; unsigned char *p;
int cnt; int cnt, w;
cnt = sprited[0] & 0x7f; cnt = sprited[0] & 0x7f;
if (cnt == 0) return; if (cnt == 0) return;
p = &sprited[3]; p = &sprited[4];
if ((sprited[1] & (SPRL_TILE_OVFL|SPRL_HAVE_MASK0)) == (SPRL_TILE_OVFL|SPRL_HAVE_MASK0))
return; // masking effective due to tile overflow
// Go through sprites backwards: // Go through sprites backwards:
for (cnt--; cnt >= 0; cnt--) w = p[cnt]; // possibly clipped width of last sprite
for (cnt--; cnt >= 0; cnt--, w = 0)
{ {
int *sprite, code, pal, tile, sx, sy; int *sprite, code, pal, tile, sx, sy;
int offs, delta, width, height, row; int offs, delta, width, height, row;
@ -940,6 +949,7 @@ static void DrawSpritesSHi(unsigned char *sprited, const struct PicoEState *est)
tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address
delta<<=4; // Delta of address delta<<=4; // Delta of address
if (w) width = w; // tile limit
for (; width; width--,sx+=8,tile+=delta) for (; width; width--,sx+=8,tile+=delta)
{ {
unsigned int pack; unsigned int pack;
@ -967,7 +977,9 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
if (cnt == 0) return; if (cnt == 0) return;
memset(mb, 0xff, sizeof(mb)); memset(mb, 0xff, sizeof(mb));
p = &sprited[3]; p = &sprited[4];
if ((sprited[1] & (SPRL_TILE_OVFL|SPRL_HAVE_MASK0)) == (SPRL_TILE_OVFL|SPRL_HAVE_MASK0))
return; // masking effective due to tile overflow
// Go through sprites: // Go through sprites:
for (entry = 0; entry < cnt; entry++) for (entry = 0; entry < cnt; entry++)
@ -1019,6 +1031,7 @@ static void DrawSpritesHiAS(unsigned char *sprited, int sh)
tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address
delta<<=4; // Delta of address delta<<=4; // Delta of address
if (entry+1 == cnt) width = p[entry+1]; // last sprite width limited?
for (; width; width--,sx+=8,tile+=delta) for (; width; width--,sx+=8,tile+=delta)
{ {
unsigned int pack; unsigned int pack;
@ -1065,10 +1078,10 @@ static NOINLINE void PrepareSprites(int full)
{ {
int pack; int pack;
// updates: tilecode, sx // updates: tilecode, sx
for (u=0; u < max_sprites && (pack = *pd); u++, pd+=2) for (u=0; u < max_sprites && link < max_sprites && (pack = *pd); u++, pd+=2)
{ {
unsigned int *sprite; unsigned int *sprite;
int code2, sx, sy, height; int code2, sx, sy, height, width;
sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite
@ -1078,25 +1091,29 @@ static NOINLINE void PrepareSprites(int full)
sx -= 0x78; // Get X coordinate + 8 sx -= 0x78; // Get X coordinate + 8
sy = (pack << 16) >> 16; sy = (pack << 16) >> 16;
height = (pack >> 24) & 0xf; height = (pack >> 24) & 0xf;
width = (pack >> 28);
if (sy < max_lines && if (sy < max_lines &&
sy + (height<<3) > est->DrawScanline && // sprite onscreen (y)? sy + (height<<3) > est->DrawScanline) // sprite onscreen (y)?
(sx > -24 || sx < max_width)) // onscreen x
{ {
int y = (sy >= est->DrawScanline) ? sy : est->DrawScanline; int y = (sy >= est->DrawScanline) ? sy : est->DrawScanline;
int entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80); int entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);
for (; y < sy + (height<<3) && y < max_lines; y++) for (; y < sy + (height<<3) && y < max_lines; y++)
{ {
int i, cnt; int i, cnt;
cnt = HighLnSpr[y][0] & 0x7f; cnt = HighLnSpr[y][0];
if (cnt >= max_line_sprites) continue; // sprite limit? if (HighLnSpr[y][3] >= max_line_sprites) continue; // sprite limit?
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
if (((HighLnSpr[y][3+i] ^ entry) & 0x7f) == 0) goto found; if (((HighLnSpr[y][4+i] ^ entry) & 0x7f) == 0) goto found;
// this sprite was previously missing // this sprite was previously missing
HighLnSpr[y][3+cnt] = entry; HighLnSpr[y][3] ++;
if (sx > -24 && sx < max_width) { // onscreen x
HighLnSpr[y][4+cnt] = entry; // XXX wrong sequence?
HighLnSpr[y][5+cnt] = width; // XXX should count tiles for limit
HighLnSpr[y][0] = cnt + 1; HighLnSpr[y][0] = cnt + 1;
}
found:; found:;
if (entry & 0x80) if (entry & 0x80)
HighLnSpr[y][1] |= SPRL_HAVE_HI; HighLnSpr[y][1] |= SPRL_HAVE_HI;
@ -1118,7 +1135,7 @@ found:;
for (u = 0; u < max_lines; u++) for (u = 0; u < max_lines; u++)
*((int *)&HighLnSpr[u][0]) = 0; *((int *)&HighLnSpr[u][0]) = 0;
for (u = 0; u < max_sprites; u++) for (u = 0; u < max_sprites && link < max_sprites; u++)
{ {
unsigned int *sprite; unsigned int *sprite;
int code, code2, sx, sy, hv, height, width; int code, code2, sx, sy, hv, height, width;
@ -1138,7 +1155,7 @@ found:;
if (sy < max_lines && sy + (height<<3) > est->DrawScanline) // sprite onscreen (y)? if (sy < max_lines && sy + (height<<3) > est->DrawScanline) // sprite onscreen (y)?
{ {
int entry, y, sx_min, onscr_x, maybe_op = 0; int entry, y, w, sx_min, onscr_x, maybe_op = 0;
sx_min = 8-(width<<3); sx_min = 8-(width<<3);
onscr_x = sx_min < sx && sx < max_width; onscr_x = sx_min < sx && sx < max_width;
@ -1151,27 +1168,34 @@ found:;
{ {
unsigned char *p = &HighLnSpr[y][0]; unsigned char *p = &HighLnSpr[y][0];
int cnt = p[0]; int cnt = p[0];
if (cnt >= max_line_sprites) continue; // sprite limit? if (p[3] >= max_line_sprites) continue; // sprite limit?
if ((p[1] & SPRL_MASKED) && !(entry & 0x80)) continue; // masked?
if (p[2] >= max_line_sprites*2) { // tile limit? w = width;
p[0] |= 0x80; if (p[2] + width > max_line_sprites*2) { // tile limit?
continue; if (y+1 < 240) HighLnSpr[y+1][1] |= SPRL_TILE_OVFL;
if (p[2] >= max_line_sprites*2) continue;
w = max_line_sprites*2 - p[2];
} }
p[2] += width; p[2] += w;
p[3] ++;
if (sx == -0x78) { if (sx == -0x78) {
if (cnt > 0) if (p[1] & (SPRL_HAVE_X|SPRL_TILE_OVFL))
p[0] |= 0x80; // masked, no more sprites for this line p[1] |= SPRL_MASKED; // masked, no more low sprites for this line
continue; if (!(p[1] & SPRL_HAVE_X) && cnt == 0)
} p[1] |= SPRL_HAVE_MASK0; // 1st sprite is masking
// must keep the first sprite even if it's offscreen, for masking } else
if (cnt > 0 && !onscr_x) continue; // offscreen x p[1] |= SPRL_HAVE_X;
p[3+cnt] = entry; if (!onscr_x) continue; // offscreen x
p[4+cnt] = entry;
p[5+cnt] = w; // width clipped by tile limit for sprite renderer
p[0] = cnt + 1; p[0] = cnt + 1;
p[1] |= (entry & 0x80) ? SPRL_HAVE_HI : SPRL_HAVE_LO; p[1] |= (entry & 0x80) ? SPRL_HAVE_HI : SPRL_HAVE_LO;
p[1] |= maybe_op; // there might be op sprites on this line p[1] |= maybe_op; // there might be op sprites on this line
if (cnt > 0 && (code2 & 0x8000) && !(p[3+cnt-1]&0x80)) if (cnt > 0 && (code2 & 0x8000) && !(p[4+cnt-1]&0x80))
p[1] |= SPRL_LO_ABOVE_HI; p[1] |= SPRL_LO_ABOVE_HI;
} }
} }
@ -1189,9 +1213,10 @@ found:;
for (u = 0; u < max_lines; u++) for (u = 0; u < max_lines; u++)
{ {
int y; int y;
printf("c%03i: %2i, %2i: ", u, HighLnSpr[u][0] & 0x7f, HighLnSpr[u][2]); printf("c%03i: f %x c %2i/%2i w %2i: ", u, HighLnSpr[u][1],
for (y = 0; y < HighLnSpr[u][0] & 0x7f; y++) HighLnSpr[u][0], HighLnSpr[u][3], HighLnSpr[u][2]);
printf(" %i", HighLnSpr[u][y+3]); for (y = 0; y < HighLnSpr[u][0]; y++)
printf(" %i", HighLnSpr[u][y+4]);
printf("\n"); printf("\n");
} }
#endif #endif
@ -1203,20 +1228,22 @@ static void DrawAllSprites(unsigned char *sprited, int prio, int sh,
struct PicoEState *est) struct PicoEState *est)
{ {
unsigned char *p; unsigned char *p;
int cnt; int cnt, w = sprited[2];
cnt = sprited[0] & 0x7f; cnt = sprited[0] & 0x7f;
if (cnt == 0) return; if (cnt == 0) return;
p = &sprited[3]; p = &sprited[4];
if ((sprited[1] & (SPRL_TILE_OVFL|SPRL_HAVE_MASK0)) == (SPRL_TILE_OVFL|SPRL_HAVE_MASK0))
return; // masking effective due to tile overflow
// Go through sprites backwards: // Go through sprites backwards:
for (cnt--; cnt >= 0; cnt--) w = p[cnt]; // possibly clipped width of last sprite
for (cnt--; cnt >= 0; cnt--, w = 0)
{ {
int offs; int *sp = HighPreSpr + (p[cnt]&0x7f) * 2;
if ((p[cnt] >> 7) != prio) continue; if ((p[cnt] >> 7) != prio) continue;
offs = (p[cnt]&0x7f) * 2; DrawSprite(sp, sh, w);
DrawSprite(HighPreSpr + offs, sh);
} }
} }

View file

@ -420,12 +420,13 @@ static void DrawAllSpritesFull(int prio, int maxwidth)
int i,u,link=0; int i,u,link=0;
unsigned int *sprites[80]; // Sprites unsigned int *sprites[80]; // Sprites
int y_min=START_ROW*8, y_max=END_ROW*8; // for a simple sprite masking int y_min=START_ROW*8, y_max=END_ROW*8; // for a simple sprite masking
int max_sprites = Pico.video.reg[12]&1 ? 80 : 64;
table=pvid->reg[5]&0x7f; table=pvid->reg[5]&0x7f;
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 (i=u=0; u < 80; u++) for (i = u = 0; u < max_sprites && link < max_sprites; u++)
{ {
unsigned int *sprite=NULL; unsigned int *sprite=NULL;
int code, code2, sx, sy, height; int code, code2, sx, sy, height;

View file

@ -942,17 +942,23 @@ DrawTilesFromCache:
.global DrawSpritesSHi .global DrawSpritesSHi
DrawSpritesSHi: DrawSpritesSHi:
ldr r3, [r0] ldrb r3, [r0]
mov r12,#0xff mov r12,#0xff
ands r3, r3, #0x7f ands r3, r3, #0x7f
bxeq lr bxeq lr
stmfd sp!, {r1,r4-r11,lr} @ +est stmfd sp!, {r1,r3-r11,lr} @ +est
strb r12,[r0,#2] @ set end marker strb r12,[r0,#3] @ set end marker
add r10,r0, #3 @ r10=HighLnSpr end ldrb r12,[r0,#1]
add r10,r0, #4 @ r10=HighLnSpr end
mvn r12,r12
tst r12,#0x6 @ masking in slot 1 and tile ovfl?
ldmeqfd sp!, {r1,r3-r11,pc}
add r10,r10,r3 @ r10=HighLnSpr end add r10,r10,r3 @ r10=HighLnSpr end
ldrb r12,[r10,#0] @ width of last sprite
ldr r11,[r1, #OFS_EST_HighCol] ldr r11,[r1, #OFS_EST_HighCol]
str r12,[sp, #4]
mov r12,#0xf mov r12,#0xf
ldr lr, [r1, #OFS_EST_PicoMem_vram] ldr lr, [r1, #OFS_EST_PicoMem_vram]
@ -963,7 +969,7 @@ DrawSpriteSHi:
ldr r7, [sp] @ est ldr r7, [sp] @ est
ldr r1, [r7, #OFS_EST_HighPreSpr] ldr r1, [r7, #OFS_EST_HighPreSpr]
cmp r0, #0xff cmp r0, #0xff
ldmeqfd sp!, {r1,r4-r11,pc} @ end of list ldmeqfd sp!, {r1,r3-r11,pc} @ end of list
and r0, r0, #0x7f and r0, r0, #0x7f
add r0, r1, r0, lsl #3 add r0, r1, r0, lsl #3
@ -1007,10 +1013,16 @@ DrawSpriteSHi:
and r7, r7, #7 and r7, r7, #7
add r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address add r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address
ldr r0, [sp, #4]
add r6, r6, #1 @ inc now
cmp r0, #0 @ check width of last sprite
movne r6, r0
movne r0, #0
strne r0, [sp, #4]
mov r5, r5, lsl #4 @ delta<<=4; // Delta of address mov r5, r5, lsl #4 @ delta<<=4; // Delta of address
mov r3, r4, lsr #9 @ r3=pal=((code>>9)&0x30); mov r3, r4, lsr #9 @ r3=pal=((code>>9)&0x30);
add r6, r6, #1 @ inc now
adds r0, r2, #0 @ mov sx to r0 and set ZV flags adds r0, r2, #0 @ mov sx to r0 and set ZV flags
b .dsprShi_loop_enter b .dsprShi_loop_enter
@ -1126,11 +1138,18 @@ DrawAllSprites:
@ time to do some real work @ time to do some real work
stmfd sp!, {r1,r3-r11,lr} @ +sh|prio<<1 +est stmfd sp!, {r1,r3-r11,lr} @ +sh|prio<<1 +est
mov r12,#0xff mov r12,#0xff
strb r12,[r0,#2] @ set end marker strb r12,[r0,#3] @ set end marker
add r10,r0, #3 ldrb r12,[r0,#1]
add r10,r0 ,#4
mvn r12,r12
tst r12,#0x6 @ masking in slot 1 and tile ovfl?
ldmeqfd sp!, {r1,r3-r11,pc}
add r10,r10,r2 @ r10=HighLnSpr end add r10,r10,r2 @ r10=HighLnSpr end
ldrb r12,[r10,#0] @ width of last sprite
ldr r11,[r3, #OFS_EST_HighCol] ldr r11,[r3, #OFS_EST_HighCol]
orr r1 ,r1 ,r12,lsl #24
str r1, [sp]
mov r12,#0xf mov r12,#0xf
ldr lr, [r3, #OFS_EST_PicoMem_vram] ldr lr, [r3, #OFS_EST_PicoMem_vram]
@ -1140,13 +1159,13 @@ DrawAllSprites:
DrawSprite: DrawSprite:
@ draw next sprite @ draw next sprite
ldrb r0, [r10,#-1]! ldrb r0, [r10,#-1]!
ldr r8, [sp] @ sh|prio<<1 ldr r4, [sp] @ sh|prio<<1|lastw<<24
ldr r7, [sp, #4] @ est ldr r7, [sp, #4] @ est
mov r2, r0, lsr #7 mov r2, r0, lsl #24
cmp r0, #0xff cmp r0, #0xff
ldmeqfd sp!, {r1,r3-r11,pc} @ end of list ldmeqfd sp!, {r1,r3-r11,pc} @ end of list
cmp r2, r8, lsr #1 eor r2, r2, r4, lsl #30
bne DrawSprite @ wrong priority bmi DrawSprite @ wrong priority
ldr r1, [r7, #OFS_EST_HighPreSpr] ldr r1, [r7, #OFS_EST_HighPreSpr]
and r0, r0, #0x7f and r0, r0, #0x7f
add r0, r1, r0, lsl #3 add r0, r1, r0, lsl #3
@ -1158,20 +1177,20 @@ DrawSprite:
mov r5, r3, lsr #24 mov r5, r3, lsr #24
and r5, r5, #7 @ r5=height and r5, r5, #7 @ r5=height
mov r4, r3, lsl #16 @ r4=sy<<16 (tmp) mov r8, r3, lsl #16 @ r8=sy<<16 (tmp)
ldr r9, [r0, #4] ldr r9, [r0, #4]
sub r7, r7, r4, asr #16 @ r7=row=DrawScanline-sy sub r7, r7, r8, asr #16 @ r7=row=DrawScanline-sy
mov r2, r9, asr #16 @ r2=sx mov r2, r9, asr #16 @ r2=sx
mov r9, r9, lsl #16 mov r9, r9, lsl #16
mov r9, r9, lsr #16 mov r9, r9, lsr #16
orr r9, r9, r8, lsl #31 @ r9=code|sh[31] orr r9, r9, r4, lsl #31 @ r9=code|sh[31]
tst r9, #0x1000 tst r9, #0x1000
movne r4, r5, lsl #3 movne r8, r5, lsl #3
subne r4, r4, #1 subne r8, r8, #1
subne r7, r4, r7 @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y subne r7, r8, r7 @ if (code&0x1000) row=(height<<3)-1-row; // Flip Y
add r8, r9, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down add r8, r9, r7, lsr #3 @ tile+=row>>3; // Tile number increases going down
tst r9, #0x0800 tst r9, #0x0800
@ -1183,7 +1202,12 @@ DrawSprite:
and r7, r7, #7 and r7, r7, #7
add r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address add r8, r8, r7, lsl #1 @ tile+=(row&7)<<1; // Tile address
.dspr_continue: add r6, r6, #1 @ inc now
cmp r4, #0x1000000 @ check width of last sprite
movhs r6, r4, lsr #24
bichs r4, r4, #0xff000000
strhs r4, [sp]
@ cache some stuff to avoid mem access @ cache some stuff to avoid mem access
mov r5, r5, lsl #4 @ delta<<=4; // Delta of address mov r5, r5, lsl #4 @ delta<<=4; // Delta of address
and r4, r9, #0x6000 and r4, r9, #0x6000
@ -1193,7 +1217,6 @@ DrawSprite:
mov r3, r4, lsr #9 @ r3=pal=((code>>9)&0x30); mov r3, r4, lsr #9 @ r3=pal=((code>>9)&0x30);
orrmi r3, r3, #0x40 @ for sh/hi orrmi r3, r3, #0x40 @ for sh/hi
add r6, r6, #1 @ inc now
adds r0, r2, #0 @ mov sx to r0 and set ZV flags adds r0, r2, #0 @ mov sx to r0 and set ZV flags
b .dspr_loop_enter b .dspr_loop_enter

View file

@ -667,8 +667,8 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est);
void PicoDrawSetOutBufMD(void *dest, int increment); void PicoDrawSetOutBufMD(void *dest, int increment);
extern int (*PicoScanBegin)(unsigned int num); extern int (*PicoScanBegin)(unsigned int num);
extern int (*PicoScanEnd)(unsigned int num); extern int (*PicoScanEnd)(unsigned int num);
#define MAX_LINE_SPRITES 29 #define MAX_LINE_SPRITES 27 // +1 last sprite width, +4 hdr; total 32
extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; extern unsigned char HighLnSpr[240][4+MAX_LINE_SPRITES+1];
extern void *DrawLineDestBase; extern void *DrawLineDestBase;
extern int DrawLineDestIncrement; extern int DrawLineDestIncrement;

View file

@ -200,6 +200,7 @@ static void DmaSlow(int len, unsigned int source)
a = (a + inc) & 0x1ffff; a = (a + inc) & 0x1ffff;
} }
Pico.video.addr_u = a >> 16; Pico.video.addr_u = a >> 16;
Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
break; break;
default: default:
@ -266,6 +267,7 @@ static NOINLINE void DmaFill(int data)
// Increment address register // Increment address register
a = (u16)(a + inc); a = (u16)(a + inc);
} }
Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
break; break;
case 3: // cram case 3: // cram
case 5: { // vsram case 5: { // vsram
@ -289,7 +291,6 @@ static NOINLINE void DmaFill(int data)
Pico.video.reg[0x15] = source; Pico.video.reg[0x15] = source;
Pico.video.reg[0x16] = source >> 8; Pico.video.reg[0x16] = source >> 8;
Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
} }
static NOINLINE void CommandDma(void) static NOINLINE void CommandDma(void)