Merge branch 'implement-codo-maps' into 'develop'

Move back to develop, as the unstable part is done

Even though this still isn't done, the unstable part is done. The only thing left to do is to rewrite the remaining code step by step, but this can be done in develop as well
This commit is contained in:
momo5502 2016-09-22 08:30:49 +02:00
commit 6310ba9315
24 changed files with 1159 additions and 80 deletions

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit c44ca26fe89ed8a81d3ee475a2ccc1797141dbce
Subproject commit 4f379f81cef4dd8e005fd0bcc9199bf842fc35d4

2
deps/zlib vendored

@ -1 +1 @@
Subproject commit 70a8763b7187f2536ce7fe4d399ce9a79c9faf7c
Subproject commit 9852c209ac49c0d8d1192e46115d7c37d4344bbd

View File

@ -89,6 +89,7 @@ namespace Components
void AntiCheat::CrashClient()
{
#ifdef DEBUG_DETECTIONS
Logger::Flush();
MessageBoxA(0, "Check the log for more information!", "AntiCheat triggered", MB_ICONERROR);
ExitProcess(0xFFFFFFFF);
#else
@ -217,8 +218,8 @@ namespace Components
if (lastCheck) count = 0;
else ++count;
// If there was no check within the last 120 seconds, crash!
if ((milliseconds > 1000 * 25) && ((lastCheck && (milliseconds - lastCheck) > 1000 * 40) || count > 1))
// If there was no check within the last 40 seconds, crash!
if ((milliseconds > 1000 * 40) && ((lastCheck && (milliseconds - lastCheck) > 1000 * 40) || count > 1))
{
#ifdef DEBUG_DETECTIONS
Logger::Print("AntiCheat: Integrity check failed");
@ -260,7 +261,7 @@ namespace Components
void AntiCheat::Frame()
{
// Perform check only every 30 seconds
// Perform check only every 10 seconds
if (AntiCheat::LastCheck && (Game::Sys_Milliseconds() - AntiCheat::LastCheck) < 1000 * 10) return;
AntiCheat::LastCheck = Game::Sys_Milliseconds();

View File

@ -50,16 +50,19 @@ namespace Components
{
Game::XAssetHeader header = { 0 };
// Allow call DB_FindXAssetHeader within the hook
AssetHandler::BypassState = true;
if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end())
if (filename)
{
header = AssetHandler::TypeCallbacks[type](type, filename);
}
// Allow call DB_FindXAssetHeader within the hook
AssetHandler::BypassState = true;
// Disallow calling DB_FindXAssetHeader ;)
AssetHandler::BypassState = false;
if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end())
{
header = AssetHandler::TypeCallbacks[type](type, filename);
}
// Disallow calling DB_FindXAssetHeader ;)
AssetHandler::BypassState = false;
}
return header;
}
@ -155,6 +158,11 @@ namespace Components
AssetHandler::RestrictSignal.connect(callback);
}
void AssetHandler::ClearRelocations()
{
AssetHandler::Relocations.clear();
}
void AssetHandler::Relocate(void* start, void* to, DWORD size)
{
for (DWORD i = 0; i < size; i += 4)
@ -167,12 +175,14 @@ namespace Components
void AssetHandler::OffsetToAlias(Utils::Stream::Offset* offset)
{
// Same here, reinterpret the value, as we're operating inside the game's environment
offset->pointer = *reinterpret_cast<void**>((*Game::g_streamBlocks)[offset->GetUnpackedBlock()].data + offset->GetUnpackedOffset());
void* pointer = (*Game::g_streamBlocks)[offset->GetUnpackedBlock()].data + offset->GetUnpackedOffset();
if (AssetHandler::Relocations.find(offset->pointer) != AssetHandler::Relocations.end())
if (AssetHandler::Relocations.find(pointer) != AssetHandler::Relocations.end())
{
offset->pointer = AssetHandler::Relocations[offset->pointer];
pointer = AssetHandler::Relocations[pointer];
}
offset->pointer = *reinterpret_cast<void**>(pointer);
}
void AssetHandler::ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder)
@ -285,6 +295,7 @@ namespace Components
delete i->second;
}
AssetHandler::Relocations.clear();
AssetHandler::AssetInterfaces.clear();
AssetHandler::RestrictSignal.clear();
AssetHandler::TypeCallbacks.clear();

View File

@ -27,8 +27,13 @@ namespace Components
static void OnFind(Game::XAssetType type, Callback* callback);
static void OnLoad(RestrictCallback* callback);
static void ClearRelocations();
static void Relocate(void* start, void* to, DWORD size = 4);
static void Relocate(DWORD start, DWORD size, DWORD to) {
Relocate((void*)start, (void*)to, size);
}
static void ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder);
static void ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder);

View File

@ -532,7 +532,7 @@ namespace Components
"\r\n", mimeType.data(), buffer.size());
mg_send(nc, buffer.data(), static_cast<int>(buffer.size()));
}
}
else
{
mg_printf(nc,

View File

@ -154,6 +154,12 @@ namespace Components
}
Zones::InstallPatches(*version);
// TODO: Ugly hotpatch, beautify that!
// if (*version >= 316)
// {
// *version = XFILE_VERSION;
// }
}
FastFiles::FastFiles()

View File

@ -2,30 +2,45 @@
namespace Components
{
FileSystem::File::File(std::string file) : Name(file), Handle(0)
void FileSystem::File::Read()
{
char* buffer = nullptr;
int size = Game::FS_ReadFile(this->FilePath.data(), &buffer);
this->Buffer.clear();
if (size >= 0)
{
this->Buffer.append(buffer, size);
Game::FS_FreeFile(buffer);
}
}
FileSystem::FileReader::FileReader(std::string file) : Name(file), Handle(0)
{
this->Size = Game::FS_FOpenFileRead(this->Name.data(), &this->Handle, 0);
}
FileSystem::File::~File()
FileSystem::FileReader::~FileReader()
{
if (this->Exists())
if (this->Exists() && this->Handle)
{
Game::FS_FCloseFile(this->Handle);
}
}
bool FileSystem::File::Exists()
bool FileSystem::FileReader::Exists()
{
return (this->Size > 0);
}
std::string FileSystem::File::GetName()
std::string FileSystem::FileReader::GetName()
{
return this->Name;
}
std::string FileSystem::File::GetBuffer()
std::string FileSystem::FileReader::GetBuffer()
{
Utils::Memory::Allocator allocator;
if (!this->Exists()) return std::string();
@ -34,7 +49,7 @@ namespace Components
this->Seek(0, FS_SEEK_SET);
char* buffer = allocator.AllocateArray<char>(this->Size);
if (!FileSystem::File::Read(buffer, this->Size))
if (!this->Read(buffer, this->Size))
{
this->Seek(position, FS_SEEK_SET);
return std::string();
@ -45,7 +60,7 @@ namespace Components
return std::string(buffer, this->Size);
}
bool FileSystem::File::Read(void* buffer, size_t size)
bool FileSystem::FileReader::Read(void* buffer, size_t size)
{
if (!this->Exists() || static_cast<size_t>(this->Size) < size || Game::FS_Read(buffer, size, this->Handle) != static_cast<int>(size))
{
@ -55,7 +70,7 @@ namespace Components
return true;
}
void FileSystem::File::Seek(int offset, int origin)
void FileSystem::FileReader::Seek(int offset, int origin)
{
if (this->Exists())
{

View File

@ -4,12 +4,29 @@ namespace Components
{
public:
class File
class File
{
public:
File() {};
File(std::string file) : FilePath(file) { this->Read(); };
bool Exists() { return !this->Buffer.empty(); };
std::string GetName() { return this->FilePath; };
std::string& GetBuffer() { return this->Buffer; };
private:
std::string FilePath;
std::string Buffer;
void Read();
};
class FileReader
{
public:
File() : Size(-1), Name(), Handle(0) {};
File(std::string file);
~File();
FileReader() : Size(-1), Name(), Handle(0) {};
FileReader(std::string file);
~FileReader();
bool Exists();
std::string GetName();

View File

@ -83,6 +83,21 @@ namespace Components
return buffer;
}
void Logger::Flush()
{
// if (!Game::Sys_IsMainThread())
// {
// while (!Logger::MessageQueue.empty())
// {
// std::this_thread::sleep_for(10ms);
// }
// }
// else
{
Logger::Frame();
}
}
void Logger::Frame()
{
std::lock_guard<std::mutex> _(Logger::MessageMutex);
@ -300,5 +315,11 @@ namespace Components
Logger::MessageMutex.lock();
Logger::MessageQueue.clear();
Logger::MessageMutex.unlock();
// Flush the console log
if (int fh = *reinterpret_cast<int*>(0x1AD8F28))
{
Game::FS_FCloseFile(fh);
}
}
}

View File

@ -23,6 +23,8 @@ namespace Components
static void PipeOutput(void(*callback)(std::string));
static void Flush();
private:
static std::mutex MessageMutex;
static std::vector<std::string> MessageQueue;

View File

@ -84,6 +84,24 @@ namespace Components
return;
}
if (type == Game::XAssetType::ASSET_TYPE_WEAPON)
{
if (!strstr(name.data(), "_mp") && name != "none" && name != "destructible_car")
{
*restrict = true;
return;
}
}
if (type == Game::XAssetType::ASSET_TYPE_STRINGTABLE)
{
if (FastFiles::Current() == "mp_cross_fire")
{
*restrict = true;
return;
}
}
if (type == Game::XAssetType::ASSET_TYPE_MAP_ENTS)
{
static std::string mapEntities;
@ -106,7 +124,10 @@ namespace Components
if (_strnicmp("mp_", mapname, 3))
{
format = "maps/%s.d3dbsp";
}
if (_strnicmp("mp_", mapname, 3) || mapname == "mp_nuked"s || mapname == "mp_bloc"s || mapname == "mp_cargoship"s || mapname == "mp_cross_fire"s)
{
// Adjust pointer to GameMap_Data
Utils::Hook::Set<Game::GameMap_Data**>(0x4D90B7, &(Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAME_MAP_SP].gameMapSP[0].data));
}
@ -137,6 +158,11 @@ namespace Components
Maps::DependencyList[expression] = zone;
}
int Maps::IgnoreEntityStub(const char* entity)
{
return (Utils::String::StartsWith(entity, "dyn_") || Utils::String::StartsWith(entity, "node_") || Utils::String::StartsWith(entity, "actor_"));
}
void Maps::ReallocateEntryPool()
{
Assert_Size(Game::XAssetEntry, 16);
@ -196,6 +222,9 @@ namespace Components
// Intercept map zone loading
Utils::Hook(0x42C2AF, Maps::LoadMapZones, HOOK_CALL).Install()->Quick();
// Ignore SP entities
Utils::Hook(0x444810, Maps::IgnoreEntityStub, HOOK_JUMP).Install()->Quick();
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAME_MAP_SP, 1);
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, 7168);
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700);
@ -218,6 +247,11 @@ namespace Components
//Maps::AddDependency("gulag", "mp_subbase");
//Maps::AddDependency("invasion", "mp_rust");
Maps::AddDependency("co_hunted", "mp_storm");
Maps::AddDependency("mp_nuked", "iw4x_dependencies_mp");
Maps::AddDependency("mp_bloc", "iw4x_dependencies_mp");
Maps::AddDependency("mp_bloc", "iw4x_dependencies_mp");
Maps::AddDependency("mp_cargoship", "iw4x_dependencies_mp");
Maps::AddDependency("mp_cross_fire", "iw4x_dependencies_mp");
Maps::AddDependency("^(?!mp_).*", "iw4x_dependencies_mp"); // All maps not starting with "mp_"
}

View File

@ -24,6 +24,8 @@ namespace Components
static void OverrideMapEnts(Game::MapEnts* ents);
static int IgnoreEntityStub(const char* entity);
void ReallocateEntryPool();
};
}

View File

@ -45,7 +45,7 @@ namespace Components
Game::Script_SetupTokens(script, reinterpret_cast<char*>(0x797F80));
script->punctuations = reinterpret_cast<Game::punctuation_t*>(0x797F80);
memcpy(script->buffer, buffer.data(), script->length + 1);
std::memcpy(script->buffer, buffer.data(), script->length + 1);
script->length = Game::Script_CleanString(script->buffer);

View File

