diff --git a/src/Crypto/Crypto.cpp b/src/Crypto/Crypto.cpp index 759bcd83..9eb876fe 100644 --- a/src/Crypto/Crypto.cpp +++ b/src/Crypto/Crypto.cpp @@ -2,12 +2,18 @@ #include "Impl/AlgorithmRSA.h" #include "Impl/AlgorithmSHA1.h" #include "Impl/AlgorithmSalsa20.h" +#include "Impl/AlgorithmSHA256.h" IHashFunction* Crypto::CreateSHA1() { return new AlgorithmSHA1(); } +IHashFunction* Crypto::CreateSHA256() +{ + return new AlgorithmSHA256(); +} + IStreamCipher* Crypto::CreateSalsa20(const uint8_t* keyBytes, const size_t keySize) { return new AlgorithmSalsa20(keyBytes, keySize); diff --git a/src/Crypto/Crypto.h b/src/Crypto/Crypto.h index ca9dc4ca..8daa8eaf 100644 --- a/src/Crypto/Crypto.h +++ b/src/Crypto/Crypto.h @@ -13,6 +13,7 @@ public: }; static IHashFunction* CreateSHA1(); + static IHashFunction* CreateSHA256(); static IStreamCipher* CreateSalsa20(const uint8_t* keyBytes, size_t keySize); diff --git a/src/Crypto/Impl/AlgorithmSHA256.cpp b/src/Crypto/Impl/AlgorithmSHA256.cpp new file mode 100644 index 00000000..7de8948b --- /dev/null +++ b/src/Crypto/Impl/AlgorithmSHA256.cpp @@ -0,0 +1,63 @@ +#include "AlgorithmSHA256.h" + +#include "CryptoLibrary.h" +#include + +class AlgorithmSHA256::Impl +{ + hash_state m_state{}; + +public: + Impl() + { + CryptoLibrary::Init(); + + Init(); + } + + void Init() + { + sha256_init(&m_state); + } + + void Process(const void* input, const size_t inputSize) + { + sha256_process(&m_state, static_cast(input), inputSize); + } + + void Finish(void* hashBuffer) + { + sha256_done(&m_state, static_cast(hashBuffer)); + } +}; + +AlgorithmSHA256::AlgorithmSHA256() +{ + m_impl = new Impl(); +} + +AlgorithmSHA256::~AlgorithmSHA256() +{ + delete m_impl; + m_impl = nullptr; +} + +size_t AlgorithmSHA256::GetHashSize() +{ + return HASH_SIZE; +} + +void AlgorithmSHA256::Init() +{ + m_impl->Init(); +} + +void AlgorithmSHA256::Process(const void* input, const size_t inputSize) +{ + m_impl->Process(input, inputSize); +} + +void AlgorithmSHA256::Finish(void* hashBuffer) +{ + m_impl->Finish(hashBuffer); +} \ No newline at end of file diff --git a/src/Crypto/Impl/AlgorithmSHA256.h b/src/Crypto/Impl/AlgorithmSHA256.h new file mode 100644 index 00000000..54875a2a --- /dev/null +++ b/src/Crypto/Impl/AlgorithmSHA256.h @@ -0,0 +1,20 @@ +#pragma once +#include "IHashFunction.h" + +class AlgorithmSHA256 : public IHashFunction +{ + class Impl; + Impl* m_impl; + +public: + static const int HASH_SIZE = 32; + + AlgorithmSHA256(); + ~AlgorithmSHA256() override; + + size_t GetHashSize() override; + + void Init() override; + void Process(const void* input, size_t inputSize) override; + void Finish(void* hashBuffer) override; +}; diff --git a/src/ZoneCommon/Game/IW4/CommonIW4.cpp b/src/ZoneCommon/Game/IW4/CommonIW4.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCommon/Game/IW4/CommonIW4.h b/src/ZoneCommon/Game/IW4/CommonIW4.h new file mode 100644 index 00000000..e69de29b diff --git a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp new file mode 100644 index 00000000..d9ac8e10 --- /dev/null +++ b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp @@ -0,0 +1,484 @@ +#include "GameAssetPoolIW4.h" +#include "Pool/AssetPoolStatic.h" +#include "Pool/AssetPoolDynamic.h" +#include + +using namespace IW4; + +const std::string GameAssetPoolIW4::ASSET_TYPE_INVALID = "invalid_asset"; +const std::string GameAssetPoolIW4::ASSET_TYPE_NAMES[] +{ + "physpreset", + "physcollmap", + "xanim", + "xmodelsurfs", + "xmodel", + "material", + "pixelshader", + "vertexshader", + "vertexdecl", + "techniqueset", + "image", + "sound", + "soundcurve", + "loadedsound", + "clipmap", + "clipmap", + "comworld", + "gameworldsp", + "gameworldmp", + "mapents", + "fxworld", + "gfxworld", + "lightdef", + "uimap", + "font", + "menulist", + "menu", + "localize", + "weapon", + "snddriverglobals", + "fx", + "impactfx", + "aitype", + "mptype", + "character", + "xmodelalias", + "rawfile", + "stringtable", + "leaderboard", + "structureddatadef", + "tracer", + "vehicle", + "addonmapents" +}; + +GameAssetPoolIW4::GameAssetPoolIW4(const int priority) +{ + assert(_countof(ASSET_TYPE_NAMES) == ASSET_TYPE_COUNT); + + m_priority = priority; + + /*m_phys_preset = nullptr; + m_phys_constraints = nullptr; + m_destructible_def = nullptr; + m_xanim_parts = nullptr; + m_xmodel = nullptr; + m_material = nullptr; + m_technique_set = nullptr; + m_image = nullptr; + m_sound_bank = nullptr; + m_sound_patch = nullptr; + m_clip_map = nullptr; + m_com_world = nullptr; + m_game_world_sp = nullptr; + m_game_world_mp = nullptr; + m_map_ents = nullptr; + m_gfx_world = nullptr; + m_gfx_light_def = nullptr; + m_font = nullptr; + m_font_icon = nullptr; + m_menu_list = nullptr; + m_menu_def = nullptr; + m_localize = nullptr; + m_weapon = nullptr; + m_attachment = nullptr; + m_attachment_unique = nullptr; + m_camo = nullptr; + m_snd_driver_globals = nullptr; + m_fx = nullptr; + m_fx_impact_table = nullptr; + m_raw_file = nullptr; + m_string_table = nullptr; + m_leaderboard = nullptr; + m_xglobals = nullptr; + m_ddl = nullptr; + m_glasses = nullptr; + m_emblem_set = nullptr; + m_script = nullptr; + m_key_value_pairs = nullptr; + m_vehicle = nullptr; + m_memory_block = nullptr; + m_addon_map_ents = nullptr; + m_tracer = nullptr; + m_skinned_verts = nullptr; + m_qdb = nullptr; + m_slug = nullptr; + m_footstep_table = nullptr; + m_footstep_fx_table = nullptr; + m_zbarrier = nullptr;*/ +} + +GameAssetPoolIW4::~GameAssetPoolIW4() +{ +#define DELETE_POOL(poolName) \ + delete (poolName); (poolName) = nullptr; + + /*DELETE_POOL(m_phys_preset); + DELETE_POOL(m_phys_constraints); + DELETE_POOL(m_destructible_def); + DELETE_POOL(m_xanim_parts); + DELETE_POOL(m_xmodel); + DELETE_POOL(m_material); + DELETE_POOL(m_technique_set); + DELETE_POOL(m_image); + DELETE_POOL(m_sound_bank); + DELETE_POOL(m_sound_patch); + DELETE_POOL(m_clip_map); + DELETE_POOL(m_com_world); + DELETE_POOL(m_game_world_sp); + DELETE_POOL(m_game_world_mp); + DELETE_POOL(m_map_ents); + DELETE_POOL(m_gfx_world); + DELETE_POOL(m_gfx_light_def); + DELETE_POOL(m_font); + DELETE_POOL(m_font_icon); + DELETE_POOL(m_menu_list); + DELETE_POOL(m_menu_def); + DELETE_POOL(m_localize); + DELETE_POOL(m_weapon); + DELETE_POOL(m_attachment); + DELETE_POOL(m_attachment_unique); + DELETE_POOL(m_camo); + DELETE_POOL(m_snd_driver_globals); + DELETE_POOL(m_fx); + DELETE_POOL(m_fx_impact_table); + DELETE_POOL(m_raw_file); + DELETE_POOL(m_string_table); + DELETE_POOL(m_leaderboard); + DELETE_POOL(m_xglobals); + DELETE_POOL(m_ddl); + DELETE_POOL(m_glasses); + DELETE_POOL(m_emblem_set); + DELETE_POOL(m_script); + DELETE_POOL(m_key_value_pairs); + DELETE_POOL(m_vehicle); + DELETE_POOL(m_memory_block); + DELETE_POOL(m_addon_map_ents); + DELETE_POOL(m_tracer); + DELETE_POOL(m_skinned_verts); + DELETE_POOL(m_qdb); + DELETE_POOL(m_slug); + DELETE_POOL(m_footstep_table); + DELETE_POOL(m_footstep_fx_table); + DELETE_POOL(m_zbarrier);*/ + +#undef DELETE_POOL +} + +void GameAssetPoolIW4::InitPoolStatic(const asset_type_t type, const size_t capacity) +{ +#define CASE_INIT_POOL_STATIC(assetType, poolName, poolType) \ + case assetType: \ + { \ + if((poolName) == nullptr && capacity > 0) \ + { \ + (poolName) = new AssetPoolStatic(capacity, m_priority, (assetType)); \ + } \ + break; \ + } + + switch (type) + { + /*CASE_INIT_POOL_STATIC(ASSET_TYPE_PHYSPRESET, m_phys_preset, PhysPreset); + CASE_INIT_POOL_STATIC(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints, PhysConstraints); + CASE_INIT_POOL_STATIC(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def, DestructibleDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_XANIMPARTS, m_xanim_parts, XAnimParts); + CASE_INIT_POOL_STATIC(ASSET_TYPE_XMODEL, m_xmodel, XModel); + CASE_INIT_POOL_STATIC(ASSET_TYPE_MATERIAL, m_material, Material); + CASE_INIT_POOL_STATIC(ASSET_TYPE_TECHNIQUE_SET, m_technique_set, MaterialTechniqueSet); + CASE_INIT_POOL_STATIC(ASSET_TYPE_IMAGE, m_image, GfxImage); + CASE_INIT_POOL_STATIC(ASSET_TYPE_SOUND, m_sound_bank, SndBank); + CASE_INIT_POOL_STATIC(ASSET_TYPE_SOUND_PATCH, m_sound_patch, SndPatch); + CASE_INIT_POOL_STATIC(ASSET_TYPE_CLIPMAP, m_clip_map, clipMap_t); + CASE_INIT_POOL_STATIC(ASSET_TYPE_CLIPMAP_PVS, m_clip_map, clipMap_t); + CASE_INIT_POOL_STATIC(ASSET_TYPE_COMWORLD, m_com_world, ComWorld); + CASE_INIT_POOL_STATIC(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp, GameWorldSp); + CASE_INIT_POOL_STATIC(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp, GameWorldMp); + CASE_INIT_POOL_STATIC(ASSET_TYPE_MAP_ENTS, m_map_ents, MapEnts); + CASE_INIT_POOL_STATIC(ASSET_TYPE_GFXWORLD, m_gfx_world, GfxWorld); + CASE_INIT_POOL_STATIC(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def, GfxLightDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_FONT, m_font, Font_s); + CASE_INIT_POOL_STATIC(ASSET_TYPE_FONTICON, m_font_icon, FontIcon); + CASE_INIT_POOL_STATIC(ASSET_TYPE_MENULIST, m_menu_list, MenuList); + CASE_INIT_POOL_STATIC(ASSET_TYPE_MENU, m_menu_def, menuDef_t); + CASE_INIT_POOL_STATIC(ASSET_TYPE_LOCALIZE_ENTRY, m_localize, LocalizeEntry); + CASE_INIT_POOL_STATIC(ASSET_TYPE_WEAPON, m_weapon, WeaponVariantDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_ATTACHMENT, m_attachment, WeaponAttachment); + CASE_INIT_POOL_STATIC(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique, WeaponAttachmentUnique); + CASE_INIT_POOL_STATIC(ASSET_TYPE_WEAPON_CAMO, m_camo, WeaponCamo); + CASE_INIT_POOL_STATIC(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals, SndDriverGlobals); + CASE_INIT_POOL_STATIC(ASSET_TYPE_FX, m_fx, FxEffectDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_IMPACT_FX, m_fx_impact_table, FxImpactTable); + CASE_INIT_POOL_STATIC(ASSET_TYPE_RAWFILE, m_raw_file, RawFile); + CASE_INIT_POOL_STATIC(ASSET_TYPE_STRINGTABLE, m_string_table, StringTable); + CASE_INIT_POOL_STATIC(ASSET_TYPE_LEADERBOARD, m_leaderboard, LeaderboardDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_XGLOBALS, m_xglobals, XGlobals); + CASE_INIT_POOL_STATIC(ASSET_TYPE_DDL, m_ddl, ddlRoot_t); + CASE_INIT_POOL_STATIC(ASSET_TYPE_GLASSES, m_glasses, Glasses); + CASE_INIT_POOL_STATIC(ASSET_TYPE_EMBLEMSET, m_emblem_set, EmblemSet); + CASE_INIT_POOL_STATIC(ASSET_TYPE_SCRIPTPARSETREE, m_script, ScriptParseTree); + CASE_INIT_POOL_STATIC(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs, KeyValuePairs); + CASE_INIT_POOL_STATIC(ASSET_TYPE_VEHICLEDEF, m_vehicle, VehicleDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_MEMORYBLOCK, m_memory_block, MemoryBlock); + CASE_INIT_POOL_STATIC(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents, AddonMapEnts); + CASE_INIT_POOL_STATIC(ASSET_TYPE_TRACER, m_tracer, TracerDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts, SkinnedVertsDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_QDB, m_qdb, Qdb); + CASE_INIT_POOL_STATIC(ASSET_TYPE_SLUG, m_slug, Slug); + CASE_INIT_POOL_STATIC(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table, FootstepTableDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table, FootstepFXTableDef); + CASE_INIT_POOL_STATIC(ASSET_TYPE_ZBARRIER, m_zbarrier, ZBarrierDef);*/ + + default: + assert(type >= 0 && type < ASSET_TYPE_COUNT); + break; + } + +#undef CASE_INIT_POOL_STATIC +} + +void GameAssetPoolIW4::InitPoolDynamic(const asset_type_t type) +{ +#define CASE_INIT_POOL_DYNAMIC(assetType, poolName, poolType) \ + case assetType: \ + { \ + if((poolName) == nullptr) \ + { \ + (poolName) = new AssetPoolDynamic(m_priority, (assetType)); \ + } \ + break; \ + } + + switch (type) + { + /*CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_PHYSPRESET, m_phys_preset, PhysPreset); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints, PhysConstraints); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def, DestructibleDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_XANIMPARTS, m_xanim_parts, XAnimParts); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_XMODEL, m_xmodel, XModel); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MATERIAL, m_material, Material); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_TECHNIQUE_SET, m_technique_set, MaterialTechniqueSet); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_IMAGE, m_image, GfxImage); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SOUND, m_sound_bank, SndBank); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SOUND_PATCH, m_sound_patch, SndPatch); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_CLIPMAP, m_clip_map, clipMap_t); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_CLIPMAP_PVS, m_clip_map, clipMap_t); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_COMWORLD, m_com_world, ComWorld); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp, GameWorldSp); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp, GameWorldMp); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MAP_ENTS, m_map_ents, MapEnts); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GFXWORLD, m_gfx_world, GfxWorld); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def, GfxLightDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FONT, m_font, Font_s); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FONTICON, m_font_icon, FontIcon); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MENULIST, m_menu_list, MenuList); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MENU, m_menu_def, menuDef_t); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_LOCALIZE_ENTRY, m_localize, LocalizeEntry); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_WEAPON, m_weapon, WeaponVariantDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ATTACHMENT, m_attachment, WeaponAttachment); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique, WeaponAttachmentUnique); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_WEAPON_CAMO, m_camo, WeaponCamo); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals, SndDriverGlobals); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FX, m_fx, FxEffectDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_IMPACT_FX, m_fx_impact_table, FxImpactTable); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_RAWFILE, m_raw_file, RawFile); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_STRINGTABLE, m_string_table, StringTable); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_LEADERBOARD, m_leaderboard, LeaderboardDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_XGLOBALS, m_xglobals, XGlobals); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_DDL, m_ddl, ddlRoot_t); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GLASSES, m_glasses, Glasses); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_EMBLEMSET, m_emblem_set, EmblemSet); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SCRIPTPARSETREE, m_script, ScriptParseTree); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs, KeyValuePairs); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_VEHICLEDEF, m_vehicle, VehicleDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MEMORYBLOCK, m_memory_block, MemoryBlock); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents, AddonMapEnts); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_TRACER, m_tracer, TracerDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts, SkinnedVertsDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_QDB, m_qdb, Qdb); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SLUG, m_slug, Slug); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table, FootstepTableDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table, FootstepFXTableDef); + CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ZBARRIER, m_zbarrier, ZBarrierDef);*/ + + default: + assert(type >= 0 && type < ASSET_TYPE_COUNT); + break; + } + +#undef CASE_INIT_POOL_STATIC +} + +XAssetInfoGeneric* GameAssetPoolIW4::AddAsset(asset_type_t type, std::string name, void* asset, + std::vector& scriptStrings, + std::vector& dependencies) +{ + XAsset xAsset{}; + + xAsset.type = static_cast(type); + xAsset.header.data = asset; + +#define CASE_ADD_TO_POOL(assetType, poolName, headerName) \ + case assetType: \ + { \ + assert((poolName) != nullptr); \ + auto* assetInfo = (poolName)->AddAsset(std::move(name), xAsset.header.headerName, scriptStrings, dependencies); \ + if(assetInfo) \ + { \ + m_assets_in_order.push_back(assetInfo); \ + } \ + return assetInfo; \ + } + + switch (xAsset.type) + { + /*CASE_ADD_TO_POOL(ASSET_TYPE_PHYSPRESET, m_phys_preset, physPreset); + CASE_ADD_TO_POOL(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints, physConstraints); + CASE_ADD_TO_POOL(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def, destructibleDef); + CASE_ADD_TO_POOL(ASSET_TYPE_XANIMPARTS, m_xanim_parts, parts); + CASE_ADD_TO_POOL(ASSET_TYPE_XMODEL, m_xmodel, model); + CASE_ADD_TO_POOL(ASSET_TYPE_MATERIAL, m_material, material); + CASE_ADD_TO_POOL(ASSET_TYPE_TECHNIQUE_SET, m_technique_set, techniqueSet); + CASE_ADD_TO_POOL(ASSET_TYPE_IMAGE, m_image, image); + CASE_ADD_TO_POOL(ASSET_TYPE_SOUND, m_sound_bank, sound); + CASE_ADD_TO_POOL(ASSET_TYPE_SOUND_PATCH, m_sound_patch, soundPatch); + CASE_ADD_TO_POOL(ASSET_TYPE_CLIPMAP, m_clip_map, clipMap); + CASE_ADD_TO_POOL(ASSET_TYPE_CLIPMAP_PVS, m_clip_map, clipMap); + CASE_ADD_TO_POOL(ASSET_TYPE_COMWORLD, m_com_world, comWorld); + CASE_ADD_TO_POOL(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp, gameWorldSp); + CASE_ADD_TO_POOL(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp, gameWorldMp); + CASE_ADD_TO_POOL(ASSET_TYPE_MAP_ENTS, m_map_ents, mapEnts); + CASE_ADD_TO_POOL(ASSET_TYPE_GFXWORLD, m_gfx_world, gfxWorld); + CASE_ADD_TO_POOL(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def, lightDef); + CASE_ADD_TO_POOL(ASSET_TYPE_FONT, m_font, font); + CASE_ADD_TO_POOL(ASSET_TYPE_FONTICON, m_font_icon, fontIcon); + CASE_ADD_TO_POOL(ASSET_TYPE_MENULIST, m_menu_list, menuList); + CASE_ADD_TO_POOL(ASSET_TYPE_MENU, m_menu_def, menu); + CASE_ADD_TO_POOL(ASSET_TYPE_LOCALIZE_ENTRY, m_localize, localize); + CASE_ADD_TO_POOL(ASSET_TYPE_WEAPON, m_weapon, weapon); + CASE_ADD_TO_POOL(ASSET_TYPE_ATTACHMENT, m_attachment, attachment); + CASE_ADD_TO_POOL(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique, attachmentUnique); + CASE_ADD_TO_POOL(ASSET_TYPE_WEAPON_CAMO, m_camo, weaponCamo); + CASE_ADD_TO_POOL(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals, sndDriverGlobals); + CASE_ADD_TO_POOL(ASSET_TYPE_FX, m_fx, fx); + CASE_ADD_TO_POOL(ASSET_TYPE_IMPACT_FX, m_fx_impact_table, impactFx); + CASE_ADD_TO_POOL(ASSET_TYPE_RAWFILE, m_raw_file, rawfile); + CASE_ADD_TO_POOL(ASSET_TYPE_STRINGTABLE, m_string_table, stringTable); + CASE_ADD_TO_POOL(ASSET_TYPE_LEADERBOARD, m_leaderboard, leaderboardDef); + CASE_ADD_TO_POOL(ASSET_TYPE_XGLOBALS, m_xglobals, xGlobals); + CASE_ADD_TO_POOL(ASSET_TYPE_DDL, m_ddl, ddlRoot); + CASE_ADD_TO_POOL(ASSET_TYPE_GLASSES, m_glasses, glasses); + CASE_ADD_TO_POOL(ASSET_TYPE_EMBLEMSET, m_emblem_set, emblemSet); + CASE_ADD_TO_POOL(ASSET_TYPE_SCRIPTPARSETREE, m_script, scriptParseTree); + CASE_ADD_TO_POOL(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs, keyValuePairs); + CASE_ADD_TO_POOL(ASSET_TYPE_VEHICLEDEF, m_vehicle, vehicleDef); + CASE_ADD_TO_POOL(ASSET_TYPE_MEMORYBLOCK, m_memory_block, memoryBlock); + CASE_ADD_TO_POOL(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents, addonMapEnts); + CASE_ADD_TO_POOL(ASSET_TYPE_TRACER, m_tracer, tracerDef); + CASE_ADD_TO_POOL(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts, skinnedVertsDef); + CASE_ADD_TO_POOL(ASSET_TYPE_QDB, m_qdb, qdb); + CASE_ADD_TO_POOL(ASSET_TYPE_SLUG, m_slug, slug); + CASE_ADD_TO_POOL(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table, footstepTableDef); + CASE_ADD_TO_POOL(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table, footstepFXTableDef); + CASE_ADD_TO_POOL(ASSET_TYPE_ZBARRIER, m_zbarrier, zbarrierDef);*/ + + default: + assert(false); + break; + } + + return nullptr; + +#undef CASE_ADD_TO_POOL +} + +XAssetInfoGeneric* GameAssetPoolIW4::GetAsset(const asset_type_t type, std::string name) const +{ +#define CASE_GET_ASSET(assetType, poolName) \ + case assetType: \ + { \ + if((poolName) != nullptr) \ + return (poolName)->GetAsset(std::move(name)); \ + break; \ + } + + switch (type) + { + /*CASE_GET_ASSET(ASSET_TYPE_PHYSPRESET, m_phys_preset); + CASE_GET_ASSET(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints); + CASE_GET_ASSET(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def); + CASE_GET_ASSET(ASSET_TYPE_XANIMPARTS, m_xanim_parts); + CASE_GET_ASSET(ASSET_TYPE_XMODEL, m_xmodel); + CASE_GET_ASSET(ASSET_TYPE_MATERIAL, m_material); + CASE_GET_ASSET(ASSET_TYPE_TECHNIQUE_SET, m_technique_set); + CASE_GET_ASSET(ASSET_TYPE_IMAGE, m_image); + CASE_GET_ASSET(ASSET_TYPE_SOUND, m_sound_bank); + CASE_GET_ASSET(ASSET_TYPE_SOUND_PATCH, m_sound_patch); + CASE_GET_ASSET(ASSET_TYPE_CLIPMAP, m_clip_map); + CASE_GET_ASSET(ASSET_TYPE_CLIPMAP_PVS, m_clip_map); + CASE_GET_ASSET(ASSET_TYPE_COMWORLD, m_com_world); + CASE_GET_ASSET(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp); + CASE_GET_ASSET(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp); + CASE_GET_ASSET(ASSET_TYPE_MAP_ENTS, m_map_ents); + CASE_GET_ASSET(ASSET_TYPE_GFXWORLD, m_gfx_world); + CASE_GET_ASSET(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def); + CASE_GET_ASSET(ASSET_TYPE_FONT, m_font); + CASE_GET_ASSET(ASSET_TYPE_FONTICON, m_font_icon); + CASE_GET_ASSET(ASSET_TYPE_MENULIST, m_menu_list); + CASE_GET_ASSET(ASSET_TYPE_MENU, m_menu_def); + CASE_GET_ASSET(ASSET_TYPE_LOCALIZE_ENTRY, m_localize); + CASE_GET_ASSET(ASSET_TYPE_WEAPON, m_weapon); + CASE_GET_ASSET(ASSET_TYPE_ATTACHMENT, m_attachment); + CASE_GET_ASSET(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique); + CASE_GET_ASSET(ASSET_TYPE_WEAPON_CAMO, m_camo); + CASE_GET_ASSET(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals); + CASE_GET_ASSET(ASSET_TYPE_FX, m_fx); + CASE_GET_ASSET(ASSET_TYPE_IMPACT_FX, m_fx_impact_table); + CASE_GET_ASSET(ASSET_TYPE_RAWFILE, m_raw_file); + CASE_GET_ASSET(ASSET_TYPE_STRINGTABLE, m_string_table); + CASE_GET_ASSET(ASSET_TYPE_LEADERBOARD, m_leaderboard); + CASE_GET_ASSET(ASSET_TYPE_XGLOBALS, m_xglobals); + CASE_GET_ASSET(ASSET_TYPE_DDL, m_ddl); + CASE_GET_ASSET(ASSET_TYPE_GLASSES, m_glasses); + CASE_GET_ASSET(ASSET_TYPE_EMBLEMSET, m_emblem_set); + CASE_GET_ASSET(ASSET_TYPE_SCRIPTPARSETREE, m_script); + CASE_GET_ASSET(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs); + CASE_GET_ASSET(ASSET_TYPE_VEHICLEDEF, m_vehicle); + CASE_GET_ASSET(ASSET_TYPE_MEMORYBLOCK, m_memory_block); + CASE_GET_ASSET(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents); + CASE_GET_ASSET(ASSET_TYPE_TRACER, m_tracer); + CASE_GET_ASSET(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts); + CASE_GET_ASSET(ASSET_TYPE_QDB, m_qdb); + CASE_GET_ASSET(ASSET_TYPE_SLUG, m_slug); + CASE_GET_ASSET(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table); + CASE_GET_ASSET(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table); + CASE_GET_ASSET(ASSET_TYPE_ZBARRIER, m_zbarrier);*/ + + default: + assert(false); + break; + } + + return nullptr; + +#undef CASE_GET_ASSET +} + +const std::string& GameAssetPoolIW4::GetAssetTypeName(const asset_type_t assetType) const +{ + if (assetType >= 0 && assetType < static_cast(_countof(ASSET_TYPE_NAMES))) + return ASSET_TYPE_NAMES[assetType]; + + return ASSET_TYPE_INVALID; +} + +IZoneAssetPools::iterator GameAssetPoolIW4::begin() const +{ + return m_assets_in_order.begin(); +} + +IZoneAssetPools::iterator GameAssetPoolIW4::end() const +{ + return m_assets_in_order.end(); +} diff --git a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h new file mode 100644 index 00000000..2566da53 --- /dev/null +++ b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h @@ -0,0 +1,77 @@ +#pragma once + +#include "Pool/IZoneAssetPools.h" +#include "Pool/AssetPool.h" +#include "IW4.h" + +class GameAssetPoolIW4 final : public IZoneAssetPools +{ + int m_priority; + std::vector m_assets_in_order; + + static const std::string ASSET_TYPE_INVALID; + static const std::string ASSET_TYPE_NAMES[]; + +public: + /*AssetPool* m_phys_preset; + AssetPool* m_phys_constraints; + AssetPool* m_destructible_def; + AssetPool* m_xanim_parts; + AssetPool* m_xmodel; + AssetPool* m_material; + AssetPool* m_technique_set; + AssetPool* m_image; + AssetPool* m_sound_bank; + AssetPool* m_sound_patch; + AssetPool* m_clip_map; + AssetPool* m_com_world; + AssetPool* m_game_world_sp; + AssetPool* m_game_world_mp; + AssetPool* m_map_ents; + AssetPool* m_gfx_world; + AssetPool* m_gfx_light_def; + AssetPool* m_font; + AssetPool* m_font_icon; + AssetPool* m_menu_list; + AssetPool* m_menu_def; + AssetPool* m_localize; + AssetPool* m_weapon; + AssetPool* m_attachment; + AssetPool* m_attachment_unique; + AssetPool* m_camo; + AssetPool* m_snd_driver_globals; + AssetPool* m_fx; + AssetPool* m_fx_impact_table; + AssetPool* m_raw_file; + AssetPool* m_string_table; + AssetPool* m_leaderboard; + AssetPool* m_xglobals; + AssetPool* m_ddl; + AssetPool* m_glasses; + AssetPool* m_emblem_set; + AssetPool* m_script; + AssetPool* m_key_value_pairs; + AssetPool* m_vehicle; + AssetPool* m_memory_block; + AssetPool* m_addon_map_ents; + AssetPool* m_tracer; + AssetPool* m_skinned_verts; + AssetPool* m_qdb; + AssetPool* m_slug; + AssetPool* m_footstep_table; + AssetPool* m_footstep_fx_table; + AssetPool* m_zbarrier;*/ + + explicit GameAssetPoolIW4(int priority); + ~GameAssetPoolIW4() override; + + void InitPoolStatic(asset_type_t type, size_t capacity) override; + void InitPoolDynamic(asset_type_t type) override; + + XAssetInfoGeneric* AddAsset(asset_type_t type, std::string name, void* asset, std::vector& scriptStrings, std::vector& dependencies) override; + XAssetInfoGeneric* GetAsset(asset_type_t type, std::string name) const override; + const std::string& GetAssetTypeName(asset_type_t assetType) const override; + + iterator begin() const override; + iterator end() const override; +}; diff --git a/src/ZoneCommon/Game/IW4/GameIW4.cpp b/src/ZoneCommon/Game/IW4/GameIW4.cpp new file mode 100644 index 00000000..b71e5c8a --- /dev/null +++ b/src/ZoneCommon/Game/IW4/GameIW4.cpp @@ -0,0 +1,37 @@ +#include "GameIW4.h" +#include "IW4.h" + +using namespace IW4; + +GameIW4 g_GameIW4; + +const std::string GameIW4::NAME = "IW4"; + +const std::string& GameIW4::GetName() +{ + return NAME; +} + +void GameIW4::AddZone(Zone* zone) +{ + m_zones.push_back(zone); +} + +void GameIW4::RemoveZone(Zone* zone) +{ + const auto foundEntry = std::find(m_zones.begin(), m_zones.end(), zone); + + if (foundEntry != m_zones.end()) + m_zones.erase(foundEntry); +} + +std::vector GameIW4::GetZones() +{ + return m_zones; +} + +std::vector GameIW4::GetLanguagePrefixes() +{ + std::vector prefixes; + return prefixes; +} diff --git a/src/ZoneCommon/Game/IW4/GameIW4.h b/src/ZoneCommon/Game/IW4/GameIW4.h new file mode 100644 index 00000000..920a55d9 --- /dev/null +++ b/src/ZoneCommon/Game/IW4/GameIW4.h @@ -0,0 +1,17 @@ +#pragma once +#include "Game/IGame.h" + +class GameIW4 : public IGame +{ + static const std::string NAME; + std::vector m_zones; + +public: + const std::string& GetName() override; + void AddZone(Zone* zone) override; + void RemoveZone(Zone* zone) override; + std::vector GetZones() override; + std::vector GetLanguagePrefixes() override; +}; + +extern GameIW4 g_GameIW4; \ No newline at end of file diff --git a/src/ZoneCommon/Game/IW4/IW4.h b/src/ZoneCommon/Game/IW4/IW4.h new file mode 100644 index 00000000..15c74157 --- /dev/null +++ b/src/ZoneCommon/Game/IW4/IW4.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include "Image/Texture.h" + +#include "IW4_Assets.h" + +namespace IW4 +{ + struct DB_AuthHash + { + char bytes[32]; + }; + + struct DB_AuthSignature + { + char bytes[256]; + }; + + struct DB_AuthSubHeader + { + char fastfileName[32]; + unsigned int reserved; + DB_AuthHash masterBlockHashes[244]; + }; + + struct DB_AuthHeader + { + char magic[8]; // + 0 + unsigned int reserved; // + 8 + DB_AuthHash subheaderHash; // + 12 + DB_AuthSignature signedSubheaderHash; // + 44 + DB_AuthSubHeader subheader; // + 300 + }; + + struct ScriptStringList + { + int count; + const char** strings; + }; + + struct XAsset + { + XAssetType type; + XAssetHeader header; + }; + + struct XAssetList + { + ScriptStringList stringList; + int assetCount; + XAsset* assets; + }; +} \ No newline at end of file diff --git a/src/ZoneCommon/Game/IW4/IW4_Assets.h b/src/ZoneCommon/Game/IW4/IW4_Assets.h new file mode 100644 index 00000000..bb93fa40 --- /dev/null +++ b/src/ZoneCommon/Game/IW4/IW4_Assets.h @@ -0,0 +1,114 @@ +#pragma once + +namespace IW4 +{ + + enum XAssetType + { + ASSET_TYPE_PHYSPRESET = 0x0, + ASSET_TYPE_PHYSCOLLMAP = 0x1, + ASSET_TYPE_XANIMPARTS = 0x2, + ASSET_TYPE_XMODEL_SURFS = 0x3, + ASSET_TYPE_XMODEL = 0x4, + ASSET_TYPE_MATERIAL = 0x5, + ASSET_TYPE_PIXELSHADER = 0x6, + ASSET_TYPE_VERTEXSHADER = 0x7, + ASSET_TYPE_VERTEXDECL = 0x8, + ASSET_TYPE_TECHNIQUE_SET = 0x9, + ASSET_TYPE_IMAGE = 0xA, + ASSET_TYPE_SOUND = 0xB, + ASSET_TYPE_SOUND_CURVE = 0xC, + ASSET_TYPE_LOADED_SOUND = 0xD, + ASSET_TYPE_CLIPMAP_SP = 0xE, + ASSET_TYPE_CLIPMAP_MP = 0xF, + ASSET_TYPE_COMWORLD = 0x10, + ASSET_TYPE_GAMEWORLD_SP = 0x11, + ASSET_TYPE_GAMEWORLD_MP = 0x12, + ASSET_TYPE_MAP_ENTS = 0x13, + ASSET_TYPE_FXWORLD = 0x14, + ASSET_TYPE_GFXWORLD = 0x15, + ASSET_TYPE_LIGHT_DEF = 0x16, + ASSET_TYPE_UI_MAP = 0x17, + ASSET_TYPE_FONT = 0x18, + ASSET_TYPE_MENULIST = 0x19, + ASSET_TYPE_MENU = 0x1A, + ASSET_TYPE_LOCALIZE_ENTRY = 0x1B, + ASSET_TYPE_WEAPON = 0x1C, + ASSET_TYPE_SNDDRIVER_GLOBALS = 0x1D, + ASSET_TYPE_FX = 0x1E, + ASSET_TYPE_IMPACT_FX = 0x1F, + ASSET_TYPE_AITYPE = 0x20, + ASSET_TYPE_MPTYPE = 0x21, + ASSET_TYPE_CHARACTER = 0x22, + ASSET_TYPE_XMODELALIAS = 0x23, + ASSET_TYPE_RAWFILE = 0x24, + ASSET_TYPE_STRINGTABLE = 0x25, + ASSET_TYPE_LEADERBOARD = 0x26, + ASSET_TYPE_STRUCTURED_DATA_DEF = 0x27, + ASSET_TYPE_TRACER = 0x28, + ASSET_TYPE_VEHICLE = 0x29, + ASSET_TYPE_ADDON_MAP_ENTS = 0x2A, + + ASSET_TYPE_COUNT, + ASSET_TYPE_STRING = ASSET_TYPE_COUNT, + ASSET_TYPE_ASSETLIST = 0x2C, + + ASSET_TYPE_FULLCOUNT + }; + + enum XFileBlock + { + XFILE_BLOCK_TEMP, + XFILE_BLOCK_PHYSICAL, + XFILE_BLOCK_RUNTIME, + XFILE_BLOCK_VIRTUAL, + XFILE_BLOCK_LARGE, + XFILE_BLOCK_CALLBACK, + XFILE_BLOCK_VERTEX, + XFILE_BLOCK_INDEX, + + MAX_XFILE_COUNT, + }; + + union XAssetHeader + { + /*PhysPreset* physPreset; + PhysCollmap* physCollmap; + XAnimParts* parts; + XModelSurfs* modelSurfs; + XModel* model; + Material* material; + MaterialPixelShader* pixelShader; + MaterialVertexShader* vertexShader; + MaterialVertexDeclaration* vertexDecl; + MaterialTechniqueSet* techniqueSet; + GfxImage* image; + snd_alias_list_t* sound; + SndCurve* sndCurve; + LoadedSound* loadSnd; + clipMap_t* clipMap; + ComWorld* comWorld; + GameWorldSp* gameWorldSp; + GameWorldMp* gameWorldMp; + MapEnts* mapEnts; + FxWorld* fxWorld; + GfxWorld* gfxWorld; + GfxLightDef* lightDef; + Font_s* font; + MenuList* menuList; + menuDef_t* menu; + LocalizeEntry* localize; + WeaponCompleteDef* weapon; + SndDriverGlobals* sndDriverGlobals; + FxEffectDef* fx; + FxImpactTable* impactFx; + RawFile* rawfile; + StringTable* stringTable; + LeaderboardDef* leaderboardDef; + StructuredDataDefSet* structuredDataDefSet; + TracerDef* tracerDef; + VehicleDef* vehDef; + AddonMapEnts* addonMapEnts;*/ + void* data; + }; +} \ No newline at end of file diff --git a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp new file mode 100644 index 00000000..954d824b --- /dev/null +++ b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp @@ -0,0 +1,228 @@ +#include "ContentLoaderIW4.h" +#include "Game/IW4/IW4.h" +#include "Loading/Exception/UnsupportedAssetTypeException.h" + +#include + +//#include "Game/T6/XAssets/addonmapents/addonmapents_load_db.h" +//#include "Game/T6/XAssets/clipmap_t/clipmap_t_load_db.h" +//#include "Game/T6/XAssets/comworld/comworld_load_db.h" +//#include "Game/T6/XAssets/ddlroot_t/ddlroot_t_load_db.h" +//#include "Game/T6/XAssets/destructibledef/destructibledef_load_db.h" +//#include "Game/T6/XAssets/emblemset/emblemset_load_db.h" +//#include "Game/T6/XAssets/font_s/font_s_load_db.h" +//#include "Game/T6/XAssets/fonticon/fonticon_load_db.h" +//#include "Game/T6/XAssets/footstepfxtabledef/footstepfxtabledef_load_db.h" +//#include "Game/T6/XAssets/footsteptabledef/footsteptabledef_load_db.h" +//#include "Game/T6/XAssets/fxeffectdef/fxeffectdef_load_db.h" +//#include "Game/T6/XAssets/fximpacttable/fximpacttable_load_db.h" +//#include "Game/T6/XAssets/gameworldmp/gameworldmp_load_db.h" +//#include "Game/T6/XAssets/gameworldsp/gameworldsp_load_db.h" +//#include "Game/T6/XAssets/gfximage/gfximage_load_db.h" +//#include "Game/T6/XAssets/gfxlightdef/gfxlightdef_load_db.h" +//#include "Game/T6/XAssets/gfxworld/gfxworld_load_db.h" +//#include "Game/T6/XAssets/glasses/glasses_load_db.h" +//#include "Game/T6/XAssets/keyvaluepairs/keyvaluepairs_load_db.h" +//#include "Game/T6/XAssets/leaderboarddef/leaderboarddef_load_db.h" +//#include "Game/T6/XAssets/localizeentry/localizeentry_load_db.h" +//#include "Game/T6/XAssets/mapents/mapents_load_db.h" +//#include "Game/T6/XAssets/material/material_load_db.h" +//#include "Game/T6/XAssets/materialtechniqueset/materialtechniqueset_load_db.h" +//#include "Game/T6/XAssets/memoryblock/memoryblock_load_db.h" +//#include "Game/T6/XAssets/menudef_t/menudef_t_load_db.h" +//#include "Game/T6/XAssets/menulist/menulist_load_db.h" +//#include "Game/T6/XAssets/physconstraints/physconstraints_load_db.h" +//#include "Game/T6/XAssets/physpreset/physpreset_load_db.h" +//#include "Game/T6/XAssets/qdb/qdb_load_db.h" +//#include "Game/T6/XAssets/rawfile/rawfile_load_db.h" +//#include "Game/T6/XAssets/scriptparsetree/scriptparsetree_load_db.h" +//#include "Game/T6/XAssets/skinnedvertsdef/skinnedvertsdef_load_db.h" +//#include "Game/T6/XAssets/slug/slug_load_db.h" +//#include "Game/T6/XAssets/sndbank/sndbank_load_db.h" +//#include "Game/T6/XAssets/snddriverglobals/snddriverglobals_load_db.h" +//#include "Game/T6/XAssets/sndpatch/sndpatch_load_db.h" +//#include "Game/T6/XAssets/stringtable/stringtable_load_db.h" +//#include "Game/T6/XAssets/tracerdef/tracerdef_load_db.h" +//#include "Game/T6/XAssets/vehicledef/vehicledef_load_db.h" +//#include "Game/T6/XAssets/weaponattachment/weaponattachment_load_db.h" +//#include "Game/T6/XAssets/weaponattachmentunique/weaponattachmentunique_load_db.h" +//#include "Game/T6/XAssets/weaponcamo/weaponcamo_load_db.h" +//#include "Game/T6/XAssets/weaponvariantdef/weaponvariantdef_load_db.h" +//#include "Game/T6/XAssets/xanimparts/xanimparts_load_db.h" +//#include "Game/T6/XAssets/xglobals/xglobals_load_db.h" +//#include "Game/T6/XAssets/xmodel/xmodel_load_db.h" +//#include "Game/T6/XAssets/zbarrierdef/zbarrierdef_load_db.h" + +using namespace IW4; + +ContentLoaderIW4::ContentLoaderIW4() +{ + varXAsset = nullptr; + varScriptStringList = nullptr; + + // Script String 0 is always empty string + m_script_strings.emplace_back(""); +} + +void ContentLoaderIW4::LoadScriptStringList(const bool atStreamStart) +{ + m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + + if (atStreamStart) + m_stream->Load(varScriptStringList); + + if (varScriptStringList->strings != nullptr) + { + assert(varScriptStringList->strings == PTR_FOLLOWING); + + varScriptStringList->strings = m_stream->Alloc(alignof(const char*)); + varXString = varScriptStringList->strings; + LoadXStringArray(true, varScriptStringList->count); + + for (int i = 0; i < varScriptStringList->count; i++) + { + if (varScriptStringList->strings[i]) + { + m_script_strings.emplace_back(varScriptStringList->strings[i]); + } + else + { + m_script_strings.emplace_back(""); + } + } + } + + m_stream->PopBlock(); +} + +void ContentLoaderIW4::LoadXAsset(const bool atStreamStart) +{ +#define LOAD_ASSET(type_index, typeName, headerEntry) \ + case type_index: \ + { \ + Loader_##typeName loader(this, m_zone, m_stream); \ + loader.Load(&varXAsset->header.headerEntry); \ + break; \ + } + + assert(varXAsset != nullptr); + + if (atStreamStart) + m_stream->Load(varXAsset); + + switch (varXAsset->type) + { + //LOAD_ASSET(ASSET_TYPE_PHYSPRESET, PhysPreset, physPreset); + //LOAD_ASSET(ASSET_TYPE_PHYSCONSTRAINTS, PhysConstraints, physConstraints); + //LOAD_ASSET(ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef, destructibleDef); + //LOAD_ASSET(ASSET_TYPE_XANIMPARTS, XAnimParts, parts); + //LOAD_ASSET(ASSET_TYPE_XMODEL, XModel, model); + //LOAD_ASSET(ASSET_TYPE_MATERIAL, Material, material); + //LOAD_ASSET(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet, techniqueSet); + //LOAD_ASSET(ASSET_TYPE_IMAGE, GfxImage, image); + //LOAD_ASSET(ASSET_TYPE_SOUND, SndBank, sound); + //LOAD_ASSET(ASSET_TYPE_SOUND_PATCH, SndPatch, soundPatch); + //LOAD_ASSET(ASSET_TYPE_CLIPMAP, clipMap_t, clipMap); + //LOAD_ASSET(ASSET_TYPE_CLIPMAP_PVS, clipMap_t, clipMap); + //LOAD_ASSET(ASSET_TYPE_COMWORLD, ComWorld, comWorld); + //LOAD_ASSET(ASSET_TYPE_GAMEWORLD_SP, GameWorldSp, gameWorldSp); + //LOAD_ASSET(ASSET_TYPE_GAMEWORLD_MP, GameWorldMp, gameWorldMp); + //LOAD_ASSET(ASSET_TYPE_MAP_ENTS, MapEnts, mapEnts); + //LOAD_ASSET(ASSET_TYPE_GFXWORLD, GfxWorld, gfxWorld); + //LOAD_ASSET(ASSET_TYPE_LIGHT_DEF, GfxLightDef, lightDef); + //LOAD_ASSET(ASSET_TYPE_FONT, Font_s, font); + //LOAD_ASSET(ASSET_TYPE_FONTICON, FontIcon, fontIcon); + //LOAD_ASSET(ASSET_TYPE_MENULIST, MenuList, menuList); + //LOAD_ASSET(ASSET_TYPE_MENU, menuDef_t, menu); + //LOAD_ASSET(ASSET_TYPE_LOCALIZE_ENTRY, LocalizeEntry, localize); + //LOAD_ASSET(ASSET_TYPE_WEAPON, WeaponVariantDef, weapon); + //LOAD_ASSET(ASSET_TYPE_ATTACHMENT, WeaponAttachment, attachment); + //LOAD_ASSET(ASSET_TYPE_ATTACHMENT_UNIQUE, WeaponAttachmentUnique, attachmentUnique); + //LOAD_ASSET(ASSET_TYPE_WEAPON_CAMO, WeaponCamo, weaponCamo); + //LOAD_ASSET(ASSET_TYPE_SNDDRIVER_GLOBALS, SndDriverGlobals, sndDriverGlobals); + //LOAD_ASSET(ASSET_TYPE_FX, FxEffectDef, fx); + //LOAD_ASSET(ASSET_TYPE_IMPACT_FX, FxImpactTable, impactFx); + //LOAD_ASSET(ASSET_TYPE_RAWFILE, RawFile, rawfile); + //LOAD_ASSET(ASSET_TYPE_STRINGTABLE, StringTable, stringTable); + //LOAD_ASSET(ASSET_TYPE_LEADERBOARD, LeaderboardDef, leaderboardDef); + //LOAD_ASSET(ASSET_TYPE_XGLOBALS, XGlobals, xGlobals); + //LOAD_ASSET(ASSET_TYPE_DDL, ddlRoot_t, ddlRoot); + //LOAD_ASSET(ASSET_TYPE_GLASSES, Glasses, glasses); + //LOAD_ASSET(ASSET_TYPE_EMBLEMSET, EmblemSet, emblemSet); + //LOAD_ASSET(ASSET_TYPE_SCRIPTPARSETREE, ScriptParseTree, scriptParseTree); + //LOAD_ASSET(ASSET_TYPE_KEYVALUEPAIRS, KeyValuePairs, keyValuePairs); + //LOAD_ASSET(ASSET_TYPE_VEHICLEDEF, VehicleDef, vehicleDef); + //// LOAD_ASSET(ASSET_TYPE_MEMORYBLOCK, MemoryBlock, memoryBlock); + //LOAD_ASSET(ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts, addonMapEnts); + //LOAD_ASSET(ASSET_TYPE_TRACER, TracerDef, tracerDef); + //LOAD_ASSET(ASSET_TYPE_SKINNEDVERTS, SkinnedVertsDef, skinnedVertsDef); + //LOAD_ASSET(ASSET_TYPE_QDB, Qdb, qdb); + //LOAD_ASSET(ASSET_TYPE_SLUG, Slug, slug); + //LOAD_ASSET(ASSET_TYPE_FOOTSTEP_TABLE, FootstepTableDef, footstepTableDef); + //LOAD_ASSET(ASSET_TYPE_FOOTSTEPFX_TABLE, FootstepFXTableDef, footstepFXTableDef); + //LOAD_ASSET(ASSET_TYPE_ZBARRIER, ZBarrierDef, zbarrierDef); + + default: + { + throw UnsupportedAssetTypeException(varXAsset->type); + } + } + +#undef LOAD_ASSET +} + +void ContentLoaderIW4::LoadXAssetArray(const bool atStreamStart, const size_t count) +{ + assert(varXAsset != nullptr); + + if (atStreamStart) + m_stream->Load(varXAsset, count); + + for (asset_type_t assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + { + m_zone->GetPools()->InitPoolDynamic(assetType); + } + + for (size_t index = 0; index < count; index++) + { + LoadXAsset(false); + varXAsset++; + } +} + +void ContentLoaderIW4::Load(Zone* zone, IZoneInputStream* stream) +{ + m_zone = zone; + m_stream = stream; + + m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + + XAssetList assetList{}; + m_stream->LoadDataRaw(&assetList, sizeof assetList); + + varScriptStringList = &assetList.stringList; + LoadScriptStringList(false); + + if (assetList.assets != nullptr) + { + assert(assetList.assets == PTR_FOLLOWING); + + assetList.assets = m_stream->Alloc(alignof(XAsset)); + varXAsset = assetList.assets; + LoadXAssetArray(true, assetList.assetCount); + } + + m_stream->PopBlock(); +} + +std::string& ContentLoaderIW4::GetZoneScriptString(const scr_string_t scrString) +{ + assert(scrString >= 0 && scrString < m_script_strings.size()); + + if (scrString < 0 || scrString >= m_script_strings.size()) + { + return m_script_strings[0]; + } + + return m_script_strings[scrString]; +} \ No newline at end of file diff --git a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h new file mode 100644 index 00000000..5237c7c7 --- /dev/null +++ b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h @@ -0,0 +1,23 @@ +#pragma once +#include "Loading/ContentLoader.h" +#include "Loading/IContentLoadingEntryPoint.h" +#include "Game/IW4/IW4.h" +#include "Loading/IZoneScriptStringProvider.h" + +class ContentLoaderIW4 final : public ContentLoader, public IContentLoadingEntryPoint, public IZoneScriptStringProvider +{ + std::vector m_script_strings; + IW4::XAsset* varXAsset; + IW4::ScriptStringList* varScriptStringList; + + void LoadScriptStringList(bool atStreamStart); + + void LoadXAsset(bool atStreamStart); + void LoadXAssetArray(bool atStreamStart, size_t count); + +public: + ContentLoaderIW4(); + + void Load(Zone* zone, IZoneInputStream* stream) override; + std::string& GetZoneScriptString(scr_string_t scrString) override; +}; diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp new file mode 100644 index 00000000..5634d742 --- /dev/null +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp @@ -0,0 +1,234 @@ +#include "ZoneLoaderFactoryIW4.h" +#include "Game/IW4/IW4.h" + +#include "Loading/Steps/StepVerifyMagic.h" +#include "Loading/Steps/StepSkipBytes.h" +#include "Loading/Steps/StepVerifyFileName.h" +#include "Loading/Steps/StepLoadSignature.h" +#include "Loading/Steps/StepVerifySignature.h" +#include "Loading/Steps/StepAddProcessor.h" +#include "Loading/Steps/StepAllocXBlocks.h" + +#include "Utils/ClassUtils.h" +#include +#include "Loading/Steps/StepLoadZoneContent.h" +#include "ContentLoaderIW4.h" +#include "Game/IW4/GameAssetPoolIW4.h" +#include "Game/IW4/GameIW4.h" +#include "Game/GameLanguage.h" +#include "Loading/Processor/ProcessorCaptureData.h" +#include "Loading/Steps/StepLoadHash.h" +#include "Loading/Steps/StepRemoveProcessor.h" +#include "Loading/Steps/StepVerifyHash.h" + +const std::string ZoneLoaderFactoryIW4::MAGIC_SIGNED_INFINITY_WARD = "IWff0100"; +const std::string ZoneLoaderFactoryIW4::MAGIC_UNSIGNED = "IWffu100"; +const int ZoneLoaderFactoryIW4::VERSION = 276; + +const int ZoneLoaderFactoryIW4::STREAM_COUNT = 4; +const int ZoneLoaderFactoryIW4::VANILLA_BUFFER_SIZE = 0x80000; +const int ZoneLoaderFactoryIW4::OFFSET_BLOCK_BIT_COUNT = 4; +const block_t ZoneLoaderFactoryIW4::INSERT_BLOCK = IW4::XFILE_BLOCK_VIRTUAL; + +const std::string ZoneLoaderFactoryIW4::MAGIC_AUTH_HEADER = "IWffs100"; + +const uint8_t ZoneLoaderFactoryIW4::RSA_PUBLIC_KEY_INFINITY_WARD[] +{ + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xA5, 0x86, 0xCC, 0x18, 0xA9, 0x12, 0x17, + 0x4F, 0x3A, 0xC9, 0x0C, 0xD2, 0x38, 0x5D, 0xDB, + 0x67, 0x62, 0xA4, 0xE3, 0xD4, 0x42, 0x05, 0x8A, + 0x57, 0x0C, 0x31, 0x4E, 0x19, 0xE4, 0xBA, 0x89, + 0x73, 0x13, 0xDB, 0x72, 0x25, 0x63, 0xB1, 0x2F, + 0xD7, 0xF1, 0x08, 0x48, 0x34, 0x06, 0xD7, 0x84, + 0x5F, 0xC8, 0xCF, 0x2F, 0xB6, 0xA3, 0x5A, 0x8F, + 0x7E, 0xAA, 0x9D, 0x51, 0xE7, 0x0F, 0xB9, 0x07, + 0xB7, 0x30, 0x91, 0x04, 0x39, 0x9C, 0xDC, 0x1C, + 0xF1, 0x16, 0xCB, 0x96, 0x10, 0xEB, 0x38, 0xB1, + 0x3B, 0xBA, 0x42, 0xE3, 0xE2, 0x78, 0xBD, 0x77, + 0x82, 0x1A, 0x2B, 0x54, 0x27, 0x0A, 0xF7, 0x66, + 0x06, 0xAD, 0x46, 0x39, 0xC0, 0xEB, 0xB5, 0xC2, + 0x27, 0xDD, 0x2C, 0x08, 0x62, 0x2C, 0x0B, 0xC4, + 0x00, 0x0D, 0xCB, 0xAD, 0x22, 0x67, 0x01, 0xA6, + 0x92, 0x9C, 0x00, 0xAF, 0x9D, 0x55, 0xCC, 0x68, + 0xEC, 0x39, 0x49, 0x85, 0x7E, 0x2C, 0x98, 0xCF, + 0x4C, 0x12, 0x8D, 0xED, 0xC7, 0x1D, 0x21, 0x54, + 0x9C, 0x2F, 0xC9, 0x54, 0x36, 0x08, 0xA9, 0x67, + 0xEE, 0x91, 0xE6, 0xD9, 0xB1, 0xFA, 0xA9, 0x2B, + 0x88, 0xAD, 0x2A, 0xD0, 0xAA, 0x28, 0xF9, 0x47, + 0xA6, 0x0F, 0xCF, 0x55, 0x4C, 0x9B, 0x26, 0x41, + 0x89, 0x76, 0x11, 0xFD, 0x1B, 0x83, 0xE4, 0xE8, + 0x8E, 0x7E, 0xB4, 0x03, 0xA3, 0x29, 0xDD, 0x4F, + 0xAC, 0x99, 0xBE, 0x7C, 0xD3, 0xFD, 0x14, 0x28, + 0x1C, 0x59, 0x69, 0xE0, 0x79, 0x5F, 0x4B, 0xDA, + 0x6B, 0xAB, 0x48, 0x4E, 0x28, 0x39, 0x84, 0xC6, + 0x2B, 0xC6, 0x20, 0x05, 0xDB, 0x05, 0x21, 0xC3, + 0xE1, 0xD4, 0x20, 0x28, 0xDD, 0x3A, 0x4D, 0x51, + 0xE7, 0x49, 0x8A, 0x49, 0xEF, 0xF5, 0xDA, 0xDA, + 0x7D, 0x5D, 0xA8, 0x0B, 0xA1, 0x77, 0xCD, 0x62, + 0x7D, 0x9D, 0x40, 0x26, 0x44, 0x4B, 0x3B, 0x0A, + 0x89, 0x02, 0x03, 0x01, 0x00, 0x01 +}; + +class ZoneLoaderFactoryIW4::Impl +{ + static GameLanguage GetZoneLanguage(std::string& zoneName) + { + return GameLanguage::LANGUAGE_NONE; + } + + static bool CanLoad(ZoneHeader& header, bool* isSecure, bool* isOfficial) + { + assert(isSecure != nullptr); + assert(isOfficial != nullptr); + + if (header.m_version != VERSION) + { + return false; + } + + if (!memcmp(header.m_magic, MAGIC_SIGNED_INFINITY_WARD.c_str(), 8)) + { + *isSecure = true; + *isOfficial = true; + return true; + } + + if (!memcmp(header.m_magic, MAGIC_UNSIGNED.c_str(), 8)) + { + *isSecure = false; + *isOfficial = true; + return true; + } + + return false; + } + + static void SetupBlock(ZoneLoader* zoneLoader) + { +#define XBLOCK_DEF(name, type) new XBlock(STR(name), name, type) + + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader->AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + +#undef XBLOCK_DEF + } + + static IPublicKeyAlgorithm* SetupRSA(const bool isOfficial) + { + if (isOfficial) + { + auto* rsa = Crypto::CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm::RSA_HASH_SHA256, + Crypto::RSAPaddingMode::RSA_PADDING_PSS); + + if (!rsa->SetKey(RSA_PUBLIC_KEY_INFINITY_WARD, sizeof(RSA_PUBLIC_KEY_INFINITY_WARD))) + { + printf("Invalid public key for signature checking\n"); + + delete rsa; + return nullptr; + } + + return rsa; + } + else + { + assert(false); + + // TODO: Load custom RSA key here + return nullptr; + } + } + + static IHashProvider* AddAuthHeaderSteps(const bool isSecure, const bool isOfficial, ZoneLoader* zoneLoader, std::string& fileName) + { + // Unsigned zones do not have an auth header + if (!isSecure) + return nullptr; + + // If file is signed setup a RSA instance. + IPublicKeyAlgorithm* rsa = SetupRSA(isOfficial); + auto sha256 = std::unique_ptr(Crypto::CreateSHA256()); + + zoneLoader->AddLoadingStep(new StepVerifyMagic(MAGIC_AUTH_HEADER.c_str())); + zoneLoader->AddLoadingStep(new StepSkipBytes(4)); // Skip reserved + + auto* subheaderHash = new StepLoadHash(sizeof IW4::DB_AuthHash::bytes, 1); + zoneLoader->AddLoadingStep(subheaderHash); + + auto* subheaderHashSignature = new StepLoadSignature(sizeof IW4::DB_AuthSignature::bytes); + zoneLoader->AddLoadingStep(subheaderHashSignature); + + zoneLoader->AddLoadingStep(new StepVerifySignature(rsa, subheaderHashSignature, subheaderHash)); + + auto* subHeaderCapture = new ProcessorCaptureData(sizeof(IW4::DB_AuthSubHeader)); + zoneLoader->AddLoadingStep(new StepAddProcessor(subHeaderCapture)); + + zoneLoader->AddLoadingStep(new StepVerifyFileName(fileName, sizeof IW4::DB_AuthSubHeader::fastfileName)); + zoneLoader->AddLoadingStep(new StepSkipBytes(4)); // Skip reserved + auto* masterBlockHashes = new StepLoadHash(sizeof IW4::DB_AuthHash::bytes, _countof(IW4::DB_AuthSubHeader::masterBlockHashes)); + zoneLoader->AddLoadingStep(masterBlockHashes); + + zoneLoader->AddLoadingStep(new StepRemoveProcessor(subHeaderCapture)); + zoneLoader->AddLoadingStep(new StepVerifyHash(std::move(sha256), 0, subheaderHash, subHeaderCapture)); + + return masterBlockHashes; + } + +public: + static ZoneLoader* CreateLoaderForHeader(ZoneHeader& header, std::string& fileName) + { + bool isSecure; + bool isOfficial; + + // Check if this file is a supported IW4 zone. + if (!CanLoad(header, &isSecure, &isOfficial)) + return nullptr; + + // Create new zone + auto* zone = new Zone(fileName, 0, new GameAssetPoolIW4(0), &g_GameIW4); + zone->m_language = GetZoneLanguage(fileName); + + // File is supported. Now setup all required steps for loading this file. + auto* zoneLoader = new ZoneLoader(zone); + + SetupBlock(zoneLoader); + + // Skip unknown 1 byte field that the game ignores as well + zoneLoader->AddLoadingStep(new StepSkipBytes(1)); + + // Skip timestamp + zoneLoader->AddLoadingStep(new StepSkipBytes(8)); + + // Add steps for loading the auth header which also contain the signature of the zone if it is signed. + IHashProvider* masterBlockHashProvider = AddAuthHeaderSteps(isSecure, isOfficial, zoneLoader, fileName); + + // Start of the XFile struct + zoneLoader->AddLoadingStep(new StepSkipBytes(8)); + // Skip size and externalSize fields since they are not interesting for us + zoneLoader->AddLoadingStep(new StepAllocXBlocks()); + + // Start of the zone content + zoneLoader->AddLoadingStep( + new StepLoadZoneContent(new ContentLoaderIW4(), zone, OFFSET_BLOCK_BIT_COUNT, INSERT_BLOCK)); + + /*if (isSecure) + { + zoneLoader->AddLoadingStep(new StepVerifySignature(rsa, signatureProvider, signatureDataProvider)); + }*/ + + // Return the fully setup zoneloader + return zoneLoader; + } +}; + +ZoneLoader* ZoneLoaderFactoryIW4::CreateLoaderForHeader(ZoneHeader& header, std::string& fileName) +{ + return Impl::CreateLoaderForHeader(header, fileName); +} diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.h b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.h new file mode 100644 index 00000000..18d3bdc1 --- /dev/null +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Loading/IZoneLoaderFactory.h" +#include + +class ZoneLoaderFactoryIW4 final : public IZoneLoaderFactory +{ + static const std::string MAGIC_SIGNED_INFINITY_WARD; + static const std::string MAGIC_UNSIGNED; + static const int VERSION; + + static const int STREAM_COUNT; + static const int VANILLA_BUFFER_SIZE; + static const int OFFSET_BLOCK_BIT_COUNT; + static const block_t INSERT_BLOCK; + + static const std::string MAGIC_AUTH_HEADER; + static const uint8_t RSA_PUBLIC_KEY_INFINITY_WARD[]; + + class Impl; + +public: + ZoneLoader* CreateLoaderForHeader(ZoneHeader& header, std::string& fileName) override; +}; diff --git a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp index b119dc38..0e7f88b0 100644 --- a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp +++ b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp @@ -203,9 +203,9 @@ class ZoneLoaderFactoryT6::ZoneLoaderFactoryT6Impl return signatureLoadStep; } - static ISignatureDataProvider* AddXChunkProcessor(bool isEncrypted, ZoneLoader* zoneLoader, std::string& fileName) + static ICapturedDataProvider* AddXChunkProcessor(bool isEncrypted, ZoneLoader* zoneLoader, std::string& fileName) { - ISignatureDataProvider* result = nullptr; + ICapturedDataProvider* result = nullptr; auto* xChunkProcessor = new ProcessorXChunks(STREAM_COUNT, XCHUNK_SIZE, VANILLA_BUFFER_SIZE); if(isEncrypted) @@ -251,7 +251,7 @@ public: ISignatureProvider* signatureProvider = AddAuthHeaderSteps(isSecure, zoneLoader, fileName); // Setup loading XChunks from the zone from this point on. - ISignatureDataProvider* signatureDataProvider = AddXChunkProcessor(isEncrypted, zoneLoader, fileName); + ICapturedDataProvider* signatureDataProvider = AddXChunkProcessor(isEncrypted, zoneLoader, fileName); // Start of the XFile struct zoneLoader->AddLoadingStep(new StepSkipBytes(8)); // Skip size and externalSize fields since they are not interesting for us diff --git a/src/ZoneLoading/Loading/Exception/InvalidHashException.cpp b/src/ZoneLoading/Loading/Exception/InvalidHashException.cpp new file mode 100644 index 00000000..327ddbef --- /dev/null +++ b/src/ZoneLoading/Loading/Exception/InvalidHashException.cpp @@ -0,0 +1,11 @@ +#include "InvalidHashException.h" + +std::string InvalidHashException::DetailedMessage() +{ + return "Loaded fastfile has an invalid hash."; +} + +char const* InvalidHashException::what() const +{ + return "Loaded fastfile has an invalid hash."; +} \ No newline at end of file diff --git a/src/ZoneLoading/Loading/Exception/InvalidHashException.h b/src/ZoneLoading/Loading/Exception/InvalidHashException.h new file mode 100644 index 00000000..07de0764 --- /dev/null +++ b/src/ZoneLoading/Loading/Exception/InvalidHashException.h @@ -0,0 +1,9 @@ +#pragma once +#include "LoadingException.h" + +class InvalidHashException final : public LoadingException +{ +public: + std::string DetailedMessage() override; + char const* what() const override; +}; diff --git a/src/ZoneLoading/Loading/ICapturedDataProvider.h b/src/ZoneLoading/Loading/ICapturedDataProvider.h new file mode 100644 index 00000000..4c37420f --- /dev/null +++ b/src/ZoneLoading/Loading/ICapturedDataProvider.h @@ -0,0 +1,8 @@ +#pragma once +#include + +class ICapturedDataProvider +{ +public: + virtual void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) = 0; +}; diff --git a/src/ZoneLoading/Loading/IHashProvider.h b/src/ZoneLoading/Loading/IHashProvider.h new file mode 100644 index 00000000..27d8562c --- /dev/null +++ b/src/ZoneLoading/Loading/IHashProvider.h @@ -0,0 +1,8 @@ +#pragma once +#include + +class IHashProvider +{ +public: + virtual void GetHash(unsigned hashIndex, const uint8_t** pHash, size_t* pSize) = 0; +}; diff --git a/src/ZoneLoading/Loading/ISignatureDataProvider.h b/src/ZoneLoading/Loading/ISignatureDataProvider.h deleted file mode 100644 index 526beaa8..00000000 --- a/src/ZoneLoading/Loading/ISignatureDataProvider.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -class ISignatureDataProvider -{ -public: - virtual void GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) = 0; -}; diff --git a/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp new file mode 100644 index 00000000..506652b1 --- /dev/null +++ b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp @@ -0,0 +1,47 @@ +#include "ProcessorAuthedBlocks.h" + +class ProcessorAuthedBlocks::Impl final : public StreamProcessor +{ + const int m_authed_chunk_count; + const int m_max_master_block_count; + IHashProvider* m_hash_provider; + +public: + Impl(const int authedChunkCount, const int maxMasterBlockCount, IHashProvider* masterBlockHashProvider) + : m_authed_chunk_count(authedChunkCount), + m_max_master_block_count(maxMasterBlockCount), + m_hash_provider(masterBlockHashProvider) + { + } + + size_t Load(void* buffer, size_t length) override + { + return 0; + } + + int64_t Pos() override + { + return 0; + } +}; + +ProcessorAuthedBlocks::ProcessorAuthedBlocks(const int authedChunkCount, const int maxMasterBlockCount, IHashProvider* masterBlockHashProvider) + : m_impl(new Impl(authedChunkCount, maxMasterBlockCount, masterBlockHashProvider)) +{ +} + +ProcessorAuthedBlocks::~ProcessorAuthedBlocks() +{ + delete m_impl; + m_impl = nullptr; +} + +size_t ProcessorAuthedBlocks::Load(void* buffer, const size_t length) +{ + return m_impl->Load(buffer, length); +} + +int64_t ProcessorAuthedBlocks::Pos() +{ + return m_impl->Pos(); +} diff --git a/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h new file mode 100644 index 00000000..03db7597 --- /dev/null +++ b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h @@ -0,0 +1,16 @@ +#pragma once +#include "Loading/StreamProcessor.h" +#include "Loading/IHashProvider.h" + +class ProcessorAuthedBlocks : public StreamProcessor +{ + class Impl; + Impl* m_impl; + +public: + ProcessorAuthedBlocks(int authedChunkCount, int maxMasterBlockCount, IHashProvider* masterBlockHashProvider); + ~ProcessorAuthedBlocks() override; + + size_t Load(void* buffer, size_t length) override; + int64_t Pos() override; +}; diff --git a/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp new file mode 100644 index 00000000..1eae5253 --- /dev/null +++ b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp @@ -0,0 +1,50 @@ +#include "ProcessorCaptureData.h" + +#include + +ProcessorCaptureData::ProcessorCaptureData(const size_t captureSize) + : m_data(std::make_unique(captureSize)), + m_capture_size(captureSize), + m_captured_data_size(0) +{ +} + +ProcessorCaptureData::~ProcessorCaptureData() += default; + +size_t ProcessorCaptureData::Load(void* buffer, const size_t length) +{ + if (m_captured_data_size >= m_capture_size) + return m_base_stream->Load(buffer, length); + + size_t dataToCapture = m_capture_size - m_captured_data_size; + + if (length < dataToCapture) + dataToCapture = length; + + size_t loadedSize = m_base_stream->Load(&m_data[m_captured_data_size], dataToCapture); + memcpy_s(buffer, length, &m_data[m_captured_data_size], loadedSize); + + m_captured_data_size += loadedSize; + + if(length > dataToCapture) + loadedSize += m_base_stream->Load(&static_cast(buffer)[dataToCapture], length - dataToCapture); + + return loadedSize; +} + +int64_t ProcessorCaptureData::Pos() +{ + return m_base_stream->Pos(); +} + +void ProcessorCaptureData::GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) +{ + assert(pCapturedData != nullptr); + assert(pSize != nullptr); + + assert(m_captured_data_size == m_capture_size); + + *pCapturedData = m_data.get(); + *pSize = m_captured_data_size; +} diff --git a/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h new file mode 100644 index 00000000..1c827404 --- /dev/null +++ b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h @@ -0,0 +1,20 @@ +#pragma once +#include + +#include "Loading/StreamProcessor.h" +#include "Loading/ICapturedDataProvider.h" + +class ProcessorCaptureData final : public StreamProcessor, public ICapturedDataProvider +{ + std::unique_ptr m_data; + const size_t m_capture_size; + size_t m_captured_data_size; + +public: + explicit ProcessorCaptureData(size_t captureSize); + ~ProcessorCaptureData() override; + + size_t Load(void* buffer, size_t length) override; + int64_t Pos() override; + void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; +}; diff --git a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp index cfedb9c0..648f060b 100644 --- a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp +++ b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.cpp @@ -150,7 +150,7 @@ size_t ChunkProcessorSalsa20::Process(const int streamNumber, const uint8_t* inp return m_impl->Process(streamNumber, input, inputLength, output, outputBufferSize); } -void ChunkProcessorSalsa20::GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) +void ChunkProcessorSalsa20::GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) { - m_impl->GetSignatureData(pSignatureData, pSize); + m_impl->GetSignatureData(pCapturedData, pSize); } \ No newline at end of file diff --git a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h index 8d822f15..7ddb4a3f 100644 --- a/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h +++ b/src/ZoneLoading/Loading/Processor/XChunks/ChunkProcessorSalsa20.h @@ -1,9 +1,9 @@ #pragma once #include "IXChunkProcessor.h" -#include "Loading/ISignatureDataProvider.h" +#include "Loading/ICapturedDataProvider.h" #include -class ChunkProcessorSalsa20 : public IXChunkProcessor, public ISignatureDataProvider +class ChunkProcessorSalsa20 : public IXChunkProcessor, public ICapturedDataProvider { class ChunkProcessorSalsa20Impl; ChunkProcessorSalsa20Impl* m_impl; @@ -13,5 +13,5 @@ public: ~ChunkProcessorSalsa20() override; size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override; - void GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) override; + void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; }; diff --git a/src/ZoneLoading/Loading/Steps/StepLoadHash.cpp b/src/ZoneLoading/Loading/Steps/StepLoadHash.cpp new file mode 100644 index 00000000..847f5c5b --- /dev/null +++ b/src/ZoneLoading/Loading/Steps/StepLoadHash.cpp @@ -0,0 +1,42 @@ +#include "StepLoadHash.h" +#include "Loading/Exception/UnexpectedEndOfFileException.h" +#include + +StepLoadHash::StepLoadHash(const size_t hashSize, const unsigned hashCount) + : m_hash_size(hashSize), + m_hash_count(hashCount), + m_hashes(std::make_unique(hashSize * hashCount)) +{ +} + +StepLoadHash::~StepLoadHash() += default; + +void StepLoadHash::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) +{ + assert(stream != nullptr); + + if (stream->Load(m_hashes.get(), m_hash_size * m_hash_count) != m_hash_size * m_hash_count) + throw UnexpectedEndOfFileException(); +} + +void StepLoadHash::GetHash(const unsigned hashIndex, const uint8_t** pHash, size_t* pSize) +{ + assert(pHash != nullptr); + assert(pSize != nullptr); + assert(hashIndex >= 0 && hashIndex < m_hash_count); + + assert(m_hashes); + + *pHash = &m_hashes[m_hash_size * hashIndex]; + *pSize = m_hash_size; +} + +void StepLoadHash::GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) +{ + assert(pCapturedData != nullptr); + assert(pSize != nullptr); + + *pCapturedData = m_hashes.get(); + *pSize = m_hash_size * m_hash_count; +} diff --git a/src/ZoneLoading/Loading/Steps/StepLoadHash.h b/src/ZoneLoading/Loading/Steps/StepLoadHash.h new file mode 100644 index 00000000..8d1e8652 --- /dev/null +++ b/src/ZoneLoading/Loading/Steps/StepLoadHash.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "Loading/ICapturedDataProvider.h" +#include "Loading/ILoadingStep.h" +#include "Loading/IHashProvider.h" + +class StepLoadHash final : public ILoadingStep, public IHashProvider, public ICapturedDataProvider +{ + const size_t m_hash_size; + const unsigned m_hash_count; + std::unique_ptr m_hashes; + +public: + StepLoadHash(size_t hashSize, unsigned hashCount); + ~StepLoadHash() override; + + StepLoadHash(const StepLoadHash& other) = delete; + StepLoadHash(StepLoadHash&& other) noexcept = default; + StepLoadHash& operator=(const StepLoadHash& other) = delete; + StepLoadHash& operator=(StepLoadHash&& other) noexcept = delete; + + void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override; + void GetHash(unsigned hashIndex, const uint8_t** pHash, size_t* pSize) override; + void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; +}; diff --git a/src/ZoneLoading/Loading/Steps/StepRemoveProcessor.cpp b/src/ZoneLoading/Loading/Steps/StepRemoveProcessor.cpp new file mode 100644 index 00000000..6e47f97e --- /dev/null +++ b/src/ZoneLoading/Loading/Steps/StepRemoveProcessor.cpp @@ -0,0 +1,26 @@ +#include "StepRemoveProcessor.h" +#include + +StepRemoveProcessor::StepRemoveProcessor(StreamProcessor* streamProcessor) + : m_stream_processor(streamProcessor), + m_removed(false) +{ +} + +StepRemoveProcessor::~StepRemoveProcessor() +{ + if(m_removed) + { + delete m_stream_processor; + m_stream_processor = nullptr; + } +} + +void StepRemoveProcessor::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) +{ + assert(zoneLoader != nullptr); + assert(m_stream_processor != nullptr); + + zoneLoader->RemoveStreamProcessor(m_stream_processor); + m_removed = true; +} diff --git a/src/ZoneLoading/Loading/Steps/StepRemoveProcessor.h b/src/ZoneLoading/Loading/Steps/StepRemoveProcessor.h new file mode 100644 index 00000000..89aeb734 --- /dev/null +++ b/src/ZoneLoading/Loading/Steps/StepRemoveProcessor.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Loading/ILoadingStep.h" + +class StepRemoveProcessor final : public ILoadingStep +{ + StreamProcessor* m_stream_processor; + bool m_removed; + +public: + explicit StepRemoveProcessor(StreamProcessor* streamProcessor); + ~StepRemoveProcessor() override; + + void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override; +}; diff --git a/src/ZoneLoading/Loading/Steps/StepVerifyFileName.cpp b/src/ZoneLoading/Loading/Steps/StepVerifyFileName.cpp index cceedb85..3f633f63 100644 --- a/src/ZoneLoading/Loading/Steps/StepVerifyFileName.cpp +++ b/src/ZoneLoading/Loading/Steps/StepVerifyFileName.cpp @@ -1,4 +1,7 @@ #include "StepVerifyFileName.h" + +#include + #include "Loading/Exception/InvalidFileNameException.h" StepVerifyFileName::StepVerifyFileName(std::string fileName, const size_t fileNameBufferSize) @@ -12,7 +15,7 @@ StepVerifyFileName::StepVerifyFileName(std::string fileName, const size_t fileNa void StepVerifyFileName::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) { - std::string originalFileName; + std::stringstream originalFilenameStream; unsigned bufferOffset = 0; char c; @@ -27,7 +30,7 @@ void StepVerifyFileName::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* str break; } - originalFileName += c; + originalFilenameStream << c; } // Skip the rest of the buffer which should be null bytes @@ -37,6 +40,8 @@ void StepVerifyFileName::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* str bufferOffset++; } + std::string originalFileName = originalFilenameStream.str(); + if(originalFileName != m_file_name) throw InvalidFileNameException(m_file_name, originalFileName); } \ No newline at end of file diff --git a/src/ZoneLoading/Loading/Steps/StepVerifyHash.cpp b/src/ZoneLoading/Loading/Steps/StepVerifyHash.cpp new file mode 100644 index 00000000..7f100dac --- /dev/null +++ b/src/ZoneLoading/Loading/Steps/StepVerifyHash.cpp @@ -0,0 +1,39 @@ +#include "StepVerifyHash.h" + +#include + +#include "Loading/Exception/InvalidHashException.h" + +StepVerifyHash::StepVerifyHash(std::unique_ptr hashFunction, const unsigned hashIndex, IHashProvider* hashProvider, + ICapturedDataProvider* dataProvider) + : m_hash_function(std::move(hashFunction)), + m_hash_index(hashIndex), + m_hash_provider(hashProvider), + m_data_provider(dataProvider) +{ +} + +StepVerifyHash::~StepVerifyHash() += default; + +void StepVerifyHash::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) +{ + const uint8_t* dataToHash = nullptr; + size_t dataToHashSize = 0; + m_data_provider->GetCapturedData(&dataToHash, &dataToHashSize); + + const uint8_t* hashData = nullptr; + size_t hashSize = 0; + m_hash_provider->GetHash(m_hash_index, &hashData, &hashSize); + + if (hashSize != m_hash_function->GetHashSize()) + throw InvalidHashException(); + + const std::unique_ptr hashMemory = std::make_unique(m_hash_function->GetHashSize()); + m_hash_function->Init(); + m_hash_function->Process(dataToHash, dataToHashSize); + m_hash_function->Finish(hashMemory.get()); + + if(std::memcmp(hashData, hashMemory.get(), m_hash_function->GetHashSize()) != 0) + throw InvalidHashException(); +} diff --git a/src/ZoneLoading/Loading/Steps/StepVerifyHash.h b/src/ZoneLoading/Loading/Steps/StepVerifyHash.h new file mode 100644 index 00000000..397cb5fb --- /dev/null +++ b/src/ZoneLoading/Loading/Steps/StepVerifyHash.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "Crypto.h" +#include "Loading/ILoadingStep.h" +#include "Loading/ICapturedDataProvider.h" +#include "Loading/IHashProvider.h" + +class StepVerifyHash final : public ILoadingStep +{ + std::unique_ptr m_hash_function; + unsigned m_hash_index; + IHashProvider* m_hash_provider; + ICapturedDataProvider* m_data_provider; + +public: + StepVerifyHash(std::unique_ptr hashFunction, unsigned hashIndex, IHashProvider* hashProvider, ICapturedDataProvider* dataProvider); + ~StepVerifyHash(); + StepVerifyHash(const StepVerifyHash& other) = delete; + StepVerifyHash(StepVerifyHash&& other) noexcept = default; + StepVerifyHash& operator=(const StepVerifyHash& other) = delete; + StepVerifyHash& operator=(StepVerifyHash&& other) noexcept = default; + + void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override; +}; diff --git a/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp b/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp index 28db12bc..1ce1b9cf 100644 --- a/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp +++ b/src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp @@ -2,7 +2,7 @@ #include "Loading/Exception/InvalidSignatureException.h" #include -StepVerifySignature::StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ISignatureDataProvider* signatureDataProvider) +StepVerifySignature::StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider) { m_algorithm = signatureAlgorithm; m_signature_provider = signatureProvider; @@ -27,7 +27,7 @@ void StepVerifySignature::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* st const uint8_t* signatureData; size_t signatureDataSize; - m_signature_data_provider->GetSignatureData(&signatureData, &signatureDataSize); + m_signature_data_provider->GetCapturedData(&signatureData, &signatureDataSize); if(!m_algorithm->Verify(signatureData, signatureDataSize, signature, signatureSize)) { diff --git a/src/ZoneLoading/Loading/Steps/StepVerifySignature.h b/src/ZoneLoading/Loading/Steps/StepVerifySignature.h index 90683033..722190a6 100644 --- a/src/ZoneLoading/Loading/Steps/StepVerifySignature.h +++ b/src/ZoneLoading/Loading/Steps/StepVerifySignature.h @@ -3,17 +3,21 @@ #include "Loading/ILoadingStep.h" #include "Crypto.h" #include "Loading/ISignatureProvider.h" -#include "Loading/ISignatureDataProvider.h" +#include "Loading/ICapturedDataProvider.h" class StepVerifySignature final : public ILoadingStep { IPublicKeyAlgorithm* m_algorithm; ISignatureProvider* m_signature_provider; - ISignatureDataProvider* m_signature_data_provider; + ICapturedDataProvider* m_signature_data_provider; public: - StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ISignatureDataProvider* signatureDataProvider); + StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ICapturedDataProvider* signatureDataProvider); ~StepVerifySignature(); + StepVerifySignature(const StepVerifySignature& other) = default; + StepVerifySignature(StepVerifySignature&& other) noexcept = default; + StepVerifySignature& operator=(const StepVerifySignature& other) = default; + StepVerifySignature& operator=(StepVerifySignature&& other) noexcept = default; void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override; }; \ No newline at end of file diff --git a/src/ZoneLoading/Loading/ZoneLoader.cpp b/src/ZoneLoading/Loading/ZoneLoader.cpp index 9cb5d230..16f7621b 100644 --- a/src/ZoneLoading/Loading/ZoneLoader.cpp +++ b/src/ZoneLoading/Loading/ZoneLoader.cpp @@ -63,6 +63,17 @@ void ZoneLoader::AddStreamProcessor(StreamProcessor* streamProcessor) m_processor_chain_dirty = true; } +void ZoneLoader::RemoveStreamProcessor(StreamProcessor* streamProcessor) +{ + const auto foundEntry = std::find(m_processors.begin(), m_processors.end(), streamProcessor); + + if(foundEntry != m_processors.end()) + { + m_processors.erase(foundEntry); + m_processor_chain_dirty = true; + } +} + Zone* ZoneLoader::LoadZone(FileAPI::File* file) { LoadingFileStream fileStream(file); @@ -93,4 +104,4 @@ Zone* ZoneLoader::LoadZone(FileAPI::File* file) m_zone->Register(); return m_zone; -} \ No newline at end of file +} diff --git a/src/ZoneLoading/Loading/ZoneLoader.h b/src/ZoneLoading/Loading/ZoneLoader.h index 992205f9..c77e3fc1 100644 --- a/src/ZoneLoading/Loading/ZoneLoader.h +++ b/src/ZoneLoading/Loading/ZoneLoader.h @@ -31,5 +31,7 @@ public: void AddLoadingStep(ILoadingStep* step); void AddStreamProcessor(StreamProcessor* streamProcessor); + void RemoveStreamProcessor(StreamProcessor* streamProcessor); + Zone* LoadZone(FileAPI::File* file); }; diff --git a/src/ZoneLoading/ZoneLoading.cpp b/src/ZoneLoading/ZoneLoading.cpp index e37a116b..6ef6162d 100644 --- a/src/ZoneLoading/ZoneLoading.cpp +++ b/src/ZoneLoading/ZoneLoading.cpp @@ -1,9 +1,12 @@ #include "ZoneLoading.h" + #include "Utils/PathUtils.h" +#include "Game/IW4/ZoneLoaderFactoryIW4.h" #include "Game/T6/ZoneLoaderFactoryT6.h" IZoneLoaderFactory* zoneLoaderFactories[] { + new ZoneLoaderFactoryIW4(), new ZoneLoaderFactoryT6() };