From 84b16f2aeb4571782a5adeda443fbf597176aba4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 21 Dec 2025 21:24:32 -0600 Subject: [PATCH] fix(gx): fix buffer overruns in TEXTLINETEXTURE::WriteGeometry --- src/gx/font/CGxString.cpp | 123 +++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/src/gx/font/CGxString.cpp b/src/gx/font/CGxString.cpp index 7fc9ea1..fd95b57 100644 --- a/src/gx/font/CGxString.cpp +++ b/src/gx/font/CGxString.cpp @@ -37,78 +37,89 @@ void TEXTLINETEXTURE::WriteGeometry(CGxVertexPCT* buffer, const CImVector& fontC ? this->m_colors.Count() : 0; - if (vertexOffset >= this->m_vert.Count()) { - return; - } - - uint32_t v24 = this->m_vert.Count() - vertexOffset; - - if (vertexCount >= v24) { - vertexCount = v24; - } + // Drop shadows if (hasShadow) { - C3Vector shadowTranslation = { - viewTranslation.x + floor(ScreenToPixelWidth(0, shadowOffset.x)), - viewTranslation.y + floor(ScreenToPixelHeight(0, shadowOffset.y)), - viewTranslation.z - }; + if (vertexOffset < this->m_vert.Count()) { + int32_t availableVertexCount = this->m_vert.Count() - vertexOffset; + int32_t shadowVertexCount = vertexCount >= availableVertexCount ? availableVertexCount : vertexCount; - auto color = colorCount ? this->m_colors[vertexOffset] : fontColor; + C3Vector shadowTranslation = { + viewTranslation.x + floor(ScreenToPixelWidth(0, shadowOffset.x)), + viewTranslation.y + floor(ScreenToPixelHeight(0, shadowOffset.y)), + viewTranslation.z + }; - for (int32_t i = 0; i < vertexCount; i++) { + auto color = colorCount ? this->m_colors[vertexOffset] : fontColor; + + for (int32_t i = 0; i < shadowVertexCount; i++) { + auto& vertex = this->m_vert[vertexOffset + i]; + + C3Vector p = { + vertex.vc.x + shadowTranslation.x, + vertex.vc.y + shadowTranslation.y, + vertex.vc.z + shadowTranslation.z + }; + + buffer->p = p; + buffer->tc[0] = vertex.tc; + + auto formattedShadowColor = shadowColor; + if (a8 && colorCount) { + formattedShadowColor.a = static_cast( + (static_cast(formattedShadowColor.a) * static_cast(color.a)) / 65536.0f + ); + } + GxFormatColor(formattedShadowColor); + buffer->c = formattedShadowColor; + + buffer++; + } + + vertexCount -= shadowVertexCount; + if (vertexOffset + shadowVertexCount >= this->m_vert.Count()) { + vertexOffset = 0; + } + } else { + vertexOffset -= this->m_vert.Count(); + } + } + + // Characters + + if (vertexCount && vertexOffset < this->m_vert.Count()) { + int32_t availableVertexCount = this->m_vert.Count() - vertexOffset; + int32_t characterVertexCount = vertexCount >= availableVertexCount ? availableVertexCount : vertexCount; + + // if (BATCHEDRENDERFONTDESC::s_billboarded) { + // // TODO + // } + + for (int32_t i = 0; i < characterVertexCount; i++) { auto& vertex = this->m_vert[vertexOffset + i]; + auto color = colorCount ? this->m_colors[vertexOffset + i] : fontColor; + GxFormatColor(color); + + // if (BATCHEDRENDERFONTDESC::s_billboarded) { + // // TODO + // continue; + // } + C3Vector p = { - vertex.vc.x + shadowTranslation.x, - vertex.vc.y + shadowTranslation.y, - vertex.vc.z + shadowTranslation.z + vertex.vc.x + viewTranslation.x, + vertex.vc.y + viewTranslation.y, + vertex.vc.z + viewTranslation.z }; buffer->p = p; buffer->tc[0] = vertex.tc; - auto formattedShadowColor = shadowColor; - if (a8 && colorCount) { - formattedShadowColor.a = static_cast( - (static_cast(formattedShadowColor.a) * static_cast(color.a)) / 65536.0f - ); - } - GxFormatColor(formattedShadowColor); - buffer->c = formattedShadowColor; + buffer->c = color; buffer++; } } - - // if (BATCHEDRENDERFONTDESC::s_billboarded) { - // // TODO - // } - - for (int32_t i = 0; i < vertexCount; i++) { - auto& vertex = this->m_vert[vertexOffset + i]; - - auto color = colorCount ? this->m_colors[vertexOffset + i] : fontColor; - GxFormatColor(color); - - // if (BATCHEDRENDERFONTDESC::s_billboarded) { - // // TODO - // continue; - // } - - C3Vector p = { - vertex.vc.x + viewTranslation.x, - vertex.vc.y + viewTranslation.y, - vertex.vc.z + viewTranslation.z - }; - - buffer->p = p; - buffer->tc[0] = vertex.tc; - - buffer->c = color; - - buffer++; - } } CGxString* CGxString::GetNewString(int32_t linkOnList) {