Skip to content
Permalink
Browse files

Remove debugging code from 4a1aadf

Anim crashes have disappeared after disabling the IFP unloading code. We don't need the Hardware breakpoints anymore since the crashes won't occur.
  • Loading branch information...
codenulls committed Aug 10, 2019
1 parent 970bd8f commit 2fdf9a4a5398343b0a743836a33f4b2cf9eeb1d9
@@ -50,8 +50,6 @@ unsigned long CMultiplayerSA::ADDR_GotFocus;

unsigned long CMultiplayerSA::FUNC_CPlayerInfoBase;

std::array<unsigned int, 3> CMultiplayerSA::arrGroupsToProtect = {{ANIM_GROUP_BBBAT_1, ANIM_GROUP_MUSCULAR, ANIM_GROUP_SWORD_1}};

#define HOOKPOS_FxManager_CreateFxSystem 0x4A9BE0
#define HOOKPOS_FxManager_DestroyFxSystem 0x4A9810

@@ -288,11 +288,10 @@ class CMultiplayerSA : public CMultiplayer
DWORD GetLastStaticAnimationID() { return m_dwLastStaticAnimID; }
DWORD GetLastAnimArrayAddress() { return m_dwLastAnimArrayAddress; }

CVector m_vecAkimboTarget;
bool m_bAkimboTargetUp;
static char* ms_PlayerImgCachePtr;
static std::array<unsigned int, 3> arrGroupsToProtect;
bool m_bBadDrivebyHitboxesDisabled;
CVector m_vecAkimboTarget;
bool m_bAkimboTargetUp;
static char* ms_PlayerImgCachePtr;
bool m_bBadDrivebyHitboxesDisabled;

private:
bool m_bSuspensionEnabled;
@@ -13,7 +13,6 @@
#include "../game_sa/CTasksSA.h"
#include "../game_sa/CAnimBlendSequenceSA.h"
#include "../game_sa/CAnimBlendHierarchySA.h"
#include "../game_sa/CAnimBlendAssocGroupSA.h"

extern CCoreInterface* g_pCore;

@@ -1466,10 +1465,10 @@ void OnMY_CAnimBlendNode_GetCurrentTranslation(CAnimBlendNodeSAInterface* pInter
// Crash will occur at offset 0xCFCD6
OnCrashAverted(32);
CAnimBlendAssociationSAInterface* pAnimAssoc = pInterface->pAnimBlendAssociation;
CAnimBlendSequenceSAInterface* pAnimSequence = pInterface->pAnimSequence;
CAnimBlendHierarchySAInterface* pAnimHierarchy = pAnimAssoc->pAnimHierarchy;
CAnimBlendSequenceSAInterface* pAnimSequence = pInterface->pAnimSequence;
CAnimBlendHierarchySAInterface* pAnimHierarchy = pAnimAssoc->pAnimHierarchy;

bool bSequenceExistsInHierarchy = false;
bool bSequenceExistsInHierarchy = false;
CAnimBlendSequenceSAInterface* pAnimHierSequence = pAnimHierarchy->pSequences;
for (int i = 0; i < pAnimHierarchy->usNumSequences; i++)
{
@@ -1482,12 +1481,13 @@ void OnMY_CAnimBlendNode_GetCurrentTranslation(CAnimBlendNodeSAInterface* pInter
}

LogEvent(588, "GetCurrentTranslation", "Incorrect endKeyFrameIndex",
SString("m_endKeyFrameId = %d | pAnimAssoc = %p | GroupID = %d | AnimID = %d | \
SString("m_endKeyFrameId = %d | pAnimAssoc = %p | GroupID = %d | AnimID = %d | \
pAnimSeq = %p | BoneID = %d | BoneHash = %u | \
pAnimHier = %p | HierHash = %u | SequenceExistsInHierarchy: %s",
pInterface->m_endKeyFrameId, pAnimAssoc, pAnimAssoc->sAnimGroup, pAnimAssoc->sAnimID, pAnimSequence, pAnimSequence->m_boneId,
pAnimSequence->m_hash, pAnimHierarchy, pAnimHierarchy->uiHashKey, bSequenceExistsInHierarchy ? "Yes" : "No"),
588);
pInterface->m_endKeyFrameId, pAnimAssoc, pAnimAssoc->sAnimGroup, pAnimAssoc->sAnimID,
pAnimSequence, pAnimSequence->m_boneId, pAnimSequence->m_hash, pAnimHierarchy,
pAnimHierarchy->uiHashKey, bSequenceExistsInHierarchy ? "Yes" : "No"), 588);

}

