From 73f46a9ef897a046e1cb50322e30fca1a1676abf Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:34:08 +0200 Subject: [PATCH 1/4] fix(scorch): Early return if scorch does not fit in buffer --- .../Source/W3DDevice/GameClient/W3DScorch.cpp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp index f8ff61611d8..0eb171541a6 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp @@ -196,14 +196,28 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, { maxY = map.getYExtent() - map.getBorderSizeInline(); } + + const Int vertexCountX = maxX - minX; + const Int vertexCountY = maxY - minY; + if (vertexCountX <= 0 || vertexCountY <= 0) + { + return true; + } + + const Int requiredVertices = vertexCountX * vertexCountY; + const Int requiredIndices = 6 * (vertexCountX - 1) * (vertexCountY - 1); + if (requiredVertices > MAX_SCORCH_VERTEX - m_curNumScorchVertices || + requiredIndices > MAX_SCORCH_INDEX - m_curNumScorchIndices) + { + return false; + } + Int startVertex = m_curNumScorchVertices; Int i, j; for (j = minY; j < maxY; j++) { for (i = minX; i < maxX; i++) { - if (m_curNumScorchVertices >= MAX_SCORCH_VERTEX) - return false; curVb->diffuse = diffuse; Real theZ = amtToFloat + getMapHeight(map, i, j); // The scorchmarks are spaced out by 1.5 in the texture. @@ -225,8 +239,6 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, { for (i = 0; i < maxX - minX - 1; i++) { - if (m_curNumScorchIndices + 6 > MAX_SCORCH_INDEX) - return false; Int xNdx = i + minX + map.getBorderSizeInline(); Int yNdx = j + minY + map.getBorderSizeInline(); Bool flipForBlend = map.getFlipState(xNdx, yNdx); From 8e9e3046c03327bbb1e3372cc47a9a15f3c99ca1 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:07:52 +0200 Subject: [PATCH 2/4] tweak(scorch): Increase scorch buffer limits to 16-bit maximum --- .../GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h index 02423a0e867..b22076c58d7 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h @@ -68,8 +68,8 @@ class W3DScorch : public W3DScorchInterface enum { - MAX_SCORCH_VERTEX = 8194, - MAX_SCORCH_INDEX = 6 * 8194, + MAX_SCORCH_VERTEX = 65535 / 2, + MAX_SCORCH_INDEX = 65535, MAX_SCORCH_MARKS = 500, SCORCH_MARKS_IN_TEXTURE = 9, SCORCH_PER_ROW = 3 From 3ebf3588992358a587ce306b4a139737a58dd5ec Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Fri, 21 Aug 2026 20:25:18 +0200 Subject: [PATCH 3/4] Address review comment --- .../Source/W3DDevice/GameClient/W3DScorch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp index 0eb171541a6..91529152656 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp @@ -206,8 +206,8 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, const Int requiredVertices = vertexCountX * vertexCountY; const Int requiredIndices = 6 * (vertexCountX - 1) * (vertexCountY - 1); - if (requiredVertices > MAX_SCORCH_VERTEX - m_curNumScorchVertices || - requiredIndices > MAX_SCORCH_INDEX - m_curNumScorchIndices) + if (m_curNumScorchVertices + requiredVertices > MAX_SCORCH_VERTEX || + m_curNumScorchIndices + requiredIndices > MAX_SCORCH_INDEX) { return false; } From 2482a6f961c6eb28a81681c9b267397b4a19e5b6 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Sun, 23 Aug 2026 11:48:09 +0200 Subject: [PATCH 4/4] Correct power of two. Add scorch result enum --- .../Include/W3DDevice/GameClient/W3DScorch.h | 13 ++++++++++--- .../Source/W3DDevice/GameClient/W3DScorch.cpp | 15 ++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h index b22076c58d7..20d5f33b609 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h @@ -68,17 +68,24 @@ class W3DScorch : public W3DScorchInterface enum { - MAX_SCORCH_VERTEX = 65535 / 2, + MAX_SCORCH_VERTEX = 32768, MAX_SCORCH_INDEX = 65535, MAX_SCORCH_MARKS = 500, SCORCH_MARKS_IN_TEXTURE = 9, SCORCH_PER_ROW = 3 }; + enum WriteScorchResult + { + SCORCH_WRITTEN, + SCORCH_SKIPPED, + SCORCH_BUFFER_FULL + }; + Bool isDuplicate(const TScorch& scorch) const; void updateScorches(WorldHeightMap& map); ///< Update m_vertexScorch and m_indexScorch so all scorches will be drawn. - Bool writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, UnsignedInt diffuse, - VertexFormatXYZDUV1* curVb, UnsignedShort* curIb); + WriteScorchResult writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, UnsignedInt diffuse, + VertexFormatXYZDUV1* curVb, UnsignedShort* curIb); DX8VertexBufferClass* m_vertexScorch; ///< Scorch vertex buffer. DX8IndexBufferClass* m_indexScorch; ///< indices defining a triangles for the scorch drawing. diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp index 91529152656..1a44e3e8fa4 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp @@ -162,16 +162,17 @@ void W3DScorch::updateScorches(WorldHeightMap& map) // TheSuperHackers @info Scorches are written in reverse order to ensure that the last added scorches fit in the buffers. for (std::deque::reverse_iterator it = m_scorches.rbegin(); it != m_scorches.rend(); ++it) { - if (!writeScorchToBuffer(*it, map, diffuse, - vb + m_curNumScorchVertices, ib + m_curNumScorchIndices)) + if (writeScorchToBuffer(*it, map, diffuse, + vb + m_curNumScorchVertices, ib + m_curNumScorchIndices) == SCORCH_BUFFER_FULL) { return; } } } -Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, UnsignedInt diffuse, - VertexFormatXYZDUV1* curVb, UnsignedShort* curIb) +W3DScorch::WriteScorchResult W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, + UnsignedInt diffuse, VertexFormatXYZDUV1* curVb, + UnsignedShort* curIb) { Real radius = scorch.radius; Vector3 loc = scorch.location; @@ -201,7 +202,7 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, const Int vertexCountY = maxY - minY; if (vertexCountX <= 0 || vertexCountY <= 0) { - return true; + return SCORCH_SKIPPED; } const Int requiredVertices = vertexCountX * vertexCountY; @@ -209,7 +210,7 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, if (m_curNumScorchVertices + requiredVertices > MAX_SCORCH_VERTEX || m_curNumScorchIndices + requiredIndices > MAX_SCORCH_INDEX) { - return false; + return SCORCH_BUFFER_FULL; } Int startVertex = m_curNumScorchVertices; @@ -269,5 +270,5 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, } } - return true; + return SCORCH_WRITTEN; }