@@ -224,6 +224,10 @@ void CRenderWareSA::PulseWorldTextureWatch()
224224// //////////////////////////////////////////////////////////////
225225void CRenderWareSA::StreamingAddedTexture (ushort usTxdId, const SString& strTextureName, CD3DDUMMY* pD3DData)
226226{
227+ // Skip textures without valid D3D data or name - shader matching requires both
228+ if (!pD3DData || strTextureName.empty ())
229+ return ;
230+
227231 STexInfo* pTexInfo = CreateTexInfo (usTxdId, strTextureName, pD3DData);
228232 OnTextureStreamIn (pTexInfo);
229233}
@@ -258,6 +262,50 @@ void CRenderWareSA::StreamingRemovedTxd(ushort usTxdId)
258262 TIMING_CHECKPOINT (" -StreamingRemovedTxd" );
259263}
260264
265+ // //////////////////////////////////////////////////////////////
266+ //
267+ // CRenderWareSA::RemoveStreamingTexture
268+ //
269+ // Remove a single texture that was added via StreamingAddedTexture.
270+ // Finds the texture by matching TXD ID and D3D data pointer.
271+ //
272+ // //////////////////////////////////////////////////////////////
273+ void CRenderWareSA::RemoveStreamingTexture (unsigned short usTxdId, CD3DDUMMY* pD3DData)
274+ {
275+ if (!pD3DData)
276+ return ;
277+
278+ typedef std::multimap<ushort, STexInfo*>::iterator IterType;
279+ std::pair<IterType, IterType> range = m_TexInfoMap.equal_range (usTxdId);
280+ for (IterType iter = range.first ; iter != range.second ;)
281+ {
282+ STexInfo* pTexInfo = iter->second ;
283+ if (pTexInfo && pTexInfo->pD3DData == pD3DData)
284+ {
285+ OnTextureStreamOut (pTexInfo);
286+ DestroyTexInfo (pTexInfo);
287+ m_TexInfoMap.erase (iter++);
288+ return ; // Only one entry per D3D data
289+ }
290+ else
291+ ++iter;
292+ }
293+ }
294+
295+ // //////////////////////////////////////////////////////////////
296+ //
297+ // CRenderWareSA::IsTexInfoRegistered
298+ //
299+ // Check if a D3D data pointer is already registered in the shader system.
300+ //
301+ // //////////////////////////////////////////////////////////////
302+ bool CRenderWareSA::IsTexInfoRegistered (CD3DDUMMY* pD3DData) const
303+ {
304+ if (!pD3DData)
305+ return false ;
306+ return MapContains (m_D3DDataTexInfoMap, pD3DData);
307+ }
308+
261309// //////////////////////////////////////////////////////////////
262310//
263311// CRenderWareSA::ScriptAddedTxd
@@ -269,13 +317,28 @@ void CRenderWareSA::StreamingRemovedTxd(ushort usTxdId)
269317void CRenderWareSA::ScriptAddedTxd (RwTexDictionary* pTxd)
270318{
271319 TIMING_CHECKPOINT (" +ScriptAddedTxd" );
320+
321+ // Validate TXD pointer before iterating
322+ if (!pTxd || !SharedUtil::IsReadablePointer (pTxd, sizeof (RwTexDictionary)))
323+ {
324+ TIMING_CHECKPOINT (" -ScriptAddedTxd" );
325+ return ;
326+ }
327+
272328 std::vector<RwTexture*> textureList;
273329 GetTxdTextures (textureList, pTxd);
274330 for (std::vector<RwTexture*>::iterator iter = textureList.begin (); iter != textureList.end (); iter++)
275331 {
276332 RwTexture* texture = *iter;
333+ if (!texture || !SharedUtil::IsReadablePointer (texture, sizeof (RwTexture)))
334+ continue ;
335+
277336 const char * szTextureName = texture->name ;
278- CD3DDUMMY* pD3DData = texture->raster ? (CD3DDUMMY*)texture->raster ->renderResource : NULL ;
337+ CD3DDUMMY* pD3DData = (texture->raster && SharedUtil::IsReadablePointer (texture->raster , sizeof (RwRaster)))
338+ ? (CD3DDUMMY*)texture->raster ->renderResource : NULL ;
339+
340+ if (!pD3DData || !szTextureName[0 ])
341+ continue ;
279342
280343 // Added texture
281344 STexInfo* pTexInfo = CreateTexInfo (texture, szTextureName, pD3DData);
@@ -320,12 +383,21 @@ void CRenderWareSA::ScriptRemovedTexture(RwTexture* pTex)
320383// //////////////////////////////////////////////////////////////
321384void CRenderWareSA::SpecialAddedTexture (RwTexture* texture, const char * szTextureName)
322385{
386+ if (!texture || !SharedUtil::IsReadablePointer (texture, sizeof (RwTexture)))
387+ return ;
388+
323389 if (!szTextureName)
324390 szTextureName = texture->name ;
391+ if (!szTextureName || !szTextureName[0 ])
392+ return ;
325393
326- OutputDebug (SString (" Adding special texture %s" , szTextureName));
394+ CD3DDUMMY* pD3DData = (texture->raster && SharedUtil::IsReadablePointer (texture->raster , sizeof (RwRaster)))
395+ ? (CD3DDUMMY*)texture->raster ->renderResource : NULL ;
327396
328- CD3DDUMMY* pD3DData = texture->raster ? (CD3DDUMMY*)texture->raster ->renderResource : NULL ;
397+ if (!pD3DData)
398+ return ;
399+
400+ OutputDebug (SString (" Adding special texture %s" , szTextureName));
329401
330402 // Added texture
331403 STexInfo* pTexInfo = CreateTexInfo (texture, szTextureName, pD3DData);
0 commit comments