// Hook info
@@ -1523,66 +1523,6 @@ void _declspec(naked) HOOK_CAnimBlendNode_GetCurrentTranslation()
}
}

//////////////////////////////////////////////////////////////////////////////////////////
//
// CAnimManager_CreateAnimAssocGroups
//
// Protect `pAssociationsArray` member of specific anim groups (CAnimBlendAssocGroupSAInterface)
// from corruption by placing a WRITE operation breakpoint on its address.
//
//////////////////////////////////////////////////////////////////////////////////////////
void __cdecl OnMY_CAnimManager_CreateAnimAssocGroups_Protect(CAnimBlendAssocGroupSAInterface* pGroupInterface)
{
static std::set<unsigned int> setOfGroupBreakpointsAdded;

void* ppAssociationsArray = reinterpret_cast<void*>(&pGroupInterface->pAssociationsArray);
for (auto groupID : CMultiplayerSA::arrGroupsToProtect)
{
if (pGroupInterface->groupID == groupID && !MapContains(setOfGroupBreakpointsAdded, groupID))
{
HANDLE mainThread = OpenThread(THREAD_ALL_ACCESS, TRUE, SharedUtil::GetMainThreadId());
assert(mainThread != NULL);

SetHardwareBreakpoint(mainThread, HWBRK_TYPE_WRITE, HWBRK_SIZE_4, ppAssociationsArray);

CloseHandle(mainThread);

setOfGroupBreakpointsAdded.insert(groupID);

LogEvent(511, "Breakpoint", "Hardware Breakpoint set on WRITE access",
SString("groupID: %u | pGroupInterface: %#.8x, ppAssociationsArray = %#.8x | pAssociationsArray: %p", groupID, pGroupInterface,
ppAssociationsArray, pGroupInterface->pAssociationsArray),
511);
return;
}
}

LogEvent(512, "GroupLoaded", "Anim group loaded",
SString("groupID: %u | pGroupInterface: %#.8x, ppAssociationsArray = %#.8x | pAssociationsArray: %p", pGroupInterface->groupID, pGroupInterface,
ppAssociationsArray, pGroupInterface->pAssociationsArray),
512);
}

// Hook info
#define HOOKPOS_CAnimManager_CreateAnimAssocGroups_Protect 0x4D3DAD
#define HOOKSIZE_CAnimManager_CreateAnimAssocGroups_Protect 6
DWORD RETURN_CAnimManager_CreateAnimAssocGroups_Protect = 0x4D3DB3;
void _declspec(naked) HOOK_CAnimManager_CreateAnimAssocGroups_Protect()
{
_asm
{
pushad
add eax, esi
push eax
call OnMY_CAnimManager_CreateAnimAssocGroups_Protect
add esp, 0x4
popad

mov ecx, [esi + eax + 8]
xor edi, edi
jmp RETURN_CAnimManager_CreateAnimAssocGroups_Protect
}
}

//////////////////////////////////////////////////////////////////////////////////////////
//
@@ -1625,6 +1565,8 @@ void _declspec(naked) HOOK_CStreaming_AreAnimsUsedByRequestedModels()

//////////////////////////////////////////////////////////////////////////////////////////
//
=======
>>>>>>> parent of 4a1aadf6d... Revert 48f2c99c9bc511a3ea8473371f8b59ad933a21eb Debugging code for anim crashes
// Setup hooks for CrashFixHacks
//
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1668,7 +1610,6 @@ void CMultiplayerSA::InitHooks_CrashFixHacks()
EZHookInstallChecked(CVolumetricShadowMgr_Update);
EZHookInstallChecked(CAnimManager_CreateAnimAssocGroups);
EZHookInstall(CAnimBlendNode_GetCurrentTranslation);
EZHookInstall(CAnimManager_CreateAnimAssocGroups_Protect);
EZHookInstall(CStreaming_AreAnimsUsedByRequestedModels);
EZHookInstall(CTaskComplexCarSlowBeDraggedOut_CreateFirstSubTask);
EZHookInstallChecked(printf);
@@ -547,46 +547,6 @@ void _declspec(naked) HOOK_CTaskSimpleRunNamedAnimDestructor()
}
}

