diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-07-05 19:31:13 +0200 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-07-05 19:31:13 +0200 |
commit | 93ab7064b203c463607258cb3bc94f5da9729959 (patch) | |
tree | 0f59c3a4c428b227a9c67c8d2dfaf70467b79596 | |
parent | 678ae00e0a4dc7fbe7b4027a1ed7bc3bcd253cec (diff) |
2D: implement large BG, fix non-large bitmap BG. fixes #61
-rw-r--r-- | src/GPU2D.cpp | 126 | ||||
-rw-r--r-- | src/GPU2D.h | 1 |
2 files changed, 106 insertions, 21 deletions
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index a9bd498..ee1fbc1 100644 --- a/src/GPU2D.cpp +++ b/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]; diff --git a/src/GPU2D.h b/src/GPU2D.h index 289f1fe..4c68cdb 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -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); |