Skip to content

Fix segfault in WaterRenderObjClass when skybox asset fails to load#188

Merged
fbraz3 merged 1 commit into
fbraz3:mainfrom
1rgs:fix/skybox-null-guard
Jul 9, 2026
Merged

Fix segfault in WaterRenderObjClass when skybox asset fails to load#188
fbraz3 merged 1 commit into
fbraz3:mainfrom
1rgs:fix/skybox-null-guard

Conversation

@1rgs

@1rgs 1rgs commented Jul 5, 2026

Copy link
Copy Markdown

Problem

On macOS (Apple Silicon, macos-vulkan preset, Beta 12), the game segfaults as soon as the shell map — or any map with water — renders:

Thread 0 Crashed (SIGSEGV, address 0x0):
  WaterRenderObjClass::Render(RenderInfoClass&)
  DefaultStaticSortListClass::Render_And_Clear(RenderInfoClass&)
  WW3D::Render_And_Clear_Static_Sort_Lists(RenderInfoClass&)
  RTS3DScene::Flush(RenderInfoClass&)
  ...

Root cause

WaterRenderObjClass::Render() dereferences m_skyBox whenever TheGlobalData->m_drawSkyBox is set, but Create_Render_Obj("new_skybox") returns null when the skybox asset is unavailable — e.g. when the base Generals archives aren't found at init (Steam layout without ZH_Generals/, or any partial-asset setup). Disassembly of the crash site confirms the null deref is the m_skyBox->Set_Position() / m_skyBox->Render() pair after the water-type switch.

replaceSkyboxTexture() has the same hazard: it passes m_skyBox into replacePrototypeTexture()replaceAssetTexture(), which calls robj->Class_ID() unconditionally, so any map that swaps skybox textures crashes the same way.

Fix

  • Guard the m_skyBox use in Render() (null check alongside the existing TheGlobalData check)
  • Early-return in replaceSkyboxTexture() when m_skyBox is null
  • Add [TEX_MISSING] stderr logging in Apply_Missing_Texture() (guarded #ifndef _WIN32), as proposed in the Session 44 notes — this is what made the missing-asset root cause diagnosable here

Testing

  • Before: reproducible SIGSEGV on shell map load and on entering the USA campaign (macOS 26.5, M-series, Beta 12 + retail Steam ZH assets)
  • After: shell map renders and plays fine; entering maps with water no longer crashes; when assets are complete the skybox renders as before (guard is a no-op)
  • [TEX_MISSING] output confirmed: 247 missing textures with base archives absent → 1 (trstrtholecvr.tga, absent from retail archives) once ZH_Generals/ is in place

🤖 Generated with Claude Code

WaterRenderObjClass::Render() dereferences m_skyBox whenever
TheGlobalData->m_drawSkyBox is set, but Create_Render_Obj("new_skybox")
can return null when the skybox asset is unavailable (e.g. the base
Generals archives are not found at init). On macOS this segfaults
(SIGSEGV in WaterRenderObjClass::Render via
Render_And_Clear_Static_Sort_Lists) as soon as the shell map or any
water-bearing map renders.

- Guard the m_skyBox use in Render()
- Early-return in replaceSkyboxTexture(), since
  replaceAssetTexture() dereferences the render object unconditionally
- Add [TEX_MISSING] stderr logging in Apply_Missing_Texture()
  (non-Windows only), as proposed in Session 44 notes - this is what
  made the missing-asset root cause diagnosable

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fbraz3 fbraz3 merged commit 931e248 into fbraz3:main Jul 9, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants