iw4x-client/src/Components/Modules/AssetHandler.cpp

159 lines
3.4 KiB
C++
Raw Normal View History

2015-12-28 20:52:31 -05:00
#include "..\..\STDInclude.hpp"
2015-12-23 16:21:03 -05:00
namespace Components
{
bool AssetHandler::BypassState = false;
std::map<Game::XAssetType, AssetHandler::Callback> AssetHandler::TypeCallbacks;
2015-12-25 20:51:58 -05:00
std::vector<AssetHandler::RestrictCallback> AssetHandler::RestrictCallbacks;
2015-12-23 16:21:03 -05:00
2015-12-28 19:45:04 -05:00
std::map<void*, void*> AssetHandler::Relocations;
2015-12-23 16:21:03 -05:00
Game::XAssetHeader AssetHandler::FindAsset(Game::XAssetType type, const char* filename)
{
2015-12-23 21:26:46 -05:00
Game::XAssetHeader header = { 0 };
2015-12-23 16:21:03 -05:00
2015-12-23 21:26:46 -05:00
// Allow call DB_FindXAssetHeader within the hook
2015-12-23 16:21:03 -05:00
AssetHandler::BypassState = true;
if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end())
{
header = AssetHandler::TypeCallbacks[type](type, filename);
}
2015-12-23 21:26:46 -05:00
// Disallow calling DB_FindXAssetHeader ;)
2015-12-23 16:21:03 -05:00
AssetHandler::BypassState = false;
return header;
}
void __declspec(naked) AssetHandler::FindAssetStub()
{
__asm
{
push ecx
push ebx
push ebp
push esi
push edi
// Check if custom handler should be bypassed
xor eax, eax
mov al, AssetHandler::BypassState
test al, al
jnz finishOriginal
mov ecx, [esp + 18h] // Asset type
mov ebx, [esp + 1Ch] // Filename
push ebx
push ecx
call AssetHandler::FindAsset
add esp, 8h
test eax, eax
jnz finishFound
finishOriginal:
// Asset not found using custom handlers, redirect to DB_FindXAssetHeader
mov ebx, ds:6D7190h // InterlockedDecrement
mov eax, 40793Bh
jmp eax
finishFound:
pop edi
pop esi
pop ebp
pop ebx
pop ecx
retn
}
}
2015-12-25 20:51:58 -05:00
bool AssetHandler::IsAssetEligible(Game::XAssetType type, Game::XAssetHeader *asset)
{
const char* name = Game::DB_GetXAssetNameHandlers[type](asset);
if (!name) return false;
for (auto callback : AssetHandler::RestrictCallbacks)
{
if (!callback(type, *asset, name))
{
return false;
}
}
return true;
}
void __declspec(naked) AssetHandler::AddAssetStub()
{
__asm
{
push [esp + 8]
push [esp + 8]
call AssetHandler::IsAssetEligible
add esp, 08h
test al, al
jz doNotLoad
mov eax, [esp + 8]
sub esp, 14h
mov ecx, 5BB657h
jmp ecx
doNotLoad:
mov eax, [esp + 8]
retn
}
}
2015-12-26 08:27:34 -05:00
void AssetHandler::OnFind(Game::XAssetType type, AssetHandler::Callback callback)
2015-12-23 16:21:03 -05:00
{
AssetHandler::TypeCallbacks[type] = callback;
}
2015-12-26 08:27:34 -05:00
void AssetHandler::OnLoad(RestrictCallback callback)
2015-12-25 20:51:58 -05:00
{
AssetHandler::RestrictCallbacks.push_back(callback);
}
2015-12-28 19:45:04 -05:00
void AssetHandler::Relocate(void* start, void* to, DWORD size)
{
for (DWORD i = 0; i < size; i += 4)
{
AssetHandler::Relocations[reinterpret_cast<char*>(start) + i] = reinterpret_cast<char*>(to) + i;
}
}
void AssetHandler::OffsetToAlias(FastFiles::Offset* offset)
{
offset->fullPointer = *reinterpret_cast<void**>((*Game::g_streamBlocks)[offset->GetDecrementedStream()].data + offset->GetDecrementedPointer());
if (AssetHandler::Relocations.find(offset->fullPointer) != AssetHandler::Relocations.end())
{
offset->fullPointer = AssetHandler::Relocations[offset->fullPointer];
}
}
2015-12-23 16:21:03 -05:00
AssetHandler::AssetHandler()
{
2015-12-28 19:45:04 -05:00
// DB_FindXAssetHeader
2015-12-23 16:21:03 -05:00
Utils::Hook(Game::DB_FindXAssetHeader, AssetHandler::FindAssetStub).Install()->Quick();
2015-12-25 20:51:58 -05:00
2015-12-28 19:45:04 -05:00
// DB_ConvertOffsetToAlias
Utils::Hook(0x4FDFA0, AssetHandler::OffsetToAlias, HOOK_JUMP).Install()->Quick();
// DB_AddXAsset
2015-12-25 20:51:58 -05:00
Utils::Hook(0x5BB650, AssetHandler::AddAssetStub, HOOK_JUMP).Install()->Quick();
2015-12-23 16:21:03 -05:00
}
AssetHandler::~AssetHandler()
{
AssetHandler::TypeCallbacks.clear();
}
}