void _cdecl OnCAnimBlendAssocGroupDestructor(CAnimBlendAssocGroupSAInterface* pGroupInterface)
{
for (auto groupID : CMultiplayerSA::arrGroupsToProtect)
{
if (pGroupInterface->groupID == groupID)
{
void* ppAssociationsArray = reinterpret_cast<void*>(&pGroupInterface->pAssociationsArray);
LogEvent(519, "groupUnload", "Unloading anim group",
SString("groupID: %u | pGroupInterface: %#.8x, ppAssociationsArray = %#.8x | pAssociationsArray: %p", groupID, pGroupInterface,
ppAssociationsArray, pGroupInterface->pAssociationsArray),
519);

// crash it to get the stack
void* pPointer = nullptr;
assert(pPointer != nullptr);
}
}
}

// Hook info
#define HOOKPOS_CAnimBlendAssocGroupDestructor 0x4CE1D0
#define HOOKSIZE_CAnimBlendAssocGroupDestructor 6
DWORD RETURN_CAnimBlendAssocGroupDestructor = 0x4CE1D6;
void _declspec(naked) HOOK_CAnimBlendAssocGroupDestructor()
{
_asm
{
pushad
push ecx
call OnCAnimBlendAssocGroupDestructor
add esp, 0x4
popad

push esi
mov esi, ecx
mov ecx, [esi + 0x4]
jmp RETURN_CAnimBlendAssocGroupDestructor
}
}

//////////////////////////////////////////////////////////////////////////////////////////
//
// Set handlers
@@ -634,7 +594,6 @@ void CMultiplayerSA::SetGameRunNamedAnimDestructorHandler(GameRunNamedAnimDestru
//////////////////////////////////////////////////////////////////////////////////////////
void CMultiplayerSA::InitHooks_HookDestructors()
{
EZHookInstall(CAnimBlendAssocGroupDestructor);
EZHookInstall(CTaskSimpleRunNamedAnimDestructor);
EZHookInstall(CObjectDestructor);
EZHookInstall(CVehicleDestructor);
@@ -39,7 +39,6 @@
#include "..\game_sa\CEntitySA.h"
#include "..\game_sa\CBuildingSA.h"
#include "..\game_sa\CPedSA.h"
#include "..\game_sa\CAnimBlendAssocGroupSA.h"
#include "..\game_sa\common.h"
#include "..\core\CCrashDumpWriter.h"

1 comment on commit 2fdf9a4

@Dutchman101

This comment has been minimized.

Copy link
Contributor

commented on 2fdf9a4 Aug 10, 2019

some background on continuing to prevent unloading:

  • it stops a few common animation crashes (such as the getGroupID crash that saml1er has been trying to debug and fix for almost a year)
  • MTA was trying to play (player movement) animations from a block that SA had previously unloaded, resulting in a chance to crash. Crashfix Misc13 can fire, but fail to avert it.

To-do:

  • search MTA code which is related to playing tasks and add sanity checks there if they don't already exist.. check if anims/blocks are loaded before attempting to play them.

when unloading was initially disabled, it was because of the debugging code breakpoints getting hit prematurely (preventing the collection of dumps with useful info) when GTA decided to unload anims.
now while it was disabled, the crashes stopped, so the debugging code was useless again - we only learned what is written in the To-do.

GTA unloads anims and anim blocks when memory usage is high and there are no references to them at all. The effect of unloading them is barely noticable in memory usage, as @saml1er confirmed.
So disabling it until we can ensure MTA doesn't mishandle unloaded anims should be no problem.

Please sign in to comment.
You can’t perform that action at this time.