static int HighPreSpr[80*2+1]; // slightly preprocessed sprites\r
char HighSprZ[320+8+8]; // Z-buffer for accurate sprites and shadow/hilight mode\r
// (if bit 7 == 0, sh caused by tile; if bit 6 == 0 pixel must be shadowed, else hilighted, if bit5 == 1)\r
-// lsb->msb: moved sprites, all window tiles don't use same priority, accurate sprites (copied from PicoOpt), interlace\r
-// dirty sprites, sonic mode\r
+// lsb->msb: moved sprites, not all window tiles use same priority, accurate sprites (copied from PicoOpt), interlace\r
+// dirty sprites, sonic mode, have layer with all hi prio tiles (mk3), layer sh/hi already processed\r
int rendstatus;\r
void *DrawLineDest=DefOutBuff; // pointer to dest buffer where to draw this line to\r
int Scanline=0; // Scanline\r
\r
// terminate the cache list\r
*ts->hc = 0;\r
+ // if oldcode wasn't changed, it means all layer is hi priority\r
+ if (oldcode == -1) rendstatus|=0x40;\r
}\r
\r
// this is messy\r
\r
// terminate the cache list\r
*ts->hc = 0;\r
+ if (oldcode == -1) rendstatus|=0x40;\r
}\r
#endif\r
\r
\r
static void DrawTilesFromCache(int *hc, int sh)\r
{\r
- int code, addr, zero, dx;\r
+ int code, addr, dx;\r
int pal;\r
- short blank=-1; // The tile we know is blank\r
\r
// *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it\r
\r
- while((code=*hc++)) {\r
- if(!sh && (short)code == blank) continue;\r
+ if (sh && (rendstatus&0xc0))\r
+ {\r
+ if (!(rendstatus&0x80))\r
+ {\r
+ // as some layer has covered whole line with hi priority tiles,\r
+ // we can process whole line and then act as if sh/hi mode was off.\r
+ rendstatus|=0x80;\r
+ int c = 320/4, *zb = (int *)(HighCol+8);\r
+ while (c--)\r
+ {\r
+ int tmp = *zb;\r
+ if (!(tmp & 0x80808080)) *zb=tmp&0x3f3f3f3f;\r
+ else {\r
+ if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000;\r
+ if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000;\r
+ *zb=tmp;\r
+ }\r
+ zb++;\r
+ }\r
+ }\r
+ sh = 0;\r
+ }\r
\r
- // Get tile address/2:\r
- addr=(code&0x7ff)<<4;\r
- addr+=(unsigned int)code>>25; // y offset into tile\r
- dx=(code>>16)&0x1ff;\r
- if(sh) {\r
- unsigned char *zb = HighCol+dx;\r
+ if (sh)\r
+ {\r
+ while((code=*hc++)) {\r
+ unsigned char *zb;\r
+ // Get tile address/2:\r
+ addr=(code&0x7ff)<<4;\r
+ addr+=(unsigned int)code>>25; // y offset into tile\r
+ dx=(code>>16)&0x1ff;\r
+ zb = HighCol+dx;\r
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;\r
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;\r
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;\r
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;\r
+\r
+ pal=((code>>9)&0x30);\r
+\r
+ if (code&0x0800) TileFlip(dx,addr,pal);\r
+ else TileNorm(dx,addr,pal);\r
}\r
+ }\r
+ else\r
+ {\r
+ short blank=-1; // The tile we know is blank\r
+ while((code=*hc++)) {\r
+ int zero;\r
+ if((short)code == blank) continue;\r
+ // Get tile address/2:\r
+ addr=(code&0x7ff)<<4;\r
+ addr+=(unsigned int)code>>25; // y offset into tile\r
+ dx=(code>>16)&0x1ff;\r
\r
- pal=((code>>9)&0x30);\r
+ pal=((code>>9)&0x30);\r
\r
- if (code&0x0800) zero=TileFlip(dx,addr,pal);\r
- else zero=TileNorm(dx,addr,pal);\r
+ if (code&0x0800) zero=TileFlip(dx,addr,pal);\r
+ else zero=TileNorm(dx,addr,pal);\r
\r
- if(zero) blank=(short)code;\r
+ if(zero) blank=(short)code;\r
+ }\r
}\r
}\r
\r
int win=0,edge=0,hvwind=0;\r
int maxw, maxcells;\r
\r
+ rendstatus&=~0xc0;\r
+\r
if(pvid->reg[12]&1) {\r
maxw = 328; maxcells = 40;\r
} else {\r
if(HighCacheA[0]) DrawTilesFromCache(HighCacheA, sh);\r
DrawAllSprites(HighCacheS, maxw, 1, sh);\r
\r
+#if 0\r
+ {\r
+ int *c, a, b;\r
+ for (a = 0, c = HighCacheA; *c; c++, a++);\r
+ for (b = 0, c = HighCacheB; *c; c++, b++);\r
+ printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count, Scanline, a, b);\r
+ }\r
+#endif\r
+\r
return 0;\r
}\r
\r
\r
tst r9, #1<<31\r
mov r3, #0\r
- orrne r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|ty)\r
+ orrne r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|had_output<<21|ty)\r
movne r3, #0x40 @ default to shadowed pal on sh mode\r
\r
mvn r9, #0 @ r9=prevcode=-1\r
beq .DrawStrip_samecode @ we know stuff about this tile already\r
\r
mov r9, r7 @ remember code\r
+ orr r10, r10, #1<<21 @ seen non hi-prio tile\r
\r
movs r2, r9, lsl #20 @ if (code&0x1000)\r
mov r2, r2, lsl #1\r
strneb r4, [r1], #1 @ have a remaining unaligned pixel?\r
b .dsloop_subr1\r
\r
-.DrawStrip_hiprio:\r
- tst r10, #0x00c00000\r
- beq .DrawStrip_hiprio_maybempt\r
- sub r0, r1, r11\r
- orr r7, r7, r0, lsl #16\r
- orr r7, r7, r10, lsl #25 @ (ty<<25)\r
- tst r7, #0x1000\r
- eorne r7, r7, #7<<26 @ if(code&0x1000) cval^=7<<26;\r
- str r7, [r6], #4 @ cache hi priority tile\r
- mov r0, #0xf\r
- b .dsloop\r
-\r
.DrawStrip_hiprio_maybempt:\r
cmp r7, r9\r
beq .dsloop @ must've been empty, otherwise we wouldn't get here\r
ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
mov r9, r7 @ remember code\r
tst r2, r2\r
- orrne r10, r10, #1<<22\r
- bne .DrawStrip_hiprio\r
+ beq .dsloop\r
+ orr r10, r10, #1<<22\r
+\r
+.DrawStrip_hiprio:\r
+ tst r10, #0x00c00000\r
+ beq .DrawStrip_hiprio_maybempt\r
+ sub r0, r1, r11\r
+ orr r7, r7, r0, lsl #16\r
+ orr r7, r7, r10, lsl #25 @ (ty<<25)\r
+ tst r7, #0x1000\r
+ eorne r7, r7, #7<<26 @ if(code&0x1000) cval^=7<<26;\r
+ str r7, [r6], #4 @ cache hi priority tile\r
+ mov r0, #0xf\r
b .dsloop\r
\r
.dsloop_exit:\r
+ tst r10, #1<<21 @ seen non hi-prio tile\r
+ ldreq r1, =rendstatus\r
mov r0, #0\r
+ ldreq r2, [r1]\r
str r0, [r6] @ terminate the cache list\r
+ orreq r2, r2, #0x40 @ had a layer with all hi-prio tiles\r
+ streq r2, [r1]\r
\r
ldmfd sp!, {r4-r11,lr}\r
bx lr\r
rsb r8, r3, #0\r
mov r8, r8, lsr #3 @ r8=tilex=(-ts->hscroll)>>3\r
bic r8, r8, #0xff000000\r
- orr r8, r8, r5, lsl #25 @ r8=(xmask[31:25]|tilex[15:0])\r
+ orr r8, r8, r5, lsl #25 @ r8=(xmask[31:25]|had_output[24]|tilex[15:0])\r
\r
ldr r4, =Scanline\r
orr r5, r1, r10, lsl #24\r
add r10,r10, #0x01000000\r
and r4, r10, #0x003f0000\r
cmp r4, r10, asr #8\r
- ble .dsloop_exit\r
+ ble .dsloop_vs_exit\r
\r
@ calc offset and read tileline code to r7, also calc ty\r
add r7, lr, #0x012000\r
beq .DrawStrip_vs_samecode @ we know stuff about this tile already\r
\r
mov r9, r7 @ remember code\r
+ orr r8, r8, #1<<24 @ seen non hi-prio tile\r
\r
movs r2, r9, lsl #20 @ if (code&0x1000)\r
mov r2, r2, lsl #1\r
bne .DrawStrip_vs_hiprio\r
b .dsloop_vs\r
\r
+.dsloop_vs_exit:\r
+ tst r8, #1<<24 @ seen non hi-prio tile\r
+ ldreq r1, =rendstatus\r
+ mov r0, #0\r
+ ldreq r2, [r1]\r
+ str r0, [r6] @ terminate the cache list\r
+ orreq r2, r2, #0x40 @ had a layer with all hi-prio tiles\r
+ streq r2, [r1]\r
+\r
+ ldmfd sp!, {r4-r11,lr}\r
+ bx lr\r
+\r
\r
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
\r
DrawTilesFromCache:\r
stmfd sp!, {r4-r8,r11,lr}\r
\r
- mvn r5, #0 @ r5=prevcode=-1\r
- mov r8, r1\r
-\r
@ cache some stuff to avoid mem access\r
ldr r11,=HighCol\r
ldr lr, =(Pico+0x10000) @ lr=Pico.vram\r
mov r12,#0xf\r
\r
+ mvn r5, #0 @ r5=prevcode=-1\r
+ movs r8, r1\r
+ bne .dtfc_check_rendflags\r
+\r
@ scratch: r4, r7\r
.dtfc_loop:\r
ldr r6, [r0], #4 @ read code\r
mov r12, #0xf\r
b .dtfc_loop\r
\r
+@ check if we have detected layer covered with hi-prio tiles:\r
+.dtfc_check_rendflags:\r
+ ldr r1, =rendstatus\r
+ ldr r2, [r1]\r
+ tst r2, #0xc0\r
+ beq .dtfc_loop\r
+ mov r8, #0 @ sh/hi mode off\r
+ tst r2, #0x80\r
+ bne .dtfc_loop @ already processed\r
+ orr r2, r2, #0x80\r
+ str r2, [r1]\r
+\r
+ add r1, r11,#8\r
+ mov r3, #320/4\r
+ mov r7, #0x80\r
+ orr r7, r7, r7, lsl #8\r
+ orr r7, r7, r7, lsl #16\r
+ mov r6, #0x3f\r
+ orr r6, r6, r6, lsl #8\r
+ orr r6, r6, r6, lsl #16\r
+.dtfc_loop_shprep:\r
+ subs r3, r3, #1\r
+ bmi .dtfc_loop @ done\r
+ ldr r2, [r1]\r
+ tst r2, r7\r
+ andeq r2, r2, r6\r
+ streq r2, [r1], #4\r
+ beq .dtfc_loop_shprep\r
+ tst r2, #0x80000000\r
+ biceq r2, r2, #0xc0000000\r
+ tst r2, #0x00800000\r
+ biceq r2, r2, #0x00c00000\r
+ tst r2, #0x00008000\r
+ biceq r2, r2, #0x0000c000\r
+ tst r2, #0x00000080\r
+ biceq r2, r2, #0x000000c0\r
+ str r2, [r1], #4\r
+ b .dtfc_loop_shprep\r
+\r
.pool\r
\r
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r