Refactor the GPU to be object-oriented (#1873)
* Refactor GPU3D to be an object - Who has two thumbs and is the sworn enemy of global state? This guy! * Refactor GPU itself to be an object - Wow, it's used in a lot of places - Also introduce a new `Melon` namespace for a few classes - I expect other classes will be moved into `Melon` over time * Change signature of Renderer3D::SetRenderSettings - Make it noexcept, and its argument const * Remove some stray whitespace
This commit is contained in:
parent
88072a02c5
commit
4558be0d8e
11
src/ARM.cpp
11
src/ARM.cpp
|
@ -109,10 +109,11 @@ u32 ARM::ConditionTable[16] =
|
|||
};
|
||||
|
||||
|
||||
ARM::ARM(u32 num)
|
||||
ARM::ARM(u32 num, Melon::GPU& gpu) :
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
: GdbStub(this, Platform::GetConfigInt(num ? Platform::GdbPortARM7 : Platform::GdbPortARM9))
|
||||
GdbStub(this, Platform::GetConfigInt(num ? Platform::GdbPortARM7 : Platform::GdbPortARM9)),
|
||||
#endif
|
||||
GPU(gpu)
|
||||
{
|
||||
// well uh
|
||||
Num = num;
|
||||
|
@ -133,7 +134,7 @@ ARM::~ARM()
|
|||
// dorp
|
||||
}
|
||||
|
||||
ARMv5::ARMv5() : ARM(0)
|
||||
ARMv5::ARMv5(Melon::GPU& gpu) : ARM(0, gpu)
|
||||
{
|
||||
#ifndef JIT_ENABLED
|
||||
DTCM = new u8[DTCMPhysicalSize];
|
||||
|
@ -142,7 +143,7 @@ ARMv5::ARMv5() : ARM(0)
|
|||
PU_Map = PU_PrivMap;
|
||||
}
|
||||
|
||||
ARMv4::ARMv4() : ARM(1)
|
||||
ARMv4::ARMv4(Melon::GPU& gpu) : ARM(1, gpu)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
@ -1144,7 +1145,7 @@ void ARM::WriteMem(u32 addr, int size, u32 v)
|
|||
void ARM::ResetGdb()
|
||||
{
|
||||
NDS::Reset();
|
||||
GPU::StartFrame(); // need this to properly kick off the scheduler & frame output
|
||||
GPU.StartFrame(); // need this to properly kick off the scheduler & frame output
|
||||
}
|
||||
int ARM::RemoteCmd(const u8* cmd, size_t len)
|
||||
{
|
||||
|
|
13
src/ARM.h
13
src/ARM.h
|
@ -42,13 +42,18 @@ enum
|
|||
const u32 ITCMPhysicalSize = 0x8000;
|
||||
const u32 DTCMPhysicalSize = 0x4000;
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
class ARM
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
: public Gdb::StubCallbacks
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
ARM(u32 num);
|
||||
ARM(u32 num, Melon::GPU& gpu);
|
||||
virtual ~ARM(); // destroy shit
|
||||
|
||||
virtual void Reset();
|
||||
|
@ -209,12 +214,14 @@ protected:
|
|||
void GdbCheckA();
|
||||
void GdbCheckB();
|
||||
void GdbCheckC();
|
||||
private:
|
||||
Melon::GPU& GPU;
|
||||
};
|
||||
|
||||
class ARMv5 : public ARM
|
||||
{
|
||||
public:
|
||||
ARMv5();
|
||||
ARMv5(Melon::GPU& gpu);
|
||||
~ARMv5();
|
||||
|
||||
void Reset() override;
|
||||
|
@ -358,7 +365,7 @@ public:
|
|||
class ARMv4 : public ARM
|
||||
{
|
||||
public:
|
||||
ARMv4();
|
||||
ARMv4(Melon::GPU& gpu);
|
||||
|
||||
void Reset() override;
|
||||
|
||||
|
|
|
@ -1228,11 +1228,11 @@ void VRAMWrite(u32 addr, T val)
|
|||
{
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: GPU::WriteVRAM_ABG<T>(addr, val); return;
|
||||
case 0x00200000: GPU::WriteVRAM_BBG<T>(addr, val); return;
|
||||
case 0x00400000: GPU::WriteVRAM_AOBJ<T>(addr, val); return;
|
||||
case 0x00600000: GPU::WriteVRAM_BOBJ<T>(addr, val); return;
|
||||
default: GPU::WriteVRAM_LCDC<T>(addr, val); return;
|
||||
case 0x00000000: NDS::GPU->WriteVRAM_ABG<T>(addr, val); return;
|
||||
case 0x00200000: NDS::GPU->WriteVRAM_BBG<T>(addr, val); return;
|
||||
case 0x00400000: NDS::GPU->WriteVRAM_AOBJ<T>(addr, val); return;
|
||||
case 0x00600000: NDS::GPU->WriteVRAM_BOBJ<T>(addr, val); return;
|
||||
default: NDS::GPU->WriteVRAM_LCDC<T>(addr, val); return;
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
|
@ -1240,14 +1240,56 @@ T VRAMRead(u32 addr)
|
|||
{
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: return GPU::ReadVRAM_ABG<T>(addr);
|
||||
case 0x00200000: return GPU::ReadVRAM_BBG<T>(addr);
|
||||
case 0x00400000: return GPU::ReadVRAM_AOBJ<T>(addr);
|
||||
case 0x00600000: return GPU::ReadVRAM_BOBJ<T>(addr);
|
||||
default: return GPU::ReadVRAM_LCDC<T>(addr);
|
||||
case 0x00000000: return NDS::GPU->ReadVRAM_ABG<T>(addr);
|
||||
case 0x00200000: return NDS::GPU->ReadVRAM_BBG<T>(addr);
|
||||
case 0x00400000: return NDS::GPU->ReadVRAM_AOBJ<T>(addr);
|
||||
case 0x00600000: return NDS::GPU->ReadVRAM_BOBJ<T>(addr);
|
||||
default: return NDS::GPU->ReadVRAM_LCDC<T>(addr);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 GPU3D_Read8(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->GPU3D.Read8(addr);
|
||||
}
|
||||
|
||||
static u16 GPU3D_Read16(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->GPU3D.Read16(addr);
|
||||
}
|
||||
|
||||
static u32 GPU3D_Read32(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->GPU3D.Read32(addr);
|
||||
}
|
||||
|
||||
static void GPU3D_Write8(u32 addr, u8 val) noexcept
|
||||
{
|
||||
NDS::GPU->GPU3D.Write8(addr, val);
|
||||
}
|
||||
|
||||
static void GPU3D_Write16(u32 addr, u16 val) noexcept
|
||||
{
|
||||
NDS::GPU->GPU3D.Write16(addr, val);
|
||||
}
|
||||
|
||||
static void GPU3D_Write32(u32 addr, u32 val) noexcept
|
||||
{
|
||||
NDS::GPU->GPU3D.Write32(addr, val);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T GPU_ReadVRAM_ARM7(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->ReadVRAM_ARM7<T>(addr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void GPU_WriteVRAM_ARM7(u32 addr, T val) noexcept
|
||||
{
|
||||
NDS::GPU->WriteVRAM_ARM7<T>(addr, val);
|
||||
}
|
||||
|
||||
u32 NDSCartSlot_ReadROMData()
|
||||
{ // TODO: Add a NDS* parameter, when NDS* is eventually implemented
|
||||
return NDS::NDSCartSlot->ReadROMData();
|
||||
|
@ -1273,12 +1315,12 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
|
|||
{
|
||||
switch (size | store)
|
||||
{
|
||||
case 8: return (void*)GPU3D::Read8;
|
||||
case 9: return (void*)GPU3D::Write8;
|
||||
case 16: return (void*)GPU3D::Read16;
|
||||
case 17: return (void*)GPU3D::Write16;
|
||||
case 32: return (void*)GPU3D::Read32;
|
||||
case 33: return (void*)GPU3D::Write32;
|
||||
case 8: return (void*)GPU3D_Read8;
|
||||
case 9: return (void*)GPU3D_Write8;
|
||||
case 16: return (void*)GPU3D_Read16;
|
||||
case 17: return (void*)GPU3D_Write16;
|
||||
case 32: return (void*)GPU3D_Read32;
|
||||
case 33: return (void*)GPU3D_Write32;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1380,12 +1422,12 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
|
|||
case 0x06800000:
|
||||
switch (size | store)
|
||||
{
|
||||
case 8: return (void*)GPU::ReadVRAM_ARM7<u8>;
|
||||
case 9: return (void*)GPU::WriteVRAM_ARM7<u8>;
|
||||
case 16: return (void*)GPU::ReadVRAM_ARM7<u16>;
|
||||
case 17: return (void*)GPU::WriteVRAM_ARM7<u16>;
|
||||
case 32: return (void*)GPU::ReadVRAM_ARM7<u32>;
|
||||
case 33: return (void*)GPU::WriteVRAM_ARM7<u32>;
|
||||
case 8: return (void*)GPU_ReadVRAM_ARM7<u8>;
|
||||
case 9: return (void*)GPU_WriteVRAM_ARM7<u8>;
|
||||
case 16: return (void*)GPU_ReadVRAM_ARM7<u16>;
|
||||
case 17: return (void*)GPU_WriteVRAM_ARM7<u16>;
|
||||
case 32: return (void*)GPU_ReadVRAM_ARM7<u32>;
|
||||
case 33: return (void*)GPU_WriteVRAM_ARM7<u32>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,10 @@ using Platform::LogLevel;
|
|||
// TODO: timings are nonseq when address is fixed/decrementing
|
||||
|
||||
|
||||
DMA::DMA(u32 cpu, u32 num) :
|
||||
DMA::DMA(u32 cpu, u32 num, Melon::GPU& gpu) :
|
||||
CPU(cpu),
|
||||
Num(num)
|
||||
Num(num),
|
||||
GPU(gpu)
|
||||
{
|
||||
if (cpu == 0)
|
||||
CountMask = 0x001FFFFF;
|
||||
|
@ -142,7 +143,7 @@ void DMA::WriteCnt(u32 val)
|
|||
if ((StartMode & 0x7) == 0)
|
||||
Start();
|
||||
else if (StartMode == 0x07)
|
||||
GPU3D::CheckFIFODMA();
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
|
||||
if (StartMode==0x06 || StartMode==0x13)
|
||||
Log(LogLevel::Warn, "UNIMPLEMENTED ARM%d DMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr);
|
||||
|
@ -609,7 +610,7 @@ void DMA::Run9()
|
|||
NDS::ResumeCPU(0, 1<<Num);
|
||||
|
||||
if (StartMode == 0x07)
|
||||
GPU3D::CheckFIFODMA();
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -24,10 +24,15 @@
|
|||
#include "Savestate.h"
|
||||
#include "DMA_Timings.h"
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
class DMA
|
||||
{
|
||||
public:
|
||||
DMA(u32 cpu, u32 num);
|
||||
DMA(u32 cpu, u32 num, Melon::GPU& gpu);
|
||||
~DMA() = default;
|
||||
|
||||
void Reset();
|
||||
|
@ -79,6 +84,7 @@ public:
|
|||
u32 Cnt {};
|
||||
|
||||
private:
|
||||
Melon::GPU& GPU;
|
||||
u32 CPU {};
|
||||
u32 Num {};
|
||||
|
||||
|
|
34
src/DSi.cpp
34
src/DSi.cpp
|
@ -105,14 +105,14 @@ bool Init()
|
|||
NWRAM_C = new u8[NWRAMSize];
|
||||
#endif
|
||||
|
||||
NDMAs[0] = new DSi_NDMA(0, 0);
|
||||
NDMAs[1] = new DSi_NDMA(0, 1);
|
||||
NDMAs[2] = new DSi_NDMA(0, 2);
|
||||
NDMAs[3] = new DSi_NDMA(0, 3);
|
||||
NDMAs[4] = new DSi_NDMA(1, 0);
|
||||
NDMAs[5] = new DSi_NDMA(1, 1);
|
||||
NDMAs[6] = new DSi_NDMA(1, 2);
|
||||
NDMAs[7] = new DSi_NDMA(1, 3);
|
||||
NDMAs[0] = new DSi_NDMA(0, 0, *NDS::GPU);
|
||||
NDMAs[1] = new DSi_NDMA(0, 1, *NDS::GPU);
|
||||
NDMAs[2] = new DSi_NDMA(0, 2, *NDS::GPU);
|
||||
NDMAs[3] = new DSi_NDMA(0, 3, *NDS::GPU);
|
||||
NDMAs[4] = new DSi_NDMA(1, 0, *NDS::GPU);
|
||||
NDMAs[5] = new DSi_NDMA(1, 1, *NDS::GPU);
|
||||
NDMAs[6] = new DSi_NDMA(1, 2, *NDS::GPU);
|
||||
NDMAs[7] = new DSi_NDMA(1, 3, *NDS::GPU);
|
||||
|
||||
SDMMC = new DSi_SDHost(0);
|
||||
SDIO = new DSi_SDHost(1);
|
||||
|
@ -205,8 +205,8 @@ void Reset()
|
|||
GPIO_WiFi = 0;
|
||||
|
||||
// LCD init flag
|
||||
GPU::DispStat[0] |= (1<<6);
|
||||
GPU::DispStat[1] |= (1<<6);
|
||||
NDS::GPU->DispStat[0] |= (1<<6);
|
||||
NDS::GPU->DispStat[1] |= (1<<6);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
|
@ -730,8 +730,8 @@ void SoftReset()
|
|||
|
||||
|
||||
// LCD init flag
|
||||
GPU::DispStat[0] |= (1<<6);
|
||||
GPU::DispStat[1] |= (1<<6);
|
||||
NDS::GPU->DispStat[0] |= (1<<6);
|
||||
NDS::GPU->DispStat[1] |= (1<<6);
|
||||
}
|
||||
|
||||
bool LoadNAND()
|
||||
|
@ -1528,11 +1528,11 @@ void ARM9Write8(u32 addr, u8 val)
|
|||
#endif
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: GPU::WriteVRAM_ABG<u8>(addr, val); return;
|
||||
case 0x00200000: GPU::WriteVRAM_BBG<u8>(addr, val); return;
|
||||
case 0x00400000: GPU::WriteVRAM_AOBJ<u8>(addr, val); return;
|
||||
case 0x00600000: GPU::WriteVRAM_BOBJ<u8>(addr, val); return;
|
||||
default: GPU::WriteVRAM_LCDC<u8>(addr, val); return;
|
||||
case 0x00000000: NDS::GPU->WriteVRAM_ABG<u8>(addr, val); return;
|
||||
case 0x00200000: NDS::GPU->WriteVRAM_BBG<u8>(addr, val); return;
|
||||
case 0x00400000: NDS::GPU->WriteVRAM_AOBJ<u8>(addr, val); return;
|
||||
case 0x00600000: NDS::GPU->WriteVRAM_BOBJ<u8>(addr, val); return;
|
||||
default: NDS::GPU->WriteVRAM_LCDC<u8>(addr, val); return;
|
||||
}
|
||||
|
||||
case 0x08000000:
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
using Platform::Log;
|
||||
using Platform::LogLevel;
|
||||
|
||||
DSi_NDMA::DSi_NDMA(u32 cpu, u32 num)
|
||||
DSi_NDMA::DSi_NDMA(u32 cpu, u32 num, Melon::GPU& gpu) : GPU(gpu)
|
||||
{
|
||||
CPU = cpu;
|
||||
Num = num;
|
||||
|
@ -125,7 +125,7 @@ void DSi_NDMA::WriteCnt(u32 val)
|
|||
if ((StartMode & 0x1F) == 0x10)
|
||||
Start();
|
||||
else if (StartMode == 0x0A)
|
||||
GPU3D::CheckFIFODMA();
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
|
||||
// TODO: unsupported start modes:
|
||||
// * timers (00-03)
|
||||
|
@ -259,7 +259,7 @@ void DSi_NDMA::Run9()
|
|||
NDS::ResumeCPU(0, 1<<(Num+4));
|
||||
|
||||
if (StartMode == 0x0A)
|
||||
GPU3D::CheckFIFODMA();
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -22,10 +22,15 @@
|
|||
#include "types.h"
|
||||
#include "Savestate.h"
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
class DSi_NDMA
|
||||
{
|
||||
public:
|
||||
DSi_NDMA(u32 cpu, u32 num);
|
||||
DSi_NDMA(u32 cpu, u32 num, Melon::GPU& gpu);
|
||||
~DSi_NDMA();
|
||||
|
||||
void Reset();
|
||||
|
@ -73,6 +78,7 @@ public:
|
|||
u32 Cnt;
|
||||
|
||||
private:
|
||||
Melon::GPU& GPU;
|
||||
u32 CPU, Num;
|
||||
|
||||
u32 StartMode;
|
||||
|
|
386
src/GPU.cpp
386
src/GPU.cpp
|
@ -25,17 +25,18 @@
|
|||
#endif
|
||||
|
||||
#include "GPU2D_Soft.h"
|
||||
#include "GPU3D_Soft.h"
|
||||
#include "GPU3D_OpenGL.h"
|
||||
|
||||
using Platform::Log;
|
||||
using Platform::LogLevel;
|
||||
|
||||
namespace GPU
|
||||
{
|
||||
|
||||
#define LINE_CYCLES (355*6)
|
||||
#define HBLANK_CYCLES (48+(256*6))
|
||||
#define FRAME_CYCLES (LINE_CYCLES * 263)
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
enum
|
||||
{
|
||||
LCD_StartHBlank = 0,
|
||||
|
@ -43,62 +44,6 @@ enum
|
|||
LCD_FinishFrame,
|
||||
};
|
||||
|
||||
u16 VCount;
|
||||
u32 NextVCount;
|
||||
u16 TotalScanlines;
|
||||
|
||||
bool RunFIFO;
|
||||
|
||||
u16 DispStat[2], VMatch[2];
|
||||
|
||||
u8 Palette[2*1024];
|
||||
u8 OAM[2*1024];
|
||||
|
||||
u8 VRAM_A[128*1024];
|
||||
u8 VRAM_B[128*1024];
|
||||
u8 VRAM_C[128*1024];
|
||||
u8 VRAM_D[128*1024];
|
||||
u8 VRAM_E[ 64*1024];
|
||||
u8 VRAM_F[ 16*1024];
|
||||
u8 VRAM_G[ 16*1024];
|
||||
u8 VRAM_H[ 32*1024];
|
||||
u8 VRAM_I[ 16*1024];
|
||||
u8* const VRAM[9] = {VRAM_A, VRAM_B, VRAM_C, VRAM_D, VRAM_E, VRAM_F, VRAM_G, VRAM_H, VRAM_I};
|
||||
u32 const VRAMMask[9] = {0x1FFFF, 0x1FFFF, 0x1FFFF, 0x1FFFF, 0xFFFF, 0x3FFF, 0x3FFF, 0x7FFF, 0x3FFF};
|
||||
|
||||
u8 VRAMCNT[9];
|
||||
u8 VRAMSTAT;
|
||||
|
||||
u32 VRAMMap_LCDC;
|
||||
|
||||
u32 VRAMMap_ABG[0x20];
|
||||
u32 VRAMMap_AOBJ[0x10];
|
||||
u32 VRAMMap_BBG[0x8];
|
||||
u32 VRAMMap_BOBJ[0x8];
|
||||
|
||||
u32 VRAMMap_ABGExtPal[4];
|
||||
u32 VRAMMap_AOBJExtPal;
|
||||
u32 VRAMMap_BBGExtPal[4];
|
||||
u32 VRAMMap_BOBJExtPal;
|
||||
|
||||
u32 VRAMMap_Texture[4];
|
||||
u32 VRAMMap_TexPal[8];
|
||||
|
||||
u32 VRAMMap_ARM7[2];
|
||||
|
||||
u8* VRAMPtr_ABG[0x20];
|
||||
u8* VRAMPtr_AOBJ[0x10];
|
||||
u8* VRAMPtr_BBG[0x8];
|
||||
u8* VRAMPtr_BOBJ[0x8];
|
||||
|
||||
int FrontBuffer;
|
||||
u32* Framebuffer[2][2];
|
||||
int Renderer = 0;
|
||||
|
||||
GPU2D::Unit GPU2D_A(0);
|
||||
GPU2D::Unit GPU2D_B(1);
|
||||
|
||||
std::unique_ptr<GPU2D::Renderer2D> GPU2D_Renderer = {};
|
||||
|
||||
/*
|
||||
VRAM invalidation tracking
|
||||
|
@ -121,64 +66,24 @@ std::unique_ptr<GPU2D::Renderer2D> GPU2D_Renderer = {};
|
|||
VRAMDirty need to be reset for the respective VRAM bank.
|
||||
*/
|
||||
|
||||
VRAMTrackingSet<512*1024, 16*1024> VRAMDirty_ABG;
|
||||
VRAMTrackingSet<256*1024, 16*1024> VRAMDirty_AOBJ;
|
||||
VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_BBG;
|
||||
VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_BOBJ;
|
||||
|
||||
VRAMTrackingSet<32*1024, 8*1024> VRAMDirty_ABGExtPal;
|
||||
VRAMTrackingSet<32*1024, 8*1024> VRAMDirty_BBGExtPal;
|
||||
VRAMTrackingSet<8*1024, 8*1024> VRAMDirty_AOBJExtPal;
|
||||
VRAMTrackingSet<8*1024, 8*1024> VRAMDirty_BOBJExtPal;
|
||||
|
||||
VRAMTrackingSet<512*1024, 128*1024> VRAMDirty_Texture;
|
||||
VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_TexPal;
|
||||
|
||||
NonStupidBitField<128*1024/VRAMDirtyGranularity> VRAMDirty[9];
|
||||
|
||||
u8 VRAMFlat_ABG[512*1024];
|
||||
u8 VRAMFlat_BBG[128*1024];
|
||||
u8 VRAMFlat_AOBJ[256*1024];
|
||||
u8 VRAMFlat_BOBJ[128*1024];
|
||||
|
||||
u8 VRAMFlat_ABGExtPal[32*1024];
|
||||
u8 VRAMFlat_BBGExtPal[32*1024];
|
||||
u8 VRAMFlat_AOBJExtPal[8*1024];
|
||||
u8 VRAMFlat_BOBJExtPal[8*1024];
|
||||
|
||||
u8 VRAMFlat_Texture[512*1024];
|
||||
u8 VRAMFlat_TexPal[128*1024];
|
||||
|
||||
u32 OAMDirty;
|
||||
u32 PaletteDirty;
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
std::unique_ptr<GLCompositor> CurGLCompositor = {};
|
||||
#endif
|
||||
|
||||
bool Init()
|
||||
GPU::GPU() noexcept : GPU2D_A(0, *this), GPU2D_B(1, *this)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartHBlank, StartHBlank);
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartScanline, StartScanline);
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_FinishFrame, FinishFrame);
|
||||
NDS::RegisterEventFunc(NDS::Event_DisplayFIFO, 0, DisplayFIFO);
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartHBlank, MemberEventFunc(GPU, StartHBlank));
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartScanline, MemberEventFunc(GPU, StartScanline));
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_FinishFrame, MemberEventFunc(GPU, FinishFrame));
|
||||
NDS::RegisterEventFunc(NDS::Event_DisplayFIFO, 0, MemberEventFunc(GPU, DisplayFIFO));
|
||||
|
||||
GPU2D_Renderer = std::make_unique<GPU2D::SoftRenderer>();
|
||||
if (!GPU3D::Init()) return false;
|
||||
GPU2D_Renderer = std::make_unique<GPU2D::SoftRenderer>(*this);
|
||||
|
||||
FrontBuffer = 0;
|
||||
Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL;
|
||||
Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL;
|
||||
Renderer = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
GPU::~GPU() noexcept
|
||||
{
|
||||
GPU2D_Renderer.reset();
|
||||
GPU3D::DeInit();
|
||||
|
||||
// All unique_ptr fields are automatically cleaned up
|
||||
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||
|
@ -189,17 +94,13 @@ void DeInit()
|
|||
Framebuffer[1][0] = nullptr;
|
||||
Framebuffer[1][1] = nullptr;
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
CurGLCompositor = nullptr;
|
||||
#endif
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_StartHBlank);
|
||||
NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_StartScanline);
|
||||
NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_FinishFrame);
|
||||
NDS::UnregisterEventFunc(NDS::Event_DisplayFIFO, 0);
|
||||
}
|
||||
|
||||
void ResetVRAMCache()
|
||||
void GPU::ResetVRAMCache() noexcept
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
VRAMDirty[i] = NonStupidBitField<128*1024/VRAMDirtyGranularity>();
|
||||
|
@ -227,7 +128,7 @@ void ResetVRAMCache()
|
|||
memset(VRAMFlat_TexPal, 0, sizeof(VRAMFlat_TexPal));
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void GPU::Reset() noexcept
|
||||
{
|
||||
VCount = 0;
|
||||
NextVCount = -1;
|
||||
|
@ -278,7 +179,7 @@ void Reset()
|
|||
memset(VRAMPtr_BOBJ, 0, sizeof(VRAMPtr_BOBJ));
|
||||
|
||||
size_t fbsize;
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU3D.IsRendererAccelerated())
|
||||
fbsize = (256*3 + 1) * 192;
|
||||
else
|
||||
fbsize = 256 * 192;
|
||||
|
@ -296,7 +197,7 @@ void Reset()
|
|||
|
||||
GPU2D_A.Reset();
|
||||
GPU2D_B.Reset();
|
||||
GPU3D::Reset();
|
||||
GPU3D.Reset();
|
||||
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
GPU2D_Renderer->SetFramebuffer(Framebuffer[backbuf][1], Framebuffer[backbuf][0]);
|
||||
|
@ -309,10 +210,10 @@ void Reset()
|
|||
PaletteDirty = 0xF;
|
||||
}
|
||||
|
||||
void Stop()
|
||||
void GPU::Stop() noexcept
|
||||
{
|
||||
int fbsize;
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU3D.IsRendererAccelerated())
|
||||
fbsize = (256*3 + 1) * 192;
|
||||
else
|
||||
fbsize = 256 * 192;
|
||||
|
@ -325,12 +226,12 @@ void Stop()
|
|||
#ifdef OGLRENDERER_ENABLED
|
||||
// This needs a better way to know that we're
|
||||
// using the OpenGL renderer specifically
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU3D.IsRendererAccelerated())
|
||||
CurGLCompositor->Stop();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
void GPU::DoSavestate(Savestate* file) noexcept
|
||||
{
|
||||
file->Section("GPUG");
|
||||
|
||||
|
@ -391,12 +292,12 @@ void DoSavestate(Savestate* file)
|
|||
|
||||
GPU2D_A.DoSavestate(file);
|
||||
GPU2D_B.DoSavestate(file);
|
||||
GPU3D::DoSavestate(file);
|
||||
GPU3D.DoSavestate(file);
|
||||
|
||||
ResetVRAMCache();
|
||||
}
|
||||
|
||||
void AssignFramebuffers()
|
||||
void GPU::AssignFramebuffers() noexcept
|
||||
{
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
if (NDS::PowerControl9 & (1<<15))
|
||||
|
@ -409,41 +310,41 @@ void AssignFramebuffers()
|
|||
}
|
||||
}
|
||||
|
||||
void InitRenderer(int renderer)
|
||||
void GPU::InitRenderer(int renderer) noexcept
|
||||
{
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
if (renderer == 1)
|
||||
{
|
||||
CurGLCompositor = GLCompositor::New();
|
||||
CurGLCompositor = GLCompositor::New(*this);
|
||||
// Create opengl renderer
|
||||
if (!CurGLCompositor)
|
||||
{
|
||||
// Fallback on software renderer
|
||||
renderer = 0;
|
||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
||||
GPU3D.SetCurrentRenderer(std::make_unique<GPU3D::SoftRenderer>(*this));
|
||||
}
|
||||
GPU3D::CurrentRenderer = GPU3D::GLRenderer::New();
|
||||
if (!GPU3D::CurrentRenderer)
|
||||
GPU3D.SetCurrentRenderer(GPU3D::GLRenderer::New(*this));
|
||||
if (!GPU3D.GetCurrentRenderer())
|
||||
{
|
||||
// Fallback on software renderer
|
||||
CurGLCompositor.reset();
|
||||
renderer = 0;
|
||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
||||
GPU3D.SetCurrentRenderer(std::make_unique<GPU3D::SoftRenderer>(*this));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
||||
GPU3D.SetCurrentRenderer(std::make_unique<GPU3D::SoftRenderer>(*this));
|
||||
}
|
||||
|
||||
Renderer = renderer;
|
||||
}
|
||||
|
||||
void DeInitRenderer()
|
||||
void GPU::DeInitRenderer() noexcept
|
||||
{
|
||||
// Delete the 3D renderer, if it exists
|
||||
GPU3D::CurrentRenderer.reset();
|
||||
GPU3D.SetCurrentRenderer(nullptr);
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
// Delete the compositor, if one exists
|
||||
|
@ -451,22 +352,22 @@ void DeInitRenderer()
|
|||
#endif
|
||||
}
|
||||
|
||||
void ResetRenderer()
|
||||
void GPU::ResetRenderer() noexcept
|
||||
{
|
||||
if (Renderer == 0)
|
||||
{
|
||||
GPU3D::CurrentRenderer->Reset();
|
||||
GPU3D.GetCurrentRenderer()->Reset();
|
||||
}
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
else
|
||||
{
|
||||
CurGLCompositor->Reset();
|
||||
GPU3D::CurrentRenderer->Reset();
|
||||
GPU3D.GetCurrentRenderer()->Reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetRenderSettings(int renderer, RenderSettings& settings)
|
||||
void GPU::SetRenderSettings(int renderer, RenderSettings& settings) noexcept
|
||||
{
|
||||
if (renderer != Renderer)
|
||||
{
|
||||
|
@ -475,7 +376,7 @@ void SetRenderSettings(int renderer, RenderSettings& settings)
|
|||
}
|
||||
|
||||
int fbsize;
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU3D.IsRendererAccelerated())
|
||||
fbsize = (256*3 + 1) * 192;
|
||||
else
|
||||
fbsize = 256 * 192;
|
||||
|
@ -499,13 +400,13 @@ void SetRenderSettings(int renderer, RenderSettings& settings)
|
|||
|
||||
if (Renderer == 0)
|
||||
{
|
||||
GPU3D::CurrentRenderer->SetRenderSettings(settings);
|
||||
GPU3D.GetCurrentRenderer()->SetRenderSettings(settings);
|
||||
}
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
else
|
||||
{
|
||||
CurGLCompositor->SetRenderSettings(settings);
|
||||
GPU3D::CurrentRenderer->SetRenderSettings(settings);
|
||||
GPU3D.GetCurrentRenderer()->SetRenderSettings(settings);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -541,7 +442,14 @@ void SetRenderSettings(int renderer, RenderSettings& settings)
|
|||
// when reading: values are read from each bank and ORed together
|
||||
// when writing: value is written to each bank
|
||||
|
||||
u8* GetUniqueBankPtr(u32 mask, u32 offset)
|
||||
u8* GPU::GetUniqueBankPtr(u32 mask, u32 offset) noexcept
|
||||
{
|
||||
if (!mask || (mask & (mask - 1)) != 0) return NULL;
|
||||
int num = __builtin_ctz(mask);
|
||||
return &VRAM[num][offset & VRAMMask[num]];
|
||||
}
|
||||
|
||||
const u8* GPU::GetUniqueBankPtr(u32 mask, u32 offset) const noexcept
|
||||
{
|
||||
if (!mask || (mask & (mask - 1)) != 0) return NULL;
|
||||
int num = __builtin_ctz(mask);
|
||||
|
@ -556,7 +464,7 @@ u8* GetUniqueBankPtr(u32 mask, u32 offset)
|
|||
#define UNMAP_RANGE_PTR(map, base, n) \
|
||||
for (int i = 0; i < n; i++) { VRAMMap_##map[(base)+i] &= ~bankmask; VRAMPtr_##map[(base)+i] = GetUniqueBankPtr(VRAMMap_##map[(base)+i], ((base)+i)<<14); }
|
||||
|
||||
void MapVRAM_AB(u32 bank, u8 cnt)
|
||||
void GPU::MapVRAM_AB(u32 bank, u8 cnt) noexcept
|
||||
{
|
||||
cnt &= 0x9B;
|
||||
|
||||
|
@ -616,7 +524,7 @@ void MapVRAM_AB(u32 bank, u8 cnt)
|
|||
}
|
||||
}
|
||||
|
||||
void MapVRAM_CD(u32 bank, u8 cnt)
|
||||
void GPU::MapVRAM_CD(u32 bank, u8 cnt) noexcept
|
||||
{
|
||||
cnt &= 0x9F;
|
||||
|
||||
|
@ -705,7 +613,7 @@ void MapVRAM_CD(u32 bank, u8 cnt)
|
|||
}
|
||||
}
|
||||
|
||||
void MapVRAM_E(u32 bank, u8 cnt)
|
||||
void GPU::MapVRAM_E(u32 bank, u8 cnt) noexcept
|
||||
{
|
||||
cnt &= 0x87;
|
||||
|
||||
|
@ -769,7 +677,7 @@ void MapVRAM_E(u32 bank, u8 cnt)
|
|||
}
|
||||
}
|
||||
|
||||
void MapVRAM_FG(u32 bank, u8 cnt)
|
||||
void GPU::MapVRAM_FG(u32 bank, u8 cnt) noexcept
|
||||
{
|
||||
cnt &= 0x9F;
|
||||
|
||||
|
@ -869,7 +777,7 @@ void MapVRAM_FG(u32 bank, u8 cnt)
|
|||
}
|
||||
}
|
||||
|
||||
void MapVRAM_H(u32 bank, u8 cnt)
|
||||
void GPU::MapVRAM_H(u32 bank, u8 cnt) noexcept
|
||||
{
|
||||
cnt &= 0x83;
|
||||
|
||||
|
@ -931,7 +839,7 @@ void MapVRAM_H(u32 bank, u8 cnt)
|
|||
}
|
||||
}
|
||||
|
||||
void MapVRAM_I(u32 bank, u8 cnt)
|
||||
void GPU::MapVRAM_I(u32 bank, u8 cnt) noexcept
|
||||
{
|
||||
cnt &= 0x83;
|
||||
|
||||
|
@ -1002,7 +910,7 @@ void MapVRAM_I(u32 bank, u8 cnt)
|
|||
}
|
||||
|
||||
|
||||
void SetPowerCnt(u32 val)
|
||||
void GPU::SetPowerCnt(u32 val) noexcept
|
||||
{
|
||||
// POWCNT1 effects:
|
||||
// * bit0: asplodes hardware??? not tested.
|
||||
|
@ -1016,13 +924,13 @@ void SetPowerCnt(u32 val)
|
|||
|
||||
GPU2D_A.SetEnabled(val & (1<<1));
|
||||
GPU2D_B.SetEnabled(val & (1<<9));
|
||||
GPU3D::SetEnabled(val & (1<<3), val & (1<<2));
|
||||
GPU3D.SetEnabled(val & (1<<3), val & (1<<2));
|
||||
|
||||
AssignFramebuffers();
|
||||
}
|
||||
|
||||
|
||||
void DisplayFIFO(u32 x)
|
||||
void GPU::DisplayFIFO(u32 x) noexcept
|
||||
{
|
||||
// sample the FIFO
|
||||
// as this starts 16 cycles (~3 pixels) before display start,
|
||||
|
@ -1045,7 +953,7 @@ void DisplayFIFO(u32 x)
|
|||
GPU2D_A.SampleFIFO(253, 3); // sample the remaining pixels
|
||||
}
|
||||
|
||||
void StartFrame()
|
||||
void GPU::StartFrame() noexcept
|
||||
{
|
||||
// only run the display FIFO if needed:
|
||||
// * if it is used for display or capture
|
||||
|
@ -1056,7 +964,7 @@ void StartFrame()
|
|||
StartScanline(0);
|
||||
}
|
||||
|
||||
void StartHBlank(u32 line)
|
||||
void GPU::StartHBlank(u32 line) noexcept
|
||||
{
|
||||
DispStat[0] |= (1<<1);
|
||||
DispStat[1] |= (1<<1);
|
||||
|
@ -1082,7 +990,7 @@ void StartHBlank(u32 line)
|
|||
}
|
||||
else if (VCount == 215)
|
||||
{
|
||||
GPU3D::VCount215();
|
||||
GPU3D.VCount215();
|
||||
}
|
||||
else if (VCount == 262)
|
||||
{
|
||||
|
@ -1099,25 +1007,25 @@ void StartHBlank(u32 line)
|
|||
NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_FinishFrame, line+1);
|
||||
}
|
||||
|
||||
void FinishFrame(u32 lines)
|
||||
void GPU::FinishFrame(u32 lines) noexcept
|
||||
{
|
||||
FrontBuffer = FrontBuffer ? 0 : 1;
|
||||
AssignFramebuffers();
|
||||
|
||||
TotalScanlines = lines;
|
||||
|
||||
if (GPU3D::AbortFrame)
|
||||
if (GPU3D.AbortFrame)
|
||||
{
|
||||
GPU3D::RestartFrame();
|
||||
GPU3D::AbortFrame = false;
|
||||
GPU3D.RestartFrame();
|
||||
GPU3D.AbortFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BlankFrame()
|
||||
void GPU::BlankFrame() noexcept
|
||||
{
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
int fbsize;
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU3D.IsRendererAccelerated())
|
||||
fbsize = (256*3 + 1) * 192;
|
||||
else
|
||||
fbsize = 256 * 192;
|
||||
|
@ -1131,7 +1039,7 @@ void BlankFrame()
|
|||
TotalScanlines = 263;
|
||||
}
|
||||
|
||||
void StartScanline(u32 line)
|
||||
void GPU::StartScanline(u32 line) noexcept
|
||||
{
|
||||
if (line == 0)
|
||||
VCount = 0;
|
||||
|
@ -1201,7 +1109,7 @@ void StartScanline(u32 line)
|
|||
// texture memory anyway and only update it before the start
|
||||
//of the next frame.
|
||||
// So we can give the rasteriser a bit more headroom
|
||||
GPU3D::VCount144();
|
||||
GPU3D.VCount144();
|
||||
|
||||
// VBlank
|
||||
DispStat[0] |= (1<<0);
|
||||
|
@ -1217,11 +1125,11 @@ void StartScanline(u32 line)
|
|||
|
||||
GPU2D_A.VBlank();
|
||||
GPU2D_B.VBlank();
|
||||
GPU3D::VBlank();
|
||||
GPU3D.VBlank();
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
// Need a better way to identify the openGL renderer in particular
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU3D.IsRendererAccelerated())
|
||||
CurGLCompositor->RenderFrame();
|
||||
#endif
|
||||
}
|
||||
|
@ -1231,7 +1139,7 @@ void StartScanline(u32 line)
|
|||
}
|
||||
|
||||
|
||||
void SetDispStat(u32 cpu, u16 val)
|
||||
void GPU::SetDispStat(u32 cpu, u16 val) noexcept
|
||||
{
|
||||
val &= 0xFFB8;
|
||||
DispStat[cpu] &= 0x0047;
|
||||
|
@ -1240,7 +1148,7 @@ void SetDispStat(u32 cpu, u16 val)
|
|||
VMatch[cpu] = (val >> 8) | ((val & 0x80) << 1);
|
||||
}
|
||||
|
||||
void SetVCount(u16 val)
|
||||
void GPU::SetVCount(u16 val) noexcept
|
||||
{
|
||||
// VCount write is delayed until the next scanline
|
||||
|
||||
|
@ -1248,12 +1156,12 @@ void SetVCount(u16 val)
|
|||
// 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
|
||||
|
||||
GPU3D::AbortFrame |= NextVCount != val;
|
||||
GPU3D.AbortFrame |= NextVCount != val;
|
||||
NextVCount = val;
|
||||
}
|
||||
|
||||
template <u32 Size, u32 MappingGranularity>
|
||||
NonStupidBitField<Size/VRAMDirtyGranularity> VRAMTrackingSet<Size, MappingGranularity>::DeriveState(u32* currentMappings)
|
||||
NonStupidBitField<Size/VRAMDirtyGranularity> VRAMTrackingSet<Size, MappingGranularity>::DeriveState(u32* currentMappings, GPU& gpu)
|
||||
{
|
||||
NonStupidBitField<Size/VRAMDirtyGranularity> result;
|
||||
u16 banksToBeZeroed = 0;
|
||||
|
@ -1282,20 +1190,20 @@ NonStupidBitField<Size/VRAMDirtyGranularity> VRAMTrackingSet<Size, MappingGranul
|
|||
static_assert(VRAMDirtyGranularity == 512, "");
|
||||
if (MappingGranularity == 16*1024)
|
||||
{
|
||||
u32 dirty = ((u32*)VRAMDirty[num].Data)[i & (VRAMMask[num] >> 14)];
|
||||
u32 dirty = ((u32*)gpu.VRAMDirty[num].Data)[i & (gpu.VRAMMask[num] >> 14)];
|
||||
result.Data[i / 2] |= (u64)dirty << ((i&1)*32);
|
||||
}
|
||||
else if (MappingGranularity == 8*1024)
|
||||
{
|
||||
u16 dirty = ((u16*)VRAMDirty[num].Data)[i & (VRAMMask[num] >> 13)];
|
||||
u16 dirty = ((u16*)gpu.VRAMDirty[num].Data)[i & (gpu.VRAMMask[num] >> 13)];
|
||||
result.Data[i / 4] |= (u64)dirty << ((i&3)*16);
|
||||
}
|
||||
else if (MappingGranularity == 128*1024)
|
||||
{
|
||||
result.Data[i * 4 + 0] |= VRAMDirty[num].Data[0];
|
||||
result.Data[i * 4 + 1] |= VRAMDirty[num].Data[1];
|
||||
result.Data[i * 4 + 2] |= VRAMDirty[num].Data[2];
|
||||
result.Data[i * 4 + 3] |= VRAMDirty[num].Data[3];
|
||||
result.Data[i * 4 + 0] |= gpu.VRAMDirty[num].Data[0];
|
||||
result.Data[i * 4 + 1] |= gpu.VRAMDirty[num].Data[1];
|
||||
result.Data[i * 4 + 2] |= gpu.VRAMDirty[num].Data[2];
|
||||
result.Data[i * 4 + 3] |= gpu.VRAMDirty[num].Data[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1310,137 +1218,63 @@ NonStupidBitField<Size/VRAMDirtyGranularity> VRAMTrackingSet<Size, MappingGranul
|
|||
{
|
||||
u32 num = __builtin_ctz(banksToBeZeroed);
|
||||
banksToBeZeroed &= ~(1 << num);
|
||||
VRAMDirty[num].Clear();
|
||||
gpu.VRAMDirty[num].Clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template NonStupidBitField<32*1024/VRAMDirtyGranularity> VRAMTrackingSet<32*1024, 8*1024>::DeriveState(u32*);
|
||||
template NonStupidBitField<8*1024/VRAMDirtyGranularity> VRAMTrackingSet<8*1024, 8*1024>::DeriveState(u32*);
|
||||
template NonStupidBitField<512*1024/VRAMDirtyGranularity> VRAMTrackingSet<512*1024, 128*1024>::DeriveState(u32*);
|
||||
template NonStupidBitField<128*1024/VRAMDirtyGranularity> VRAMTrackingSet<128*1024, 16*1024>::DeriveState(u32*);
|
||||
template NonStupidBitField<256*1024/VRAMDirtyGranularity> VRAMTrackingSet<256*1024, 16*1024>::DeriveState(u32*);
|
||||
template NonStupidBitField<512*1024/VRAMDirtyGranularity> VRAMTrackingSet<512*1024, 16*1024>::DeriveState(u32*);
|
||||
template NonStupidBitField<32*1024/VRAMDirtyGranularity> VRAMTrackingSet<32*1024, 8*1024>::DeriveState(u32*, GPU& gpu);
|
||||
template NonStupidBitField<8*1024/VRAMDirtyGranularity> VRAMTrackingSet<8*1024, 8*1024>::DeriveState(u32*, GPU& gpu);
|
||||
template NonStupidBitField<512*1024/VRAMDirtyGranularity> VRAMTrackingSet<512*1024, 128*1024>::DeriveState(u32*, GPU& gpu);
|
||||
template NonStupidBitField<128*1024/VRAMDirtyGranularity> VRAMTrackingSet<128*1024, 16*1024>::DeriveState(u32*, GPU& gpu);
|
||||
template NonStupidBitField<256*1024/VRAMDirtyGranularity> VRAMTrackingSet<256*1024, 16*1024>::DeriveState(u32*, GPU& gpu);
|
||||
template NonStupidBitField<512*1024/VRAMDirtyGranularity> VRAMTrackingSet<512*1024, 16*1024>::DeriveState(u32*, GPU& gpu);
|
||||
|
||||
template <u32 MappingGranularity, u32 Size>
|
||||
inline bool CopyLinearVRAM(u8* flat, u32* mappings, NonStupidBitField<Size>& dirty, u64 (*slowAccess)(u32 addr))
|
||||
|
||||
|
||||
bool GPU::MakeVRAMFlat_TextureCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
const u32 VRAMBitsPerMapping = MappingGranularity / VRAMDirtyGranularity;
|
||||
|
||||
bool change = false;
|
||||
|
||||
typename NonStupidBitField<Size>::Iterator it = dirty.Begin();
|
||||
while (it != dirty.End())
|
||||
{
|
||||
u32 offset = *it * VRAMDirtyGranularity;
|
||||
u8* dst = flat + offset;
|
||||
u8* fastAccess = GetUniqueBankPtr(mappings[*it / VRAMBitsPerMapping], offset);
|
||||
if (fastAccess)
|
||||
{
|
||||
memcpy(dst, fastAccess, VRAMDirtyGranularity);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < VRAMDirtyGranularity; i += 8)
|
||||
*(u64*)&dst[i] = slowAccess(offset + i);
|
||||
}
|
||||
change = true;
|
||||
it++;
|
||||
}
|
||||
return change;
|
||||
return CopyLinearVRAM<128*1024>(VRAMFlat_Texture, VRAMMap_Texture, dirty, &GPU::ReadVRAM_Texture<u64>);
|
||||
}
|
||||
|
||||
bool MakeVRAMFlat_TextureCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty)
|
||||
bool GPU::MakeVRAMFlat_TexPalCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
return CopyLinearVRAM<128*1024>(VRAMFlat_Texture, VRAMMap_Texture, dirty, ReadVRAM_Texture<u64>);
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_TexPal, VRAMMap_TexPal, dirty, &GPU::ReadVRAM_TexPal<u64>);
|
||||
}
|
||||
bool MakeVRAMFlat_TexPalCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty)
|
||||
|
||||
bool GPU::MakeVRAMFlat_ABGCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_TexPal, VRAMMap_TexPal, dirty, ReadVRAM_TexPal<u64>);
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_ABG, VRAMMap_ABG, dirty, &GPU::ReadVRAM_ABG<u64>);
|
||||
}
|
||||
|
||||
bool MakeVRAMFlat_ABGCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty)
|
||||
bool GPU::MakeVRAMFlat_BBGCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_ABG, VRAMMap_ABG, dirty, ReadVRAM_ABG<u64>);
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_BBG, VRAMMap_BBG, dirty, &GPU::ReadVRAM_BBG<u64>);
|
||||
}
|
||||
bool MakeVRAMFlat_BBGCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty)
|
||||
|
||||
bool GPU::MakeVRAMFlat_AOBJCoherent(NonStupidBitField<256*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_BBG, VRAMMap_BBG, dirty, ReadVRAM_BBG<u64>);
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_AOBJ, VRAMMap_AOBJ, dirty, &GPU::ReadVRAM_AOBJ<u64>);
|
||||
}
|
||||
|
||||
bool MakeVRAMFlat_AOBJCoherent(NonStupidBitField<256*1024/VRAMDirtyGranularity>& dirty)
|
||||
bool GPU::MakeVRAMFlat_BOBJCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_AOBJ, VRAMMap_AOBJ, dirty, ReadVRAM_AOBJ<u64>);
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_BOBJ, VRAMMap_BOBJ, dirty, &GPU::ReadVRAM_BOBJ<u64>);
|
||||
}
|
||||
bool MakeVRAMFlat_BOBJCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty)
|
||||
|
||||
bool GPU::MakeVRAMFlat_ABGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
return CopyLinearVRAM<16*1024>(VRAMFlat_BOBJ, VRAMMap_BOBJ, dirty, ReadVRAM_BOBJ<u64>);
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_ABGExtPal, VRAMMap_ABGExtPal, dirty, &GPU::ReadVRAM_ABGExtPal<u64>);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ReadVRAM_ABGExtPal(u32 addr)
|
||||
bool GPU::MakeVRAMFlat_BBGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
u32 mask = VRAMMap_ABGExtPal[(addr >> 13) & 0x3];
|
||||
|
||||
T ret = 0;
|
||||
if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0x7FFF];
|
||||
if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
|
||||
if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
|
||||
|
||||
return ret;
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_BBGExtPal, VRAMMap_BBGExtPal, dirty, &GPU::ReadVRAM_BBGExtPal<u64>);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ReadVRAM_BBGExtPal(u32 addr)
|
||||
bool GPU::MakeVRAMFlat_AOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
u32 mask = VRAMMap_BBGExtPal[(addr >> 13) & 0x3];
|
||||
|
||||
T ret = 0;
|
||||
if (mask & (1<<7)) ret |= *(T*)&VRAM_H[addr & 0x7FFF];
|
||||
|
||||
return ret;
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_AOBJExtPal, &VRAMMap_AOBJExtPal, dirty, &GPU::ReadVRAM_AOBJExtPal<u64>);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ReadVRAM_AOBJExtPal(u32 addr)
|
||||
bool GPU::MakeVRAMFlat_BOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty) noexcept
|
||||
{
|
||||
u32 mask = VRAMMap_AOBJExtPal;
|
||||
|
||||
T ret = 0;
|
||||
if (mask & (1<<4)) ret |= *(T*)&VRAM_F[addr & 0x1FFF];
|
||||
if (mask & (1<<5)) ret |= *(T*)&VRAM_G[addr & 0x1FFF];
|
||||
|
||||
return ret;
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_BOBJExtPal, &VRAMMap_BOBJExtPal, dirty, &GPU::ReadVRAM_BOBJExtPal<u64>);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ReadVRAM_BOBJExtPal(u32 addr)
|
||||
{
|
||||
u32 mask = VRAMMap_BOBJExtPal;
|
||||
|
||||
T ret = 0;
|
||||
if (mask & (1<<8)) ret |= *(T*)&VRAM_I[addr & 0x1FFF];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MakeVRAMFlat_ABGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty)
|
||||
{
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_ABGExtPal, VRAMMap_ABGExtPal, dirty, ReadVRAM_ABGExtPal<u64>);
|
||||
}
|
||||
bool MakeVRAMFlat_BBGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty)
|
||||
{
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_BBGExtPal, VRAMMap_BBGExtPal, dirty, ReadVRAM_BBGExtPal<u64>);
|
||||
}
|
||||
|
||||
bool MakeVRAMFlat_AOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty)
|
||||
{
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_AOBJExtPal, &VRAMMap_AOBJExtPal, dirty, ReadVRAM_AOBJExtPal<u64>);
|
||||
}
|
||||
bool MakeVRAMFlat_BOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty)
|
||||
{
|
||||
return CopyLinearVRAM<8*1024>(VRAMFlat_BOBJExtPal, &VRAMMap_BOBJExtPal, dirty, ReadVRAM_BOBJExtPal<u64>);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -85,9 +85,8 @@ using Platform::LogLevel;
|
|||
namespace GPU2D
|
||||
{
|
||||
|
||||
Unit::Unit(u32 num)
|
||||
Unit::Unit(u32 num, Melon::GPU& gpu) : Num(num), GPU(gpu)
|
||||
{
|
||||
Num = num;
|
||||
}
|
||||
|
||||
void Unit::Reset()
|
||||
|
@ -287,10 +286,10 @@ void Unit::Write8(u32 addr, u8 val)
|
|||
return;
|
||||
|
||||
case 0x10:
|
||||
if (!Num) GPU3D::SetRenderXPos((GPU3D::RenderXPos & 0xFF00) | val);
|
||||
if (!Num) GPU.GPU3D.SetRenderXPos((GPU.GPU3D.GetRenderXPos() & 0xFF00) | val);
|
||||
break;
|
||||
case 0x11:
|
||||
if (!Num) GPU3D::SetRenderXPos((GPU3D::RenderXPos & 0x00FF) | (val << 8));
|
||||
if (!Num) GPU.GPU3D.SetRenderXPos((GPU.GPU3D.GetRenderXPos() & 0x00FF) | (val << 8));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -383,7 +382,7 @@ void Unit::Write16(u32 addr, u16 val)
|
|||
return;
|
||||
|
||||
case 0x010:
|
||||
if (!Num) GPU3D::SetRenderXPos(val);
|
||||
if (!Num) GPU.GPU3D.SetRenderXPos(val);
|
||||
break;
|
||||
|
||||
case 0x068:
|
||||
|
@ -422,21 +421,21 @@ void Unit::Write16(u32 addr, u16 val)
|
|||
case 0x026: BGRotD[0] = val; return;
|
||||
case 0x028:
|
||||
BGXRef[0] = (BGXRef[0] & 0xFFFF0000) | val;
|
||||
if (GPU::VCount < 192) BGXRefInternal[0] = BGXRef[0];
|
||||
if (GPU.VCount < 192) BGXRefInternal[0] = BGXRef[0];
|
||||
return;
|
||||
case 0x02A:
|
||||
if (val & 0x0800) val |= 0xF000;
|
||||
BGXRef[0] = (BGXRef[0] & 0xFFFF) | (val << 16);
|
||||
if (GPU::VCount < 192) BGXRefInternal[0] = BGXRef[0];
|
||||
if (GPU.VCount < 192) BGXRefInternal[0] = BGXRef[0];
|
||||
return;
|
||||
case 0x02C:
|
||||
BGYRef[0] = (BGYRef[0] & 0xFFFF0000) | val;
|
||||
if (GPU::VCount < 192) BGYRefInternal[0] = BGYRef[0];
|
||||
if (GPU.VCount < 192) BGYRefInternal[0] = BGYRef[0];
|
||||
return;
|
||||
case 0x02E:
|
||||
if (val & 0x0800) val |= 0xF000;
|
||||
BGYRef[0] = (BGYRef[0] & 0xFFFF) | (val << 16);
|
||||
if (GPU::VCount < 192) BGYRefInternal[0] = BGYRef[0];
|
||||
if (GPU.VCount < 192) BGYRefInternal[0] = BGYRef[0];
|
||||
return;
|
||||
|
||||
case 0x030: BGRotA[1] = val; return;
|
||||
|
@ -445,21 +444,21 @@ void Unit::Write16(u32 addr, u16 val)
|
|||
case 0x036: BGRotD[1] = val; return;
|
||||
case 0x038:
|
||||
BGXRef[1] = (BGXRef[1] & 0xFFFF0000) | val;
|
||||
if (GPU::VCount < 192) BGXRefInternal[1] = BGXRef[1];
|
||||
if (GPU.VCount < 192) BGXRefInternal[1] = BGXRef[1];
|
||||
return;
|
||||
case 0x03A:
|
||||
if (val & 0x0800) val |= 0xF000;
|
||||
BGXRef[1] = (BGXRef[1] & 0xFFFF) | (val << 16);
|
||||
if (GPU::VCount < 192) BGXRefInternal[1] = BGXRef[1];
|
||||
if (GPU.VCount < 192) BGXRefInternal[1] = BGXRef[1];
|
||||
return;
|
||||
case 0x03C:
|
||||
BGYRef[1] = (BGYRef[1] & 0xFFFF0000) | val;
|
||||
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||
if (GPU.VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||
return;
|
||||
case 0x03E:
|
||||
if (val & 0x0800) val |= 0xF000;
|
||||
BGYRef[1] = (BGYRef[1] & 0xFFFF) | (val << 16);
|
||||
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||
if (GPU.VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||
return;
|
||||
|
||||
case 0x040:
|
||||
|
@ -541,23 +540,23 @@ void Unit::Write32(u32 addr, u32 val)
|
|||
case 0x028:
|
||||
if (val & 0x08000000) val |= 0xF0000000;
|
||||
BGXRef[0] = val;
|
||||
if (GPU::VCount < 192) BGXRefInternal[0] = BGXRef[0];
|
||||
if (GPU.VCount < 192) BGXRefInternal[0] = BGXRef[0];
|
||||
return;
|
||||
case 0x02C:
|
||||
if (val & 0x08000000) val |= 0xF0000000;
|
||||
BGYRef[0] = val;
|
||||
if (GPU::VCount < 192) BGYRefInternal[0] = BGYRef[0];
|
||||
if (GPU.VCount < 192) BGYRefInternal[0] = BGYRef[0];
|
||||
return;
|
||||
|
||||
case 0x038:
|
||||
if (val & 0x08000000) val |= 0xF0000000;
|
||||
BGXRef[1] = val;
|
||||
if (GPU::VCount < 192) BGXRefInternal[1] = BGXRef[1];
|
||||
if (GPU.VCount < 192) BGXRefInternal[1] = BGXRef[1];
|
||||
return;
|
||||
case 0x03C:
|
||||
if (val & 0x08000000) val |= 0xF0000000;
|
||||
BGYRef[1] = val;
|
||||
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||
if (GPU.VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -628,15 +627,15 @@ u16* Unit::GetBGExtPal(u32 slot, u32 pal)
|
|||
const u32 PaletteSize = 256 * 2;
|
||||
const u32 SlotSize = PaletteSize * 16;
|
||||
return (u16*)&(Num == 0
|
||||
? GPU::VRAMFlat_ABGExtPal
|
||||
: GPU::VRAMFlat_BBGExtPal)[slot * SlotSize + pal * PaletteSize];
|
||||
? GPU.VRAMFlat_ABGExtPal
|
||||
: GPU.VRAMFlat_BBGExtPal)[slot * SlotSize + pal * PaletteSize];
|
||||
}
|
||||
|
||||
u16* Unit::GetOBJExtPal()
|
||||
{
|
||||
return Num == 0
|
||||
? (u16*)GPU::VRAMFlat_AOBJExtPal
|
||||
: (u16*)GPU::VRAMFlat_BOBJExtPal;
|
||||
? (u16*)GPU.VRAMFlat_AOBJExtPal
|
||||
: (u16*)GPU.VRAMFlat_BOBJExtPal;
|
||||
}
|
||||
|
||||
void Unit::CheckWindows(u32 line)
|
||||
|
@ -698,12 +697,12 @@ void Unit::GetBGVRAM(u8*& data, u32& mask)
|
|||
{
|
||||
if (Num == 0)
|
||||
{
|
||||
data = GPU::VRAMFlat_ABG;
|
||||
data = GPU.VRAMFlat_ABG;
|
||||
mask = 0x7FFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = GPU::VRAMFlat_BBG;
|
||||
data = GPU.VRAMFlat_BBG;
|
||||
mask = 0x1FFFF;
|
||||
}
|
||||
}
|
||||
|
@ -712,12 +711,12 @@ void Unit::GetOBJVRAM(u8*& data, u32& mask)
|
|||
{
|
||||
if (Num == 0)
|
||||
{
|
||||
data = GPU::VRAMFlat_AOBJ;
|
||||
data = GPU.VRAMFlat_AOBJ;
|
||||
mask = 0x3FFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = GPU::VRAMFlat_BOBJ;
|
||||
data = GPU.VRAMFlat_BOBJ;
|
||||
mask = 0x1FFFF;
|
||||
}
|
||||
}
|
||||
|
|
11
src/GPU2D.h
11
src/GPU2D.h
|
@ -22,13 +22,20 @@
|
|||
#include "types.h"
|
||||
#include "Savestate.h"
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
namespace GPU2D
|
||||
{
|
||||
|
||||
class Unit
|
||||
{
|
||||
public:
|
||||
Unit(u32 num);
|
||||
// take a reference to the GPU so we can access its state
|
||||
// and ensure that it's not null
|
||||
Unit(u32 num, Melon::GPU& gpu);
|
||||
|
||||
Unit(const Unit&) = delete;
|
||||
Unit& operator=(const Unit&) = delete;
|
||||
|
@ -116,6 +123,8 @@ public:
|
|||
u32 CaptureCnt;
|
||||
|
||||
u16 MasterBrightness;
|
||||
private:
|
||||
Melon::GPU& GPU;
|
||||
};
|
||||
|
||||
class Renderer2D
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
|
||||
#include "GPU2D_Soft.h"
|
||||
#include "GPU.h"
|
||||
#include "GPU3D_OpenGL.h"
|
||||
|
||||
namespace GPU2D
|
||||
{
|
||||
|
||||
SoftRenderer::SoftRenderer()
|
||||
: Renderer2D()
|
||||
SoftRenderer::SoftRenderer(Melon::GPU& gpu)
|
||||
: Renderer2D(), GPU(gpu)
|
||||
{
|
||||
// initialize mosaic table
|
||||
for (int m = 0; m < 16; m++)
|
||||
|
@ -165,29 +166,29 @@ void SoftRenderer::DrawScanline(u32 line, Unit* unit)
|
|||
{
|
||||
CurUnit = unit;
|
||||
|
||||
int stride = GPU3D::CurrentRenderer->Accelerated ? (256*3 + 1) : 256;
|
||||
int stride = GPU.GPU3D.IsRendererAccelerated() ? (256*3 + 1) : 256;
|
||||
u32* dst = &Framebuffer[CurUnit->Num][stride * line];
|
||||
|
||||
int n3dline = line;
|
||||
line = GPU::VCount;
|
||||
line = GPU.VCount;
|
||||
|
||||
if (CurUnit->Num == 0)
|
||||
{
|
||||
auto bgDirty = GPU::VRAMDirty_ABG.DeriveState(GPU::VRAMMap_ABG);
|
||||
GPU::MakeVRAMFlat_ABGCoherent(bgDirty);
|
||||
auto bgExtPalDirty = GPU::VRAMDirty_ABGExtPal.DeriveState(GPU::VRAMMap_ABGExtPal);
|
||||
GPU::MakeVRAMFlat_ABGExtPalCoherent(bgExtPalDirty);
|
||||
auto objExtPalDirty = GPU::VRAMDirty_AOBJExtPal.DeriveState(&GPU::VRAMMap_AOBJExtPal);
|
||||
GPU::MakeVRAMFlat_AOBJExtPalCoherent(objExtPalDirty);
|
||||
auto bgDirty = GPU.VRAMDirty_ABG.DeriveState(GPU.VRAMMap_ABG, GPU);
|
||||
GPU.MakeVRAMFlat_ABGCoherent(bgDirty);
|
||||
auto bgExtPalDirty = GPU.VRAMDirty_ABGExtPal.DeriveState(GPU.VRAMMap_ABGExtPal, GPU);
|
||||
GPU.MakeVRAMFlat_ABGExtPalCoherent(bgExtPalDirty);
|
||||
auto objExtPalDirty = GPU.VRAMDirty_AOBJExtPal.DeriveState(&GPU.VRAMMap_AOBJExtPal, GPU);
|
||||
GPU.MakeVRAMFlat_AOBJExtPalCoherent(objExtPalDirty);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto bgDirty = GPU::VRAMDirty_BBG.DeriveState(GPU::VRAMMap_BBG);
|
||||
GPU::MakeVRAMFlat_BBGCoherent(bgDirty);
|
||||
auto bgExtPalDirty = GPU::VRAMDirty_BBGExtPal.DeriveState(GPU::VRAMMap_BBGExtPal);
|
||||
GPU::MakeVRAMFlat_BBGExtPalCoherent(bgExtPalDirty);
|
||||
auto objExtPalDirty = GPU::VRAMDirty_BOBJExtPal.DeriveState(&GPU::VRAMMap_BOBJExtPal);
|
||||
GPU::MakeVRAMFlat_BOBJExtPalCoherent(objExtPalDirty);
|
||||
auto bgDirty = GPU.VRAMDirty_BBG.DeriveState(GPU.VRAMMap_BBG, GPU);
|
||||
GPU.MakeVRAMFlat_BBGCoherent(bgDirty);
|
||||
auto bgExtPalDirty = GPU.VRAMDirty_BBGExtPal.DeriveState(GPU.VRAMMap_BBGExtPal, GPU);
|
||||
GPU.MakeVRAMFlat_BBGExtPalCoherent(bgExtPalDirty);
|
||||
auto objExtPalDirty = GPU.VRAMDirty_BOBJExtPal.DeriveState(&GPU.VRAMMap_BOBJExtPal, GPU);
|
||||
GPU.MakeVRAMFlat_BOBJExtPalCoherent(objExtPalDirty);
|
||||
}
|
||||
|
||||
bool forceblank = false;
|
||||
|
@ -205,11 +206,11 @@ void SoftRenderer::DrawScanline(u32 line, Unit* unit)
|
|||
|
||||
if (CurUnit->Num == 0)
|
||||
{
|
||||
if (!GPU3D::CurrentRenderer->Accelerated)
|
||||
_3DLine = GPU3D::GetLine(n3dline);
|
||||
if (!GPU.GPU3D.IsRendererAccelerated())
|
||||
_3DLine = GPU.GPU3D.GetLine(n3dline);
|
||||
else if (CurUnit->CaptureLatch && (((CurUnit->CaptureCnt >> 29) & 0x3) != 1))
|
||||
{
|
||||
_3DLine = GPU3D::GetLine(n3dline);
|
||||
_3DLine = GPU.GPU3D.GetLine(n3dline);
|
||||
//GPU3D::GLRenderer::PrepareCaptureFrame();
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +220,7 @@ void SoftRenderer::DrawScanline(u32 line, Unit* unit)
|
|||
for (int i = 0; i < 256; i++)
|
||||
dst[i] = 0xFFFFFFFF;
|
||||
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU.GPU3D.IsRendererAccelerated())
|
||||
{
|
||||
dst[256*3] = 0;
|
||||
}
|
||||
|
@ -253,9 +254,9 @@ void SoftRenderer::DrawScanline(u32 line, Unit* unit)
|
|||
case 2: // VRAM display
|
||||
{
|
||||
u32 vrambank = (CurUnit->DispCnt >> 18) & 0x3;
|
||||
if (GPU::VRAMMap_LCDC & (1<<vrambank))
|
||||
if (GPU.VRAMMap_LCDC & (1<<vrambank))
|
||||
{
|
||||
u16* vram = (u16*)GPU::VRAM[vrambank];
|
||||
u16* vram = (u16*)GPU.VRAM[vrambank];
|
||||
vram = &vram[line * 256];
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
|
@ -311,7 +312,7 @@ void SoftRenderer::DrawScanline(u32 line, Unit* unit)
|
|||
|
||||
u32 masterBrightness = CurUnit->MasterBrightness;
|
||||
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU.GPU3D.IsRendererAccelerated())
|
||||
{
|
||||
dst[256*3] = masterBrightness | (CurUnit->DispCnt & 0x30000);
|
||||
return;
|
||||
|
@ -363,11 +364,11 @@ void SoftRenderer::DrawScanline(u32 line, Unit* unit)
|
|||
void SoftRenderer::VBlankEnd(Unit* unitA, Unit* unitB)
|
||||
{
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU.GPU3D.IsRendererAccelerated())
|
||||
{
|
||||
if ((unitA->CaptureCnt & (1<<31)) && (((unitA->CaptureCnt >> 29) & 0x3) != 1))
|
||||
{
|
||||
reinterpret_cast<GPU3D::GLRenderer*>(GPU3D::CurrentRenderer.get())->PrepareCaptureFrame();
|
||||
reinterpret_cast<GPU3D::GLRenderer*>(GPU.GPU3D.GetCurrentRenderer())->PrepareCaptureFrame();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -380,10 +381,10 @@ void SoftRenderer::DoCapture(u32 line, u32 width)
|
|||
|
||||
// TODO: confirm this
|
||||
// it should work like VRAM display mode, which requires VRAM to be mapped to LCDC
|
||||
if (!(GPU::VRAMMap_LCDC & (1<<dstvram)))
|
||||
if (!(GPU.VRAMMap_LCDC & (1<<dstvram)))
|
||||
return;
|
||||
|
||||
u16* dst = (u16*)GPU::VRAM[dstvram];
|
||||
u16* dst = (u16*)GPU.VRAM[dstvram];
|
||||
u32 dstaddr = (((captureCnt >> 18) & 0x3) << 14) + (line * width);
|
||||
|
||||
// TODO: handle 3D in GPU3D::CurrentRenderer->Accelerated mode!!
|
||||
|
@ -396,7 +397,7 @@ void SoftRenderer::DoCapture(u32 line, u32 width)
|
|||
else
|
||||
{
|
||||
srcA = BGOBJLine;
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU.GPU3D.IsRendererAccelerated())
|
||||
{
|
||||
// in GPU3D::CurrentRenderer->Accelerated mode, compositing is normally done on the GPU
|
||||
// but when doing display capture, we do need the composited output
|
||||
|
@ -468,8 +469,8 @@ void SoftRenderer::DoCapture(u32 line, u32 width)
|
|||
else
|
||||
{
|
||||
u32 srcvram = (CurUnit->DispCnt >> 18) & 0x3;
|
||||
if (GPU::VRAMMap_LCDC & (1<<srcvram))
|
||||
srcB = (u16*)GPU::VRAM[srcvram];
|
||||
if (GPU.VRAMMap_LCDC & (1<<srcvram))
|
||||
srcB = (u16*)GPU.VRAM[srcvram];
|
||||
|
||||
if (((CurUnit->DispCnt >> 16) & 0x3) != 2)
|
||||
srcBaddr += ((captureCnt >> 26) & 0x3) << 14;
|
||||
|
@ -478,8 +479,8 @@ void SoftRenderer::DoCapture(u32 line, u32 width)
|
|||
dstaddr &= 0xFFFF;
|
||||
srcBaddr &= 0xFFFF;
|
||||
|
||||
static_assert(GPU::VRAMDirtyGranularity == 512, "");
|
||||
GPU::VRAMDirty[dstvram][(dstaddr * 2) / GPU::VRAMDirtyGranularity] = true;
|
||||
static_assert(Melon::VRAMDirtyGranularity == 512);
|
||||
GPU.VRAMDirty[dstvram][(dstaddr * 2) / Melon::VRAMDirtyGranularity] = true;
|
||||
|
||||
switch ((captureCnt >> 29) & 0x3)
|
||||
{
|
||||
|
@ -600,12 +601,12 @@ void SoftRenderer::DoCapture(u32 line, u32 width)
|
|||
{ \
|
||||
if ((bgCnt[num] & 0x0040) && (CurUnit->BGMosaicSize[0] > 0)) \
|
||||
{ \
|
||||
if (GPU3D::CurrentRenderer->Accelerated) DrawBG_##type<true, DrawPixel_Accel>(line, num); \
|
||||
if (GPU.GPU3D.IsRendererAccelerated()) DrawBG_##type<true, DrawPixel_Accel>(line, num); \
|
||||
else DrawBG_##type<true, DrawPixel_Normal>(line, num); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (GPU3D::CurrentRenderer->Accelerated) DrawBG_##type<false, DrawPixel_Accel>(line, num); \
|
||||
if (GPU.GPU3D.IsRendererAccelerated()) DrawBG_##type<false, DrawPixel_Accel>(line, num); \
|
||||
else DrawBG_##type<false, DrawPixel_Normal>(line, num); \
|
||||
} \
|
||||
} while (false)
|
||||
|
@ -615,18 +616,18 @@ void SoftRenderer::DoCapture(u32 line, u32 width)
|
|||
{ \
|
||||
if ((bgCnt[2] & 0x0040) && (CurUnit->BGMosaicSize[0] > 0)) \
|
||||
{ \
|
||||
if (GPU3D::CurrentRenderer->Accelerated) DrawBG_Large<true, DrawPixel_Accel>(line); \
|
||||
if (GPU.GPU3D.IsRendererAccelerated()) DrawBG_Large<true, DrawPixel_Accel>(line); \
|
||||
else DrawBG_Large<true, DrawPixel_Normal>(line); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (GPU3D::CurrentRenderer->Accelerated) DrawBG_Large<false, DrawPixel_Accel>(line); \
|
||||
if (GPU.GPU3D.IsRendererAccelerated()) DrawBG_Large<false, DrawPixel_Accel>(line); \
|
||||
else DrawBG_Large<false, DrawPixel_Normal>(line); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define DoInterleaveSprites(prio) \
|
||||
if (GPU3D::CurrentRenderer->Accelerated) InterleaveSprites<DrawPixel_Accel>(prio); else InterleaveSprites<DrawPixel_Normal>(prio);
|
||||
if (GPU.GPU3D.IsRendererAccelerated()) InterleaveSprites<DrawPixel_Accel>(prio); else InterleaveSprites<DrawPixel_Normal>(prio);
|
||||
|
||||
template<u32 bgmode>
|
||||
void SoftRenderer::DrawScanlineBGMode(u32 line)
|
||||
|
@ -756,8 +757,8 @@ void SoftRenderer::DrawScanline_BGOBJ(u32 line)
|
|||
}
|
||||
|
||||
u64 backdrop;
|
||||
if (CurUnit->Num) backdrop = *(u16*)&GPU::Palette[0x400];
|
||||
else backdrop = *(u16*)&GPU::Palette[0];
|
||||
if (CurUnit->Num) backdrop = *(u16*)&GPU.Palette[0x400];
|
||||
else backdrop = *(u16*)&GPU.Palette[0];
|
||||
|
||||
{
|
||||
u8 r = (backdrop & 0x001F) << 1;
|
||||
|
@ -794,7 +795,7 @@ void SoftRenderer::DrawScanline_BGOBJ(u32 line)
|
|||
// color special effects
|
||||
// can likely be optimized
|
||||
|
||||
if (!GPU3D::CurrentRenderer->Accelerated)
|
||||
if (!GPU.GPU3D.IsRendererAccelerated())
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
|
@ -940,7 +941,7 @@ void SoftRenderer::DrawBG_3D()
|
|||
{
|
||||
int i = 0;
|
||||
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
if (GPU.GPU3D.IsRendererAccelerated())
|
||||
{
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
|
@ -997,14 +998,14 @@ void SoftRenderer::DrawBG_Text(u32 line, u32 bgnum)
|
|||
tilesetaddr = ((bgcnt & 0x003C) << 12);
|
||||
tilemapaddr = ((bgcnt & 0x1F00) << 3);
|
||||
|
||||
pal = (u16*)&GPU::Palette[0x400];
|
||||
pal = (u16*)&GPU.Palette[0x400];
|
||||
}
|
||||
else
|
||||
{
|
||||
tilesetaddr = ((CurUnit->DispCnt & 0x07000000) >> 8) + ((bgcnt & 0x003C) << 12);
|
||||
tilemapaddr = ((CurUnit->DispCnt & 0x38000000) >> 11) + ((bgcnt & 0x1F00) << 3);
|
||||
|
||||
pal = (u16*)&GPU::Palette[0];
|
||||
pal = (u16*)&GPU.Palette[0];
|
||||
}
|
||||
|
||||
// adjust Y position in tilemap
|
||||
|
@ -1176,14 +1177,14 @@ void SoftRenderer::DrawBG_Affine(u32 line, u32 bgnum)
|
|||
tilesetaddr = ((bgcnt & 0x003C) << 12);
|
||||
tilemapaddr = ((bgcnt & 0x1F00) << 3);
|
||||
|
||||
pal = (u16*)&GPU::Palette[0x400];
|
||||
pal = (u16*)&GPU.Palette[0x400];
|
||||
}
|
||||
else
|
||||
{
|
||||
tilesetaddr = ((CurUnit->DispCnt & 0x07000000) >> 8) + ((bgcnt & 0x003C) << 12);
|
||||
tilemapaddr = ((CurUnit->DispCnt & 0x38000000) >> 11) + ((bgcnt & 0x1F00) << 3);
|
||||
|
||||
pal = (u16*)&GPU::Palette[0];
|
||||
pal = (u16*)&GPU.Palette[0];
|
||||
}
|
||||
|
||||
u16 curtile;
|
||||
|
@ -1330,8 +1331,8 @@ void SoftRenderer::DrawBG_Extended(u32 line, u32 bgnum)
|
|||
{
|
||||
// 256-color bitmap
|
||||
|
||||
if (CurUnit->Num) pal = (u16*)&GPU::Palette[0x400];
|
||||
else pal = (u16*)&GPU::Palette[0];
|
||||
if (CurUnit->Num) pal = (u16*)&GPU.Palette[0x400];
|
||||
else pal = (u16*)&GPU.Palette[0];
|
||||
|
||||
u8 color;
|
||||
|
||||
|
@ -1389,14 +1390,14 @@ void SoftRenderer::DrawBG_Extended(u32 line, u32 bgnum)
|
|||
tilesetaddr = ((bgcnt & 0x003C) << 12);
|
||||
tilemapaddr = ((bgcnt & 0x1F00) << 3);
|
||||
|
||||
pal = (u16*)&GPU::Palette[0x400];
|
||||
pal = (u16*)&GPU.Palette[0x400];
|
||||
}
|
||||
else
|
||||
{
|
||||
tilesetaddr = ((CurUnit->DispCnt & 0x07000000) >> 8) + ((bgcnt & 0x003C) << 12);
|
||||
tilemapaddr = ((CurUnit->DispCnt & 0x38000000) >> 11) + ((bgcnt & 0x1F00) << 3);
|
||||
|
||||
pal = (u16*)&GPU::Palette[0];
|
||||
pal = (u16*)&GPU.Palette[0];
|
||||
}
|
||||
|
||||
u16 curtile;
|
||||
|
@ -1507,8 +1508,8 @@ void SoftRenderer::DrawBG_Large(u32 line) // BG is always BG2
|
|||
|
||||
// 256-color bitmap
|
||||
|
||||
if (CurUnit->Num) pal = (u16*)&GPU::Palette[0x400];
|
||||
else pal = (u16*)&GPU::Palette[0];
|
||||
if (CurUnit->Num) pal = (u16*)&GPU.Palette[0x400];
|
||||
else pal = (u16*)&GPU.Palette[0];
|
||||
|
||||
u8 color;
|
||||
|
||||
|
@ -1581,7 +1582,7 @@ template <SoftRenderer::DrawPixel drawPixel>
|
|||
void SoftRenderer::InterleaveSprites(u32 prio)
|
||||
{
|
||||
u32* objLine = OBJLine[CurUnit->Num];
|
||||
u16* pal = (u16*)&GPU::Palette[CurUnit->Num ? 0x600 : 0x200];
|
||||
u16* pal = (u16*)&GPU.Palette[CurUnit->Num ? 0x600 : 0x200];
|
||||
|
||||
if (CurUnit->DispCnt & 0x80000000)
|
||||
{
|
||||
|
@ -1655,13 +1656,13 @@ void SoftRenderer::DrawSprites(u32 line, Unit* unit)
|
|||
|
||||
if (CurUnit->Num == 0)
|
||||
{
|
||||
auto objDirty = GPU::VRAMDirty_AOBJ.DeriveState(GPU::VRAMMap_AOBJ);
|
||||
GPU::MakeVRAMFlat_AOBJCoherent(objDirty);
|
||||
auto objDirty = GPU.VRAMDirty_AOBJ.DeriveState(GPU.VRAMMap_AOBJ, GPU);
|
||||
GPU.MakeVRAMFlat_AOBJCoherent(objDirty);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto objDirty = GPU::VRAMDirty_BOBJ.DeriveState(GPU::VRAMMap_BOBJ);
|
||||
GPU::MakeVRAMFlat_BOBJCoherent(objDirty);
|
||||
auto objDirty = GPU.VRAMDirty_BOBJ.DeriveState(GPU.VRAMMap_BOBJ, GPU);
|
||||
GPU.MakeVRAMFlat_BOBJCoherent(objDirty);
|
||||
}
|
||||
|
||||
NumSprites[CurUnit->Num] = 0;
|
||||
|
@ -1669,7 +1670,7 @@ void SoftRenderer::DrawSprites(u32 line, Unit* unit)
|
|||
memset(OBJWindow[CurUnit->Num], 0, 256);
|
||||
if (!(CurUnit->DispCnt & 0x1000)) return;
|
||||
|
||||
u16* oam = (u16*)&GPU::OAM[CurUnit->Num ? 0x400 : 0];
|
||||
u16* oam = (u16*)&GPU.OAM[CurUnit->Num ? 0x400 : 0];
|
||||
|
||||
const s32 spritewidth[16] =
|
||||
{
|
||||
|
@ -1764,7 +1765,7 @@ void SoftRenderer::DrawSprites(u32 line, Unit* unit)
|
|||
template<bool window>
|
||||
void SoftRenderer::DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos)
|
||||
{
|
||||
u16* oam = (u16*)&GPU::OAM[CurUnit->Num ? 0x400 : 0];
|
||||
u16* oam = (u16*)&GPU.OAM[CurUnit->Num ? 0x400 : 0];
|
||||
u16* attrib = &oam[num * 4];
|
||||
u16* rotparams = &oam[(((attrib[1] >> 9) & 0x1F) * 16) + 3];
|
||||
|
||||
|
@ -1976,7 +1977,7 @@ void SoftRenderer::DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight,
|
|||
template<bool window>
|
||||
void SoftRenderer::DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos)
|
||||
{
|
||||
u16* oam = (u16*)&GPU::OAM[CurUnit->Num ? 0x400 : 0];
|
||||
u16* oam = (u16*)&GPU.OAM[CurUnit->Num ? 0x400 : 0];
|
||||
u16* attrib = &oam[num * 4];
|
||||
|
||||
u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000;
|
||||
|
|
|
@ -20,19 +20,25 @@
|
|||
|
||||
#include "GPU2D.h"
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
namespace GPU2D
|
||||
{
|
||||
|
||||
class SoftRenderer : public Renderer2D
|
||||
{
|
||||
public:
|
||||
SoftRenderer();
|
||||
SoftRenderer(Melon::GPU& gpu);
|
||||
~SoftRenderer() override {}
|
||||
|
||||
void DrawScanline(u32 line, Unit* unit) override;
|
||||
void DrawSprites(u32 line, Unit* unit) override;
|
||||
void VBlankEnd(Unit* unitA, Unit* unitB) override;
|
||||
private:
|
||||
Melon::GPU& GPU;
|
||||
alignas(8) u32 BGOBJLine[256*3];
|
||||
u32* _3DLine;
|
||||
|
||||
|
|
282
src/GPU3D.cpp
282
src/GPU3D.cpp
|
@ -138,158 +138,9 @@ const u8 CmdNumParams[256] =
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
u64 _contents;
|
||||
struct
|
||||
{
|
||||
u32 Param;
|
||||
u8 Command;
|
||||
};
|
||||
|
||||
} CmdFIFOEntry;
|
||||
|
||||
FIFO<CmdFIFOEntry, 256> CmdFIFO;
|
||||
FIFO<CmdFIFOEntry, 4> CmdPIPE;
|
||||
|
||||
FIFO<CmdFIFOEntry, 64> CmdStallQueue;
|
||||
|
||||
u32 NumCommands, CurCommand, ParamCount, TotalParams;
|
||||
|
||||
bool GeometryEnabled;
|
||||
bool RenderingEnabled;
|
||||
|
||||
u32 DispCnt;
|
||||
u8 AlphaRefVal, AlphaRef;
|
||||
|
||||
u16 ToonTable[32];
|
||||
u16 EdgeTable[8];
|
||||
|
||||
u32 FogColor, FogOffset;
|
||||
u8 FogDensityTable[32];
|
||||
|
||||
u32 ClearAttr1, ClearAttr2;
|
||||
|
||||
u32 RenderDispCnt;
|
||||
u8 RenderAlphaRef;
|
||||
|
||||
u16 RenderToonTable[32];
|
||||
u16 RenderEdgeTable[8];
|
||||
|
||||
u32 RenderFogColor, RenderFogOffset, RenderFogShift;
|
||||
u8 RenderFogDensityTable[34];
|
||||
|
||||
u32 RenderClearAttr1, RenderClearAttr2;
|
||||
|
||||
bool RenderFrameIdentical;
|
||||
|
||||
u16 RenderXPos;
|
||||
|
||||
u32 ZeroDotWLimit;
|
||||
|
||||
u32 GXStat;
|
||||
|
||||
u32 ExecParams[32];
|
||||
u32 ExecParamCount;
|
||||
|
||||
u64 Timestamp;
|
||||
s32 CycleCount;
|
||||
s32 VertexPipeline;
|
||||
s32 NormalPipeline;
|
||||
s32 PolygonPipeline;
|
||||
s32 VertexSlotCounter;
|
||||
u32 VertexSlotsFree;
|
||||
|
||||
u32 NumPushPopCommands;
|
||||
u32 NumTestCommands;
|
||||
|
||||
|
||||
u32 MatrixMode;
|
||||
|
||||
s32 ProjMatrix[16];
|
||||
s32 PosMatrix[16];
|
||||
s32 VecMatrix[16];
|
||||
s32 TexMatrix[16];
|
||||
|
||||
s32 ClipMatrix[16];
|
||||
bool ClipMatrixDirty;
|
||||
|
||||
u32 Viewport[6];
|
||||
|
||||
s32 ProjMatrixStack[16];
|
||||
s32 PosMatrixStack[32][16];
|
||||
s32 VecMatrixStack[32][16];
|
||||
s32 TexMatrixStack[16];
|
||||
s32 ProjMatrixStackPointer;
|
||||
s32 PosMatrixStackPointer;
|
||||
s32 TexMatrixStackPointer;
|
||||
|
||||
void MatrixLoadIdentity(s32* m);
|
||||
void UpdateClipMatrix();
|
||||
|
||||
|
||||
u32 PolygonMode;
|
||||
s16 CurVertex[3];
|
||||
u8 VertexColor[3];
|
||||
s16 TexCoords[2];
|
||||
s16 RawTexCoords[2];
|
||||
s16 Normal[3];
|
||||
|
||||
s16 LightDirection[4][3];
|
||||
u8 LightColor[4][3];
|
||||
u8 MatDiffuse[3];
|
||||
u8 MatAmbient[3];
|
||||
u8 MatSpecular[3];
|
||||
u8 MatEmission[3];
|
||||
|
||||
bool UseShininessTable;
|
||||
u8 ShininessTable[128];
|
||||
|
||||
u32 PolygonAttr;
|
||||
u32 CurPolygonAttr;
|
||||
|
||||
u32 TexParam;
|
||||
u32 TexPalette;
|
||||
|
||||
s32 PosTestResult[4];
|
||||
s16 VecTestResult[3];
|
||||
|
||||
Vertex TempVertexBuffer[4];
|
||||
u32 VertexNum;
|
||||
u32 VertexNumInPoly;
|
||||
u32 NumConsecutivePolygons;
|
||||
Polygon* LastStripPolygon;
|
||||
u32 NumOpaquePolygons;
|
||||
|
||||
Vertex VertexRAM[6144 * 2];
|
||||
Polygon PolygonRAM[2048 * 2];
|
||||
|
||||
Vertex* CurVertexRAM;
|
||||
Polygon* CurPolygonRAM;
|
||||
u32 NumVertices, NumPolygons;
|
||||
u32 CurRAMBank;
|
||||
|
||||
std::array<Polygon*,2048> RenderPolygonRAM;
|
||||
u32 RenderNumPolygons;
|
||||
|
||||
u32 FlushRequest;
|
||||
u32 FlushAttributes;
|
||||
|
||||
std::unique_ptr<GPU3D::Renderer3D> CurrentRenderer = {};
|
||||
|
||||
bool AbortFrame;
|
||||
|
||||
bool Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
CurrentRenderer = nullptr;
|
||||
}
|
||||
|
||||
void ResetRenderingState()
|
||||
void GPU3D::ResetRenderingState() noexcept
|
||||
{
|
||||
RenderNumPolygons = 0;
|
||||
|
||||
|
@ -308,7 +159,7 @@ void ResetRenderingState()
|
|||
RenderClearAttr2 = 0x00007FFF;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void GPU3D::Reset() noexcept
|
||||
{
|
||||
CmdFIFO.Clear();
|
||||
CmdPIPE.Clear();
|
||||
|
@ -389,7 +240,7 @@ void Reset()
|
|||
AbortFrame = false;
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
void GPU3D::DoSavestate(Savestate* file) noexcept
|
||||
{
|
||||
file->Section("GP3D");
|
||||
|
||||
|
@ -634,7 +485,7 @@ void DoSavestate(Savestate* file)
|
|||
|
||||
|
||||
|
||||
void SetEnabled(bool geometry, bool rendering)
|
||||
void GPU3D::SetEnabled(bool geometry, bool rendering) noexcept
|
||||
{
|
||||
GeometryEnabled = geometry;
|
||||
RenderingEnabled = rendering;
|
||||
|
@ -767,7 +618,7 @@ void MatrixTranslate(s32* m, s32* s)
|
|||
m[15] += ((s64)s[0]*m[3] + (s64)s[1]*m[7] + (s64)s[2]*m[11]) >> 12;
|
||||
}
|
||||
|
||||
void UpdateClipMatrix()
|
||||
void GPU3D::UpdateClipMatrix() noexcept
|
||||
{
|
||||
if (!ClipMatrixDirty) return;
|
||||
ClipMatrixDirty = false;
|
||||
|
@ -778,7 +629,7 @@ void UpdateClipMatrix()
|
|||
|
||||
|
||||
|
||||
void AddCycles(s32 num)
|
||||
void GPU3D::AddCycles(s32 num) noexcept
|
||||
{
|
||||
CycleCount += num;
|
||||
|
||||
|
@ -809,7 +660,7 @@ void AddCycles(s32 num)
|
|||
}
|
||||
}
|
||||
|
||||
void NextVertexSlot()
|
||||
void GPU3D::NextVertexSlot() noexcept
|
||||
{
|
||||
s32 num = (9 - VertexSlotCounter) + 1;
|
||||
|
||||
|
@ -852,7 +703,7 @@ void NextVertexSlot()
|
|||
}
|
||||
}
|
||||
|
||||
void StallPolygonPipeline(s32 delay, s32 nonstalldelay)
|
||||
void GPU3D::StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept
|
||||
{
|
||||
if (PolygonPipeline > 0)
|
||||
{
|
||||
|
@ -907,7 +758,7 @@ void ClipSegment(Vertex* outbuf, Vertex* vin, Vertex* vout)
|
|||
}
|
||||
|
||||
template<int comp, bool attribs>
|
||||
int ClipAgainstPlane(Vertex* vertices, int nverts, int clipstart)
|
||||
int ClipAgainstPlane(const GPU3D& gpu, Vertex* vertices, int nverts, int clipstart)
|
||||
{
|
||||
Vertex temp[10];
|
||||
int prev, next;
|
||||
|
@ -927,7 +778,7 @@ int ClipAgainstPlane(Vertex* vertices, int nverts, int clipstart)
|
|||
Vertex vtx = vertices[i];
|
||||
if (vtx.Position[comp] > vtx.Position[3])
|
||||
{
|
||||
if ((comp == 2) && (!(CurPolygonAttr & (1<<12)))) return 0;
|
||||
if ((comp == 2) && (!(gpu.CurPolygonAttr & (1<<12)))) return 0;
|
||||
|
||||
Vertex* vprev = &vertices[prev];
|
||||
if (vprev->Position[comp] <= vprev->Position[3])
|
||||
|
@ -988,7 +839,7 @@ int ClipAgainstPlane(Vertex* vertices, int nverts, int clipstart)
|
|||
}
|
||||
|
||||
template<bool attribs>
|
||||
int ClipPolygon(Vertex* vertices, int nverts, int clipstart)
|
||||
int ClipPolygon(GPU3D& gpu, Vertex* vertices, int nverts, int clipstart)
|
||||
{
|
||||
// clip.
|
||||
// for each vertex:
|
||||
|
@ -1001,13 +852,13 @@ int ClipPolygon(Vertex* vertices, int nverts, int clipstart)
|
|||
// clipping seems to process the Y plane before the X plane.
|
||||
|
||||
// Z clipping
|
||||
nverts = ClipAgainstPlane<2, attribs>(vertices, nverts, clipstart);
|
||||
nverts = ClipAgainstPlane<2, attribs>(gpu, vertices, nverts, clipstart);
|
||||
|
||||
// Y clipping
|
||||
nverts = ClipAgainstPlane<1, attribs>(vertices, nverts, clipstart);
|
||||
nverts = ClipAgainstPlane<1, attribs>(gpu, vertices, nverts, clipstart);
|
||||
|
||||
// X clipping
|
||||
nverts = ClipAgainstPlane<0, attribs>(vertices, nverts, clipstart);
|
||||
nverts = ClipAgainstPlane<0, attribs>(gpu, vertices, nverts, clipstart);
|
||||
|
||||
return nverts;
|
||||
}
|
||||
|
@ -1020,7 +871,7 @@ bool ClipCoordsEqual(Vertex* a, Vertex* b)
|
|||
a->Position[3] == b->Position[3];
|
||||
}
|
||||
|
||||
void SubmitPolygon()
|
||||
void GPU3D::SubmitPolygon() noexcept
|
||||
{
|
||||
Vertex clippedvertices[10];
|
||||
Vertex* reusedvertices[2];
|
||||
|
@ -1153,7 +1004,7 @@ void SubmitPolygon()
|
|||
|
||||
// clipping
|
||||
|
||||
nverts = ClipPolygon<true>(clippedvertices, nverts, clipstart);
|
||||
nverts = ClipPolygon<true>(*this, clippedvertices, nverts, clipstart);
|
||||
if (nverts == 0)
|
||||
{
|
||||
LastStripPolygon = NULL;
|
||||
|
@ -1425,7 +1276,7 @@ void SubmitPolygon()
|
|||
LastStripPolygon = NULL;
|
||||
}
|
||||
|
||||
void SubmitVertex()
|
||||
void GPU3D::SubmitVertex() noexcept
|
||||
{
|
||||
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
|
||||
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
|
||||
|
@ -1523,7 +1374,7 @@ void SubmitVertex()
|
|||
AddCycles(3);
|
||||
}
|
||||
|
||||
void CalculateLighting()
|
||||
void GPU3D::CalculateLighting() noexcept
|
||||
{
|
||||
if ((TexParam >> 30) == 2)
|
||||
{
|
||||
|
@ -1598,7 +1449,7 @@ void CalculateLighting()
|
|||
}
|
||||
|
||||
|
||||
void BoxTest(u32* params)
|
||||
void GPU3D::BoxTest(u32* params) noexcept
|
||||
{
|
||||
Vertex cube[8];
|
||||
Vertex face[10];
|
||||
|
@ -1642,7 +1493,7 @@ void BoxTest(u32* params)
|
|||
|
||||
// front face (-Z)
|
||||
face[0] = cube[0]; face[1] = cube[1]; face[2] = cube[2]; face[3] = cube[3];
|
||||
res = ClipPolygon<false>(face, 4, 0);
|
||||
res = ClipPolygon<false>(*this, face, 4, 0);
|
||||
if (res > 0)
|
||||
{
|
||||
GXStat |= (1<<1);
|
||||
|
@ -1651,7 +1502,7 @@ void BoxTest(u32* params)
|
|||
|
||||
// back face (+Z)
|
||||
face[0] = cube[4]; face[1] = cube[5]; face[2] = cube[6]; face[3] = cube[7];
|
||||
res = ClipPolygon<false>(face, 4, 0);
|
||||
res = ClipPolygon<false>(*this, face, 4, 0);
|
||||
if (res > 0)
|
||||
{
|
||||
GXStat |= (1<<1);
|
||||
|
@ -1660,7 +1511,7 @@ void BoxTest(u32* params)
|
|||
|
||||
// left face (-X)
|
||||
face[0] = cube[0]; face[1] = cube[3]; face[2] = cube[4]; face[3] = cube[5];
|
||||
res = ClipPolygon<false>(face, 4, 0);
|
||||
res = ClipPolygon<false>(*this, face, 4, 0);
|
||||
if (res > 0)
|
||||
{
|
||||
GXStat |= (1<<1);
|
||||
|
@ -1669,7 +1520,7 @@ void BoxTest(u32* params)
|
|||
|
||||
// right face (+X)
|
||||
face[0] = cube[1]; face[1] = cube[2]; face[2] = cube[7]; face[3] = cube[6];
|
||||
res = ClipPolygon<false>(face, 4, 0);
|
||||
res = ClipPolygon<false>(*this, face, 4, 0);
|
||||
if (res > 0)
|
||||
{
|
||||
GXStat |= (1<<1);
|
||||
|
@ -1678,7 +1529,7 @@ void BoxTest(u32* params)
|
|||
|
||||
// bottom face (-Y)
|
||||
face[0] = cube[0]; face[1] = cube[1]; face[2] = cube[6]; face[3] = cube[5];
|
||||
res = ClipPolygon<false>(face, 4, 0);
|
||||
res = ClipPolygon<false>(*this, face, 4, 0);
|
||||
if (res > 0)
|
||||
{
|
||||
GXStat |= (1<<1);
|
||||
|
@ -1687,7 +1538,7 @@ void BoxTest(u32* params)
|
|||
|
||||
// top face (+Y)
|
||||
face[0] = cube[2]; face[1] = cube[3]; face[2] = cube[4]; face[3] = cube[7];
|
||||
res = ClipPolygon<false>(face, 4, 0);
|
||||
res = ClipPolygon<false>(*this, face, 4, 0);
|
||||
if (res > 0)
|
||||
{
|
||||
GXStat |= (1<<1);
|
||||
|
@ -1695,7 +1546,7 @@ void BoxTest(u32* params)
|
|||
}
|
||||
}
|
||||
|
||||
void PosTest()
|
||||
void GPU3D::PosTest() noexcept
|
||||
{
|
||||
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
|
||||
|
||||
|
@ -1708,7 +1559,7 @@ void PosTest()
|
|||
AddCycles(5);
|
||||
}
|
||||
|
||||
void VecTest(u32 param)
|
||||
void GPU3D::VecTest(u32 param) noexcept
|
||||
{
|
||||
// TODO: maybe it overwrites the normal registers, too
|
||||
|
||||
|
@ -1731,7 +1582,7 @@ void VecTest(u32 param)
|
|||
|
||||
|
||||
|
||||
void CmdFIFOWrite(CmdFIFOEntry& entry)
|
||||
void GPU3D::CmdFIFOWrite(CmdFIFOEntry& entry) noexcept
|
||||
{
|
||||
if (CmdFIFO.IsEmpty() && !CmdPIPE.IsFull())
|
||||
{
|
||||
|
@ -1767,7 +1618,7 @@ void CmdFIFOWrite(CmdFIFOEntry& entry)
|
|||
}
|
||||
}
|
||||
|
||||
CmdFIFOEntry CmdFIFORead()
|
||||
GPU3D::CmdFIFOEntry GPU3D::CmdFIFORead() noexcept
|
||||
{
|
||||
CmdFIFOEntry ret = CmdPIPE.Read();
|
||||
|
||||
|
@ -1800,39 +1651,7 @@ CmdFIFOEntry CmdFIFORead()
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline void VertexPipelineSubmitCmd()
|
||||
{
|
||||
// vertex commands 0x24, 0x25, 0x26, 0x27, 0x28
|
||||
if (!(VertexSlotsFree & 0x1)) NextVertexSlot();
|
||||
else AddCycles(1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
inline void VertexPipelineCmdDelayed6()
|
||||
{
|
||||
// commands 0x20, 0x30, 0x31, 0x72 that can run 6 cycles after a vertex
|
||||
if (VertexPipeline > 2) AddCycles((VertexPipeline - 2) + 1);
|
||||
else AddCycles(NormalPipeline + 1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
inline void VertexPipelineCmdDelayed8()
|
||||
{
|
||||
// commands 0x29, 0x2A, 0x2B, 0x33, 0x34, 0x41, 0x60, 0x71 that can run 8 cycles after a vertex
|
||||
if (VertexPipeline > 0) AddCycles(VertexPipeline + 1);
|
||||
else AddCycles(NormalPipeline + 1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
inline void VertexPipelineCmdDelayed4()
|
||||
{
|
||||
// all other commands can run 4 cycles after a vertex
|
||||
// no need to do much here since that is the minimum
|
||||
AddCycles(NormalPipeline + 1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
void ExecuteCommand()
|
||||
void GPU3D::ExecuteCommand() noexcept
|
||||
{
|
||||
CmdFIFOEntry entry = CmdFIFORead();
|
||||
|
||||
|
@ -2430,13 +2249,13 @@ void ExecuteCommand()
|
|||
}
|
||||
}
|
||||
|
||||
s32 CyclesToRunFor()
|
||||
s32 GPU3D::CyclesToRunFor() const noexcept
|
||||
{
|
||||
if (CycleCount < 0) return 0;
|
||||
return CycleCount;
|
||||
}
|
||||
|
||||
void FinishWork(s32 cycles)
|
||||
void GPU3D::FinishWork(s32 cycles) noexcept
|
||||
{
|
||||
AddCycles(cycles);
|
||||
if (NormalPipeline)
|
||||
|
@ -2450,7 +2269,7 @@ void FinishWork(s32 cycles)
|
|||
GXStat &= ~(1<<27);
|
||||
}
|
||||
|
||||
void Run()
|
||||
void GPU3D::Run() noexcept
|
||||
{
|
||||
if (!GeometryEnabled || FlushRequest ||
|
||||
(CmdPIPE.IsEmpty() && !(GXStat & (1<<27))))
|
||||
|
@ -2485,7 +2304,7 @@ void Run()
|
|||
}
|
||||
|
||||
|
||||
void CheckFIFOIRQ()
|
||||
void GPU3D::CheckFIFOIRQ() noexcept
|
||||
{
|
||||
bool irq = false;
|
||||
switch (GXStat >> 30)
|
||||
|
@ -2498,18 +2317,18 @@ void CheckFIFOIRQ()
|
|||
else NDS::ClearIRQ(0, NDS::IRQ_GXFIFO);
|
||||
}
|
||||
|
||||
void CheckFIFODMA()
|
||||
void GPU3D::CheckFIFODMA() noexcept
|
||||
{
|
||||
if (CmdFIFO.Level() < 128)
|
||||
NDS::CheckDMAs(0, 0x07);
|
||||
}
|
||||
|
||||
void VCount144()
|
||||
void GPU3D::VCount144() noexcept
|
||||
{
|
||||
CurrentRenderer->VCount144();
|
||||
}
|
||||
|
||||
void RestartFrame()
|
||||
void GPU3D::RestartFrame() noexcept
|
||||
{
|
||||
CurrentRenderer->RestartFrame();
|
||||
}
|
||||
|
@ -2527,7 +2346,7 @@ bool YSort(Polygon* a, Polygon* b)
|
|||
return a->SortKey < b->SortKey;
|
||||
}
|
||||
|
||||
void VBlank()
|
||||
void GPU3D::VBlank() noexcept
|
||||
{
|
||||
if (GeometryEnabled)
|
||||
{
|
||||
|
@ -2604,21 +2423,20 @@ void VBlank()
|
|||
}
|
||||
}
|
||||
|
||||
void VCount215()
|
||||
void GPU3D::VCount215() noexcept
|
||||
{
|
||||
CurrentRenderer->RenderFrame();
|
||||
}
|
||||
|
||||
void SetRenderXPos(u16 xpos)
|
||||
void GPU3D::SetRenderXPos(u16 xpos) noexcept
|
||||
{
|
||||
if (!RenderingEnabled) return;
|
||||
|
||||
RenderXPos = xpos & 0x01FF;
|
||||
}
|
||||
|
||||
u32 ScrolledLine[256];
|
||||
|
||||
u32* GetLine(int line)
|
||||
u32* GPU3D::GetLine(int line) noexcept
|
||||
{
|
||||
if (!AbortFrame)
|
||||
{
|
||||
|
@ -2653,8 +2471,12 @@ u32* GetLine(int line)
|
|||
return ScrolledLine;
|
||||
}
|
||||
|
||||
bool GPU3D::IsRendererAccelerated() const noexcept
|
||||
{
|
||||
return CurrentRenderer && CurrentRenderer->Accelerated;
|
||||
}
|
||||
|
||||
void WriteToGXFIFO(u32 val)
|
||||
void GPU3D::WriteToGXFIFO(u32 val) noexcept
|
||||
{
|
||||
if (NumCommands == 0)
|
||||
{
|
||||
|
@ -2693,7 +2515,7 @@ void WriteToGXFIFO(u32 val)
|
|||
}
|
||||
|
||||
|
||||
u8 Read8(u32 addr)
|
||||
u8 GPU3D::Read8(u32 addr) noexcept
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -2732,7 +2554,7 @@ u8 Read8(u32 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u16 Read16(u32 addr)
|
||||
u16 GPU3D::Read16(u32 addr) noexcept
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -2776,7 +2598,7 @@ u16 Read16(u32 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 Read32(u32 addr)
|
||||
u32 GPU3D::Read32(u32 addr) noexcept
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -2829,7 +2651,7 @@ u32 Read32(u32 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Write8(u32 addr, u8 val)
|
||||
void GPU3D::Write8(u32 addr, u8 val) noexcept
|
||||
{
|
||||
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
|
||||
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
|
||||
|
@ -2879,7 +2701,7 @@ void Write8(u32 addr, u8 val)
|
|||
Log(LogLevel::Debug, "unknown GPU3D write8 %08X %02X\n", addr, val);
|
||||
}
|
||||
|
||||
void Write16(u32 addr, u16 val)
|
||||
void GPU3D::Write16(u32 addr, u16 val) noexcept
|
||||
{
|
||||
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
|
||||
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
|
||||
|
@ -2966,7 +2788,7 @@ void Write16(u32 addr, u16 val)
|
|||
Log(LogLevel::Debug, "unknown GPU3D write16 %08X %04X\n", addr, val);
|
||||
}
|
||||
|
||||
void Write32(u32 addr, u32 val)
|
||||
void GPU3D::Write32(u32 addr, u32 val) noexcept
|
||||
{
|
||||
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
|
||||
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
|
||||
|
|
276
src/GPU3D.h
276
src/GPU3D.h
|
@ -22,8 +22,13 @@
|
|||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
#include "GPU.h"
|
||||
#include "Savestate.h"
|
||||
#include "FIFO.h"
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
struct RenderSettings;
|
||||
}
|
||||
|
||||
namespace GPU3D
|
||||
{
|
||||
|
@ -79,60 +84,246 @@ struct Polygon
|
|||
|
||||
};
|
||||
|
||||
extern u32 RenderDispCnt;
|
||||
extern u8 RenderAlphaRef;
|
||||
class Renderer3D;
|
||||
|
||||
extern u16 RenderToonTable[32];
|
||||
extern u16 RenderEdgeTable[8];
|
||||
class GPU3D
|
||||
{
|
||||
public:
|
||||
GPU3D() noexcept = default;
|
||||
~GPU3D() noexcept = default;
|
||||
void Reset() noexcept;
|
||||
|
||||
extern u32 RenderFogColor, RenderFogOffset, RenderFogShift;
|
||||
extern u8 RenderFogDensityTable[34];
|
||||
void DoSavestate(Savestate* file) noexcept;
|
||||
|
||||
extern u32 RenderClearAttr1, RenderClearAttr2;
|
||||
void SetEnabled(bool geometry, bool rendering) noexcept;
|
||||
|
||||
extern bool RenderFrameIdentical;
|
||||
void ExecuteCommand() noexcept;
|
||||
|
||||
extern u16 RenderXPos;
|
||||
s32 CyclesToRunFor() const noexcept;
|
||||
void Run() noexcept;
|
||||
void CheckFIFOIRQ() noexcept;
|
||||
void CheckFIFODMA() noexcept;
|
||||
|
||||
extern std::array<Polygon*,2048> RenderPolygonRAM;
|
||||
extern u32 RenderNumPolygons;
|
||||
void VCount144() noexcept;
|
||||
void VBlank() noexcept;
|
||||
void VCount215() noexcept;
|
||||
|
||||
extern bool AbortFrame;
|
||||
void RestartFrame() noexcept;
|
||||
|
||||
extern u64 Timestamp;
|
||||
void SetRenderXPos(u16 xpos) noexcept;
|
||||
[[nodiscard]] u16 GetRenderXPos() const noexcept { return RenderXPos; }
|
||||
u32* GetLine(int line) noexcept;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
void WriteToGXFIFO(u32 val) noexcept;
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
[[nodiscard]] bool IsRendererAccelerated() const noexcept;
|
||||
[[nodiscard]] Renderer3D* GetCurrentRenderer() noexcept { return CurrentRenderer.get(); }
|
||||
[[nodiscard]] const Renderer3D* GetCurrentRenderer() const noexcept { return CurrentRenderer.get(); }
|
||||
void SetCurrentRenderer(std::unique_ptr<Renderer3D>&& renderer) noexcept { CurrentRenderer = std::move(renderer); }
|
||||
|
||||
void SetEnabled(bool geometry, bool rendering);
|
||||
u8 Read8(u32 addr) noexcept;
|
||||
u16 Read16(u32 addr) noexcept;
|
||||
u32 Read32(u32 addr) noexcept;
|
||||
void Write8(u32 addr, u8 val) noexcept;
|
||||
void Write16(u32 addr, u16 val) noexcept;
|
||||
void Write32(u32 addr, u32 val) noexcept;
|
||||
private:
|
||||
typedef union
|
||||
{
|
||||
u64 _contents;
|
||||
struct
|
||||
{
|
||||
u32 Param;
|
||||
u8 Command;
|
||||
};
|
||||
|
||||
void ExecuteCommand();
|
||||
} CmdFIFOEntry;
|
||||
|
||||
s32 CyclesToRunFor();
|
||||
void Run();
|
||||
void CheckFIFOIRQ();
|
||||
void CheckFIFODMA();
|
||||
void UpdateClipMatrix() noexcept;
|
||||
void ResetRenderingState() noexcept;
|
||||
void AddCycles(s32 num) noexcept;
|
||||
void NextVertexSlot() noexcept;
|
||||
void StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept;
|
||||
void SubmitPolygon() noexcept;
|
||||
void SubmitVertex() noexcept;
|
||||
void CalculateLighting() noexcept;
|
||||
void BoxTest(u32* params) noexcept;
|
||||
void PosTest() noexcept;
|
||||
void VecTest(u32 param) noexcept;
|
||||
void CmdFIFOWrite(CmdFIFOEntry& entry) noexcept;
|
||||
CmdFIFOEntry CmdFIFORead() noexcept;
|
||||
void FinishWork(s32 cycles) noexcept;
|
||||
void VertexPipelineSubmitCmd() noexcept
|
||||
{
|
||||
// vertex commands 0x24, 0x25, 0x26, 0x27, 0x28
|
||||
if (!(VertexSlotsFree & 0x1)) NextVertexSlot();
|
||||
else AddCycles(1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
void VCount144();
|
||||
void VBlank();
|
||||
void VCount215();
|
||||
void VertexPipelineCmdDelayed6() noexcept
|
||||
{
|
||||
// commands 0x20, 0x30, 0x31, 0x72 that can run 6 cycles after a vertex
|
||||
if (VertexPipeline > 2) AddCycles((VertexPipeline - 2) + 1);
|
||||
else AddCycles(NormalPipeline + 1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
void RestartFrame();
|
||||
void VertexPipelineCmdDelayed8() noexcept
|
||||
{
|
||||
// commands 0x29, 0x2A, 0x2B, 0x33, 0x34, 0x41, 0x60, 0x71 that can run 8 cycles after a vertex
|
||||
if (VertexPipeline > 0) AddCycles(VertexPipeline + 1);
|
||||
else AddCycles(NormalPipeline + 1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
void SetRenderXPos(u16 xpos);
|
||||
u32* GetLine(int line);
|
||||
void VertexPipelineCmdDelayed4() noexcept
|
||||
{
|
||||
// all other commands can run 4 cycles after a vertex
|
||||
// no need to do much here since that is the minimum
|
||||
AddCycles(NormalPipeline + 1);
|
||||
NormalPipeline = 0;
|
||||
}
|
||||
|
||||
void WriteToGXFIFO(u32 val);
|
||||
std::unique_ptr<Renderer3D> CurrentRenderer = nullptr;
|
||||
|
||||
u8 Read8(u32 addr);
|
||||
u16 Read16(u32 addr);
|
||||
u32 Read32(u32 addr);
|
||||
void Write8(u32 addr, u8 val);
|
||||
void Write16(u32 addr, u16 val);
|
||||
void Write32(u32 addr, u32 val);
|
||||
u16 RenderXPos = 0;
|
||||
|
||||
public:
|
||||
FIFO<CmdFIFOEntry, 256> CmdFIFO {};
|
||||
FIFO<CmdFIFOEntry, 4> CmdPIPE {};
|
||||
|
||||
FIFO<CmdFIFOEntry, 64> CmdStallQueue {};
|
||||
|
||||
u32 ZeroDotWLimit = 0;
|
||||
|
||||
u32 GXStat = 0;
|
||||
|
||||
u32 ExecParams[32] {};
|
||||
u32 ExecParamCount = 0;
|
||||
|
||||
s32 CycleCount = 0;
|
||||
s32 VertexPipeline = 0;
|
||||
s32 NormalPipeline = 0;
|
||||
s32 PolygonPipeline = 0;
|
||||
s32 VertexSlotCounter = 0;
|
||||
u32 VertexSlotsFree = 0;
|
||||
|
||||
u32 NumPushPopCommands = 0;
|
||||
u32 NumTestCommands = 0;
|
||||
|
||||
|
||||
u32 MatrixMode = 0;
|
||||
|
||||
s32 ProjMatrix[16] {};
|
||||
s32 PosMatrix[16] {};
|
||||
s32 VecMatrix[16] {};
|
||||
s32 TexMatrix[16] {};
|
||||
|
||||
s32 ClipMatrix[16] {};
|
||||
bool ClipMatrixDirty = false;
|
||||
|
||||
u32 Viewport[6] {};
|
||||
|
||||
s32 ProjMatrixStack[16] {};
|
||||
s32 PosMatrixStack[32][16] {};
|
||||
s32 VecMatrixStack[32][16] {};
|
||||
s32 TexMatrixStack[16] {};
|
||||
s32 ProjMatrixStackPointer = 0;
|
||||
s32 PosMatrixStackPointer = 0;
|
||||
s32 TexMatrixStackPointer = 0;
|
||||
|
||||
u32 NumCommands = 0;
|
||||
u32 CurCommand = 0;
|
||||
u32 ParamCount = 0;
|
||||
u32 TotalParams = 0;
|
||||
|
||||
bool GeometryEnabled = false;
|
||||
bool RenderingEnabled = false;
|
||||
|
||||
u32 DispCnt = 0;
|
||||
u8 AlphaRefVal = 0;
|
||||
u8 AlphaRef = 0;
|
||||
|
||||
u16 ToonTable[32] {};
|
||||
u16 EdgeTable[8] {};
|
||||
|
||||
u32 FogColor = 0;
|
||||
u32 FogOffset = 0;
|
||||
u8 FogDensityTable[32] {};
|
||||
|
||||
u32 ClearAttr1 = 0;
|
||||
u32 ClearAttr2 = 0;
|
||||
u32 RenderDispCnt = 0;
|
||||
u8 RenderAlphaRef = 0;
|
||||
|
||||
u16 RenderToonTable[32] {};
|
||||
u16 RenderEdgeTable[8] {};
|
||||
|
||||
u32 RenderFogColor = 0;
|
||||
u32 RenderFogOffset = 0;
|
||||
u32 RenderFogShift = 0;
|
||||
u8 RenderFogDensityTable[34] {};
|
||||
|
||||
u32 RenderClearAttr1 = 0;
|
||||
u32 RenderClearAttr2 = 0;
|
||||
|
||||
bool RenderFrameIdentical = false;
|
||||
|
||||
bool AbortFrame = false;
|
||||
|
||||
u64 Timestamp = 0;
|
||||
|
||||
|
||||
u32 PolygonMode = 0;
|
||||
s16 CurVertex[3] {};
|
||||
u8 VertexColor[3] {};
|
||||
s16 TexCoords[2] {};
|
||||
s16 RawTexCoords[2] {};
|
||||
s16 Normal[3] {};
|
||||
|
||||
s16 LightDirection[4][3] {};
|
||||
u8 LightColor[4][3] {};
|
||||
u8 MatDiffuse[3] {};
|
||||
u8 MatAmbient[3] {};
|
||||
u8 MatSpecular[3] {};
|
||||
u8 MatEmission[3] {};
|
||||
|
||||
bool UseShininessTable = false;
|
||||
u8 ShininessTable[128] {};
|
||||
|
||||
u32 PolygonAttr = 0;
|
||||
u32 CurPolygonAttr = 0;
|
||||
|
||||
u32 TexParam = 0;
|
||||
u32 TexPalette = 0;
|
||||
|
||||
s32 PosTestResult[4] {};
|
||||
s16 VecTestResult[3] {};
|
||||
|
||||
Vertex TempVertexBuffer[4] {};
|
||||
u32 VertexNum = 0;
|
||||
u32 VertexNumInPoly = 0;
|
||||
u32 NumConsecutivePolygons = 0;
|
||||
Polygon* LastStripPolygon = nullptr;
|
||||
u32 NumOpaquePolygons = 0;
|
||||
|
||||
Vertex VertexRAM[6144 * 2] {};
|
||||
Polygon PolygonRAM[2048 * 2] {};
|
||||
|
||||
Vertex* CurVertexRAM = nullptr;
|
||||
Polygon* CurPolygonRAM = nullptr;
|
||||
u32 NumVertices = 0;
|
||||
u32 NumPolygons = 0;
|
||||
u32 CurRAMBank = 0;
|
||||
|
||||
std::array<Polygon*,2048> RenderPolygonRAM {};
|
||||
u32 RenderNumPolygons = 0;
|
||||
|
||||
u32 FlushRequest = 0;
|
||||
u32 FlushAttributes = 0;
|
||||
u32 ScrolledLine[256];
|
||||
};
|
||||
|
||||
class Renderer3D
|
||||
{
|
||||
|
@ -149,7 +340,7 @@ public:
|
|||
// are more detailed "traits" that we can ask of the Renderer3D type
|
||||
const bool Accelerated;
|
||||
|
||||
virtual void SetRenderSettings(GPU::RenderSettings& settings) = 0;
|
||||
virtual void SetRenderSettings(const Melon::RenderSettings& settings) noexcept = 0;
|
||||
|
||||
virtual void VCount144() {};
|
||||
|
||||
|
@ -160,15 +351,6 @@ protected:
|
|||
Renderer3D(bool Accelerated);
|
||||
};
|
||||
|
||||
extern int Renderer;
|
||||
extern std::unique_ptr<Renderer3D> CurrentRenderer;
|
||||
|
||||
}
|
||||
|
||||
#include "GPU3D_Soft.h"
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
#include "GPU3D_OpenGL.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -97,20 +97,20 @@ void SetupDefaultTexParams(GLuint tex)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
GLRenderer::GLRenderer() noexcept : Renderer3D(true)
|
||||
GLRenderer::GLRenderer(Melon::GPU& gpu) noexcept : Renderer3D(true), GPU(gpu)
|
||||
{
|
||||
// GLRenderer::New() will be used to actually initialize the renderer;
|
||||
// The various glDelete* functions silently ignore invalid IDs,
|
||||
// so we can just let the destructor clean up a half-initialized renderer.
|
||||
}
|
||||
|
||||
std::unique_ptr<GLRenderer> GLRenderer::New() noexcept
|
||||
std::unique_ptr<GLRenderer> GLRenderer::New(Melon::GPU& gpu) noexcept
|
||||
{
|
||||
assert(glEnable != nullptr);
|
||||
|
||||
// Will be returned if the initialization succeeds,
|
||||
// or cleaned up via RAII if it fails.
|
||||
std::unique_ptr<GLRenderer> result = std::unique_ptr<GLRenderer>(new GLRenderer());
|
||||
std::unique_ptr<GLRenderer> result = std::unique_ptr<GLRenderer>(new GLRenderer(gpu));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
@ -329,7 +329,7 @@ void GLRenderer::Reset()
|
|||
{
|
||||
}
|
||||
|
||||
void GLRenderer::SetRenderSettings(GPU::RenderSettings& settings)
|
||||
void GLRenderer::SetRenderSettings(const Melon::RenderSettings& settings) noexcept
|
||||
{
|
||||
int scale = settings.GL_ScaleFactor;
|
||||
|
||||
|
@ -766,11 +766,11 @@ int GLRenderer::RenderPolygonEdgeBatch(int i)
|
|||
void GLRenderer::RenderSceneChunk(int y, int h)
|
||||
{
|
||||
u32 flags = 0;
|
||||
if (RenderPolygonRAM[0]->WBuffer) flags |= RenderFlag_WBuffer;
|
||||
if (GPU.GPU3D.RenderPolygonRAM[0]->WBuffer) flags |= RenderFlag_WBuffer;
|
||||
|
||||
if (h != 192) glScissor(0, y<<ScaleFactor, 256<<ScaleFactor, h<<ScaleFactor);
|
||||
|
||||
GLboolean fogenable = (RenderDispCnt & (1<<7)) ? GL_TRUE : GL_FALSE;
|
||||
GLboolean fogenable = (GPU.GPU3D.RenderDispCnt & (1<<7)) ? GL_TRUE : GL_FALSE;
|
||||
|
||||
// TODO: proper 'equal' depth test!
|
||||
// (has margin of +-0x200 in Z-buffer mode, +-0xFF in W-buffer mode)
|
||||
|
@ -842,7 +842,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
|
|||
glEnable(GL_BLEND);
|
||||
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
|
||||
|
||||
if (RenderDispCnt & (1<<3))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<3))
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
|
||||
else
|
||||
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE);
|
||||
|
@ -854,7 +854,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
|
|||
// pass 2: if needed, render translucent pixels that are against background pixels
|
||||
// when background alpha is zero, those need to be rendered with blending disabled
|
||||
|
||||
if ((RenderClearAttr1 & 0x001F0000) == 0)
|
||||
if ((GPU.GPU3D.RenderClearAttr1 & 0x001F0000) == 0)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
@ -918,7 +918,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
|
|||
if (rp->PolyData->IsShadow)
|
||||
{
|
||||
// shadow against clear-plane will only pass if its polyID matches that of the clear plane
|
||||
u32 clrpolyid = (RenderClearAttr1 >> 24) & 0x3F;
|
||||
u32 clrpolyid = (GPU.GPU3D.RenderClearAttr1 >> 24) & 0x3F;
|
||||
if (polyid != clrpolyid) { i++; continue; }
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
@ -1066,7 +1066,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
|
|||
}
|
||||
}
|
||||
|
||||
if (RenderDispCnt & 0x00A0) // fog/edge enabled
|
||||
if (GPU.GPU3D.RenderDispCnt & 0x00A0) // fog/edge enabled
|
||||
{
|
||||
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glColorMaski(1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
@ -1088,7 +1088,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
|
|||
glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);
|
||||
glBindVertexArray(ClearVertexArrayID);
|
||||
|
||||
if (RenderDispCnt & (1<<5))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<5))
|
||||
{
|
||||
// edge marking
|
||||
// TODO: depth/polyid values at screen edges
|
||||
|
@ -1100,19 +1100,19 @@ void GLRenderer::RenderSceneChunk(int y, int h)
|
|||
glDrawArrays(GL_TRIANGLES, 0, 2*3);
|
||||
}
|
||||
|
||||
if (RenderDispCnt & (1<<7))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<7))
|
||||
{
|
||||
// fog
|
||||
|
||||
glUseProgram(FinalPassFogShader[2]);
|
||||
|
||||
if (RenderDispCnt & (1<<6))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<6))
|
||||
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||
else
|
||||
glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
{
|
||||
u32 c = RenderFogColor;
|
||||
u32 c = GPU.GPU3D.RenderFogColor;
|
||||
u32 r = c & 0x1F;
|
||||
u32 g = (c >> 5) & 0x1F;
|
||||
u32 b = (c >> 10) & 0x1F;
|
||||
|
@ -1136,11 +1136,11 @@ void GLRenderer::RenderFrame()
|
|||
|
||||
ShaderConfig.uScreenSize[0] = ScreenW;
|
||||
ShaderConfig.uScreenSize[1] = ScreenH;
|
||||
ShaderConfig.uDispCnt = RenderDispCnt;
|
||||
ShaderConfig.uDispCnt = GPU.GPU3D.RenderDispCnt;
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
u16 c = RenderToonTable[i];
|
||||
u16 c = GPU.GPU3D.RenderToonTable[i];
|
||||
u32 r = c & 0x1F;
|
||||
u32 g = (c >> 5) & 0x1F;
|
||||
u32 b = (c >> 10) & 0x1F;
|
||||
|
@ -1152,7 +1152,7 @@ void GLRenderer::RenderFrame()
|
|||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
u16 c = RenderEdgeTable[i];
|
||||
u16 c = GPU.GPU3D.RenderEdgeTable[i];
|
||||
u32 r = c & 0x1F;
|
||||
u32 g = (c >> 5) & 0x1F;
|
||||
u32 b = (c >> 10) & 0x1F;
|
||||
|
@ -1163,7 +1163,7 @@ void GLRenderer::RenderFrame()
|
|||
}
|
||||
|
||||
{
|
||||
u32 c = RenderFogColor;
|
||||
u32 c = GPU.GPU3D.RenderFogColor;
|
||||
u32 r = c & 0x1F;
|
||||
u32 g = (c >> 5) & 0x1F;
|
||||
u32 b = (c >> 10) & 0x1F;
|
||||
|
@ -1177,12 +1177,12 @@ void GLRenderer::RenderFrame()
|
|||
|
||||
for (int i = 0; i < 34; i++)
|
||||
{
|
||||
u8 d = RenderFogDensityTable[i];
|
||||
u8 d = GPU.GPU3D.RenderFogDensityTable[i];
|
||||
ShaderConfig.uFogDensity[i][0] = (float)d / 127.0;
|
||||
}
|
||||
|
||||
ShaderConfig.uFogOffset = RenderFogOffset;
|
||||
ShaderConfig.uFogShift = RenderFogShift;
|
||||
ShaderConfig.uFogOffset = GPU.GPU3D.RenderFogOffset;
|
||||
ShaderConfig.uFogShift = GPU.GPU3D.RenderFogShift;
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, ShaderConfigUBO);
|
||||
void* unibuf = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
|
||||
|
@ -1195,13 +1195,13 @@ void GLRenderer::RenderFrame()
|
|||
glBindTexture(GL_TEXTURE_2D, TexMemID);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
u32 mask = GPU::VRAMMap_Texture[i];
|
||||
u32 mask = GPU.VRAMMap_Texture[i];
|
||||
u8* vram;
|
||||
if (!mask) continue;
|
||||
else if (mask & (1<<0)) vram = GPU::VRAM_A;
|
||||
else if (mask & (1<<1)) vram = GPU::VRAM_B;
|
||||
else if (mask & (1<<2)) vram = GPU::VRAM_C;
|
||||
else if (mask & (1<<3)) vram = GPU::VRAM_D;
|
||||
else if (mask & (1<<0)) vram = GPU.VRAM_A;
|
||||
else if (mask & (1<<1)) vram = GPU.VRAM_B;
|
||||
else if (mask & (1<<2)) vram = GPU.VRAM_C;
|
||||
else if (mask & (1<<3)) vram = GPU.VRAM_D;
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i*128, 1024, 128, GL_RED_INTEGER, GL_UNSIGNED_BYTE, vram);
|
||||
}
|
||||
|
@ -1211,12 +1211,12 @@ void GLRenderer::RenderFrame()
|
|||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// 6 x 16K chunks
|
||||
u32 mask = GPU::VRAMMap_TexPal[i];
|
||||
u32 mask = GPU.VRAMMap_TexPal[i];
|
||||
u8* vram;
|
||||
if (!mask) continue;
|
||||
else if (mask & (1<<4)) vram = &GPU::VRAM_E[(i&3)*0x4000];
|
||||
else if (mask & (1<<5)) vram = GPU::VRAM_F;
|
||||
else if (mask & (1<<6)) vram = GPU::VRAM_G;
|
||||
else if (mask & (1<<4)) vram = &GPU.VRAM_E[(i&3)*0x4000];
|
||||
else if (mask & (1<<5)) vram = GPU.VRAM_F;
|
||||
else if (mask & (1<<6)) vram = GPU.VRAM_G;
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i*8, 1024, 8, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, vram);
|
||||
}
|
||||
|
@ -1241,13 +1241,13 @@ void GLRenderer::RenderFrame()
|
|||
glUseProgram(ClearShaderPlain[2]);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
u32 r = RenderClearAttr1 & 0x1F;
|
||||
u32 g = (RenderClearAttr1 >> 5) & 0x1F;
|
||||
u32 b = (RenderClearAttr1 >> 10) & 0x1F;
|
||||
u32 fog = (RenderClearAttr1 >> 15) & 0x1;
|
||||
u32 a = (RenderClearAttr1 >> 16) & 0x1F;
|
||||
u32 polyid = (RenderClearAttr1 >> 24) & 0x3F;
|
||||
u32 z = ((RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||
u32 r = GPU.GPU3D.RenderClearAttr1 & 0x1F;
|
||||
u32 g = (GPU.GPU3D.RenderClearAttr1 >> 5) & 0x1F;
|
||||
u32 b = (GPU.GPU3D.RenderClearAttr1 >> 10) & 0x1F;
|
||||
u32 fog = (GPU.GPU3D.RenderClearAttr1 >> 15) & 0x1;
|
||||
u32 a = (GPU.GPU3D.RenderClearAttr1 >> 16) & 0x1F;
|
||||
u32 polyid = (GPU.GPU3D.RenderClearAttr1 >> 24) & 0x3F;
|
||||
u32 z = ((GPU.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 0xFF, 0xFF);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
|
@ -1266,20 +1266,20 @@ void GLRenderer::RenderFrame()
|
|||
glDrawArrays(GL_TRIANGLES, 0, 2*3);
|
||||
}
|
||||
|
||||
if (RenderNumPolygons)
|
||||
if (GPU.GPU3D.RenderNumPolygons)
|
||||
{
|
||||
// render shit here
|
||||
u32 flags = 0;
|
||||
if (RenderPolygonRAM[0]->WBuffer) flags |= RenderFlag_WBuffer;
|
||||
if (GPU.GPU3D.RenderPolygonRAM[0]->WBuffer) flags |= RenderFlag_WBuffer;
|
||||
|
||||
int npolys = 0;
|
||||
int firsttrans = -1;
|
||||
for (u32 i = 0; i < RenderNumPolygons; i++)
|
||||
for (u32 i = 0; i < GPU.GPU3D.RenderNumPolygons; i++)
|
||||
{
|
||||
if (RenderPolygonRAM[i]->Degenerate) continue;
|
||||
if (GPU.GPU3D.RenderPolygonRAM[i]->Degenerate) continue;
|
||||
|
||||
SetupPolygon(&PolygonList[npolys], RenderPolygonRAM[i]);
|
||||
if (firsttrans < 0 && RenderPolygonRAM[i]->Translucent)
|
||||
SetupPolygon(&PolygonList[npolys], GPU.GPU3D.RenderPolygonRAM[i]);
|
||||
if (firsttrans < 0 && GPU.GPU3D.RenderPolygonRAM[i]->Translucent)
|
||||
firsttrans = npolys;
|
||||
|
||||
npolys++;
|
||||
|
|
|
@ -18,10 +18,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
#include "GPU3D.h"
|
||||
|
||||
#include "OpenGLSupport.h"
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
namespace GPU3D
|
||||
{
|
||||
|
@ -31,7 +36,7 @@ public:
|
|||
virtual ~GLRenderer() override;
|
||||
virtual void Reset() override;
|
||||
|
||||
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
|
||||
virtual void SetRenderSettings(const Melon::RenderSettings& settings) noexcept override;
|
||||
|
||||
virtual void VCount144() override {};
|
||||
virtual void RenderFrame() override;
|
||||
|
@ -40,10 +45,10 @@ public:
|
|||
void SetupAccelFrame();
|
||||
void PrepareCaptureFrame();
|
||||
|
||||
static std::unique_ptr<GLRenderer> New() noexcept;
|
||||
static std::unique_ptr<GLRenderer> New(Melon::GPU& gpu) noexcept;
|
||||
private:
|
||||
// Used by New()
|
||||
GLRenderer() noexcept;
|
||||
GLRenderer(Melon::GPU& gpu) noexcept;
|
||||
|
||||
// GL version requirements
|
||||
// * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS)
|
||||
|
@ -63,6 +68,7 @@ private:
|
|||
u32 RenderKey;
|
||||
};
|
||||
|
||||
Melon::GPU& GPU;
|
||||
RendererPolygon PolygonList[2048] {};
|
||||
|
||||
bool BuildRenderShader(u32 flags, const char* vs, const char* fs);
|
||||
|
@ -151,3 +157,4 @@ private:
|
|||
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -72,8 +72,8 @@ void SoftRenderer::SetupRenderThread()
|
|||
}
|
||||
|
||||
|
||||
SoftRenderer::SoftRenderer() noexcept
|
||||
: Renderer3D(false)
|
||||
SoftRenderer::SoftRenderer(Melon::GPU& gpu) noexcept
|
||||
: Renderer3D(false), GPU(gpu)
|
||||
{
|
||||
Sema_RenderStart = Platform::Semaphore_Create();
|
||||
Sema_RenderDone = Platform::Semaphore_Create();
|
||||
|
@ -105,7 +105,7 @@ void SoftRenderer::Reset()
|
|||
SetupRenderThread();
|
||||
}
|
||||
|
||||
void SoftRenderer::SetRenderSettings(GPU::RenderSettings& settings)
|
||||
void SoftRenderer::SetRenderSettings(const Melon::RenderSettings& settings) noexcept
|
||||
{
|
||||
Threaded = settings.Soft_Threaded;
|
||||
SetupRenderThread();
|
||||
|
@ -387,7 +387,7 @@ bool DepthTest_LessThan_FrontFacing(s32 dstz, s32 z, u32 dstattr)
|
|||
return false;
|
||||
}
|
||||
|
||||
u32 AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha)
|
||||
u32 SoftRenderer::AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha) noexcept
|
||||
{
|
||||
u32 dstalpha = dstcolor >> 24;
|
||||
|
||||
|
@ -398,7 +398,7 @@ u32 AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha)
|
|||
u32 srcG = (srccolor >> 8) & 0x3F;
|
||||
u32 srcB = (srccolor >> 16) & 0x3F;
|
||||
|
||||
if (RenderDispCnt & (1<<3))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<3))
|
||||
{
|
||||
u32 dstR = dstcolor & 0x3F;
|
||||
u32 dstG = (dstcolor >> 8) & 0x3F;
|
||||
|
@ -427,7 +427,7 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
|||
|
||||
if (blendmode == 2)
|
||||
{
|
||||
if (RenderDispCnt & (1<<1))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<1))
|
||||
{
|
||||
// highlight mode: color is calculated normally
|
||||
// except all vertex color components are set
|
||||
|
@ -441,7 +441,7 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
|||
{
|
||||
// toon mode: vertex color is replaced by toon color
|
||||
|
||||
u16 tooncolor = RenderToonTable[vr >> 1];
|
||||
u16 tooncolor = GPU.GPU3D.RenderToonTable[vr >> 1];
|
||||
|
||||
vr = (tooncolor << 1) & 0x3E; if (vr) vr++;
|
||||
vg = (tooncolor >> 4) & 0x3E; if (vg) vg++;
|
||||
|
@ -449,7 +449,7 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
|||
}
|
||||
}
|
||||
|
||||
if ((RenderDispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
|
||||
if ((GPU.GPU3D.RenderDispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
|
||||
{
|
||||
u8 tr, tg, tb;
|
||||
|
||||
|
@ -502,9 +502,9 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
|||
a = polyalpha;
|
||||
}
|
||||
|
||||
if ((blendmode == 2) && (RenderDispCnt & (1<<1)))
|
||||
if ((blendmode == 2) && (GPU.GPU3D.RenderDispCnt & (1<<1)))
|
||||
{
|
||||
u16 tooncolor = RenderToonTable[vr >> 1];
|
||||
u16 tooncolor = GPU.GPU3D.RenderToonTable[vr >> 1];
|
||||
|
||||
vr = (tooncolor << 1) & 0x3E; if (vr) vr++;
|
||||
vg = (tooncolor >> 4) & 0x3E; if (vg) vg++;
|
||||
|
@ -748,7 +748,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
|
|||
std::swap(zl, zr);
|
||||
|
||||
// CHECKME: edge fill rules for swapped opaque shadow mask polygons
|
||||
if ((polyalpha < 31) || (RenderDispCnt & (3<<4)))
|
||||
if ((polyalpha < 31) || (GPU.GPU3D.RenderDispCnt & (3<<4)))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
|
@ -776,7 +776,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
|
|||
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
|
||||
|
||||
// CHECKME: edge fill rules for unswapped opaque shadow mask polygons
|
||||
if ((polyalpha < 31) || (RenderDispCnt & (3<<4)))
|
||||
if ((polyalpha < 31) || (GPU.GPU3D.RenderDispCnt & (3<<4)))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
|
@ -797,7 +797,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
|
|||
// similarly, we can perform alpha test early (checkme)
|
||||
|
||||
if (wireframe) polyalpha = 31;
|
||||
if (polyalpha <= RenderAlphaRef) return;
|
||||
if (polyalpha <= GPU.GPU3D.RenderAlphaRef) return;
|
||||
|
||||
// in wireframe mode, there are special rules for equal Z (TODO)
|
||||
|
||||
|
@ -982,7 +982,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
|||
// * the bottom-most pixel of negative x-major slopes are filled if they are next to a flat bottom edge
|
||||
// edges are always filled if antialiasing/edgemarking are enabled or if the pixels are translucent
|
||||
// checkme: do swapped line polygons exist?
|
||||
if ((polyalpha < 31) || wireframe || (RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
if ((polyalpha < 31) || wireframe || (GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
|
@ -1016,7 +1016,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
|||
// * the bottom-most pixel of negative x-major slopes are filled if they are next to a flat bottom edge
|
||||
// * edges are filled if both sides are identical and fully overlapping
|
||||
// edges are always filled if antialiasing/edgemarking are enabled or if the pixels are translucent
|
||||
if ((polyalpha < 31) || wireframe || (RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
if ((polyalpha < 31) || wireframe || (GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
|
@ -1119,13 +1119,13 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
|||
u8 alpha = color >> 24;
|
||||
|
||||
// alpha test
|
||||
if (alpha <= RenderAlphaRef) continue;
|
||||
if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
|
||||
|
||||
if (alpha == 31)
|
||||
{
|
||||
u32 attr = polyattr | edge;
|
||||
|
||||
if (RenderDispCnt & (1<<4))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<4))
|
||||
{
|
||||
// anti-aliasing: all edges are rendered
|
||||
|
||||
|
@ -1215,13 +1215,13 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
|||
u8 alpha = color >> 24;
|
||||
|
||||
// alpha test
|
||||
if (alpha <= RenderAlphaRef) continue;
|
||||
if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
|
||||
|
||||
if (alpha == 31)
|
||||
{
|
||||
u32 attr = polyattr | edge;
|
||||
|
||||
if ((RenderDispCnt & (1<<4)) && (attr & 0xF))
|
||||
if ((GPU.GPU3D.RenderDispCnt & (1<<4)) && (attr & 0xF))
|
||||
{
|
||||
// anti-aliasing: all edges are rendered
|
||||
|
||||
|
@ -1307,13 +1307,13 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
|||
u8 alpha = color >> 24;
|
||||
|
||||
// alpha test
|
||||
if (alpha <= RenderAlphaRef) continue;
|
||||
if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
|
||||
|
||||
if (alpha == 31)
|
||||
{
|
||||
u32 attr = polyattr | edge;
|
||||
|
||||
if (RenderDispCnt & (1<<4))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<4))
|
||||
{
|
||||
// anti-aliasing: all edges are rendered
|
||||
|
||||
|
@ -1377,7 +1377,7 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr)
|
|||
u32 z = DepthBuffer[pixeladdr];
|
||||
u32 densityid, densityfrac;
|
||||
|
||||
if (z < RenderFogOffset)
|
||||
if (z < GPU.GPU3D.RenderFogOffset)
|
||||
{
|
||||
densityid = 0;
|
||||
densityfrac = 0;
|
||||
|
@ -1389,8 +1389,8 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr)
|
|||
// on hardware, the final value can overflow the 32-bit range with a shift big enough,
|
||||
// causing fog to 'wrap around' and accidentally apply to larger Z ranges
|
||||
|
||||
z -= RenderFogOffset;
|
||||
z = (z >> 2) << RenderFogShift;
|
||||
z -= GPU.GPU3D.RenderFogOffset;
|
||||
z = (z >> 2) << GPU.GPU3D.RenderFogShift;
|
||||
|
||||
densityid = z >> 17;
|
||||
if (densityid >= 32)
|
||||
|
@ -1404,8 +1404,8 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr)
|
|||
|
||||
// checkme (may be too precise?)
|
||||
u32 density =
|
||||
((RenderFogDensityTable[densityid] * (0x20000-densityfrac)) +
|
||||
(RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;
|
||||
((GPU.GPU3D.RenderFogDensityTable[densityid] * (0x20000-densityfrac)) +
|
||||
(GPU.GPU3D.RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;
|
||||
if (density >= 127) density = 128;
|
||||
|
||||
return density;
|
||||
|
@ -1417,7 +1417,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
|||
// clearing all polygon fog flags if the master flag isn't set?
|
||||
// merging all final pass loops into one?
|
||||
|
||||
if (RenderDispCnt & (1<<5))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<5))
|
||||
{
|
||||
// edge marking
|
||||
// only applied to topmost pixels
|
||||
|
@ -1437,7 +1437,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
|||
((polyid != (AttrBuffer[pixeladdr-ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr-ScanlineWidth])) ||
|
||||
((polyid != (AttrBuffer[pixeladdr+ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr+ScanlineWidth])))
|
||||
{
|
||||
u16 edgecolor = RenderEdgeTable[polyid >> 3];
|
||||
u16 edgecolor = GPU.GPU3D.RenderEdgeTable[polyid >> 3];
|
||||
u32 edgeR = (edgecolor << 1) & 0x3E; if (edgeR) edgeR++;
|
||||
u32 edgeG = (edgecolor >> 4) & 0x3E; if (edgeG) edgeG++;
|
||||
u32 edgeB = (edgecolor >> 9) & 0x3E; if (edgeB) edgeB++;
|
||||
|
@ -1450,7 +1450,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
|||
}
|
||||
}
|
||||
|
||||
if (RenderDispCnt & (1<<7))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<7))
|
||||
{
|
||||
// fog
|
||||
|
||||
|
@ -1463,12 +1463,12 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
|||
|
||||
// TODO: check the 'fog alpha glitch with small Z' GBAtek talks about
|
||||
|
||||
bool fogcolor = !(RenderDispCnt & (1<<6));
|
||||
bool fogcolor = !(GPU.GPU3D.RenderDispCnt & (1<<6));
|
||||
|
||||
u32 fogR = (RenderFogColor << 1) & 0x3E; if (fogR) fogR++;
|
||||
u32 fogG = (RenderFogColor >> 4) & 0x3E; if (fogG) fogG++;
|
||||
u32 fogB = (RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;
|
||||
u32 fogA = (RenderFogColor >> 16) & 0x1F;
|
||||
u32 fogR = (GPU.GPU3D.RenderFogColor << 1) & 0x3E; if (fogR) fogR++;
|
||||
u32 fogG = (GPU.GPU3D.RenderFogColor >> 4) & 0x3E; if (fogG) fogG++;
|
||||
u32 fogB = (GPU.GPU3D.RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;
|
||||
u32 fogA = (GPU.GPU3D.RenderFogColor >> 16) & 0x1F;
|
||||
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
|
@ -1528,7 +1528,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
|||
}
|
||||
}
|
||||
|
||||
if (RenderDispCnt & (1<<4))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<4))
|
||||
{
|
||||
// anti-aliasing
|
||||
|
||||
|
@ -1583,8 +1583,8 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
|||
|
||||
void SoftRenderer::ClearBuffers()
|
||||
{
|
||||
u32 clearz = ((RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||
u32 polyid = RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
|
||||
u32 clearz = ((GPU.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||
u32 polyid = GPU.GPU3D.RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
|
||||
|
||||
// fill screen borders for edge marking
|
||||
|
||||
|
@ -1614,10 +1614,10 @@ void SoftRenderer::ClearBuffers()
|
|||
|
||||
// clear the screen
|
||||
|
||||
if (RenderDispCnt & (1<<14))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<14))
|
||||
{
|
||||
u8 xoff = (RenderClearAttr2 >> 16) & 0xFF;
|
||||
u8 yoff = (RenderClearAttr2 >> 24) & 0xFF;
|
||||
u8 xoff = (GPU.GPU3D.RenderClearAttr2 >> 16) & 0xFF;
|
||||
u8 yoff = (GPU.GPU3D.RenderClearAttr2 >> 24) & 0xFF;
|
||||
|
||||
for (int y = 0; y < ScanlineWidth*192; y+=ScanlineWidth)
|
||||
{
|
||||
|
@ -1649,13 +1649,13 @@ void SoftRenderer::ClearBuffers()
|
|||
else
|
||||
{
|
||||
// TODO: confirm color conversion
|
||||
u32 r = (RenderClearAttr1 << 1) & 0x3E; if (r) r++;
|
||||
u32 g = (RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
|
||||
u32 b = (RenderClearAttr1 >> 9) & 0x3E; if (b) b++;
|
||||
u32 a = (RenderClearAttr1 >> 16) & 0x1F;
|
||||
u32 r = (GPU.GPU3D.RenderClearAttr1 << 1) & 0x3E; if (r) r++;
|
||||
u32 g = (GPU.GPU3D.RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
|
||||
u32 b = (GPU.GPU3D.RenderClearAttr1 >> 9) & 0x3E; if (b) b++;
|
||||
u32 a = (GPU.GPU3D.RenderClearAttr1 >> 16) & 0x1F;
|
||||
u32 color = r | (g << 8) | (b << 16) | (a << 24);
|
||||
|
||||
polyid |= (RenderClearAttr1 & 0x8000);
|
||||
polyid |= (GPU.GPU3D.RenderClearAttr1 & 0x8000);
|
||||
|
||||
for (int y = 0; y < ScanlineWidth*192; y+=ScanlineWidth)
|
||||
{
|
||||
|
@ -1698,19 +1698,19 @@ void SoftRenderer::RenderPolygons(bool threaded, Polygon** polygons, int npolys)
|
|||
|
||||
void SoftRenderer::VCount144()
|
||||
{
|
||||
if (RenderThreadRunning.load(std::memory_order_relaxed) && !GPU3D::AbortFrame)
|
||||
if (RenderThreadRunning.load(std::memory_order_relaxed) && !GPU.GPU3D.AbortFrame)
|
||||
Platform::Semaphore_Wait(Sema_RenderDone);
|
||||
}
|
||||
|
||||
void SoftRenderer::RenderFrame()
|
||||
{
|
||||
auto textureDirty = GPU::VRAMDirty_Texture.DeriveState(GPU::VRAMMap_Texture);
|
||||
auto texPalDirty = GPU::VRAMDirty_TexPal.DeriveState(GPU::VRAMMap_TexPal);
|
||||
auto textureDirty = GPU.VRAMDirty_Texture.DeriveState(GPU.VRAMMap_Texture, GPU);
|
||||
auto texPalDirty = GPU.VRAMDirty_TexPal.DeriveState(GPU.VRAMMap_TexPal, GPU);
|
||||
|
||||
bool textureChanged = GPU::MakeVRAMFlat_TextureCoherent(textureDirty);
|
||||
bool texPalChanged = GPU::MakeVRAMFlat_TexPalCoherent(texPalDirty);
|
||||
bool textureChanged = GPU.MakeVRAMFlat_TextureCoherent(textureDirty);
|
||||
bool texPalChanged = GPU.MakeVRAMFlat_TexPalCoherent(texPalDirty);
|
||||
|
||||
FrameIdentical = !(textureChanged || texPalChanged) && RenderFrameIdentical;
|
||||
FrameIdentical = !(textureChanged || texPalChanged) && GPU.GPU3D.RenderFrameIdentical;
|
||||
|
||||
if (RenderThreadRunning.load(std::memory_order_relaxed))
|
||||
{
|
||||
|
@ -1719,7 +1719,7 @@ void SoftRenderer::RenderFrame()
|
|||
else if (!FrameIdentical)
|
||||
{
|
||||
ClearBuffers();
|
||||
RenderPolygons(false, &RenderPolygonRAM[0], RenderNumPolygons);
|
||||
RenderPolygons(false, &GPU.GPU3D.RenderPolygonRAM[0], GPU.GPU3D.RenderNumPolygons);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1743,7 +1743,7 @@ void SoftRenderer::RenderThreadFunc()
|
|||
else
|
||||
{
|
||||
ClearBuffers();
|
||||
RenderPolygons(true, &RenderPolygonRAM[0], RenderNumPolygons);
|
||||
RenderPolygons(true, &GPU.GPU3D.RenderPolygonRAM[0], GPU.GPU3D.RenderNumPolygons);
|
||||
}
|
||||
|
||||
Platform::Semaphore_Post(Sema_RenderDone);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GPU.h"
|
||||
#include "GPU3D.h"
|
||||
#include "Platform.h"
|
||||
#include <thread>
|
||||
|
@ -28,11 +29,11 @@ namespace GPU3D
|
|||
class SoftRenderer : public Renderer3D
|
||||
{
|
||||
public:
|
||||
SoftRenderer() noexcept;
|
||||
SoftRenderer(Melon::GPU& gpu) noexcept;
|
||||
virtual ~SoftRenderer() override;
|
||||
virtual void Reset() override;
|
||||
|
||||
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
|
||||
virtual void SetRenderSettings(const Melon::RenderSettings& settings) noexcept override;
|
||||
|
||||
virtual void VCount144() override;
|
||||
virtual void RenderFrame() override;
|
||||
|
@ -429,13 +430,14 @@ private:
|
|||
template <typename T>
|
||||
inline T ReadVRAM_Texture(u32 addr)
|
||||
{
|
||||
return *(T*)&GPU::VRAMFlat_Texture[addr & 0x7FFFF];
|
||||
return *(T*)&GPU.VRAMFlat_Texture[addr & 0x7FFFF];
|
||||
}
|
||||
template <typename T>
|
||||
inline T ReadVRAM_TexPal(u32 addr)
|
||||
{
|
||||
return *(T*)&GPU::VRAMFlat_TexPal[addr & 0x1FFFF];
|
||||
return *(T*)&GPU.VRAMFlat_TexPal[addr & 0x1FFFF];
|
||||
}
|
||||
u32 AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha) noexcept;
|
||||
|
||||
struct RendererPolygon
|
||||
{
|
||||
|
@ -449,6 +451,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
Melon::GPU& GPU;
|
||||
RendererPolygon PolygonList[2048];
|
||||
void TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha);
|
||||
u32 RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16 t);
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
#include "OpenGLSupport.h"
|
||||
#include "GPU_OpenGL_shaders.h"
|
||||
|
||||
namespace GPU
|
||||
namespace Melon
|
||||
{
|
||||
|
||||
using namespace OpenGL;
|
||||
|
||||
std::unique_ptr<GLCompositor> GLCompositor::New() noexcept
|
||||
std::unique_ptr<GLCompositor> GLCompositor::New(Melon::GPU& gpu) noexcept
|
||||
{
|
||||
assert(glBindAttribLocation != nullptr);
|
||||
|
||||
|
@ -50,10 +50,10 @@ std::unique_ptr<GLCompositor> GLCompositor::New() noexcept
|
|||
// if linking the shaders together failed.
|
||||
return nullptr;
|
||||
|
||||
return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader));
|
||||
return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader, gpu));
|
||||
}
|
||||
|
||||
GLCompositor::GLCompositor(std::array<GLuint, 3> compShader) noexcept : CompShader(compShader)
|
||||
GLCompositor::GLCompositor(std::array<GLuint, 3> compShader, Melon::GPU& gpu) noexcept : CompShader(compShader), GPU(gpu)
|
||||
{
|
||||
CompScaleLoc = glGetUniformLocation(CompShader[2], "u3DScale");
|
||||
Comp3DXPosLoc = glGetUniformLocation(CompShader[2], "u3DXPos");
|
||||
|
@ -144,7 +144,7 @@ void GLCompositor::Reset()
|
|||
}
|
||||
|
||||
|
||||
void GLCompositor::SetRenderSettings(RenderSettings& settings)
|
||||
void GLCompositor::SetRenderSettings(const RenderSettings& settings) noexcept
|
||||
{
|
||||
int scale = settings.GL_ScaleFactor;
|
||||
|
||||
|
@ -174,7 +174,7 @@ void GLCompositor::Stop()
|
|||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int frontbuf = GPU::FrontBuffer;
|
||||
int frontbuf = GPU.FrontBuffer;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB[frontbuf]);
|
||||
|
||||
|
@ -186,7 +186,7 @@ void GLCompositor::Stop()
|
|||
|
||||
void GLCompositor::RenderFrame()
|
||||
{
|
||||
int frontbuf = GPU::FrontBuffer;
|
||||
int frontbuf = GPU.FrontBuffer;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB[frontbuf]);
|
||||
|
||||
|
@ -204,21 +204,21 @@ void GLCompositor::RenderFrame()
|
|||
glUniform1ui(CompScaleLoc, Scale);
|
||||
|
||||
// TODO: support setting this midframe, if ever needed
|
||||
glUniform1i(Comp3DXPosLoc, ((int)GPU3D::RenderXPos << 23) >> 23);
|
||||
glUniform1i(Comp3DXPosLoc, ((int)GPU.GPU3D.GetRenderXPos() << 23) >> 23);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, CompScreenInputTex);
|
||||
|
||||
if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1])
|
||||
if (GPU.Framebuffer[frontbuf][0] && GPU.Framebuffer[frontbuf][1])
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER,
|
||||
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
|
||||
GL_UNSIGNED_BYTE, GPU.Framebuffer[frontbuf][0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER,
|
||||
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
|
||||
GL_UNSIGNED_BYTE, GPU.Framebuffer[frontbuf][1]);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
reinterpret_cast<GPU3D::GLRenderer*>(GPU3D::CurrentRenderer.get())->SetupAccelFrame();
|
||||
reinterpret_cast<GPU3D::GLRenderer*>(GPU.GPU3D.GetCurrentRenderer())->SetupAccelFrame();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID);
|
||||
glBindVertexArray(CompVertexArrayID);
|
||||
|
|
|
@ -23,29 +23,29 @@
|
|||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace GPU
|
||||
namespace Melon
|
||||
{
|
||||
|
||||
class GPU;
|
||||
struct RenderSettings;
|
||||
|
||||
class GLCompositor
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<GLCompositor> New() noexcept;
|
||||
static std::unique_ptr<GLCompositor> New(Melon::GPU& gpu) noexcept;
|
||||
GLCompositor(const GLCompositor&) = delete;
|
||||
GLCompositor& operator=(const GLCompositor&) = delete;
|
||||
~GLCompositor();
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetRenderSettings(RenderSettings& settings);
|
||||
void SetRenderSettings(const RenderSettings& settings) noexcept;
|
||||
|
||||
void Stop();
|
||||
void RenderFrame();
|
||||
void BindOutputTexture(int buf);
|
||||
private:
|
||||
GLCompositor(std::array<GLuint, 3> CompShader) noexcept;
|
||||
|
||||
GLCompositor(std::array<GLuint, 3> CompShader, Melon::GPU& gpu) noexcept;
|
||||
Melon::GPU& GPU;
|
||||
int Scale;
|
||||
int ScreenH, ScreenW;
|
||||
|
||||
|
|
329
src/NDS.cpp
329
src/NDS.cpp
|
@ -185,6 +185,7 @@ class RTC* RTC;
|
|||
class Wifi* Wifi;
|
||||
std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
||||
std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
||||
std::unique_ptr<Melon::GPU> GPU;
|
||||
class AREngine* AREngine;
|
||||
|
||||
bool Running;
|
||||
|
@ -204,8 +205,9 @@ bool Init()
|
|||
RegisterEventFunc(Event_Div, 0, DivDone);
|
||||
RegisterEventFunc(Event_Sqrt, 0, SqrtDone);
|
||||
|
||||
ARM9 = new ARMv5();
|
||||
ARM7 = new ARMv4();
|
||||
GPU = std::make_unique<Melon::GPU>();
|
||||
ARM9 = new ARMv5(*GPU);
|
||||
ARM7 = new ARMv4(*GPU);
|
||||
|
||||
#ifdef JIT_ENABLED
|
||||
ARMJIT::Init();
|
||||
|
@ -215,14 +217,14 @@ bool Init()
|
|||
SharedWRAM = new u8[SharedWRAMSize];
|
||||
#endif
|
||||
|
||||
DMAs[0] = new DMA(0, 0);
|
||||
DMAs[1] = new DMA(0, 1);
|
||||
DMAs[2] = new DMA(0, 2);
|
||||
DMAs[3] = new DMA(0, 3);
|
||||
DMAs[4] = new DMA(1, 0);
|
||||
DMAs[5] = new DMA(1, 1);
|
||||
DMAs[6] = new DMA(1, 2);
|
||||
DMAs[7] = new DMA(1, 3);
|
||||
DMAs[0] = new DMA(0, 0, *GPU);
|
||||
DMAs[1] = new DMA(0, 1, *GPU);
|
||||
DMAs[2] = new DMA(0, 2, *GPU);
|
||||
DMAs[3] = new DMA(0, 3, *GPU);
|
||||
DMAs[4] = new DMA(1, 0, *GPU);
|
||||
DMAs[5] = new DMA(1, 1, *GPU);
|
||||
DMAs[6] = new DMA(1, 2, *GPU);
|
||||
DMAs[7] = new DMA(1, 3, *GPU);
|
||||
|
||||
SPU = new class SPU;
|
||||
SPI = new class SPIHost();
|
||||
|
@ -230,7 +232,6 @@ bool Init()
|
|||
Wifi = new class Wifi();
|
||||
NDSCartSlot = std::make_unique<NDSCart::NDSCartSlot>();
|
||||
GBACartSlot = std::make_unique<GBACart::GBACartSlot>();
|
||||
if (!GPU::Init()) return false;
|
||||
|
||||
if (!DSi::Init()) return false;
|
||||
|
||||
|
@ -261,7 +262,7 @@ void DeInit()
|
|||
|
||||
NDSCartSlot = nullptr;
|
||||
GBACartSlot = nullptr;
|
||||
GPU::DeInit();
|
||||
GPU = nullptr;
|
||||
|
||||
DSi::DeInit();
|
||||
|
||||
|
@ -521,7 +522,7 @@ void SetupDirectBoot(const std::string& romname)
|
|||
PostFlag7 = 0x01;
|
||||
|
||||
PowerControl9 = 0x820F;
|
||||
GPU::SetPowerCnt(PowerControl9);
|
||||
GPU->SetPowerCnt(PowerControl9);
|
||||
|
||||
// checkme
|
||||
RCnt = 0x8000;
|
||||
|
@ -644,9 +645,9 @@ void Reset()
|
|||
KeyCnt[1] = 0;
|
||||
RCnt = 0;
|
||||
|
||||
GPU->Reset();
|
||||
NDSCartSlot->Reset();
|
||||
GBACartSlot->Reset();
|
||||
GPU::Reset();
|
||||
SPU->Reset();
|
||||
SPI->Reset();
|
||||
RTC->Reset();
|
||||
|
@ -720,7 +721,7 @@ void Stop(Platform::StopReason reason)
|
|||
Log(level, "Stopping emulated console (Reason: %s)\n", StopReasonName(reason));
|
||||
Running = false;
|
||||
Platform::SignalStop(reason);
|
||||
GPU::Stop();
|
||||
GPU->Stop();
|
||||
SPU->Stop();
|
||||
|
||||
if (ConsoleType == 1)
|
||||
|
@ -848,7 +849,7 @@ bool DoSavestate(Savestate* file)
|
|||
NDSCartSlot->DoSavestate(file);
|
||||
if (ConsoleType == 0)
|
||||
GBACartSlot->DoSavestate(file);
|
||||
GPU::DoSavestate(file);
|
||||
GPU->DoSavestate(file);
|
||||
SPU->DoSavestate(file);
|
||||
SPI->DoSavestate(file);
|
||||
RTC->DoSavestate(file);
|
||||
|
@ -859,7 +860,7 @@ bool DoSavestate(Savestate* file)
|
|||
|
||||
if (!file->Saving)
|
||||
{
|
||||
GPU::SetPowerCnt(PowerControl9);
|
||||
GPU->SetPowerCnt(PowerControl9);
|
||||
|
||||
SPU->SetPowerCnt(PowerControl7 & 0x0001);
|
||||
Wifi->SetPowerCnt(PowerControl7 & 0x0002);
|
||||
|
@ -1071,7 +1072,7 @@ u32 RunFrame()
|
|||
{
|
||||
FrameStartTimestamp = SysTimestamp;
|
||||
|
||||
GPU::TotalScanlines = 0;
|
||||
GPU->TotalScanlines = 0;
|
||||
|
||||
LagFrameFlag = true;
|
||||
bool runFrame = Running && !(CPUStop & CPUStop_Sleep);
|
||||
|
@ -1095,7 +1096,7 @@ u32 RunFrame()
|
|||
ARM7Timestamp = target;
|
||||
TimerTimestamp[0] = target;
|
||||
TimerTimestamp[1] = target;
|
||||
GPU3D::Timestamp = target;
|
||||
GPU->GPU3D.Timestamp = target;
|
||||
RunSystemSleep(target);
|
||||
|
||||
if (!(CPUStop & CPUStop_Sleep))
|
||||
|
@ -1103,7 +1104,7 @@ u32 RunFrame()
|
|||
}
|
||||
|
||||
if (SysTimestamp >= frametarget)
|
||||
GPU::BlankFrame();
|
||||
GPU->BlankFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1112,11 +1113,11 @@ u32 RunFrame()
|
|||
|
||||
if (!(CPUStop & CPUStop_Wakeup))
|
||||
{
|
||||
GPU::StartFrame();
|
||||
GPU->StartFrame();
|
||||
}
|
||||
CPUStop &= ~CPUStop_Wakeup;
|
||||
|
||||
while (Running && GPU::TotalScanlines==0)
|
||||
while (Running && GPU->TotalScanlines==0)
|
||||
{
|
||||
u64 target = NextTarget();
|
||||
ARM9Target = target << ARM9ClockShift;
|
||||
|
@ -1125,7 +1126,7 @@ u32 RunFrame()
|
|||
if (CPUStop & CPUStop_GXStall)
|
||||
{
|
||||
// GXFIFO stall
|
||||
s32 cycles = GPU3D::CyclesToRunFor();
|
||||
s32 cycles = GPU->GPU3D.CyclesToRunFor();
|
||||
|
||||
ARM9Timestamp = std::min(ARM9Target, ARM9Timestamp+(cycles<<ARM9ClockShift));
|
||||
}
|
||||
|
@ -1148,7 +1149,7 @@ u32 RunFrame()
|
|||
}
|
||||
|
||||
RunTimers(0);
|
||||
GPU3D::Run();
|
||||
GPU->GPU3D.Run();
|
||||
|
||||
target = ARM9Timestamp >> ARM9ClockShift;
|
||||
CurCPU = 1;
|
||||
|
@ -1187,7 +1188,7 @@ u32 RunFrame()
|
|||
}
|
||||
}
|
||||
|
||||
if (GPU::TotalScanlines == 0)
|
||||
if (GPU->TotalScanlines == 0)
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG_CHECK_DESYNC
|
||||
|
@ -1208,7 +1209,7 @@ u32 RunFrame()
|
|||
NumLagFrames++;
|
||||
|
||||
if (Running)
|
||||
return GPU::TotalScanlines;
|
||||
return GPU->TotalScanlines;
|
||||
else
|
||||
return 263;
|
||||
}
|
||||
|
@ -1531,7 +1532,7 @@ void SetIRQ(u32 cpu, u32 irq)
|
|||
{
|
||||
CPUStop &= ~CPUStop_Sleep;
|
||||
CPUStop |= CPUStop_Wakeup;
|
||||
GPU3D::RestartFrame();
|
||||
GPU->GPU3D.RestartFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1708,7 +1709,7 @@ void NocashPrint(u32 ncpu, u32 addr)
|
|||
else if (!strcmp(cmd, "lr")) sprintf(subs, "%08X", cpu->R[14]);
|
||||
else if (!strcmp(cmd, "pc")) sprintf(subs, "%08X", cpu->R[15]);
|
||||
else if (!strcmp(cmd, "frame")) sprintf(subs, "%u", NumFrames);
|
||||
else if (!strcmp(cmd, "scanline")) sprintf(subs, "%u", GPU::VCount);
|
||||
else if (!strcmp(cmd, "scanline")) sprintf(subs, "%u", GPU->VCount);
|
||||
else if (!strcmp(cmd, "totalclks")) sprintf(subs, "%" PRIu64, GetSysClockCycles(0));
|
||||
else if (!strcmp(cmd, "lastclks")) sprintf(subs, "%" PRIu64, GetSysClockCycles(1));
|
||||
else if (!strcmp(cmd, "zeroclks"))
|
||||
|
@ -2081,7 +2082,7 @@ void debug(u32 param)
|
|||
Log(LogLevel::Debug, "ARM7 IME=%08X IE=%08X IF=%08X IE2=%04X IF2=%04X\n", IME[1], IE[1], IF[1], IE2, IF2);
|
||||
|
||||
//for (int i = 0; i < 9; i++)
|
||||
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
||||
// printf("VRAM %c: %02X\n", 'A'+i, GPU->VRAMCNT[i]);
|
||||
|
||||
FILE*
|
||||
shit = fopen("debug/DSfirmware.bin", "wb");
|
||||
|
@ -2149,21 +2150,21 @@ u8 ARM9Read8(u32 addr)
|
|||
|
||||
case 0x05000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||
return GPU::ReadPalette<u8>(addr);
|
||||
return GPU->ReadPalette<u8>(addr);
|
||||
|
||||
case 0x06000000:
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: return GPU::ReadVRAM_ABG<u8>(addr);
|
||||
case 0x00200000: return GPU::ReadVRAM_BBG<u8>(addr);
|
||||
case 0x00400000: return GPU::ReadVRAM_AOBJ<u8>(addr);
|
||||
case 0x00600000: return GPU::ReadVRAM_BOBJ<u8>(addr);
|
||||
default: return GPU::ReadVRAM_LCDC<u8>(addr);
|
||||
case 0x00000000: return GPU->ReadVRAM_ABG<u8>(addr);
|
||||
case 0x00200000: return GPU->ReadVRAM_BBG<u8>(addr);
|
||||
case 0x00400000: return GPU->ReadVRAM_AOBJ<u8>(addr);
|
||||
case 0x00600000: return GPU->ReadVRAM_BOBJ<u8>(addr);
|
||||
default: return GPU->ReadVRAM_LCDC<u8>(addr);
|
||||
}
|
||||
|
||||
case 0x07000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||
return GPU::ReadOAM<u8>(addr);
|
||||
return GPU->ReadOAM<u8>(addr);
|
||||
|
||||
case 0x08000000:
|
||||
case 0x09000000:
|
||||
|
@ -2211,21 +2212,21 @@ u16 ARM9Read16(u32 addr)
|
|||
|
||||
case 0x05000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||
return GPU::ReadPalette<u16>(addr);
|
||||
return GPU->ReadPalette<u16>(addr);
|
||||
|
||||
case 0x06000000:
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: return GPU::ReadVRAM_ABG<u16>(addr);
|
||||
case 0x00200000: return GPU::ReadVRAM_BBG<u16>(addr);
|
||||
case 0x00400000: return GPU::ReadVRAM_AOBJ<u16>(addr);
|
||||
case 0x00600000: return GPU::ReadVRAM_BOBJ<u16>(addr);
|
||||
default: return GPU::ReadVRAM_LCDC<u16>(addr);
|
||||
case 0x00000000: return GPU->ReadVRAM_ABG<u16>(addr);
|
||||
case 0x00200000: return GPU->ReadVRAM_BBG<u16>(addr);
|
||||
case 0x00400000: return GPU->ReadVRAM_AOBJ<u16>(addr);
|
||||
case 0x00600000: return GPU->ReadVRAM_BOBJ<u16>(addr);
|
||||
default: return GPU->ReadVRAM_LCDC<u16>(addr);
|
||||
}
|
||||
|
||||
case 0x07000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||
return GPU::ReadOAM<u16>(addr);
|
||||
return GPU->ReadOAM<u16>(addr);
|
||||
|
||||
case 0x08000000:
|
||||
case 0x09000000:
|
||||
|
@ -2273,21 +2274,21 @@ u32 ARM9Read32(u32 addr)
|
|||
|
||||
case 0x05000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||
return GPU::ReadPalette<u32>(addr);
|
||||
return GPU->ReadPalette<u32>(addr);
|
||||
|
||||
case 0x06000000:
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: return GPU::ReadVRAM_ABG<u32>(addr);
|
||||
case 0x00200000: return GPU::ReadVRAM_BBG<u32>(addr);
|
||||
case 0x00400000: return GPU::ReadVRAM_AOBJ<u32>(addr);
|
||||
case 0x00600000: return GPU::ReadVRAM_BOBJ<u32>(addr);
|
||||
default: return GPU::ReadVRAM_LCDC<u32>(addr);
|
||||
case 0x00000000: return GPU->ReadVRAM_ABG<u32>(addr);
|
||||
case 0x00200000: return GPU->ReadVRAM_BBG<u32>(addr);
|
||||
case 0x00400000: return GPU->ReadVRAM_AOBJ<u32>(addr);
|
||||
case 0x00600000: return GPU->ReadVRAM_BOBJ<u32>(addr);
|
||||
default: return GPU->ReadVRAM_LCDC<u32>(addr);
|
||||
}
|
||||
|
||||
case 0x07000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0;
|
||||
return GPU::ReadOAM<u32>(addr & 0x7FF);
|
||||
return GPU->ReadOAM<u32>(addr & 0x7FF);
|
||||
|
||||
case 0x08000000:
|
||||
case 0x09000000:
|
||||
|
@ -2382,7 +2383,7 @@ void ARM9Write16(u32 addr, u16 val)
|
|||
|
||||
case 0x05000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||
GPU::WritePalette<u16>(addr, val);
|
||||
GPU->WritePalette<u16>(addr, val);
|
||||
return;
|
||||
|
||||
case 0x06000000:
|
||||
|
@ -2391,16 +2392,16 @@ void ARM9Write16(u32 addr, u16 val)
|
|||
#endif
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: GPU::WriteVRAM_ABG<u16>(addr, val); return;
|
||||
case 0x00200000: GPU::WriteVRAM_BBG<u16>(addr, val); return;
|
||||
case 0x00400000: GPU::WriteVRAM_AOBJ<u16>(addr, val); return;
|
||||
case 0x00600000: GPU::WriteVRAM_BOBJ<u16>(addr, val); return;
|
||||
default: GPU::WriteVRAM_LCDC<u16>(addr, val); return;
|
||||
case 0x00000000: GPU->WriteVRAM_ABG<u16>(addr, val); return;
|
||||
case 0x00200000: GPU->WriteVRAM_BBG<u16>(addr, val); return;
|
||||
case 0x00400000: GPU->WriteVRAM_AOBJ<u16>(addr, val); return;
|
||||
case 0x00600000: GPU->WriteVRAM_BOBJ<u16>(addr, val); return;
|
||||
default: GPU->WriteVRAM_LCDC<u16>(addr, val); return;
|
||||
}
|
||||
|
||||
case 0x07000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||
GPU::WriteOAM<u16>(addr, val);
|
||||
GPU->WriteOAM<u16>(addr, val);
|
||||
return;
|
||||
|
||||
case 0x08000000:
|
||||
|
@ -2450,7 +2451,7 @@ void ARM9Write32(u32 addr, u32 val)
|
|||
|
||||
case 0x05000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||
GPU::WritePalette(addr, val);
|
||||
GPU->WritePalette(addr, val);
|
||||
return;
|
||||
|
||||
case 0x06000000:
|
||||
|
@ -2459,16 +2460,16 @@ void ARM9Write32(u32 addr, u32 val)
|
|||
#endif
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: GPU::WriteVRAM_ABG<u32>(addr, val); return;
|
||||
case 0x00200000: GPU::WriteVRAM_BBG<u32>(addr, val); return;
|
||||
case 0x00400000: GPU::WriteVRAM_AOBJ<u32>(addr, val); return;
|
||||
case 0x00600000: GPU::WriteVRAM_BOBJ<u32>(addr, val); return;
|
||||
default: GPU::WriteVRAM_LCDC<u32>(addr, val); return;
|
||||
case 0x00000000: GPU->WriteVRAM_ABG<u32>(addr, val); return;
|
||||
case 0x00200000: GPU->WriteVRAM_BBG<u32>(addr, val); return;
|
||||
case 0x00400000: GPU->WriteVRAM_AOBJ<u32>(addr, val); return;
|
||||
case 0x00600000: GPU->WriteVRAM_BOBJ<u32>(addr, val); return;
|
||||
default: GPU->WriteVRAM_LCDC<u32>(addr, val); return;
|
||||
}
|
||||
|
||||
case 0x07000000:
|
||||
if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return;
|
||||
GPU::WriteOAM<u32>(addr, val);
|
||||
GPU->WriteOAM<u32>(addr, val);
|
||||
return;
|
||||
|
||||
case 0x08000000:
|
||||
|
@ -2570,7 +2571,7 @@ u8 ARM7Read8(u32 addr)
|
|||
|
||||
case 0x06000000:
|
||||
case 0x06800000:
|
||||
return GPU::ReadVRAM_ARM7<u8>(addr);
|
||||
return GPU->ReadVRAM_ARM7<u8>(addr);
|
||||
|
||||
case 0x08000000:
|
||||
case 0x08800000:
|
||||
|
@ -2638,7 +2639,7 @@ u16 ARM7Read16(u32 addr)
|
|||
|
||||
case 0x06000000:
|
||||
case 0x06800000:
|
||||
return GPU::ReadVRAM_ARM7<u16>(addr);
|
||||
return GPU->ReadVRAM_ARM7<u16>(addr);
|
||||
|
||||
case 0x08000000:
|
||||
case 0x08800000:
|
||||
|
@ -2706,7 +2707,7 @@ u32 ARM7Read32(u32 addr)
|
|||
|
||||
case 0x06000000:
|
||||
case 0x06800000:
|
||||
return GPU::ReadVRAM_ARM7<u32>(addr);
|
||||
return GPU->ReadVRAM_ARM7<u32>(addr);
|
||||
|
||||
case 0x08000000:
|
||||
case 0x08800000:
|
||||
|
@ -2777,7 +2778,7 @@ void ARM7Write8(u32 addr, u8 val)
|
|||
#ifdef JIT_ENABLED
|
||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
||||
#endif
|
||||
GPU::WriteVRAM_ARM7<u8>(addr, val);
|
||||
GPU->WriteVRAM_ARM7<u8>(addr, val);
|
||||
return;
|
||||
|
||||
case 0x08000000:
|
||||
|
@ -2856,7 +2857,7 @@ void ARM7Write16(u32 addr, u16 val)
|
|||
#ifdef JIT_ENABLED
|
||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
||||
#endif
|
||||
GPU::WriteVRAM_ARM7<u16>(addr, val);
|
||||
GPU->WriteVRAM_ARM7<u16>(addr, val);
|
||||
return;
|
||||
|
||||
case 0x08000000:
|
||||
|
@ -2938,7 +2939,7 @@ void ARM7Write32(u32 addr, u32 val)
|
|||
#ifdef JIT_ENABLED
|
||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
||||
#endif
|
||||
GPU::WriteVRAM_ARM7<u32>(addr, val);
|
||||
GPU->WriteVRAM_ARM7<u32>(addr, val);
|
||||
return;
|
||||
|
||||
case 0x08000000:
|
||||
|
@ -3073,16 +3074,16 @@ u8 ARM9IORead8(u32 addr)
|
|||
|
||||
case 0x04000208: return IME[0];
|
||||
|
||||
case 0x04000240: return GPU::VRAMCNT[0];
|
||||
case 0x04000241: return GPU::VRAMCNT[1];
|
||||
case 0x04000242: return GPU::VRAMCNT[2];
|
||||
case 0x04000243: return GPU::VRAMCNT[3];
|
||||
case 0x04000244: return GPU::VRAMCNT[4];
|
||||
case 0x04000245: return GPU::VRAMCNT[5];
|
||||
case 0x04000246: return GPU::VRAMCNT[6];
|
||||
case 0x04000240: return GPU->VRAMCNT[0];
|
||||
case 0x04000241: return GPU->VRAMCNT[1];
|
||||
case 0x04000242: return GPU->VRAMCNT[2];
|
||||
case 0x04000243: return GPU->VRAMCNT[3];
|
||||
case 0x04000244: return GPU->VRAMCNT[4];
|
||||
case 0x04000245: return GPU->VRAMCNT[5];
|
||||
case 0x04000246: return GPU->VRAMCNT[6];
|
||||
case 0x04000247: return WRAMCnt;
|
||||
case 0x04000248: return GPU::VRAMCNT[7];
|
||||
case 0x04000249: return GPU::VRAMCNT[8];
|
||||
case 0x04000248: return GPU->VRAMCNT[7];
|
||||
case 0x04000249: return GPU->VRAMCNT[8];
|
||||
|
||||
CASE_READ8_16BIT(0x04000280, DivCnt)
|
||||
CASE_READ8_32BIT(0x04000290, DivNumerator[0])
|
||||
|
@ -3104,15 +3105,15 @@ u8 ARM9IORead8(u32 addr)
|
|||
|
||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||
{
|
||||
return GPU::GPU2D_A.Read8(addr);
|
||||
return GPU->GPU2D_A.Read8(addr);
|
||||
}
|
||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||
{
|
||||
return GPU::GPU2D_B.Read8(addr);
|
||||
return GPU->GPU2D_B.Read8(addr);
|
||||
}
|
||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||
{
|
||||
return GPU3D::Read8(addr);
|
||||
return GPU->GPU3D.Read8(addr);
|
||||
}
|
||||
// NO$GBA debug register "Emulation ID"
|
||||
if(addr >= 0x04FFFA00 && addr < 0x04FFFA10)
|
||||
|
@ -3132,12 +3133,12 @@ u16 ARM9IORead16(u32 addr)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004: return GPU::DispStat[0];
|
||||
case 0x04000006: return GPU::VCount;
|
||||
case 0x04000004: return GPU->DispStat[0];
|
||||
case 0x04000006: return GPU->VCount;
|
||||
|
||||
case 0x04000060: return GPU3D::Read16(addr);
|
||||
case 0x04000060: return GPU->GPU3D.Read16(addr);
|
||||
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 0x040000BA: return DMAs[0]->Cnt >> 16;
|
||||
|
@ -3215,11 +3216,11 @@ u16 ARM9IORead16(u32 addr)
|
|||
case 0x04000210: return IE[0] & 0xFFFF;
|
||||
case 0x04000212: return IE[0] >> 16;
|
||||
|
||||
case 0x04000240: return GPU::VRAMCNT[0] | (GPU::VRAMCNT[1] << 8);
|
||||
case 0x04000242: return GPU::VRAMCNT[2] | (GPU::VRAMCNT[3] << 8);
|
||||
case 0x04000244: return GPU::VRAMCNT[4] | (GPU::VRAMCNT[5] << 8);
|
||||
case 0x04000246: return GPU::VRAMCNT[6] | (WRAMCnt << 8);
|
||||
case 0x04000248: return GPU::VRAMCNT[7] | (GPU::VRAMCNT[8] << 8);
|
||||
case 0x04000240: return GPU->VRAMCNT[0] | (GPU->VRAMCNT[1] << 8);
|
||||
case 0x04000242: return GPU->VRAMCNT[2] | (GPU->VRAMCNT[3] << 8);
|
||||
case 0x04000244: return GPU->VRAMCNT[4] | (GPU->VRAMCNT[5] << 8);
|
||||
case 0x04000246: return GPU->VRAMCNT[6] | (WRAMCnt << 8);
|
||||
case 0x04000248: return GPU->VRAMCNT[7] | (GPU->VRAMCNT[8] << 8);
|
||||
|
||||
case 0x04000280: return DivCnt;
|
||||
case 0x04000290: return DivNumerator[0] & 0xFFFF;
|
||||
|
@ -3259,15 +3260,15 @@ u16 ARM9IORead16(u32 addr)
|
|||
|
||||
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))
|
||||
{
|
||||
return GPU::GPU2D_B.Read16(addr);
|
||||
return GPU->GPU2D_B.Read16(addr);
|
||||
}
|
||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||
{
|
||||
return GPU3D::Read16(addr);
|
||||
return GPU->GPU3D.Read16(addr);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFF000) != 0x04004000)
|
||||
|
@ -3279,10 +3280,10 @@ u32 ARM9IORead32(u32 addr)
|
|||
{
|
||||
switch (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 0x04000064: return GPU::GPU2D_A.Read32(addr);
|
||||
case 0x04000060: return GPU->GPU3D.Read32(addr);
|
||||
case 0x04000064: return GPU->GPU2D_A.Read32(addr);
|
||||
|
||||
case 0x040000B0: return DMAs[0]->SrcAddr;
|
||||
case 0x040000B4: return DMAs[0]->DstAddr;
|
||||
|
@ -3342,9 +3343,9 @@ u32 ARM9IORead32(u32 addr)
|
|||
case 0x04000210: return IE[0];
|
||||
case 0x04000214: return IF[0];
|
||||
|
||||
case 0x04000240: return GPU::VRAMCNT[0] | (GPU::VRAMCNT[1] << 8) | (GPU::VRAMCNT[2] << 16) | (GPU::VRAMCNT[3] << 24);
|
||||
case 0x04000244: return GPU::VRAMCNT[4] | (GPU::VRAMCNT[5] << 8) | (GPU::VRAMCNT[6] << 16) | (WRAMCnt << 24);
|
||||
case 0x04000248: return GPU::VRAMCNT[7] | (GPU::VRAMCNT[8] << 8);
|
||||
case 0x04000240: return GPU->VRAMCNT[0] | (GPU->VRAMCNT[1] << 8) | (GPU->VRAMCNT[2] << 16) | (GPU->VRAMCNT[3] << 24);
|
||||
case 0x04000244: return GPU->VRAMCNT[4] | (GPU->VRAMCNT[5] << 8) | (GPU->VRAMCNT[6] << 16) | (WRAMCnt << 24);
|
||||
case 0x04000248: return GPU->VRAMCNT[7] | (GPU->VRAMCNT[8] << 8);
|
||||
|
||||
case 0x04000280: return DivCnt;
|
||||
case 0x04000290: return DivNumerator[0];
|
||||
|
@ -3403,15 +3404,15 @@ u32 ARM9IORead32(u32 addr)
|
|||
|
||||
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))
|
||||
{
|
||||
return GPU::GPU2D_B.Read32(addr);
|
||||
return GPU->GPU2D_B.Read32(addr);
|
||||
}
|
||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||
{
|
||||
return GPU3D::Read32(addr);
|
||||
return GPU->GPU3D.Read32(addr);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFF000) != 0x04004000)
|
||||
|
@ -3424,9 +3425,9 @@ void ARM9IOWrite8(u32 addr, u8 val)
|
|||
switch (addr)
|
||||
{
|
||||
case 0x0400006C:
|
||||
case 0x0400006D: GPU::GPU2D_A.Write8(addr, val); return;
|
||||
case 0x0400006D: GPU->GPU2D_A.Write8(addr, val); return;
|
||||
case 0x0400106C:
|
||||
case 0x0400106D: GPU::GPU2D_B.Write8(addr, val); return;
|
||||
case 0x0400106D: GPU->GPU2D_B.Write8(addr, val); return;
|
||||
|
||||
case 0x04000132:
|
||||
KeyCnt[0] = (KeyCnt[0] & 0xFF00) | val;
|
||||
|
@ -3463,16 +3464,16 @@ void ARM9IOWrite8(u32 addr, u8 val)
|
|||
|
||||
case 0x04000208: IME[0] = val & 0x1; UpdateIRQ(0); return;
|
||||
|
||||
case 0x04000240: GPU::MapVRAM_AB(0, val); return;
|
||||
case 0x04000241: GPU::MapVRAM_AB(1, val); return;
|
||||
case 0x04000242: GPU::MapVRAM_CD(2, val); return;
|
||||
case 0x04000243: GPU::MapVRAM_CD(3, val); return;
|
||||
case 0x04000244: GPU::MapVRAM_E(4, val); return;
|
||||
case 0x04000245: GPU::MapVRAM_FG(5, val); return;
|
||||
case 0x04000246: GPU::MapVRAM_FG(6, val); return;
|
||||
case 0x04000240: GPU->MapVRAM_AB(0, val); return;
|
||||
case 0x04000241: GPU->MapVRAM_AB(1, val); return;
|
||||
case 0x04000242: GPU->MapVRAM_CD(2, val); return;
|
||||
case 0x04000243: GPU->MapVRAM_CD(3, val); return;
|
||||
case 0x04000244: GPU->MapVRAM_E(4, val); return;
|
||||
case 0x04000245: GPU->MapVRAM_FG(5, val); return;
|
||||
case 0x04000246: GPU->MapVRAM_FG(6, val); return;
|
||||
case 0x04000247: MapSharedWRAM(val); return;
|
||||
case 0x04000248: GPU::MapVRAM_H(7, val); return;
|
||||
case 0x04000249: GPU::MapVRAM_I(8, val); return;
|
||||
case 0x04000248: GPU->MapVRAM_H(7, val); return;
|
||||
case 0x04000249: GPU->MapVRAM_I(8, val); return;
|
||||
|
||||
case 0x04000300:
|
||||
if (PostFlag9 & 0x01) val |= 0x01;
|
||||
|
@ -3482,17 +3483,17 @@ void ARM9IOWrite8(u32 addr, u8 val)
|
|||
|
||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||
{
|
||||
GPU::GPU2D_A.Write8(addr, val);
|
||||
GPU->GPU2D_A.Write8(addr, val);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||
{
|
||||
GPU::GPU2D_B.Write8(addr, val);
|
||||
GPU->GPU2D_B.Write8(addr, val);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||
{
|
||||
GPU3D::Write8(addr, val);
|
||||
GPU->GPU3D.Write8(addr, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3503,16 +3504,16 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004: GPU::SetDispStat(0, val); return;
|
||||
case 0x04000006: GPU::SetVCount(val); return;
|
||||
case 0x04000004: GPU->SetDispStat(0, val); return;
|
||||
case 0x04000006: GPU->SetVCount(val); return;
|
||||
|
||||
case 0x04000060: GPU3D::Write16(addr, val); return;
|
||||
case 0x04000060: GPU->GPU3D.Write16(addr, val); return;
|
||||
|
||||
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 0x0400106C: GPU::GPU2D_B.Write16(addr, val); return;
|
||||
case 0x0400006C: GPU->GPU2D_A.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 0x040000BA: DMAs[0]->WriteCnt((DMAs[0]->Cnt & 0x0000FFFF) | (val << 16)); return;
|
||||
|
@ -3629,24 +3630,24 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||
// TODO: what happens when writing to IF this way??
|
||||
|
||||
case 0x04000240:
|
||||
GPU::MapVRAM_AB(0, val & 0xFF);
|
||||
GPU::MapVRAM_AB(1, val >> 8);
|
||||
GPU->MapVRAM_AB(0, val & 0xFF);
|
||||
GPU->MapVRAM_AB(1, val >> 8);
|
||||
return;
|
||||
case 0x04000242:
|
||||
GPU::MapVRAM_CD(2, val & 0xFF);
|
||||
GPU::MapVRAM_CD(3, val >> 8);
|
||||
GPU->MapVRAM_CD(2, val & 0xFF);
|
||||
GPU->MapVRAM_CD(3, val >> 8);
|
||||
return;
|
||||
case 0x04000244:
|
||||
GPU::MapVRAM_E(4, val & 0xFF);
|
||||
GPU::MapVRAM_FG(5, val >> 8);
|
||||
GPU->MapVRAM_E(4, val & 0xFF);
|
||||
GPU->MapVRAM_FG(5, val >> 8);
|
||||
return;
|
||||
case 0x04000246:
|
||||
GPU::MapVRAM_FG(6, val & 0xFF);
|
||||
GPU->MapVRAM_FG(6, val & 0xFF);
|
||||
MapSharedWRAM(val >> 8);
|
||||
return;
|
||||
case 0x04000248:
|
||||
GPU::MapVRAM_H(7, val & 0xFF);
|
||||
GPU::MapVRAM_I(8, val >> 8);
|
||||
GPU->MapVRAM_H(7, val & 0xFF);
|
||||
GPU->MapVRAM_I(8, val >> 8);
|
||||
return;
|
||||
|
||||
case 0x04000280: DivCnt = val; StartDiv(); return;
|
||||
|
@ -3660,23 +3661,23 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||
|
||||
case 0x04000304:
|
||||
PowerControl9 = val & 0x820F;
|
||||
GPU::SetPowerCnt(PowerControl9);
|
||||
GPU->SetPowerCnt(PowerControl9);
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||
{
|
||||
GPU::GPU2D_A.Write16(addr, val);
|
||||
GPU->GPU2D_A.Write16(addr, val);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||
{
|
||||
GPU::GPU2D_B.Write16(addr, val);
|
||||
GPU->GPU2D_B.Write16(addr, val);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||
{
|
||||
GPU3D::Write16(addr, val);
|
||||
GPU->GPU3D.Write16(addr, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3688,16 +3689,16 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||
switch (addr)
|
||||
{
|
||||
case 0x04000004:
|
||||
GPU::SetDispStat(0, val & 0xFFFF);
|
||||
GPU::SetVCount(val >> 16);
|
||||
GPU->SetDispStat(0, val & 0xFFFF);
|
||||
GPU->SetVCount(val >> 16);
|
||||
return;
|
||||
|
||||
case 0x04000060: GPU3D::Write32(addr, val); return;
|
||||
case 0x04000060: GPU->GPU3D.Write32(addr, val); return;
|
||||
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 0x0400106C: GPU::GPU2D_B.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 0x040000B0: DMAs[0]->SrcAddr = val; return;
|
||||
case 0x040000B4: DMAs[0]->DstAddr = val; return;
|
||||
|
@ -3793,23 +3794,23 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||
|
||||
case 0x04000208: IME[0] = val & 0x1; UpdateIRQ(0); return;
|
||||
case 0x04000210: IE[0] = val; UpdateIRQ(0); return;
|
||||
case 0x04000214: IF[0] &= ~val; GPU3D::CheckFIFOIRQ(); UpdateIRQ(0); return;
|
||||
case 0x04000214: IF[0] &= ~val; GPU->GPU3D.CheckFIFOIRQ(); UpdateIRQ(0); return;
|
||||
|
||||
case 0x04000240:
|
||||
GPU::MapVRAM_AB(0, val & 0xFF);
|
||||
GPU::MapVRAM_AB(1, (val >> 8) & 0xFF);
|
||||
GPU::MapVRAM_CD(2, (val >> 16) & 0xFF);
|
||||
GPU::MapVRAM_CD(3, val >> 24);
|
||||
GPU->MapVRAM_AB(0, val & 0xFF);
|
||||
GPU->MapVRAM_AB(1, (val >> 8) & 0xFF);
|
||||
GPU->MapVRAM_CD(2, (val >> 16) & 0xFF);
|
||||
GPU->MapVRAM_CD(3, val >> 24);
|
||||
return;
|
||||
case 0x04000244:
|
||||
GPU::MapVRAM_E(4, val & 0xFF);
|
||||
GPU::MapVRAM_FG(5, (val >> 8) & 0xFF);
|
||||
GPU::MapVRAM_FG(6, (val >> 16) & 0xFF);
|
||||
GPU->MapVRAM_E(4, val & 0xFF);
|
||||
GPU->MapVRAM_FG(5, (val >> 8) & 0xFF);
|
||||
GPU->MapVRAM_FG(6, (val >> 16) & 0xFF);
|
||||
MapSharedWRAM(val >> 24);
|
||||
return;
|
||||
case 0x04000248:
|
||||
GPU::MapVRAM_H(7, val & 0xFF);
|
||||
GPU::MapVRAM_I(8, (val >> 8) & 0xFF);
|
||||
GPU->MapVRAM_H(7, val & 0xFF);
|
||||
GPU->MapVRAM_I(8, (val >> 8) & 0xFF);
|
||||
return;
|
||||
|
||||
case 0x04000280: DivCnt = val; StartDiv(); return;
|
||||
|
@ -3826,7 +3827,7 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||
|
||||
case 0x04000304:
|
||||
PowerControl9 = val & 0x820F;
|
||||
GPU::SetPowerCnt(PowerControl9);
|
||||
GPU->SetPowerCnt(PowerControl9);
|
||||
return;
|
||||
|
||||
case 0x04100010:
|
||||
|
@ -3864,17 +3865,17 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||
|
||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||
{
|
||||
GPU::GPU2D_A.Write32(addr, val);
|
||||
GPU->GPU2D_A.Write32(addr, val);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x04001000 && addr < 0x04001060)
|
||||
{
|
||||
GPU::GPU2D_B.Write32(addr, val);
|
||||
GPU->GPU2D_B.Write32(addr, val);
|
||||
return;
|
||||
}
|
||||
if (addr >= 0x04000320 && addr < 0x040006A4)
|
||||
{
|
||||
GPU3D::Write32(addr, val);
|
||||
GPU->GPU3D.Write32(addr, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3939,7 +3940,7 @@ u8 ARM7IORead8(u32 addr)
|
|||
|
||||
case 0x04000208: return IME[1];
|
||||
|
||||
case 0x04000240: return GPU::VRAMSTAT;
|
||||
case 0x04000240: return GPU->VRAMSTAT;
|
||||
case 0x04000241: return WRAMCnt;
|
||||
|
||||
case 0x04000300: return PostFlag7;
|
||||
|
@ -3960,8 +3961,8 @@ u16 ARM7IORead16(u32 addr)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004: return GPU::DispStat[1];
|
||||
case 0x04000006: return GPU::VCount;
|
||||
case 0x04000004: return GPU->DispStat[1];
|
||||
case 0x04000006: return GPU->VCount;
|
||||
|
||||
case 0x040000B8: return DMAs[4]->Cnt & 0xFFFF;
|
||||
case 0x040000BA: return DMAs[4]->Cnt >> 16;
|
||||
|
@ -4054,7 +4055,7 @@ u32 ARM7IORead32(u32 addr)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004: return GPU::DispStat[1] | (GPU::VCount << 16);
|
||||
case 0x04000004: return GPU->DispStat[1] | (GPU->VCount << 16);
|
||||
|
||||
case 0x040000B0: return DMAs[4]->SrcAddr;
|
||||
case 0x040000B4: return DMAs[4]->DstAddr;
|
||||
|
@ -4232,8 +4233,8 @@ void ARM7IOWrite16(u32 addr, u16 val)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004: GPU::SetDispStat(1, val); return;
|
||||
case 0x04000006: GPU::SetVCount(val); return;
|
||||
case 0x04000004: GPU->SetDispStat(1, val); return;
|
||||
case 0x04000006: GPU->SetVCount(val); return;
|
||||
|
||||
case 0x040000B8: DMAs[4]->WriteCnt((DMAs[4]->Cnt & 0xFFFF0000) | val); return;
|
||||
case 0x040000BA: DMAs[4]->WriteCnt((DMAs[4]->Cnt & 0x0000FFFF) | (val << 16)); return;
|
||||
|
@ -4388,8 +4389,8 @@ void ARM7IOWrite32(u32 addr, u32 val)
|
|||
switch (addr)
|
||||
{
|
||||
case 0x04000004:
|
||||
GPU::SetDispStat(1, val & 0xFFFF);
|
||||
GPU::SetVCount(val >> 16);
|
||||
GPU->SetDispStat(1, val & 0xFFFF);
|
||||
GPU->SetVCount(val >> 16);
|
||||
return;
|
||||
|
||||
case 0x040000B0: DMAs[4]->SrcAddr = val; return;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef NDS_H
|
||||
#define NDS_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
@ -40,6 +41,11 @@ class Wifi;
|
|||
|
||||
class AREngine;
|
||||
|
||||
namespace Melon
|
||||
{
|
||||
class GPU;
|
||||
}
|
||||
|
||||
namespace NDS
|
||||
{
|
||||
|
||||
|
@ -262,6 +268,7 @@ extern class RTC* RTC;
|
|||
extern class Wifi* Wifi;
|
||||
extern std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
||||
extern std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
||||
extern std::unique_ptr<Melon::GPU> GPU;
|
||||
extern class AREngine* AREngine;
|
||||
|
||||
const u32 ARM7WRAMSize = 0x10000;
|
||||
|
|
|
@ -163,7 +163,7 @@ EmuThread* emuThread;
|
|||
int autoScreenSizing = 0;
|
||||
|
||||
int videoRenderer;
|
||||
GPU::RenderSettings videoSettings;
|
||||
Melon::RenderSettings videoSettings;
|
||||
bool videoSettingsDirty;
|
||||
|
||||
CameraManager* camManager[2];
|
||||
|
@ -340,8 +340,8 @@ void EmuThread::run()
|
|||
videoRenderer = 0;
|
||||
}
|
||||
|
||||
GPU::InitRenderer(videoRenderer);
|
||||
GPU::SetRenderSettings(videoRenderer, videoSettings);
|
||||
NDS::GPU->InitRenderer(videoRenderer);
|
||||
NDS::GPU->SetRenderSettings(videoRenderer, videoSettings);
|
||||
|
||||
NDS::SPU->SetInterpolation(Config::AudioInterp);
|
||||
|
||||
|
@ -472,7 +472,7 @@ void EmuThread::run()
|
|||
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
|
||||
videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons;
|
||||
|
||||
GPU::SetRenderSettings(videoRenderer, videoSettings);
|
||||
NDS::GPU->SetRenderSettings(videoRenderer, videoSettings);
|
||||
}
|
||||
|
||||
// process input and hotkeys
|
||||
|
@ -534,12 +534,12 @@ void EmuThread::run()
|
|||
if (!oglContext)
|
||||
{
|
||||
FrontBufferLock.lock();
|
||||
FrontBuffer = GPU::FrontBuffer;
|
||||
FrontBuffer = NDS::GPU->FrontBuffer;
|
||||
FrontBufferLock.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
FrontBuffer = GPU::FrontBuffer;
|
||||
FrontBuffer = NDS::GPU->FrontBuffer;
|
||||
drawScreenGL();
|
||||
}
|
||||
|
||||
|
@ -676,7 +676,7 @@ void EmuThread::run()
|
|||
|
||||
EmuStatus = emuStatus_Exit;
|
||||
|
||||
GPU::DeInitRenderer();
|
||||
NDS::GPU->DeInitRenderer();
|
||||
NDS::DeInit();
|
||||
//Platform::LAN_DeInit();
|
||||
}
|
||||
|
@ -780,10 +780,10 @@ void EmuThread::drawScreenGL()
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
if (GPU::Renderer != 0)
|
||||
if (NDS::GPU->Renderer != 0)
|
||||
{
|
||||
// hardware-accelerated render
|
||||
GPU::CurGLCompositor->BindOutputTexture(frontbuf);
|
||||
NDS::GPU->CurGLCompositor->BindOutputTexture(frontbuf);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -791,12 +791,12 @@ void EmuThread::drawScreenGL()
|
|||
// regular render
|
||||
glBindTexture(GL_TEXTURE_2D, screenTexture);
|
||||
|
||||
if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1])
|
||||
if (NDS::GPU->Framebuffer[frontbuf][0] && NDS::GPU->Framebuffer[frontbuf][1])
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
|
||||
GL_UNSIGNED_BYTE, NDS::GPU->Framebuffer[frontbuf][0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
|
||||
GL_UNSIGNED_BYTE, NDS::GPU->Framebuffer[frontbuf][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1082,14 +1082,14 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
|||
{
|
||||
emuThread->FrontBufferLock.lock();
|
||||
int frontbuf = emuThread->FrontBuffer;
|
||||
if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1])
|
||||
if (!NDS::GPU->Framebuffer[frontbuf][0] || !NDS::GPU->Framebuffer[frontbuf][1])
|
||||
{
|
||||
emuThread->FrontBufferLock.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(screen[0].scanLine(0), GPU::Framebuffer[frontbuf][0], 256 * 192 * 4);
|
||||
memcpy(screen[1].scanLine(0), GPU::Framebuffer[frontbuf][1], 256 * 192 * 4);
|
||||
memcpy(screen[0].scanLine(0), NDS::GPU->Framebuffer[frontbuf][0], 256 * 192 * 4);
|
||||
memcpy(screen[1].scanLine(0), NDS::GPU->Framebuffer[frontbuf][1], 256 * 192 * 4);
|
||||
emuThread->FrontBufferLock.unlock();
|
||||
|
||||
QRect screenrc(0, 0, 256, 192);
|
||||
|
|
Loading…
Reference in New Issue