@ -3,7 +3,7 @@
namespace Components
{
std::map<void*, IUnknown*> ModelSurfs::BufferMap;
std::map<void*, Game::CModelAllocData*> ModelSurfs::AllocMap;
std::map<std::string, Game::CModelAllocData*> ModelSurfs::AllocMap;
IUnknown* ModelSurfs::GetBuffer(void* buffer)
{
@ -38,7 +38,7 @@ namespace Components
Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(std::string name)
{
Utils::Memory::Allocator allocator;
FileSystem::File model(fmt::sprintf("models/%s", name.data()));
FileSystem::FileReader model(fmt::sprintf("models/%s", name.data()));
if (!model.Exists())
{
@ -79,7 +79,7 @@ namespace Components
Game::CModelSectionHeader* section = &header.sectionHeader[i];
for (int j = section->fixupStart; j < section->fixupStart + section->fixupCount; ++j)
{
unsigned int fixup = fixups[i];
unsigned int fixup = fixups[j];
*reinterpret_cast<DWORD*>(reinterpret_cast<char*>(section->buffer) + (fixup >> 3)) += reinterpret_cast<DWORD>(header.sectionHeader[fixup & 3].buffer);
}
}
@ -90,24 +90,26 @@ namespace Components
allocationData->indexBuffer = header.sectionHeader[Game::SECTION_INDEX].buffer;
allocationData->vertexBuffer = header.sectionHeader[Game::SECTION_VERTEX].buffer;
ModelSurfs::AllocMap[allocationData->vertexBuffer] = allocationData;
*reinterpret_cast<void**>(reinterpret_cast<char*>(allocationData->mainArray) + 44) = allocationData;
Assert_Size(Game::XSurface, 64);
Game::XModelSurfs* modelSurfs = reinterpret_cast<Game::XModelSurfs*>(allocationData->mainArray);
Game::XSurface* tempSurfaces = allocator.AllocateArray<Game::XSurface>(modelSurfs->numSurfaces);
char* surfaceData = reinterpret_cast<char*>(modelSurfs->surfaces);
ModelSurfs::AllocMap[modelSurfs->name] = allocationData;
*reinterpret_cast<void**>(reinterpret_cast<char*>(allocationData->mainArray) + 44) = allocationData;
for (int i = 0; i < modelSurfs->numSurfaces; ++i)
{
memcpy(&tempSurfaces[i], surfaceData + (i * 84), 12);
memcpy(&tempSurfaces[i].indexBuffer, surfaceData + (i * 84) + 16, 20);
memcpy(&tempSurfaces[i].numCT, surfaceData + (i * 84) + 40, 8);
memcpy(&tempSurfaces[i].pad5, surfaceData + (i * 84) + 52, 24);
char* source = &surfaceData[i * 84];
std::memcpy(&tempSurfaces[i], source, 12);
std::memcpy(&tempSurfaces[i].indexBuffer, source + 16, 20);
std::memcpy(&tempSurfaces[i].numCT, source + 40, 8);
std::memcpy(&tempSurfaces[i].something, source + 52, 24);
tempSurfaces[i].streamHandle = 0xFF; // Fake handle for buffer interception
}
memcpy(surfaceData, tempSurfaces, 64 * modelSurfs->numSurfaces);
std::memcpy(surfaceData, tempSurfaces, 64 * modelSurfs->numSurfaces);
ModelSurfs::CreateBuffers(modelSurfs);
@ -117,8 +119,8 @@ namespace Components
bool ModelSurfs::LoadSurfaces(Game::XModel* model)
{
if (!model) return false;
bool changed = false;
bool changed = false;
short surfCount = 0;
for (char i = 0; i < model->numLods; ++i)
@ -129,16 +131,18 @@ namespace Components
{
Game::XModelSurfs* newSurfs = ModelSurfs::LoadXModelSurfaces(surfs->name);
surfs->surfaces = newSurfs->surfaces;
surfs->numSurfaces = newSurfs->numSurfaces;
surfs->surfaces = newSurfs->surfaces;
surfs->numSurfaces = newSurfs->numSurfaces;
model->lods[i].surfaces = newSurfs;
memcpy(model->lods[i].pad3, newSurfs->pad, 24);
model->lods[i].surfs = newSurfs->surfaces;
std::memcpy(model->lods[i].pad3, newSurfs->pad, 24);
short numSurfs = static_cast<short>(newSurfs->numSurfaces);
model->lods[i].someCount = numSurfs;
model->lods[i].someTotalCount = surfCount;
model->lods[i].numSurfs = numSurfs;
model->lods[i].maxSurfs = surfCount;
surfCount += numSurfs;
changed = true;
}
}
@ -147,11 +151,15 @@ namespace Components
void ModelSurfs::ReleaseModelSurf(Game::XAssetHeader header)
{
bool hasCustomSurface = false;
for (int i = 0; i < header.surfaces->numSurfaces && header.surfaces->surfaces; ++i)
{
Game::XSurface* surface = &header.surfaces->surfaces[i];
if (surface->streamHandle == 0xFF)
{
hasCustomSurface = true;
auto buffer = ModelSurfs::BufferMap.find(surface->indexBuffer);
if (buffer != ModelSurfs::BufferMap.end())
{
@ -165,17 +173,20 @@ namespace Components
buffer->second->Release();
ModelSurfs::BufferMap.erase(buffer);
}
}
}
auto allocData = ModelSurfs::AllocMap.find(surface->vertexBuffer);
if (allocData != ModelSurfs::AllocMap.end())
{
Utils::Memory::Free(allocData->second->indexBuffer);
Utils::Memory::Free(allocData->second->vertexBuffer);
Utils::Memory::Free(allocData->second->mainArray);
Utils::Memory::Free(allocData->second);
if (hasCustomSurface)
{
auto allocData = ModelSurfs::AllocMap.find(header.surfaces->name);
if (allocData != ModelSurfs::AllocMap.end())
{
Utils::Memory::FreeAlign(allocData->second->indexBuffer);
Utils::Memory::FreeAlign(allocData->second->vertexBuffer);
Utils::Memory::Free(allocData->second->mainArray);
Utils::Memory::Free(allocData->second);
ModelSurfs::AllocMap.erase(allocData);
}
ModelSurfs::AllocMap.erase(allocData);
}
}
}
@ -295,7 +306,7 @@ namespace Components
// Install hooks
Utils::Hook(0x47A6BD, ModelSurfs::XModelSurfsFixup, HOOK_CALL).Install()->Quick();
Utils::Hook(0x558F12, ModelSurfs::GetIndexBaseStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x5BC050, ModelSurfs::GetIndexBufferStub, HOOK_JUMP).Install()->Quick();
Utils::Hook(0x4B4DE0, ModelSurfs::GetIndexBufferStub, HOOK_JUMP).Install()->Quick();
Utils::Hook(0x558E70, ModelSurfs::GetIndexBufferStub2, HOOK_CALL).Install()->Quick();
Utils::Hook(0x5BC050, ModelSurfs::GetVertexBufferStub, HOOK_JUMP).Install()->Quick();
}

View File

@ -10,9 +10,9 @@ namespace Components
const char* GetName() { return "ModelSurfs"; };
#endif
private:
//private:
static std::map<void*, IUnknown*> BufferMap;
static std::map<void*, Game::CModelAllocData*> AllocMap;
static std::map<std::string, Game::CModelAllocData*> AllocMap;
static void ReleaseModelSurf(Game::XAssetHeader header);

View File

@ -88,7 +88,7 @@ namespace Components
size = Game::MSG_ReadBitsCompress(from, buffer, size);
if (size > 0x800) return 0;
memcpy(to, buffer, size);
std::memcpy(to, buffer, size);
return size;
}
@ -101,7 +101,7 @@ namespace Components
size = Game::MSG_ReadBitsCompress(from, buffer, size);
if (size > 0x20000) return 0;
memcpy(to, buffer, size);
std::memcpy(to, buffer, size);
return size;
}

View File

