// --------------------------------------------\r
\r
#ifndef _ASM_DRAW_C\r
+#define DrawTile(mask) { \\r
+ if (code!=oldcode) { \\r
+ oldcode = code; \\r
+ \\r
+ pack = 0; \\r
+ if (code != blank) { \\r
+ /* Get tile address/2: */\\r
+ u32 addr = ((code&0x7ff)<<4) + ty; \\r
+ if (code & 0x1000) addr ^= 0xe; /* Y-flip */ \\r
+ \\r
+ pal = ((code>>9)&0x30) | sh; /* shadow */ \\r
+ \\r
+ pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \\r
+ if (!pack) \\r
+ blank = code; \\r
+ } \\r
+ } \\r
+ \\r
+ if (code & 0x8000) { /* (un-forced) high priority tile */ \\r
+ if (sh | (pack&mask)) { \\r
+ code |= (dx<<16) | (ty<<25); \\r
+ if (code & 0x1000) code ^= 0xe<<25; \\r
+ *hc++ = code, *hc++ = pack&mask; /* cache it */ \\r
+ } \\r
+ } else if (pack&mask) { \\r
+ if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \\r
+ else TileNorm(pd + dx, pack&mask, pal); \\r
+ } \\r
+}\r
+\r
static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip)\r
{\r
unsigned char *pd = Pico.est.HighCol;\r
u32 *hc = ts->hc;\r
int tilex, dx, ty, cells;\r
- u32 pack = 0, oldcode = -1, blank = -1; // The tile we know is blank\r
- unsigned int pal = 0, sh;\r
+ u32 code, oldcode = -1, blank = -1; // The tile we know is blank\r
+ unsigned int pal = 0, pack = 0, sh, mask = ~0;\r
\r
// Draw tiles across screen:\r
sh = (lflags & LF_SH) << 6; // shadow\r
ty=(ts->line&7)<<1; // Y-Offset into tile\r
dx=((ts->hscroll-1)&7)+1;\r
cells = ts->cells - cellskip;\r
- if(dx != 8) cells++; // have hscroll, need to draw 1 cell more\r
dx+=cellskip<<3;\r
\r
+ if (dx & 7) {\r
+ code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
+ mask = 0xffffffff<<((dx&7)*4);\r
+ if (code & 0x0800) mask = 0xffffffff>>((dx&7)*4);\r
+ mask = (~mask << 16) | (~mask >> 16);\r
+\r
+ DrawTile(mask);\r
+ dx += 8, tilex++, cells--;\r
+ }\r
+\r
// int force = (lflags&LF_FORCE) << 13;\r
for (; cells > 0; dx+=8, tilex++, cells--)\r
{\r
- u32 code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
+ code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
// code &= ~force; // forced always draw everything\r
\r
if (code == blank && !((code & 0x8000) && sh))\r
continue;\r
\r
- if (code!=oldcode) {\r
- oldcode = code;\r
-\r
- pack = 0;\r
- if (code != blank) {\r
- // Get tile address/2:\r
- u32 addr = ((code&0x7ff)<<4) + ty;\r
- if (code & 0x1000) addr ^= 0xe; // Y-flip\r
-\r
- pal = ((code>>9)&0x30) | sh; // shadow\r
+ DrawTile(~0);\r
+ }\r
\r
- pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr));\r
- if (!pack)\r
- blank = code;\r
- }\r
- }\r
+ if (dx & 7) {\r
+ code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
+// code &= ~force; // forced always draw everything\r
+ if (!(code == blank && !((code & 0x8000) && sh))) {\r
+ mask = 0xffffffff<<((dx&7)*4);\r
+ if (code & 0x0800) mask = 0xffffffff>>((dx&7)*4);\r
+ mask = (mask << 16) | (mask >> 16);\r
\r
- if (code & 0x8000) { // (un-forced) high priority tile\r
- code |= (dx<<16) | (ty<<25);\r
- if (code & 0x1000) code ^= 0xe<<25;\r
- *hc++ = code, *hc++ = pack; // cache it\r
- } else if (code != blank) {\r
- if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
- else TileNorm(pd + dx, pack, pal);\r
+ DrawTile(mask);\r
}\r
}\r
\r
}\r
#endif\r
\r
+#define DrawTileInterlace(mask) { \\r
+ if (code!=oldcode) { \\r
+ oldcode = code; \\r
+ \\r
+ pack = 0; \\r
+ if (code != blank) { \\r
+ /* Get tile address/2: */ \\r
+ u32 addr = ((code&0x3ff)<<5) + ty; \\r
+ if (code & 0x1000) addr ^= 0x1e; /* Y-flip */ \\r
+ \\r
+ pal = ((code>>9)&0x30) | sh; /* shadow */ \\r
+ \\r
+ pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \\r
+ if (!pack) \\r
+ blank = code; \\r
+ } \\r
+ } \\r
+ \\r
+ if (code & 0x8000) { /* high priority tile */ \\r
+ if (sh | (pack&mask)) { \\r
+ code = (code&0xfc00) | ((code&0x3ff)<<1) | (dx<<16) | (ty<<25); \\r
+ if (code & 0x1000) code ^= 0x1e<<25; \\r
+ *hc++ = code, *hc++ = pack&mask; /* cache it */ \\r
+ } \\r
+ } else if (pack&mask) { \\r
+ if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \\r
+ else TileNorm(pd + dx, pack&mask, pal); \\r
+ } \\r
+}\r
+\r
#ifndef _ASM_DRAW_C\r
static\r
#endif\r
unsigned char *pd = Pico.est.HighCol;\r
u32 *hc = ts->hc;\r
int tilex = 0, dx = 0, ty = 0, cells;\r
- u32 oldcode = -1, blank = -1; // The tile we know is blank\r
- unsigned int pal = 0, pack = 0, sh;\r
+ u32 code, oldcode = -1, blank = -1; // The tile we know is blank\r
+ unsigned int pal = 0, pack = 0, sh, mask = ~0;\r
\r
// Draw tiles across screen:\r
sh = (plane_sh & LF_SH) << 6; // shadow\r
ty=(ts->line&15)<<1; // Y-Offset into tile\r
dx=((ts->hscroll-1)&7)+1;\r
cells = ts->cells;\r
- if(dx != 8) cells++; // have hscroll, need to draw 1 cell more\r
+\r
+ if (dx & 7) {\r
+ code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
+ mask = 0xffffffff<<(dx*4);\r
+ if (code & 0x0800) mask = 0xffffffff>>(dx*4);\r
+ mask = (~mask << 16) | (~mask >> 16);\r
+\r
+ DrawTileInterlace(mask);\r
+ dx += 8, tilex++, cells--;\r
+ }\r
\r
// int force = (plane_sh&LF_FORCE) << 13;\r
for (; cells; dx+=8,tilex++,cells--)\r
if (code == blank && !(code & 0x8000))\r
continue;\r
\r
- if (code!=oldcode) {\r
- oldcode = code;\r
-\r
- pack = 0;\r
- if (code != blank) {\r
- // Get tile address/2:\r
- u32 addr = ((code&0x3ff)<<5) + ty;\r
- if (code & 0x1000) addr ^= 0x1e; // Y-flip\r
-\r
- pal = ((code>>9)&0x30) | sh; // shadow\r
+ DrawTileInterlace(~0);\r
+ }\r
\r
- pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr));\r
- if (!pack)\r
- blank = code;\r
- }\r
- }\r
+ if (dx & 7) {\r
+ code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
+// code &= ~force; // forced always draw everything\r
+ if (!(code == blank && !((code & 0x8000) && sh))) {\r
+ mask = 0xffffffff<<((dx&7)*4);\r
+ if (code & 0x0800) mask = 0xffffffff>>((dx&7)*4);\r
+ mask = (mask << 16) | (mask >> 16);\r
\r
- if (code & 0x8000) { // high priority tile\r
- if ((plane_sh&LF_SH) | (code!=blank)) {\r
- code = (code&0xfc00) | ((code&0x3ff)<<1) | (dx<<16) | (ty<<25);\r
- if (code & 0x1000) code ^= 0x1e<<25;\r
- *hc++ = code, *hc++ = pack; // cache it\r
- }\r
- continue;\r
- } else if (code != blank) {\r
- if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
- else TileNorm(pd + dx, pack, pal);\r
+ DrawTileInterlace(mask);\r
}\r
}\r
\r
\r
// --------------------------------------------\r
\r
-static void DrawTilesFromCacheShPrep(void)\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
- // but leave lo pri op sprite markers alone\r
- int c = 320/4, *zb = (int *)(Pico.est.HighCol+8);\r
- Pico.est.rendstatus |= PDRAW_SHHI_DONE;\r
- while (c--)\r
- {\r
- *zb++ &= 0x7f7f7f7f;\r
- }\r
-}\r
-\r
static void DrawTilesFromCache(u32 *hc, int sh, int rlim, struct PicoEState *est)\r
{\r
unsigned char *pd = est->HighCol;\r
\r
if (sh && (est->rendstatus & (PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO)))\r
{\r
- if (!(est->rendstatus & PDRAW_SHHI_DONE))\r
- DrawTilesFromCacheShPrep();\r
+ if (!(est->rendstatus & PDRAW_SHHI_DONE)) {\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
+ // but leave lo pri op sprite markers alone\r
+ int *zb = (int *)(Pico.est.HighCol+8);\r
+ int c = rlim / 4;\r
+ while (c--)\r
+ {\r
+ *zb++ &= 0x7f7f7f7f;\r
+ }\r
+ Pico.est.rendstatus |= PDRAW_SHHI_DONE;\r
+ }\r
sh = 0;\r
}\r
\r
{\r
while ((code=*hc++)) {\r
pack = *hc++;\r
+ if (rlim-dx < 0)\r
+ goto last_cut_tile;\r
if (!pack)\r
continue;\r
\r
dx = (code >> 16) & 0x1ff;\r
pal = ((code >> 9) & 0x30);\r
- if (rlim-dx < 0)\r
- goto last_cut_tile;\r
\r
if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
else TileNorm(pd + dx, pack, pal);\r
*zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f;\r
\r
pack = *hc++;\r
+ if (rlim - dx < 0)\r
+ goto last_cut_tile;\r
if (!pack)\r
continue;\r
\r
pal = ((code >> 9) & 0x30);\r
- if (rlim - dx < 0)\r
- goto last_cut_tile;\r
\r
if (code & 0x0800) TileFlip(pd + dx, pack, pal);\r
else TileNorm(pd + dx, pack, pal);\r
last_cut_tile:\r
// for vertical window cutoff\r
{\r
- unsigned int t;\r
-\r
- pd += dx;\r
- if (code&0x0800)\r
- {\r
- switch (rlim-dx+8)\r
- {\r
- case 7: t=pack&0x00000f00; if (t) pd[6]=(unsigned char)(pal|(t>> 8)); // "break" is left out intentionally\r
- case 6: t=pack&0x000000f0; if (t) pd[5]=(unsigned char)(pal|(t>> 4));\r
- case 5: t=pack&0x0000000f; if (t) pd[4]=(unsigned char)(pal|(t ));\r
- case 4: t=pack&0xf0000000; if (t) pd[3]=(unsigned char)(pal|(t>>28));\r
- case 3: t=pack&0x0f000000; if (t) pd[2]=(unsigned char)(pal|(t>>24));\r
- case 2: t=pack&0x00f00000; if (t) pd[1]=(unsigned char)(pal|(t>>20));\r
- case 1: t=pack&0x000f0000; if (t) pd[0]=(unsigned char)(pal|(t>>16));\r
- default: break;\r
- }\r
- }\r
- else\r
- {\r
- switch (rlim-dx+8)\r
- {\r
- case 7: t=pack&0x00f00000; if (t) pd[6]=(unsigned char)(pal|(t>>20));\r
- case 6: t=pack&0x0f000000; if (t) pd[5]=(unsigned char)(pal|(t>>24));\r
- case 5: t=pack&0xf0000000; if (t) pd[4]=(unsigned char)(pal|(t>>28));\r
- case 4: t=pack&0x0000000f; if (t) pd[3]=(unsigned char)(pal|(t ));\r
- case 3: t=pack&0x000000f0; if (t) pd[2]=(unsigned char)(pal|(t>> 4));\r
- case 2: t=pack&0x00000f00; if (t) pd[1]=(unsigned char)(pal|(t>> 8));\r
- case 1: t=pack&0x0000f000; if (t) pd[0]=(unsigned char)(pal|(t>>12));\r
- default: break;\r
+ unsigned int t, mask;\r
+\r
+ // rlim-dx + 8 px to draw -> mask shift 8-(rlim-dx + 8)\r
+ t = -(rlim - dx);\r
+ if (t < 8) {\r
+ mask = 0xffffffff<<(t*4);\r
+ if (code & 0x0800) mask = 0xffffffff>>(t*4);\r
+ mask = (mask << 16) | (mask >> 16);\r
+\r
+ if (pack&mask) {\r
+ if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal);\r
+ else TileNorm(pd + dx, pack&mask, pal);\r
}\r
}\r
}\r
movs r3, r9, lsl #1 @ (force[31]|sh[30]) << 1\r
mov r3, #0\r
orrmi r10,r10, #1<<23 @ r10=cells[31:24]|sh[23]|hi_not_empty[22]\r
-@ orrcc r10,r10, #1<<20 @ |had_output[21]|!force[20]|ty[15:0]\r
+@ orrcc r10,r10, #1<<20 @ |had_output[21]|!force[20]|hscroll[19:17]|ty[15:0]\r
movmi r3, #0x80 @ default to shadowed pal on sh mode\r
\r
- cmp r7, #8\r
- addne r10,r10, #0x01000000 @ we will loop cells+1 times if there is scroll\r
+ and r4, r7, #7\r
+ orr r10,r10, r4, lsl #16 @ we will process cells+1 if there is scroll\r
\r
and r9, r9, #0xff00\r
add r8, r8, r9, lsr #8 @ tilex+=cellskip\r
mvn r9, #0 @ r9=prevcode=-1\r
add r1, r11, r7 @ r1=pdest\r
\r
- @ r10=cells[31:24]|sh[23]|hi_not_empty[22]|had_output[21]|!force[20]|ty[15:0]\r
+ @ r10=cells[31:24]|sh[23]|hi_not_empty[22]|had_output[21]|!force[20]|hscroll[19:17]|ty[15:0]\r
@ r1=pd+dx r2=pack r3=pal r5=xmask r6=hc r8=tilex r9=prevcode r11=HighCol r12=nametab lr=vram\r
@ r4 & r7 are scratch in this loop\r
+\r
+ ands r4, r10, #7<<16 @ hscroll?\r
+ beq .dsloop_subr1\r
+ subs r10,r10, #0x01000000\r
+ bmi .dsloop_exit\r
+\r
+ and r7, r5, r8 @ do first cut tile\r
+ add r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords)\r
+ ldrh r9, [r7, r12] @ r7=code (int, but from unsigned, no sign extend)\r
+\r
+ add r8, r8, #1\r
+\r
+ movs r2, r9, lsl #20 @ if (code&0x1000)\r
+ mov r2, r2, lsl #1\r
+ add r2, r2, r10, lsl #17\r
+ mov r2, r2, lsr #17\r
+ eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe;\r
+\r
+ ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
+\r
+ mvn r7, #0\r
+ mov r4, r4, lsr #16-2 @ (dx&7)*4\r
+ tst r9, #0x0800\r
+ moveq r7, r7, lsl r4 @ mask = ~0 [shift] (dx&7)*4\r
+ movne r7, r7, lsr r4\r
+ mvn r7, r7, ror #16\r
+ and r2, r2, r7 @ pack&mask\r
+\r
+ orr r9, r9, #0x80000000 @ invalidate oldcode since pack is masked\r
+ b .DrawStrip_samecode\r
+\r
.dsloop_subr1:\r
sub r1, r1, #8\r
.dsloop: @ 40-41 times\r
eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe;\r
\r
ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
-\r
.DrawStrip_samecode:\r
tst r9, #0x8000\r
@ tstne r10, #1<<20 @ !force[20]\r
b .dsloop\r
\r
.dsloop_exit:\r
+ ands r4,r10, #7<<16 @ hscroll?\r
+ beq .DrawStrip_noscroll\r
+\r
+ and r7, r5, r8 @ do one more cut tile\r
+ add r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords)\r
+ ldrh r9, [r7, r12] @ r7=code (int, but from unsigned, no sign extend)\r
+\r
+ add r1, r1, #8\r
+\r
+ movs r2, r9, lsl #20 @ if (code&0x1000)\r
+ mov r2, r2, lsl #1\r
+ add r2, r2, r10, lsl #17\r
+ mov r2, r2, lsr #17\r
+ eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe;\r
+\r
+ ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
+\r
+ mvn r7, #0\r
+ mov r4, r4, lsr #16-2 @ (dx&7)*4\r
+ tst r9, #0x0800\r
+ moveq r7, r7, lsl r4 @ mask = ~0 [shift] (dx&7)*4\r
+ movne r7, r7, lsr r4\r
+ mov r7, r7, ror #16\r
+ and r2, r2, r7 @ pack&mask\r
+\r
+ bic r10,r10, #7<<16\r
+ b .DrawStrip_samecode @ one last time, with last tile now masked\r
+\r
+.DrawStrip_noscroll:\r
tst r10, #1<<21 @ seen non hi-prio tile\r
ldr r1, [sp, #9*4] @ est\r
mov r0, #0\r
b .dtfc_loop\r
\r
.dtfc_cut_tile:\r
- add r4, r4, #7 @ 0-6\r
+ cmn r4, #8\r
+ ble .dtfc_loop @ off limits\r
+\r
+ rsb r4, r4, #0 @ 1-7\r
mov r4, r4, lsl #2\r
- mov r12,#0xf<<28\r
- mov r12,r12,asr r4\r
- mov r2, r2, ror #16\r
+ mvn r12,#0\r
tst r6, #0x0800 @ flipped?\r
- mvnne r12,r12\r
+ moveq r12,r12, lsl r4\r
+ movne r12,r12, lsr r4\r
+ mov r12,r12, ror #16\r
and r2, r2, r12\r
- mov r2, r2, ror #16\r
mov r12,#0xf\r
tst r8, #1\r
bne .dtfc_shadow\r