diff options
Diffstat (limited to 'src/GPU2D.cpp')
-rw-r--r-- | src/GPU2D.cpp | 130 |
1 files changed, 95 insertions, 35 deletions
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index e0da772..288ee58 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -246,6 +246,11 @@ u8 GPU2D::Read8(u32 addr) case 0x049: return WinCnt[1]; case 0x04A: return WinCnt[2]; case 0x04B: return WinCnt[3]; + + // there are games accidentally trying to read those + // those are write-only + case 0x04C: + case 0x04D: return 0; } printf("unknown GPU read8 %08X\n", addr); @@ -299,10 +304,22 @@ void GPU2D::Write8(u32 addr, u8 val) switch (addr & 0x00000FFF) { - case 0x000: DispCnt = (DispCnt & 0xFFFFFF00) | val; return; - case 0x001: DispCnt = (DispCnt & 0xFFFF00FF) | (val << 8); return; - case 0x002: DispCnt = (DispCnt & 0xFF00FFFF) | (val << 16); return; - case 0x003: DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24); return; + case 0x000: + DispCnt = (DispCnt & 0xFFFFFF00) | val; + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x001: + DispCnt = (DispCnt & 0xFFFF00FF) | (val << 8); + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x002: + DispCnt = (DispCnt & 0xFF00FFFF) | (val << 16); + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x003: + DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24); + if (Num) DispCnt &= 0xC0B1FFF7; + return; case 0x008: BGCnt[0] = (BGCnt[0] & 0xFF00) | val; return; case 0x009: BGCnt[0] = (BGCnt[0] & 0x00FF) | (val << 8); return; @@ -381,8 +398,14 @@ void GPU2D::Write16(u32 addr, u16 val) switch (addr & 0x00000FFF) { - case 0x000: DispCnt = (DispCnt & 0xFFFF0000) | val; return; - case 0x002: DispCnt = (DispCnt & 0x0000FFFF) | (val << 16); return; + case 0x000: + DispCnt = (DispCnt & 0xFFFF0000) | val; + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x002: + DispCnt = (DispCnt & 0x0000FFFF) | (val << 16); + if (Num) DispCnt &= 0xC0B1FFF7; + return; case 0x008: BGCnt[0] = val; return; case 0x00A: BGCnt[1] = val; return; @@ -514,6 +537,7 @@ void GPU2D::Write32(u32 addr, u32 val) { case 0x000: DispCnt = val; + if (Num) DispCnt &= 0xC0B1FFF7; return; case 0x028: @@ -704,10 +728,6 @@ void GPU2D::DrawScanline(u32 line) // oddly that's not the case for GPU A if (Num && !Enabled) forceblank = true; - // forced blank - // (checkme: are there still things that can run under this mode? likely not) - if (DispCnt & (1<<7)) forceblank = true; - if (forceblank) { for (int i = 0; i < 256; i++) @@ -748,8 +768,10 @@ void GPU2D::DrawScanline(u32 line) case 1: // regular display { - for (int i = 0; i < stride; i+=2) + int i = 0; + for (; i < (stride & ~1); i+=2) *(u64*)&dst[i] = *(u64*)&BGOBJLine[i]; + if (stride & 1) dst[i] = BGOBJLine[i]; } break; @@ -1313,12 +1335,6 @@ void GPU2D::DrawScanlineBGMode(u32 line) void GPU2D::DrawScanlineBGMode6(u32 line) { - if (Num) - { - printf("GPU2D: MODE6 ON SUB GPU???\n"); - return; - } - for (int i = 3; i >= 0; i--) { if ((BGCnt[2] & 0x3) == i) @@ -1332,8 +1348,36 @@ void GPU2D::DrawScanlineBGMode6(u32 line) { if (DispCnt & 0x0100) { - if (DispCnt & 0x8) + if ((!Num) && (DispCnt & 0x8)) + DrawBG_3D(); + } + } + if ((DispCnt & 0x1000) && NumSprites) + InterleaveSprites(0x8000 | (i<<16)); + } +} + +void GPU2D::DrawScanlineBGMode7(u32 line) +{ + // mode 7 only has text-mode BG0 and BG1 + + for (int i = 3; i >= 0; i--) + { + if ((BGCnt[1] & 0x3) == i) + { + if (DispCnt & 0x0200) + { + DrawBG_Text(line, 1); + } + } + if ((BGCnt[0] & 0x3) == i) + { + if (DispCnt & 0x0100) + { + if ((!Num) && (DispCnt & 0x8)) DrawBG_3D(); + else + DrawBG_Text(line, 0); } } if ((DispCnt & 0x1000) && NumSprites) @@ -1343,6 +1387,15 @@ void GPU2D::DrawScanlineBGMode6(u32 line) void GPU2D::DrawScanline_BGOBJ(u32 line) { + // forced blank disables BG/OBJ compositing + if (DispCnt & (1<<7)) + { + for (int i = 0; i < 256; i++) + BGOBJLine[i] = 0xFF3F3F3F; + + return; + } + u64 backdrop; if (Num) backdrop = *(u16*)&GPU::Palette[0x400]; else backdrop = *(u16*)&GPU::Palette[0]; @@ -1364,7 +1417,6 @@ void GPU2D::DrawScanline_BGOBJ(u32 line) else memset(WindowMask, 0xFF, 256); - // TODO: what happens in mode 7? mode 6 on the sub engine? switch (DispCnt & 0x7) { case 0: DrawScanlineBGMode<0>(line); break; @@ -1374,6 +1426,7 @@ void GPU2D::DrawScanline_BGOBJ(u32 line) case 4: DrawScanlineBGMode<4>(line); break; case 5: DrawScanlineBGMode<5>(line); break; case 6: DrawScanlineBGMode6(line); break; + case 7: DrawScanlineBGMode7(line); break; } // color special effects @@ -2035,14 +2088,19 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2 u32 tilesetaddr, tilemapaddr; u16* pal; + // large BG sizes: + // 0: 512x1024 + // 1: 1024x512 + // 2: 512x256 + // 3: 512x512 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; + case 0x8000: xmask = 0x1FFFF; ymask = 0x0FFFF; yshift = 9; break; + case 0xC000: xmask = 0x1FFFF; ymask = 0x1FFFF; yshift = 9; break; } u32 ofxmask, ofymask; @@ -2134,21 +2192,19 @@ void GPU2D::DrawSprites(u32 line) const s32 spritewidth[16] = { - 8, 16, 8, 0, - 16, 32, 8, 0, - 32, 32, 16, 0, - 64, 64, 32, 0 + 8, 16, 8, 8, + 16, 32, 8, 8, + 32, 32, 16, 8, + 64, 64, 32, 8 }; const s32 spriteheight[16] = { - 8, 8, 16, 0, - 16, 8, 32, 0, - 32, 16, 32, 0, - 64, 32, 64, 0 + 8, 8, 16, 8, + 16, 8, 32, 8, + 32, 16, 32, 8, + 64, 32, 64, 8 }; - u32 nsprites = 0; - for (int bgnum = 0x0C00; bgnum >= 0x0000; bgnum -= 0x0400) { for (int sprnum = 127; sprnum >= 0; sprnum--) @@ -2287,8 +2343,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 { if (DispCnt & 0x20) { - // TODO ("reserved") - printf("bad reserved mode\n"); + // 'reserved' + // draws nothing + + return; } else { @@ -2520,8 +2578,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) { if (DispCnt & 0x20) { - // TODO ("reserved") - printf("bad reserved mode\n"); + // 'reserved' + // draws nothing + + return; } else { |