diff options
author | StapleButter <thetotalworm@gmail.com> | 2018-12-18 17:04:42 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2018-12-18 17:04:42 +0100 |
commit | dd30b417b817024d48b4e14a23a2b19370e8ff97 (patch) | |
tree | efa6fe0f4a535148826af98dedfd7b538245a6f8 | |
parent | 1b64e871157314def6e82a476ba390d6f341f391 (diff) |
implement proper support for POWCNT1.
fixes #260
-rw-r--r-- | src/GPU.cpp | 19 | ||||
-rw-r--r-- | src/GPU.h | 2 | ||||
-rw-r--r-- | src/GPU2D.cpp | 22 | ||||
-rw-r--r-- | src/GPU2D.h | 2 | ||||
-rw-r--r-- | src/GPU3D.cpp | 107 | ||||
-rw-r--r-- | src/GPU3D.h | 2 | ||||
-rw-r--r-- | src/GPU3D_Soft.cpp | 3 | ||||
-rw-r--r-- | src/NDS.cpp | 27 |
8 files changed, 137 insertions, 47 deletions
diff --git a/src/GPU.cpp b/src/GPU.cpp index aba97a5..ba04c84 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -650,9 +650,23 @@ void MapVRAM_I(u32 bank, u8 cnt) } -void DisplaySwap(u32 val) +void SetPowerCnt(u32 val) { - if (val) + // POWCNT1 effects: + // * bit0: asplodes hardware??? not tested. + // * bit1: disables engine A palette and OAM (zero-filled) (TODO: affects mem timings???) + // * bit2: disables rendering engine, resets its internal state (polygons and registers) + // * bit3: disables geometry engine + // * bit9: disables engine B palette, OAM and rendering (screen turns white) + // * bit15: screen swap + + if (!(val & (1<<0))) printf("!!! CLEARING POWCNT BIT0. DANGER\n"); + + GPU2D_A->SetEnabled(val & (1<<1)); + GPU2D_B->SetEnabled(val & (1<<9)); + GPU3D::SetEnabled(val & (1<<3), val & (1<<2)); + + if (val & (1<<15)) { GPU2D_A->SetFramebuffer(&Framebuffer[256*0]); GPU2D_B->SetFramebuffer(&Framebuffer[256*192]); @@ -838,6 +852,7 @@ void SetVCount(u16 val) // VCount write is delayed until the next scanline // TODO: how does the 3D engine react to VCount writes while it's rendering? + // 3D engine seems to give up on the current frame in that situation, repeating the last two scanlines // TODO: also check the various DMA types that can be involved NextVCount = val; @@ -387,7 +387,7 @@ T ReadVRAM_TexPal(u32 addr) } -void DisplaySwap(u32 val); +void SetPowerCnt(u32 val); void StartFrame(); void FinishFrame(u32 lines); diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 4951404..f7e834d 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -273,6 +273,8 @@ u32 GPU2D::Read32(u32 addr) void GPU2D::Write8(u32 addr, u8 val) { + if (!Enabled) return; + switch (addr & 0x00000FFF) { case 0x000: DispCnt = (DispCnt & 0xFFFFFF00) | val; return; @@ -353,6 +355,8 @@ void GPU2D::Write8(u32 addr, u8 val) void GPU2D::Write16(u32 addr, u16 val) { + if (!Enabled) return; + switch (addr & 0x00000FFF) { case 0x000: DispCnt = (DispCnt & 0xFFFF0000) | val; return; @@ -482,6 +486,8 @@ void GPU2D::Write16(u32 addr, u16 val) void GPU2D::Write32(u32 addr, u32 val) { + if (!Enabled) return; + switch (addr & 0x00000FFF) { case 0x000: @@ -542,19 +548,21 @@ void GPU2D::DrawScanline(u32 line) line = GPU::VCount; + bool forceblank = false; + // scanlines that end up outside of the GPU drawing range // (as a result of writing to VCount) are filled white - if (line > 192) - { - for (int i = 0; i < 256; i++) - dst[i] = 0xFFFFFFFF; + if (line > 192) forceblank = true; - return; - } + // GPU B can be completely disabled by POWCNT1 + // 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)) + if (DispCnt & (1<<7)) forceblank = true; + + if (forceblank) { for (int i = 0; i < 256; i++) dst[i] = 0xFFFFFFFF; diff --git a/src/GPU2D.h b/src/GPU2D.h index 5a1192e..1776680 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -29,6 +29,7 @@ public: void DoSavestate(Savestate* file); + void SetEnabled(bool enable) { Enabled = enable; } void SetFramebuffer(u32* buf); u8 Read8(u32 addr); @@ -64,6 +65,7 @@ public: private: u32 Num; + bool Enabled; u32* Framebuffer; u16 DispFIFO[16]; diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index bc1ab1b..3b69577 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -152,6 +152,9 @@ FIFO<CmdFIFOEntry>* CmdStallQueue; u32 NumCommands, CurCommand, ParamCount, TotalParams; +bool GeometryEnabled; +bool RenderingEnabled; + u32 DispCnt; u8 AlphaRefVal, AlphaRef; @@ -285,6 +288,25 @@ void DeInit() delete CmdStallQueue; } +void ResetRenderingState() +{ + RenderNumPolygons = 0; + + RenderDispCnt = 0; + RenderAlphaRef = 0; + + memset(RenderEdgeTable, 0, 8*2); + memset(RenderToonTable, 0, 32*2); + + RenderFogColor = 0; + RenderFogOffset = 0; + RenderFogShift = 0; + memset(RenderFogDensityTable, 0, 34); + + RenderClearAttr1 = 0x3F000000; + RenderClearAttr2 = 0x00007FFF; +} + void Reset() { CmdFIFO->Clear(); @@ -356,6 +378,7 @@ void Reset() FlushRequest = 0; FlushAttributes = 0; + ResetRenderingState(); SoftRenderer::Reset(); } @@ -556,6 +579,16 @@ void DoSavestate(Savestate* file) +void SetEnabled(bool geometry, bool rendering) +{ + GeometryEnabled = geometry; + RenderingEnabled = rendering; + + if (!rendering) ResetRenderingState(); +} + + + void MatrixLoadIdentity(s32* m) { m[0] = 0x1000; m[1] = 0; m[2] = 0; m[3] = 0; @@ -2213,6 +2246,8 @@ void FinishWork(s32 cycles) void Run(s32 cycles) { + if (!GeometryEnabled) + return; if (FlushRequest) return; if (CmdPIPE->IsEmpty() && !(GXStat & (1<<27))) @@ -2281,46 +2316,49 @@ bool YSort(Polygon* a, Polygon* b) void VBlank() { - if (FlushRequest) + if (GeometryEnabled && FlushRequest) { - if (NumPolygons) + if (RenderingEnabled) { - // separate translucent polygons from opaque ones - - u32 io = 0, it = NumOpaquePolygons; - for (u32 i = 0; i < NumPolygons; i++) + if (NumPolygons) { - Polygon* poly = &CurPolygonRAM[i]; - if (poly->Translucent) - RenderPolygonRAM[it++] = poly; - else - RenderPolygonRAM[io++] = poly; - } + // separate translucent polygons from opaque ones + + u32 io = 0, it = NumOpaquePolygons; + for (u32 i = 0; i < NumPolygons; i++) + { + Polygon* poly = &CurPolygonRAM[i]; + if (poly->Translucent) + RenderPolygonRAM[it++] = poly; + else + RenderPolygonRAM[io++] = poly; + } - // apply Y-sorting + // apply Y-sorting - std::stable_sort(RenderPolygonRAM.begin(), - RenderPolygonRAM.begin() + ((FlushAttributes & 0x1) ? NumOpaquePolygons : NumPolygons), - YSort); - } + std::stable_sort(RenderPolygonRAM.begin(), + RenderPolygonRAM.begin() + ((FlushAttributes & 0x1) ? NumOpaquePolygons : NumPolygons), + YSort); + } - RenderNumPolygons = NumPolygons; + RenderNumPolygons = NumPolygons; - RenderDispCnt = DispCnt; - RenderAlphaRef = AlphaRef; + RenderDispCnt = DispCnt; + RenderAlphaRef = AlphaRef; - memcpy(RenderEdgeTable, EdgeTable, 8*2); - memcpy(RenderToonTable, ToonTable, 32*2); + memcpy(RenderEdgeTable, EdgeTable, 8*2); + memcpy(RenderToonTable, ToonTable, 32*2); - RenderFogColor = FogColor; - RenderFogOffset = FogOffset * 0x200; - RenderFogShift = (RenderDispCnt >> 8) & 0xF; - RenderFogDensityTable[0] = FogDensityTable[0]; - memcpy(&RenderFogDensityTable[1], FogDensityTable, 32); - RenderFogDensityTable[33] = FogDensityTable[31]; + RenderFogColor = FogColor; + RenderFogOffset = FogOffset * 0x200; + RenderFogShift = (RenderDispCnt >> 8) & 0xF; + RenderFogDensityTable[0] = FogDensityTable[0]; + memcpy(&RenderFogDensityTable[1], FogDensityTable, 32); + RenderFogDensityTable[33] = FogDensityTable[31]; - RenderClearAttr1 = ClearAttr1; - RenderClearAttr2 = ClearAttr2; + RenderClearAttr1 = ClearAttr1; + RenderClearAttr2 = ClearAttr2; + } CurRAMBank = CurRAMBank?0:1; CurVertexRAM = &VertexRAM[CurRAMBank ? 6144 : 0]; @@ -2515,6 +2553,9 @@ u32 Read32(u32 addr) void Write8(u32 addr, u8 val) { + if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return; + if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return; + switch (addr) { case 0x04000340: @@ -2550,6 +2591,9 @@ void Write8(u32 addr, u8 val) void Write16(u32 addr, u16 val) { + if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return; + if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return; + switch (addr) { case 0x04000060: @@ -2629,6 +2673,9 @@ void Write16(u32 addr, u16 val) void Write32(u32 addr, u32 val) { + if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return; + if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return; + switch (addr) { case 0x04000060: diff --git a/src/GPU3D.h b/src/GPU3D.h index b74e421..d510d30 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -88,6 +88,8 @@ void Reset(); void DoSavestate(Savestate* file); +void SetEnabled(bool geometry, bool rendering); + void ExecuteCommand(); s32 CyclesToRunFor(); diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index daf5cdd..923348a 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -56,6 +56,8 @@ u32 AttrBuffer[BufferSize * 2]; u8 StencilBuffer[256*2]; bool PrevIsShadowMask; +bool Enabled; + // threading void* RenderThread; @@ -137,6 +139,7 @@ void Reset() } + // Notes on the interpolator: // // This is a theory on how the DS hardware interpolates values. It matches hardware output diff --git a/src/NDS.cpp b/src/NDS.cpp index 07273d7..aa8b1d3 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -363,7 +363,7 @@ void SetupDirectBoot() PostFlag7 = 0x01; PowerControl9 = 0x820F; - GPU::DisplaySwap(PowerControl9); + GPU::SetPowerCnt(PowerControl9); // checkme RCnt = 0x8000; @@ -678,8 +678,6 @@ bool DoSavestate(Savestate* file) if (!file->Saving) { - GPU::DisplaySwap(PowerControl9>>15); - InitTimings(); SetGBASlotTimings(); @@ -698,6 +696,11 @@ bool DoSavestate(Savestate* file) RTC::DoSavestate(file); Wifi::DoSavestate(file); + if (!file->Saving) + { + GPU::SetPowerCnt(PowerControl9); + } + return true; } @@ -1618,6 +1621,7 @@ u8 ARM9Read8(u32 addr) return ARM9IORead8(addr); case 0x05000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; return *(u8*)&GPU::Palette[addr & 0x7FF]; case 0x06000000: @@ -1631,6 +1635,7 @@ u8 ARM9Read8(u32 addr) } case 0x07000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; return *(u8*)&GPU::OAM[addr & 0x7FF]; case 0x08000000: @@ -1677,6 +1682,7 @@ u16 ARM9Read16(u32 addr) return ARM9IORead16(addr); case 0x05000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; return *(u16*)&GPU::Palette[addr & 0x7FF]; case 0x06000000: @@ -1690,6 +1696,7 @@ u16 ARM9Read16(u32 addr) } case 0x07000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; return *(u16*)&GPU::OAM[addr & 0x7FF]; case 0x08000000: @@ -1736,6 +1743,7 @@ u32 ARM9Read32(u32 addr) return ARM9IORead32(addr); case 0x05000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; return *(u32*)&GPU::Palette[addr & 0x7FF]; case 0x06000000: @@ -1749,6 +1757,7 @@ u32 ARM9Read32(u32 addr) } case 0x07000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; return *(u32*)&GPU::OAM[addr & 0x7FF]; case 0x08000000: @@ -1818,6 +1827,7 @@ void ARM9Write16(u32 addr, u16 val) return; case 0x05000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u16*)&GPU::Palette[addr & 0x7FF] = val; return; @@ -1832,6 +1842,7 @@ void ARM9Write16(u32 addr, u16 val) } case 0x07000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u16*)&GPU::OAM[addr & 0x7FF] = val; return; } @@ -1859,6 +1870,7 @@ void ARM9Write32(u32 addr, u32 val) return; case 0x05000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u32*)&GPU::Palette[addr & 0x7FF] = val; return; @@ -1873,6 +1885,7 @@ void ARM9Write32(u32 addr, u32 val) } case 0x07000000: + if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u32*)&GPU::OAM[addr & 0x7FF] = val; return; } @@ -2809,8 +2822,8 @@ void ARM9IOWrite16(u32 addr, u16 val) return; case 0x04000304: - PowerControl9 = val; - GPU::DisplaySwap(PowerControl9>>15); + PowerControl9 = val & 0x820F; + GPU::SetPowerCnt(PowerControl9); return; } @@ -2962,8 +2975,8 @@ void ARM9IOWrite32(u32 addr, u32 val) case 0x040002BC: SqrtVal[1] = val; StartSqrt(); return; case 0x04000304: - PowerControl9 = val & 0xFFFF; - GPU::DisplaySwap(PowerControl9>>15); + PowerControl9 = val & 0x820F; + GPU::SetPowerCnt(PowerControl9); return; } |