@ -2,16 +2,813 @@
namespace Components
{
int Zones::ZoneVersion;
int Zones::ZoneVersion;
Utils::Hook Zones::LoadFxElemDefHook;
Utils::Hook Zones::LoadFxElemDefArrayHook;
Utils::Hook Zones::LoadXModelLodInfoHook;
Utils::Hook Zones::LoadXModelHook;
Utils::Hook Zones::LoadXSurfaceArrayHook;
Utils::Hook Zones::LoadGameWorldSpHook;
Utils::Hook Zones::LoadPathDataHook;
Utils::Hook Zones::LoadVehicleDefHook;
Utils::Hook Zones::Loadsnd_alias_tArrayHook;
Utils::Hook Zones::LoadLoadedSoundHook;
Utils::Hook fxEffectLoadHook;
static char* fxEffectStringValue[64];
static int fxEffectIndex = 0;
void FxEffectLoadHookFunc(int a1, char* buffer, int len)
{
len /= 252;
int count = len;
len *= 260;
__asm
{
push len
push buffer
push a1
call fxEffectLoadHook.Original
add esp, 0Ch
}
fxEffectIndex = 0;
char* tempVar = new char[len];
for (int i = 0; i < count; i++)
{
AssetHandler::Relocate((DWORD)buffer + (260 * i), 252, (DWORD)buffer + (252 * i));
std::memcpy(tempVar + (252 * i), buffer + (260 * i), 252);
fxEffectStringValue[i] = *(char**)(buffer + (260 * i) + 256);
}
std::memcpy(buffer, tempVar, len);
delete[] tempVar;
}
bool Zones::LoadFxElemDefStub(bool atStreamStart, Game::FxElemDef* fxElem, int size)
{
if (fxElem->elemType == 3)
{
fxElem->elemType = 2;
}
else if (fxElem->elemType >= 5)
{
fxElem->elemType -= 2;
}
return Game::Load_Stream(atStreamStart, fxElem, size);
}
void Zones::LoadFxElemDefArrayStub(bool atStreamStart)
{
Game::Load_FxElemDef(atStreamStart);
*Game::varXString = &fxEffectStringValue[fxEffectIndex++];
Game::Load_XString(0);
}
bool Zones::LoadXModel(bool atStreamStart, char* xmodel, int size)
{
bool result = Game::Load_Stream(atStreamStart, xmodel, size);
int elSize = (Zones::ZoneVersion == VERSION_ALPHA2) ? 364 : 360;
Game::XModel model[2]; // Allocate 2 models, as we exceed the buffer
std::memcpy(model, xmodel, 36);
std::memcpy(&model->pad3[0x1C], &xmodel[44], 28);
for (int i = 0; i < 4; i++)
{
std::memcpy(&model->lods[i], &xmodel[72 + (i * 56)], 12);
std::memcpy(&model->lods[i].pad3, &xmodel[72 + (i * 56) + 16], 32);
std::memcpy(reinterpret_cast<char*>(&model) + (elSize - 4) - (i * 4), &xmodel[72 + (i * 56) + 12], 4);
}
std::memcpy(&model->lods[3].pad4[0], &xmodel[292], (elSize - 292 - 4)/*68*/);
std::memcpy(&model->physPreset, &xmodel[(elSize - 8)], 8);
model[1].name = reinterpret_cast<char*>(0xDEC0ADDE);
std::memcpy(xmodel, &model, elSize);
return result;
}
void Zones::LoadXModelLodInfo(int i)
{
int elSize = (Zones::ZoneVersion == VERSION_ALPHA2) ? 364 : 360;
*Game::varXString = reinterpret_cast<char**>(reinterpret_cast<char*>(*Game::varXModel) + (elSize - 4) - (4 * (4 - i)));
Game::Load_XString(false);
}
void __declspec(naked) Zones::LoadXModelLodInfoStub()
{
__asm
{
push edi
call Zones::LoadXModelLodInfo
pop edi
jmp Game::Load_XModelSurfsFixup
}
}
bool Zones::LoadXSurfaceArray(bool atStreamStart, char* buffer, int size)
{
size >>= 6;
int count = size;
size *= 84;
bool result = Game::Load_Stream(atStreamStart, buffer, size);
Utils::Memory::Allocator allocator;
Game::XSurface* tempSurfaces = allocator.AllocateArray<Game::XSurface>(count);
for (int i = 0; i < count; ++i)
{
char* source = &buffer[i * 84];
std::memcpy(&tempSurfaces[i], source, 12);
std::memcpy(&tempSurfaces[i].indexBuffer, source + 16, 20);
std::memcpy(&tempSurfaces[i].numCT, source + 40, 8);
std::memcpy(&tempSurfaces[i].something, source + 52, 24);
}
std::memcpy(buffer, tempSurfaces, sizeof(Game::XSurface) * count);
return result;
}
Utils::Hook loadWeaponDefHook;
void Load_WeaponDef_CodC(int /*doLoad*/)
{
// setup structures we use
DWORD varWeaponDef = *(DWORD*)0x112A9F4;//*(DWORD*)0x112AE14;
// and do the stuff
Game::Load_Stream(1, (void*)varWeaponDef, (Zones::ZoneVersion >= 318) ? 3156 : 3112);
Game::DB_PushStreamPos(3);
*Game::varXString = (char**)(varWeaponDef + 0);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 4);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 8);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 12);
Game::Load_XString(false);
*Game::varXModelPtr = (Game::XModel*)(varWeaponDef + 16);
Game::Load_XModelPtr(false);
for (int i = 0, offset = 20; i < 32; i++, offset += 4)
{
*Game::varXModelPtr = (Game::XModel*)(varWeaponDef + offset);
Game::Load_XModelPtr(false);
}
// 148
for (int offset = 148; offset <= 168; offset += 4)
{
*Game::varXModelPtr = (Game::XModel*)(varWeaponDef + offset);
Game::Load_XModelPtr(false);
}
// 172
// 32 scriptstrings, should not need to be loaded
// 236
*Game::varXString = (char**)(varWeaponDef + 236);
Game::Load_XStringArray(false, 48);
// 428
*Game::varXString = (char**)(varWeaponDef + 428);
Game::Load_XStringArray(false, 48);
// 620
*Game::varXString = (char**)(varWeaponDef + 620);
Game::Load_XStringArray(false, 48);
// 812
// 16 * 4 scriptstrings
// 972
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 972);;
Game::Load_FxEffectDefHandle(false);
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 976);
Game::Load_FxEffectDefHandle(false);
// 980
// 50 soundalias name references; up to and including 1180
for (int i = 0, offset = 980; i < 50; i++, offset += 4)
{
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + offset);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
}
if (Zones::ZoneVersion >= 318)
{
for (int i = 0, offset = 1184; i < 2; i++, offset += 4)
{
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + offset);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
}
varWeaponDef += 8; // to compensate for the 2 in between here
}
if (*(DWORD*)(varWeaponDef + 1184))
{
if (*(DWORD*)(varWeaponDef + 1184) == -1)
{
*(DWORD*)(varWeaponDef + 1184) = (DWORD)Game::DB_AllocStreamPos(3);
*Game::varsnd_alias_list_name = *(Game::snd_alias_list_t***)(varWeaponDef + 1184);
Game::Load_snd_alias_list_nameArray(true, 31);
}
else
{
// full usability requires ConvertOffsetToPointer here
}
}
if (*(DWORD*)(varWeaponDef + 1188))
{
if (*(DWORD*)(varWeaponDef + 1188) == -1)
{
*(DWORD*)(varWeaponDef + 1188) = (DWORD)Game::DB_AllocStreamPos(3);
*Game::varsnd_alias_list_name = *(Game::snd_alias_list_t***)(varWeaponDef + 1188);
Game::Load_snd_alias_list_nameArray(true, 31);
}
else
{
// full usability requires ConvertOffsetToPointer here
}
}
// 1192
for (int offset = 1192; offset <= 1204; offset += 4)
{
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + offset);
Game::Load_FxEffectDefHandle(false);
}
// 1208
static int matOffsets1[] = { 1208, 1212, 1428, 1432, 1436, 1440, 1444, 1448, 1456, 1464 };
for (int i = 0; i < sizeof(matOffsets1) / sizeof(int); i++)
{
*Game::varMaterialHandle = (Game::Material*)(varWeaponDef + matOffsets1[i]);
Game::Load_MaterialHandle(false);
}
*Game::varXString = (char**)(varWeaponDef + 1484);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 1492);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 1508);
Game::Load_XString(false);
for (int offset = 1764; offset <= 1776; offset += 4)
{
*Game::varMaterialHandle = (Game::Material*)(varWeaponDef + offset);
Game::Load_MaterialHandle(false);
}
*Game::varPhysCollmapPtr = (Game::PhysCollmap*)(varWeaponDef + 1964);
Game::Load_PhysCollmapPtr(0);
*Game::varXModelPtr = (Game::XModel*)(varWeaponDef + 2052);
Game::Load_XModelPtr(0);
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 2060);
Game::Load_FxEffectDefHandle(false);
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 2064);
Game::Load_FxEffectDefHandle(false);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2068);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2072);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 2336);
Game::Load_FxEffectDefHandle(false);
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 2340);
Game::Load_FxEffectDefHandle(false);
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 2368); // 2376
Game::Load_FxEffectDefHandle(false);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2372); // 2380
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
*Game::varXString = (char**)(varWeaponDef + 2548); // 2556
Game::Load_XString(false);
if (*(DWORD*)(varWeaponDef + 2556) == -1) // 2564
{
DWORD vec2 = (DWORD)Game::DB_AllocStreamPos(3);
*(DWORD*)(varWeaponDef + 2556) = vec2;
Game::Load_Stream(1, (void*)vec2, 8 * *(short*)(varWeaponDef + ((Zones::ZoneVersion >= 318) ? 3076 : 3040)));
}
*Game::varXString = (char**)(varWeaponDef + 2552);
Game::Load_XString(false);
if (*(DWORD*)(varWeaponDef + 2560) == -1)
{
DWORD vec2 = (DWORD)Game::DB_AllocStreamPos(3);
*(DWORD*)(varWeaponDef + 2560) = vec2;
Game::Load_Stream(1, (void*)vec2, 8 * *(short*)(varWeaponDef + ((Zones::ZoneVersion >= 318) ? 3078 : 3042)));
}
*Game::varXString = (char**)(varWeaponDef + 2640);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 2644);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 2676);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 2680);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 2804);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 2808);
Game::Load_XString(false);
*Game::varTracerDefPtr = (Game::TracerDef*)(varWeaponDef + 2812);
Game::Load_TracerDefPtr(false);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2840);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name); // 2848
*Game::varFxEffectDefHandle = (Game::FxEffectDef*)(varWeaponDef + 2844);
Game::Load_FxEffectDefHandle(false);
*Game::varXString = (char**)(varWeaponDef + 2848);
Game::Load_XString(false);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2864);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2868);
Game::Load_snd_alias_list_nameArray(false, 4);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2884);
Game::Load_snd_alias_list_nameArray(false, 4);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2900);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + 2904); // 2912
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
if (Zones::ZoneVersion >= 318)
{
for (int i = 0, offset = 2972; i < 6; i++, offset += 4)
{
*Game::varsnd_alias_list_name = (Game::snd_alias_list_t**)(varWeaponDef + offset);
Game::Load_SndAliasCustom(*Game::varsnd_alias_list_name);
}
varWeaponDef += (6 * 4);
varWeaponDef += 12;
}
else
{
}
*Game::varXString = (char**)(varWeaponDef + 2984);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 2996);
Game::Load_XString(false);
*Game::varXString = (char**)(varWeaponDef + 3000);
Game::Load_XString(false);
*Game::varMaterialHandle = (Game::Material*)(varWeaponDef + 3008);
Game::Load_MaterialHandle(false);
*Game::varMaterialHandle = (Game::Material*)(varWeaponDef + 3012);
Game::Load_MaterialHandle(false);
*Game::varMaterialHandle = (Game::Material*)(varWeaponDef + 3016);
Game::Load_MaterialHandle(false);
if (*(DWORD*)(varWeaponDef + 3044) == -1)
{
DWORD vec2 = (DWORD)Game::DB_AllocStreamPos(3);
*(DWORD*)(varWeaponDef + 3044) = vec2;
Game::Load_Stream(1, (void*)vec2, 8 * *(short*)(varWeaponDef + 3040));
}
if (*(DWORD*)(varWeaponDef + 3048) == -1)
{
DWORD vec2 = (DWORD)Game::DB_AllocStreamPos(3);
*(DWORD*)(varWeaponDef + 3048) = vec2;
Game::Load_Stream(1, (void*)vec2, 8 * *(short*)(varWeaponDef + 3042));
}
Game::DB_PopStreamPos();
}
bool Zones::LoadGameWorldSp(bool atStreamStart, char* buffer)
{
bool result = Game::Load_Stream(atStreamStart, buffer, 84);
Game::GameWorldSp world[2];
std::memcpy(&world, buffer, 44);
std::memcpy(&world[1], &buffer[44], 28);
std::memcpy(&world->vehicleTrack, &buffer[72], 12);
std::memcpy(buffer, world, 84);
return result;
}
Utils::Hook pathDataTailHook;
void PathDataTailHookFunc()
{
DWORD varStuff = *(DWORD*)0x112AD7C;
DWORD varThing;
if (*(DWORD*)(varStuff + 56))
{
*(DWORD*)(varStuff + 56) = (DWORD)Game::DB_AllocStreamPos(0);
varThing = *(DWORD*)(varStuff + 56);
Game::Load_Stream(1, (void*)varThing, *(DWORD*)(varStuff + 52));
}
if (*(DWORD*)(varStuff + 64))
{
*(DWORD*)(varStuff + 64) = (DWORD)Game::DB_AllocStreamPos(0);
varThing = *(DWORD*)(varStuff + 64);
Game::Load_Stream(1, (void*)varThing, *(DWORD*)(varStuff + 60));
}
if (*(DWORD*)(varStuff + 76))
{
*(DWORD*)(varStuff + 76) = (DWORD)Game::DB_AllocStreamPos(0);
varThing = *(DWORD*)(varStuff + 76);
Game::Load_Stream(1, (void*)varThing, *(DWORD*)(varStuff + 72));
}
}
bool Zones::Loadsnd_alias_tArray(bool atStreamStart, char* buffer, int len)
{
len /= 100;
int count = len;
len *= 108;
bool result = Game::Load_Stream(atStreamStart, buffer, len);
Utils::Memory::Allocator allocator;
Game::snd_alias_t* tempSounds = allocator.AllocateArray<Game::snd_alias_t>(count);
for (int i = 0; i < count; i++)
{
char* src = &buffer[i * 108];
std::memcpy(&tempSounds[i], src + 0, 60);
std::memcpy(&tempSounds[i].pad2[36], src + 68, 20);
std::memcpy(&tempSounds[i].pad2[56], src + 88, 20);
AssetHandler::Relocate(src + 0, buffer + (i * 100) + 0, 60);
AssetHandler::Relocate(src + 68, buffer + (i * 100) + 60, 20);
AssetHandler::Relocate(src + 88, buffer + (i * 100) + 80, 20);
}
std::memcpy(buffer, tempSounds, sizeof(Game::snd_alias_t) * count);
return result;
}
bool Zones::LoadLoadedSound(bool atStreamStart, char* buffer)
{
bool result = Game::Load_Stream(atStreamStart, buffer, 48);
std::memmove(buffer + 28, buffer + 32, 16);
AssetHandler::Relocate(buffer + 32, buffer + 28, 16);
return result;
}
bool Zones::LoadVehicleDef(bool atStreamStart, char* buffer)
{
bool result = Game::Load_Stream(atStreamStart, buffer, 788);
Game::VehicleDef vehicle[2];
std::memcpy(vehicle, &buffer[0], 400);
std::memcpy(&vehicle->pad[404], &buffer[400], 388);
AssetHandler::Relocate(buffer + 400, buffer + 408, 388);
std::memcpy(buffer, vehicle, 788);
return result;
}
Utils::Hook loadWeaponAttachHook;
DWORD varWeaponAttachStuff;
void Load_WeaponAttachStuff(int count)
{
Game::Load_Stream(1, (void*)varWeaponAttachStuff, 12 * count);
DWORD* varStuff = (DWORD*)varWeaponAttachStuff;
for (int i = 0; i < count; i++)
{
//DWORD* varXString = (DWORD*)0x112B340;
if (varStuff[1] < 16 || varStuff[1] == 39)
{
if (varStuff[2] == -1)
{
varStuff[2] = (DWORD)Game::DB_AllocStreamPos(0);
*Game::varConstChar = (const char*)varStuff[2];
Game::Load_XStringCustom(Game::varConstChar);
//if (*useEntryNames)
{
//DBG(("wA: %s\n", *varXStringData));
}
}
else if (varStuff[2])
{
// meh, no convertin' here
}
}
varStuff += 3;
}
}
Utils::Hook menuDefLoadHook;
void MenuDefLoadHookFunc(int doLoad, char* buffer, int len)
{
len += 4;
__asm
{
push len
push buffer
push doLoad
call menuDefLoadHook.Original
add esp, 0Ch
}
std::memcpy(buffer + 168, buffer + 172, 232);
AssetHandler::Relocate((DWORD)buffer + 172, 232, (DWORD)buffer + 168);
}
void Load_WeaponAttach(int /*doLoad*/)
{
// setup structures we use
DWORD varWeaponAttach = *(DWORD*)0x112ADE0;//*(DWORD*)0x112AE14;
DWORD* varXString = (DWORD*)0x112B340;
// and do the stuff
Game::Load_Stream(1, (void*)varWeaponAttach, 12);
Game::DB_PushStreamPos(3);
*varXString = varWeaponAttach + 0;
Game::Load_XString(false);
*(void**)(varWeaponAttach + 8) = Game::DB_AllocStreamPos(3);
varWeaponAttachStuff = *(DWORD*)(varWeaponAttach + 8);
Load_WeaponAttachStuff(*(int*)(varWeaponAttach + 4));
Game::DB_PopStreamPos();
}
Utils::Hook loadTechniquePassHook;
void Load_TechniquePassHookFunc(bool atStreamStart, Game::ShaderArgumentDef* pass, size_t size)
{
int count = size / 8;
Game::MaterialPass* curPass = *(Game::MaterialPass**)0x112A960;
count = curPass->argCount1 + curPass->argCount2 + curPass->argCount3;
Game::Load_Stream(atStreamStart, pass, size);
for (int i = 0; i < count; i++)
{
Game::ShaderArgumentDef* arg = &pass[i];
if (arg->type != 3 && arg->type != 5)
{
continue;
}
// should be min 68 currently
// >= 58 fixes foliage without bad side effects
// >= 53 still has broken shadow mapping
// >= 23 is still broken somehow
if (arg->paramID >= 58 && arg->paramID <= 135) // >= 34 would be 31 in iw4 terms
{
arg->paramID -= 3;
}
// >= 21 works fine for specular, but breaks trees
// >= 4 is too low, breaks specular
else if (arg->paramID >= 11 && arg->paramID < 58)
{
arg->paramID -= 2;
}
}
}
Utils::Hook loadStructuredDataChildArrayHook;
void Load_StructuredDataChildArrayHookFunc(bool atStreamStart, char* data, size_t size)
{
int count = size / 16;
size = count * 24;
Game::Load_Stream(atStreamStart, data, size);
for (int i = 0; i < count; i++)
{
std::memcpy(data + (i * 16), data + (i * 24), 16);
AssetHandler::Relocate((DWORD)data + (i * 24), 16, (DWORD)data + (i * 16));
}
}
void Zones::InstallPatches(int version)
{
AssetHandler::ClearRelocations();
if (Zones::ZoneVersion == version) return;
Zones::ZoneVersion = version;
bool patch = (version >= VERSION_ALPHA2);
if (Zones::ZoneVersion == VERSION_ALPHA2 || Zones::ZoneVersion == VERSION_ALPHA3 || Zones::ZoneVersion == XFILE_VERSION)
{
Utils::Hook::Set<DWORD>(0x4158F4, version);
Utils::Hook::Set<DWORD>(0x4158FB, version);
}
// physpreset size
Utils::Hook::Set<BYTE>(0x49CE0A, (patch) ? 68 : 44);
// XModel size
Utils::Hook::Set<DWORD>(0x410D8A, (patch) ? ((Zones::ZoneVersion == VERSION_ALPHA2) ? 0x16C : 0x168) : 0x130);
// XSurface size
Utils::Hook::Set<BYTE>(0x48E84A, (patch) ? 48 : 36);
// impactfx internal size/count
Utils::Hook::Set<DWORD>(0x4447B6, (patch) ? 0x8C0 : 0x834);
Utils::Hook::Set<DWORD>(0x4447D1, (patch) ? 16 : 15);
// GameWorldSp asset type
Utils::Hook::Set<BYTE>(0x41899A, (patch) ? 18 : 17);
// PathData internal struct size
Utils::Hook::Set<DWORD>(0x4D6A04, (patch) ? 148 : 136);
Utils::Hook::Set<DWORD>(0x4D6A49, (patch) ? 148 : 136);
// PathData internal struct data size
Utils::Hook::Set<WORD>(0x463D63, (patch) ? 0x9090 : 0x048D);
Utils::Hook::Set<BYTE>(0x463D65, (patch) ? 0x90 : 0x40);
Utils::Hook::Set<DWORD>(0x463D66, (patch) ? 0x9004E0C1 : 0xC003C003); // shl eax, 4 instead of add eax, eax * 2
// addon_map_ents asset type (we reuse it for weaponattach)
Utils::Hook::Set<BYTE>(0x418B30, (patch) ? 43 : Game::ASSET_TYPE_ADDON_MAP_ENTS);
if (patch)
{
Zones::LoadFxElemDefArrayHook.Install();
Zones::LoadFxElemDefHook.Install();
Zones::LoadXModelLodInfoHook.Install();
Zones::LoadXModelHook.Install();
Zones::LoadXSurfaceArrayHook.Install();
Zones::LoadGameWorldSpHook.Install();
pathDataTailHook.Install();
loadWeaponDefHook.Install();
Zones::LoadVehicleDefHook.Install();
Zones::Loadsnd_alias_tArrayHook.Install();
Zones::LoadLoadedSoundHook.Install();
menuDefLoadHook.Install();
fxEffectLoadHook.Install();
loadWeaponAttachHook.Install();
if (Zones::ZoneVersion >= VERSION_ALPHA3)
{
Zones::LoadPathDataHook.Install();
}
loadTechniquePassHook.Install();
loadStructuredDataChildArrayHook.Install();
}
else
{
Zones::LoadFxElemDefArrayHook.Uninstall();
Zones::LoadFxElemDefHook.Uninstall();
Zones::LoadXModelLodInfoHook.Uninstall();
Zones::LoadXModelHook.Uninstall();
Zones::LoadXSurfaceArrayHook.Uninstall();
Zones::LoadGameWorldSpHook.Uninstall();
pathDataTailHook.Uninstall();
loadWeaponDefHook.Uninstall();
Zones::LoadVehicleDefHook.Uninstall();
Zones::Loadsnd_alias_tArrayHook.Uninstall();
Zones::LoadLoadedSoundHook.Uninstall();
menuDefLoadHook.Uninstall();
fxEffectLoadHook.Uninstall();
loadWeaponAttachHook.Uninstall();
Zones::LoadPathDataHook.Uninstall();
loadTechniquePassHook.Uninstall();
loadStructuredDataChildArrayHook.Uninstall();
}
AntiCheat::EmptyHash();
}
Zones::Zones()
{
Zones::ZoneVersion = 0;
// Ignore missing soundaliases for now
// TODO: Include them in the dependency zone!
Utils::Hook::Nop(0x644207, 5);
// Block Mark_pathnode_constant_t
Utils::Hook::Set<BYTE>(0x4F74B0, 0xC3);
Zones::LoadFxElemDefArrayHook.Initialize(0x495938, Zones::LoadFxElemDefArrayStub, HOOK_CALL);
Zones::LoadFxElemDefHook.Initialize(0x45ADA0, Zones::LoadFxElemDefStub, HOOK_CALL);
Zones::LoadXModelLodInfoHook.Initialize(0x4EA6FE, Zones::LoadXModelLodInfoStub, HOOK_CALL);
Zones::LoadXModelHook.Initialize(0x410D90, Zones::LoadXModel, HOOK_CALL);
Zones::LoadXSurfaceArrayHook.Initialize(0x4925C8, Zones::LoadXSurfaceArray, HOOK_CALL);
Zones::LoadGameWorldSpHook.Initialize(0x4F4D0D, Zones::LoadGameWorldSp, HOOK_CALL);
loadWeaponDefHook.Initialize(0x47CCD2, Load_WeaponDef_CodC, HOOK_CALL);
Zones::LoadVehicleDefHook.Initialize(0x483DA0, Zones::LoadVehicleDef, HOOK_CALL);
Zones::Loadsnd_alias_tArrayHook.Initialize(0x4F0AC8, Zones::Loadsnd_alias_tArray, HOOK_CALL);
Zones::LoadLoadedSoundHook.Initialize(0x403A5D, Zones::LoadLoadedSound, HOOK_CALL);
loadWeaponAttachHook.Initialize(0x463022, Load_WeaponAttach, HOOK_CALL);
menuDefLoadHook.Initialize(0x41A570, MenuDefLoadHookFunc, HOOK_CALL);
fxEffectLoadHook.Initialize(0x49591B, FxEffectLoadHookFunc, HOOK_CALL);
loadTechniquePassHook.Initialize(0x428F0A, Load_TechniquePassHookFunc, HOOK_CALL);
loadStructuredDataChildArrayHook.Initialize(0x4B1EB8, Load_StructuredDataChildArrayHookFunc, HOOK_CALL);
pathDataTailHook.Initialize(0x427A1B, PathDataTailHookFunc, HOOK_JUMP);
Zones::LoadPathDataHook.Initialize(0x4F4D3B, [] ()
{
ZeroMemory(*Game::varPathData, sizeof(Game::PathData));
}, HOOK_CALL);
}
Zones::~Zones()

