* AS is enabled by user and takes priority over "sonic mode".\r
*\r
* since renderer always draws line in 8bit mode, there are 2 spare bits:\r
- * b \ mode: s/h sonic\r
- * 00 normal pal index\r
- * 01 shadow pal index\r
- * 10 hilight+op spr pal index\r
- * 11 shadow +op spr pal index\r
+ * b \ mode: s/h sonic\r
+ * 00 normal pal index\r
+ * 01 hilight pal index\r
+ * 10 shadow pal index\r
+ * 11 hilight|shadow=normal pal index\r
+ *\r
+ * sprite ops can only be correctly done after the plane rendering s/h state is\r
+ * known since the op result changes if there's at least one high prio plane.\r
+ * sprite op rendering is deferred until this is known, and hilight is used as\r
+ * mark since it can't occur before sprite ops:\r
+ * x1 op marker pal index\r
+ *\r
+ * low prio s/h rendering:\r
+ * - plane and non-op sprite pixels have shadow\r
+ * - sprite op pixel rendering is marked with hilight (deferred)\r
+ * high prio s/h rendering:\r
+ * - plane and non-op sprite pixels are normal\r
+ * - all op sprite pixels (marked low, or high prio) are rendered\r
*\r
* not handled properly:\r
- * - hilight op on shadow tile\r
+ * - high prio s/h ops overlapping low prio sprite shows low sprite, not A,B,G\r
*/\r
\r
#include "pico_int.h"\r
\r
unsigned int VdpSATCache[128]; // VDP sprite cache (1st 32 sprite attr bits)\r
\r
-#define LF_PLANE_1 (1 << 0)\r
+// NB don't change any defines without checking their usage in ASM\r
+\r
+#define LF_PLANE (1 << 0) // must be = 1\r
#define LF_SH (1 << 1) // must be = 2\r
#define LF_FORCE (1 << 2)\r
\r
+#define LF_PLANE_A 0\r
+#define LF_PLANE_B 1\r
+\r
#define SPRL_HAVE_HI 0x80 // have hi priority sprites\r
#define SPRL_HAVE_LO 0x40 // *lo*\r
#define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line\r
#define SPRL_TILE_OVFL 0x04 // tile limit exceeded on previous line\r
#define SPRL_HAVE_MASK0 0x02 // have sprite with x == 0 in 1st slot\r
#define SPRL_MASKED 0x01 // lo prio masking by sprite with x == 0 active\r
+\r
unsigned char HighLnSpr[240][4+MAX_LINE_SPRITES+1]; // sprite_count, ^flags, tile_count, sprites_total, [spritep]..., last_width\r
\r
int rendstatus_old;\r
TileFlipMaker_(pix_func,)\r
\r
#define TileNormMakerAS(funcname, pix_func) \\r
-static unsigned funcname(unsigned char *pd, unsigned m, unsigned int pack, int pal) \\r
+static unsigned funcname(unsigned m, unsigned char *pd, unsigned int pack, int pal) \\r
TileNormMaker_(pix_func,m)\r
\r
#define TileFlipMakerAS(funcname, pix_func) \\r
-static unsigned funcname(unsigned char *pd, unsigned m, unsigned int pack, int pal) \\r
+static unsigned funcname(unsigned m, unsigned char *pd, unsigned int pack, int pal) \\r
TileFlipMaker_(pix_func,m)\r
\r
+// draw layer or non-s/h sprite pixels (no operator colors)\r
#define pix_just_write(x) \\r
if (t) pd[x]=pal|t\r
\r
-TileNormMaker(TileNorm,pix_just_write)\r
-TileFlipMaker(TileFlip,pix_just_write)\r
+TileNormMaker(TileNorm, pix_just_write)\r
+TileFlipMaker(TileFlip, pix_just_write)\r
\r
#ifndef _ASM_DRAW_C\r
\r
-// draw a sprite pixel, process operator colors\r
+// draw sprite pixels, process operator colors\r
#define pix_sh(x) \\r
if (!t); \\r
- else if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
+ else if (t>=0xe) pd[x]|=(t-1)<<6; /* 80 shadow, 40 hilight */ \\r
else pd[x]=pal|t\r
\r
TileNormMaker(TileNormSH, pix_sh)\r
TileFlipMaker(TileFlipSH, pix_sh)\r
\r
-// draw a sprite pixel, mark operator colors\r
+// draw sprite pixels, mark but don't process operator colors\r
#define pix_sh_markop(x) \\r
if (!t); \\r
- else if (t>=0xe) pd[x]|=0x80; \\r
+ else if (t>=0xe) pd[x]|=0x40; \\r
else pd[x]=pal|t\r
\r
TileNormMaker(TileNormSH_markop, pix_sh_markop)\r
\r
#endif\r
\r
-// process operator pixels only, apply only on low pri tiles and other op pixels\r
+// draw low prio sprite operator pixels if visible (i.e. marked)\r
#define pix_sh_onlyop(x) \\r
- if (t>=0xe && (pd[x]&0xc0)) \\r
- pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
+ if (t>=0xe && (pd[x]&0x40)) \\r
+ pd[x]=(pd[x]&0xbf)|((t-1)<<6)\r
\r
#ifndef _ASM_DRAW_C\r
\r
\r
// AS: sprite mask bits in m shifted to bits 8-15, see DrawSpritesHiAS\r
\r
-// draw a sprite pixel (AS)\r
+// draw high prio sprite pixels (AS)\r
#define pix_as(x) \\r
if (t && (m & (1<<(x+8)))) m &= ~(1<<(x+8)), pd[x] = pal | t\r
\r
TileNormMakerAS(TileNormAS, pix_as)\r
TileFlipMakerAS(TileFlipAS, pix_as)\r
\r
-// draw a sprite pixel, process operator colors (AS)\r
+// draw high prio sprite pixels, process operator colors (AS)\r
+// sprite+planes: h+s->n, h+[nh]->h, s+[nhs]->s, hence mask h before op\r
#define pix_sh_as(x) \\r
if (t && (m & (1<<(x+8)))) { \\r
m &= ~(1<<(x+8)); \\r
- if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
+ if (t>=0xe) pd[x]=(pd[x]&0xbf)|((t-1)<<6); \\r
else pd[x] = pal | t; \\r
}\r
\r
TileNormMakerAS(TileNormSH_AS, pix_sh_as)\r
TileFlipMakerAS(TileFlipSH_AS, pix_sh_as)\r
\r
+// draw only sprite operator pixels (AS)\r
#define pix_sh_as_onlyop(x) \\r
if (t && (m & (1<<(x+8)))) { \\r
m &= ~(1<<(x+8)); \\r
TileNormMakerAS(TileNormSH_AS_onlyop_lp, pix_sh_as_onlyop)\r
TileFlipMakerAS(TileFlipSH_AS_onlyop_lp, pix_sh_as_onlyop)\r
\r
-// mark pixel as sprite pixel (AS)\r
+// mark low prio sprite pixels (AS)\r
#define pix_sh_as_onlymark(x) \\r
if (t) m &= ~(1<<(x+8))\r
\r
#define pix_sh_as_and(x) /* XXX is there S/H with forced draw? */ \\r
if (m & (1<<(x+8))) { \\r
m &= ~(1<<(x+8)); \\r
- if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \\r
+ if (t>=0xe) pd[x]=(pd[x]&0xbf)|((t-1)<<6); \\r
else pd[x] = (pd[x] & 0xc0) | (pd[x] & (pal | t)); \\r
}\r
\r
unsigned char *pd = Pico.est.HighCol;\r
int tilex,dx,ty,code=0,addr=0,cells;\r
int oldcode=-1,blank=-1; // The tile we know is blank\r
- int pal=0,sh;\r
+ int pal=0;\r
\r
// Draw tiles across screen:\r
- sh = (lflags & LF_SH) << 5; // 0x40\r
tilex=((-ts->hscroll)>>3)+cellskip;\r
ty=(ts->line&7)<<1; // Y-Offset into tile\r
dx=((ts->hscroll-1)&7)+1;\r
unsigned int pack;\r
\r
code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)];\r
- if (code == blank)\r
- continue;\r
if ((code >> 15) | (lflags & LF_FORCE)) { // high priority tile\r
int cval = code | (dx<<16) | (ty<<25);\r
if(code&0x1000) cval^=7<<26;\r
*ts->hc++ = cval; // cache it\r
continue;\r
}\r
+ if (code == blank)\r
+ continue;\r
\r
if (code!=oldcode) {\r
oldcode = code;\r
addr+=ty;\r
if (code&0x1000) addr^=0xe; // Y-flip\r
\r
- pal=((code>>9)&0x30)|sh;\r
+ pal=((code>>9)&0x30)|((lflags&LF_SH)<<6); // shadow\r
}\r
\r
pack = *(unsigned int *)(PicoMem.vram + addr);\r
}\r
\r
code=PicoMem.vram[ts->nametab+nametabadd+(tilex&ts->xmask)];\r
- if ((code<<16|ty)==blank) continue;\r
if (code>>15) { // high priority tile\r
int cval = code | (dx<<16) | (ty<<25);\r
if(code&0x1000) cval^=7<<26;\r
*ts->hc++ = cval; // cache it\r
continue;\r
}\r
+ if ((code<<16|ty)==blank) continue;\r
\r
if (code!=oldcode) {\r
oldcode = code;\r
// Get tile address/2:\r
addr=(code&0x7ff)<<4;\r
\r
- pal=((code>>9)&0x30)|((plane_sh<<5)&0x40);\r
+ pal=((code>>9)&0x30)|((plane_sh&LF_SH)<<6); // shadow\r
}\r
\r
if (code & 0x1000) ty ^= 0xe; // Y-flip\r
#ifndef _ASM_DRAW_C\r
static\r
#endif\r
-void DrawStripInterlace(struct TileStrip *ts)\r
+void DrawStripInterlace(struct TileStrip *ts, int plane_sh)\r
{\r
unsigned char *pd = Pico.est.HighCol;\r
int tilex=0,dx=0,ty=0,code=0,addr=0,cells;\r
addr=(code&0x3ff)<<5;\r
if (code&0x1000) addr+=30-ty; else addr+=ty; // Y-flip\r
\r
-// pal=Pico.cram+((code>>9)&0x30);\r
- pal=((code>>9)&0x30);\r
+ pal=((code>>9)&0x30)|((plane_sh&LF_SH)<<6); // shadow\r
}\r
\r
pack = *(unsigned int *)(PicoMem.vram + addr);\r
}\r
\r
// Find name table:\r
- if (plane_sh&1) ts.nametab=(pvid->reg[4]&0x07)<<12; // B\r
- else ts.nametab=(pvid->reg[2]&0x38)<< 9; // A\r
+ if (plane_sh&LF_PLANE) ts.nametab=(pvid->reg[4]&0x07)<<12; // B\r
+ else ts.nametab=(pvid->reg[2]&0x38)<< 9; // A\r
\r
htab=pvid->reg[13]<<9; // Horizontal scroll table address\r
switch (pvid->reg[11]&3) {\r
case 2: htab += (est->DrawScanline<<1) & ~0x0f; break; // Offset by tile\r
case 3: htab += (est->DrawScanline<<1); break; // Offset by line\r
}\r
- htab+=plane_sh&1; // A or B\r
+ htab+=plane_sh&LF_PLANE; // A or B\r
\r
// Get horizontal scroll value, will be masked later\r
ts.hscroll = PicoMem.vram[htab & 0x7fff];\r
\r
if((pvid->reg[12]&6) == 6) {\r
// interlace mode 2\r
- vscroll = PicoMem.vsram[plane_sh & 1]; // Get vertical scroll value\r
+ vscroll = PicoMem.vsram[plane_sh&LF_PLANE]; // Get vertical scroll value\r
\r
// Find the line in the name table\r
ts.line=(vscroll+(est->DrawScanline<<1))&((ymask<<1)|1);\r
ts.nametab+=(ts.line>>4)<<shift[width];\r
\r
- DrawStripInterlace(&ts);\r
+ DrawStripInterlace(&ts, plane_sh);\r
} else if( pvid->reg[11]&4) {\r
// shit, we have 2-cell column based vscroll\r
// luckily this doesn't happen too often\r
// vscroll value for leftmost cells in case of hscroll not on 16px boundary\r
// XXX it's unclear what exactly the hw is doing. Continue reading where it\r
// stopped last seems to work best (H40: 0x50 (wrap->0x00), H32 0x40).\r
- plane_sh |= PicoMem.vsram[(pvid->reg[12]&1?0x00:0x20) + (plane_sh&1)] << 16;\r
+ plane_sh |= PicoMem.vsram[(pvid->reg[12]&1?0x00:0x20) + (plane_sh&LF_PLANE)] << 16;\r
DrawStripVSRam(&ts, plane_sh, cellskip);\r
} else {\r
- vscroll = PicoMem.vsram[plane_sh & 1]; // Get vertical scroll value\r
+ vscroll = PicoMem.vsram[plane_sh&LF_PLANE]; // Get vertical scroll value\r
\r
// Find the line in the name table\r
ts.line=(vscroll+est->DrawScanline)&ymask;\r
\r
if (prio) {\r
int *zb = (int *)(est->HighCol+8+(tilex<<3));\r
- *zb++ &= 0xbfbfbfbf;\r
- *zb &= 0xbfbfbfbf;\r
+ *zb++ &= 0x7f7f7f7f;\r
+ *zb &= 0x7f7f7f7f;\r
} else {\r
- pal |= 0x40;\r
+ pal |= 0x80;\r
}\r
\r
// Get tile address/2:\r
Pico.est.rendstatus |= PDRAW_SHHI_DONE;\r
while (c--)\r
{\r
- *zb++ &= 0xbfbfbfbf;\r
+ *zb++ &= 0x7f7f7f7f;\r
}\r
}\r
\r
while ((code=*hc++)) {\r
// Get tile address/2:\r
addr = (code & 0x7ff) << 4;\r
- addr += code >> 25; // y offset into tile\r
+ addr += (unsigned int)code >> 25; // y offset into tile\r
\r
pack = *(unsigned int *)(PicoMem.vram + addr);\r
if (!pack)\r
addr+=(unsigned int)code>>25; // y offset into tile\r
dx=(code>>16)&0x1ff;\r
zb = est->HighCol+dx;\r
- *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf;\r
- *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf;\r
+ *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f;\r
+ *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f;\r
\r
pack = *(unsigned int *)(PicoMem.vram + addr);\r
if (!pack)\r
delta<<=4; // Delta of address\r
\r
pal=(code>>9)&0x30;\r
- pal|=sh<<6;\r
+ pal|=sh<<7; // shadow\r
\r
if (sh && (code&0x6000) == 0x6000) {\r
if(code&0x0800) fTileFunc=TileFlipSH_markop;\r
\r
static void DrawSpritesHiAS(unsigned char *sprited, int sh)\r
{\r
- static unsigned (*tilefuncs[2][2][2])(unsigned char *, unsigned, unsigned, int) = {\r
+ static unsigned (*tilefuncs[2][2][2])(unsigned, unsigned char *, unsigned, int) = {\r
{ {TileNormAS_onlymark, TileFlipAS_onlymark}, {TileNormAS, TileFlipAS} },\r
{ {TileNormSH_AS_onlyop_lp, TileFlipSH_AS_onlyop_lp}, {TileNormSH_AS, TileFlipSH_AS} }\r
}; // [sh?][hi?][flip?]\r
- unsigned (*fTileFunc)(unsigned char *pd, unsigned m, unsigned int pack, int pal);\r
+ unsigned (*fTileFunc)(unsigned m, unsigned char *pd, unsigned int pack, int pal);\r
unsigned char *pd = Pico.est.HighCol;\r
- unsigned char mb[1+320/8+1];\r
+ unsigned char mb[sizeof(DefHighCol)/8];\r
unsigned char *p, *mp;\r
unsigned m;\r
int entry, cnt;\r
\r
m |= mp[1] << 8; // next mask byte\r
// shift mask bits to bits 8-15 for easier load/store handling\r
- m = fTileFunc(pd + sx, m << (8-(sx&0x7)), pack, pal) >> (8-(sx&0x7));\r
+ m = fTileFunc(m << (8-(sx&0x7)), pd + sx, pack, pal) >> (8-(sx&0x7));\r
} \r
*mp = m; // write last mask byte\r
}\r
unsigned char *pd = Pico.est.HighCol;\r
int tilex,dx,ty,code=0,addr=0,cells;\r
int oldcode=-1;\r
- int pal=0,sh;\r
+ int pal=0;\r
\r
// Draw tiles across screen:\r
- sh = (lflags & LF_SH) << 5; // 0x40\r
tilex=((-ts->hscroll)>>3)+cellskip;\r
ty=(ts->line&7)<<1; // Y-Offset into tile\r
dx=((ts->hscroll-1)&7)+1;\r
addr+=ty;\r
if (code&0x1000) addr^=0xe; // Y-flip\r
\r
- pal=((code>>9)&0x30)|sh;\r
+ pal=((code>>9)&0x30)|((lflags & LF_SH) << 6);\r
}\r
\r
pack = *(unsigned int *)(PicoMem.vram + addr);\r
// Get tile address/2:\r
addr=(code&0x7ff)<<4;\r
\r
- pal=((code>>9)&0x30)|((plane_sh<<5)&0x40);\r
+ pal=((code>>9)&0x30)|((plane_sh&LF_SH)<<6); // shadow\r
}\r
\r
if (code & 0x1000) ty ^= 0xe; // Y-flip\r
ts.line=(vscroll+(est->DrawScanline<<1))&((ymask<<1)|1);\r
ts.nametab+=(ts.line>>4)<<shift[width];\r
\r
- DrawStripInterlace(&ts);\r
+ DrawStripInterlace(&ts, plane_sh);\r
} else if( pvid->reg[11]&4) {\r
// shit, we have 2-cell column based vscroll\r
// luckily this doesn't happen too often\r
// rather messy (XXX revisit layer compositing)\r
static void DrawSpritesForced(unsigned char *sprited)\r
{\r
- unsigned (*fTileFunc)(unsigned char *pd, unsigned m, unsigned int pack, int pal);\r
+ unsigned (*fTileFunc)(unsigned m, unsigned char *pd, unsigned int pack, int pal);\r
unsigned char *pd = Pico.est.HighCol;\r
- unsigned char mb[1+320/8+1];\r
+ unsigned char mb[sizeof(DefHighCol)/8];\r
unsigned char *p, *mp;\r
unsigned m;\r
int entry, cnt;\r
\r
m |= mp[1] << 8; // next mask byte\r
// shift mask bits to bits 8-15 for easier load/store handling\r
- m = fTileFunc(pd + sx, m << (8-(sx&0x7)), pack, pal) >> (8-(sx&0x7));\r
+ m = fTileFunc(m << (8-(sx&0x7)), pd + sx, pack, pal) >> (8-(sx&0x7));\r
} \r
*mp = m; // write last mask byte\r
}\r
\r
// Start with a blank scanline (background colour):\r
back=reg7&0x3f;\r
- back|=sh<<6;\r
+ back|=sh<<7; // shadow\r
back|=back<<8;\r
back|=back<<16;\r
\r
// treat it like it was 4-bit per channel, since in s/h mode it somewhat is that.\r
// otherwise intensity difference between this and s/h will be wrong\r
t |= (t >> 4) & 0x08610861; // 0x18e318e3\r
- dpal[i] = t;\r
+ dpal[i] = dpal[0xc0/2 + i] = t;\r
}\r
\r
// norm: xxx0, sh: 0xxx, hi: 0xxx + 7\r
{\r
// shadowed pixels\r
for (i = 0; i < 0x40 / 2; i++)\r
- dpal[0x40/2 | i] = dpal[0xc0/2 | i] = (dpal[i] >> 1) & 0x738e738e;\r
+ dpal[0x80/2 + i] = (dpal[i] >> 1) & 0x738e738e;\r
// hilighted pixels\r
for (i = 0; i < 0x40 / 2; i++) {\r
t = ((dpal[i] >> 1) & 0x738e738e) + 0x738e738e; // 0x7bef7bef;\r
t |= (t >> 4) & 0x08610861;\r
- dpal[0x80/2 | i] = t;\r
+ dpal[0x40/2 + i] = t;\r
}\r
+ // pixels in color 14 always appear normal (hw bug?)\r
+ unsigned short *hpal = est->HighPal;\r
+ hpal[0x80 + 0x0e] = hpal[0x40 + 0x0e] = hpal[0x0e];\r
+ hpal[0x80 + 0x1e] = hpal[0x40 + 0x1e] = hpal[0x1e];\r
+ hpal[0x80 + 0x2e] = hpal[0x40 + 0x2e] = hpal[0x2e];\r
}\r
}\r
\r
for (i = 0; i < 0x40 / 2; i++) {\r
t = spal[i];\r
#ifdef USE_BGR555\r
- t = ((t & 0x000e000e)<< 1) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)<<4);\r
+ t = ((t & 0x0e000e00)<< 3) | ((t & 0x00e000e0)<<2) | ((t & 0x000e000e)<<1);\r
#else\r
t = ((t & 0x000e000e)<<12) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)>>7);\r
#endif\r
// treat it like it was 4-bit per channel, since in s/h mode it somewhat is that.\r
// otherwise intensity difference between this and s/h will be wrong\r
t |= (t >> 4) & 0x08610861; // 0x18e318e3\r
- dpal[i] = t;\r
+ dpal[i] = dpal[0xc0/2 + i] = t;\r
}\r
\r
// norm: xxx0, sh: 0xxx, hi: 0xxx + 7\r
{\r
// shadowed pixels\r
for (i = 0; i < 0x40 / 2; i++)\r
- dpal[0x40/2 | i] = dpal[0xc0/2 | i] = (dpal[i] >> 1) & 0x738e738e;\r
+ dpal[0x80/2 + i] = (dpal[i] >> 1) & 0x738e738e;\r
// hilighted pixels\r
for (i = 0; i < 0x40 / 2; i++) {\r
t = ((dpal[i] >> 1) & 0x738e738e) + 0x738e738e; // 0x7bef7bef;\r
t |= (t >> 4) & 0x08610861;\r
- dpal[0x80/2 | i] = t;\r
+ dpal[0x40/2 + i] = t;\r
}\r
+ // pixels in color 14 always appear normal (hw bug?)\r
+ unsigned short *hpal = est->HighPal;\r
+ hpal[0x80 + 0x0e] = hpal[0x40 + 0x0e] = hpal[0x0e];\r
+ hpal[0x80 + 0x1e] = hpal[0x40 + 0x1e] = hpal[0x1e];\r
+ hpal[0x80 + 0x2e] = hpal[0x40 + 0x2e] = hpal[0x2e];\r
}\r
}\r
\r
\r
/* - layer B low - */\r
if (!(pvid->debug_p & PVD_KILL_B)) {\r
- lflags = LF_PLANE_1 | (sh << 1);\r
+ lflags = LF_PLANE_B | (sh<<1);\r
DrawLayer(lflags, HighCacheB, 0, maxcells, est);\r
}\r
/* - layer A low - */\r
- lflags = 0 | (sh << 1);\r
+ lflags = LF_PLANE_A | (sh<<1);\r
if (pvid->debug_p & PVD_KILL_A)\r
;\r
else if (hvwind == 1)\r
else if (est->rendstatus & PDRAW_INTERLACE)\r
DrawAllSpritesInterlace(1, sh);\r
// have sprites without layer pri bit ontop of sprites with that bit\r
- else if ((sprited[1] & 0xd0) == 0xd0 && (PicoIn.opt & POPT_ACC_SPRITES))\r
+ else if ((sprited[1] & SPRL_LO_ABOVE_HI) && (PicoIn.opt & POPT_ACC_SPRITES))\r
DrawSpritesHiAS(sprited, sh);\r
else if (sh && (sprited[1] & SPRL_MAY_HAVE_OP))\r
DrawSpritesSHi(sprited, est);\r
\r
#ifdef FORCE\r
if (pvid->debug_p & PVD_FORCE_B) {\r
- lflags = LF_PLANE_1 | (sh << 1);\r
+ lflags = LF_PLANE_B | (sh<<1);\r
DrawLayerForced(lflags, 0, maxcells, est);\r
} else if (pvid->debug_p & PVD_FORCE_A) {\r
- lflags = (sh << 1);\r
+ lflags = LF_PLANE_A | (sh<<1);\r
DrawLayerForced(lflags, 0, maxcells, est);\r
} else if (pvid->debug_p & PVD_FORCE_S)\r
DrawSpritesForced(sprited);\r
.endif\r
ldreqb r4, [r1,#\offs]\r
orrne r4, r3, r4\r
- andeq r4, r4, #0xbf\r
+ andeq r4, r4, #0x7f\r
strb r4, [r1,#\offs]\r
.endm\r
\r
@ TileSingleSh (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx; r12: helper pattern 0xf\r
.macro TileSingleSh\r
tst r0, #1 @ not aligned?\r
- mov r7, #0x00c000\r
- orr r7, r7, #0xc0\r
- ldrneb r4, [r1]\r
- ldreqh r4, [r1]\r
- orr r4, r4, r7\r
- strneb r4, [r1], #1\r
- streqh r4, [r1], #2\r
- ldrh r4, [r1]\r
- orr r4, r4, r7\r
- strh r4, [r1], #2\r
- ldrh r4, [r1]\r
- orr r4, r4, r7\r
- strh r4, [r1], #2\r
- ldrh r4, [r1]\r
- orr r4, r4, r7\r
- strh r4, [r1], #2\r
- ldrneb r4, [r1]\r
- orr r4, r4, r7\r
- strneb r4, [r1], #1\r
+ mov r7, #0x008000\r
+ orr r7, r7, #0x80\r
+ ldrneb r4, [r1], #1\r
+ ldreqh r4, [r1], #2 @ 1ci\r
+ ldrh r12, [r1], #2\r
+ orr r4, r4, r7\r
+ strneb r4, [r1, #-3]\r
+ streqh r4, [r1, #-4]\r
+ ldrh r4, [r1], #2\r
+ orr r12, r12, r7\r
+ strh r12, [r1, #-4]\r
+ ldrh r12, [r1], #2\r
+ orr r4, r4, r7\r
+ strh r4, [r1, #-4]\r
+ ldrneb r4, [r1]\r
+ orr r12, r12, r7\r
+ strh r12, [r1, #-2]\r
+ orrne r4, r4, r7\r
+ strneb r4, [r1], #1\r
+ mov r12, #0xf\r
.endm\r
\r
@ TileSingleHi (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=sx, r12: register with helper pattern 0xf\r
.macro TileSingleHi\r
tst r1, #1 @ not aligned?\r
- mov r7, #0x008000\r
- orr r7, r7, #0x80\r
+ mov r7, #0x004000\r
+ orr r7, r7, #0x40\r
ldrneb r4, [r1], #1\r
ldreqh r4, [r1], #2 @ 1ci\r
ldrh r12, [r1], #2\r
- bic r4, r4, r7, lsr #1\r
orr r4, r4, r7\r
strneb r4, [r1, #-3]\r
streqh r4, [r1, #-4]\r
ldrh r4, [r1], #2\r
- bic r12, r12, r7, lsr #1\r
orr r12, r12, r7\r
strh r12, [r1, #-4]\r
ldrh r12, [r1], #2\r
- bic r4, r4, r7, lsr #1\r
orr r4, r4, r7\r
strh r4, [r1, #-4]\r
ldrneb r4, [r1]\r
- bic r12, r12, r7, lsr #1\r
orr r12, r12, r7\r
strh r12, [r1, #-2]\r
- bicne r4, r4, r7, lsr #1\r
orrne r4, r4, r7\r
strneb r4, [r1], #1\r
mov r12, #0xf\r
ldrgeb r7, [r1,#\ofs]\r
orrlt r7, r3, r4 @ normal\r
\r
- bicge r7, r7, #0xc0\r
+ subge r4, r4, #1\r
orrge r7, r7, r4, lsl #6\r
strb r7, [r1,#\ofs]\r
0:\r
cmp r4, #0xe\r
ldrgeb r4, [r1,#\ofs]\r
orrlt r4, r3, r4\r
- orrge r4, r4, #0x80\r
+ orrge r4, r4, #0x40\r
strb r4, [r1,#\ofs]\r
0:\r
.endm\r
cmp r7, #0xe\r
blt 0f\r
\r
- tst r4, #0xc0\r
- bicne r4, r4, #0xc0\r
+ tst r4, #0x40\r
+ bicne r4, r4, #0x40\r
+ subne r7, r7, #1\r
orrne r4, r4, r7, lsl #6\r
strneb r4, [r1,#\ofs]\r
0:\r
mov r3, #0\r
orrmi r10,r10, #1<<23 @ r10=cells[31:24]|sh[23]|hi_not_empty[22]\r
orrcs r10,r10, #1<<20 @ |had_output[21]|force[20]|ty[15:0]\r
- movmi r3, #0x40 @ default to shadowed pal on sh mode\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
\r
ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels\r
\r
- bic r7, r3, #0x3f\r
+ bic r7, r3, #0x7f\r
and r3, r9, #0x6000\r
add r3, r7, r3, lsr #9 @ r3=pal=((code&0x6000)>>9);\r
\r
strneb r4, [r1], #1 @ have a remaining unaligned pixel?\r
b .dsloop_subr1\r
\r
-.DrawStrip_hiprio_maybempt:\r
- cmp r7, r9\r
- beq .dsloop @ must've been empty, otherwise we wouldn't get here\r
- movs r2, r7, 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
- 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
- beq .dsloop\r
- orr r10, r10, #1<<22\r
-\r
.DrawStrip_hiprio:\r
- tst r10, #0x00d00000 @ sh[23]|hi_not_empty[22]|force[20]\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
ldreq r3, [r1, #0x40] @ r3=vsram[0x20..0x21]\r
str r3, [r1, #0x7c] @ vsram[0x3e..0x3f]=r3\r
0:\r
- tst r9, #1<<31\r
+ tst r9, #1<<30\r
mov r3, #0\r
orrne r10,r10, #1<<23 @ r10=(cell[31:24]|sh[23]|hi_not_empty[22]|cells_max[21:16]|plane[15]|ty[14:0])\r
- movne r3, #0x40 @ default to shadowed pal on sh mode\r
+ movne r3, #0x80 @ default to shadowed pal on sh mode\r
\r
and r9, r9, #0xff00\r
add r8, r8, r9, lsr #8 @ tilex+=cellskip\r
\r
ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels\r
\r
- bic r7, r3, #0x3f\r
+ bic r7, r3, #0x7f\r
and r3, r9, #0x6000\r
add r3, r7, r3, lsr #9 @ r3=pal=((code&0x6000)>>9);\r
\r
b .dsloop_vs_subr1\r
\r
.DrawStrip_vs_hiprio:\r
- tst r10, #0x00c00000\r
- beq .DrawStrip_vs_hiprio_maybempt\r
sub r0, r1, r11\r
orr r7, r7, r0, lsl #16\r
orr r7, r7, r10, lsl #25 @ (ty<<25)\r
mov r0, #0xf\r
b .dsloop_vs\r
\r
-.DrawStrip_vs_hiprio_maybempt:\r
- cmp r7, r9\r
- beq .dsloop_vs @ must've been empty, otherwise we wouldn't get here\r
- movs r2, r7, 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
- ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels\r
- mov r9, r7 @ remember code\r
- tst r2, r2\r
- orrne r10, r10, #1<<22\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
ldr r1, [sp, #9*4] @ est\r
stmia sp, {r0,r2,r3,r5,r6,r9}\r
\r
mov r0, sp\r
- bl DrawStripInterlace @ struct TileStrip *ts\r
+ mov r1, r9, lsr #29\r
+ bl DrawStripInterlace @ struct TileStrip *ts, int plane_sh\r
\r
add sp, sp, #6*4\r
ldmfd sp!, {r4-r11,lr}\r
mov r0, r0, lsr #26\r
add lr, lr, #8\r
\r
- orr r0, r0, r1, lsl #6\r
+ orr r0, r0, r1, lsl #7\r
orr r0, r0, r0, lsl #8\r
orr r0, r0, r0, lsl #16\r
\r
.dtfc_shadow_blank:\r
tst r1, #1\r
ldrneb r4, [r1]\r
- mov r6, #0xbf\r
- and r4, r4, #0xbf\r
+ mov r6, #0x7f\r
+ and r4, r4, r6\r
strneb r4, [r1], #1\r
ldrh r4, [r1]\r
orr r6, r6, r6, lsl #8\r
\r
add r1, r11,#8\r
mov r3, #320/4/4\r
- mov r6, #0xbf\r
+ mov r6, #0x7f\r
orr r6, r6, r6, lsl #8\r
orr r6, r6, r6, lsl #16\r
.dtfc_loop_shprep:\r
orrs r9, r9, #0x10000000 @ r9=scc1 ???? ... <code> (s=shadow/hilight, cc=pal)\r
\r
mov r3, r4, lsr #9 @ r3=pal=((code>>9)&0x30);\r
- orrmi r3, r3, #0x40 @ for sh/hi\r
+ orrmi r3, r3, #0x80 @ for sh/hi\r
\r
adds r0, r2, #0 @ mov sx to r0 and set ZV flags\r
b .dspr_loop_enter\r
\r
.dw_shadow:\r
tst r6, #1 @ hi pri?\r
- orreq r3, r3, #0x40\r
+ orreq r3, r3, #0x80\r
beq .dw_shadow_done\r
ldr r4, [r1]\r
- mov r5, #0x3f\r
+ mov r5, #0x7f\r
orr r5, r5, r5, lsl #8\r
orr r5, r5, r5, lsl #16\r
and r4, r4, r5\r
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
\r
\r
-@ hilights 2 pixels in RGB444/BGR444 format\r
-.macro TileDoShHi2Pixels444 reg\r
- mov \reg, \reg, ror #12\r
- adds \reg, \reg, #0x40000000\r
- orrcs \reg, \reg, #0xf0000000\r
- mov \reg, \reg, ror #28\r
- adds \reg, \reg, #0x40000000\r
- orrcs \reg, \reg, #0xf0000000\r
- mov \reg, \reg, ror #28\r
- adds \reg, \reg, #0x40000000\r
- orrcs \reg, \reg, #0xf0000000\r
- mov \reg, \reg, ror #24\r
- adds \reg, \reg, #0x40000000\r
- orrcs \reg, \reg, #0xf0000000\r
- mov \reg, \reg, ror #28\r
- adds \reg, \reg, #0x40000000\r
- orrcs \reg, \reg, #0xf0000000\r
- mov \reg, \reg, ror #28\r
- adds \reg, \reg, #0x40000000\r
- orrcs \reg, \reg, #0xf0000000\r
- mov \reg, \reg, ror #12\r
-.endm\r
-\r
-\r
-@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r
-\r
-\r
@ Convert 0000bbb0 ggg0rrr0\r
@ to rrrrrggg gggbbbbb\r
\r
beq PicoDoHighPal555_end\r
\r
add r3, r10, #OFS_EST_HighPal\r
-\r
- @ shadowed pixels:\r
- mov r12, #0x008e\r
add r4, r3, #0x40*2\r
- orr r12,r12,#0x7300\r
- add r5, r3, #0xc0*2\r
- orr r12,r12,r12,lsl #16\r
- mov lr, #0x40/4\r
-.fl_loopcpRGB555_sh:\r
- ldmia r3!, {r1,r6}\r
- subs lr, lr, #1\r
- and r1, r12, r1, lsr #1\r
- and r6, r12, r6, lsr #1\r
- stmia r4!, {r1,r6}\r
- stmia r5!, {r1,r6}\r
- bne .fl_loopcpRGB555_sh\r
\r
- @ hilighted pixels:\r
+ @ hilighted pixels (0x40-0x7f):\r
@ t = ((dpal[i] >> 1) & 0x738e738e) + 0x738e738e;\r
@ t |= (t >> 4) & 0x08610861;\r
@ r8=0x08610861\r
- sub r3, r3, #0x40*2\r
+ mov r12, #0x008e\r
+ orr r12,r12,#0x7300\r
+ orr r12,r12,r12,lsl #16\r
mov lr, #0x40/4\r
.fl_loopcpRGB555_hi:\r
ldmia r3!, {r1,r6}\r
stmia r4!, {r1,r6}\r
subs lr, lr, #1\r
bne .fl_loopcpRGB555_hi\r
- mov r0, #1\r
\r
+ sub r3, r3, #0x40*2\r
+ @ shadowed (0x80-0xbf), shadow|hilight (aka normal, 0xc0-0xff) pixels:\r
+ add r5, r3, #0xc0*2\r
+ mov lr, #0x40/4\r
+.fl_loopcpRGB555_sh:\r
+ ldmia r3!, {r1,r6}\r
+ subs lr, lr, #1\r
+ stmia r5!, {r1,r6} @ 0xc0, normal\r
+ and r1, r12, r1, lsr #1\r
+ and r6, r12, r6, lsr #1\r
+ stmia r4!, {r1,r6}\r
+ bne .fl_loopcpRGB555_sh\r
+\r
+ @ fixup color 14 in palette 0,1,2 (always normal)\r
+ sub r4, r3, #0x40*2\r
+ ldrh r1, [r4, #0x0e*2] @ 0x0e, 0x1e, 0x2e\r
+ ldrh r5, [r4, #0x1e*2]\r
+ ldrh r6, [r4, #0x2e*2]\r
+ strh r1, [r3, #0x0e*2] @ 0x4e, 0x5e, 0x6e\r
+ strh r5, [r3, #0x1e*2]\r
+ strh r6, [r3, #0x2e*2]\r
+ strh r1, [r3, #0x4e*2] @ 0x8e, 0x9e, 0xae\r
+ strh r5, [r3, #0x5e*2]\r
+ strh r6, [r3, #0x6e*2]\r
+\r
+ mov r0, #1\r
PicoDoHighPal555_end:\r
ldmfd sp!, {r4-r10,pc}\r
\r