From 64a23c22cc4c1f07d10f4b9f4f0cdd018f354c34 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 2 Dec 2022 00:19:15 -0500 Subject: [PATCH] DolphinCGraphics inches closer --- asm/Kyoto/Graphics/DolphinCGraphics.s | 8 - include/Kyoto/Graphics/CGraphics.hpp | 28 ++- include/dolphin/os/OSCache.h | 1 + src/Kyoto/Graphics/DolphinCGraphics.cpp | 286 +++++++++++++++++++++++- 4 files changed, 299 insertions(+), 24 deletions(-) diff --git a/asm/Kyoto/Graphics/DolphinCGraphics.s b/asm/Kyoto/Graphics/DolphinCGraphics.s index c4e696c4..9dd0480d 100644 --- a/asm/Kyoto/Graphics/DolphinCGraphics.s +++ b/asm/Kyoto/Graphics/DolphinCGraphics.s @@ -1626,7 +1626,6 @@ FullRender__9CGraphicsFv: /* 8030A4C0 00307420 7C 03 00 2E */ lwzx r0, r3, r0 /* 8030A4C4 00307424 7C 09 03 A6 */ mtctr r0 /* 8030A4C8 00307428 4E 80 04 20 */ bctr -.global lbl_8030A4CC lbl_8030A4CC: /* 8030A4CC 0030742C 80 CD A7 FC */ lwz r6, mNumPrimitives__9CGraphics@sda21(r13) /* 8030A4D0 00307430 38 E0 00 00 */ li r7, 0 @@ -1713,7 +1712,6 @@ lbl_8030A5F0: /* 8030A608 00307568 D0 23 80 00 */ stfs f1, 0xCC008000@l(r3) /* 8030A60C 0030756C 42 00 FF E4 */ bdnz lbl_8030A5F0 /* 8030A610 00307570 48 00 08 AC */ b lbl_8030AEBC -.global lbl_8030A614 lbl_8030A614: /* 8030A614 00307574 80 0D A7 FC */ lwz r0, mNumPrimitives__9CGraphics@sda21(r13) /* 8030A618 00307578 3C 80 CC 01 */ lis r4, 0xcc01 @@ -1798,7 +1796,6 @@ lbl_8030A714: /* 8030A748 003076A8 D0 44 80 00 */ stfs f2, 0xCC008000@l(r4) /* 8030A74C 003076AC 42 00 FF C8 */ bdnz lbl_8030A714 /* 8030A750 003076B0 48 00 07 6C */ b lbl_8030AEBC -.global lbl_8030A754 lbl_8030A754: /* 8030A754 003076B4 80 ED A7 FC */ lwz r7, mNumPrimitives__9CGraphics@sda21(r13) /* 8030A758 003076B8 39 00 00 00 */ li r8, 0 @@ -1909,7 +1906,6 @@ lbl_8030A8CC: /* 8030A8F0 00307850 90 03 80 00 */ stw r0, 0xCC008000@l(r3) /* 8030A8F4 00307854 42 00 FF D8 */ bdnz lbl_8030A8CC /* 8030A8F8 00307858 48 00 05 C4 */ b lbl_8030AEBC -.global lbl_8030A8FC lbl_8030A8FC: /* 8030A8FC 0030785C 80 0D A7 FC */ lwz r0, mNumPrimitives__9CGraphics@sda21(r13) /* 8030A900 00307860 3C 80 CC 01 */ lis r4, 0xcc01 @@ -1984,7 +1980,6 @@ lbl_8030A9DC: /* 8030AA08 00307968 D0 24 80 00 */ stfs f1, 0xCC008000@l(r4) /* 8030AA0C 0030796C 42 00 FF D0 */ bdnz lbl_8030A9DC /* 8030AA10 00307970 48 00 04 AC */ b lbl_8030AEBC -.global lbl_8030AA14 lbl_8030AA14: /* 8030AA14 00307974 80 0D A7 FC */ lwz r0, mNumPrimitives__9CGraphics@sda21(r13) /* 8030AA18 00307978 3C 80 CC 01 */ lis r4, 0xcc01 @@ -2060,7 +2055,6 @@ lbl_8030AADC: /* 8030AB24 00307A84 D0 24 80 00 */ stfs f1, 0xCC008000@l(r4) /* 8030AB28 00307A88 42 00 FF B4 */ bdnz lbl_8030AADC /* 8030AB2C 00307A8C 48 00 03 90 */ b lbl_8030AEBC -.global lbl_8030AB30 lbl_8030AB30: /* 8030AB30 00307A90 80 0D A7 FC */ lwz r0, mNumPrimitives__9CGraphics@sda21(r13) /* 8030AB34 00307A94 3C 80 CC 01 */ lis r4, 0xcc01 @@ -2130,7 +2124,6 @@ lbl_8030ABE8: /* 8030AC28 00307B88 90 04 80 00 */ stw r0, 0xCC008000@l(r4) /* 8030AC2C 00307B8C 42 00 FF BC */ bdnz lbl_8030ABE8 /* 8030AC30 00307B90 48 00 02 8C */ b lbl_8030AEBC -.global lbl_8030AC34 lbl_8030AC34: /* 8030AC34 00307B94 80 0D A7 FC */ lwz r0, mNumPrimitives__9CGraphics@sda21(r13) /* 8030AC38 00307B98 3C 80 CC 01 */ lis r4, 0xcc01 @@ -2218,7 +2211,6 @@ lbl_8030AD3C: /* 8030AD74 00307CD4 D0 24 80 00 */ stfs f1, 0xCC008000@l(r4) /* 8030AD78 00307CD8 42 00 FF C4 */ bdnz lbl_8030AD3C /* 8030AD7C 00307CDC 48 00 01 40 */ b lbl_8030AEBC -.global lbl_8030AD80 lbl_8030AD80: /* 8030AD80 00307CE0 80 0D A7 FC */ lwz r0, mNumPrimitives__9CGraphics@sda21(r13) /* 8030AD84 00307CE4 3C 80 CC 01 */ lis r4, 0xcc01 diff --git a/include/Kyoto/Graphics/CGraphics.hpp b/include/Kyoto/Graphics/CGraphics.hpp index a3ab5d09..4e8485bb 100644 --- a/include/Kyoto/Graphics/CGraphics.hpp +++ b/include/Kyoto/Graphics/CGraphics.hpp @@ -149,6 +149,15 @@ enum ERglLight { kLightMax, }; +enum ERglTexOffset { + kTO_Zero = GX_TO_ZERO, + kTO_Sixteenth = GX_TO_SIXTEENTH, + kTO_Eighth = GX_TO_EIGHTH, + kTO_Fourth = GX_TO_FOURTH, + kTO_Half = GX_TO_HALF, + kTO_One = GX_TO_ONE, +}; + struct CViewport { int mLeft; int mTop; @@ -222,6 +231,7 @@ public: static void SetLightState(uchar lights); static void SetViewMatrix(); static void SetScissor(int left, int bottom, int width, int height); + static void SetLineWidth(float w, ERglTexOffset offs); static void ClearBackAndDepthBuffers(); static void SetIdentityViewPointMatrix(); @@ -247,13 +257,14 @@ public: static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass); static void StreamBegin(ERglPrimitive primitive); static void StreamColor(uint color); - static void StreamColor(float, float, float, float); + static void StreamColor(float r, float g, float b, float a); static void StreamColor(const CColor& color); static void StreamTexcoord(float u, float v); - static void StreamVertex(float, float, float); + static void StreamTexcoord(const CVector2f& uv); + static void StreamVertex(float x, float y, float z); static void StreamVertex(const CVector3f& vtx); - static void StreamVertex(const float*); - static void StreamNormal(const float*); + static void StreamVertex(const float* vtx); + static void StreamNormal(const float* nrm); static void StreamEnd(); static void Render2D(const CTexture& tex, int x, int y, int w, int h, const CColor& col); static void DrawPrimitive(ERglPrimitive primitive, const float* pos, const CVector3f& normal, const CColor& col, int numVerts); @@ -301,12 +312,17 @@ public: static CTevCombiners::CTevPass kEnvModulateColorByAlpha; private: + static void UpdateVertexDataStream(); + static void ResetVertexDataStream(bool initial); + static void FlushStream(); + static void FullRender(); + static CRenderState sRenderState; static VecPtr vtxBuffer; static VecPtr nrmBuffer; static Vec2Ptr txtBuffer0; static Vec2Ptr txtBuffer1; - static GXColor* clrBuffer; + static uint* clrBuffer; static bool mJustReset; static ERglCullMode mCullMode; static int mNumLightsActive; @@ -315,7 +331,7 @@ private: static VecPtr mpNrmBuffer; static Vec2Ptr mpTxtBuffer0; static Vec2Ptr mpTxtBuffer1; - static GXColor* mpClrBuffer; + static uint* mpClrBuffer; static int mNumPrimitives; static int mFrameCounter; static float mFramesPerSecond; diff --git a/include/dolphin/os/OSCache.h b/include/dolphin/os/OSCache.h index 20709d2f..b3dd94a2 100644 --- a/include/dolphin/os/OSCache.h +++ b/include/dolphin/os/OSCache.h @@ -18,6 +18,7 @@ void ICInvalidateRange(void* addr, u32 nBytes); #define LC_BASE_PREFIX 0xE000 #define LC_BASE (LC_BASE_PREFIX << 16) +#define LCGetBase() ((void*)LC_BASE) void LCEnable(); void LCDisable(void); diff --git a/src/Kyoto/Graphics/DolphinCGraphics.cpp b/src/Kyoto/Graphics/DolphinCGraphics.cpp index a2f29837..fcc458c2 100644 --- a/src/Kyoto/Graphics/DolphinCGraphics.cpp +++ b/src/Kyoto/Graphics/DolphinCGraphics.cpp @@ -10,6 +10,8 @@ #include "dolphin/vi.h" +#include + bool CGraphicsSys::mGraphicsInitialized; static CStopwatch sFPSTimer; static uchar sSpareFrameBuffer[640 * 448]; @@ -162,7 +164,7 @@ VecPtr CGraphics::vtxBuffer; VecPtr CGraphics::nrmBuffer; Vec2Ptr CGraphics::txtBuffer0; Vec2Ptr CGraphics::txtBuffer1; -GXColor* CGraphics::clrBuffer; +uint* CGraphics::clrBuffer; bool CGraphics::mJustReset; ERglCullMode CGraphics::mCullMode; int CGraphics::mNumLightsActive; @@ -171,7 +173,7 @@ VecPtr CGraphics::mpVtxBuffer; VecPtr CGraphics::mpNrmBuffer; Vec2Ptr CGraphics::mpTxtBuffer0; Vec2Ptr CGraphics::mpTxtBuffer1; -GXColor* CGraphics::mpClrBuffer; +uint* CGraphics::mpClrBuffer; struct CGXLightParams { int x0_; @@ -187,11 +189,10 @@ CGXLightParams mLightParams[8]; struct { Vec vtx; Vec nrm; - float uvU, uvV; - int unk0; - int unk1; - GXColor color; - short textureUsed; + Vec2 uv0; + Vec2 uv1; + uint color; + ushort textureUsed; uchar streamFlags; } vtxDescr; @@ -354,7 +355,7 @@ void CGraphics::ConfigureFrameBuffer(const COsContext& osContext) { GXSetDispCopyDst(mRenderModeObj.fbWidth, mRenderModeObj.efbHeight); GXSetDispCopyYScale(static_cast< float >(mRenderModeObj.xfbHeight) / static_cast< float >(mRenderModeObj.efbHeight)); - GXSetCopyFilter(mRenderModeObj.aa, mRenderModeObj.sample_pattern, GX_TRUE, + GXSetCopyFilter(mRenderModeObj.aa, mRenderModeObj.sample_pattern, GX_ENABLE, mRenderModeObj.vfilter); if (mRenderModeObj.aa) { GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); @@ -487,7 +488,7 @@ void CGraphics::SetLightState(uchar lights) { if (lights != 0) { diffFn = GX_DF_CLAMP; } - CGX::SetChanCtrl(CGX::Channel0, lights != 0 ? GX_TRUE : GX_FALSE, GX_SRC_REG, + CGX::SetChanCtrl(CGX::Channel0, lights != 0 ? GX_ENABLE : GX_DISABLE, GX_SRC_REG, (vtxDescr.streamFlags & 2) != 0 ? GX_SRC_VTX : GX_SRC_REG, static_cast< GXLightID >(lights), diffFn, attnFn); mLightActive = lights; @@ -754,7 +755,7 @@ void CGraphics::EndScene() { GXSetCopyFilter(mRenderModeObj.aa, mRenderModeObj.sample_pattern, true, vfilter); GXCopyDisp(frameBuf, mIsBeginSceneClearFb ? GX_TRUE : GX_FALSE); GXSetCopyFilter(mRenderModeObj.aa, mRenderModeObj.sample_pattern, - mUseVideoFilter ? GX_TRUE : GX_FALSE, mRenderModeObj.vfilter); + mUseVideoFilter ? GX_ENABLE : GX_DISABLE, mRenderModeObj.vfilter); GXSetBreakPtCallback(SwapBuffers); VISetPreRetraceCallback(VideoPreCallback); VISetPostRetraceCallback(VideoPostCallback); @@ -864,3 +865,268 @@ void CGraphics::DrawPrimitive(ERglPrimitive primitive, const float* pos, const C } StreamEnd(); } + +#define STREAM_PRIM_BUFFER_SIZE 240 + +#define VTX_BUFFER_ADDR LC_BASE +#if NONMATCHING +// Bug fix: these should be 3 times larger to avoid overflow +// Likely the result of bad pointer arithmetic +#define NRM_BUFFER_ADDR (VTX_BUFFER_ADDR + ((STREAM_PRIM_BUFFER_SIZE + 1) * sizeof(Vec))) +#define TXT0_BUFFER_ADDR (NRM_BUFFER_ADDR + ((STREAM_PRIM_BUFFER_SIZE + 1) * sizeof(Vec))) +#else +#define NRM_BUFFER_ADDR (VTX_BUFFER_ADDR + ((STREAM_PRIM_BUFFER_SIZE + 1) * sizeof(float))) +#define TXT0_BUFFER_ADDR (NRM_BUFFER_ADDR + ((STREAM_PRIM_BUFFER_SIZE + 1) * sizeof(float))) +#endif +#define TXT1_BUFFER_ADDR (TXT0_BUFFER_ADDR + ((STREAM_PRIM_BUFFER_SIZE + 1) * sizeof(Vec2))) +#define CLR_BUFFER_ADDR (TXT1_BUFFER_ADDR + ((STREAM_PRIM_BUFFER_SIZE + 1) * sizeof(Vec2))) + +static const uchar kHasNormals = 1; +static const uchar kHasColor = 2; +static const uchar kHasTexture = 4; + +void CGraphics::StreamBegin(ERglPrimitive primitive) { + vtxBuffer = reinterpret_cast< VecPtr >(VTX_BUFFER_ADDR); + nrmBuffer = reinterpret_cast< VecPtr >(NRM_BUFFER_ADDR); + txtBuffer0 = reinterpret_cast< Vec2Ptr >(TXT0_BUFFER_ADDR); + txtBuffer1 = reinterpret_cast< Vec2Ptr >(TXT1_BUFFER_ADDR); + clrBuffer = reinterpret_cast< uint* >(CLR_BUFFER_ADDR); + ResetVertexDataStream(true); + mCurrentPrimitive = primitive; + vtxDescr.streamFlags = kHasColor; +} + +void CGraphics::StreamVertex(float x, float y, float z) { + vtxDescr.vtx.x = x; + vtxDescr.vtx.y = y; + vtxDescr.vtx.z = z; + UpdateVertexDataStream(); +} + +void CGraphics::StreamVertex(const float* vtx) { + vtxDescr.vtx.x = vtx[0]; + vtxDescr.vtx.y = vtx[1]; + vtxDescr.vtx.z = vtx[2]; + UpdateVertexDataStream(); +} + +void CGraphics::StreamVertex(const CVector3f& vtx) { + vtxDescr.vtx.x = vtx.GetX(); + vtxDescr.vtx.y = vtx.GetY(); + vtxDescr.vtx.z = vtx.GetZ(); + UpdateVertexDataStream(); +} + +void CGraphics::StreamNormal(const float* nrm) { + vtxDescr.nrm.x = nrm[0]; + vtxDescr.nrm.y = nrm[1]; + vtxDescr.nrm.z = nrm[2]; + vtxDescr.streamFlags |= kHasNormals; +} + +void CGraphics::StreamColor(uint color) { + vtxDescr.color = color; + vtxDescr.streamFlags |= kHasColor; +} + +void CGraphics::StreamColor(const CColor& color) { + vtxDescr.color = color.GetColor_u32(); + vtxDescr.streamFlags |= kHasColor; +} + +void CGraphics::StreamColor(float r, float g, float b, float a) { + // clang-format off + vtxDescr.color = (static_cast< uchar >(r * 255.f) << 24) | + (static_cast< uchar >(g * 255.f) << 16) | + (static_cast< uchar >(b * 255.f) << 8) | + static_cast< uchar >(a * 255.f); + // clang-format on + vtxDescr.streamFlags |= kHasColor; +} + +void CGraphics::StreamTexcoord(const CVector2f& uv) { + vtxDescr.uv0.x = uv.GetX(); + vtxDescr.uv0.y = uv.GetY(); + vtxDescr.streamFlags |= kHasTexture; + vtxDescr.textureUsed |= 1; +} + +void CGraphics::StreamTexcoord(float u, float v) { + vtxDescr.uv0.x = u; + vtxDescr.uv0.y = v; + vtxDescr.streamFlags |= kHasTexture; + vtxDescr.textureUsed |= 1; +} + +void CGraphics::StreamEnd() { + if (mNumPrimitives != 0) { + FlushStream(); + } + vtxBuffer = nullptr; + vtxDescr.streamFlags = 0; + vtxDescr.textureUsed = 0; + nrmBuffer = nullptr; + txtBuffer0 = nullptr; + txtBuffer1 = nullptr; + clrBuffer = nullptr; +} + +void CGraphics::SetLineWidth(float w, ERglTexOffset offs) { + CGX::SetLineWidth(static_cast< uchar >(w * 6.f), static_cast< GXTexOffset >(offs)); +} + +void CGraphics::UpdateVertexDataStream() { + ++mNumPrimitives; + mpVtxBuffer->x = vtxDescr.vtx.x; + mpVtxBuffer->y = vtxDescr.vtx.y; + mpVtxBuffer->z = vtxDescr.vtx.z; + ++mpVtxBuffer; + if ((vtxDescr.streamFlags & kHasNormals) != 0) { + mpNrmBuffer->x = vtxDescr.nrm.x; + mpNrmBuffer->y = vtxDescr.nrm.y; + mpNrmBuffer->z = vtxDescr.nrm.z; + ++mpNrmBuffer; + } + if ((vtxDescr.streamFlags & kHasTexture) != 0) { + mpTxtBuffer0->x = vtxDescr.uv0.x; + mpTxtBuffer0->y = vtxDescr.uv0.y; + ++mpTxtBuffer0; + + mpTxtBuffer1->x = vtxDescr.uv1.x; + mpTxtBuffer1->y = vtxDescr.uv1.y; + ++mpTxtBuffer1; + } + if ((vtxDescr.streamFlags & kHasColor) != 0) { + *mpClrBuffer = vtxDescr.color; + ++mpClrBuffer; + } + mJustReset = 0; + if (mNumPrimitives == STREAM_PRIM_BUFFER_SIZE) { + FlushStream(); + ResetVertexDataStream(false); + } +} + +void CGraphics::ResetVertexDataStream(bool initial) { + mpVtxBuffer = vtxBuffer; + mpNrmBuffer = nrmBuffer; + mpTxtBuffer0 = txtBuffer0; + mpTxtBuffer1 = txtBuffer1; + mpClrBuffer = clrBuffer; + mNumPrimitives = 0; + + if (initial) { + return; + } + + switch (mCurrentPrimitive) { + case kP_TriangleFan: + mpVtxBuffer = vtxBuffer + 1; + memcpy(mpVtxBuffer, &vtxDescr.vtx, sizeof(Vec)); + ++mpVtxBuffer; + + if ((vtxDescr.streamFlags & kHasNormals) != 0) { + ++mpNrmBuffer; + memcpy(mpNrmBuffer, &vtxDescr.nrm, sizeof(Vec)); + ++mpNrmBuffer; + } + + if ((vtxDescr.streamFlags & kHasTexture) != 0) { + ++mpTxtBuffer0; + memcpy(mpTxtBuffer0, &vtxDescr.uv0, sizeof(Vec2)); + ++mpTxtBuffer0; + + ++mpTxtBuffer1; + memcpy(mpTxtBuffer1, &vtxDescr.uv1, sizeof(Vec2)); + ++mpTxtBuffer1; + } + + if ((vtxDescr.streamFlags & kHasColor) != 0) { + ++mpClrBuffer; + *mpClrBuffer = vtxDescr.color; + ++mpClrBuffer; + } + + mNumPrimitives += 2; + break; + + default: + break; + } + + mJustReset = 1; +} + +void CGraphics::FlushStream() { + GXVtxDescList vtxDesc[10]; + + GXVtxDescList* curDesc = vtxDesc; + const GXVtxDescList vtxDescPos = {GX_VA_POS, GX_DIRECT}; + *curDesc++ = vtxDescPos; + + if ((vtxDescr.streamFlags & kHasNormals) != 0) { + const GXVtxDescList vtxDescNrm = {GX_VA_CLR0, GX_DIRECT}; + *curDesc++ = vtxDescNrm; + } + + if ((vtxDescr.streamFlags & kHasColor) != 0) { + const GXVtxDescList vtxDescClr0 = {GX_VA_CLR0, GX_DIRECT}; + *curDesc++ = vtxDescClr0; + } + + if ((vtxDescr.streamFlags & kHasTexture) != 0) { + const GXVtxDescList vtxDescTex0 = {GX_VA_TEX0, GX_DIRECT}; + *curDesc++ = vtxDescTex0; + } + + const GXVtxDescList vtxDescNull = {GX_VA_NULL, GX_NONE}; + *curDesc = vtxDescNull; + + CGX::SetVtxDescv(vtxDesc); + SetTevStates(vtxDescr.streamFlags); + FullRender(); +} + +void CGraphics::SetTevStates(uchar flags) { + switch (flags) { + case 0: + case kHasNormals: + case kHasColor: + case kHasNormals | kHasColor: + CGX::SetNumChans(1); + CGX::SetNumTexGens(0); + CGX::SetNumTevStages(1); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + break; + case kHasTexture: + case kHasNormals | kHasTexture: + case kHasColor | kHasTexture: + case kHasNormals | kHasColor | kHasTexture: + CGX::SetNumChans(1); + if ((vtxDescr.textureUsed & 3) != 0) { + CGX::SetNumTexGens(2); + } else { + CGX::SetNumTexGens(1); + } + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); + break; + } + CGX::SetNumIndStages(0); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, false, GX_PTIDENTITY); + + uint light = mLightActive; + GXAttnFn attnFn = GX_AF_NONE; + if (light != 0) { + attnFn = GX_AF_SPOT; + } + GXDiffuseFn diffFn = GX_DF_NONE; + if (light != 0) { + diffFn = GX_DF_CLAMP; + } + CGX::SetChanCtrl(CGX::Channel0, light ? GX_ENABLE : GX_DISABLE, GX_SRC_REG, + (flags & kHasColor) ? GX_SRC_VTX : GX_SRC_REG, static_cast< GXLightID >(light), + diffFn, attnFn); +}