View File

@ -1,3 +1,6 @@
#define VERSION_ALPHA2 316
#define VERSION_ALPHA3 318//319
namespace Components
{
class Zones : public Component
@ -12,7 +15,30 @@ namespace Components
static void InstallPatches(int version);
private:
//private:
static int ZoneVersion;
static Utils::Hook LoadFxElemDefHook;
static Utils::Hook LoadFxElemDefArrayHook;
static Utils::Hook LoadXModelLodInfoHook;
static Utils::Hook LoadXModelHook;
static Utils::Hook LoadXSurfaceArrayHook;
static Utils::Hook LoadGameWorldSpHook;
static Utils::Hook LoadPathDataHook;
static Utils::Hook LoadVehicleDefHook;
static Utils::Hook Loadsnd_alias_tArrayHook;
static Utils::Hook LoadLoadedSoundHook;
static void LoadFxElemDefArrayStub(bool atStreamStart);
static bool LoadFxElemDefStub(bool atStreamStart, Game::FxElemDef* fxElem, int size);
static void LoadXModelLodInfo(int i);
static void LoadXModelLodInfoStub();
static bool LoadXModel(bool atStreamStart, char* xmodel, int size);
static bool LoadXSurfaceArray(bool atStreamStart, char* buffer, int size);
static bool LoadGameWorldSp(bool atStreamStart, char* buffer);
static bool LoadVehicleDef(bool atStreamStart, char* buffer);
static bool Loadsnd_alias_tArray(bool atStreamStart, char* buffer, int len);
static bool LoadLoadedSound(bool atStreamStart, char* buffer);
};
}

