Skip to content

Commit 40a0d1d

Browse files
committed
Cleanup & crash fix
1 parent bd44f1d commit 40a0d1d

File tree

2 files changed

+45
-89
lines changed

2 files changed

+45
-89
lines changed

Client/game_sa/CRenderWareSA.cpp

Lines changed: 45 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -496,49 +496,46 @@ bool CRenderWareSA::ReplaceObjectModel(RpClump* newClump, std::uint16_t modelID)
496496
if ((newClump == reinterpret_cast<RpClump*>(currentModelInterface->pRwObject) || DoContainTheSameGeometry(newClump, nullptr, reinterpret_cast<RpAtomic*>(currentModelInterface->pRwObject))) && pModelInfo->IsSameModelType())
497497
return true;
498498

499-
// We create a copy of the current interface to later call DeleteRwObject on it,
500-
// so we can remove the old RwObject after setting the new one
501-
// Old RwObject must be deleted after setting the new one to avoid crashes during restream
502-
CBaseModelInfoSAInterface* copyCurrentModelInterface = nullptr;
503-
switch (reinterpret_cast<std::uintptr_t>(currentModelInterface->VFTBL))
499+
// We need to make a copy here because DeleteRwObject removes atomics from our new clump
500+
RpClump* clonedClump = RpClumpClone(newClump);
501+
if (!clonedClump)
502+
return false;
503+
504+
// Add extra reference to prevent the TXD from being unloaded after calling DeleteRwObject
505+
bool extraRefAdded = false;
506+
if (currentModelInterface->pRwObject)
504507
{
505-
case VTBL_CAtomicModelInfo:
506-
{
507-
copyCurrentModelInterface = new CAtomicModelInfoSAInterface();
508-
MemCpyFast(copyCurrentModelInterface, currentModelInterface, sizeof(CAtomicModelInfoSAInterface));
508+
CTxdStore_AddRef(currentModelInterface->usTextureDictionary);
509+
extraRefAdded = true;
510+
}
509511

510-
break;
511-
}
512-
case VTBL_CDamageAtomicModelInfo:
513-
{
514-
copyCurrentModelInterface = new CDamageableModelInfoSAInterface();
515-
MemCpyFast(copyCurrentModelInterface, currentModelInterface, sizeof(CDamageableModelInfoSAInterface));
512+
// Destroy RwObject from original interface after type conversion
513+
CBaseModelInfoSAInterface* originalInterface = pModelInfo->GetOriginalInterface();
514+
if (originalInterface && originalInterface->pRwObject)
515+
{
516+
originalInterface->DeleteRwObject();
516517

517-
break;
518-
}
519-
case VTBL_CClumpModelInfo:
520-
{
521-
copyCurrentModelInterface = new CClumpModelInfoSAInterface();
522-
MemCpyFast(copyCurrentModelInterface, currentModelInterface, sizeof(CClumpModelInfoSAInterface));
518+
// If the originalInterface has an existing RwObject, it points to the same one as copyCurrentModelInterface
519+
currentModelInterface->pRwObject = nullptr;
520+
}
523521

524-
break;
525-
}
526-
case VTBL_CTimeModelInfo:
527-
{
528-
copyCurrentModelInterface = new CTimeModelInfoSAInterface();
529-
MemCpyFast(copyCurrentModelInterface, currentModelInterface, sizeof(CTimeModelInfoSAInterface));
522+
// The user can convert the same model multiple times, but its original model interface is saved only once,
523+
// so we remove the RwObject and the interface created during the last conversion
524+
CBaseModelInfoSAInterface* lastConversionInterface = pModelInfo->GetLastConversionInterface();
525+
if (lastConversionInterface)
526+
{
527+
if (lastConversionInterface->pRwObject == currentModelInterface->pRwObject)
528+
currentModelInterface->pRwObject = nullptr;
530529

531-
break;
532-
}
533-
}
530+
lastConversionInterface->DeleteRwObject();
531+
delete lastConversionInterface;
534532

535-
copyCurrentModelInterface->usNumberOfRefs = 0;
536-
currentModelInterface->pRwObject = nullptr;
533+
pModelInfo->SetLastConversionInterface(nullptr);
534+
}
537535

538-
// We need to make a copy here because DeleteRwObject removes atomics from our new clump
539-
RpClump* clonedClump = RpClumpClone(newClump);
540-
if (!clonedClump)
541-
return false;
536+
// Destroy current (old) RwObject
537+
if (currentModelInterface->pRwObject)
538+
currentModelInterface->DeleteRwObject();
542539

