aboutsummaryrefslogtreecommitdiff
path: root/src/GPU.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/GPU.h')
-rw-r--r--src/GPU.h1009
1 files changed, 549 insertions, 460 deletions
diff --git a/src/GPU.h b/src/GPU.h
index ea9c777..17164ab 100644
--- a/src/GPU.h
+++ b/src/GPU.h
@@ -22,67 +22,23 @@
#include <memory>
#include "GPU2D.h"
+#include "GPU3D.h"
#include "NonStupidBitfield.h"
#ifdef OGLRENDERER_ENABLED
#include "GPU_OpenGL.h"
#endif
-namespace GPU
-{
-
-extern u16 VCount;
-extern u16 TotalScanlines;
-
-extern u16 DispStat[2];
-
-extern u8 VRAMCNT[9];
-extern u8 VRAMSTAT;
-
-extern u8 Palette[2*1024];
-extern u8 OAM[2*1024];
-
-extern u8 VRAM_A[128*1024];
-extern u8 VRAM_B[128*1024];
-extern u8 VRAM_C[128*1024];
-extern u8 VRAM_D[128*1024];
-extern u8 VRAM_E[ 64*1024];
-extern u8 VRAM_F[ 16*1024];
-extern u8 VRAM_G[ 16*1024];
-extern u8 VRAM_H[ 32*1024];
-extern u8 VRAM_I[ 16*1024];
-
-extern u8* const VRAM[9];
-
-extern u32 VRAMMap_LCDC;
-extern u32 VRAMMap_ABG[0x20];
-extern u32 VRAMMap_AOBJ[0x10];
-extern u32 VRAMMap_BBG[0x8];
-extern u32 VRAMMap_BOBJ[0x8];
-extern u32 VRAMMap_ABGExtPal[4];
-extern u32 VRAMMap_AOBJExtPal;
-extern u32 VRAMMap_BBGExtPal[4];
-extern u32 VRAMMap_BOBJExtPal;
-extern u32 VRAMMap_Texture[4];
-extern u32 VRAMMap_TexPal[8];
-extern u32 VRAMMap_ARM7[2];
-
-extern u8* VRAMPtr_ABG[0x20];
-extern u8* VRAMPtr_AOBJ[0x10];
-extern u8* VRAMPtr_BBG[0x8];
-extern u8* VRAMPtr_BOBJ[0x8];
-
-extern int FrontBuffer;
-extern u32* Framebuffer[2][2];
-
-extern GPU2D::Unit GPU2D_A;
-extern GPU2D::Unit GPU2D_B;
-extern int Renderer;
-
-const u32 VRAMDirtyGranularity = 512;
+namespace GPU3D
+{
+class GPU3D;
+}
-extern NonStupidBitField<128*1024/VRAMDirtyGranularity> VRAMDirty[9];
+namespace Melon
+{
+static constexpr u32 VRAMDirtyGranularity = 512;
+class GPU;
template <u32 Size, u32 MappingGranularity>
struct VRAMTrackingSet
@@ -100,524 +56,657 @@ struct VRAMTrackingSet
Mapping[i] = 0x8000;
}
}
- NonStupidBitField<Size/VRAMDirtyGranularity> DeriveState(u32* currentMappings);
+ NonStupidBitField<Size/VRAMDirtyGranularity> DeriveState(u32* currentMappings, GPU& gpu);
};
-extern VRAMTrackingSet<512*1024, 16*1024> VRAMDirty_ABG;
-extern VRAMTrackingSet<256*1024, 16*1024> VRAMDirty_AOBJ;
-extern VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_BBG;
-extern VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_BOBJ;
+struct RenderSettings
+{
+ bool Soft_Threaded;
-extern VRAMTrackingSet<32*1024, 8*1024> VRAMDirty_ABGExtPal;
-extern VRAMTrackingSet<32*1024, 8*1024> VRAMDirty_BBGExtPal;
-extern VRAMTrackingSet<8*1024, 8*1024> VRAMDirty_AOBJExtPal;
-extern VRAMTrackingSet<8*1024, 8*1024> VRAMDirty_BOBJExtPal;
+ int GL_ScaleFactor;
+ bool GL_BetterPolygons;
+};
-extern VRAMTrackingSet<512*1024, 128*1024> VRAMDirty_Texture;
-extern VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_TexPal;
+class GPU
+{
+public:
+ GPU() noexcept;
+ ~GPU() noexcept;
+ void Reset() noexcept;
+ void Stop() noexcept;
-extern u8 VRAMFlat_ABG[512*1024];
-extern u8 VRAMFlat_BBG[128*1024];
-extern u8 VRAMFlat_AOBJ[256*1024];
-extern u8 VRAMFlat_BOBJ[128*1024];
+ void DoSavestate(Savestate* file) noexcept;
-extern u8 VRAMFlat_ABGExtPal[32*1024];
-extern u8 VRAMFlat_BBGExtPal[32*1024];
+ [[deprecated("Set the renderer directly instead of using an integer code")]] void InitRenderer(int renderer) noexcept;
+ void DeInitRenderer() noexcept;
+ void ResetRenderer() noexcept;
-extern u8 VRAMFlat_AOBJExtPal[8*1024];
-extern u8 VRAMFlat_BOBJExtPal[8*1024];
+ void SetRenderSettings(int renderer, RenderSettings& settings) noexcept;
-extern u8 VRAMFlat_Texture[512*1024];
-extern u8 VRAMFlat_TexPal[128*1024];
+ u8* GetUniqueBankPtr(u32 mask, u32 offset) noexcept;
+ const u8* GetUniqueBankPtr(u32 mask, u32 offset) const noexcept;
-bool MakeVRAMFlat_ABGCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty);
-bool MakeVRAMFlat_BBGCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty);
+ void MapVRAM_AB(u32 bank, u8 cnt) noexcept;
+ void MapVRAM_CD(u32 bank, u8 cnt) noexcept;
+ void MapVRAM_E(u32 bank, u8 cnt) noexcept;
+ void MapVRAM_FG(u32 bank, u8 cnt) noexcept;
+ void MapVRAM_H(u32 bank, u8 cnt) noexcept;
+ void MapVRAM_I(u32 bank, u8 cnt) noexcept;
-bool MakeVRAMFlat_AOBJCoherent(NonStupidBitField<256*1024/VRAMDirtyGranularity>& dirty);
-bool MakeVRAMFlat_BOBJCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty);
+ template<typename T>
+ T ReadVRAM_LCDC(u32 addr) const noexcept
+ {
+ int bank;
-bool MakeVRAMFlat_ABGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty);
-bool MakeVRAMFlat_BBGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty);
+ switch (addr & 0xFF8FC000)
+ {
+ case 0x06800000: case 0x06804000: case 0x06808000: case 0x0680C000:
+ case 0x06810000: case 0x06814000: case 0x06818000: case 0x0681C000:
+ bank = 0;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06820000: case 0x06824000: case 0x06828000: case 0x0682C000:
+ case 0x06830000: case 0x06834000: case 0x06838000: case 0x0683C000:
+ bank = 1;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06840000: case 0x06844000: case 0x06848000: case 0x0684C000:
+ case 0x06850000: case 0x06854000: case 0x06858000: case 0x0685C000:
+ bank = 2;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06860000: case 0x06864000: case 0x06868000: case 0x0686C000:
+ case 0x06870000: case 0x06874000: case 0x06878000: case 0x0687C000:
+ bank = 3;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06880000: case 0x06884000: case 0x06888000: case 0x0688C000:
+ bank = 4;
+ addr &= 0xFFFF;
+ break;
+
+ case 0x06890000:
+ bank = 5;
+ addr &= 0x3FFF;
+ break;
+
+ case 0x06894000:
+ bank = 6;
+ addr &= 0x3FFF;
+ break;
+
+ case 0x06898000:
+ case 0x0689C000:
+ bank = 7;
+ addr &= 0x7FFF;
+ break;
+
+ case 0x068A0000:
+ bank = 8;
+ addr &= 0x3FFF;
+ break;
+
+ default: return 0;
+ }
-bool MakeVRAMFlat_AOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty);
-bool MakeVRAMFlat_BOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty);
+ if (VRAMMap_LCDC & (1<<bank)) return *(T*)&VRAM[bank][addr];
-bool MakeVRAMFlat_TextureCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty);
-bool MakeVRAMFlat_TexPalCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty);
+ return 0;
+ }
-void SyncDirtyFlags();
+ template<typename T>
+ void WriteVRAM_LCDC(u32 addr, T val)
+ {
+ int bank;
-extern u32 OAMDirty;
-extern u32 PaletteDirty;
+ switch (addr & 0xFF8FC000)
+ {
+ case 0x06800000: case 0x06804000: case 0x06808000: case 0x0680C000:
+ case 0x06810000: case 0x06814000: case 0x06818000: case 0x0681C000:
+ bank = 0;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06820000: case 0x06824000: case 0x06828000: case 0x0682C000:
+ case 0x06830000: case 0x06834000: case 0x06838000: case 0x0683C000:
+ bank = 1;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06840000: case 0x06844000: case 0x06848000: case 0x0684C000:
+ case 0x06850000: case 0x06854000: case 0x06858000: case 0x0685C000:
+ bank = 2;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06860000: case 0x06864000: case 0x06868000: case 0x0686C000:
+ case 0x06870000: case 0x06874000: case 0x06878000: case 0x0687C000:
+ bank = 3;
+ addr &= 0x1FFFF;
+ break;
+
+ case 0x06880000: case 0x06884000: case 0x06888000: case 0x0688C000:
+ bank = 4;
+ addr &= 0xFFFF;
+ break;
+
+ case 0x06890000:
+ bank = 5;
+ addr &= 0x3FFF;
+ break;
+
+ case 0x06894000:
+ bank = 6;
+ addr &= 0x3FFF;
+ break;
+
+ case 0x06898000:
+ case 0x0689C000:
+ bank = 7;
+ addr &= 0x7FFF;
+ break;
+
+ case 0x068A0000:
+ bank = 8;
+ addr &= 0x3FFF;
+ break;
+
+ default: return;
+ }
-#ifdef OGLRENDERER_ENABLED
-extern std::unique_ptr<GLCompositor> CurGLCompositor;
-#endif
+ if (VRAMMap_LCDC & (1<<bank))
+ {
+ *(T*)&VRAM[bank][addr] = val;
+ VRAMDirty[bank][addr / VRAMDirtyGranularity] = true;
+ }
+ }
-struct RenderSettings
-{
- bool Soft_Threaded;
- int GL_ScaleFactor;
- bool GL_BetterPolygons;
-};
+ template<typename T>
+ T ReadVRAM_ABG(u32 addr) const noexcept
+ {
+ u8* ptr = VRAMPtr_ABG[(addr >> 14) & 0x1F];
+ if (ptr) return *(T*)&ptr[addr & 0x3FFF];
+ T ret = 0;
+ u32 mask = VRAMMap_ABG[(addr >> 14) & 0x1F];
-bool Init();
-void DeInit();
-void Reset();
-void Stop();
+ if (mask & (1<<0)) ret |= *(T*)&VRAM_A[addr & 0x1FFFF];
+ if (mask & (1<<1)) ret |= *(T*)&VRAM_B[addr & 0x1FFFF];
+ if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
+ if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
+ if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0xFFFF];
+ if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
+ if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
-void DoSavestate(Savestate* file);
+ return ret;
+ }
-void InitRenderer(int renderer);
-void DeInitRenderer();
-void ResetRenderer();
+ template<typename T>
+ void WriteVRAM_ABG(u32 addr, T val)
+ {
+ u32 mask = VRAMMap_ABG[(addr >> 14) & 0x1F];
-void SetRenderSettings(int renderer, RenderSettings& settings);
+ if (mask & (1<<0))
+ {
+ VRAMDirty[0][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_A[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<1))
+ {
+ VRAMDirty[1][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_B[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<2))
+ {
+ VRAMDirty[2][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_C[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<3))
+ {
+ VRAMDirty[3][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_D[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<4))
+ {
+ VRAMDirty[4][(addr & 0xFFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_E[addr & 0xFFFF] = val;
+ }
+ if (mask & (1<<5))
+ {
+ VRAMDirty[5][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_F[addr & 0x3FFF] = val;
+ }
+ if (mask & (1<<6))
+ {
+ VRAMDirty[6][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_G[addr & 0x3FFF] = val;
+ }
+ }
-u8* GetUniqueBankPtr(u32 mask, u32 offset);
+ template<typename T>
+ T ReadVRAM_AOBJ(u32 addr) const noexcept
+ {
+ u8* ptr = VRAMPtr_AOBJ[(addr >> 14) & 0xF];
+ if (ptr) return *(T*)&ptr[addr & 0x3FFF];
-void MapVRAM_AB(u32 bank, u8 cnt);
-void MapVRAM_CD(u32 bank, u8 cnt);
-void MapVRAM_E(u32 bank, u8 cnt);
-void MapVRAM_FG(u32 bank, u8 cnt);
-void MapVRAM_H(u32 bank, u8 cnt);
-void MapVRAM_I(u32 bank, u8 cnt);
+ T ret = 0;
+ u32 mask = VRAMMap_AOBJ[(addr >> 14) & 0xF];
+ if (mask & (1<<0)) ret |= *(T*)&VRAM_A[addr & 0x1FFFF];
+ if (mask & (1<<1)) ret |= *(T*)&VRAM_B[addr & 0x1FFFF];
+ if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0xFFFF];
+ if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
+ if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
-template<typename T>
-T ReadVRAM_LCDC(u32 addr)
-{
- int bank;
+ return ret;
+ }
- switch (addr & 0xFF8FC000)
+ template<typename T>
+ void WriteVRAM_AOBJ(u32 addr, T val)
{
- case 0x06800000: case 0x06804000: case 0x06808000: case 0x0680C000:
- case 0x06810000: case 0x06814000: case 0x06818000: case 0x0681C000:
- bank = 0;
- addr &= 0x1FFFF;
- break;
-
- case 0x06820000: case 0x06824000: case 0x06828000: case 0x0682C000:
- case 0x06830000: case 0x06834000: case 0x06838000: case 0x0683C000:
- bank = 1;
- addr &= 0x1FFFF;
- break;
-
- case 0x06840000: case 0x06844000: case 0x06848000: case 0x0684C000:
- case 0x06850000: case 0x06854000: case 0x06858000: case 0x0685C000:
- bank = 2;
- addr &= 0x1FFFF;
- break;
-
- case 0x06860000: case 0x06864000: case 0x06868000: case 0x0686C000:
- case 0x06870000: case 0x06874000: case 0x06878000: case 0x0687C000:
- bank = 3;
- addr &= 0x1FFFF;
- break;
-
- case 0x06880000: case 0x06884000: case 0x06888000: case 0x0688C000:
- bank = 4;
- addr &= 0xFFFF;
- break;
-
- case 0x06890000:
- bank = 5;
- addr &= 0x3FFF;
- break;
-
- case 0x06894000:
- bank = 6;
- addr &= 0x3FFF;
- break;
-
- case 0x06898000:
- case 0x0689C000:
- bank = 7;
- addr &= 0x7FFF;
- break;
-
- case 0x068A0000:
- bank = 8;
- addr &= 0x3FFF;
- break;
-
- default: return 0;
+ u32 mask = VRAMMap_AOBJ[(addr >> 14) & 0xF];
+
+ if (mask & (1<<0))
+ {
+ VRAMDirty[0][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_A[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<1))
+ {
+ VRAMDirty[1][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_B[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<4))
+ {
+ VRAMDirty[4][(addr & 0xFFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_E[addr & 0xFFFF] = val;
+ }
+ if (mask & (1<<5))
+ {
+ VRAMDirty[5][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_F[addr & 0x3FFF] = val;
+ }
+ if (mask & (1<<6))
+ {
+ VRAMDirty[6][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_G[addr & 0x3FFF] = val;
+ }
}
- if (VRAMMap_LCDC & (1<<bank)) return *(T*)&VRAM[bank][addr];
- return 0;
-}
+ template<typename T>
+ T ReadVRAM_BBG(u32 addr) const noexcept
+ {
+ u8* ptr = VRAMPtr_BBG[(addr >> 14) & 0x7];
+ if (ptr) return *(T*)&ptr[addr & 0x3FFF];
-template<typename T>
-void WriteVRAM_LCDC(u32 addr, T val)
-{
- int bank;
+ T ret = 0;
+ u32 mask = VRAMMap_BBG[(addr >> 14) & 0x7];
- switch (addr & 0xFF8FC000)
- {
- case 0x06800000: case 0x06804000: case 0x06808000: case 0x0680C000:
- case 0x06810000: case 0x06814000: case 0x06818000: case 0x0681C000:
- bank = 0;
- addr &= 0x1FFFF;
- break;
-
- case 0x06820000: case 0x06824000: case 0x06828000: case 0x0682C000:
- case 0x06830000: case 0x06834000: case 0x06838000: case 0x0683C000:
- bank = 1;
- addr &= 0x1FFFF;
- break;
-
- case 0x06840000: case 0x06844000: case 0x06848000: case 0x0684C000:
- case 0x06850000: case 0x06854000: case 0x06858000: case 0x0685C000:
- bank = 2;
- addr &= 0x1FFFF;
- break;
-
- case 0x06860000: case 0x06864000: case 0x06868000: case 0x0686C000:
- case 0x06870000: case 0x06874000: case 0x06878000: case 0x0687C000:
- bank = 3;
- addr &= 0x1FFFF;
- break;
-
- case 0x06880000: case 0x06884000: case 0x06888000: case 0x0688C000:
- bank = 4;
- addr &= 0xFFFF;
- break;
-
- case 0x06890000:
- bank = 5;
- addr &= 0x3FFF;
- break;
-
- case 0x06894000:
- bank = 6;
- addr &= 0x3FFF;
- break;
-
- case 0x06898000:
- case 0x0689C000:
- bank = 7;
- addr &= 0x7FFF;
- break;
-
- case 0x068A0000:
- bank = 8;
- addr &= 0x3FFF;
- break;
-
- default: return;
- }
+ if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
+ if (mask & (1<<7)) ret |= *(T*)&VRAM_H[addr & 0x7FFF];
+ if (mask & (1<<8)) ret |= *(T*)&VRAM_I[addr & 0x3FFF];
- if (VRAMMap_LCDC & (1<<bank))
- {
- *(T*)&VRAM[bank][addr] = val;
- VRAMDirty[bank][addr / VRAMDirtyGranularity] = true;
+ return ret;
}
-}
+ template<typename T>
+ void WriteVRAM_BBG(u32 addr, T val)
+ {
+ u32 mask = VRAMMap_BBG[(addr >> 14) & 0x7];
-template<typename T>
-T ReadVRAM_ABG(u32 addr)
-{
- u8* ptr = VRAMPtr_ABG[(addr >> 14) & 0x1F];
- if (ptr) return *(T*)&ptr[addr & 0x3FFF];
+ if (mask & (1<<2))
+ {
+ VRAMDirty[2][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_C[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<7))
+ {
+ VRAMDirty[7][(addr & 0x7FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_H[addr & 0x7FFF] = val;
+ }
+ if (mask & (1<<8))
+ {
+ VRAMDirty[8][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_I[addr & 0x3FFF] = val;
+ }
+ }
- T ret = 0;
- u32 mask = VRAMMap_ABG[(addr >> 14) & 0x1F];
- if (mask & (1<<0)) ret |= *(T*)&VRAM_A[addr & 0x1FFFF];
- if (mask & (1<<1)) ret |= *(T*)&VRAM_B[addr & 0x1FFFF];
- if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
- if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
- if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0xFFFF];
- if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
- if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
+ template<typename T>
+ T ReadVRAM_BOBJ(u32 addr) const noexcept
+ {
+ u8* ptr = VRAMPtr_BOBJ[(addr >> 14) & 0x7];
+ if (ptr) return *(T*)&ptr[addr & 0x3FFF];
- return ret;
-}
+ T ret = 0;
+ u32 mask = VRAMMap_BOBJ[(addr >> 14) & 0x7];
-template<typename T>
-void WriteVRAM_ABG(u32 addr, T val)
-{
- u32 mask = VRAMMap_ABG[(addr >> 14) & 0x1F];
+ if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
+ if (mask & (1<<8)) ret |= *(T*)&VRAM_I[addr & 0x3FFF];
- if (mask & (1<<0))
- {
- VRAMDirty[0][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_A[addr & 0x1FFFF] = val;
- }
- if (mask & (1<<1))
- {
- VRAMDirty[1][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_B[addr & 0x1FFFF] = val;
+ return ret;
}
- if (mask & (1<<2))
+
+ template<typename T>
+ void WriteVRAM_BOBJ(u32 addr, T val)
{
- VRAMDirty[2][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_C[addr & 0x1FFFF] = val;
+ u32 mask = VRAMMap_BOBJ[(addr >> 14) & 0x7];
+
+ if (mask & (1<<3))
+ {
+ VRAMDirty[3][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_D[addr & 0x1FFFF] = val;
+ }
+ if (mask & (1<<8))
+ {
+ VRAMDirty[8][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
+ *(T*)&VRAM_I[addr & 0x3FFF] = val;
+ }
}
- if (mask & (1<<3))
+
+ template<typename T>
+ T ReadVRAM_ARM7(u32 addr) const noexcept
{
- VRAMDirty[3][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_D[addr & 0x1FFFF] = val;
+ T ret = 0;
+ u32 mask = VRAMMap_ARM7[(addr >> 17) & 0x1];
+
+ if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
+ if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
+
+ return ret;
}
- if (mask & (1<<4))
+
+ template<typename T>
+ void WriteVRAM_ARM7(u32 addr, T val)
{
- VRAMDirty[4][(addr & 0xFFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_E[addr & 0xFFFF] = val;
+ u32 mask = VRAMMap_ARM7[(addr >> 17) & 0x1];
+
+ if (mask & (1<<2)) *(T*)&VRAM_C[addr & 0x1FFFF] = val;
+ if (mask & (1<<3)) *(T*)&VRAM_D[addr & 0x1FFFF] = val;
}
- if (mask & (1<<5))
+
+
+ template<typename T>
+ T ReadVRAM_BG(u32 addr) const noexcept
{
- VRAMDirty[5][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_F[addr & 0x3FFF] = val;
+ if ((addr & 0xFFE00000) == 0x06000000)
+ return ReadVRAM_ABG<T>(addr);
+ else
+ return ReadVRAM_BBG<T>(addr);
}
- if (mask & (1<<6))
+
+ template<typename T>
+ T ReadVRAM_OBJ(u32 addr) const noexcept
{
- VRAMDirty[6][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_G[addr & 0x3FFF] = val;
+ if ((addr & 0xFFE00000) == 0x06400000)
+ return ReadVRAM_AOBJ<T>(addr);
+ else
+ return ReadVRAM_BOBJ<T>(addr);
}
-}
-template<typename T>
-T ReadVRAM_AOBJ(u32 addr)
-{
- u8* ptr = VRAMPtr_AOBJ[(addr >> 14) & 0xF];
- if (ptr) return *(T*)&ptr[addr & 0x3FFF];
+ template<typename T>
+ T ReadVRAM_Texture(u32 addr) const noexcept
+ {
+ T ret = 0;
+ u32 mask = VRAMMap_Texture[(addr >> 17) & 0x3];
- T ret = 0;
- u32 mask = VRAMMap_AOBJ[(addr >> 14) & 0xF];
+ if (mask & (1<<0)) ret |= *(T*)&VRAM_A[addr & 0x1FFFF];
+ if (mask & (1<<1)) ret |= *(T*)&VRAM_B[addr & 0x1FFFF];
+ if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
+ if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
- if (mask & (1<<0)) ret |= *(T*)&VRAM_A[addr & 0x1FFFF];
- if (mask & (1<<1)) ret |= *(T*)&VRAM_B[addr & 0x1FFFF];
- if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0xFFFF];
- if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
- if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
+ return ret;
+ }
- return ret;
-}
+ template<typename T>
+ T ReadVRAM_TexPal(u32 addr) const noexcept
+ {
+ T ret = 0;
+ u32 mask = VRAMMap_TexPal[(addr >> 14) & 0x7];
-template<typename T>
-void WriteVRAM_AOBJ(u32 addr, T val)
-{
- u32 mask = VRAMMap_AOBJ[(addr >> 14) & 0xF];
+ if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0xFFFF];
+ if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
+ if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
- if (mask & (1<<0))
- {
- VRAMDirty[0][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_A[addr & 0x1FFFF] = val;
+ return ret;
}
- if (mask & (1<<1))
+
+ template<typename T>
+ T ReadPalette(u32 addr) const noexcept
{
- VRAMDirty[1][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_B[addr & 0x1FFFF] = val;
+ return *(T*)&Palette[addr & 0x7FF];
}
- if (mask & (1<<4))
+
+ template<typename T>
+ void WritePalette(u32 addr, T val)
{
- VRAMDirty[4][(addr & 0xFFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_E[addr & 0xFFFF] = val;
+ addr &= 0x7FF;
+
+ *(T*)&Palette[addr] = val;
+ PaletteDirty |= 1 << (addr / VRAMDirtyGranularity);
}
- if (mask & (1<<5))
+
+ template<typename T>
+ T ReadOAM(u32 addr) const noexcept
{
- VRAMDirty[5][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_F[addr & 0x3FFF] = val;
+ return *(T*)&OAM[addr & 0x7FF];
}
- if (mask & (1<<6))
+
+ template<typename T>
+ void WriteOAM(u32 addr, T val)
{
- VRAMDirty[6][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_G[addr & 0x3FFF] = val;
+ addr &= 0x7FF;
+
+ *(T*)&OAM[addr] = val;
+ OAMDirty |= 1 << (addr / 1024);
}
-}
+ void SetPowerCnt(u32 val) noexcept;
-template<typename T>
-T ReadVRAM_BBG(u32 addr)
-{
- u8* ptr = VRAMPtr_BBG[(addr >> 14) & 0x7];
- if (ptr) return *(T*)&ptr[addr & 0x3FFF];
+ void StartFrame() noexcept;
+ void FinishFrame(u32 lines) noexcept;
+ void BlankFrame() noexcept;
+ void StartScanline(u32 line) noexcept;
+ void StartHBlank(u32 line) noexcept;
- T ret = 0;
- u32 mask = VRAMMap_BBG[(addr >> 14) & 0x7];
+ void DisplayFIFO(u32 x) noexcept;
- if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
- if (mask & (1<<7)) ret |= *(T*)&VRAM_H[addr & 0x7FFF];
- if (mask & (1<<8)) ret |= *(T*)&VRAM_I[addr & 0x3FFF];
+ void SetDispStat(u32 cpu, u16 val) noexcept;
- return ret;
-}
+ void SetVCount(u16 val) noexcept;
+ bool MakeVRAMFlat_ABGCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty) noexcept;
+ bool MakeVRAMFlat_BBGCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty) noexcept;
-template<typename T>
-void WriteVRAM_BBG(u32 addr, T val)
-{
- u32 mask = VRAMMap_BBG[(addr >> 14) & 0x7];
+ bool MakeVRAMFlat_AOBJCoherent(NonStupidBitField<256*1024/VRAMDirtyGranularity>& dirty) noexcept;
+ bool MakeVRAMFlat_BOBJCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty) noexcept;
- if (mask & (1<<2))
- {
- VRAMDirty[2][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_C[addr & 0x1FFFF] = val;
- }
- if (mask & (1<<7))
- {
- VRAMDirty[7][(addr & 0x7FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_H[addr & 0x7FFF] = val;
- }
- if (mask & (1<<8))
- {
- VRAMDirty[8][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_I[addr & 0x3FFF] = val;
- }
-}
+ bool MakeVRAMFlat_ABGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty) noexcept;
+ bool MakeVRAMFlat_BBGExtPalCoherent(NonStupidBitField<32*1024/VRAMDirtyGranularity>& dirty) noexcept;
+ bool MakeVRAMFlat_AOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty) noexcept;
+ bool MakeVRAMFlat_BOBJExtPalCoherent(NonStupidBitField<8*1024/VRAMDirtyGranularity>& dirty) noexcept;
-template<typename T>
-T ReadVRAM_BOBJ(u32 addr)
-{
- u8* ptr = VRAMPtr_BOBJ[(addr >> 14) & 0x7];
- if (ptr) return *(T*)&ptr[addr & 0x3FFF];
+ bool MakeVRAMFlat_TextureCoherent(NonStupidBitField<512*1024/VRAMDirtyGranularity>& dirty) noexcept;
+ bool MakeVRAMFlat_TexPalCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity>& dirty) noexcept;
- T ret = 0;
- u32 mask = VRAMMap_BOBJ[(addr >> 14) & 0x7];
+ void SyncDirtyFlags() noexcept;
- if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
- if (mask & (1<<8)) ret |= *(T*)&VRAM_I[addr & 0x3FFF];
+ u16 VCount = 0;
+ u16 TotalScanlines = 0;
+ u16 DispStat[2] {};
+ u8 VRAMCNT[9] {};
+ u8 VRAMSTAT = 0;
- return ret;
-}
+ u8 Palette[2*1024] {};
+ u8 OAM[2*1024] {};
-template<typename T>
-void WriteVRAM_BOBJ(u32 addr, T val)
-{
- u32 mask = VRAMMap_BOBJ[(addr >> 14) & 0x7];
+ 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] {};
- if (mask & (1<<3))
- {
- VRAMDirty[3][(addr & 0x1FFFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_D[addr & 0x1FFFF] = val;
- }
- if (mask & (1<<8))
- {
- VRAMDirty[8][(addr & 0x3FFF) / VRAMDirtyGranularity] = true;
- *(T*)&VRAM_I[addr & 0x3FFF] = val;
- }
-}
+ 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};
-template<typename T>
-T ReadVRAM_ARM7(u32 addr)
-{
- T ret = 0;
- u32 mask = VRAMMap_ARM7[(addr >> 17) & 0x1];
+ u32 VRAMMap_LCDC = 0;
+ 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] {};
- if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
- if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
+ u8* VRAMPtr_ABG[0x20] {};
+ u8* VRAMPtr_AOBJ[0x10] {};
+ u8* VRAMPtr_BBG[0x8] {};
+ u8* VRAMPtr_BOBJ[0x8] {};
- return ret;
-}
+ int FrontBuffer = 0;
+ u32* Framebuffer[2][2] {};
-template<typename T>
-void WriteVRAM_ARM7(u32 addr, T val)
-{
- u32 mask = VRAMMap_ARM7[(addr >> 17) & 0x1];
+ GPU2D::Unit GPU2D_A;
+ GPU2D::Unit GPU2D_B;
+ GPU3D::GPU3D GPU3D {};
- if (mask & (1<<2)) *(T*)&VRAM_C[addr & 0x1FFFF] = val;
- if (mask & (1<<3)) *(T*)&VRAM_D[addr & 0x1FFFF] = val;
-}
+ NonStupidBitField<128*1024/VRAMDirtyGranularity> VRAMDirty[9] {};
+ 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 {};
-template<typename T>
-T ReadVRAM_BG(u32 addr)
-{
- if ((addr & 0xFFE00000) == 0x06000000)
- return ReadVRAM_ABG<T>(addr);
- else
- return ReadVRAM_BBG<T>(addr);
-}
+ VRAMTrackingSet<512*1024, 128*1024> VRAMDirty_Texture {};
+ VRAMTrackingSet<128*1024, 16*1024> VRAMDirty_TexPal {};
-template<typename T>
-T ReadVRAM_OBJ(u32 addr)
-{
- if ((addr & 0xFFE00000) == 0x06400000)
- return ReadVRAM_AOBJ<T>(addr);
- else
- return ReadVRAM_BOBJ<T>(addr);
-}
+ 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] {};
-template<typename T>
-T ReadVRAM_Texture(u32 addr)
-{
- T ret = 0;
- u32 mask = VRAMMap_Texture[(addr >> 17) & 0x3];
+ u8 VRAMFlat_AOBJExtPal[8*1024] {};
+ u8 VRAMFlat_BOBJExtPal[8*1024] {};
+
+ u8 VRAMFlat_Texture[512*1024] {};
+ u8 VRAMFlat_TexPal[128*1024] {};
+
+ int Renderer = 0;
+#ifdef OGLRENDERER_ENABLED
+ std::unique_ptr<GLCompositor> CurGLCompositor = nullptr;
+#endif
+private:
+ void ResetVRAMCache() noexcept;
+ void AssignFramebuffers() noexcept;
+ template<typename T>
+ T ReadVRAM_ABGExtPal(u32 addr) const noexcept
+ {
+ u32 mask = VRAMMap_ABGExtPal[(addr >> 13) & 0x3];
- if (mask & (1<<0)) ret |= *(T*)&VRAM_A[addr & 0x1FFFF];
- if (mask & (1<<1)) ret |= *(T*)&VRAM_B[addr & 0x1FFFF];
- if (mask & (1<<2)) ret |= *(T*)&VRAM_C[addr & 0x1FFFF];
- if (mask & (1<<3)) ret |= *(T*)&VRAM_D[addr & 0x1FFFF];
+ 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 ret;
+ }
-template<typename T>
-T ReadVRAM_TexPal(u32 addr)
-{
- T ret = 0;
- u32 mask = VRAMMap_TexPal[(addr >> 14) & 0x7];
+ template<typename T>
+ T ReadVRAM_BBGExtPal(u32 addr) const noexcept
+ {
+ u32 mask = VRAMMap_BBGExtPal[(addr >> 13) & 0x3];
- if (mask & (1<<4)) ret |= *(T*)&VRAM_E[addr & 0xFFFF];
- if (mask & (1<<5)) ret |= *(T*)&VRAM_F[addr & 0x3FFF];
- if (mask & (1<<6)) ret |= *(T*)&VRAM_G[addr & 0x3FFF];
+ T ret = 0;
+ if (mask & (1<<7)) ret |= *(T*)&VRAM_H[addr & 0x7FFF];
- return ret;
-}
+ return ret;
+ }
-template<typename T>
-T ReadPalette(u32 addr)
-{
- return *(T*)&Palette[addr & 0x7FF];
-}
+ template<typename T>
+ T ReadVRAM_AOBJExtPal(u32 addr) const noexcept
+ {
+ u32 mask = VRAMMap_AOBJExtPal;
-template<typename T>
-void WritePalette(u32 addr, T val)
-{
- addr &= 0x7FF;
+ T ret = 0;
+ if (mask & (1<<4)) ret |= *(T*)&VRAM_F[addr & 0x1FFF];
+ if (mask & (1<<5)) ret |= *(T*)&VRAM_G[addr & 0x1FFF];
- *(T*)&Palette[addr] = val;
- PaletteDirty |= 1 << (addr / VRAMDirtyGranularity);
-}
+ return ret;
+ }
-template<typename T>
-T ReadOAM(u32 addr)
-{
- return *(T*)&OAM[addr & 0x7FF];
-}
+ template<typename T>
+ T ReadVRAM_BOBJExtPal(u32 addr) const noexcept
+ {
+ u32 mask = VRAMMap_BOBJExtPal;
-template<typename T>
-void WriteOAM(u32 addr, T val)
-{
- addr &= 0x7FF;
+ T ret = 0;
+ if (mask & (1<<8)) ret |= *(T*)&VRAM_I[addr & 0x1FFF];
- *(T*)&OAM[addr] = val;
- OAMDirty |= 1 << (addr / 1024);
-}
+ return ret;
+ }
-void SetPowerCnt(u32 val);
+ template <u32 MappingGranularity, u32 Size>
+ constexpr bool CopyLinearVRAM(u8* flat, const u32* mappings, NonStupidBitField<Size>& dirty, u64 (GPU::* const slowAccess)(u32) const noexcept) noexcept
+ {
+ const u32 VRAMBitsPerMapping = MappingGranularity / VRAMDirtyGranularity;
-void StartFrame();
-void FinishFrame(u32 lines);
-void BlankFrame();
-void StartScanline(u32 line);
-void StartHBlank(u32 line);
+ bool change = false;
-void DisplayFIFO(u32 x);
+ 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] = (this->*slowAccess)(offset + i);
+ }
+ change = true;
+ it++;
+ }
+ return change;
+ }
-void SetDispStat(u32 cpu, u16 val);
+ u32 NextVCount = 0;
-void SetVCount(u16 val);
-}
+ bool RunFIFO = false;
-#include "GPU3D.h"
+ u16 VMatch[2] {};
+
+ std::unique_ptr<GPU2D::Renderer2D> GPU2D_Renderer = nullptr;
+
+ u32 OAMDirty = 0;
+ u32 PaletteDirty = 0;
+};
+}
#endif