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.

This commit is contained in:
Ian Curtis 2018-09-02 21:36:24 +00:00
parent c1c2dedcfa
commit e4f5f0bcaf
2 changed files with 23 additions and 21 deletions

View file

@ -23,12 +23,12 @@ CNew3D::CNew3D(const Util::Config::Node &config, std::string gameName)
m_cullingRAMHi = nullptr; m_cullingRAMHi = nullptr;
m_polyRAM = nullptr; m_polyRAM = nullptr;
m_vrom = nullptr; m_vrom = nullptr;
m_textureRAM = nullptr; m_textureRAM = nullptr;
m_sunClamp = true; m_sunClamp = true;
m_shadeIsSigned = true; m_shadeIsSigned = true;
} }
CNew3D::~CNew3D() CNew3D::~CNew3D()
{ {
m_vbo.Destroy(); m_vbo.Destroy();
} }
@ -1026,9 +1026,7 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph)
void CNew3D::CacheModel(Model *m, const UINT32 *data) void CNew3D::CacheModel(Model *m, const UINT32 *data)
{ {
Vertex prev[4];
UINT16 texCoords[4][2]; UINT16 texCoords[4][2];
UINT16 prevTexCoords[4][2];
PolyHeader ph; PolyHeader ph;
UINT64 lastHash = -1; UINT64 lastHash = -1;
SortingMesh* currentMesh = nullptr; SortingMesh* currentMesh = nullptr;
@ -1086,10 +1084,10 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
{ {
if (ph.SharedVertex(i)) if (ph.SharedVertex(i))
{ {
p.v[j] = prev[i]; p.v[j] = m_prev[i];
texCoords[j][0] = prevTexCoords[i][0]; texCoords[j][0] = m_prevTexCoords[i][0];
texCoords[j][1] = prevTexCoords[i][1]; 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 //check if we need to recalc tex coords - will only happen if tex tiles are different + sharing vertices
if (hash != lastHash) { if (hash != lastHash) {
@ -1178,7 +1176,8 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
p.v[j].fixedShade = shade; p.v[j].fixedShade = shade;
} }
float texU, texV = 0; float texU = 0;
float texV = 0;
// tex coords // tex coords
if (currentMesh->textured) { if (currentMesh->textured) {
@ -1233,9 +1232,9 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
// Copy current vertices into previous vertex array // Copy current vertices into previous vertex array
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
prev[i] = p.v[i]; m_prev[i] = p.v[i];
prevTexCoords[i][0] = texCoords[i][0]; m_prevTexCoords[i][0] = texCoords[i][0];
prevTexCoords[i][1] = texCoords[i][1]; m_prevTexCoords[i][1] = texCoords[i][1];
} }
} while (ph.NextPoly()); } while (ph.NextPoly());
@ -1659,10 +1658,10 @@ void CNew3D::SetSunClamp(bool enable)
{ {
m_sunClamp = enable; m_sunClamp = enable;
} }
void CNew3D::SetSignedShade(bool enable) void CNew3D::SetSignedShade(bool enable)
{ {
m_shadeIsSigned = enable; m_shadeIsSigned = enable;
} }
} // New3D } // New3D

View file

@ -250,6 +250,9 @@ private:
NodeAttributes m_nodeAttribs; NodeAttributes m_nodeAttribs;
Mat4 m_modelMat; // current modelview matrix 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<Node> m_nodes; // this represents the entire render frame std::vector<Node> m_nodes; // this represents the entire render frame
std::vector<Poly> m_polyBufferRam; // dynamic polys std::vector<Poly> m_polyBufferRam; // dynamic polys
std::vector<Poly> m_polyBufferRom; // rom polys std::vector<Poly> m_polyBufferRom; // rom polys