543540
// Check model type
544541
switch (pModelInfo->GetModelType())
@@ -549,6 +546,9 @@ bool CRenderWareSA::ReplaceObjectModel(RpClump* newClump, std::uint16_t modelID)
549546
if (!atomic)
550547
return false;
551548

549+
// Create main root frame
550+
RpAtomicSetFrame(atomic, RwFrameCreate());
551+
552552
// Is damageable object?
553553
if (currentModelInterface->IsDamageAtomicVTBL())
554554
{
@@ -573,6 +573,8 @@ bool CRenderWareSA::ReplaceObjectModel(RpClump* newClump, std::uint16_t modelID)
573573
else
574574
static_cast<CAtomicModelInfoSAInterface*>(damagedInfo->baseInterface)->SetAtomic(atomic);
575575

576+
// Create main root frame
577+
RpAtomicSetFrame(atomic, RwFrameCreate());
576578
pGame->GetVisibilityPlugins()->SetAtomicId(atomic, damagedInfo->modelId);
577579

578580
// Remove our atomic from temp clump
@@ -599,6 +601,9 @@ bool CRenderWareSA::ReplaceObjectModel(RpClump* newClump, std::uint16_t modelID)
599601
if (!atomic)
600602
return false;
601603

604+
// Create main root frame
605+
RpAtomicSetFrame(atomic, RwFrameCreate());
606+
602607
static_cast<CTimeModelInfoSAInterface*>(currentModelInterface)->SetAtomic(atomic);
603608
pGame->GetVisibilityPlugins()->SetAtomicId(atomic, modelID);
604609

@@ -618,52 +623,10 @@ bool CRenderWareSA::ReplaceObjectModel(RpClump* newClump, std::uint16_t modelID)
618623
}
619624
}
620625

621-
// Destroy old RwObject
622-
// RwObject from original interface after type conversion
623-
CBaseModelInfoSAInterface* originalInterface = pModelInfo->GetOriginalInterface();
624-
if (originalInterface && originalInterface->pRwObject)
625-
{
626-
originalInterface->DeleteRwObject();
627-
628-
// If the originalInterface has an existing RwObject, it points to the same one as copyCurrentModelInterface
629-
copyCurrentModelInterface->pRwObject = nullptr;
630-
}
631-
632-
// The user can convert the same model multiple times, but its original model interface is saved only once,
633-
// so we remove the RwObject and the interface created during the last conversion
634-
CBaseModelInfoSAInterface* lastConversionInterface = pModelInfo->GetLastConversionInterface();
635-
if (lastConversionInterface)
636-
{
637-
if (lastConversionInterface->pRwObject == copyCurrentModelInterface->pRwObject)
638-
copyCurrentModelInterface->pRwObject = nullptr;
639-
640-
lastConversionInterface->DeleteRwObject();
641-
delete lastConversionInterface;
642-
643-
pModelInfo->SetLastConversionInterface(nullptr);
644-
}
645-
646-
// Delete old RwObject (after setting the new one)
647-
if (copyCurrentModelInterface)
648-
{
649-
// Update 2dfx counter
650-
RwObject* object = copyCurrentModelInterface->pRwObject;
651-
if (object)
652-
{
653-
if (object->type == RP_TYPE_ATOMIC)
654-
currentModelInterface->ucNumOf2DEffects -= RpGeometryGet2dFxCount(reinterpret_cast<RpAtomic*>(object)->geometry);
655-
else if (object->type == RP_TYPE_CLUMP)
656-
{
657-
RpAtomic* atomic = Get2DEffectAtomic(reinterpret_cast<RpClump*>(object));
658-
if (atomic)
659-
currentModelInterface->ucNumOf2DEffects -= RpGeometryGet2dFxCount(atomic->geometry);
660-
}
661-
}
662-
663-
copyCurrentModelInterface->DeleteRwObject();
664-
delete copyCurrentModelInterface;
665-
}
666-
626+
// Remove extra ref
627+
if (extraRefAdded)
628+
CTxdStore_RemoveRef(currentModelInterface->usTextureDictionary);
629+
667630
return true;
668631
}
669632

win-create-projects.bat

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
@echo off
22

3-
rem Update CEF eventually
4-
utils\premake5.exe install_cef
53

6-
rem Update Unifont
7-
utils\premake5.exe install_unifont
8-
9-
rem Update discord-rpc
10-
utils\premake5.exe install_discord
114

125
rem Generate solutions
136
utils\premake5.exe vs2022

0 commit comments

Comments
 (0)