2D: implement large BG, fix non-large bitmap BG. fixes #61
This commit is contained in:
parent
678ae00e0a
commit
93ab7064b2
126
src/GPU2D.cpp
126
src/GPU2D.cpp
|
@ -934,7 +934,7 @@ void GPU2D::DrawScanlineBGMode6(u32 line, u32* spritebuf, u32* dst)
|
|||
{
|
||||
if (DispCnt & 0x0400)
|
||||
{
|
||||
printf("GPU2D: MODE6 LARGE BG TODO\n");
|
||||
DrawBG_Large(line, dst);
|
||||
}
|
||||
}
|
||||
if ((BGCnt[0] & 0x3) == i)
|
||||
|
@ -1387,20 +1387,6 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||
u16* pal;
|
||||
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);
|
||||
|
||||
s16 rotA = BGRotA[bgnum-2];
|
||||
|
@ -1415,20 +1401,40 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||
{
|
||||
// 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);
|
||||
else tilemapaddr = 0x06000000 + ((bgcnt & 0x1F00) << 6);
|
||||
|
||||
coordmask |= 0x7FF;
|
||||
|
||||
if (bgcnt & 0x0004)
|
||||
{
|
||||
// direct color bitmap
|
||||
|
||||
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)
|
||||
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++)
|
||||
{
|
||||
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)
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
tilesetaddr = 0x06200000 + ((bgcnt & 0x003C) << 12);
|
||||
|
@ -1516,6 +1536,70 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum)
|
|||
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)
|
||||
{
|
||||
u8* windowmask = (u8*)&dst[256*2];
|
||||
|
|
|
@ -114,6 +114,7 @@ private:
|
|||
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 DrawBG_Large(u32 line, u32* dst);
|
||||
|
||||
void InterleaveSprites(u32* buf, u32 prio, u32* dst);
|
||||
void DrawSprites(u32 line, u32* dst);
|
||||
|
|
Loading…
Reference in New Issue