parent
1b64e87115
commit
dd30b417b8
19
src/GPU.cpp
19
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_A->SetFramebuffer(&Framebuffer[256*0]);
|
||||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*192]);
|
GPU2D_B->SetFramebuffer(&Framebuffer[256*192]);
|
||||||
|
@ -838,6 +852,7 @@ void SetVCount(u16 val)
|
||||||
// VCount write is delayed until the next scanline
|
// VCount write is delayed until the next scanline
|
||||||
|
|
||||||
// TODO: how does the 3D engine react to VCount writes while it's rendering?
|
// 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
|
// TODO: also check the various DMA types that can be involved
|
||||||
|
|
||||||
NextVCount = val;
|
NextVCount = val;
|
||||||
|
|
|
@ -387,7 +387,7 @@ T ReadVRAM_TexPal(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DisplaySwap(u32 val);
|
void SetPowerCnt(u32 val);
|
||||||
|
|
||||||
void StartFrame();
|
void StartFrame();
|
||||||
void FinishFrame(u32 lines);
|
void FinishFrame(u32 lines);
|
||||||
|
|
|
@ -273,6 +273,8 @@ u32 GPU2D::Read32(u32 addr)
|
||||||
|
|
||||||
void GPU2D::Write8(u32 addr, u8 val)
|
void GPU2D::Write8(u32 addr, u8 val)
|
||||||
{
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
case 0x000: DispCnt = (DispCnt & 0xFFFFFF00) | val; return;
|
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)
|
void GPU2D::Write16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
case 0x000: DispCnt = (DispCnt & 0xFFFF0000) | val; return;
|
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)
|
void GPU2D::Write32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
case 0x000:
|
case 0x000:
|
||||||
|
@ -542,19 +548,21 @@ void GPU2D::DrawScanline(u32 line)
|
||||||
|
|
||||||
line = GPU::VCount;
|
line = GPU::VCount;
|
||||||
|
|
||||||
|
bool forceblank = false;
|
||||||
|
|
||||||
// scanlines that end up outside of the GPU drawing range
|
// scanlines that end up outside of the GPU drawing range
|
||||||
// (as a result of writing to VCount) are filled white
|
// (as a result of writing to VCount) are filled white
|
||||||
if (line > 192)
|
if (line > 192) forceblank = true;
|
||||||
{
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
dst[i] = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
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
|
// forced blank
|
||||||
// (checkme: are there still things that can run under this mode? likely not)
|
// (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++)
|
for (int i = 0; i < 256; i++)
|
||||||
dst[i] = 0xFFFFFFFF;
|
dst[i] = 0xFFFFFFFF;
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
|
|
||||||
void DoSavestate(Savestate* file);
|
void DoSavestate(Savestate* file);
|
||||||
|
|
||||||
|
void SetEnabled(bool enable) { Enabled = enable; }
|
||||||
void SetFramebuffer(u32* buf);
|
void SetFramebuffer(u32* buf);
|
||||||
|
|
||||||
u8 Read8(u32 addr);
|
u8 Read8(u32 addr);
|
||||||
|
@ -64,6 +65,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 Num;
|
u32 Num;
|
||||||
|
bool Enabled;
|
||||||
u32* Framebuffer;
|
u32* Framebuffer;
|
||||||
|
|
||||||
u16 DispFIFO[16];
|
u16 DispFIFO[16];
|
||||||
|
|
|
@ -152,6 +152,9 @@ FIFO<CmdFIFOEntry>* CmdStallQueue;
|
||||||
|
|
||||||
u32 NumCommands, CurCommand, ParamCount, TotalParams;
|
u32 NumCommands, CurCommand, ParamCount, TotalParams;
|
||||||
|
|
||||||
|
bool GeometryEnabled;
|
||||||
|
bool RenderingEnabled;
|
||||||
|
|
||||||
u32 DispCnt;
|
u32 DispCnt;
|
||||||
u8 AlphaRefVal, AlphaRef;
|
u8 AlphaRefVal, AlphaRef;
|
||||||
|
|
||||||
|
@ -285,6 +288,25 @@ void DeInit()
|
||||||
delete CmdStallQueue;
|
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()
|
void Reset()
|
||||||
{
|
{
|
||||||
CmdFIFO->Clear();
|
CmdFIFO->Clear();
|
||||||
|
@ -356,6 +378,7 @@ void Reset()
|
||||||
FlushRequest = 0;
|
FlushRequest = 0;
|
||||||
FlushAttributes = 0;
|
FlushAttributes = 0;
|
||||||
|
|
||||||
|
ResetRenderingState();
|
||||||
SoftRenderer::Reset();
|
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)
|
void MatrixLoadIdentity(s32* m)
|
||||||
{
|
{
|
||||||
m[0] = 0x1000; m[1] = 0; m[2] = 0; m[3] = 0;
|
m[0] = 0x1000; m[1] = 0; m[2] = 0; m[3] = 0;
|
||||||
|
@ -2213,6 +2246,8 @@ void FinishWork(s32 cycles)
|
||||||
|
|
||||||
void Run(s32 cycles)
|
void Run(s32 cycles)
|
||||||
{
|
{
|
||||||
|
if (!GeometryEnabled)
|
||||||
|
return;
|
||||||
if (FlushRequest)
|
if (FlushRequest)
|
||||||
return;
|
return;
|
||||||
if (CmdPIPE->IsEmpty() && !(GXStat & (1<<27)))
|
if (CmdPIPE->IsEmpty() && !(GXStat & (1<<27)))
|
||||||
|
@ -2281,7 +2316,9 @@ bool YSort(Polygon* a, Polygon* b)
|
||||||
|
|
||||||
void VBlank()
|
void VBlank()
|
||||||
{
|
{
|
||||||
if (FlushRequest)
|
if (GeometryEnabled && FlushRequest)
|
||||||
|
{
|
||||||
|
if (RenderingEnabled)
|
||||||
{
|
{
|
||||||
if (NumPolygons)
|
if (NumPolygons)
|
||||||
{
|
{
|
||||||
|
@ -2321,6 +2358,7 @@ void VBlank()
|
||||||
|
|
||||||
RenderClearAttr1 = ClearAttr1;
|
RenderClearAttr1 = ClearAttr1;
|
||||||
RenderClearAttr2 = ClearAttr2;
|
RenderClearAttr2 = ClearAttr2;
|
||||||
|
}
|
||||||
|
|
||||||
CurRAMBank = CurRAMBank?0:1;
|
CurRAMBank = CurRAMBank?0:1;
|
||||||
CurVertexRAM = &VertexRAM[CurRAMBank ? 6144 : 0];
|
CurVertexRAM = &VertexRAM[CurRAMBank ? 6144 : 0];
|
||||||
|
@ -2515,6 +2553,9 @@ u32 Read32(u32 addr)
|
||||||
|
|
||||||
void Write8(u32 addr, u8 val)
|
void Write8(u32 addr, u8 val)
|
||||||
{
|
{
|
||||||
|
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
|
||||||
|
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04000340:
|
case 0x04000340:
|
||||||
|
@ -2550,6 +2591,9 @@ void Write8(u32 addr, u8 val)
|
||||||
|
|
||||||
void Write16(u32 addr, u16 val)
|
void Write16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
|
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
|
||||||
|
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04000060:
|
case 0x04000060:
|
||||||
|
@ -2629,6 +2673,9 @@ void Write16(u32 addr, u16 val)
|
||||||
|
|
||||||
void Write32(u32 addr, u32 val)
|
void Write32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
|
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
|
||||||
|
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04000060:
|
case 0x04000060:
|
||||||
|
|
|
@ -88,6 +88,8 @@ void Reset();
|
||||||
|
|
||||||
void DoSavestate(Savestate* file);
|
void DoSavestate(Savestate* file);
|
||||||
|
|
||||||
|
void SetEnabled(bool geometry, bool rendering);
|
||||||
|
|
||||||
void ExecuteCommand();
|
void ExecuteCommand();
|
||||||
|
|
||||||
s32 CyclesToRunFor();
|
s32 CyclesToRunFor();
|
||||||
|
|
|
@ -56,6 +56,8 @@ u32 AttrBuffer[BufferSize * 2];
|
||||||
u8 StencilBuffer[256*2];
|
u8 StencilBuffer[256*2];
|
||||||
bool PrevIsShadowMask;
|
bool PrevIsShadowMask;
|
||||||
|
|
||||||
|
bool Enabled;
|
||||||
|
|
||||||
// threading
|
// threading
|
||||||
|
|
||||||
void* RenderThread;
|
void* RenderThread;
|
||||||
|
@ -137,6 +139,7 @@ void Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Notes on the interpolator:
|
// Notes on the interpolator:
|
||||||
//
|
//
|
||||||
// This is a theory on how the DS hardware interpolates values. It matches hardware output
|
// This is a theory on how the DS hardware interpolates values. It matches hardware output
|
||||||
|
|
27
src/NDS.cpp
27
src/NDS.cpp
|
@ -363,7 +363,7 @@ void SetupDirectBoot()
|
||||||
PostFlag7 = 0x01;
|
PostFlag7 = 0x01;
|
||||||
|
|
||||||
PowerControl9 = 0x820F;
|
PowerControl9 = 0x820F;
|
||||||
GPU::DisplaySwap(PowerControl9);
|
GPU::SetPowerCnt(PowerControl9);
|
||||||
|
|
||||||
// checkme
|
// checkme
|
||||||
RCnt = 0x8000;
|
RCnt = 0x8000;
|
||||||
|
@ -678,8 +678,6 @@ bool DoSavestate(Savestate* file)
|
||||||
|
|
||||||
if (!file->Saving)
|
if (!file->Saving)
|
||||||
{
|
{
|
||||||
GPU::DisplaySwap(PowerControl9>>15);
|
|
||||||
|
|
||||||
InitTimings();
|
InitTimings();
|
||||||
SetGBASlotTimings();
|
SetGBASlotTimings();
|
||||||
|
|
||||||
|
@ -698,6 +696,11 @@ bool DoSavestate(Savestate* file)
|
||||||
RTC::DoSavestate(file);
|
RTC::DoSavestate(file);
|
||||||
Wifi::DoSavestate(file);
|
Wifi::DoSavestate(file);
|
||||||
|
|
||||||
|
if (!file->Saving)
|
||||||
|
{
|
||||||
|
GPU::SetPowerCnt(PowerControl9);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,6 +1621,7 @@ u8 ARM9Read8(u32 addr)
|
||||||
return ARM9IORead8(addr);
|
return ARM9IORead8(addr);
|
||||||
|
|
||||||
case 0x05000000:
|
case 0x05000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||||
return *(u8*)&GPU::Palette[addr & 0x7FF];
|
return *(u8*)&GPU::Palette[addr & 0x7FF];
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
|
@ -1631,6 +1635,7 @@ u8 ARM9Read8(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x07000000:
|
case 0x07000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||||
return *(u8*)&GPU::OAM[addr & 0x7FF];
|
return *(u8*)&GPU::OAM[addr & 0x7FF];
|
||||||
|
|
||||||
case 0x08000000:
|
case 0x08000000:
|
||||||
|
@ -1677,6 +1682,7 @@ u16 ARM9Read16(u32 addr)
|
||||||
return ARM9IORead16(addr);
|
return ARM9IORead16(addr);
|
||||||
|
|
||||||
case 0x05000000:
|
case 0x05000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||||
return *(u16*)&GPU::Palette[addr & 0x7FF];
|
return *(u16*)&GPU::Palette[addr & 0x7FF];
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
|
@ -1690,6 +1696,7 @@ u16 ARM9Read16(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x07000000:
|
case 0x07000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||||
return *(u16*)&GPU::OAM[addr & 0x7FF];
|
return *(u16*)&GPU::OAM[addr & 0x7FF];
|
||||||
|
|
||||||
case 0x08000000:
|
case 0x08000000:
|
||||||
|
@ -1736,6 +1743,7 @@ u32 ARM9Read32(u32 addr)
|
||||||
return ARM9IORead32(addr);
|
return ARM9IORead32(addr);
|
||||||
|
|
||||||
case 0x05000000:
|
case 0x05000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||||
return *(u32*)&GPU::Palette[addr & 0x7FF];
|
return *(u32*)&GPU::Palette[addr & 0x7FF];
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
|
@ -1749,6 +1757,7 @@ u32 ARM9Read32(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x07000000:
|
case 0x07000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||||
return *(u32*)&GPU::OAM[addr & 0x7FF];
|
return *(u32*)&GPU::OAM[addr & 0x7FF];
|
||||||
|
|
||||||
case 0x08000000:
|
case 0x08000000:
|
||||||
|
@ -1818,6 +1827,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x05000000:
|
case 0x05000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||||
*(u16*)&GPU::Palette[addr & 0x7FF] = val;
|
*(u16*)&GPU::Palette[addr & 0x7FF] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1832,6 +1842,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x07000000:
|
case 0x07000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||||
*(u16*)&GPU::OAM[addr & 0x7FF] = val;
|
*(u16*)&GPU::OAM[addr & 0x7FF] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1859,6 +1870,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x05000000:
|
case 0x05000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||||
*(u32*)&GPU::Palette[addr & 0x7FF] = val;
|
*(u32*)&GPU::Palette[addr & 0x7FF] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1873,6 +1885,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x07000000:
|
case 0x07000000:
|
||||||
|
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||||
*(u32*)&GPU::OAM[addr & 0x7FF] = val;
|
*(u32*)&GPU::OAM[addr & 0x7FF] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2809,8 +2822,8 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x04000304:
|
case 0x04000304:
|
||||||
PowerControl9 = val;
|
PowerControl9 = val & 0x820F;
|
||||||
GPU::DisplaySwap(PowerControl9>>15);
|
GPU::SetPowerCnt(PowerControl9);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2962,8 +2975,8 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
||||||
case 0x040002BC: SqrtVal[1] = val; StartSqrt(); return;
|
case 0x040002BC: SqrtVal[1] = val; StartSqrt(); return;
|
||||||
|
|
||||||
case 0x04000304:
|
case 0x04000304:
|
||||||
PowerControl9 = val & 0xFFFF;
|
PowerControl9 = val & 0x820F;
|
||||||
GPU::DisplaySwap(PowerControl9>>15);
|
GPU::SetPowerCnt(PowerControl9);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue