From e4f5f0bcaf39defa256190f285b33882d8446780 Mon Sep 17 00:00:00 2001 From: Ian Curtis Date: Sun, 2 Sep 2018 21:36:24 +0000 Subject: [PATCH] Sega bass fishing is starting some off the meshes with a shared vertex. Without having a previous vertex to share with, the values were just uninitialised and junk. The hardware itself seems to hold the value from the previous mesh, and sega bass fishing relies on this undefined behaviour to function correctly. Storing the cached vertices as member variables instead of locally to the function means it holds the values from the last mesh, and uses those values instead of random garbage. --- Src/Graphics/New3D/New3D.cpp | 41 ++++++++++++++++++------------------ Src/Graphics/New3D/New3D.h | 3 +++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index 3dd339b..bde3bdc 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -23,12 +23,12 @@ CNew3D::CNew3D(const Util::Config::Node &config, std::string gameName) m_cullingRAMHi = nullptr; m_polyRAM = nullptr; m_vrom = nullptr; - m_textureRAM = nullptr; - m_sunClamp = true; - m_shadeIsSigned = true; -} - -CNew3D::~CNew3D() + m_textureRAM = nullptr; + m_sunClamp = true; + m_shadeIsSigned = true; +} + +CNew3D::~CNew3D() { m_vbo.Destroy(); } @@ -1026,9 +1026,7 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph) void CNew3D::CacheModel(Model *m, const UINT32 *data) { - Vertex prev[4]; UINT16 texCoords[4][2]; - UINT16 prevTexCoords[4][2]; PolyHeader ph; UINT64 lastHash = -1; SortingMesh* currentMesh = nullptr; @@ -1086,10 +1084,10 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data) { if (ph.SharedVertex(i)) { - p.v[j] = prev[i]; + p.v[j] = m_prev[i]; - texCoords[j][0] = prevTexCoords[i][0]; - texCoords[j][1] = prevTexCoords[i][1]; + texCoords[j][0] = m_prevTexCoords[i][0]; + texCoords[j][1] = m_prevTexCoords[i][1]; //check if we need to recalc tex coords - will only happen if tex tiles are different + sharing vertices if (hash != lastHash) { @@ -1178,7 +1176,8 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data) p.v[j].fixedShade = shade; } - float texU, texV = 0; + float texU = 0; + float texV = 0; // tex coords if (currentMesh->textured) { @@ -1233,9 +1232,9 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data) // Copy current vertices into previous vertex array for (i = 0; i < 4; i++) { - prev[i] = p.v[i]; - prevTexCoords[i][0] = texCoords[i][0]; - prevTexCoords[i][1] = texCoords[i][1]; + m_prev[i] = p.v[i]; + m_prevTexCoords[i][0] = texCoords[i][0]; + m_prevTexCoords[i][1] = texCoords[i][1]; } } while (ph.NextPoly()); @@ -1659,10 +1658,10 @@ void CNew3D::SetSunClamp(bool enable) { m_sunClamp = enable; } - -void CNew3D::SetSignedShade(bool enable) -{ - m_shadeIsSigned = enable; -} - + +void CNew3D::SetSignedShade(bool enable) +{ + m_shadeIsSigned = enable; +} + } // New3D diff --git a/Src/Graphics/New3D/New3D.h b/Src/Graphics/New3D/New3D.h index 321d37b..1e74263 100644 --- a/Src/Graphics/New3D/New3D.h +++ b/Src/Graphics/New3D/New3D.h @@ -250,6 +250,9 @@ private: NodeAttributes m_nodeAttribs; Mat4 m_modelMat; // current modelview matrix + Vertex m_prev[4]; // these are class variables because sega bass fishing starts meshes with shared vertices from the previous one + UINT16 m_prevTexCoords[4][2]; // basically relying on undefined behavour + std::vector m_nodes; // this represents the entire render frame std::vector m_polyBufferRam; // dynamic polys std::vector m_polyBufferRom; // rom polys