mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-23 14:19:55 -06:00
2D: implement large BG, fix non-large bitmap BG. fixes #61
This commit is contained in:
126
src/GPU2D.cpp
126
src/GPU2D.cpp
@ -934,7 +934,7 @@ void GPU2D::DrawScanlineBGMode6(u32 line, u32* spritebuf, u32* dst)
|
|||||||
{
|
{
|
||||||
if (DispCnt & 0x0400)
|
if (DispCnt & 0x0400)
|
||||||
{
|
{
|
||||||
printf("GPU2D: MODE6 LARGE BG TODO\n");
|
DrawBG_Large(line, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((BGCnt[0] & 0x3) == i)
|
if ((BGCnt[0] & 0x3) == i)
|
||||||
@ -1387,20 +1387,6 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||||||
u16* pal;
|
u16* pal;
|
||||||
u32 extpal;
|
u32 extpal;
|
||||||
|
|
||||||
u32 coordmask;
|
|
||||||
u32 yshift;
|
|
||||||
switch (bgcnt & 0xC000)
|
|
||||||
{
|
|
||||||
case 0x0000: coordmask = 0x07800; yshift = 7; break;
|
|
||||||
case 0x4000: coordmask = 0x0F800; yshift = 8; break;
|
|
||||||
case 0x8000: coordmask = 0x1F800; yshift = 9; break;
|
|
||||||
case 0xC000: coordmask = 0x3F800; yshift = 10; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 overflowmask;
|
|
||||||
if (bgcnt & 0x2000) overflowmask = 0;
|
|
||||||
else overflowmask = ~(coordmask | 0x7FF);
|
|
||||||
|
|
||||||
extpal = (DispCnt & 0x40000000);
|
extpal = (DispCnt & 0x40000000);
|
||||||
|
|
||||||
s16 rotA = BGRotA[bgnum-2];
|
s16 rotA = BGRotA[bgnum-2];
|
||||||
@ -1415,20 +1401,40 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||||||
{
|
{
|
||||||
// bitmap modes
|
// bitmap modes
|
||||||
|
|
||||||
|
u32 xmask, ymask;
|
||||||
|
u32 yshift;
|
||||||
|
switch (bgcnt & 0xC000)
|
||||||
|
{
|
||||||
|
case 0x0000: xmask = 0x07FFF; ymask = 0x07FFF; yshift = 7; break;
|
||||||
|
case 0x4000: xmask = 0x0FFFF; ymask = 0x0FFFF; yshift = 8; break;
|
||||||
|
case 0x8000: xmask = 0x1FFFF; ymask = 0x0FFFF; yshift = 9; break;
|
||||||
|
case 0xC000: xmask = 0x1FFFF; ymask = 0x1FFFF; yshift = 9; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ofxmask, ofymask;
|
||||||
|
if (bgcnt & 0x2000)
|
||||||
|
{
|
||||||
|
ofxmask = 0;
|
||||||
|
ofymask = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ofxmask = ~xmask;
|
||||||
|
ofymask = ~ymask;
|
||||||
|
}
|
||||||
|
|
||||||
if (Num) tilemapaddr = 0x06200000 + ((bgcnt & 0x1F00) << 6);
|
if (Num) tilemapaddr = 0x06200000 + ((bgcnt & 0x1F00) << 6);
|
||||||
else tilemapaddr = 0x06000000 + ((bgcnt & 0x1F00) << 6);
|
else tilemapaddr = 0x06000000 + ((bgcnt & 0x1F00) << 6);
|
||||||
|
|
||||||
coordmask |= 0x7FF;
|
|
||||||
|
|
||||||
if (bgcnt & 0x0004)
|
if (bgcnt & 0x0004)
|
||||||
{
|
{
|
||||||
// direct color bitmap
|
// direct color bitmap
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
if ((!((rotX|rotY) & overflowmask)) && (windowmask[i] & (1<<bgnum)))
|
if (!(rotX & ofxmask) && !(rotY & ofymask) && (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 & ymask) >> 8) << yshift) + ((rotX & xmask) >> 8)) << 1));
|
||||||
|
|
||||||
if (color & 0x8000)
|
if (color & 0x8000)
|
||||||
DrawPixel(&dst[i], color, 0x01000000<<bgnum);
|
DrawPixel(&dst[i], color, 0x01000000<<bgnum);
|
||||||
@ -1447,9 +1453,9 @@ 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)) && (windowmask[i] & (1<<bgnum)))
|
if (!(rotX & ofxmask) && !(rotY & ofymask) && (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 & ymask) >> 8) << yshift) + ((rotX & xmask) >> 8));
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
DrawPixel(&dst[i], pal[color], 0x01000000<<bgnum);
|
DrawPixel(&dst[i], pal[color], 0x01000000<<bgnum);
|
||||||
@ -1464,6 +1470,20 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||||||
{
|
{
|
||||||
// mixed affine/text mode
|
// mixed affine/text mode
|
||||||
|
|
||||||
|
u32 coordmask;
|
||||||
|
u32 yshift;
|
||||||
|
switch (bgcnt & 0xC000)
|
||||||
|
{
|
||||||
|
case 0x0000: coordmask = 0x07800; yshift = 7; break;
|
||||||
|
case 0x4000: coordmask = 0x0F800; yshift = 8; break;
|
||||||
|
case 0x8000: coordmask = 0x1F800; yshift = 9; break;
|
||||||
|
case 0xC000: coordmask = 0x3F800; yshift = 10; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 overflowmask;
|
||||||
|
if (bgcnt & 0x2000) overflowmask = 0;
|
||||||
|
else overflowmask = ~(coordmask | 0x7FF);
|
||||||
|
|
||||||
if (Num)
|
if (Num)
|
||||||
{
|
{
|
||||||
tilesetaddr = 0x06200000 + ((bgcnt & 0x003C) << 12);
|
tilesetaddr = 0x06200000 + ((bgcnt & 0x003C) << 12);
|
||||||
@ -1516,6 +1536,70 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||||||
BGYRefInternal[bgnum-2] += rotD;
|
BGYRefInternal[bgnum-2] += rotD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU2D::DrawBG_Large(u32 line, u32* dst) // BG is always BG2
|
||||||
|
{
|
||||||
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
|
u16 bgcnt = BGCnt[2];
|
||||||
|
|
||||||
|
u32 tilesetaddr, tilemapaddr;
|
||||||
|
u16* pal;
|
||||||
|
|
||||||
|
u32 xmask, ymask;
|
||||||
|
u32 yshift;
|
||||||
|
switch (bgcnt & 0xC000)
|
||||||
|
{
|
||||||
|
case 0x0000: xmask = 0x1FFFF; ymask = 0x3FFFF; yshift = 9; break;
|
||||||
|
case 0x4000: xmask = 0x3FFFF; ymask = 0x1FFFF; yshift = 10; break;
|
||||||
|
case 0x8000: // TODO (most likely the second size bit is just ignored)
|
||||||
|
case 0xC000: printf("bad BG size for large BG: %04X\n", bgcnt); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ofxmask, ofymask;
|
||||||
|
if (bgcnt & 0x2000)
|
||||||
|
{
|
||||||
|
ofxmask = 0;
|
||||||
|
ofymask = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ofxmask = ~xmask;
|
||||||
|
ofymask = ~ymask;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 rotA = BGRotA[0];
|
||||||
|
s16 rotB = BGRotB[0];
|
||||||
|
s16 rotC = BGRotC[0];
|
||||||
|
s16 rotD = BGRotD[0];
|
||||||
|
|
||||||
|
s32 rotX = BGXRefInternal[0];
|
||||||
|
s32 rotY = BGYRefInternal[0];
|
||||||
|
|
||||||
|
if (Num) tilemapaddr = 0x06200000;
|
||||||
|
else tilemapaddr = 0x06000000;
|
||||||
|
|
||||||
|
// 256-color bitmap
|
||||||
|
|
||||||
|
if (Num) pal = (u16*)&GPU::Palette[0x400];
|
||||||
|
else pal = (u16*)&GPU::Palette[0];
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
if (!(rotX & ofxmask) && !(rotY & ofymask) && (windowmask[i] & (1<<2)))
|
||||||
|
{
|
||||||
|
u8 color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((rotY & ymask) >> 8) << yshift) + ((rotX & xmask) >> 8));
|
||||||
|
|
||||||
|
if (color)
|
||||||
|
DrawPixel(&dst[i], pal[color], 0x01000000<<2);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotX += rotA;
|
||||||
|
rotY += rotC;
|
||||||
|
}
|
||||||
|
|
||||||
|
BGXRefInternal[0] += rotB;
|
||||||
|
BGYRefInternal[0] += rotD;
|
||||||
|
}
|
||||||
|
|
||||||
void GPU2D::InterleaveSprites(u32* buf, u32 prio, u32* dst)
|
void GPU2D::InterleaveSprites(u32* buf, u32 prio, u32* dst)
|
||||||
{
|
{
|
||||||
u8* windowmask = (u8*)&dst[256*2];
|
u8* windowmask = (u8*)&dst[256*2];
|
||||||
|
@ -114,6 +114,7 @@ private:
|
|||||||
void DrawBG_Text(u32 line, u32* dst, u32 bgnum);
|
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 DrawBG_Large(u32 line, u32* dst);
|
||||||
|
|
||||||
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);
|
||||||
|
Reference in New Issue
Block a user