windows!
This commit is contained in:
parent
3f3b2977d7
commit
bc70f00372
|
@ -649,6 +649,9 @@ void StartScanline(u32 line)
|
||||||
else
|
else
|
||||||
DispStat[1] &= ~(1<<2);
|
DispStat[1] &= ~(1<<2);
|
||||||
|
|
||||||
|
GPU2D_A->CheckWindows(line);
|
||||||
|
GPU2D_B->CheckWindows(line);
|
||||||
|
|
||||||
if (line >= 2 && line < 194)
|
if (line >= 2 && line < 194)
|
||||||
NDS::CheckDMAs(0, 0x03);
|
NDS::CheckDMAs(0, 0x03);
|
||||||
else if (line == 194)
|
else if (line == 194)
|
||||||
|
|
367
src/GPU2D.cpp
367
src/GPU2D.cpp
|
@ -94,6 +94,10 @@ void GPU2D::Reset()
|
||||||
memset(BGRotC, 0, 2*2);
|
memset(BGRotC, 0, 2*2);
|
||||||
memset(BGRotD, 0, 2*2);
|
memset(BGRotD, 0, 2*2);
|
||||||
|
|
||||||
|
memset(Win0Coords, 0, 4);
|
||||||
|
memset(Win1Coords, 0, 4);
|
||||||
|
memset(WinCnt, 0, 4);
|
||||||
|
|
||||||
BlendCnt = 0;
|
BlendCnt = 0;
|
||||||
EVA = 16;
|
EVA = 16;
|
||||||
EVB = 0;
|
EVB = 0;
|
||||||
|
@ -120,7 +124,15 @@ void GPU2D::SetFramebuffer(u32* buf)
|
||||||
|
|
||||||
u8 GPU2D::Read8(u32 addr)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +148,9 @@ u16 GPU2D::Read16(u32 addr)
|
||||||
case 0x00C: return BGCnt[2];
|
case 0x00C: return BGCnt[2];
|
||||||
case 0x00E: return BGCnt[3];
|
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 0x050: return BlendCnt;
|
||||||
|
|
||||||
case 0x064: return CaptureCnt & 0xFFFF;
|
case 0x064: return CaptureCnt & 0xFFFF;
|
||||||
|
@ -160,7 +175,25 @@ u32 GPU2D::Read32(u32 addr)
|
||||||
|
|
||||||
void GPU2D::Write8(u32 addr, u8 val)
|
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)
|
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];
|
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||||
return;
|
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 0x050: BlendCnt = val; return;
|
||||||
case 0x052:
|
case 0x052:
|
||||||
EVA = val & 0x1F;
|
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>
|
template<u32 bgmode>
|
||||||
void GPU2D::DrawScanlineBGMode(u32 line, u32* spritebuf, u32* dst)
|
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)
|
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;
|
u32 backdrop;
|
||||||
if (Num) backdrop = *(u16*)&GPU::Palette[0x400];
|
if (Num) backdrop = *(u16*)&GPU::Palette[0x400];
|
||||||
|
@ -753,6 +867,11 @@ void GPU2D::DrawScanline_Mode1(u32 line, u32* dst)
|
||||||
linebuf[i] = backdrop;
|
linebuf[i] = backdrop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DispCnt & 0xE000)
|
||||||
|
CalculateWindowMask(line, windowmask);
|
||||||
|
else
|
||||||
|
memset(windowmask, 0xFF, 256);
|
||||||
|
|
||||||
// prerender sprites
|
// prerender sprites
|
||||||
u32 spritebuf[256];
|
u32 spritebuf[256];
|
||||||
memset(spritebuf, 0, 256*4);
|
memset(spritebuf, 0, 256*4);
|
||||||
|
@ -781,7 +900,11 @@ void GPU2D::DrawScanline_Mode1(u32 line, u32* dst)
|
||||||
u32 coloreffect, eva, evb;
|
u32 coloreffect, eva, evb;
|
||||||
|
|
||||||
u32 flag1 = val1 >> 24;
|
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
|
// sprite blending
|
||||||
|
|
||||||
|
@ -904,10 +1027,10 @@ void GPU2D::DrawPixel(u32* dst, u16 color, u32 flag)
|
||||||
|
|
||||||
void GPU2D::DrawBG_3D(u32 line, u32* dst)
|
void GPU2D::DrawBG_3D(u32 line, u32* dst)
|
||||||
{
|
{
|
||||||
// TODO: window, as for everything
|
// TODO: check if window can prevent blending from happening
|
||||||
// also check if window can prevent blending from happening
|
|
||||||
|
|
||||||
u32* src = GPU3D::GetLine(line);
|
u32* src = GPU3D::GetLine(line);
|
||||||
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
|
|
||||||
u16 xoff = BGXPos[0];
|
u16 xoff = BGXPos[0];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -929,6 +1052,7 @@ void GPU2D::DrawBG_3D(u32 line, u32* dst)
|
||||||
xoff++;
|
xoff++;
|
||||||
|
|
||||||
if ((c >> 24) == 0) continue;
|
if ((c >> 24) == 0) continue;
|
||||||
|
if (!(windowmask[i] & 0x01)) continue;
|
||||||
|
|
||||||
dst[i+256] = dst[i];
|
dst[i+256] = dst[i];
|
||||||
dst[i] = c | 0x40000000;
|
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)
|
void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
|
||||||
{
|
{
|
||||||
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
u16 bgcnt = BGCnt[bgnum];
|
u16 bgcnt = BGCnt[bgnum];
|
||||||
|
|
||||||
u32 tilesetaddr, tilemapaddr;
|
u32 tilesetaddr, tilemapaddr;
|
||||||
|
@ -1012,12 +1137,15 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw pixel
|
// draw pixel
|
||||||
u8 color;
|
if (windowmask[i] & (1<<bgnum))
|
||||||
u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
|
{
|
||||||
color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff);
|
u8 color;
|
||||||
|
u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
|
||||||
|
color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff);
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
|
DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
}
|
}
|
||||||
|
@ -1049,19 +1177,22 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum)
|
||||||
|
|
||||||
// draw pixel
|
// draw pixel
|
||||||
// TODO: optimize VRAM access
|
// TODO: optimize VRAM access
|
||||||
u8 color;
|
if (windowmask[i] & (1<<bgnum))
|
||||||
u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
|
|
||||||
if (tilexoff & 0x1)
|
|
||||||
{
|
{
|
||||||
color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) >> 4;
|
u8 color;
|
||||||
}
|
u32 tilexoff = (curtile & 0x0400) ? (7-(xoff&0x7)) : (xoff&0x7);
|
||||||
else
|
if (tilexoff & 0x1)
|
||||||
{
|
{
|
||||||
color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) & 0x0F;
|
color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) >> 4;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = GPU::ReadVRAM_BG<u8>(pixelsaddr + (tilexoff >> 1)) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
|
DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum);
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
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)
|
void GPU2D::DrawBG_Affine(u32 line, u32* dst, u32 bgnum)
|
||||||
{
|
{
|
||||||
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
u16 bgcnt = BGCnt[bgnum];
|
u16 bgcnt = BGCnt[bgnum];
|
||||||
|
|
||||||
u32 tilesetaddr, tilemapaddr;
|
u32 tilesetaddr, tilemapaddr;
|
||||||
|
@ -1118,7 +1250,7 @@ void GPU2D::DrawBG_Affine(u32 line, u32* dst, u32 bgnum)
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
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)));
|
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)
|
void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
||||||
{
|
{
|
||||||
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
u16 bgcnt = BGCnt[bgnum];
|
u16 bgcnt = BGCnt[bgnum];
|
||||||
|
|
||||||
u32 tilesetaddr, tilemapaddr;
|
u32 tilesetaddr, tilemapaddr;
|
||||||
|
@ -1188,7 +1321,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
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));
|
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++)
|
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));
|
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++)
|
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));
|
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)
|
void GPU2D::InterleaveSprites(u32* buf, u32 prio, u32* dst)
|
||||||
{
|
{
|
||||||
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
|
|
||||||
for (u32 i = 0; i < 256; i++)
|
for (u32 i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
if ((buf[i] & 0xF8000) == prio)
|
if (((buf[i] & 0xF8000) == prio) && (windowmask[i] & 0x10))
|
||||||
{
|
{
|
||||||
u32 blendfunc = 0;
|
u32 blendfunc = 0;
|
||||||
DrawPixel(&dst[i], buf[i] & 0x7FFF, buf[i] & 0xFF000000);
|
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)
|
if ((attrib[2] & 0x0C00) != bgnum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (((attrib[0] >> 10) & 0x3) == 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (attrib[0] & 0x0100)
|
if (attrib[0] & 0x0100)
|
||||||
{
|
{
|
||||||
u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12);
|
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;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1367,17 +1505,98 @@ void GPU2D::DrawSprites(u32 line, u32* dst)
|
||||||
if (attrib[1] & 0x2000)
|
if (attrib[1] & 0x2000)
|
||||||
ypos = height-1 - ypos;
|
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)
|
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 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
|
||||||
u32 tilenum = attrib[2] & 0x03FF;
|
u32 tilenum = attrib[2] & 0x03FF;
|
||||||
u32 spritemode = (attrib[0] >> 10) & 0x3;
|
u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3);
|
||||||
|
|
||||||
u32 ytilefactor;
|
u32 ytilefactor;
|
||||||
|
|
||||||
|
@ -1448,13 +1667,13 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
|
||||||
{
|
{
|
||||||
if ((u32)rotX < width && (u32)rotY < height)
|
if ((u32)rotX < width && (u32)rotY < height)
|
||||||
{
|
{
|
||||||
u8 color;
|
u8 color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
|
||||||
|
|
||||||
// blaaaarg
|
|
||||||
color = GPU::ReadVRAM_OBJ<u16>(pixelsaddr + ((rotY >> 8) * ytilefactor) + ((rotX >> 8) << 1));
|
|
||||||
|
|
||||||
if (color & 0x8000)
|
if (color & 0x8000)
|
||||||
dst[xpos] = color | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = color | prio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rotX += rotA;
|
rotX += rotA;
|
||||||
|
@ -1488,20 +1707,23 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
|
||||||
u32 extpal = (DispCnt & 0x80000000);
|
u32 extpal = (DispCnt & 0x80000000);
|
||||||
|
|
||||||
u16* pal;
|
u16* pal;
|
||||||
if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
|
if (!window)
|
||||||
else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
|
{
|
||||||
|
if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
|
||||||
|
else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
|
||||||
|
}
|
||||||
|
|
||||||
for (; xoff < boundwidth;)
|
for (; xoff < boundwidth;)
|
||||||
{
|
{
|
||||||
if ((u32)rotX < width && (u32)rotY < height)
|
if ((u32)rotX < width && (u32)rotY < height)
|
||||||
{
|
{
|
||||||
u8 color;
|
u8 color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
|
||||||
|
|
||||||
// blaaaarg
|
|
||||||
color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8));
|
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
dst[xpos] = pal[color] | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = pal[color] | prio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rotX += rotA;
|
rotX += rotA;
|
||||||
|
@ -1517,17 +1739,18 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
|
||||||
ytilefactor <<= 5;
|
ytilefactor <<= 5;
|
||||||
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
|
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
|
||||||
|
|
||||||
u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
|
u16* pal;
|
||||||
pal += (attrib[2] & 0xF000) >> 8;
|
if (!window)
|
||||||
|
{
|
||||||
|
pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
|
||||||
|
pal += (attrib[2] & 0xF000) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
for (; xoff < boundwidth;)
|
for (; xoff < boundwidth;)
|
||||||
{
|
{
|
||||||
if ((u32)rotX < width && (u32)rotY < height)
|
if ((u32)rotX < width && (u32)rotY < height)
|
||||||
{
|
{
|
||||||
u8 color;
|
u8 color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
|
||||||
|
|
||||||
// blaaaarg
|
|
||||||
color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9));
|
|
||||||
|
|
||||||
if (rotX & 0x100)
|
if (rotX & 0x100)
|
||||||
color >>= 4;
|
color >>= 4;
|
||||||
|
@ -1535,7 +1758,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
|
||||||
color &= 0x0F;
|
color &= 0x0F;
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
dst[xpos] = pal[color] | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = pal[color] | prio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rotX += rotA;
|
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)
|
void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst)
|
||||||
{
|
{
|
||||||
u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
|
u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000;
|
||||||
u32 tilenum = attrib[2] & 0x03FF;
|
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)
|
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;
|
pixelsaddr += 2;
|
||||||
|
|
||||||
if (color & 0x8000)
|
if (color & 0x8000)
|
||||||
dst[xpos] = color | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = color | prio;
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
xpos++;
|
xpos++;
|
||||||
|
@ -1645,8 +1875,11 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
|
||||||
u32 extpal = (DispCnt & 0x80000000);
|
u32 extpal = (DispCnt & 0x80000000);
|
||||||
|
|
||||||
u16* pal;
|
u16* pal;
|
||||||
if (extpal) pal = GetOBJExtPal(attrib[2] >> 12);
|
if (!window)
|
||||||
else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
|
{
|
||||||
|
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
|
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--;
|
pixelsaddr--;
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
dst[xpos] = pal[color] | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = pal[color] | prio;
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
xpos++;
|
xpos++;
|
||||||
|
@ -1677,7 +1913,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
|
||||||
pixelsaddr++;
|
pixelsaddr++;
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
dst[xpos] = pal[color] | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = pal[color] | prio;
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
xpos++;
|
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;
|
u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum;
|
||||||
pixelsaddr += ((ypos & 0x7) << 2);
|
pixelsaddr += ((ypos & 0x7) << 2);
|
||||||
|
|
||||||
u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200];
|
u16* pal;
|
||||||
pal += (attrib[2] & 0xF000) >> 8;
|
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
|
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)
|
if (color)
|
||||||
dst[xpos] = pal[color] | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = pal[color] | prio;
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
xpos++;
|
xpos++;
|
||||||
|
@ -1740,7 +1986,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
dst[xpos] = pal[color] | prio;
|
{
|
||||||
|
if (window) ((u8*)dst)[xpos] = 1;
|
||||||
|
else dst[xpos] = pal[color] | prio;
|
||||||
|
}
|
||||||
|
|
||||||
xoff++;
|
xoff++;
|
||||||
xpos++;
|
xpos++;
|
||||||
|
|
17
src/GPU2D.h
17
src/GPU2D.h
|
@ -40,6 +40,8 @@ public:
|
||||||
void VBlank();
|
void VBlank();
|
||||||
void VBlankEnd();
|
void VBlankEnd();
|
||||||
|
|
||||||
|
void CheckWindows(u32 line);
|
||||||
|
|
||||||
void BGExtPalDirty(u32 base);
|
void BGExtPalDirty(u32 base);
|
||||||
void OBJExtPalDirty();
|
void OBJExtPalDirty();
|
||||||
|
|
||||||
|
@ -69,6 +71,12 @@ private:
|
||||||
s16 BGRotC[2];
|
s16 BGRotC[2];
|
||||||
s16 BGRotD[2];
|
s16 BGRotD[2];
|
||||||
|
|
||||||
|
u8 Win0Coords[4];
|
||||||
|
u8 Win1Coords[4];
|
||||||
|
u8 WinCnt[4];
|
||||||
|
bool Win0Active;
|
||||||
|
bool Win1Active;
|
||||||
|
|
||||||
u16 BlendCnt;
|
u16 BlendCnt;
|
||||||
u8 EVA, EVB;
|
u8 EVA, EVB;
|
||||||
u8 EVY;
|
u8 EVY;
|
||||||
|
@ -88,16 +96,19 @@ private:
|
||||||
void DrawPixel(u32* dst, u16 color, u32 flag);
|
void DrawPixel(u32* dst, u16 color, u32 flag);
|
||||||
|
|
||||||
void DrawBG_3D(u32 line, u32* dst);
|
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_Affine(u32 line, u32* dst, u32 bgnum);
|
||||||
void DrawBG_Extended(u32 line, u32* dst, u32 bgnum);
|
void DrawBG_Extended(u32 line, u32* dst, u32 bgnum);
|
||||||
|
|
||||||
void InterleaveSprites(u32* buf, u32 prio, u32* dst);
|
void InterleaveSprites(u32* buf, u32 prio, u32* dst);
|
||||||
void DrawSprites(u32 line, 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 DrawSpritesWindow(u32 line, u8* dst);
|
||||||
void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* 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 DoCapture(u32 line, u32 width, u32* src);
|
||||||
|
|
||||||
|
void CalculateWindowMask(u32 line, u8* mask);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -131,13 +131,15 @@ void Channel::Reset()
|
||||||
TimerReload = 0;
|
TimerReload = 0;
|
||||||
LoopPos = 0;
|
LoopPos = 0;
|
||||||
Length = 0;
|
Length = 0;
|
||||||
|
|
||||||
|
Timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::Start()
|
void Channel::Start()
|
||||||
{
|
{
|
||||||
Timer = TimerReload;
|
Timer = TimerReload;
|
||||||
|
|
||||||
if (((Cnt >> 29) & 0x3) == 1)
|
if (((Cnt >> 29) & 0x3) == 3)
|
||||||
Pos = -1;
|
Pos = -1;
|
||||||
else
|
else
|
||||||
Pos = -3;
|
Pos = -3;
|
||||||
|
@ -338,6 +340,8 @@ void CaptureUnit::Reset()
|
||||||
DstAddr = 0;
|
DstAddr = 0;
|
||||||
TimerReload = 0;
|
TimerReload = 0;
|
||||||
Length = 0;
|
Length = 0;
|
||||||
|
|
||||||
|
Timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CaptureUnit::Run(s32 sample)
|
void CaptureUnit::Run(s32 sample)
|
||||||
|
|
Loading…
Reference in New Issue