View File

@ -32,6 +32,10 @@ namespace Game
Con_DrawMiniConsole_t Con_DrawMiniConsole = (Con_DrawMiniConsole_t)0x464F30;
Con_DrawSolidConsole_t Con_DrawSolidConsole = (Con_DrawSolidConsole_t)0x5A5040;
DB_AllocStreamPos_t DB_AllocStreamPos = (DB_AllocStreamPos_t)0x418380;
DB_PushStreamPos_t DB_PushStreamPos = (DB_PushStreamPos_t)0x458A20;
DB_PopStreamPos_t DB_PopStreamPos = (DB_PopStreamPos_t)0x4D1D60;
DB_BeginRecoverLostDevice_t DB_BeginRecoverLostDevice = (DB_BeginRecoverLostDevice_t)0x4BFF90;
DB_EndRecoverLostDevice_t DB_EndRecoverLostDevice = (DB_EndRecoverLostDevice_t)0x46B660;
DB_EnumXAssets_t DB_EnumXAssets = (DB_EnumXAssets_t)0x4B76D0;
@ -94,6 +98,20 @@ namespace Game
Image_Release_t Image_Release = (Image_Release_t)0x51F010;
LargeLocalInit_t LargeLocalInit = (LargeLocalInit_t)0x4A62A0;
Load_Stream_t Load_Stream = (Load_Stream_t)0x470E30;
Load_XString_t Load_XString = (Load_XString_t)0x47FDA0;
Load_XModelPtr_t Load_XModelPtr = (Load_XModelPtr_t)0x4FCA70;
Load_XModelSurfsFixup_t Load_XModelSurfsFixup = (Load_XModelSurfsFixup_t)0x40D7A0;
Load_XStringArray_t Load_XStringArray = (Load_XStringArray_t)0x4977F0;
Load_XStringCustom_t Load_XStringCustom = (Load_XStringCustom_t)0x4E0DD0;
Load_FxEffectDefHandle_t Load_FxEffectDefHandle = (Load_FxEffectDefHandle_t)0x4D9B90;
Load_FxElemDef_t Load_FxElemDef = (Load_FxElemDef_t)0x45AD90;
Load_SndAliasCustom_t Load_SndAliasCustom = (Load_SndAliasCustom_t)0x49B6B0;
Load_MaterialHandle_t Load_MaterialHandle = (Load_MaterialHandle_t)0x403960;
Load_PhysCollmapPtr_t Load_PhysCollmapPtr = (Load_PhysCollmapPtr_t)0x47E990;
Load_TracerDefPtr_t Load_TracerDefPtr = (Load_TracerDefPtr_t)0x493090;
Load_snd_alias_list_nameArray_t Load_snd_alias_list_nameArray = (Load_snd_alias_list_nameArray_t)0x4499F0;
Menus_CloseAll_t Menus_CloseAll = (Menus_CloseAll_t)0x4BA5B0;
Menus_OpenByName_t Menus_OpenByName = (Menus_OpenByName_t)0x4CCE60;
@ -257,6 +275,17 @@ namespace Game
mapname_t* mapnames = (mapname_t*)0x7471D0;
char*** varXString = (char***)0x112B340;
TracerDef** varTracerDefPtr = (TracerDef**)0x112B3BC;
XModel** varXModelPtr = (XModel**)0x112A934;
XModel** varXModel = (XModel**)0x112AE14;
PathData** varPathData = (PathData**)0x112AD7C;
const char** varConstChar = (const char**)0x112A774;
Material** varMaterialHandle = (Material**)0x112A878;
FxEffectDef** varFxEffectDefHandle = (FxEffectDef**)0x112ACC0;
PhysCollmap** varPhysCollmapPtr = (PhysCollmap **)0x112B440;
snd_alias_list_t*** varsnd_alias_list_name = (snd_alias_list_t***)0x112AF38;
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
{
int elSize = DB_GetXAssetSizeHandlers[type]();
@ -476,7 +505,7 @@ namespace Game
if (Components::Dvar::Var("r_loadForRenderer").Get<bool>())
{
void* buffer = R_AllocStaticIndexBuffer(storeHere, 2 * count);
memcpy(buffer, data, 2 * count);
std::memcpy(buffer, data, 2 * count);
if (storeHere && *storeHere)
{

View File

@ -66,6 +66,15 @@ namespace Game
typedef void (__cdecl * Con_DrawSolidConsole_t)();
extern Con_DrawSolidConsole_t Con_DrawSolidConsole;
typedef char *(__cdecl *DB_AllocStreamPos_t)(int alignment);
extern DB_AllocStreamPos_t DB_AllocStreamPos;
typedef void(__cdecl * DB_PushStreamPos_t)(unsigned int index);
extern DB_PushStreamPos_t DB_PushStreamPos;
typedef void(__cdecl * DB_PopStreamPos_t)();
extern DB_PopStreamPos_t DB_PopStreamPos;
typedef void(__cdecl * DB_BeginRecoverLostDevice_t)();
extern DB_BeginRecoverLostDevice_t DB_BeginRecoverLostDevice;
@ -224,6 +233,45 @@ namespace Game
typedef void(__cdecl * LargeLocalInit_t)();
extern LargeLocalInit_t LargeLocalInit;
typedef bool(__cdecl * Load_Stream_t)(bool atStreamStart, const void *ptr, int size);
extern Load_Stream_t Load_Stream;
typedef void(__cdecl * Load_XString_t)(bool atStreamStart);
extern Load_XString_t Load_XString;
typedef void(__cdecl * Load_XModelPtr_t)(bool atStreamStart);
extern Load_XModelPtr_t Load_XModelPtr;
typedef void(__cdecl * Load_XModelSurfsFixup_t)(XModelSurfs **, XModelLodInfo *);
extern Load_XModelSurfsFixup_t Load_XModelSurfsFixup;
typedef void(__cdecl * Load_XStringArray_t)(bool atStreamStart, int count);
extern Load_XStringArray_t Load_XStringArray;
typedef void(__cdecl * Load_XStringCustom_t)(const char **str);
extern Load_XStringCustom_t Load_XStringCustom;
typedef void(__cdecl *Load_FxEffectDefHandle_t)(bool atStreamStart);
extern Load_FxEffectDefHandle_t Load_FxEffectDefHandle;
typedef void(__cdecl *Load_FxElemDef_t)(bool atStreamStart);
extern Load_FxElemDef_t Load_FxElemDef;
typedef void(__cdecl * Load_SndAliasCustom_t)(snd_alias_list_t** var);
extern Load_SndAliasCustom_t Load_SndAliasCustom;
typedef void(__cdecl *Load_MaterialHandle_t)(bool atStreamStart);
extern Load_MaterialHandle_t Load_MaterialHandle;
typedef void(__cdecl *Load_PhysCollmapPtr_t)(bool atStreamStart);
extern Load_PhysCollmapPtr_t Load_PhysCollmapPtr;
typedef void(__cdecl *Load_TracerDefPtr_t)(bool atStreamStart);
extern Load_TracerDefPtr_t Load_TracerDefPtr;
typedef void(__cdecl *Load_snd_alias_list_nameArray_t)(bool atStreamStart, int count);
extern Load_snd_alias_list_nameArray_t Load_snd_alias_list_nameArray;
typedef void(__cdecl * Menus_CloseAll_t)(UiContext *dc);
extern Menus_CloseAll_t Menus_CloseAll;
@ -517,6 +565,17 @@ namespace Game
extern mapname_t* mapnames;
extern char*** varXString;
extern TracerDef** varTracerDefPtr;
extern XModel** varXModelPtr;
extern XModel** varXModel;
extern PathData** varPathData;
extern const char** varConstChar;
extern Material** varMaterialHandle;
extern FxEffectDef** varFxEffectDefHandle;
extern PhysCollmap** varPhysCollmapPtr;
extern snd_alias_list_t*** varsnd_alias_list_name;
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize);
void Menu_FreeItemMemory(Game::itemDef_t* item);
const char* TableLookup(StringTable* stringtable, int row, int column);

View File

@ -368,6 +368,19 @@ namespace Game
void *stateBitTable;
};
struct TracerDef
{
const char * name;
Material * material;
unsigned int drawInterval;
float speed;
float beamLength;
float beamWidth;
float screwRadius;
float screwDist;
float colors[5][4];
};
struct keyname_t
{
const char *name;
@ -1398,16 +1411,13 @@ namespace Game
struct XModelLodInfo
{
// I'm not sure if this is correct
short someCount;
short someTotalCount;
char pad[4];
short numSurfs; // +4
short pad2;// +6
short maxSurfs;// +6
XModelSurfs* surfaces; // +8
char pad3[24];
char pad3[24]; // +12
XSurface* surfs;
char pad4[4]; // +12
char pad4[4];
};
struct cplane_t
@ -1532,8 +1542,6 @@ namespace Game
PhysCollmap* physCollmap;
}; // total size 304
//static_assert(offsetof(XModel, lods) <= 70, "");
struct CModelAllocData
{
void* mainArray;
@ -2273,20 +2281,37 @@ namespace Game
char pad[112];
};
struct GameMap_SP
struct PathData
{
char pad[40];
};
struct VehicleTrack
{
char pad[8];
};
struct GameWorldSp
{
const char* name;
char pad[48];
PathData pathData;
VehicleTrack vehicleTrack;
GameMap_Data* data;
};
struct GameMap_MP
struct GameWorldMp
{
const char* name;
GameMap_Data* data;
};
struct VehicleDef
{
const char* name;
char pad[716];
};
union XAssetHeader
{
void *data;
@ -2312,8 +2337,10 @@ namespace Game
XAnimParts* xanim;
clipMap_t* clipMap;
FxEffectDef* fx;
GameMap_MP* gameMapMP;
GameMap_SP* gameMapSP;
GameWorldMp* gameMapMP;
GameWorldSp* gameMapSP;
TracerDef* tracer;
VehicleDef* vehicle;
};
struct XAsset

View File

@ -36,6 +36,19 @@ namespace Utils
Memory::Free(const_cast<void*>(data));
}
void Memory::FreeAlign(void* data)
{
if (data)
{
_aligned_free(data);
}
}
void Memory::FreeAlign(const void* data)
{
Memory::FreeAlign(const_cast<void*>(data));
}
// Complementary function for memset, which checks if memory is filled with a char
bool Memory::IsSet(void* mem, char chr, size_t length)
{

View File

@ -108,6 +108,9 @@ namespace Utils
static void Free(void* data);
static void Free(const void* data);
static void FreeAlign(void* data);
static void FreeAlign(const void* data);
static bool IsSet(void* mem, char chr, size_t length);
};
}