diff --git a/src/GBI.cpp b/src/GBI.cpp index af62bb4d..473aa042 100644 --- a/src/GBI.cpp +++ b/src/GBI.cpp @@ -392,6 +392,7 @@ void GBIInfo::loadMicrocode(u32 uc_start, u32 uc_dstart, u16 uc_dsize) type = F3D; } else if (strncmp(&uc_str[4], "Gfx", 3) == 0) { current.NoN = (strstr( uc_str + 4, ".NoN") != nullptr); + current.Rej = (strstr(uc_str + 4, ".Rej") != nullptr); if (strncmp( &uc_str[14], "F3D", 3 ) == 0) { if (uc_str[28] == '1' || strncmp(&uc_str[28], "0.95", 4) == 0 || strncmp(&uc_str[28], "0.96", 4) == 0) diff --git a/src/GBI.h b/src/GBI.h index b80e2caf..31d3d913 100644 --- a/src/GBI.h +++ b/src/GBI.h @@ -503,6 +503,7 @@ struct MicrocodeInfo u16 dataSize; u32 type; bool NoN = false; + bool Rej = false; bool cullBoth = true; bool negativeY = true; bool fast3DPersp = false; @@ -523,6 +524,7 @@ struct GBIInfo bool isHWLSupported() const; void setHWLSupported(bool _supported); bool isNoN() const { return m_pCurrent != nullptr ? m_pCurrent->NoN : false; } + bool isRej() const { return m_pCurrent != nullptr ? m_pCurrent->Rej : false; } bool isCullBoth() const { return m_pCurrent != nullptr ? m_pCurrent->cullBoth : false; } bool isNegativeY() const { return m_pCurrent != nullptr ? m_pCurrent->negativeY : true; } bool isTexturePersp() const { return m_pCurrent != nullptr ? m_pCurrent->texturePersp: true; } diff --git a/src/GraphicsDrawer.cpp b/src/GraphicsDrawer.cpp index 52d89782..90ae6108 100644 --- a/src/GraphicsDrawer.cpp +++ b/src/GraphicsDrawer.cpp @@ -1547,6 +1547,37 @@ void GraphicsDrawer::clearColorBuffer(float *_pColor) gfxContext.clearColorBuffer(0.0f, 0.0f, 0.0f, 0.0f); } +bool GraphicsDrawer::isRejected(s32 _v0, s32 _v1, s32 _v2) const +{ + if (!GBI.isRej()) + return false; + + static gDPScissor rejectBox; + if (gDP.changed & CHANGED_SCISSOR) { + const f32 scissorWidth2 = (gDP.scissor.lrx - gDP.scissor.ulx) * (gSP.clipRatio - 1) * 0.5f; + const f32 scissorHeight2 = (gDP.scissor.lry - gDP.scissor.uly) * (gSP.clipRatio - 1) * 0.5f; + rejectBox.ulx = gDP.scissor.ulx - scissorWidth2; + rejectBox.lrx = gDP.scissor.lrx + scissorWidth2; + rejectBox.uly = gDP.scissor.uly - scissorHeight2; + rejectBox.lry = gDP.scissor.lry + scissorHeight2; + } + s32 verts[3] = { _v0, _v1, _v2 }; + for (u32 i = 0; i < 3; ++i) { + const SPVertex & v = triangles.vertices[verts[i]]; + const f32 sx = gSP.viewport.vtrans[0] + (v.x / v.w) * gSP.viewport.vscale[0]; + if (sx < rejectBox.ulx) + return true; + if (sx > rejectBox.lrx) + return true; + const f32 sy = gSP.viewport.vtrans[1] + (v.y / v.w) * gSP.viewport.vscale[1]; + if (sy < rejectBox.uly) + return true; + if (sy > rejectBox.lry) + return true; + } + return false; +} + void GraphicsDrawer::copyTexturedRect(const CopyRectParams & _params) { m_drawingState = DrawingState::TexRect; diff --git a/src/GraphicsDrawer.h b/src/GraphicsDrawer.h index 5855fd28..e642b65b 100644 --- a/src/GraphicsDrawer.h +++ b/src/GraphicsDrawer.h @@ -132,6 +132,8 @@ public: return (triangles.vertices[_v0].clip & triangles.vertices[_v1].clip & triangles.vertices[_v2].clip) != 0; } + bool isRejected(s32 _v0, s32 _v1, s32 _v2) const; + SPVertex & getVertex(u32 _v) { return triangles.vertices[_v]; } SPVertex * getVertexPtr(u32 _v) { return triangles.vertices.data() + _v; } diff --git a/src/RSP.cpp b/src/RSP.cpp index 2b19fefb..a7882f52 100644 --- a/src/RSP.cpp +++ b/src/RSP.cpp @@ -221,6 +221,8 @@ void RSP_SetDefaultState() gSP.matrix.modelView[0][2][2] = 1.0f; gSP.matrix.modelView[0][3][3] = 1.0f; + gSP.clipRatio = 1U; + gDP.otherMode._u64 = 0U; gDP.otherMode.bi_lerp0 = gDP.otherMode.bi_lerp1 = 1; } diff --git a/src/gSP.cpp b/src/gSP.cpp index 7fd9a3f4..007d8dfd 100644 --- a/src/gSP.cpp +++ b/src/gSP.cpp @@ -74,6 +74,10 @@ void gSPTriangle(s32 v0, s32 v1, s32 v2) DebugMsg(DEBUG_NORMAL, "Triangle clipped (%i, %i, %i)\n", v0, v1, v2); return; } + if (drawer.isRejected(v0, v1, v2)) { + DebugMsg(DEBUG_NORMAL, "Triangle rejected (%i, %i, %i)\n", v0, v1, v2); + return; + } drawer.addTriangle(v0, v1, v2); DebugMsg(DEBUG_NORMAL, "Triangle #%i added (%i, %i, %i)\n", gSP.tri_num++, v0, v1, v2); } @@ -1575,9 +1579,10 @@ void gSPSegment( s32 seg, s32 base ) DebugMsg(DEBUG_NORMAL, "gSPSegment( %s, 0x%08X );\n", SegmentText[seg], base ); } -void gSPClipRatio( u32 r ) +void gSPClipRatio(u32 ratio) { - DebugMsg(DEBUG_NORMAL|DEBUG_IGNORED, "gSPClipRatio(%u);\n", r); + gSP.clipRatio = std::abs(static_cast(ratio & 0xFFFF)); + DebugMsg(DEBUG_NORMAL, "gSPClipRatio(%u);\n", gSP.clipRatio); } void gSPInsertMatrix( u32 where, u32 num ) diff --git a/src/gSP.h b/src/gSP.h index c4b5bbdb..f90596f9 100644 --- a/src/gSP.h +++ b/src/gSP.h @@ -132,6 +132,8 @@ struct gSPInfo u32 tri_num; + u32 clipRatio; + // CBFD u32 vertexNormalBase; f32 vertexCoordMod[16]; @@ -172,7 +174,7 @@ void gSPCullDisplayList( u32 v0, u32 vn ); void gSPPopMatrix( u32 param ); void gSPPopMatrixN( u32 param, u32 num ); void gSPSegment( s32 seg, s32 base ); -void gSPClipRatio( u32 r ); +void gSPClipRatio( u32 ratio ); void gSPInsertMatrix( u32 where, u32 num ); void gSPModifyVertex(u32 _vtx, u32 _where, u32 _val ); void gSPNumLights( s32 n );