aboutsummaryrefslogtreecommitdiff
path: root/src/GPU2D.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/GPU2D.cpp')
-rw-r--r--src/GPU2D.cpp99
1 files changed, 74 insertions, 25 deletions
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index b510767..30a6d45 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -943,8 +943,8 @@ void GPU2D::VBlankEnd()
BGMosaicYMax = BGMosaicSize[1];
//OBJMosaicY = 0;
//OBJMosaicYMax = OBJMosaicSize[1];
- OBJMosaicY = 0;
- OBJMosaicYCount = 0;
+ //OBJMosaicY = 0;
+ //OBJMosaicYCount = 0;
if (Accelerated)
{
@@ -2238,6 +2238,13 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2
BGYRefInternal[0] += rotD;
}
+// OBJ line buffer:
+// * bit0-15: color (bit15=1: direct color, bit15=0: palette index, bit12=0 to indicate extpal)
+// * bit16-17: BG-relative priority
+// * bit18: non-transparent sprite pixel exists here
+// * bit19: X mosaic should be applied here
+// * bit24-31: compositor flags
+
void GPU2D::ApplySpriteMosaicX()
{
// apply X mosaic if needed
@@ -2255,7 +2262,7 @@ void GPU2D::ApplySpriteMosaicX()
continue;
}
- if ((!(OBJLine[i-1] & 0x100000)) || (CurOBJXMosaicTable[i] == 0))
+ if ((OBJIndex[i] != OBJIndex[i-1]) || (CurOBJXMosaicTable[i] == 0))
lastcolor = OBJLine[i];
else
OBJLine[i] = lastcolor;
@@ -2322,11 +2329,25 @@ void GPU2D::InterleaveSprites(u32 prio)
void GPU2D::DrawSprites(u32 line)
{
+ if (line == 0)
+ {
+ // reset those counters here
+ // TODO: find out when those are supposed to be reset
+ // it would make sense to reset them at the end of VBlank
+ // however, sprites are rendered one scanline in advance
+ // so they need to be reset a bit earlier
+
+ OBJMosaicY = 0;
+ OBJMosaicYCount = 0;
+ }
+
NumSprites = 0;
memset(OBJLine, 0, 256*4);
memset(OBJWindow, 0, 256);
if (!(DispCnt & 0x1000)) return;
+ memset(OBJIndex, 0xFF, 256);
+
u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0];
const s32 spritewidth[16] =
@@ -2355,6 +2376,15 @@ void GPU2D::DrawSprites(u32 line)
bool iswin = (((attrib[0] >> 10) & 0x3) == 2);
+ u32 sprline;
+ if ((attrib[0] & 0x1000) && !iswin)
+ {
+ // apply Y mosaic
+ sprline = OBJMosaicY;
+ }
+ else
+ sprline = line;
+
if (attrib[0] & 0x0100)
{
u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12);
@@ -2370,7 +2400,7 @@ void GPU2D::DrawSprites(u32 line)
}
u32 ypos = attrib[0] & 0xFF;
- ypos = (line - ypos) & 0xFF;
+ ypos = (sprline - ypos) & 0xFF;
if (ypos >= (u32)boundheight)
continue;
@@ -2380,7 +2410,7 @@ void GPU2D::DrawSprites(u32 line)
u32 rotparamgroup = (attrib[1] >> 9) & 0x1F;
- DoDrawSprite(Rotscale, attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos);
+ DoDrawSprite(Rotscale, sprnum, boundwidth, boundheight, width, height, xpos, ypos);
NumSprites++;
}
@@ -2394,7 +2424,7 @@ void GPU2D::DrawSprites(u32 line)
s32 height = spriteheight[sizeparam];
u32 ypos = attrib[0] & 0xFF;
- ypos = (line - ypos) & 0xFF;
+ ypos = (sprline - ypos) & 0xFF;
if (ypos >= (u32)height)
continue;
@@ -2402,11 +2432,7 @@ void GPU2D::DrawSprites(u32 line)
if (xpos <= -width)
continue;
- // yflip
- if (attrib[1] & 0x2000)
- ypos = height-1 - ypos;
-
- DoDrawSprite(Normal, attrib, width, xpos, ypos);
+ DoDrawSprite(Normal, sprnum, width, height, xpos, ypos);
NumSprites++;
}
@@ -2415,8 +2441,12 @@ void GPU2D::DrawSprites(u32 line)
}
template<bool window>
-void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos)
+void GPU2D::DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos)
{
+ u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0];
+ u16* attrib = &oam[num * 4];
+ u16* rotparams = &oam[(((attrib[1] >> 9) & 0x1F) * 16) + 3];
+
u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000;
u32 tilenum = attrib[2] & 0x03FF;
u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
@@ -2429,9 +2459,6 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
if ((attrib[0] & 0x1000) && !window)
{
// apply Y mosaic
- ypos = OBJMosaicY - (attrib[0] & 0xFF);
- if (ypos < 0) ypos = 0;
-
pixelattr |= 0x100000;
}
@@ -2509,12 +2536,15 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
if (color & 0x8000)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | pixelattr;
+ else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; }
}
else if (!window)
{
if (OBJLine[xpos] == 0)
+ {
OBJLine[xpos] = pixelattr & 0x180000;
+ OBJIndex[xpos] = num;
+ }
}
}
@@ -2563,12 +2593,15 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
if (color)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | pixelattr;
+ else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; }
}
else if (!window)
{
if (OBJLine[xpos] == 0)
+ {
OBJLine[xpos] = pixelattr & 0x180000;
+ OBJIndex[xpos] = num;
+ }
}
}
@@ -2604,12 +2637,15 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
if (color)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | pixelattr;
+ else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; }
}
else if (!window)
{
if (OBJLine[xpos] == 0)
+ {
OBJLine[xpos] = pixelattr & 0x180000;
+ OBJIndex[xpos] = num;
+ }
}
}
@@ -2623,8 +2659,11 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
}
template<bool window>
-void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
+void GPU2D::DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos)
{
+ u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0];
+ u16* attrib = &oam[num * 4];
+
u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000;
u32 tilenum = attrib[2] & 0x03FF;
u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
@@ -2634,12 +2673,13 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
if ((attrib[0] & 0x1000) && !window)
{
// apply Y mosaic
- ypos = OBJMosaicY - (attrib[0] & 0xFF);
- if (ypos < 0) ypos = 0;
-
pixelattr |= 0x100000;
}
+ // yflip
+ if (attrib[1] & 0x2000)
+ ypos = height-1 - ypos;
+
u32 xoff;
u32 xend = width;
if (xpos >= 0)
@@ -2719,12 +2759,15 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
if (color & 0x8000)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | pixelattr;
+ else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; }
}
else if (!window)
{
if (OBJLine[xpos] == 0)
+ {
OBJLine[xpos] = pixelattr & 0x180000;
+ OBJIndex[xpos] = num;
+ }
}
xoff++;
@@ -2786,12 +2829,15 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
if (color)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | pixelattr;
+ else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; }
}
else if (!window)
{
if (OBJLine[xpos] == 0)
+ {
OBJLine[xpos] = pixelattr & 0x180000;
+ OBJIndex[xpos] = num;
+ }
}
xoff++;
@@ -2847,12 +2893,15 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
if (color)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | pixelattr;
+ else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; }
}
else if (!window)
{
if (OBJLine[xpos] == 0)
+ {
OBJLine[xpos] = pixelattr & 0x180000;
+ OBJIndex[xpos] = num;
+ }
}
xoff++;