2017-02-07 21:23:46 +00:00
|
|
|
/*
|
2024-06-15 15:01:19 +00:00
|
|
|
Copyright 2016-2024 melonDS team
|
2017-02-07 21:23:46 +00:00
|
|
|
|
|
|
|
This file is part of melonDS.
|
|
|
|
|
|
|
|
melonDS is free software: you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU General Public License as published by the Free
|
|
|
|
Software Foundation, either version 3 of the License, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef GPU3D_H
|
|
|
|
#define GPU3D_H
|
|
|
|
|
2017-07-05 16:11:00 +00:00
|
|
|
#include <array>
|
2021-02-09 22:38:51 +00:00
|
|
|
#include <memory>
|
|
|
|
|
2018-10-18 00:31:01 +00:00
|
|
|
#include "Savestate.h"
|
2023-11-09 20:54:51 +00:00
|
|
|
#include "FIFO.h"
|
|
|
|
|
2023-11-25 17:32:09 +00:00
|
|
|
namespace melonDS
|
2023-11-09 20:54:51 +00:00
|
|
|
{
|
2023-11-29 14:23:11 +00:00
|
|
|
class GPU;
|
2017-02-07 21:23:46 +00:00
|
|
|
|
2021-01-02 10:38:06 +00:00
|
|
|
struct Vertex
|
2017-02-10 14:24:46 +00:00
|
|
|
{
|
|
|
|
s32 Position[4];
|
2017-02-20 17:46:44 +00:00
|
|
|
s32 Color[3];
|
2017-02-27 23:50:54 +00:00
|
|
|
s16 TexCoords[2];
|
2017-02-10 14:24:46 +00:00
|
|
|
|
2017-02-14 01:43:35 +00:00
|
|
|
bool Clipped;
|
|
|
|
|
2017-02-17 03:07:00 +00:00
|
|
|
// final vertex attributes.
|
|
|
|
// allows them to be reused in polygon strips.
|
|
|
|
|
2017-04-21 20:40:15 +00:00
|
|
|
s32 FinalPosition[2];
|
2017-02-17 03:07:00 +00:00
|
|
|
s32 FinalColor[3];
|
|
|
|
|
2019-05-11 13:14:59 +00:00
|
|
|
// hi-res position (4-bit fractional part)
|
|
|
|
// TODO maybe: hi-res color? (that survives clipping)
|
|
|
|
s32 HiresPosition[2];
|
|
|
|
|
2024-01-07 22:39:43 +00:00
|
|
|
void DoSavestate(Savestate* file) noexcept;
|
2021-01-02 10:38:06 +00:00
|
|
|
};
|
2017-02-10 14:24:46 +00:00
|
|
|
|
2021-01-02 10:38:06 +00:00
|
|
|
struct Polygon
|
2017-02-10 14:24:46 +00:00
|
|
|
{
|
|
|
|
Vertex* Vertices[10];
|
|
|
|
u32 NumVertices;
|
|
|
|
|
2017-04-21 20:40:15 +00:00
|
|
|
s32 FinalZ[10];
|
|
|
|
s32 FinalW[10];
|
2017-04-28 22:20:04 +00:00
|
|
|
bool WBuffer;
|
2017-04-21 20:40:15 +00:00
|
|
|
|
2017-02-14 01:43:35 +00:00
|
|
|
u32 Attr;
|
2017-02-27 23:52:17 +00:00
|
|
|
u32 TexParam;
|
|
|
|
u32 TexPalette;
|
2017-02-14 01:43:35 +00:00
|
|
|
|
2018-12-20 00:31:31 +00:00
|
|
|
bool Degenerate;
|
|
|
|
|
2017-02-14 01:43:35 +00:00
|
|
|
bool FacingView;
|
2017-03-15 14:53:36 +00:00
|
|
|
bool Translucent;
|
2017-02-14 01:43:35 +00:00
|
|
|
|
2017-04-22 16:04:54 +00:00
|
|
|
bool IsShadowMask;
|
|
|
|
bool IsShadow;
|
|
|
|
|
2019-06-12 01:55:40 +00:00
|
|
|
int Type; // 0=regular 1=line
|
2019-06-11 01:10:32 +00:00
|
|
|
|
2017-03-16 14:55:18 +00:00
|
|
|
u32 VTop, VBottom; // vertex indices
|
|
|
|
s32 YTop, YBottom; // Y coords
|
|
|
|
s32 XTop, XBottom; // associated X coords
|
|
|
|
|
2017-07-05 16:38:10 +00:00
|
|
|
u32 SortKey;
|
|
|
|
|
2024-01-07 22:39:43 +00:00
|
|
|
void DoSavestate(Savestate* file) noexcept;
|
2021-01-02 10:38:06 +00:00
|
|
|
};
|
2017-02-10 14:24:46 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
class Renderer3D;
|
2023-11-28 22:16:41 +00:00
|
|
|
class NDS;
|
2023-11-09 20:54:51 +00:00
|
|
|
|
|
|
|
class GPU3D
|
|
|
|
{
|
|
|
|
public:
|
2023-11-29 14:23:11 +00:00
|
|
|
GPU3D(melonDS::NDS& nds, std::unique_ptr<Renderer3D>&& renderer = nullptr) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
~GPU3D() noexcept = default;
|
|
|
|
void Reset() noexcept;
|
|
|
|
|
|
|
|
void DoSavestate(Savestate* file) noexcept;
|
|
|
|
|
|
|
|
void SetEnabled(bool geometry, bool rendering) noexcept;
|
|
|
|
|
|
|
|
void ExecuteCommand() noexcept;
|
|
|
|
|
|
|
|
s32 CyclesToRunFor() const noexcept;
|
|
|
|
void Run() noexcept;
|
|
|
|
void CheckFIFOIRQ() noexcept;
|
|
|
|
void CheckFIFODMA() noexcept;
|
|
|
|
|
2023-12-15 13:53:31 +00:00
|
|
|
void VCount144(GPU& gpu) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
void VBlank() noexcept;
|
2023-12-15 13:53:31 +00:00
|
|
|
void VCount215(GPU& gpu) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
|
2023-12-15 13:53:31 +00:00
|
|
|
void RestartFrame(GPU& gpu) noexcept;
|
|
|
|
void Stop(const GPU& gpu) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
|
|
|
|
void SetRenderXPos(u16 xpos) noexcept;
|
|
|
|
[[nodiscard]] u16 GetRenderXPos() const noexcept { return RenderXPos; }
|
|
|
|
u32* GetLine(int line) noexcept;
|
|
|
|
|
|
|
|
void WriteToGXFIFO(u32 val) noexcept;
|
|
|
|
|
|
|
|
[[nodiscard]] bool IsRendererAccelerated() const noexcept;
|
2023-11-29 14:23:11 +00:00
|
|
|
[[nodiscard]] Renderer3D& GetCurrentRenderer() noexcept { return *CurrentRenderer; }
|
|
|
|
[[nodiscard]] const Renderer3D& GetCurrentRenderer() const noexcept { return *CurrentRenderer; }
|
2023-12-21 20:43:57 +00:00
|
|
|
void SetCurrentRenderer(std::unique_ptr<Renderer3D>&& renderer) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
|
|
|
|
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;
|
2023-12-15 13:53:31 +00:00
|
|
|
void Blit(const GPU& gpu) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
private:
|
2023-11-28 22:16:41 +00:00
|
|
|
melonDS::NDS& NDS;
|
2023-11-09 20:54:51 +00:00
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
u64 _contents;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u32 Param;
|
|
|
|
u8 Command;
|
|
|
|
};
|
|
|
|
|
|
|
|
} CmdFIFOEntry;
|
|
|
|
|
|
|
|
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;
|
2023-12-12 10:07:22 +00:00
|
|
|
void BoxTest(const u32* params) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
void PosTest() noexcept;
|
|
|
|
void VecTest(u32 param) noexcept;
|
2023-12-12 10:07:22 +00:00
|
|
|
void CmdFIFOWrite(const CmdFIFOEntry& entry) noexcept;
|
2023-11-09 20:54:51 +00:00
|
|
|
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 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 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 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Renderer3D> CurrentRenderer = nullptr;
|
|
|
|
|
|
|
|
u16 RenderXPos = 0;
|
|
|
|
|
|
|
|
public:
|
|
|
|
FIFO<CmdFIFOEntry, 256> CmdFIFO {};
|
|
|
|
FIFO<CmdFIFOEntry, 4> CmdPIPE {};
|
|
|
|
|
|
|
|
FIFO<CmdFIFOEntry, 64> CmdStallQueue {};
|
|
|
|
|
2024-08-01 20:46:05 +00:00
|
|
|
u32 ZeroDotWLimit = 0xFFFFFF;
|
2023-11-09 20:54:51 +00:00
|
|
|
|
|
|
|
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;
|
2017-05-09 20:22:52 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
s32 ProjMatrix[16] {};
|
|
|
|
s32 PosMatrix[16] {};
|
|
|
|
s32 VecMatrix[16] {};
|
|
|
|
s32 TexMatrix[16] {};
|
2017-02-11 02:54:08 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
s32 ClipMatrix[16] {};
|
|
|
|
bool ClipMatrixDirty = false;
|
2017-05-09 20:22:52 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 Viewport[6] {};
|
2017-04-12 18:25:54 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
s32 ProjMatrixStack[16] {};
|
|
|
|
s32 PosMatrixStack[32][16] {};
|
|
|
|
s32 VecMatrixStack[32][16] {};
|
|
|
|
s32 TexMatrixStack[16] {};
|
|
|
|
s32 ProjMatrixStackPointer = 0;
|
|
|
|
s32 PosMatrixStackPointer = 0;
|
|
|
|
s32 TexMatrixStackPointer = 0;
|
2020-11-30 15:58:52 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 NumCommands = 0;
|
|
|
|
u32 CurCommand = 0;
|
|
|
|
u32 ParamCount = 0;
|
|
|
|
u32 TotalParams = 0;
|
2020-12-10 18:12:08 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
bool GeometryEnabled = false;
|
|
|
|
bool RenderingEnabled = false;
|
2017-05-23 21:38:28 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 DispCnt = 0;
|
|
|
|
u8 AlphaRefVal = 0;
|
|
|
|
u8 AlphaRef = 0;
|
2021-08-04 12:21:45 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u16 ToonTable[32] {};
|
|
|
|
u16 EdgeTable[8] {};
|
2019-01-05 04:28:58 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 FogColor = 0;
|
|
|
|
u32 FogOffset = 0;
|
|
|
|
u8 FogDensityTable[32] {};
|
2017-02-07 21:23:46 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 ClearAttr1 = 0;
|
|
|
|
u32 ClearAttr2 = 0;
|
2023-12-08 22:42:08 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 RenderDispCnt = 0;
|
|
|
|
u8 RenderAlphaRef = 0;
|
2018-10-18 00:31:01 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u16 RenderToonTable[32] {};
|
|
|
|
u16 RenderEdgeTable[8] {};
|
2019-05-21 20:28:46 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 RenderFogColor = 0;
|
|
|
|
u32 RenderFogOffset = 0;
|
|
|
|
u32 RenderFogShift = 0;
|
|
|
|
u8 RenderFogDensityTable[34] {};
|
2017-02-17 18:34:41 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u32 RenderClearAttr1 = 0;
|
|
|
|
u32 RenderClearAttr2 = 0;
|
2017-02-07 23:52:37 +00:00
|
|
|
|
2024-01-07 22:39:43 +00:00
|
|
|
bool RenderFrameIdentical = false; // not part of the hardware state, don't serialize
|
2020-12-10 18:12:08 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
bool AbortFrame = false;
|
2021-01-26 15:42:27 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
u64 Timestamp = 0;
|
2017-02-10 14:24:46 +00:00
|
|
|
|
2017-04-23 13:25:15 +00:00
|
|
|
|
2023-11-09 20:54:51 +00:00
|
|
|
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;
|
2024-01-07 22:39:43 +00:00
|
|
|
u32 ScrolledLine[256]; // not part of the hardware state, don't serialize
|
2023-11-09 20:54:51 +00:00
|
|
|
};
|
2017-02-07 22:31:21 +00:00
|
|
|
|
2021-02-09 22:38:51 +00:00
|
|
|
class Renderer3D
|
2017-02-10 15:50:26 +00:00
|
|
|
{
|
2021-02-09 22:38:51 +00:00
|
|
|
public:
|
2023-09-15 13:31:05 +00:00
|
|
|
virtual ~Renderer3D() = default;
|
2017-02-10 15:50:26 +00:00
|
|
|
|
2021-02-09 22:38:51 +00:00
|
|
|
Renderer3D(const Renderer3D&) = delete;
|
|
|
|
Renderer3D& operator=(const Renderer3D&) = delete;
|
2017-02-10 15:50:26 +00:00
|
|
|
|
2023-12-15 13:53:31 +00:00
|
|
|
virtual void Reset(GPU& gpu) = 0;
|
2017-06-04 13:55:23 +00:00
|
|
|
|
2021-02-09 22:38:51 +00:00
|
|
|
// This "Accelerated" flag currently communicates if the framebuffer should
|
|
|
|
// be allocated differently and other little misc handlers. Ideally there
|
2023-11-03 23:21:46 +00:00
|
|
|
// are more detailed "traits" that we can ask of the Renderer3D type
|
2021-02-09 22:38:51 +00:00
|
|
|
const bool Accelerated;
|
2017-02-10 15:50:26 +00:00
|
|
|
|
2023-12-15 13:53:31 +00:00
|
|
|
virtual void VCount144(GPU& gpu) {};
|
|
|
|
virtual void Stop(const GPU& gpu) {}
|
|
|
|
virtual void RenderFrame(GPU& gpu) = 0;
|
|
|
|
virtual void RestartFrame(GPU& gpu) {};
|
2021-02-09 22:38:51 +00:00
|
|
|
virtual u32* GetLine(int line) = 0;
|
2023-12-15 13:53:31 +00:00
|
|
|
virtual void Blit(const GPU& gpu) {};
|
2024-05-13 15:17:39 +00:00
|
|
|
|
|
|
|
virtual void SetupAccelFrame() {}
|
2023-11-29 14:23:11 +00:00
|
|
|
virtual void PrepareCaptureFrame() {}
|
2024-05-13 15:17:39 +00:00
|
|
|
virtual void BindOutputTexture(int buffer) {}
|
|
|
|
|
|
|
|
virtual bool NeedsShaderCompile() { return false; }
|
|
|
|
virtual void ShaderCompileStep(int& current, int& count) {}
|
|
|
|
|
2023-09-15 13:31:05 +00:00
|
|
|
protected:
|
|
|
|
Renderer3D(bool Accelerated);
|
2021-02-09 22:38:51 +00:00
|
|
|
};
|
2019-05-12 14:32:53 +00:00
|
|
|
|
2019-04-01 00:51:31 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 21:23:46 +00:00
|
|
|
#endif
|