diff --git a/include/Kyoto/Graphics/CGraphics.hpp b/include/Kyoto/Graphics/CGraphics.hpp index 61704e25..2472b916 100644 --- a/include/Kyoto/Graphics/CGraphics.hpp +++ b/include/Kyoto/Graphics/CGraphics.hpp @@ -184,12 +184,18 @@ public: public: CRenderState(); + void Flush(); void ResetFlushAll(); + void SetVtxState(const float*, const float*, const unsigned int*); + + // In map this takes two args, but x4 is unused? + void Set(int v0) { x0_ = v0; } private: int x0_; int x4_; }; + class CProjectionState { public: CProjectionState(bool persp, float left, float right, float top, float bottom, float near, @@ -245,7 +251,15 @@ public: static void SetDefaultVtxAttrFmt(); static CMatrix4f GetPerspectiveProjectionMatrix(); static CMatrix4f CalculatePerspectiveMatrix(float fovy, float aspect, float znear, float zfar); - + static void ResetGfxStates(); + static void LoadDolphinSpareTexture(int width, int height, GXTexFmt fmt, void* data, + GXTexMapID texId); + static void LoadDolphinSpareTexture(int width, int height, GXCITexFmt fmt, GXTlut tlut, + void* data, GXTexMapID texId); + static void TickRenderTimings(); + static const CProjectionState& GetProjectionState(); + static void SetProjectionState(const CProjectionState& proj); + static float GetDepthNear() { return mDepthNear; } static float GetDepthFar() { return mDepthFar; } @@ -267,7 +281,8 @@ public: 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); + static void DrawPrimitive(ERglPrimitive primitive, const float* pos, const CVector3f& normal, + const CColor& col, int numVerts); static void VideoPreCallback(u32 retraceCount); static void VideoPostCallback(u32 retraceCount); @@ -351,7 +366,7 @@ private: static GXTexRegionCallback mGXDefaultTexRegionCallback; static void* mpFifo; static GXFifoObj* mpFifoObj; - static int mRenderTimings; + static uint mRenderTimings; static float mSecondsMod900; static CTimeProvider* mpExternalTimeProvider; // lbl_805A9408 diff --git a/include/dolphin/gx/GXTexture.h b/include/dolphin/gx/GXTexture.h index d2b50022..44a38616 100644 --- a/include/dolphin/gx/GXTexture.h +++ b/include/dolphin/gx/GXTexture.h @@ -28,6 +28,7 @@ void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 ss, u16 t void GXInitTexCacheRegion(GXTexRegion* region, GXBool is_32b_mipmap, u32 tmem_even, GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd); GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback callback); +void GXInvalidateTexRegion(const GXTexRegion* region); #ifdef __cplusplus } diff --git a/src/Kyoto/Graphics/DolphinCGraphics.cpp b/src/Kyoto/Graphics/DolphinCGraphics.cpp index 09670e5c..9d8060b0 100644 --- a/src/Kyoto/Graphics/DolphinCGraphics.cpp +++ b/src/Kyoto/Graphics/DolphinCGraphics.cpp @@ -231,7 +231,7 @@ int CGraphics::mSpareBufferTexCacheSize; GXTexRegionCallback CGraphics::mGXDefaultTexRegionCallback; void* CGraphics::mpFifo; GXFifoObj* CGraphics::mpFifoObj; -int CGraphics::mRenderTimings; +uint CGraphics::mRenderTimings; float CGraphics::mSecondsMod900; CTimeProvider* CGraphics::mpExternalTimeProvider; int lbl_805A9408; @@ -1130,3 +1130,226 @@ void CGraphics::SetTevStates(uchar flags) { (flags & kHasColor) ? GX_SRC_VTX : GX_SRC_REG, static_cast< GXLightID >(light), diffFn, attnFn); } + +void CGraphics::FullRender() { + CGX::Begin(static_cast< GXPrimitive >(mCurrentPrimitive), GX_VTXFMT0, mNumPrimitives); + switch (vtxDescr.streamFlags) { + case 0: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + } + break; + case kHasNormals: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + const Vec& nrm = nrmBuffer[i]; + GXNormal3f32(nrm.x, nrm.y, nrm.z); + } + break; + case kHasColor: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + GXColor1u32(clrBuffer[i]); + } + break; + case kHasTexture: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + const Vec2& uv = txtBuffer0[i]; + GXTexCoord2f32(uv.x, uv.y); + } + break; + case kHasNormals | kHasTexture: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + const Vec& nrm = nrmBuffer[i]; + GXNormal3f32(nrm.x, nrm.y, nrm.z); + const Vec2& uv = txtBuffer0[i]; + GXTexCoord2f32(uv.x, uv.y); + } + break; + case kHasNormals | kHasColor: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + const Vec& nrm = nrmBuffer[i]; + GXNormal3f32(nrm.x, nrm.y, nrm.z); + GXColor1u32(clrBuffer[i]); + } + break; + case kHasColor | kHasTexture: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + GXColor1u32(clrBuffer[i]); + const Vec2& uv = txtBuffer0[i]; + GXTexCoord2f32(uv.x, uv.y); + } + break; + case kHasNormals | kHasColor | kHasTexture: + for (int i = 0; i < mNumPrimitives; i++) { + const Vec& vtx = vtxBuffer[i]; + GXPosition3f32(vtx.x, vtx.y, vtx.z); + const Vec& nrm = nrmBuffer[i]; + GXNormal3f32(nrm.x, nrm.y, nrm.z); + GXColor1u32(clrBuffer[i]); + const Vec2& uv = txtBuffer0[i]; + GXTexCoord2f32(uv.x, uv.y); + } + break; + } + CGX::End(); +} + +void CGraphics::SetDepthRange(float near, float far) { + mDepthNear = near; + mDepthFar = far; + GXSetViewport(static_cast< float >(mViewport.mLeft), static_cast< float >(mViewport.mTop), + static_cast< float >(mViewport.mWidth), static_cast< float >(mViewport.mHeight), + mDepthNear, mDepthFar); +} + +static inline GXTevStageID get_texture_unit(ERglTevStage stage) { +#if NONMATCHING + // one instruction, no branches + return static_cast< GXTevStageID >(stage & (GX_MAX_TEVSTAGE - 1)); +#else + if (stage == kTS_Stage0) { + return GX_TEVSTAGE0; + } else if (stage == kTS_Stage1) { + return GX_TEVSTAGE1; + } else if (stage == kTS_Stage2) { + return GX_TEVSTAGE2; + } else if (stage == kTS_Stage3) { + return GX_TEVSTAGE3; + } else if (stage == kTS_Stage4) { + return GX_TEVSTAGE4; + } else if (stage == kTS_Stage5) { + return GX_TEVSTAGE5; + } else if (stage == kTS_Stage6) { + return GX_TEVSTAGE6; + } else if (stage == kTS_Stage7) { + return GX_TEVSTAGE7; + } else if (stage == kTS_Stage8) { + return GX_TEVSTAGE8; + } else if (stage == kTS_Stage9) { + return GX_TEVSTAGE9; + } else if (stage == kTS_Stage10) { + return GX_TEVSTAGE10; + } else if (stage == kTS_Stage11) { + return GX_TEVSTAGE11; + } else if (stage == kTS_Stage12) { + return GX_TEVSTAGE12; + } else if (stage == kTS_Stage13) { + return GX_TEVSTAGE13; + } else if (stage == kTS_Stage14) { + return GX_TEVSTAGE14; + } + // wtf? + return static_cast< GXTevStageID >(stage == kTS_Stage15 ? GX_TEVSTAGE15 : 0); +#endif +} + +void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass) { + CTevCombiners::SetupPass(get_texture_unit(stage), pass); +} + +void CGraphics::SetFog(ERglFogMode mode, float startz, float endz, const CColor& color) { + CGX::SetFog(static_cast< GXFogType >(mode), startz, endz, mProj.GetNear(), mProj.GetFar(), + color.GetGXColor()); +} + +void CGraphics::ResetGfxStates() { sRenderState.Set(0); } + +void CGraphics::SetDefaultVtxAttrFmt() { + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_U16, 15); + for (int i = 1; i <= 7; ++i) { + GXAttr attr = static_cast< GXAttr >(GX_VA_TEX0 + i); + GXSetVtxAttrFmt(GX_VTXFMT0, attr, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, attr, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, attr, GX_TEX_ST, GX_F32, 0); + } +} + +void CGraphics::LoadDolphinSpareTexture(int width, int height, GXTexFmt fmt, void* data, + GXTexMapID texId) { + GXTexObj texObj; + GXInitTexObj(&texObj, data != nullptr ? data : mpSpareBuffer, width, height, fmt, GX_CLAMP, + GX_CLAMP, GX_DISABLE); + GXInitTexObjLOD(&texObj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, GX_DISABLE, GX_DISABLE, GX_ANISO_1); + GXLoadTexObj(&texObj, texId); + CTexture::InvalidateTexmap(texId); + if (texId == GX_TEXMAP7) { + GXInvalidateTexRegion(&mTexRegions[0]); + } +} + +void CGraphics::LoadDolphinSpareTexture(int width, int height, GXCITexFmt fmt, GXTlut tlut, + void* data, GXTexMapID texId) { + GXTexObj texObj; + GXInitTexObjCI(&texObj, data != nullptr ? data : mpSpareBuffer, width, height, fmt, GX_CLAMP, + GX_CLAMP, GX_DISABLE, tlut); + GXInitTexObjLOD(&texObj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, GX_DISABLE, GX_DISABLE, GX_ANISO_1); + GXLoadTexObj(&texObj, texId); + CTexture::InvalidateTexmap(texId); + if (texId == GX_TEXMAP7) { + GXInvalidateTexRegion(&mTexRegions[0]); + } +} + +void CGraphics::TickRenderTimings() { + mRenderTimings = (mRenderTimings + 1) % (900 * 60); + mSecondsMod900 = static_cast< float >(mRenderTimings) / 60.f; +} + +float CGraphics::GetSecondsMod900() { + if (mpExternalTimeProvider != nullptr) { + return mpExternalTimeProvider->GetSecondsMod900(); + } + return mSecondsMod900; +} + +void CGraphics::SetExternalTimeProvider(CTimeProvider* timeProvider) { + mpExternalTimeProvider = timeProvider; +} + +void CGraphics::FlushProjection() { + float right = mProj.GetRight(); + float left = mProj.GetLeft(); + float top = mProj.GetTop(); + float bottom = mProj.GetBottom(); + float near = mProj.GetNear(); + float far = mProj.GetFar(); + if (mProj.IsPerspective()) { + Mtx44 mtx; + MTXFrustum(mtx, top, bottom, left, right, near, far); + GXSetProjection(mtx, GX_PERSPECTIVE); + } else { + Mtx44 mtx; + MTXOrtho(mtx, top, bottom, left, right, near, far); + GXSetProjection(mtx, GX_ORTHOGRAPHIC); + } +} + +const CGraphics::CProjectionState& CGraphics::GetProjectionState() { return mProj; } + +void CGraphics::SetProjectionState(const CProjectionState& proj) { + mProj = proj; + FlushProjection(); +}