Skip to content

Commit 22b6a75

Browse files
committed
Fix texture shader "wrap" replacement (as well as a similar case per GTA's logic)
1 parent 15bdd6d commit 22b6a75

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

Client/game_sa/CRenderWareSA.TextureReplacing.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,23 @@ bool CRenderWareSA::ModelInfoTXDAddTextures(SReplacementTextures* pReplacementTe
270270

271271
// If there is a name clash with an existing texture, replace it
272272
RwTexture* pExistingTexture = RwTexDictionaryFindNamedTexture(pInfo->pTxd, pNewTexture->name);
273+
274+
// Handle internal texture names (e.g., "remap" -> "#emap", "white" -> "@hite").
275+
// If the TXD contains the internal name, treat it as collided.
276+
// Ensure the replacement texture uses the internal name so the game engine can find it.
277+
if (!pExistingTexture)
278+
{
279+
const char* szInternalName = GetInternalTextureName(pNewTexture->name);
280+
if (szInternalName != pNewTexture->name)
281+
{
282+
pExistingTexture = RwTexDictionaryFindNamedTexture(pInfo->pTxd, szInternalName);
283+
284+
// Rename the replacement texture to match the internal name expected by the game engine.
285+
// This is required even if the original texture is missing, as the game hardcodes lookups for names like "#emap".
286+
strncpy(pNewTexture->name, szInternalName, RW_TEXTURE_NAME_LENGTH);
287+
}
288+
}
289+
273290
if (pExistingTexture)
274291
{
275292
RwTexDictionaryRemoveTexture(pInfo->pTxd, pExistingTexture);

Client/game_sa/CRenderWareSA.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*****************************************************************************/
1313

1414
#include "StdInc.h"
15+
#include <array>
1516
#include <CMatrix.h>
1617
#include <core/CCoreInterface.h>
1718
#define RWFUNC_IMPLEMENT
@@ -816,6 +817,62 @@ void CRenderWareSA::TxdForceUnload(ushort usTxdId, bool bDestroyTextures)
816817
}
817818
}
818819

820+
namespace
821+
{
822+
struct TextureMapping
823+
{
824+
const char* externalName;
825+
const char* internalName;
826+
};
827+
828+
constexpr std::array<TextureMapping, 2> kTextureMappings = {{
829+
{"remap", "#emap"},
830+
{"white", "@hite"}
831+
}};
832+
}
833+
834+
////////////////////////////////////////////////////////////////
835+
//
836+
// CRenderWareSA::GetInternalTextureName
837+
//
838+
// Maps external texture names (e.g. "remap") to internal GTA:SA names (e.g. "#emap")
839+
// Returns original name if no mapping exists
840+
//
841+
////////////////////////////////////////////////////////////////
842+
const char* CRenderWareSA::GetInternalTextureName(const char* szExternalName)
843+
{
844+
if (!szExternalName)
845+
return nullptr;
846+
847+
for (const auto& mapping : kTextureMappings)
848+
{
849+
if (_stricmp(szExternalName, mapping.externalName) == 0)
850+
return mapping.internalName;
851+
}
852+
return szExternalName;
853+
}
854+
855+
////////////////////////////////////////////////////////////////
856+
//
857+
// CRenderWareSA::GetExternalTextureName
858+
//
859+
// Maps internal GTA:SA names (e.g. "#emap") to external texture names (e.g. "remap")
860+
// Returns original name if no mapping exists
861+
//
862+
////////////////////////////////////////////////////////////////
863+
const char* CRenderWareSA::GetExternalTextureName(const char* szInternalName)
864+
{
865+
if (!szInternalName)
866+
return nullptr;
867+
868+
for (const auto& mapping : kTextureMappings)
869+
{
870+
if (_stricmp(szInternalName, mapping.internalName) == 0)
871+
return mapping.externalName;
872+
}
873+
return szInternalName;
874+
}
875+
819876
////////////////////////////////////////////////////////////////
820877
//
821878
// CRenderWareSA::GetTXDIDForModelID
@@ -889,9 +946,13 @@ void CRenderWareSA::GetModelTextureNames(std::vector<SString>& outNameList, usho
889946
std::vector<RwTexture*> textureList;
890947
GetTxdTextures(textureList, pTXD);
891948

892-
for (std::vector<RwTexture*>::iterator iter = textureList.begin(); iter != textureList.end(); iter++)
949+
for (RwTexture* pTexture : textureList)
893950
{
894-
outNameList.push_back((*iter)->name);
951+
// Fix for #emap corruption:
952+
// Some textures (like 'remap') are internally renamed to start with '#' (e.g. '#emap') by SA.
953+
// This causes issues when scripts try to access them by their original name.
954+
// We detect this case and return the expected name 'remap' instead.
955+
outNameList.push_back(GetExternalTextureName(pTexture->name));
895956
}
896957

897958
if (bLoadedModel)
@@ -951,7 +1012,8 @@ bool CRenderWareSA::GetModelTextures(std::vector<std::tuple<std::string, CPixels
9511012

9521013
for (RwTexture* pTexture : rwTextureList)
9531014
{
954-
SString strTextureName = pTexture->name;
1015+
SString strTextureName = GetExternalTextureName(pTexture->name);
1016+
9551017
bool bValidTexture = false;
9561018

9571019
if (bExcludeTextures)

Client/game_sa/CRenderWareSA.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ class CRenderWareSA : public CRenderWare
146146
static void GetClumpAtomicList(RpClump* pClump, std::vector<RpAtomic*>& outAtomicList);
147147
static bool DoContainTheSameGeometry(RpClump* pClumpA, RpClump* pClumpB, RpAtomic* pAtomicB);
148148

149+
static const char* GetInternalTextureName(const char* szExternalName);
150+
static const char* GetExternalTextureName(const char* szInternalName);
151+
149152
void OnTextureStreamIn(STexInfo* pTexInfo);
150153
void OnTextureStreamOut(STexInfo* pTexInfo);
151154
void DisableGTAVertexShadersForAWhile();

0 commit comments

Comments
 (0)