diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index 94561e8e..73e22502 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -9,6 +9,8 @@ namespace Components std::map AssetHandler::Relocations; + std::map AssetHandler::TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT]; + void AssetHandler::RegisterInterface(IAsset* iAsset) { if (!iAsset) return; @@ -26,6 +28,19 @@ namespace Components AssetHandler::AssetInterfaces[iAsset->GetType()] = iAsset; } + void AssetHandler::ClearTemporaryAssets() + { + for (int i = 0; i < Game::XAssetType::ASSET_TYPE_COUNT; i++) + { + AssetHandler::TemporaryAssets[i].clear(); + } + } + + void AssetHandler::StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset) + { + AssetHandler::TemporaryAssets[type][Game::DB_GetXAssetNameHandlers[type](&asset)] = asset; + } + Game::XAssetHeader AssetHandler::FindAsset(Game::XAssetType type, const char* filename) { Game::XAssetHeader header = { 0 }; @@ -184,6 +199,14 @@ namespace Components Game::XAssetHeader AssetHandler::FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder) { Game::XAssetHeader header = { 0 }; + if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header; + + auto tempPool = &AssetHandler::TemporaryAssets[type]; + auto entry = tempPool->find(filename); + if (entry != tempPool->end()) + { + return { entry->second }; + } if (AssetHandler::AssetInterfaces.find(type) != AssetHandler::AssetInterfaces.end()) { @@ -213,6 +236,8 @@ namespace Components AssetHandler::AssetHandler() { + AssetHandler::ClearTemporaryAssets(); + // DB_FindXAssetHeader Utils::Hook(Game::DB_FindXAssetHeader, AssetHandler::FindAssetStub).Install()->Quick(); @@ -235,6 +260,8 @@ namespace Components AssetHandler::~AssetHandler() { + ClearTemporaryAssets(); + for (auto i = AssetHandler::AssetInterfaces.begin(); i != AssetHandler::AssetInterfaces.end(); i++) { delete i->second; diff --git a/src/Components/Modules/AssetHandler.hpp b/src/Components/Modules/AssetHandler.hpp index 0661c808..295dfc31 100644 --- a/src/Components/Modules/AssetHandler.hpp +++ b/src/Components/Modules/AssetHandler.hpp @@ -31,6 +31,9 @@ namespace Components static Game::XAssetHeader FindOriginalAsset(Game::XAssetType type, const char* filename); static Game::XAssetHeader FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder); + static void ClearTemporaryAssets(); + static void StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset); + private: static bool BypassState; @@ -43,6 +46,8 @@ namespace Components static void OffsetToAlias(Utils::Stream::Offset* offset); + static std::map TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT]; + static std::map AssetInterfaces; static std::map TypeCallbacks; static std::vector RestrictCallbacks; diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp index 2b671c21..cf36624b 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp @@ -14,18 +14,59 @@ namespace Assets return; } - image->semantic = 0; - image->category = 3; + image->name = builder->GetAllocator()->DuplicateString(name); + image->semantic = 2; + image->category = 0; image->cardMemory = 0; - Game::Image_LoadFromFileWithReader(image, (Game::Reader_t)0x46CBF0); - - // Free our image when done building zone - builder->GetAllocator()->Reference(image, [] (void*data) + image->texture = builder->GetAllocator()->AllocateArray(); + if (!image->texture) { - Game::Image_Release((Game::GfxImage*)data); - }); + Components::Logger::Error("Failed to allocate GfxImageLoadDef structure!"); + return; + } + Components::FileSystem::File iwi(Utils::VA("images/%s.iwi", name.data())); + + if (!iwi.Exists()) + { + Components::Logger::Error("Loading image '%s' failed!", iwi.GetName()); + return; + } + + const Game::GfxImageFileHeader* iwiHeader = reinterpret_cast(iwi.GetBuffer().data()); + + image->mapType = 3; + image->dataLen1 = iwiHeader->fileSizeForPicmip[0] - 32; + image->dataLen2 = iwiHeader->fileSizeForPicmip[0] - 32; + + // TODO: Check tag + image->texture->dimensions[0] = iwiHeader->dimensions[0]; // Width + image->texture->dimensions[1] = iwiHeader->dimensions[1]; // Height + image->texture->dimensions[2] = iwiHeader->dimensions[2]; // Depth + image->texture->flags = 0;//iwiHeader->flags; + image->texture->mipLevels = 0; + + switch (iwiHeader->format) + { + case Game::IWI_COMPRESSION::IWI_ARGB: + image->texture->format = 21; + break; + case Game::IWI_COMPRESSION::IWI_RGB8: + image->texture->format = 20; + break; + case Game::IWI_COMPRESSION::IWI_DXT1: + image->texture->format = 0x31545844; + break; + case Game::IWI_COMPRESSION::IWI_DXT3: + image->texture->format = 0x33545844; + break; + case Game::IWI_COMPRESSION::IWI_DXT5: + image->texture->format = 0x35545844; + break; + } + + Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_IMAGE, { image }); header->image = image; } diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp index eefc4ab9..31d0be69 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterial.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterial.cpp @@ -66,6 +66,7 @@ namespace Assets Game::MaterialTextureDef textureDef; textureDef.semantic = 0; // No water image + textureDef.sampleState = -30; textureDef.nameEnd = map.string_value().data()[map.string_value().size() - 1]; textureDef.nameStart = map.string_value().data()[0]; textureDef.nameHash = Game::R_HashString(map.string_value().data()); @@ -97,6 +98,7 @@ namespace Assets material->textureCount = (char)textureList.size() & 0xFF; } + Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, { material }); header->material = material; } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index c6e7155c..ec3e5ba1 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -15,6 +15,7 @@ namespace Components ZoneBuilder::Zone::~Zone() { + AssetHandler::ClearTemporaryAssets(); Localization::ClearTemp(); ZoneBuilder::Zone::LoadedAssets.clear(); @@ -448,6 +449,9 @@ namespace Components // Prevent destroying textures Utils::Hook::Set(0x51F03D, 0xEB); + // Don't create default assets + Utils::Hook::Set(0x407BAA, 0xEB); + Command::Add("buildzone", [] (Command::Params params) { if (params.Length() < 2) return; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 245a334e..d1360edf 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -168,6 +168,25 @@ namespace Game struct menuDef_t; enum operationEnum; + enum IWI_COMPRESSION + { + IWI_INVALID = 0x0, + IWI_ARGB = 0x1, + IWI_RGB8 = 0x2, + IWI_DXT1 = 0xB, + IWI_DXT3 = 0xC, + IWI_DXT5 = 0xD, + }; + + struct GfxImageFileHeader + { + char tag[3]; + char version; + int flags; + char format; + short dimensions[3]; + int fileSizeForPicmip[4]; + }; struct GfxImageLoadDef // actually a IDirect3DTexture* but this is easier {