mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-23 06:10:03 -06:00
separate GPU2D registers and renderer
This commit is contained in:
66
src/GPU.cpp
66
src/GPU.cpp
@ -82,8 +82,10 @@ int FrontBuffer;
|
|||||||
u32* Framebuffer[2][2];
|
u32* Framebuffer[2][2];
|
||||||
int Renderer = 0;
|
int Renderer = 0;
|
||||||
|
|
||||||
std::unique_ptr<GPU2D> GPU2D_A = {};
|
GPU2D::Unit GPU2D_A(0);
|
||||||
std::unique_ptr<GPU2D> GPU2D_B = {};
|
GPU2D::Unit GPU2D_B(1);
|
||||||
|
|
||||||
|
std::unique_ptr<GPU2D::Renderer2D> GPU2D_Renderer = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
VRAM invalidation tracking
|
VRAM invalidation tracking
|
||||||
@ -143,8 +145,7 @@ std::unique_ptr<GLCompositor> CurGLCompositor = {};
|
|||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
GPU2D_A = std::make_unique<GPU2D_Soft>(0);
|
GPU2D_Renderer = std::make_unique<GPU2D::SoftRenderer>();
|
||||||
GPU2D_B = std::make_unique<GPU2D_Soft>(1);
|
|
||||||
if (!GPU3D::Init()) return false;
|
if (!GPU3D::Init()) return false;
|
||||||
|
|
||||||
FrontBuffer = 0;
|
FrontBuffer = 0;
|
||||||
@ -157,8 +158,7 @@ bool Init()
|
|||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
GPU2D_A.reset();
|
GPU2D_Renderer.reset();
|
||||||
GPU2D_B.reset();
|
|
||||||
GPU3D::DeInit();
|
GPU3D::DeInit();
|
||||||
|
|
||||||
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
||||||
@ -262,13 +262,12 @@ void Reset()
|
|||||||
Framebuffer[1][1][i] = 0xFFFFFFFF;
|
Framebuffer[1][1][i] = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU2D_A->Reset();
|
GPU2D_A.Reset();
|
||||||
GPU2D_B->Reset();
|
GPU2D_B.Reset();
|
||||||
GPU3D::Reset();
|
GPU3D::Reset();
|
||||||
|
|
||||||
int backbuf = FrontBuffer ? 0 : 1;
|
int backbuf = FrontBuffer ? 0 : 1;
|
||||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
|
GPU2D_Renderer->SetFramebuffer(Framebuffer[backbuf][1], Framebuffer[backbuf][0]);
|
||||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
|
|
||||||
|
|
||||||
ResetRenderer();
|
ResetRenderer();
|
||||||
|
|
||||||
@ -358,8 +357,8 @@ void DoSavestate(Savestate* file)
|
|||||||
VRAMPtr_BOBJ[i] = GetUniqueBankPtr(VRAMMap_BOBJ[i], i << 14);
|
VRAMPtr_BOBJ[i] = GetUniqueBankPtr(VRAMMap_BOBJ[i], i << 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU2D_A->DoSavestate(file);
|
GPU2D_A.DoSavestate(file);
|
||||||
GPU2D_B->DoSavestate(file);
|
GPU2D_B.DoSavestate(file);
|
||||||
GPU3D::DoSavestate(file);
|
GPU3D::DoSavestate(file);
|
||||||
|
|
||||||
ResetVRAMCache();
|
ResetVRAMCache();
|
||||||
@ -370,13 +369,11 @@ void AssignFramebuffers()
|
|||||||
int backbuf = FrontBuffer ? 0 : 1;
|
int backbuf = FrontBuffer ? 0 : 1;
|
||||||
if (NDS::PowerControl9 & (1<<15))
|
if (NDS::PowerControl9 & (1<<15))
|
||||||
{
|
{
|
||||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]);
|
GPU2D_Renderer->SetFramebuffer(Framebuffer[backbuf][0], Framebuffer[backbuf][1]);
|
||||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
|
GPU2D_Renderer->SetFramebuffer(Framebuffer[backbuf][1], Framebuffer[backbuf][0]);
|
||||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,8 +970,8 @@ void SetPowerCnt(u32 val)
|
|||||||
|
|
||||||
if (!(val & (1<<0))) printf("!!! CLEARING POWCNT BIT0. DANGER\n");
|
if (!(val & (1<<0))) printf("!!! CLEARING POWCNT BIT0. DANGER\n");
|
||||||
|
|
||||||
GPU2D_A->SetEnabled(val & (1<<1));
|
GPU2D_A.SetEnabled(val & (1<<1));
|
||||||
GPU2D_B->SetEnabled(val & (1<<9));
|
GPU2D_B.SetEnabled(val & (1<<9));
|
||||||
GPU3D::SetEnabled(val & (1<<3), val & (1<<2));
|
GPU3D::SetEnabled(val & (1<<3), val & (1<<2));
|
||||||
|
|
||||||
AssignFramebuffers();
|
AssignFramebuffers();
|
||||||
@ -989,9 +986,9 @@ void DisplayFIFO(u32 x)
|
|||||||
if (x > 0)
|
if (x > 0)
|
||||||
{
|
{
|
||||||
if (x == 8)
|
if (x == 8)
|
||||||
GPU2D_A->SampleFIFO(0, 5);
|
GPU2D_A.SampleFIFO(0, 5);
|
||||||
else
|
else
|
||||||
GPU2D_A->SampleFIFO(x-11, 8);
|
GPU2D_A.SampleFIFO(x-11, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x < 256)
|
if (x < 256)
|
||||||
@ -1001,7 +998,7 @@ void DisplayFIFO(u32 x)
|
|||||||
NDS::ScheduleEvent(NDS::Event_DisplayFIFO, true, 6*8, DisplayFIFO, x+8);
|
NDS::ScheduleEvent(NDS::Event_DisplayFIFO, true, 6*8, DisplayFIFO, x+8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GPU2D_A->SampleFIFO(253, 3); // sample the remaining pixels
|
GPU2D_A.SampleFIFO(253, 3); // sample the remaining pixels
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartFrame()
|
void StartFrame()
|
||||||
@ -1009,7 +1006,7 @@ void StartFrame()
|
|||||||
// only run the display FIFO if needed:
|
// only run the display FIFO if needed:
|
||||||
// * if it is used for display or capture
|
// * if it is used for display or capture
|
||||||
// * if we have display FIFO DMA
|
// * if we have display FIFO DMA
|
||||||
RunFIFO = GPU2D_A->UsesFIFO() || NDS::DMAsInMode(0, 0x04);
|
RunFIFO = GPU2D_A.UsesFIFO() || NDS::DMAsInMode(0, 0x04);
|
||||||
|
|
||||||
TotalScanlines = 0;
|
TotalScanlines = 0;
|
||||||
StartScanline(0);
|
StartScanline(0);
|
||||||
@ -1026,15 +1023,15 @@ void StartHBlank(u32 line)
|
|||||||
// note: this should start 48 cycles after the scanline start
|
// note: this should start 48 cycles after the scanline start
|
||||||
if (line < 192)
|
if (line < 192)
|
||||||
{
|
{
|
||||||
GPU2D_A->DrawScanline(line);
|
GPU2D_Renderer->DrawScanline(line, &GPU2D_A);
|
||||||
GPU2D_B->DrawScanline(line);
|
GPU2D_Renderer->DrawScanline(line, &GPU2D_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sprites are pre-rendered one scanline in advance
|
// sprites are pre-rendered one scanline in advance
|
||||||
if (line < 191)
|
if (line < 191)
|
||||||
{
|
{
|
||||||
GPU2D_A->DrawSprites(line+1);
|
GPU2D_Renderer->DrawSprites(line+1, &GPU2D_A);
|
||||||
GPU2D_B->DrawSprites(line+1);
|
GPU2D_Renderer->DrawSprites(line+1, &GPU2D_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
NDS::CheckDMAs(0, 0x02);
|
NDS::CheckDMAs(0, 0x02);
|
||||||
@ -1045,8 +1042,8 @@ void StartHBlank(u32 line)
|
|||||||
}
|
}
|
||||||
else if (VCount == 262)
|
else if (VCount == 262)
|
||||||
{
|
{
|
||||||
GPU2D_A->DrawSprites(0);
|
GPU2D_Renderer->DrawSprites(0, &GPU2D_A);
|
||||||
GPU2D_B->DrawSprites(0);
|
GPU2D_Renderer->DrawSprites(0, &GPU2D_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DispStat[0] & (1<<4)) NDS::SetIRQ(0, NDS::IRQ_HBlank);
|
if (DispStat[0] & (1<<4)) NDS::SetIRQ(0, NDS::IRQ_HBlank);
|
||||||
@ -1098,8 +1095,8 @@ void StartScanline(u32 line)
|
|||||||
else
|
else
|
||||||
DispStat[1] &= ~(1<<2);
|
DispStat[1] &= ~(1<<2);
|
||||||
|
|
||||||
GPU2D_A->CheckWindows(VCount);
|
GPU2D_A.CheckWindows(VCount);
|
||||||
GPU2D_B->CheckWindows(VCount);
|
GPU2D_B.CheckWindows(VCount);
|
||||||
|
|
||||||
if (VCount >= 2 && VCount < 194)
|
if (VCount >= 2 && VCount < 194)
|
||||||
NDS::CheckDMAs(0, 0x03);
|
NDS::CheckDMAs(0, 0x03);
|
||||||
@ -1110,8 +1107,8 @@ void StartScanline(u32 line)
|
|||||||
{
|
{
|
||||||
if (line == 0)
|
if (line == 0)
|
||||||
{
|
{
|
||||||
GPU2D_A->VBlankEnd();
|
GPU2D_A.VBlankEnd();
|
||||||
GPU2D_B->VBlankEnd();
|
GPU2D_B.VBlankEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RunFIFO)
|
if (RunFIFO)
|
||||||
@ -1149,8 +1146,9 @@ void StartScanline(u32 line)
|
|||||||
if (DispStat[0] & (1<<3)) NDS::SetIRQ(0, NDS::IRQ_VBlank);
|
if (DispStat[0] & (1<<3)) NDS::SetIRQ(0, NDS::IRQ_VBlank);
|
||||||
if (DispStat[1] & (1<<3)) NDS::SetIRQ(1, NDS::IRQ_VBlank);
|
if (DispStat[1] & (1<<3)) NDS::SetIRQ(1, NDS::IRQ_VBlank);
|
||||||
|
|
||||||
GPU2D_A->VBlank();
|
GPU2D_Renderer->VBlankEnd(&GPU2D_A, &GPU2D_B);
|
||||||
GPU2D_B->VBlank();
|
GPU2D_A.VBlank();
|
||||||
|
GPU2D_B.VBlank();
|
||||||
GPU3D::VBlank();
|
GPU3D::VBlank();
|
||||||
|
|
||||||
#ifdef OGLRENDERER_ENABLED
|
#ifdef OGLRENDERER_ENABLED
|
||||||
|
@ -75,8 +75,8 @@ extern u8* VRAMPtr_BOBJ[0x8];
|
|||||||
extern int FrontBuffer;
|
extern int FrontBuffer;
|
||||||
extern u32* Framebuffer[2][2];
|
extern u32* Framebuffer[2][2];
|
||||||
|
|
||||||
extern std::unique_ptr<GPU2D> GPU2D_A;
|
extern GPU2D::Unit GPU2D_A;
|
||||||
extern std::unique_ptr<GPU2D> GPU2D_B;
|
extern GPU2D::Unit GPU2D_B;
|
||||||
|
|
||||||
extern int Renderer;
|
extern int Renderer;
|
||||||
|
|
||||||
|
@ -80,13 +80,15 @@
|
|||||||
// for example these aren't affected by POWCNT GPU-disable bits.
|
// for example these aren't affected by POWCNT GPU-disable bits.
|
||||||
// to model the hardware more accurately, the relevant logic should be moved to GPU.cpp.
|
// to model the hardware more accurately, the relevant logic should be moved to GPU.cpp.
|
||||||
|
|
||||||
|
namespace GPU2D
|
||||||
|
{
|
||||||
|
|
||||||
GPU2D::GPU2D(u32 num)
|
Unit::Unit(u32 num)
|
||||||
{
|
{
|
||||||
Num = num;
|
Num = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::Reset()
|
void Unit::Reset()
|
||||||
{
|
{
|
||||||
Enabled = false;
|
Enabled = false;
|
||||||
DispCnt = 0;
|
DispCnt = 0;
|
||||||
@ -134,11 +136,9 @@ void GPU2D::Reset()
|
|||||||
CaptureLatch = false;
|
CaptureLatch = false;
|
||||||
|
|
||||||
MasterBrightness = 0;
|
MasterBrightness = 0;
|
||||||
|
|
||||||
MosaicXSizeChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::DoSavestate(Savestate* file)
|
void Unit::DoSavestate(Savestate* file)
|
||||||
{
|
{
|
||||||
file->Section((char*)(Num ? "GP2B" : "GP2A"));
|
file->Section((char*)(Num ? "GP2B" : "GP2A"));
|
||||||
|
|
||||||
@ -187,16 +187,9 @@ void GPU2D::DoSavestate(Savestate* file)
|
|||||||
|
|
||||||
file->Var32(&Win0Active);
|
file->Var32(&Win0Active);
|
||||||
file->Var32(&Win1Active);
|
file->Var32(&Win1Active);
|
||||||
|
|
||||||
MosaicXSizeChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::SetFramebuffer(u32* buf)
|
u8 Unit::Read8(u32 addr)
|
||||||
{
|
|
||||||
Framebuffer = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 GPU2D::Read8(u32 addr)
|
|
||||||
{
|
{
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
@ -229,7 +222,7 @@ u8 GPU2D::Read8(u32 addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 GPU2D::Read16(u32 addr)
|
u16 Unit::Read16(u32 addr)
|
||||||
{
|
{
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
@ -258,7 +251,7 @@ u16 GPU2D::Read16(u32 addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GPU2D::Read32(u32 addr)
|
u32 Unit::Read32(u32 addr)
|
||||||
{
|
{
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
@ -270,7 +263,7 @@ u32 GPU2D::Read32(u32 addr)
|
|||||||
return Read16(addr) | (Read16(addr+2) << 16);
|
return Read16(addr) | (Read16(addr+2) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::Write8(u32 addr, u8 val)
|
void Unit::Write8(u32 addr, u8 val)
|
||||||
{
|
{
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
@ -347,12 +340,10 @@ void GPU2D::Write8(u32 addr, u8 val)
|
|||||||
case 0x04C:
|
case 0x04C:
|
||||||
BGMosaicSize[0] = val & 0xF;
|
BGMosaicSize[0] = val & 0xF;
|
||||||
BGMosaicSize[1] = val >> 4;
|
BGMosaicSize[1] = val >> 4;
|
||||||
MosaicXSizeChanged();
|
|
||||||
return;
|
return;
|
||||||
case 0x04D:
|
case 0x04D:
|
||||||
OBJMosaicSize[0] = val & 0xF;
|
OBJMosaicSize[0] = val & 0xF;
|
||||||
OBJMosaicSize[1] = val >> 4;
|
OBJMosaicSize[1] = val >> 4;
|
||||||
MosaicXSizeChanged();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x050: BlendCnt = (BlendCnt & 0x3F00) | val; return;
|
case 0x050: BlendCnt = (BlendCnt & 0x3F00) | val; return;
|
||||||
@ -376,7 +367,7 @@ void GPU2D::Write8(u32 addr, u8 val)
|
|||||||
printf("unknown GPU write8 %08X %02X\n", addr, val);
|
printf("unknown GPU write8 %08X %02X\n", addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::Write16(u32 addr, u16 val)
|
void Unit::Write16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
@ -501,7 +492,6 @@ void GPU2D::Write16(u32 addr, u16 val)
|
|||||||
BGMosaicSize[1] = (val >> 4) & 0xF;
|
BGMosaicSize[1] = (val >> 4) & 0xF;
|
||||||
OBJMosaicSize[0] = (val >> 8) & 0xF;
|
OBJMosaicSize[0] = (val >> 8) & 0xF;
|
||||||
OBJMosaicSize[1] = val >> 12;
|
OBJMosaicSize[1] = val >> 12;
|
||||||
MosaicXSizeChanged();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x050: BlendCnt = val & 0x3FFF; return;
|
case 0x050: BlendCnt = val & 0x3FFF; return;
|
||||||
@ -521,7 +511,7 @@ void GPU2D::Write16(u32 addr, u16 val)
|
|||||||
//printf("unknown GPU write16 %08X %04X\n", addr, val);
|
//printf("unknown GPU write16 %08X %04X\n", addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::Write32(u32 addr, u32 val)
|
void Unit::Write32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
@ -575,7 +565,7 @@ void GPU2D::Write32(u32 addr, u32 val)
|
|||||||
Write16(addr+2, val>>16);
|
Write16(addr+2, val>>16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::UpdateMosaicCounters(u32 line)
|
void Unit::UpdateMosaicCounters(u32 line)
|
||||||
{
|
{
|
||||||
// Y mosaic uses incrementing 4-bit counters
|
// Y mosaic uses incrementing 4-bit counters
|
||||||
// the transformed Y position is updated every time the counter matches the MOSAIC register
|
// the transformed Y position is updated every time the counter matches the MOSAIC register
|
||||||
@ -592,7 +582,7 @@ void GPU2D::UpdateMosaicCounters(u32 line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::VBlank()
|
void Unit::VBlank()
|
||||||
{
|
{
|
||||||
if (CaptureLatch)
|
if (CaptureLatch)
|
||||||
{
|
{
|
||||||
@ -604,7 +594,7 @@ void GPU2D::VBlank()
|
|||||||
DispFIFOWritePtr = 0;
|
DispFIFOWritePtr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::VBlankEnd()
|
void Unit::VBlankEnd()
|
||||||
{
|
{
|
||||||
// TODO: find out the exact time this happens
|
// TODO: find out the exact time this happens
|
||||||
BGXRefInternal[0] = BGXRef[0];
|
BGXRefInternal[0] = BGXRef[0];
|
||||||
@ -620,7 +610,7 @@ void GPU2D::VBlankEnd()
|
|||||||
//OBJMosaicYCount = 0;
|
//OBJMosaicYCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::SampleFIFO(u32 offset, u32 num)
|
void Unit::SampleFIFO(u32 offset, u32 num)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < num; i++)
|
for (u32 i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
@ -632,7 +622,7 @@ void GPU2D::SampleFIFO(u32 offset, u32 num)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u16* GPU2D::GetBGExtPal(u32 slot, u32 pal)
|
u16* Unit::GetBGExtPal(u32 slot, u32 pal)
|
||||||
{
|
{
|
||||||
const u32 PaletteSize = 256 * 2;
|
const u32 PaletteSize = 256 * 2;
|
||||||
const u32 SlotSize = PaletteSize * 16;
|
const u32 SlotSize = PaletteSize * 16;
|
||||||
@ -641,14 +631,14 @@ u16* GPU2D::GetBGExtPal(u32 slot, u32 pal)
|
|||||||
: GPU::VRAMFlat_BBGExtPal)[slot * SlotSize + pal * PaletteSize];
|
: GPU::VRAMFlat_BBGExtPal)[slot * SlotSize + pal * PaletteSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
u16* GPU2D::GetOBJExtPal()
|
u16* Unit::GetOBJExtPal()
|
||||||
{
|
{
|
||||||
return Num == 0
|
return Num == 0
|
||||||
? (u16*)GPU::VRAMFlat_AOBJExtPal
|
? (u16*)GPU::VRAMFlat_AOBJExtPal
|
||||||
: (u16*)GPU::VRAMFlat_BOBJExtPal;
|
: (u16*)GPU::VRAMFlat_BOBJExtPal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::CheckWindows(u32 line)
|
void Unit::CheckWindows(u32 line)
|
||||||
{
|
{
|
||||||
line &= 0xFF;
|
line &= 0xFF;
|
||||||
if (line == Win0Coords[3]) Win0Active &= ~0x1;
|
if (line == Win0Coords[3]) Win0Active &= ~0x1;
|
||||||
@ -657,18 +647,18 @@ void GPU2D::CheckWindows(u32 line)
|
|||||||
else if (line == Win1Coords[2]) Win1Active |= 0x1;
|
else if (line == Win1Coords[2]) Win1Active |= 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::CalculateWindowMask(u32 line)
|
void Unit::CalculateWindowMask(u32 line, u8* windowMask, u8* objWindow)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < 256; i++)
|
for (u32 i = 0; i < 256; i++)
|
||||||
WindowMask[i] = WinCnt[2]; // window outside
|
windowMask[i] = WinCnt[2]; // window outside
|
||||||
|
|
||||||
if (DispCnt & (1<<15))
|
if (DispCnt & (1<<15))
|
||||||
{
|
{
|
||||||
// OBJ window
|
// OBJ window
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
if (OBJWindow[i])
|
if (objWindow[i])
|
||||||
WindowMask[i] = WinCnt[3];
|
windowMask[i] = WinCnt[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,7 +673,7 @@ void GPU2D::CalculateWindowMask(u32 line)
|
|||||||
if (i == x2) Win1Active &= ~0x2;
|
if (i == x2) Win1Active &= ~0x2;
|
||||||
else if (i == x1) Win1Active |= 0x2;
|
else if (i == x1) Win1Active |= 0x2;
|
||||||
|
|
||||||
if (Win1Active == 0x3) WindowMask[i] = WinCnt[1];
|
if (Win1Active == 0x3) windowMask[i] = WinCnt[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,12 +688,12 @@ void GPU2D::CalculateWindowMask(u32 line)
|
|||||||
if (i == x2) Win0Active &= ~0x2;
|
if (i == x2) Win0Active &= ~0x2;
|
||||||
else if (i == x1) Win0Active |= 0x2;
|
else if (i == x1) Win0Active |= 0x2;
|
||||||
|
|
||||||
if (Win0Active == 0x3) WindowMask[i] = WinCnt[0];
|
if (Win0Active == 0x3) windowMask[i] = WinCnt[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::GetBGVRAM(u8*& data, u32& mask)
|
void Unit::GetBGVRAM(u8*& data, u32& mask)
|
||||||
{
|
{
|
||||||
if (Num == 0)
|
if (Num == 0)
|
||||||
{
|
{
|
||||||
@ -717,7 +707,7 @@ void GPU2D::GetBGVRAM(u8*& data, u32& mask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU2D::GetOBJVRAM(u8*& data, u32& mask)
|
void Unit::GetOBJVRAM(u8*& data, u32& mask)
|
||||||
{
|
{
|
||||||
if (Num == 0)
|
if (Num == 0)
|
||||||
{
|
{
|
||||||
@ -730,3 +720,5 @@ void GPU2D::GetOBJVRAM(u8*& data, u32& mask)
|
|||||||
mask = 0x1FFFF;
|
mask = 0x1FFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
51
src/GPU2D.h
51
src/GPU2D.h
@ -22,21 +22,22 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Savestate.h"
|
#include "Savestate.h"
|
||||||
|
|
||||||
class GPU2D
|
namespace GPU2D
|
||||||
|
{
|
||||||
|
|
||||||
|
class Unit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPU2D(u32 num);
|
Unit(u32 num);
|
||||||
virtual ~GPU2D() {}
|
|
||||||
|
|
||||||
GPU2D(const GPU2D&) = delete;
|
Unit(const Unit&) = delete;
|
||||||
GPU2D& operator=(const GPU2D&) = delete;
|
Unit& operator=(const Unit&) = delete;
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void DoSavestate(Savestate* file);
|
void DoSavestate(Savestate* file);
|
||||||
|
|
||||||
void SetEnabled(bool enable) { Enabled = enable; }
|
void SetEnabled(bool enable) { Enabled = enable; }
|
||||||
void SetFramebuffer(u32* buf);
|
|
||||||
|
|
||||||
u8 Read8(u32 addr);
|
u8 Read8(u32 addr);
|
||||||
u16 Read16(u32 addr);
|
u16 Read16(u32 addr);
|
||||||
@ -57,8 +58,6 @@ public:
|
|||||||
|
|
||||||
void SampleFIFO(u32 offset, u32 num);
|
void SampleFIFO(u32 offset, u32 num);
|
||||||
|
|
||||||
virtual void DrawScanline(u32 line) = 0;
|
|
||||||
virtual void DrawSprites(u32 line) = 0;
|
|
||||||
void VBlank();
|
void VBlank();
|
||||||
virtual void VBlankEnd();
|
virtual void VBlankEnd();
|
||||||
|
|
||||||
@ -70,10 +69,11 @@ public:
|
|||||||
void GetBGVRAM(u8*& data, u32& mask);
|
void GetBGVRAM(u8*& data, u32& mask);
|
||||||
void GetOBJVRAM(u8*& data, u32& mask);
|
void GetOBJVRAM(u8*& data, u32& mask);
|
||||||
|
|
||||||
protected:
|
void UpdateMosaicCounters(u32 line);
|
||||||
|
void CalculateWindowMask(u32 line, u8* windowMask, u8* objWindow);
|
||||||
|
|
||||||
u32 Num;
|
u32 Num;
|
||||||
bool Enabled;
|
bool Enabled;
|
||||||
u32* Framebuffer;
|
|
||||||
|
|
||||||
u16 DispFIFO[16];
|
u16 DispFIFO[16];
|
||||||
u32 DispFIFOReadPtr;
|
u32 DispFIFOReadPtr;
|
||||||
@ -116,14 +116,29 @@ protected:
|
|||||||
u32 CaptureCnt;
|
u32 CaptureCnt;
|
||||||
|
|
||||||
u16 MasterBrightness;
|
u16 MasterBrightness;
|
||||||
|
|
||||||
alignas(8) u8 WindowMask[256];
|
|
||||||
alignas(8) u8 OBJWindow[256];
|
|
||||||
|
|
||||||
void UpdateMosaicCounters(u32 line);
|
|
||||||
void CalculateWindowMask(u32 line);
|
|
||||||
|
|
||||||
virtual void MosaicXSizeChanged() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Renderer2D
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Renderer2D() {}
|
||||||
|
|
||||||
|
virtual void DrawScanline(u32 line, Unit* unit) = 0;
|
||||||
|
virtual void DrawSprites(u32 line, Unit* unit) = 0;
|
||||||
|
|
||||||
|
virtual void VBlankEnd(Unit* unitA, Unit* unitB) = 0;
|
||||||
|
|
||||||
|
void SetFramebuffer(u32* unitA, u32* unitB)
|
||||||
|
{
|
||||||
|
Framebuffer[0] = unitA;
|
||||||
|
Framebuffer[1] = unitB;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
u32* Framebuffer[2];
|
||||||
|
|
||||||
|
Unit* CurUnit;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,32 +20,32 @@
|
|||||||
|
|
||||||
#include "GPU2D.h"
|
#include "GPU2D.h"
|
||||||
|
|
||||||
class GPU2D_Soft : public GPU2D
|
namespace GPU2D
|
||||||
|
{
|
||||||
|
|
||||||
|
class SoftRenderer : public Renderer2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPU2D_Soft(u32 num);
|
SoftRenderer();
|
||||||
~GPU2D_Soft() override {}
|
~SoftRenderer() override {}
|
||||||
|
|
||||||
void DrawScanline(u32 line) override;
|
|
||||||
void DrawSprites(u32 line) override;
|
|
||||||
void VBlankEnd() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void MosaicXSizeChanged() override;
|
|
||||||
|
|
||||||
|
void DrawScanline(u32 line, Unit* unit) override;
|
||||||
|
void DrawSprites(u32 line, Unit* unit) override;
|
||||||
|
void VBlankEnd(Unit* unitA, Unit* unitB) override;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
alignas(8) u32 BGOBJLine[256*3];
|
alignas(8) u32 BGOBJLine[256*3];
|
||||||
u32* _3DLine;
|
u32* _3DLine;
|
||||||
|
|
||||||
alignas(8) u32 OBJLine[256];
|
alignas(8) u8 WindowMask[256];
|
||||||
alignas(8) u8 OBJIndex[256];
|
|
||||||
|
|
||||||
u32 NumSprites;
|
alignas(8) u32 OBJLine[2][256];
|
||||||
|
alignas(8) u8 OBJIndex[2][256];
|
||||||
|
alignas(8) u8 OBJWindow[2][256];
|
||||||
|
|
||||||
|
u32 NumSprites[2];
|
||||||
|
|
||||||
u8 MosaicTable[16][256];
|
|
||||||
u8* CurBGXMosaicTable;
|
u8* CurBGXMosaicTable;
|
||||||
u8* CurOBJXMosaicTable;
|
u8 MosaicTable[16][256];
|
||||||
|
|
||||||
u32 ColorBlend4(u32 val1, u32 val2, u32 eva, u32 evb);
|
u32 ColorBlend4(u32 val1, u32 val2, u32 eva, u32 evb);
|
||||||
u32 ColorBlend5(u32 val1, u32 val2);
|
u32 ColorBlend5(u32 val1, u32 val2);
|
||||||
@ -76,4 +76,6 @@ private:
|
|||||||
template<bool window> void DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos);
|
template<bool window> void DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos);
|
||||||
|
|
||||||
void DoCapture(u32 line, u32 width);
|
void DoCapture(u32 line, u32 width);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
44
src/NDS.cpp
44
src/NDS.cpp
@ -2882,11 +2882,11 @@ u8 ARM9IORead8(u32 addr)
|
|||||||
|
|
||||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||||
{
|
{
|
||||||
return GPU::GPU2D_A->Read8(addr);
|
return GPU::GPU2D_A.Read8(addr);
|
||||||
}
|
}
|
||||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||||
{
|
{
|
||||||
return GPU::GPU2D_B->Read8(addr);
|
return GPU::GPU2D_B.Read8(addr);
|
||||||
}
|
}
|
||||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||||
{
|
{
|
||||||
@ -2906,7 +2906,7 @@ u16 ARM9IORead16(u32 addr)
|
|||||||
|
|
||||||
case 0x04000060: return GPU3D::Read16(addr);
|
case 0x04000060: return GPU3D::Read16(addr);
|
||||||
case 0x04000064:
|
case 0x04000064:
|
||||||
case 0x04000066: return GPU::GPU2D_A->Read16(addr);
|
case 0x04000066: return GPU::GPU2D_A.Read16(addr);
|
||||||
|
|
||||||
case 0x040000B8: return DMAs[0]->Cnt & 0xFFFF;
|
case 0x040000B8: return DMAs[0]->Cnt & 0xFFFF;
|
||||||
case 0x040000BA: return DMAs[0]->Cnt >> 16;
|
case 0x040000BA: return DMAs[0]->Cnt >> 16;
|
||||||
@ -3004,11 +3004,11 @@ u16 ARM9IORead16(u32 addr)
|
|||||||
|
|
||||||
if ((addr >= 0x04000000 && addr < 0x04000060) || (addr == 0x0400006C))
|
if ((addr >= 0x04000000 && addr < 0x04000060) || (addr == 0x0400006C))
|
||||||
{
|
{
|
||||||
return GPU::GPU2D_A->Read16(addr);
|
return GPU::GPU2D_A.Read16(addr);
|
||||||
}
|
}
|
||||||
if ((addr >= 0x04001000 && addr < 0x04001060) || (addr == 0x0400106C))
|
if ((addr >= 0x04001000 && addr < 0x04001060) || (addr == 0x0400106C))
|
||||||
{
|
{
|
||||||
return GPU::GPU2D_B->Read16(addr);
|
return GPU::GPU2D_B.Read16(addr);
|
||||||
}
|
}
|
||||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||||
{
|
{
|
||||||
@ -3026,7 +3026,7 @@ u32 ARM9IORead32(u32 addr)
|
|||||||
case 0x04000004: return GPU::DispStat[0] | (GPU::VCount << 16);
|
case 0x04000004: return GPU::DispStat[0] | (GPU::VCount << 16);
|
||||||
|
|
||||||
case 0x04000060: return GPU3D::Read32(addr);
|
case 0x04000060: return GPU3D::Read32(addr);
|
||||||
case 0x04000064: return GPU::GPU2D_A->Read32(addr);
|
case 0x04000064: return GPU::GPU2D_A.Read32(addr);
|
||||||
|
|
||||||
case 0x040000B0: return DMAs[0]->SrcAddr;
|
case 0x040000B0: return DMAs[0]->SrcAddr;
|
||||||
case 0x040000B4: return DMAs[0]->DstAddr;
|
case 0x040000B4: return DMAs[0]->DstAddr;
|
||||||
@ -3124,11 +3124,11 @@ u32 ARM9IORead32(u32 addr)
|
|||||||
|
|
||||||
if ((addr >= 0x04000000 && addr < 0x04000060) || (addr == 0x0400006C))
|
if ((addr >= 0x04000000 && addr < 0x04000060) || (addr == 0x0400006C))
|
||||||
{
|
{
|
||||||
return GPU::GPU2D_A->Read32(addr);
|
return GPU::GPU2D_A.Read32(addr);
|
||||||
}
|
}
|
||||||
if ((addr >= 0x04001000 && addr < 0x04001060) || (addr == 0x0400106C))
|
if ((addr >= 0x04001000 && addr < 0x04001060) || (addr == 0x0400106C))
|
||||||
{
|
{
|
||||||
return GPU::GPU2D_B->Read32(addr);
|
return GPU::GPU2D_B.Read32(addr);
|
||||||
}
|
}
|
||||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||||
{
|
{
|
||||||
@ -3144,9 +3144,9 @@ void ARM9IOWrite8(u32 addr, u8 val)
|
|||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x0400006C:
|
case 0x0400006C:
|
||||||
case 0x0400006D: GPU::GPU2D_A->Write8(addr, val); return;
|
case 0x0400006D: GPU::GPU2D_A.Write8(addr, val); return;
|
||||||
case 0x0400106C:
|
case 0x0400106C:
|
||||||
case 0x0400106D: GPU::GPU2D_B->Write8(addr, val); return;
|
case 0x0400106D: GPU::GPU2D_B.Write8(addr, val); return;
|
||||||
|
|
||||||
case 0x04000132:
|
case 0x04000132:
|
||||||
KeyCnt = (KeyCnt & 0xFF00) | val;
|
KeyCnt = (KeyCnt & 0xFF00) | val;
|
||||||
@ -3205,12 +3205,12 @@ void ARM9IOWrite8(u32 addr, u8 val)
|
|||||||
|
|
||||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||||
{
|
{
|
||||||
GPU::GPU2D_A->Write8(addr, val);
|
GPU::GPU2D_A.Write8(addr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||||
{
|
{
|
||||||
GPU::GPU2D_B->Write8(addr, val);
|
GPU::GPU2D_B.Write8(addr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||||
@ -3232,10 +3232,10 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||||||
case 0x04000060: GPU3D::Write16(addr, val); return;
|
case 0x04000060: GPU3D::Write16(addr, val); return;
|
||||||
|
|
||||||
case 0x04000068:
|
case 0x04000068:
|
||||||
case 0x0400006A: GPU::GPU2D_A->Write16(addr, val); return;
|
case 0x0400006A: GPU::GPU2D_A.Write16(addr, val); return;
|
||||||
|
|
||||||
case 0x0400006C: GPU::GPU2D_A->Write16(addr, val); return;
|
case 0x0400006C: GPU::GPU2D_A.Write16(addr, val); return;
|
||||||
case 0x0400106C: GPU::GPU2D_B->Write16(addr, val); return;
|
case 0x0400106C: GPU::GPU2D_B.Write16(addr, val); return;
|
||||||
|
|
||||||
case 0x040000B8: DMAs[0]->WriteCnt((DMAs[0]->Cnt & 0xFFFF0000) | val); return;
|
case 0x040000B8: DMAs[0]->WriteCnt((DMAs[0]->Cnt & 0xFFFF0000) | val); return;
|
||||||
case 0x040000BA: DMAs[0]->WriteCnt((DMAs[0]->Cnt & 0x0000FFFF) | (val << 16)); return;
|
case 0x040000BA: DMAs[0]->WriteCnt((DMAs[0]->Cnt & 0x0000FFFF) | (val << 16)); return;
|
||||||
@ -3371,12 +3371,12 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||||||
|
|
||||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||||
{
|
{
|
||||||
GPU::GPU2D_A->Write16(addr, val);
|
GPU::GPU2D_A.Write16(addr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||||
{
|
{
|
||||||
GPU::GPU2D_B->Write16(addr, val);
|
GPU::GPU2D_B.Write16(addr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||||
@ -3399,10 +3399,10 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||||||
|
|
||||||
case 0x04000060: GPU3D::Write32(addr, val); return;
|
case 0x04000060: GPU3D::Write32(addr, val); return;
|
||||||
case 0x04000064:
|
case 0x04000064:
|
||||||
case 0x04000068: GPU::GPU2D_A->Write32(addr, val); return;
|
case 0x04000068: GPU::GPU2D_A.Write32(addr, val); return;
|
||||||
|
|
||||||
case 0x0400006C: GPU::GPU2D_A->Write16(addr, val&0xFFFF); return;
|
case 0x0400006C: GPU::GPU2D_A.Write16(addr, val&0xFFFF); return;
|
||||||
case 0x0400106C: GPU::GPU2D_B->Write16(addr, val&0xFFFF); return;
|
case 0x0400106C: GPU::GPU2D_B.Write16(addr, val&0xFFFF); return;
|
||||||
|
|
||||||
case 0x040000B0: DMAs[0]->SrcAddr = val; return;
|
case 0x040000B0: DMAs[0]->SrcAddr = val; return;
|
||||||
case 0x040000B4: DMAs[0]->DstAddr = val; return;
|
case 0x040000B4: DMAs[0]->DstAddr = val; return;
|
||||||
@ -3534,12 +3534,12 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||||||
|
|
||||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||||
{
|
{
|
||||||
GPU::GPU2D_A->Write32(addr, val);
|
GPU::GPU2D_A.Write32(addr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||||
{
|
{
|
||||||
GPU::GPU2D_B->Write32(addr, val);
|
GPU::GPU2D_B.Write32(addr, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||||
|
Reference in New Issue
Block a user