diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-03-01 21:42:06 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-03-01 21:42:06 +0100 |
commit | 247558a35401e807770d162a5ed30602815d3dfb (patch) | |
tree | 912a2ae18e1fddb47b26c5aeb56cfeb58120b79a | |
parent | 5d9e9a5023b0fe1c822345446267c62a24dc3078 (diff) |
* display capture
* fix bug with bitmap BGs (wrong base offset)
-rw-r--r-- | GPU2D.cpp | 182 | ||||
-rw-r--r-- | GPU2D.h | 6 | ||||
-rw-r--r-- | NDS.cpp | 1 | ||||
-rw-r--r-- | melonDS.depend | 4 |
4 files changed, 185 insertions, 8 deletions
@@ -83,6 +83,8 @@ void GPU2D::Reset() memset(BGRotC, 0, 2*2); memset(BGRotD, 0, 2*2); + CaptureCnt = 0; + MasterBrightness = 0; BGExtPalStatus[0] = 0; @@ -205,6 +207,12 @@ void GPU2D::Write32(u32 addr, u32 val) if (val & 0x08000000) val |= 0xF0000000; BGYCenter[1] = val; return; + + case 0x064: + // TODO: check what happens when writing to it during display + // esp. if a capture is happening + CaptureCnt = val & 0xEF3F1F1F; + return; } Write16(addr, val&0xFFFF); @@ -264,11 +272,27 @@ void GPU2D::DrawScanline(u32 line) case 3: // FIFO display { - // uh, is there even anything that uses this? + // TODO } break; } + // capture + if ((!Num) && (CaptureCnt & (1<<31))) + { + u32 capwidth, capheight; + switch ((CaptureCnt >> 20) & 0x3) + { + case 0: capwidth = 128; capheight = 128; break; + case 1: capwidth = 256; capheight = 64; break; + case 2: capwidth = 256; capheight = 128; break; + case 3: capwidth = 256; capheight = 192; break; + } + + if (line < capheight) + DoCapture(line, capwidth, dst); + } + // master brightness if (dispmode != 0) { @@ -325,7 +349,153 @@ void GPU2D::DrawScanline(u32 line) void GPU2D::VBlank() { - // + CaptureCnt &= ~(1<<31); +} + + +void GPU2D::DoCapture(u32 line, u32 width, u32* src) +{ + u32 dstvram = (CaptureCnt >> 16) & 0x3; + + // TODO: confirm this + // it should work like VRAM display mode, which requires VRAM to be mapped to LCDC + if (!(GPU::VRAMMap_LCDC & (1<<dstvram))) + return; + + u16* dst = (u16*)GPU::VRAM[dstvram]; + u32 dstaddr = (((CaptureCnt >> 18) & 0x3) << 14) + (line * width); + + if (CaptureCnt & (1<<24)) + src = (u32*)GPU3D::GetLine(line); + + u16* srcB = NULL; + u32 srcBaddr = line * 256; + + if (CaptureCnt & (1<<25)) + { + // TODO: FIFO mode + } + else + { + u32 srcvram = (DispCnt >> 18) & 0x3; + if (GPU::VRAMMap_LCDC & (1<<srcvram)) + srcB = (u16*)GPU::VRAM[srcvram]; + + if (((DispCnt >> 16) & 0x3) != 2) + srcBaddr += ((CaptureCnt >> 26) & 0x3) << 14; + } + + dstaddr &= 0xFFFF; + srcBaddr &= 0xFFFF; + + switch ((DispCnt >> 29) & 0x3) + { + case 0: // source A + { + for (u32 i = 0; i < width; i++) + { + u32 val = src[i]; + + // TODO: check what happens when alpha=0 + + u32 r = (val >> 1) & 0x1F; + u32 g = (val >> 9) & 0x1F; + u32 b = (val >> 17) & 0x1F; + u32 a = ((val >> 24) != 0) ? 0x8000 : 0; + + dst[dstaddr] = r | (g << 5) | (b << 10) | a; + dstaddr = (dstaddr + 1) & 0xFFFF; + } + } + break; + + case 1: // source B + { + if (srcB) + { + for (u32 i = 0; i < width; i++) + { + dst[dstaddr] = srcB[srcBaddr]; + srcBaddr = (srcBaddr + 1) & 0xFFFF; + dstaddr = (dstaddr + 1) & 0xFFFF; + } + } + else + { + for (u32 i = 0; i < width; i++) + { + dst[dstaddr] = 0; + dstaddr = (dstaddr + 1) & 0xFFFF; + } + } + } + break; + + case 2: // sources A+B + case 3: + { + u32 eva = DispCnt & 0x1F; + u32 evb = (DispCnt >> 8) & 0x1F; + + // checkme + if (eva > 16) eva = 16; + if (evb > 16) evb = 16; + + if (srcB) + { + for (u32 i = 0; i < width; i++) + { + u32 val = src[i]; + + // TODO: check what happens when alpha=0 + + u32 rA = (val >> 1) & 0x1F; + u32 gA = (val >> 9) & 0x1F; + u32 bA = (val >> 17) & 0x1F; + u32 aA = ((val >> 24) != 0) ? 1 : 0; + + val = srcB[srcBaddr]; + + u32 rB = val & 0x1F; + u32 gB = (val >> 5) & 0x1F; + u32 bB = (val >> 10) & 0x1F; + u32 aB = val >> 15; + + u32 rD = ((rA * aA * eva) + (rB * aB * evb)) >> 4; + u32 gD = ((gA * aA * eva) + (gB * aB * evb)) >> 4; + u32 bD = ((bA * aA * eva) + (bB * aB * evb)) >> 4; + u32 aD = (eva>0 ? aA : 0) | (evb>0 ? aB : 0); + + dst[dstaddr] = rD | (gD << 5) | (bD << 10) | (aD << 15); + srcBaddr = (srcBaddr + 1) & 0xFFFF; + dstaddr = (dstaddr + 1) & 0xFFFF; + } + } + else + { + for (u32 i = 0; i < width; i++) + { + u32 val = src[i]; + + // TODO: check what happens when alpha=0 + + u32 rA = (val >> 1) & 0x1F; + u32 gA = (val >> 9) & 0x1F; + u32 bA = (val >> 17) & 0x1F; + u32 aA = ((val >> 24) != 0) ? 1 : 0; + + u32 rD = (rA * aA * eva) >> 4; + u32 gD = (gA * aA * eva) >> 4; + u32 bD = (bA * aA * eva) >> 4; + u32 aD = (eva>0 ? aA : 0); + + dst[dstaddr] = rD | (gD << 5) | (bD << 10) | (aD << 15); + dstaddr = (dstaddr + 1) & 0xFFFF; + } + } + } + break; + } } @@ -709,8 +879,8 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) { // bitmap modes - if (Num) tilesetaddr = 0x06200000 + ((bgcnt & 0x003C) << 12); - else tilesetaddr = 0x06000000 + ((bgcnt & 0x003C) << 12); + if (Num) tilemapaddr = 0x06200000 + ((bgcnt & 0x1F00) << 6); + else tilemapaddr = 0x06000000 + ((bgcnt & 0x1F00) << 6); coordmask |= 0x7FF; @@ -722,7 +892,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) { if (!((rotX|rotY) & overflowmask)) { - u16 color = GPU::ReadVRAM_BG<u16>(tilesetaddr + (((((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)) << 1)); + u16 color = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)) << 1)); if (color & 0x8000) drawpixelfn(bgnum, &dst[i], color, BlendFunc); @@ -743,7 +913,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) { if (!((rotX|rotY) & overflowmask)) { - u8 color = GPU::ReadVRAM_BG<u8>(tilesetaddr + (((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)); + u8 color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)); if (color) drawpixelfn(bgnum, &dst[i], pal[color], BlendFunc); @@ -63,6 +63,10 @@ private: s16 BGRotD[2]; u32 BlendFunc; + u8 EVA, EVB; + u8 EVY; + + u32 CaptureCnt; u16 MasterBrightness; @@ -84,6 +88,8 @@ private: 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 DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst); + + void DoCapture(u32 line, u32 width, u32* src); }; #endif @@ -1648,6 +1648,7 @@ void ARM9IOWrite32(u32 addr, u32 val) switch (addr) { case 0x04000060: return; + case 0x04000064: GPU::GPU2D_A->Write32(addr, val); return; case 0x040000B0: DMAs[0]->SrcAddr = val; return; case 0x040000B4: DMAs[0]->DstAddr = val; return; diff --git a/melonDS.depend b/melonDS.depend index fe0d65e..0aac391 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -10,7 +10,7 @@ 1481161027 c:\documents\sources\melonds\types.h -1488393021 source:c:\documents\sources\melonds\nds.cpp +1488396811 source:c:\documents\sources\melonds\nds.cpp <stdio.h> <string.h> "NDS.h" @@ -93,7 +93,7 @@ "NDS.h" "GPU.h" -1488392627 c:\documents\sources\melonds\gpu2d.h +1488398363 c:\documents\sources\melonds\gpu2d.h 1481040524 c:\documents\sources\melonds\wifi.h |