From ddcf743d1206553abf5827f9f697802865c0878c Mon Sep 17 00:00:00 2001 From: Jacob Ledbetter Date: Mon, 9 Nov 2026 20:12:47 -0700 Subject: [PATCH] fix(ww3d2): Write dynamic vertices and read screenshot pixels without pointer casts Co-Authored-By: Claude Opus 5.5 --- .../W3DDevice/GameClient/W3DScreenshot.cpp | 10 +++++--- .../Source/WWVegas/WW3D2/seglinerenderer.cpp | 25 ++++++------------- .../Source/WWVegas/WW3D2/streakRender.cpp | 23 ++++++----------- 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScreenshot.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScreenshot.cpp index 7492aaa7c5c..fa5430e5590 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScreenshot.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScreenshot.cpp @@ -82,10 +82,11 @@ static DWORD WINAPI screenshotThreadFunc(LPVOID param) // Convert A8R8G8B8/X8R8G8B8 to R8G8B8 for (unsigned int y = 0; y < height; ++y) { - const unsigned int* srcLine = reinterpret_cast(data->pixelData + y * data->pitch); + const unsigned char* srcLine = data->pixelData + y * data->pitch; for (unsigned int x = 0; x < width; ++x) { - const unsigned int argb = srcLine[x]; + unsigned int argb; + memcpy(&argb, srcLine + x * sizeof(argb), sizeof(argb)); const unsigned int index = 3 * (x + y * width); image[index + 0] = (unsigned char)(argb >> 16); // r image[index + 1] = (unsigned char)(argb >> 8); // g @@ -98,10 +99,11 @@ static DWORD WINAPI screenshotThreadFunc(LPVOID param) // Convert R5G6B5 to R8G8B8 for (unsigned int y = 0; y < height; ++y) { - const unsigned short* srcLine = reinterpret_cast(data->pixelData + y * data->pitch); + const unsigned char* srcLine = data->pixelData + y * data->pitch; for (unsigned int x = 0; x < width; ++x) { - const unsigned short rgb = srcLine[x]; + unsigned short rgb; + memcpy(&rgb, srcLine + x * sizeof(rgb), sizeof(rgb)); const unsigned int index = 3 * (x + y * width); image[index + 0] = (unsigned char)((rgb & 0xF800) >> 8); // r image[index + 1] = (unsigned char)((rgb & 0x07E0) >> 3); // g diff --git a/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp index 6c9d8ba4c25..f816e800220 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp @@ -1139,26 +1139,17 @@ void SegLineRendererClass::Render { DynamicVBAccessClass::WriteLockClass Lock(&Verts); unsigned int i; - unsigned char *vb=(unsigned char*)Lock.Get_Formatted_Vertex_Array(); - const FVFInfoClass& fvfinfo=Verts.FVF_Info(); - - const unsigned int verticesOffset = fvfinfo.Get_Location_Offset(); - const unsigned diffuseOffset = fvfinfo.Get_Diffuse_Offset(); - const unsigned textureOffset = fvfinfo.Get_Tex_Offset(0); - const unsigned vbSize = fvfinfo.Get_FVF_Size(); + VertexFormatXYZNDUV2* vb=Lock.Get_Formatted_Vertex_Array(); for (i=0; i(vb + verticesOffset); - vertex->X = vArray[i].x; - vertex->Y = vArray[i].y; - vertex->Z = vArray[i].z; - *reinterpret_cast(vb + diffuseOffset) = vArray[i].diffuse; - Vector2 *texture = reinterpret_cast(vb + textureOffset); - texture->U = vArray[i].u1; - texture->V = vArray[i].v1; - vb += vbSize; + // Copy the location, color and texture coordinates + vb[i].x = vArray[i].x; + vb[i].y = vArray[i].y; + vb[i].z = vArray[i].z; + vb[i].diffuse = vArray[i].diffuse; + vb[i].u1 = vArray[i].u1; + vb[i].v1 = vArray[i].v1; } } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/streakRender.cpp b/Core/Libraries/Source/WWVegas/WW3D2/streakRender.cpp index 42e8544d862..22b5e27b60a 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/streakRender.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/streakRender.cpp @@ -1329,27 +1329,18 @@ void StreakRendererClass::RenderStreak { DynamicVBAccessClass::WriteLockClass Lock(&Verts); unsigned int i; - unsigned char *vb=(unsigned char*)Lock.Get_Formatted_Vertex_Array(); - const FVFInfoClass& fvfinfo=Verts.FVF_Info(); - - const unsigned verticesOffset = fvfinfo.Get_Location_Offset(); - const unsigned diffuseOffset = fvfinfo.Get_Diffuse_Offset(); - const unsigned textureOffset = fvfinfo.Get_Tex_Offset(0); - const unsigned vbSize = fvfinfo.Get_FVF_Size(); + VertexFormatXYZNDUV2* vb=Lock.Get_Formatted_Vertex_Array(); for (i=0; i(vb + verticesOffset); - vertex->X = vertexArray[i].x; - vertex->Y = vertexArray[i].y; - vertex->Z = vertexArray[i].z; - *reinterpret_cast(vb + diffuseOffset) = DX8Wrapper::Convert_Color_Clamp(colors[MIN((i/2), point_cnt)]); // TODO: Does not work correctly when subdivision are not 0 - Vector2 *texture = reinterpret_cast(vb + textureOffset); - texture->U = vertexArray[i].u1; - texture->V = vertexArray[i].v1; - vb += vbSize; + vb[i].x = vertexArray[i].x; + vb[i].y = vertexArray[i].y; + vb[i].z = vertexArray[i].z; + vb[i].diffuse = DX8Wrapper::Convert_Color_Clamp(colors[MIN((i/2), point_cnt)]); // TODO: Does not work correctly when subdivision are not 0 + vb[i].u1 = vertexArray[i].u1; + vb[i].v1 = vertexArray[i].v1; } }