aboutsummaryrefslogtreecommitdiff
path: root/src/GPU2D.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/GPU2D.cpp')
-rw-r--r--src/GPU2D.cpp767
1 files changed, 397 insertions, 370 deletions
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index 288ee58..b510767 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -74,7 +74,9 @@
// mosaic:
// * mosaic grid starts at 0,0 regardless of the BG/sprite position
// * when changing it midframe: new X setting is applied immediately, new Y setting is applied only
-// after the end of the current mosaic row
+// after the end of the current mosaic row (when Y counter needs reloaded)
+// * for rotscaled sprites: coordinates that are inside the sprite are clamped to the sprite region
+// after being transformed for mosaic
// TODO: find which parts of DISPCNT are latched. for example, not possible to change video mode midframe.
@@ -82,6 +84,16 @@
GPU2D::GPU2D(u32 num)
{
Num = num;
+
+ // initialize mosaic table
+ for (int m = 0; m < 16; m++)
+ {
+ for (int x = 0; x < 256; x++)
+ {
+ int offset = x % (m+1);
+ MosaicTable[m][x] = offset;
+ }
+ }
}
GPU2D::~GPU2D()
@@ -118,6 +130,8 @@ void GPU2D::Reset()
BGMosaicYMax = 0;
OBJMosaicY = 0;
OBJMosaicYMax = 0;
+ CurBGXMosaicTable = MosaicTable[0];
+ CurOBJXMosaicTable = MosaicTable[0];
BlendCnt = 0;
EVA = 16;
@@ -207,6 +221,9 @@ void GPU2D::DoSavestate(Savestate* file)
BGExtPalStatus[2] = 0;
BGExtPalStatus[3] = 0;
OBJExtPalStatus = 0;
+
+ CurBGXMosaicTable = MosaicTable[BGMosaicSize[0]];
+ CurOBJXMosaicTable = MosaicTable[OBJMosaicSize[0]];
}
}
@@ -365,10 +382,12 @@ void GPU2D::Write8(u32 addr, u8 val)
case 0x04C:
BGMosaicSize[0] = val & 0xF;
BGMosaicSize[1] = val >> 4;
+ CurBGXMosaicTable = MosaicTable[BGMosaicSize[0]];
return;
case 0x04D:
OBJMosaicSize[0] = val & 0xF;
OBJMosaicSize[1] = val >> 4;
+ CurOBJXMosaicTable = MosaicTable[OBJMosaicSize[0]];
return;
case 0x050: BlendCnt = (BlendCnt & 0x3F00) | val; return;
@@ -497,8 +516,10 @@ void GPU2D::Write16(u32 addr, u16 val)
case 0x04C:
BGMosaicSize[0] = val & 0xF;
BGMosaicSize[1] = (val >> 4) & 0xF;
+ CurBGXMosaicTable = MosaicTable[BGMosaicSize[0]];
OBJMosaicSize[0] = (val >> 8) & 0xF;
OBJMosaicSize[1] = val >> 12;
+ CurOBJXMosaicTable = MosaicTable[OBJMosaicSize[0]];
return;
case 0x050: BlendCnt = val & 0x3FFF; return;
@@ -710,6 +731,24 @@ u32 GPU2D::ColorComposite(int i, u32 val1, u32 val2)
}
+void GPU2D::UpdateMosaicCounters(u32 line)
+{
+ // Y mosaic uses incrementing 4-bit counters
+ // the transformed Y position is updated every time the counter matches the MOSAIC register
+
+ if (OBJMosaicYCount == OBJMosaicSize[1])
+ {
+ OBJMosaicYCount = 0;
+ OBJMosaicY = line + 1;
+ }
+ else
+ {
+ OBJMosaicYCount++;
+ OBJMosaicYCount &= 0xF;
+ }
+}
+
+
void GPU2D::DrawScanline(u32 line)
{
int stride = Accelerated ? (256*3 + 1) : 256;
@@ -756,6 +795,7 @@ void GPU2D::DrawScanline(u32 line)
// always render regular graphics
DrawScanline_BGOBJ(line);
+ UpdateMosaicCounters(line);
switch (dispmode)
{
@@ -901,8 +941,10 @@ void GPU2D::VBlankEnd()
BGMosaicY = 0;
BGMosaicYMax = BGMosaicSize[1];
+ //OBJMosaicY = 0;
+ //OBJMosaicYMax = OBJMosaicSize[1];
OBJMosaicY = 0;
- OBJMosaicYMax = OBJMosaicSize[1];
+ OBJMosaicYCount = 0;
if (Accelerated)
{
@@ -1193,33 +1235,33 @@ u16* GPU2D::GetBGExtPal(u32 slot, u32 pal)
return dst;
}
-u16* GPU2D::GetOBJExtPal(u32 pal)
+u16* GPU2D::GetOBJExtPal()
{
- u16* dst = &OBJExtPalCache[pal << 8];
+ u16* dst = OBJExtPalCache;
- if (!(OBJExtPalStatus & (1<<pal)))
+ if (!OBJExtPalStatus)
{
if (Num)
{
if (GPU::VRAMMap_BOBJExtPal & (1<<8))
- memcpy(dst, &GPU::VRAM_I[(pal << 9)], 256*2);
+ memcpy(dst, &GPU::VRAM_I[0], 16*256*2);
else
- memset(dst, 0, 256*2);
+ memset(dst, 0, 16*256*2);
}
else
{
- memset(dst, 0, 256*2);
+ memset(dst, 0, 16*256*2);
if (GPU::VRAMMap_AOBJExtPal & (1<<5))
- for (int i = 0; i < 256; i+=2)
- *(u32*)&dst[i] |= *(u32*)&GPU::VRAM_F[(pal << 9) + (i << 1)];
+ for (int i = 0; i < 16*256; i+=2)
+ *(u32*)&dst[i] |= *(u32*)&GPU::VRAM_F[i << 1];
if (GPU::VRAMMap_AOBJExtPal & (1<<6))
- for (int i = 0; i < 256; i+=2)
- *(u32*)&dst[i] |= *(u32*)&GPU::VRAM_G[(pal << 9) + (i << 1)];
+ for (int i = 0; i < 16*256; i+=2)
+ *(u32*)&dst[i] |= *(u32*)&GPU::VRAM_G[i << 1];
}
- OBJExtPalStatus |= (1<<pal);
+ OBJExtPalStatus = 1;
}
return dst;
@@ -1282,6 +1324,12 @@ void GPU2D::CalculateWindowMask(u32 line)
}
+#define DoDrawBG(type, line, num) \
+ { if ((BGCnt[num] & 0x0040) && (BGMosaicSize[0] > 0)) DrawBG_##type<true>(line, num); else DrawBG_##type<false>(line, num); }
+
+#define DoDrawBG_Large(line) \
+ { if ((BGCnt[2] & 0x0040) && (BGMosaicSize[0] > 0)) DrawBG_Large<true>(line); else DrawBG_Large<false>(line); }
+
template<u32 bgmode>
void GPU2D::DrawScanlineBGMode(u32 line)
{
@@ -1292,11 +1340,11 @@ void GPU2D::DrawScanlineBGMode(u32 line)
if (DispCnt & 0x0800)
{
if (bgmode >= 3)
- DrawBG_Extended(line, 3);
+ DoDrawBG(Extended, line, 3)
else if (bgmode >= 1)
- DrawBG_Affine(line, 3);
+ DoDrawBG(Affine, line, 3)
else
- DrawBG_Text(line, 3);
+ DoDrawBG(Text, line, 3)
}
}
if ((BGCnt[2] & 0x3) == i)
@@ -1304,18 +1352,18 @@ void GPU2D::DrawScanlineBGMode(u32 line)
if (DispCnt & 0x0400)
{
if (bgmode == 5)
- DrawBG_Extended(line, 2);
+ DoDrawBG(Extended, line, 2)
else if (bgmode == 4 || bgmode == 2)
- DrawBG_Affine(line, 2);
+ DoDrawBG(Affine, line, 2)
else
- DrawBG_Text(line, 2);
+ DoDrawBG(Text, line, 2)
}
}
if ((BGCnt[1] & 0x3) == i)
{
if (DispCnt & 0x0200)
{
- DrawBG_Text(line, 1);
+ DoDrawBG(Text, line, 1)
}
}
if ((BGCnt[0] & 0x3) == i)
@@ -1325,11 +1373,11 @@ void GPU2D::DrawScanlineBGMode(u32 line)
if ((!Num) && (DispCnt & 0x8))
DrawBG_3D();
else
- DrawBG_Text(line, 0);
+ DoDrawBG(Text, line, 0)
}
}
if ((DispCnt & 0x1000) && NumSprites)
- InterleaveSprites(0x8000 | (i<<16));
+ InterleaveSprites(0x40000 | (i<<16));
}
}
@@ -1341,7 +1389,7 @@ void GPU2D::DrawScanlineBGMode6(u32 line)
{
if (DispCnt & 0x0400)
{
- DrawBG_Large(line);
+ DoDrawBG_Large(line)
}
}
if ((BGCnt[0] & 0x3) == i)
@@ -1353,7 +1401,7 @@ void GPU2D::DrawScanlineBGMode6(u32 line)
}
}
if ((DispCnt & 0x1000) && NumSprites)
- InterleaveSprites(0x8000 | (i<<16));
+ InterleaveSprites(0x40000 | (i<<16));
}
}
@@ -1367,7 +1415,7 @@ void GPU2D::DrawScanlineBGMode7(u32 line)
{
if (DispCnt & 0x0200)
{
- DrawBG_Text(line, 1);
+ DoDrawBG(Text, line, 1)
}
}
if ((BGCnt[0] & 0x3) == i)
@@ -1377,11 +1425,11 @@ void GPU2D::DrawScanlineBGMode7(u32 line)
if ((!Num) && (DispCnt & 0x8))
DrawBG_3D();
else
- DrawBG_Text(line, 0);
+ DoDrawBG(Text, line, 0)
}
}
if ((DispCnt & 0x1000) && NumSprites)
- InterleaveSprites(0x8000 | (i<<16));
+ InterleaveSprites(0x40000 | (i<<16));
}
}
@@ -1417,6 +1465,8 @@ void GPU2D::DrawScanline_BGOBJ(u32 line)
else
memset(WindowMask, 0xFF, 256);
+ ApplySpriteMosaicX();
+
switch (DispCnt & 0x7)
{
case 0: DrawScanlineBGMode<0>(line); break;
@@ -1542,13 +1592,13 @@ void GPU2D::DrawScanline_BGOBJ(u32 line)
else
BGMosaicY++;
- if (OBJMosaicY >= OBJMosaicYMax)
+ /*if (OBJMosaicY >= OBJMosaicYMax)
{
OBJMosaicY = 0;
OBJMosaicYMax = OBJMosaicSize[1];
}
else
- OBJMosaicY++;
+ OBJMosaicY++;*/
}
@@ -1557,6 +1607,7 @@ void GPU2D::DrawPixel_Normal(u32* dst, u16 color, u32 flag)
u8 r = (color & 0x001F) << 1;
u8 g = (color & 0x03E0) >> 4;
u8 b = (color & 0x7C00) >> 9;
+ //g |= ((color & 0x8000) >> 15);
*(dst+256) = *dst;
*dst = r | (g << 8) | (b << 16) | flag;
@@ -1618,10 +1669,10 @@ void GPU2D::DrawBG_3D()
}
}
+template<bool mosaic>
void GPU2D::DrawBG_Text(u32 line, u32 bgnum)
{
u16 bgcnt = BGCnt[bgnum];
- u32 xmos = 0, xmossize = 0;
u32 tilesetaddr, tilemapaddr;
u16* pal;
@@ -1632,9 +1683,8 @@ void GPU2D::DrawBG_Text(u32 line, u32 bgnum)
if (bgcnt & 0x0040)
{
- // mosaic
+ // vertical mosaic
yoff -= BGMosaicY;
- xmossize = BGMosaicSize[0];
}
u32 widexmask = (bgcnt & 0x4000) ? 0x100 : 0;
@@ -1671,15 +1721,15 @@ void GPU2D::DrawBG_Text(u32 line, u32 bgnum)
u16* curpal;
u32 pixelsaddr;
u8 color;
+ u32 lastxpos;
if (bgcnt & 0x0080)
{
// 256-color
// preload shit as needed
- if (xoff & 0x7)
+ if ((xoff & 0x7) || mosaic)
{
- // load a new tile
curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + ((xoff & 0xF8) >> 2) + ((xoff & widexmask) << 3));
if (extpal) curpal = GetBGExtPal(extpalslot, curtile>>12);
@@ -1689,31 +1739,34 @@ void GPU2D::DrawBG_Text(u32 line, u32 bgnum)
+ (((curtile & 0x0800) ? (7-(yoff&0x7)) : (yoff&0x7)) << 3);
}
+ if (mosaic) lastxpos = xoff;
+
for (int i = 0; i < 256; i++)
{
- if (!(xoff & 0x7))
+ u32 xpos;
+ if (mosaic) xpos = xoff - CurBGXMosaicTable[i];
+ else xpos = xoff;
+
+ if ((!mosaic && (!(xpos & 0x7))) ||
+ (mosaic && ((xpos >> 3) != (lastxpos >> 3))))
{
// load a new tile
- curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + ((xoff & 0xF8) >> 2) + ((xoff & widexmask) << 3));
+ curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + ((xpos & 0xF8) >> 2) + ((xpos & widexmask) << 3));
if (extpal) curpal = GetBGExtPal(extpalslot, curtile>>12);
else curpal = pal;
pixelsaddr = tilesetaddr + ((curtile & 0x03FF) << 6)
+ (((curtile & 0x0800) ? (7-(yoff&0x7)) : (yoff&0x7)) << 3);
+
+ if (mosaic) lastxpos = xpos;
}
// draw pixel
if (WindowMask[i] & (1<<bgnum))
{
- if (xmos == 0)
- {
- u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
- color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff);
- xmos = xmossize;
- }
- else
- xmos--;
+ u32 tilexoff = (curtile & 0x0400) ? (7-(xpos&0x7)) : (xpos&0x7);
+ color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff);
if (color)
DrawPixel(&BGOBJLine[i], curpal[color], 0x01000000<<bgnum);
@@ -1727,45 +1780,46 @@ void GPU2D::DrawBG_Text(u32 line, u32 bgnum)
// 16-color
// preload shit as needed
- if (xoff & 0x7)
+ if ((xoff & 0x7) || mosaic)
{
- // load a new tile
curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + ((xoff & 0xF8) >> 2) + ((xoff & widexmask) << 3));
curpal = pal + ((curtile & 0xF000) >> 8);
pixelsaddr = tilesetaddr + ((curtile & 0x03FF) << 5)
+ (((curtile & 0x0800) ? (7-(yoff&0x7)) : (yoff&0x7)) << 2);
}
+ if (mosaic) lastxpos = xoff;
+
for (int i = 0; i < 256; i++)
{
- if (!(xoff & 0x7))
+ u32 xpos;
+ if (mosaic) xpos = xoff - CurBGXMosaicTable[i];
+ else xpos = xoff;
+
+ if ((!mosaic && (!(xpos & 0x7))) ||
+ (mosaic && ((xpos >> 3) != (lastxpos >> 3))))
{
// load a new tile
- curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + ((xoff & 0xF8) >> 2) + ((xoff & widexmask) << 3));
+ curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + ((xpos & 0xF8) >> 2) + ((xpos & widexmask) << 3));
curpal = pal + ((curtile & 0xF000) >> 8);
pixelsaddr = tilesetaddr + ((curtile & 0x03FF) << 5)
+ (((curtile & 0x0800) ? (7-(yoff&0x7)) : (yoff&0x7)) << 2);
+
+ if (mosaic) lastxpos = xpos;
}
// draw pixel
- // TODO: optimize VRAM access
if (WindowMask[i] & (1<<bgnum))
{
- if (xmos == 0)
+ u32 tilexoff = (curtile & 0x0400) ? (7-(xpos&0x7)) : (xpos&0x7);
+ if (tilexoff & 0x1)
{
- u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
- if (tilexoff & 0x1)
- {
- color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) >> 4;
- }
- else
- {
- color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) & 0x0F;
- }
- xmos = xmossize;
+ color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) >> 4;
}
else
- xmos--;
+ {
+ color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) & 0x0F;
+ }
if (color)
DrawPixel(&BGOBJLine[i], curpal[color], 0x01000000<<bgnum);
@@ -1776,10 +1830,10 @@ void GPU2D::DrawBG_Text(u32 line, u32 bgnum)
}
}
+template<bool mosaic>
void GPU2D::DrawBG_Affine(u32 line, u32 bgnum)
{
u16 bgcnt = BGCnt[bgnum];
- u32 xmos = 0, xmossize = 0;
u32 tilesetaddr, tilemapaddr;
u16* pal;
@@ -1808,10 +1862,9 @@ void GPU2D::DrawBG_Affine(u32 line, u32 bgnum)
if (bgcnt & 0x0040)
{
- // mosaic
+ // vertical mosaic
rotX -= (BGMosaicY * rotB);
rotY -= (BGMosaicY * rotD);
- xmossize = BGMosaicSize[0];
}
if (Num)
@@ -1838,28 +1891,31 @@ void GPU2D::DrawBG_Affine(u32 line, u32 bgnum)
{
if (WindowMask[i] & (1<<bgnum))
{
- if (xmos > 0)
+ s32 finalX, finalY;
+ if (mosaic)
{
- if (color)
- DrawPixel(&BGOBJLine[i], pal[color], 0x01000000<<bgnum);
-
- xmos--;
+ int im = CurBGXMosaicTable[i];
+ finalX = rotX - (im * rotA);
+ finalY = rotY - (im * rotC);
}
else
- if ((!((rotX|rotY) & overflowmask)))
{
- curtile = GPU::ReadVRAM_BG<u8>(tilemapaddr + ((((rotY & coordmask) >> 11) << yshift) + ((rotX & coordmask) >> 11)));
+ finalX = rotX;
+ finalY = rotY;
+ }
+
+ if ((!((finalX|finalY) & overflowmask)))
+ {
+ curtile = GPU::ReadVRAM_BG<u8>(tilemapaddr + ((((finalY & coordmask) >> 11) << yshift) + ((finalX & coordmask) >> 11)));
// draw pixel
- u32 tilexoff = (rotX >> 8) & 0x7;
- u32 tileyoff = (rotY >> 8) & 0x7;
+ u32 tilexoff = (finalX >> 8) & 0x7;
+ u32 tileyoff = (finalY >> 8) & 0x7;
color = GPU::ReadVRAM_BG<u8>(tilesetaddr + (curtile << 6) + (tileyoff << 3) + tilexoff);
if (color)
DrawPixel(&BGOBJLine[i], pal[color], 0x01000000<<bgnum);
-
- xmos = xmossize;
}
}
@@ -1871,10 +1927,10 @@ void GPU2D::DrawBG_Affine(u32 line, u32 bgnum)
BGYRefInternal[bgnum-2] += rotD;
}
+template<bool mosaic>
void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
{
u16 bgcnt = BGCnt[bgnum];
- u32 xmos = 0, xmossize = 0;
u32 tilesetaddr, tilemapaddr;
u16* pal;
@@ -1892,10 +1948,9 @@ void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
if (bgcnt & 0x0040)
{
- // mosaic
+ // vertical mosaic
rotX -= (BGMosaicY * rotB);
rotY -= (BGMosaicY * rotD);
- xmossize = BGMosaicSize[0];
}
if (bgcnt & 0x0080)
@@ -1937,22 +1992,25 @@ void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
{
if (WindowMask[i] & (1<<bgnum))
{
- if (xmos > 0)
+ s32 finalX, finalY;
+ if (mosaic)
{
- if (color & 0x8000)
- DrawPixel(&BGOBJLine[i], color, 0x01000000<<bgnum);
-
- xmos--;
+ int im = CurBGXMosaicTable[i];
+ finalX = rotX - (im * rotA);
+ finalY = rotY - (im * rotC);
}
else
- if (!(rotX & ofxmask) && !(rotY & ofymask))
{
- color = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((rotY & ymask) >> 8) << yshift) + ((rotX & xmask) >> 8)) << 1));
+ finalX = rotX;
+ finalY = rotY;
+ }
+
+ if (!(finalX & ofxmask) && !(finalY & ofymask))
+ {
+ color = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((finalY & ymask) >> 8) << yshift) + ((finalX & xmask) >> 8)) << 1));
if (color & 0x8000)
DrawPixel(&BGOBJLine[i], color, 0x01000000<<bgnum);
-
- xmos = xmossize;
}
}
@@ -1973,22 +2031,25 @@ void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
{
if (WindowMask[i] & (1<<bgnum))
{
- if (xmos > 0)
+ s32 finalX, finalY;
+ if (mosaic)
{
- if (color)
- DrawPixel(&BGOBJLine[i], pal[color], 0x01000000<<bgnum);
-
- xmos--;
+ int im = CurBGXMosaicTable[i];
+ finalX = rotX - (im * rotA);
+ finalY = rotY - (im * rotC);
}
else
- if (!(rotX & ofxmask) && !(rotY & ofymask))
{
- color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((rotY & ymask) >> 8) << yshift) + ((rotX & xmask) >> 8));
+ finalX = rotX;
+ finalY = rotY;
+ }
+
+ if (!(finalX & ofxmask) && !(finalY & ofymask))
+ {
+ color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((finalY & ymask) >> 8) << yshift) + ((finalX & xmask) >> 8));
if (color)
DrawPixel(&BGOBJLine[i], pal[color], 0x01000000<<bgnum);
-
- xmos = xmossize;
}
}
@@ -2040,24 +2101,29 @@ void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
{
if (WindowMask[i] & (1<<bgnum))
{
- if (xmos > 0)
+ s32 finalX, finalY;
+ if (mosaic)
{
- if (color)
- DrawPixel(&BGOBJLine[i], curpal[color], 0x01000000<<bgnum);
-
- xmos--;
+ int im = CurBGXMosaicTable[i];
+ finalX = rotX - (im * rotA);
+ finalY = rotY - (im * rotC);
}
else
- if ((!((rotX|rotY) & overflowmask)))
{
- curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((rotY & coordmask) >> 11) << yshift) + ((rotX & coordmask) >> 11)) << 1));
+ finalX = rotX;
+ finalY = rotY;
+ }
+
+ if ((!((finalX|finalY) & overflowmask)))
+ {
+ curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((finalY & coordmask) >> 11) << yshift) + ((finalX & coordmask) >> 11)) << 1));
if (extpal) curpal = GetBGExtPal(bgnum, curtile>>12);
else curpal = pal;
// draw pixel
- u32 tilexoff = (rotX >> 8) & 0x7;
- u32 tileyoff = (rotY >> 8) & 0x7;
+ u32 tilexoff = (finalX >> 8) & 0x7;
+ u32 tileyoff = (finalY >> 8) & 0x7;
if (curtile & 0x0400) tilexoff = 7-tilexoff;
if (curtile & 0x0800) tileyoff = 7-tileyoff;
@@ -2066,8 +2132,6 @@ void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
if (color)
DrawPixel(&BGOBJLine[i], curpal[color], 0x01000000<<bgnum);
-
- xmos = xmossize;
}
}
@@ -2080,10 +2144,10 @@ void GPU2D::DrawBG_Extended(u32 line, u32 bgnum)
BGYRefInternal[bgnum-2] += rotD;
}
+template<bool mosaic>
void GPU2D::DrawBG_Large(u32 line) // BG is always BG2
{
u16 bgcnt = BGCnt[2];
- u32 xmos = 0, xmossize = 0;
u32 tilesetaddr, tilemapaddr;
u16* pal;
@@ -2125,10 +2189,9 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2
if (bgcnt & 0x0040)
{
- // mosaic
+ // vertical mosaic
rotX -= (BGMosaicY * rotB);
rotY -= (BGMosaicY * rotD);
- xmossize = BGMosaicSize[0];
}
if (Num) tilemapaddr = 0x06200000;
@@ -2145,17 +2208,22 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2
{
if (WindowMask[i] & (1<<2))
{
- if (xmos > 0)
+ s32 finalX, finalY;
+ if (mosaic)
{
- if (color)
- DrawPixel(&BGOBJLine[i], pal[color], 0x01000000<<2);
-
- xmos--;
+ int im = CurBGXMosaicTable[i];
+ finalX = rotX - (im * rotA);
+ finalY = rotY - (im * rotC);
}
else
- if (!(rotX & ofxmask) && !(rotY & ofymask))
{
- color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((rotY & ymask) >> 8) << yshift) + ((rotX & xmask) >> 8));
+ finalX = rotX;
+ finalY = rotY;
+ }
+
+ if (!(finalX & ofxmask) && !(finalY & ofymask))
+ {
+ color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((finalY & ymask) >> 8) << yshift) + ((finalX & xmask) >> 8));
if (color)
DrawPixel(&BGOBJLine[i], pal[color], 0x01000000<<2);
@@ -2170,17 +2238,88 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2
BGYRefInternal[0] += rotD;
}
+void GPU2D::ApplySpriteMosaicX()
+{
+ // apply X mosaic if needed
+ // X mosaic for sprites is applied after all sprites are rendered
+
+ if (OBJMosaicSize[0] == 0) return;
+
+ u32 lastcolor = OBJLine[0];
+
+ for (u32 i = 1; i < 256; i++)
+ {
+ if (!(OBJLine[i] & 0x100000))
+ {
+ // not a mosaic'd sprite pixel
+ continue;
+ }
+
+ if ((!(OBJLine[i-1] & 0x100000)) || (CurOBJXMosaicTable[i] == 0))
+ lastcolor = OBJLine[i];
+ else
+ OBJLine[i] = lastcolor;
+ }
+}
+
void GPU2D::InterleaveSprites(u32 prio)
{
- for (u32 i = 0; i < 256; i++)
+ u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+
+ if (DispCnt & 0x80000000)
+ {
+ u16* extpal = GetOBJExtPal();
+
+ for (u32 i = 0; i < 256; i++)
+ {
+ if ((OBJLine[i] & 0x70000) != prio) continue;
+ if (!(WindowMask[i] & 0x10)) continue;
+
+ u16 color;
+ u32 pixel = OBJLine[i];
+
+ if (pixel & 0x8000)
+ color = pixel & 0x7FFF;
+ else if (pixel & 0x1000)
+ color = pal[pixel & 0xFF];
+ else
+ color = extpal[pixel & 0xFFF];
+
+ DrawPixel(&BGOBJLine[i], color, pixel & 0xFF000000);
+ }
+ }
+ else
{
- if (((OBJLine[i] & 0xF8000) == prio) && (WindowMask[i] & 0x10))
+ // optimized no-extpal version
+
+ for (u32 i = 0; i < 256; i++)
{
- DrawPixel(&BGOBJLine[i], OBJLine[i] & 0x7FFF, OBJLine[i] & 0xFF000000);
+ if ((OBJLine[i] & 0x70000) != prio) continue;
+ if (!(WindowMask[i] & 0x10)) continue;
+
+ u16 color;
+ u32 pixel = OBJLine[i];
+
+ if (pixel & 0x8000)
+ color = pixel & 0x7FFF;
+ else
+ color = pal[pixel & 0xFF];
+
+ DrawPixel(&BGOBJLine[i], color, pixel & 0xFF000000);
}
}
}
+#define DoDrawSprite(type, ...) \
+ if (iswin) \
+ { \
+ DrawSprite_##type<true>(__VA_ARGS__); \
+ } \
+ else \
+ { \
+ DrawSprite_##type<false>(__VA_ARGS__); \
+ }
+
void GPU2D::DrawSprites(u32 line)
{
NumSprites = 0;
@@ -2241,10 +2380,7 @@ void GPU2D::DrawSprites(u32 line)
u32 rotparamgroup = (attrib[1] >> 9) & 0x1F;
- if (iswin)
- DrawSprite_Rotscale<true>(attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos);
- else
- DrawSprite_Rotscale<false>(attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos);
+ DoDrawSprite(Rotscale, attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos);
NumSprites++;
}
@@ -2270,10 +2406,7 @@ void GPU2D::DrawSprites(u32 line)
if (attrib[1] & 0x2000)
ypos = height-1 - ypos;
- if (iswin)
- DrawSprite_Normal<true>(attrib, width, xpos, ypos);
- else
- DrawSprite_Normal<false>(attrib, width, xpos, ypos);
+ DoDrawSprite(Normal, attrib, width, xpos, ypos);
NumSprites++;
}
@@ -2284,25 +2417,22 @@ 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)
{
- u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
+ u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000;
u32 tilenum = attrib[2] & 0x03FF;
u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
- u32 xmos = 0, xmossize = 0;
u32 ytilefactor;
s32 centerX = boundwidth >> 1;
s32 centerY = boundheight >> 1;
- if (attrib[0] & 0x1000)
+ if ((attrib[0] & 0x1000) && !window)
{
- // mosaic
- ypos -= OBJMosaicY;
+ // apply Y mosaic
+ ypos = OBJMosaicY - (attrib[0] & 0xFF);
if (ypos < 0) ypos = 0;
- xmossize = OBJMosaicSize[0];
- if (xpos > 0)
- xmos = (xmossize+1) - (xpos % (xmossize+1));
+ pixelattr |= 0x100000;
}
u32 xoff;
@@ -2337,7 +2467,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
if (!alpha) return;
alpha++;
- prio |= (0xC0000000 | (alpha << 24));
+ pixelattr |= (0xC0000000 | (alpha << 24));
if (DispCnt & 0x40)
{
@@ -2369,31 +2499,23 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
}
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
- if (xmos && !(attrib[0]&0x0200))
- color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
for (; xoff < boundwidth;)
{
if ((u32)rotX < width && (u32)rotY < height)
{
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
- xmos = xmossize;
- }
- else
- xmos--;
+ color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
if (color & 0x8000)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | prio;
+ else OBJLine[xpos] = color | pixelattr;
+ }
+ else if (!window)
+ {
+ if (OBJLine[xpos] == 0)
+ OBJLine[xpos] = pixelattr & 0x180000;
}
- }
- else
- {
- if (xmos == 0) xmos = xmossize;
- else xmos--;
}
rotX += rotA;
@@ -2414,8 +2536,8 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
ytilefactor = 0x20;
}
- if (spritemode == 1) prio |= 0x80000000;
- else prio |= 0x10000000;
+ if (spritemode == 1) pixelattr |= 0x80000000;
+ else pixelattr |= 0x10000000;
if (attrib[0] & 0x2000)
{
@@ -2424,40 +2546,30 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
ytilefactor <<= 5;
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
- u32 extpal = (DispCnt & 0x80000000);
-
- u16* pal;
if (!window)
{
- if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
- else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ if (!(DispCnt & 0x80000000))
+ pixelattr |= 0x1000;
+ else
+ pixelattr |= ((attrib[2] & 0xF000) >> 4);
}
- if (xmos && !(attrib[0]&0x0200))
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
-
for (; xoff < boundwidth;)
{
if ((u32)rotX < width && (u32)rotY < height)
{
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
- xmos = xmossize;
- }
- else
- xmos--;
+ color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
if (color)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = pal[color] | prio;
+ else OBJLine[xpos] = color | pixelattr;
+ }
+ else if (!window)
+ {
+ if (OBJLine[xpos] == 0)
+ OBJLine[xpos] = pixelattr & 0x180000;
}
- }
- else
- {
- if (xmos == 0) xmos = xmossize;
- else xmos--;
}
rotX += rotA;
@@ -2473,49 +2585,32 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
ytilefactor <<= 5;
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
- u16* pal;
if (!window)
{
- pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
- pal += (attrib[2] & 0xF000) >> 8;
- }
-
- if (xmos && !(attrib[0]&0x0200))
- {
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
- if (rotX & 0x100)
- color >>= 4;
- else
- color &= 0x0F;
+ pixelattr |= 0x1000;
+ pixelattr |= ((attrib[2] & 0xF000) >> 8);
}
for (; xoff < boundwidth;)
{
if ((u32)rotX < width && (u32)rotY < height)
{
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
- if (rotX & 0x100)
- color >>= 4;
- else
- color &= 0x0F;
-
- xmos = xmossize;
- }
+ color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
+ if (rotX & 0x100)
+ color >>= 4;
else
- xmos--;
+ color &= 0x0F;
if (color)
{
if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = pal[color] | prio;
+ else OBJLine[xpos] = color | pixelattr;
+ }
+ else if (!window)
+ {
+ if (OBJLine[xpos] == 0)
+ OBJLine[xpos] = pixelattr & 0x180000;
}
- }
- else
- {
- if (xmos == 0) xmos = xmossize;
- else xmos--;
}
rotX += rotA;
@@ -2530,22 +2625,19 @@ 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)
{
- u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
+ u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000;
u32 tilenum = attrib[2] & 0x03FF;
u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
- u32 xmos = 0, xmossize = 0;
u32 wmask = width - 8; // really ((width - 1) & ~0x7)
- if (attrib[0] & 0x1000)
+ if ((attrib[0] & 0x1000) && !window)
{
- // mosaic
- ypos -= OBJMosaicY;
+ // apply Y mosaic
+ ypos = OBJMosaicY - (attrib[0] & 0xFF);
if (ypos < 0) ypos = 0;
- xmossize = OBJMosaicSize[0];
- if (xpos > 0)
- xmos = (xmossize+1) - (xpos % (xmossize+1));
+ pixelattr |= 0x100000;
}
u32 xoff;
@@ -2572,7 +2664,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
if (!alpha) return;
alpha++;
- prio |= (0xC0000000 | (alpha << 24));
+ pixelattr |= (0xC0000000 | (alpha << 24));
if (DispCnt & 0x40)
{
@@ -2604,60 +2696,39 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
}
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
+ s32 pixelstride;
- if (attrib[1] & 0x1000)
+ if (attrib[1] & 0x1000) // xflip
{
- pixelsaddr += ((width-1 - xoff) << 1);
- if (xmos) color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr);
-
- for (; xoff < xend;)
- {
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr);
- xmos = xmossize;
- }
- else
- xmos--;
-
- pixelsaddr -= 2;
-
- if (color & 0x8000)
- {
- if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | prio;
- }
-
- xoff++;
- xpos++;
- }
+ pixelsaddr += (width-1 << 1);
+ pixelsaddr -= (xoff << 1);
+ pixelstride = -2;
}
else
{
pixelsaddr += (xoff << 1);
- if (xmos) color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr);
-
- for (; xoff < xend;)
- {
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr);
- xmos = xmossize;
- }
- else
- xmos--;
+ pixelstride = 2;
+ }
- pixelsaddr += 2;
+ for (; xoff < xend;)
+ {
+ color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr);
- if (color & 0x8000)
- {
- if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = color | prio;
- }
+ pixelsaddr += pixelstride;
- xoff++;
- xpos++;
+ if (color & 0x8000)
+ {
+ if (window) OBJWindow[xpos] = 1;
+ else OBJLine[xpos] = color | pixelattr;
+ }
+ else if (!window)
+ {
+ if (OBJLine[xpos] == 0)
+ OBJLine[xpos] = pixelattr & 0x180000;
}
+
+ xoff++;
+ xpos++;
}
}
else
@@ -2672,8 +2743,8 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
tilenum += ((ypos >> 3) * 0x20);
}
- if (spritemode == 1) prio |= 0x80000000;
- else prio |= 0x10000000;
+ if (spritemode == 1) pixelattr |= 0x80000000;
+ else pixelattr |= 0x10000000;
if (attrib[0] & 0x2000)
{
@@ -2681,73 +2752,51 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
tilenum <<= 5;
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
pixelsaddr += ((ypos & 0x7) << 3);
+ s32 pixelstride;
- u32 extpal = (DispCnt & 0x80000000);
-
- u16* pal;
if (!window)
{
- if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
- else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ if (!(DispCnt & 0x80000000))
+ pixelattr |= 0x1000;
+ else
+ pixelattr |= ((attrib[2] & 0xF000) >> 4);
}
- if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works
+ if (attrib[1] & 0x1000) // xflip
{
- pixelsaddr += (((width-1 - xoff) & wmask) << 3);
- pixelsaddr += ((width-1 - xoff) & 0x7);
- if (xmos) color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr);
-
- for (; xoff < xend;)
- {
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr);
- xmos = xmossize;
- }
- else
- xmos--;
-
- pixelsaddr--;
-
- if (color)
- {
- if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = pal[color] | prio;
- }
-
- xoff++;
- xpos++;
- if (!(xoff & 0x7)) pixelsaddr -= 56;
- }
+ pixelsaddr += (((width-1) & wmask) << 3);
+ pixelsaddr += ((width-1) & 0x7);
+ pixelsaddr -= ((xoff & wmask) << 3);
+ pixelsaddr -= (xoff & 0x7);
+ pixelstride = -1;
}
else
{
pixelsaddr += ((xoff & wmask) << 3);
pixelsaddr += (xoff & 0x7);
- if (xmos) color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr);
-
- for (; xoff < xend;)
- {
- if (xmos == 0)
- {
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr);
- xmos = xmossize;
- }
- else
- xmos--;
+ pixelstride = 1;
+ }
- pixelsaddr++;
+ for (; xoff < xend;)
+ {
+ color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr);
- if (color)
- {
- if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = pal[color] | prio;
- }
+ pixelsaddr += pixelstride;
- xoff++;
- xpos++;
- if (!(xoff & 0x7)) pixelsaddr += 56;
+ if (color)
+ {
+ if (window) OBJWindow[xpos] = 1;
+ else OBJLine[xpos] = color | pixelattr;
+ }
+ else if (!window)
+ {
+ if (OBJLine[xpos] == 0)
+ OBJLine[xpos] = pixelattr & 0x180000;
}
+
+ xoff++;
+ xpos++;
+ if (!(xoff & 0x7)) pixelsaddr += (56 * pixelstride);
}
}
else
@@ -2756,81 +2805,59 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
tilenum <<= 5;
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
pixelsaddr += ((ypos & 0x7) << 2);
+ s32 pixelstride;
- u16* pal;
if (!window)
{
- pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
- pal += (attrib[2] & 0xF000) >> 8;
+ pixelattr |= 0x1000;
+ pixelattr |= ((attrib[2] & 0xF000) >> 8);
}
- if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works
- {
- pixelsaddr += (((width-1 - xoff) & wmask) << 2);
- pixelsaddr += (((width-1 - xoff) & 0x7) >> 1);
- if (xmos)
- {
- if (xoff & 0x1) color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) & 0x0F;
- else color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) >> 4;
- }
-
- for (; xoff < xend;)
- {
- if (xmos == 0)
- {
- if (xoff & 0x1) color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) & 0x0F;
- else color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) >> 4;
- xmos = xmossize;
- }
- else
- xmos--;
-
- if (xoff & 0x1) pixelsaddr--;
+ // TODO: optimize VRAM access!!
+ // TODO: do xflip better? the 'two pixels per byte' thing makes it a bit shitty
- if (color)
- {
- if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = pal[color] | prio;
- }
-
- xoff++;
- xpos++;
- if (!(xoff & 0x7)) pixelsaddr -= 28;
- }
+ if (attrib[1] & 0x1000) // xflip
+ {
+ pixelsaddr += (((width-1) & wmask) << 2);
+ pixelsaddr += (((width-1) & 0x7) >> 1);
+ pixelsaddr -= ((xoff & wmask) << 2);
+ pixelsaddr -= ((xoff & 0x7) >> 1);
+ pixelstride = -1;
}
else
{
pixelsaddr += ((xoff & wmask) << 2);
pixelsaddr += ((xoff & 0x7) >> 1);
- if (xmos)
+ pixelstride = 1;
+ }
+
+ for (; xoff < xend;)
+ {
+ if (attrib[1] & 0x1000)
{
- if (xoff & 0x1) color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) >> 4;
- else color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) & 0x0F;
+ if (xoff & 0x1) { color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) & 0x0F; pixelsaddr--; }
+ else color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) >> 4;
}
-
- for (; xoff < xend;)
+ else
{
- if (xmos == 0)
- {
- if (xoff & 0x1) color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) >> 4;
- else color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) & 0x0F;
- xmos = xmossize;
- }
- else
- xmos--;
-
- if (xoff & 0x1) pixelsaddr++;
-
- if (color)
- {
- if (window) OBJWindow[xpos] = 1;
- else OBJLine[xpos] = pal[color] | prio;
- }
+ if (xoff & 0x1) { color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) >> 4; pixelsaddr++; }
+ else color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr) & 0x0F;
+ }
- xoff++;
- xpos++;
- if (!(xoff & 0x7)) pixelsaddr += 28;
+ if (color)
+ {
+ if (window) OBJWindow[xpos] = 1;
+ else OBJLine[xpos] = color | pixelattr;
+ }
+ else if (!window)
+ {
+ if (OBJLine[xpos] == 0)
+ OBJLine[xpos] = pixelattr & 0x180000;
}
+
+ xoff++;
+ xpos++;
+ if (!(xoff & 0x7)) pixelsaddr += ((attrib[1] & 0x1000) ? -28 : 28);
}
}
}