aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-04-09 03:35:32 +0200
committerStapleButter <thetotalworm@gmail.com>2017-04-09 03:35:32 +0200
commitbc70f0037247bc4ba68c8c330982c578b2e8f431 (patch)
tree4d9bb07f11afa40804ca1b11f86a847dda52678f /src
parent3f3b2977d7decf8f691f5f999ae9b08a6d214bc9 (diff)
windows!
Diffstat (limited to 'src')
-rw-r--r--src/GPU.cpp3
-rw-r--r--src/GPU2D.cpp367
-rw-r--r--src/GPU2D.h17
-rw-r--r--src/SPU.cpp6
4 files changed, 330 insertions, 63 deletions
diff --git a/src/GPU.cpp b/src/GPU.cpp
index d486e0c..680f08c 100644
--- a/src/GPU.cpp
+++ b/src/GPU.cpp
@@ -649,6 +649,9 @@ void StartScanline(u32 line)
else
DispStat[1] &= ~(1<<2);
+ GPU2D_A->CheckWindows(line);
+ GPU2D_B->CheckWindows(line);
+
if (line >= 2 && line < 194)
NDS::CheckDMAs(0, 0x03);
else if (line == 194)
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index ff9072d..224bfa9 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -94,6 +94,10 @@ void GPU2D::Reset()
memset(BGRotC, 0, 2*2);
memset(BGRotD, 0, 2*2);
+ memset(Win0Coords, 0, 4);
+ memset(Win1Coords, 0, 4);
+ memset(WinCnt, 0, 4);
+
BlendCnt = 0;
EVA = 16;
EVB = 0;
@@ -120,7 +124,15 @@ void GPU2D::SetFramebuffer(u32* buf)
u8 GPU2D::Read8(u32 addr)
{
- printf("!! GPU2D READ8 %08X\n", addr);
+ switch (addr & 0x00000FFF)
+ {
+ case 0x048: return WinCnt[0];
+ case 0x049: return WinCnt[1];
+ case 0x04A: return WinCnt[2];
+ case 0x04B: return WinCnt[3];
+ }
+
+ printf("unknown GPU read8 %08X\n", addr);
return 0;
}
@@ -136,6 +148,9 @@ u16 GPU2D::Read16(u32 addr)
case 0x00C: return BGCnt[2];
case 0x00E: return BGCnt[3];
+ case 0x048: return WinCnt[0] | (WinCnt[1] << 8);
+ case 0x04A: return WinCnt[2] | (WinCnt[3] << 8);
+
case 0x050: return BlendCnt;
case 0x064: return CaptureCnt & 0xFFFF;
@@ -160,7 +175,25 @@ u32 GPU2D::Read32(u32 addr)
void GPU2D::Write8(u32 addr, u8 val)
{
- printf("!! GPU2D WRITE8 %08X %02X\n", addr, val);
+ switch (addr & 0x00000FFF)
+ {
+ case 0x040: Win0Coords[1] = val; return;
+ case 0x041: Win0Coords[0] = val; return;
+ case 0x042: Win1Coords[1] = val; return;
+ case 0x043: Win1Coords[0] = val; return;
+
+ case 0x044: Win0Coords[3] = val; return;
+ case 0x045: Win0Coords[2] = val; return;
+ case 0x046: Win1Coords[3] = val; return;
+ case 0x047: Win1Coords[2] = val; return;
+
+ case 0x048: WinCnt[0] = val; return;
+ case 0x049: WinCnt[1] = val; return;
+ case 0x04A: WinCnt[2] = val; return;
+ case 0x04B: WinCnt[3] = val; return;
+ }
+
+ printf("unknown GPU write8 %08X %02X\n", addr, val);
}
void GPU2D::Write16(u32 addr, u16 val)
@@ -234,6 +267,33 @@ void GPU2D::Write16(u32 addr, u16 val)
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
return;
+ case 0x040:
+ Win0Coords[1] = val & 0xFF;
+ Win0Coords[0] = val >> 8;
+ return;
+ case 0x042:
+ Win1Coords[1] = val & 0xFF;
+ Win1Coords[0] = val >> 8;
+ return;
+
+ case 0x044:
+ Win0Coords[3] = val & 0xFF;
+ Win0Coords[2] = val >> 8;
+ return;
+ case 0x046:
+ Win1Coords[3] = val & 0xFF;
+ Win1Coords[2] = val >> 8;
+ return;
+
+ case 0x048:
+ WinCnt[0] = val & 0xFF;
+ WinCnt[1] = val >> 8;
+ return;
+ case 0x04A:
+ WinCnt[2] = val & 0xFF;
+ WinCnt[3] = val >> 8;
+ return;
+
case 0x050: BlendCnt = val; return;
case 0x052:
EVA = val & 0x1F;
@@ -683,6 +743,59 @@ u16* GPU2D::GetOBJExtPal(u32 pal)
}
+void GPU2D::CheckWindows(u32 line)
+{
+ line &= 0xFF;
+ if (line == Win0Coords[2]) Win0Active = true;
+ else if (line == Win0Coords[3]) Win0Active = false;
+ if (line == Win1Coords[2]) Win1Active = true;
+ else if (line == Win1Coords[3]) Win1Active = false;
+}
+
+void GPU2D::CalculateWindowMask(u32 line, u8* mask)
+{
+ for (u32 i = 0; i < 256; i++)
+ mask[i] = WinCnt[2]; // window outside
+
+ if ((DispCnt & (1<<15)) && (DispCnt & (1<<12)))
+ {
+ // OBJ window
+ u8 objwin[256];
+ memset(objwin, 0, 256);
+ DrawSpritesWindow(line, objwin);
+
+ for (u32 i = 0; i < 256; i++)
+ {
+ if (objwin[i]) mask[i] = WinCnt[3];
+ }
+ }
+
+ if ((DispCnt & (1<<14)) && Win1Active)
+ {
+ // window 1
+ u32 x1 = Win1Coords[0];
+ u32 x2 = Win1Coords[1];
+ if (x2 == 0 && x1 > 0) x2 = 256;
+ if (x1 > x2) x2 = 255; // checkme
+
+ for (u32 i = x1; i < x2; i++)
+ mask[i] = WinCnt[1];
+ }
+
+ if ((DispCnt & (1<<13)) && Win0Active)
+ {
+ // window 0
+ u32 x1 = Win0Coords[0];
+ u32 x2 = Win0Coords[1];
+ if (x2 == 0 && x1 > 0) x2 = 256;
+ if (x1 > x2) x2 = 255; // checkme
+
+ for (u32 i = x1; i < x2; i++)
+ mask[i] = WinCnt[0];
+ }
+}
+
+
template<u32 bgmode>
void GPU2D::DrawScanlineBGMode(u32 line, u32* spritebuf, u32* dst)
{
@@ -736,7 +849,8 @@ void GPU2D::DrawScanlineBGMode(u32 line, u32* spritebuf, u32* dst)
void GPU2D::DrawScanline_Mode1(u32 line, u32* dst)
{
- u32 linebuf[256*2];
+ u32 linebuf[256*2 + 64];
+ u8* windowmask = (u8*)&linebuf[256*2];
u32 backdrop;
if (Num) backdrop = *(u16*)&GPU::Palette[0x400];
@@ -753,6 +867,11 @@ void GPU2D::DrawScanline_Mode1(u32 line, u32* dst)
linebuf[i] = backdrop;
}
+ if (DispCnt & 0xE000)
+ CalculateWindowMask(line, windowmask);
+ else
+ memset(windowmask, 0xFF, 256);
+
// prerender sprites
u32 spritebuf[256];
memset(spritebuf, 0, 256*4);
@@ -781,7 +900,11 @@ void GPU2D::DrawScanline_Mode1(u32 line, u32* dst)
u32 coloreffect, eva, evb;
u32 flag1 = val1 >> 24;
- if ((flag1 & 0x80) && (BlendCnt & ((val2 >> 16) & 0xFF00)))
+ if (!(windowmask[i] & 0x20))
+ {
+ coloreffect = 0;
+ }
+ else if ((flag1 & 0x80) && (BlendCnt & ((val2 >> 16) & 0xFF00)))
{
// sprite blending
@@ -904,10 +1027,10 @@ void GPU2D::DrawPixel(u32* dst, u16 color, u32 flag)
void GPU2D::DrawBG_3D(u32 line, u32* dst)
{
- // TODO: window, as for everything
- // also check if window can prevent blending from happening
+ // TODO: check if window can prevent blending from happening
u32* src = GPU3D::GetLine(line);
+ u8* windowmask = (u8*)&dst[256*2];
u16 xoff = BGXPos[0];
int i = 0;
@@ -929,6 +1052,7 @@ void GPU2D::DrawBG_3D(u32 line, u32* dst)
xoff++;
if ((c >> 24) == 0) continue;
+ if (!(windowmask[i] & 0x01)) continue;
dst[i+256] = dst[i];
dst[i] = c | 0x40000000;
@@ -937,6 +1061,7 @@ void GPU2D::DrawBG_3D(u32 line, u32* dst)
void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
{
+ u8* windowmask = (u8*)&dst[256*2];
u16 bgcnt = BGCnt[bgnum];
u32 tilesetaddr, tilemapaddr;
@@ -1012,12 +1137,15 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
}
// draw pixel
- u8 color;
- u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
- color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff);
+ if (windowmask[i] & (1<<bgnum))
+ {
+ u8 color;
+ u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
+ color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff);
- if (color)
- DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
+ if (color)
+ DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
+ }
xoff++;
}
@@ -1049,19 +1177,22 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
// draw pixel
// TODO: optimize VRAM access
- u8 color;
- u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
- if (tilexoff & 0x1)
+ if (windowmask[i] & (1<<bgnum))
{
- color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) >> 4;
- }
- else
- {
- color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) & 0x0F;
- }
+ u8 color;
+ 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;
+ }
- if (color)
- DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
+ if (color)
+ DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
+ }
xoff++;
}
@@ -1070,6 +1201,7 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
void GPU2D::DrawBG_Affine(u32 line, u32* dst, u32 bgnum)
{
+ u8* windowmask = (u8*)&dst[256*2];
u16 bgcnt = BGCnt[bgnum];
u32 tilesetaddr, tilemapaddr;
@@ -1118,7 +1250,7 @@ void GPU2D::DrawBG_Affine(u32 line, u32* dst, u32 bgnum)
for (int i = 0; i < 256; i++)
{
- if (!((rotX|rotY) & overflowmask))
+ if ((!((rotX|rotY) & overflowmask)) && (windowmask[i] & (1<<bgnum)))
{
curtile = GPU::ReadVRAM_BG<u8>(tilemapaddr + ((((rotY & coordmask) >> 11) << yshift) + ((rotX & coordmask) >> 11)));
@@ -1143,6 +1275,7 @@ void GPU2D::DrawBG_Affine(u32 line, u32* dst, u32 bgnum)
void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
{
+ u8* windowmask = (u8*)&dst[256*2];
u16 bgcnt = BGCnt[bgnum];
u32 tilesetaddr, tilemapaddr;
@@ -1188,7 +1321,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
for (int i = 0; i < 256; i++)
{
- if (!((rotX|rotY) & overflowmask))
+ if ((!((rotX|rotY) & overflowmask)) && (windowmask[i] & (1<<bgnum)))
{
u16 color = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)) << 1));
@@ -1209,7 +1342,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
for (int i = 0; i < 256; i++)
{
- if (!((rotX|rotY) & overflowmask))
+ if ((!((rotX|rotY) & overflowmask)) && (windowmask[i] & (1<<bgnum)))
{
u8 color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8));
@@ -1248,7 +1381,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
for (int i = 0; i < 256; i++)
{
- if (!((rotX|rotY) & overflowmask))
+ if ((!((rotX|rotY) & overflowmask)) && (windowmask[i] & (1<<bgnum)))
{
curtile = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((rotY & coordmask) >> 11) << yshift) + ((rotX & coordmask) >> 11)) << 1));
@@ -1280,9 +1413,11 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
void GPU2D::InterleaveSprites(u32* buf, u32 prio, u32* dst)
{
+ u8* windowmask = (u8*)&dst[256*2];
+
for (u32 i = 0; i < 256; i++)
{
- if ((buf[i] & 0xF8000) == prio)
+ if (((buf[i] & 0xF8000) == prio) && (windowmask[i] & 0x10))
{
u32 blendfunc = 0;
DrawPixel(&dst[i], buf[i] & 0x7FFF, buf[i] & 0xFF000000);
@@ -1318,6 +1453,9 @@ void GPU2D::DrawSprites(u32 line, u32* dst)
if ((attrib[2] & 0x0C00) != bgnum)
continue;
+ if (((attrib[0] >> 10) & 0x3) == 2)
+ continue;
+
if (attrib[0] & 0x0100)
{
u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12);
@@ -1343,7 +1481,7 @@ void GPU2D::DrawSprites(u32 line, u32* dst)
u32 rotparamgroup = (attrib[1] >> 9) & 0x1F;
- DrawSprite_Rotscale(attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos, dst);
+ DrawSprite_Rotscale<false>(attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos, dst);
}
else
{
@@ -1367,17 +1505,98 @@ void GPU2D::DrawSprites(u32 line, u32* dst)
if (attrib[1] & 0x2000)
ypos = height-1 - ypos;
- DrawSprite_Normal(attrib, width, xpos, ypos, dst);
+ DrawSprite_Normal<false>(attrib, width, xpos, ypos, dst);
+ }
+ }
+ }
+}
+
+void GPU2D::DrawSpritesWindow(u32 line, u8* dst)
+{
+ u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0];
+
+ const s32 spritewidth[16] =
+ {
+ 8, 16, 8, 0,
+ 16, 32, 8, 0,
+ 32, 32, 16, 0,
+ 64, 64, 32, 0
+ };
+ const s32 spriteheight[16] =
+ {
+ 8, 8, 16, 0,
+ 16, 8, 32, 0,
+ 32, 16, 32, 0,
+ 64, 32, 64, 0
+ };
+
+ for (int sprnum = 127; sprnum >= 0; sprnum--)
+ {
+ u16* attrib = &oam[sprnum*4];
+
+ if (((attrib[0] >> 10) & 0x3) != 2)
+ continue;
+
+ if (attrib[0] & 0x0100)
+ {
+ u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12);
+ s32 width = spritewidth[sizeparam];
+ s32 height = spriteheight[sizeparam];
+ s32 boundwidth = width;
+ s32 boundheight = height;
+
+ if (attrib[0] & 0x0200)
+ {
+ boundwidth <<= 1;
+ boundheight <<= 1;
}
+
+ u32 ypos = attrib[0] & 0xFF;
+ ypos = (line - ypos) & 0xFF;
+ if (ypos >= (u32)boundheight)
+ continue;
+
+ s32 xpos = (s32)(attrib[1] << 23) >> 23;
+ if (xpos <= -boundwidth)
+ continue;
+
+ u32 rotparamgroup = (attrib[1] >> 9) & 0x1F;
+
+ DrawSprite_Rotscale<true>(attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos, (u32*)dst);
+ }
+ else
+ {
+ if (attrib[0] & 0x0200)
+ continue;
+
+ u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12);
+ s32 width = spritewidth[sizeparam];
+ s32 height = spriteheight[sizeparam];
+
+ u32 ypos = attrib[0] & 0xFF;
+ ypos = (line - ypos) & 0xFF;
+ if (ypos >= (u32)height)
+ continue;
+
+ s32 xpos = (s32)(attrib[1] << 23) >> 23;
+ if (xpos <= -width)
+ continue;
+
+ // yflip
+ if (attrib[1] & 0x2000)
+ ypos = height-1 - ypos;
+
+ DrawSprite_Normal<true>(attrib, width, xpos, ypos, (u32*)dst);
}
}
}
+template<bool window>
void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, u32 ypos, u32* dst)
{
u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
u32 tilenum = attrib[2] & 0x03FF;
- u32 spritemode = (attrib[0] >> 10) & 0x3;
+ u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
u32 ytilefactor;
@@ -1448,13 +1667,13 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
{
if ((u32)rotX < width && (u32)rotY < height)
{
- u8 color;
-
- // blaaaarg
- color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
+ u8 color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
if (color & 0x8000)
- dst[xpos] = color | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = color | prio;
+ }
}
rotX += rotA;
@@ -1488,20 +1707,23 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
u32 extpal = (DispCnt & 0x80000000);
u16* pal;
- if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
- else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ if (!window)
+ {
+ if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
+ else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ }
for (; xoff < boundwidth;)
{
if ((u32)rotX < width && (u32)rotY < height)
{
- u8 color;
-
- // blaaaarg
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
+ u8 color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
if (color)
- dst[xpos] = pal[color] | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = pal[color] | prio;
+ }
}
rotX += rotA;
@@ -1517,17 +1739,18 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
ytilefactor <<= 5;
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
- u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
- pal += (attrib[2] & 0xF000) >> 8;
+ u16* pal;
+ if (!window)
+ {
+ pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ pal += (attrib[2] & 0xF000) >> 8;
+ }
for (; xoff < boundwidth;)
{
if ((u32)rotX < width && (u32)rotY < height)
{
- u8 color;
-
- // blaaaarg
- color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
+ u8 color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
if (rotX & 0x100)
color >>= 4;
@@ -1535,7 +1758,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
color &= 0x0F;
if (color)
- dst[xpos] = pal[color] | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = pal[color] | prio;
+ }
}
rotX += rotA;
@@ -1547,11 +1773,12 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
}
}
+template<bool window>
void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst)
{
u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
u32 tilenum = attrib[2] & 0x03FF;
- u32 spritemode = (attrib[0] >> 10) & 0x3;
+ u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
u32 wmask = width - 8; // really ((width - 1) & ~0x7)
@@ -1614,7 +1841,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
pixelsaddr += 2;
if (color & 0x8000)
- dst[xpos] = color | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = color | prio;
+ }
xoff++;
xpos++;
@@ -1645,8 +1875,11 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
u32 extpal = (DispCnt & 0x80000000);
u16* pal;
- if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
- else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ if (!window)
+ {
+ if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
+ else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ }
if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works
{
@@ -1659,7 +1892,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
pixelsaddr--;
if (color)
- dst[xpos] = pal[color] | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = pal[color] | prio;
+ }
xoff++;
xpos++;
@@ -1677,7 +1913,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
pixelsaddr++;
if (color)
- dst[xpos] = pal[color] | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = pal[color] | prio;
+ }
xoff++;
xpos++;
@@ -1692,8 +1931,12 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
pixelsaddr += ((ypos & 0x7) << 2);
- u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
- pal += (attrib[2] & 0xF000) >> 8;
+ u16* pal;
+ if (!window)
+ {
+ pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
+ pal += (attrib[2] & 0xF000) >> 8;
+ }
if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works
{
@@ -1714,7 +1957,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
}
if (color)
- dst[xpos] = pal[color] | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = pal[color] | prio;
+ }
xoff++;
xpos++;
@@ -1740,7 +1986,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
}
if (color)
- dst[xpos] = pal[color] | prio;
+ {
+ if (window) ((u8*)dst)[xpos] = 1;
+ else dst[xpos] = pal[color] | prio;
+ }
xoff++;
xpos++;
diff --git a/src/GPU2D.h b/src/GPU2D.h
index 38cbe7e..4bf698d 100644
--- a/src/GPU2D.h
+++ b/src/GPU2D.h
@@ -40,6 +40,8 @@ public:
void VBlank();
void VBlankEnd();
+ void CheckWindows(u32 line);
+
void BGExtPalDirty(u32 base);
void OBJExtPalDirty();
@@ -69,6 +71,12 @@ private:
s16 BGRotC[2];
s16 BGRotD[2];
+ u8 Win0Coords[4];
+ u8 Win1Coords[4];
+ u8 WinCnt[4];
+ bool Win0Active;
+ bool Win1Active;
+
u16 BlendCnt;
u8 EVA, EVB;
u8 EVY;
@@ -88,16 +96,19 @@ private:
void DrawPixel(u32* dst, u16 color, u32 flag);
void DrawBG_3D(u32 line, u32* dst);
- void DrawBG_Text(u32 line, u32* dst, u32 num);
+ void DrawBG_Text(u32 line, u32* dst, u32 bgnum);
void DrawBG_Affine(u32 line, u32* dst, u32 bgnum);
void DrawBG_Extended(u32 line, u32* dst, u32 bgnum);
void InterleaveSprites(u32* buf, u32 prio, u32* dst);
void DrawSprites(u32 line, u32* dst);
- void DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, u32 ypos, u32* dst);
- void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst);
+ void DrawSpritesWindow(u32 line, u8* dst);
+ template<bool window> void DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, u32 ypos, u32* dst);
+ template<bool window> void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst);
void DoCapture(u32 line, u32 width, u32* src);
+
+ void CalculateWindowMask(u32 line, u8* mask);
};
#endif
diff --git a/src/SPU.cpp b/src/SPU.cpp
index f5a7b9b..002cde6 100644
--- a/src/SPU.cpp
+++ b/src/SPU.cpp
@@ -131,13 +131,15 @@ void Channel::Reset()
TimerReload = 0;
LoopPos = 0;
Length = 0;
+
+ Timer = 0;
}
void Channel::Start()
{
Timer = TimerReload;
- if (((Cnt >> 29) & 0x3) == 1)
+ if (((Cnt >> 29) & 0x3) == 3)
Pos = -1;
else
Pos = -3;
@@ -338,6 +340,8 @@ void CaptureUnit::Reset()
DstAddr = 0;
TimerReload = 0;
Length = 0;
+
+ Timer = 0;
}
void CaptureUnit::Run(s32 sample)