From ac4548f4c2e57a0f10a04eaa7ef4364481b25b8d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 22 Jan 2016 11:59:43 +0100 Subject: [PATCH] Build materials. --- src/Components/Modules/AssetHandler.cpp | 6 + src/Components/Modules/AssetHandler.hpp | 8 ++ .../Modules/AssetInterfaces/IGfxImage.cpp | 47 +++++++ .../Modules/AssetInterfaces/IGfxImage.hpp | 12 ++ .../AssetInterfaces/ILocalizedEntry.cpp | 4 +- .../Modules/AssetInterfaces/IMaterial.cpp | 133 ++++++++++++++++++ .../Modules/AssetInterfaces/IMaterial.hpp | 10 ++ .../AssetInterfaces/IMaterialPixelShader.cpp | 31 ++++ .../AssetInterfaces/IMaterialPixelShader.hpp | 9 ++ .../AssetInterfaces/IMaterialTechniqueSet.cpp | 118 ++++++++++++++++ .../AssetInterfaces/IMaterialTechniqueSet.hpp | 10 ++ .../IMaterialVertexDeclaration.cpp | 24 ++++ .../IMaterialVertexDeclaration.hpp | 9 ++ .../AssetInterfaces/IMaterialVertexShader.cpp | 31 ++++ .../AssetInterfaces/IMaterialVertexShader.hpp | 9 ++ .../Modules/AssetInterfaces/IRawFile.cpp | 4 +- src/Components/Modules/ZoneBuilder.cpp | 68 +++++++-- src/Components/Modules/ZoneBuilder.hpp | 2 +- src/Game/Functions.cpp | 1 + src/Game/Functions.hpp | 3 + src/Game/Structs.hpp | 49 +++++-- src/Utils/Stream.hpp | 4 + src/Utils/Utils.hpp | 2 + 23 files changed, 563 insertions(+), 31 deletions(-) create mode 100644 src/Components/Modules/AssetInterfaces/IGfxImage.cpp create mode 100644 src/Components/Modules/AssetInterfaces/IGfxImage.hpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterial.cpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterial.hpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp create mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index d98b37f4..5fb1739d 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -207,7 +207,13 @@ namespace Components // Register asset interfaces AssetHandler::RegisterInterface(new Assets::IRawFile()); + AssetHandler::RegisterInterface(new Assets::IGfxImage()); + AssetHandler::RegisterInterface(new Assets::IMaterial()); AssetHandler::RegisterInterface(new Assets::ILocalizedEntry()); + AssetHandler::RegisterInterface(new Assets::IMaterialPixelShader()); + AssetHandler::RegisterInterface(new Assets::IMaterialTechniqueSet()); + AssetHandler::RegisterInterface(new Assets::IMaterialVertexShader()); + AssetHandler::RegisterInterface(new Assets::IMaterialVertexDeclaration()); } AssetHandler::~AssetHandler() diff --git a/src/Components/Modules/AssetHandler.hpp b/src/Components/Modules/AssetHandler.hpp index 930974d4..dd6b348d 100644 --- a/src/Components/Modules/AssetHandler.hpp +++ b/src/Components/Modules/AssetHandler.hpp @@ -50,5 +50,13 @@ namespace Components }; } +#define Assert_AssetStruct(x, size) static_assert(sizeof(x) == size, STRINGIZE(x) " structure is invalid."); + #include "AssetInterfaces\IRawFile.hpp" +#include "AssetInterfaces\IGfxImage.hpp" +#include "AssetInterfaces\IMaterial.hpp" #include "AssetInterfaces\ILocalizedEntry.hpp" +#include "AssetInterfaces\IMaterialPixelShader.hpp" +#include "AssetInterfaces\IMaterialTechniqueSet.hpp" +#include "AssetInterfaces\IMaterialVertexShader.hpp" +#include "AssetInterfaces\IMaterialVertexDeclaration.hpp" diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp new file mode 100644 index 00000000..2956b13d --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp @@ -0,0 +1,47 @@ +#include + +namespace Assets +{ + void IGfxImage::Save_GfxImageLoadDef(Components::ZoneBuilder::Zone* builder, const char* name) + { + Game::GfxImageLoadDef loadDef; + ZeroMemory(&loadDef, sizeof(loadDef)); + + Utils::Stream* buffer = builder->GetBuffer(); + + + } + + void IGfxImage::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Assert_AssetStruct(Game::GfxImage, 32); + + Utils::Stream* buffer = builder->GetBuffer(); + Game::GfxImage* asset = header.image; + Game::GfxImage* dest = (Game::GfxImage*)buffer->At(); + buffer->Save(asset, sizeof(Game::GfxImage)); + + buffer->PushBlock(Game::XFILE_BLOCK_VIRTUAL); + + if (asset->name) + { + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); + dest->name = (char *)-1; + } + + if (asset->texture) + { + buffer->Align(Utils::Stream::ALIGN_4); + + Game::GfxImageLoadDef* destTexture = (Game::GfxImageLoadDef*)buffer->At(); + buffer->Save(asset->texture, 16); + + // Zero the size! + destTexture->dataSize = 0; + + dest->texture = (Game::GfxImageLoadDef*)-1; + } + + buffer->PopBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.hpp b/src/Components/Modules/AssetInterfaces/IGfxImage.hpp new file mode 100644 index 00000000..e3107c05 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.hpp @@ -0,0 +1,12 @@ +namespace Assets +{ + class IGfxImage : public Components::AssetHandler::IAsset + { + virtual Game::XAssetType GetType() override { return Game::XAssetType::ASSET_TYPE_IMAGE; }; + + virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + + private: + void Save_GfxImageLoadDef(Components::ZoneBuilder::Zone* builder, const char* name); + }; +} \ No newline at end of file diff --git a/src/Components/Modules/AssetInterfaces/ILocalizedEntry.cpp b/src/Components/Modules/AssetInterfaces/ILocalizedEntry.cpp index 54376ec7..a7d5e29f 100644 --- a/src/Components/Modules/AssetInterfaces/ILocalizedEntry.cpp +++ b/src/Components/Modules/AssetInterfaces/ILocalizedEntry.cpp @@ -4,6 +4,8 @@ namespace Assets { void ILocalizedEntry::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { + Assert_AssetStruct(Game::LocalizedEntry, 8); + Utils::Stream* buffer = builder->GetBuffer(); Game::LocalizedEntry* asset = header.localize; Game::LocalizedEntry* dest = (Game::LocalizedEntry*)buffer->At(); @@ -19,7 +21,7 @@ namespace Assets if (asset->name) { - buffer->SaveString(asset->name); + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); dest->name = (char *)-1; } diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp new file mode 100644 index 00000000..99f59ed2 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterial.cpp @@ -0,0 +1,133 @@ +#include + +namespace Assets +{ + void IMaterial::Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Game::Material* asset = header.material; + + if (asset->techniqueSet) + { + builder->LoadAsset(Game::XAssetType::ASSET_TYPE_TECHSET, asset->techniqueSet->name); + } + + if (asset->textureTable) + { + for (char i = 0; i < asset->textureCount; i++) + { + if (asset->textureTable[i].info.image) + { + if (asset->textureTable[i].semantic == SEMANTIC_WATER_MAP) + { + if (asset->textureTable[i].info.water->image) + { + builder->LoadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->textureTable[i].info.water->image->name); + } + } + else + { + builder->LoadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->textureTable[i].info.image->name); + } + } + } + } + } + + void IMaterial::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Assert_AssetStruct(Game::Material, 96); + + Utils::Stream* buffer = builder->GetBuffer(); + Game::Material* asset = header.material; + Game::Material* dest = (Game::Material*)buffer->At(); + buffer->Save(asset, sizeof(Game::Material)); + + buffer->PushBlock(Game::XFILE_BLOCK_VIRTUAL); + + if (asset->name) + { + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); + dest->name = (char *)-1; + } + + if (asset->techniqueSet) + { + dest->techniqueSet = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_TECHSET, asset->techniqueSet->name).materialTechset; + } + + if (asset->textureTable) + { + Assert_AssetStruct(Game::MaterialTextureDef, 12); + + buffer->Align(Utils::Stream::ALIGN_4); + + Game::MaterialTextureDef* destTextureTable = (Game::MaterialTextureDef*)buffer->At(); + buffer->SaveArray(asset->textureTable, asset->textureCount); + + for (char i = 0; i < asset->textureCount; i++) + { + Game::MaterialTextureDef* destTextureDef = &destTextureTable[i]; + Game::MaterialTextureDef* textureDef = &asset->textureTable[i]; + + if (textureDef->semantic == SEMANTIC_WATER_MAP) + { + Assert_AssetStruct(Game::water_t, 68); + + Game::water_t* destWater = (Game::water_t*)buffer->At(); + Game::water_t* water = textureDef->info.water; + + if (water) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->Save(water, sizeof(Game::water_t)); + destTextureDef->info.water = (Game::water_t *)-1; + + // Save_water_t + if (water->H0X) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->Save(water->H0X, 8, water->M * water->N); + destWater->H0X = (float *)-1; + } + + if (water->H0Y) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->Save(water->H0Y, 4, water->M * water->N); + destWater->H0Y = (float *)-1; + } + + if (water->image) + { + destWater->image = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_IMAGE, water->image->name).image; + } + } + } + else if(textureDef->info.image) + { + destTextureDef->info.image = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_IMAGE, textureDef->info.image->name).image; + } + } + + dest->textureTable = (Game::MaterialTextureDef*)-1; + } + + if (asset->constantTable) + { + Assert_AssetStruct(Game::MaterialConstantDef, 32); + + buffer->Align(Utils::Stream::ALIGN_16); + buffer->SaveArray(asset->constantTable, asset->constantCount); + dest->constantTable = (Game::MaterialConstantDef *)-1; + } + + if (asset->stateBitTable) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->Save(asset->stateBitTable, 8, asset->stateBitsCount); + dest->stateBitTable = (void *)-1; + } + + buffer->PopBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.hpp b/src/Components/Modules/AssetInterfaces/IMaterial.hpp new file mode 100644 index 00000000..83c82c42 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterial.hpp @@ -0,0 +1,10 @@ +namespace Assets +{ + class IMaterial : public Components::AssetHandler::IAsset + { + virtual Game::XAssetType GetType() override { return Game::XAssetType::ASSET_TYPE_MATERIAL; }; + + virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + virtual void Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + }; +} \ No newline at end of file diff --git a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp new file mode 100644 index 00000000..602c2e6d --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp @@ -0,0 +1,31 @@ +#include + +namespace Assets +{ + void IMaterialPixelShader::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Assert_AssetStruct(Game::MaterialPixelShader, 16); + + Utils::Stream* buffer = builder->GetBuffer(); + Game::MaterialPixelShader* asset = header.pixelShader; + Game::MaterialPixelShader* dest = (Game::MaterialPixelShader*)buffer->At(); + buffer->Save(asset, sizeof(Game::MaterialPixelShader)); + + buffer->PushBlock(Game::XFILE_BLOCK_VIRTUAL); + + if (asset->name) + { + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); + dest->name = (char *)-1; + } + + if (asset->loadDef.physicalPart) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->Save(asset->loadDef.physicalPart, 4, asset->loadDef.cachedPartSize & 0xFFFF); + dest->loadDef.physicalPart = (char*)-1; + } + + buffer->PopBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp new file mode 100644 index 00000000..6ff07601 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp @@ -0,0 +1,9 @@ +namespace Assets +{ + class IMaterialPixelShader : public Components::AssetHandler::IAsset + { + virtual Game::XAssetType GetType() override { return Game::XAssetType::ASSET_TYPE_PIXELSHADER; }; + + virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + }; +} \ No newline at end of file diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp new file mode 100644 index 00000000..fd86a124 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp @@ -0,0 +1,118 @@ +#include + +namespace Assets +{ + void IMaterialTechniqueSet::Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Game::MaterialTechniqueSet* asset = header.materialTechset; + + for (int i = 0; i < ARR_SIZE(Game::MaterialTechniqueSet::techniques); i++) + { + Game::MaterialTechnique* technique = asset->techniques[i]; + + if (!technique) continue; + + for (short i = 0; i < technique->numPasses; i++) + { + Game::MaterialPass* pass = &technique->passes[i]; + + if (pass->vertexDecl) + { + builder->LoadAsset(Game::XAssetType::ASSET_TYPE_VERTEXDECL, pass->vertexDecl->name); + } + + if (pass->vertexShader) + { + builder->LoadAsset(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, pass->vertexShader->name); + } + + if (pass->pixelShader) + { + builder->LoadAsset(Game::XAssetType::ASSET_TYPE_PIXELSHADER, pass->pixelShader->name); + } + } + } + } + + void IMaterialTechniqueSet::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Assert_AssetStruct(Game::MaterialTechniqueSet, 204); + + Utils::Stream* buffer = builder->GetBuffer(); + Game::MaterialTechniqueSet* asset = header.materialTechset; + Game::MaterialTechniqueSet* dest = (Game::MaterialTechniqueSet*)buffer->At(); + buffer->Save(asset, sizeof(Game::MaterialTechniqueSet)); + + buffer->PushBlock(Game::XFILE_BLOCK_VIRTUAL); + + if (asset->name) + { + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); + dest->name = (char *)-1; + } + + // Save_MaterialTechniquePtrArray + static_assert(ARR_SIZE(Game::MaterialTechniqueSet::techniques) == 48, "Techniques array invalid!"); + + for (int i = 0; i < ARR_SIZE(Game::MaterialTechniqueSet::techniques); i++) + { + Game::MaterialTechnique* technique = asset->techniques[i]; + + if (technique) + { + // Size-check is obsolete, as the structure is dynamic + buffer->Align(Utils::Stream::ALIGN_4); + + Game::MaterialTechnique* destTechnique = (Game::MaterialTechnique*)buffer->At(); + buffer->Save(technique, 8); + dest->techniques[i] = (Game::MaterialTechnique*) - 1; + + // Save_MaterialPassArray + for (short i = 0; i < technique->numPasses; i++) + { + Assert_AssetStruct(Game::MaterialPass, 20); + + Game::MaterialPass* destPass = (Game::MaterialPass*)buffer->At(); + Game::MaterialPass* pass = &technique->passes[i]; + buffer->Save(pass, sizeof(Game::MaterialPass)); + + if (pass->vertexDecl) + { + destPass->vertexDecl = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_VERTEXDECL, pass->vertexDecl->name).vertexDecl; + } + + if (pass->vertexShader) + { + destPass->vertexShader = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, pass->vertexShader->name).vertexShader; + } + + if (pass->pixelShader) + { + destPass->pixelShader = builder->RequireAsset(Game::XAssetType::ASSET_TYPE_PIXELSHADER, pass->pixelShader->name).pixelShader; + } + + if (pass->argumentDef) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->SaveArray(pass->argumentDef, pass->argCount1 + pass->argCount2 + pass->argCount3); + destPass->argumentDef = (Game::ShaderArgumentDef*)-1; + } + } + + // We absolutely have to write something here! + if (technique->name) + { + buffer->SaveString(technique->name); + } + else + { + buffer->SaveString(""); + } + + destTechnique->name = (char*)-1; + } + } + + buffer->PopBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp new file mode 100644 index 00000000..886bd2a2 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp @@ -0,0 +1,10 @@ +namespace Assets +{ + class IMaterialTechniqueSet : public Components::AssetHandler::IAsset + { + virtual Game::XAssetType GetType() override { return Game::XAssetType::ASSET_TYPE_TECHSET; }; + + virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + virtual void Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + }; +} \ No newline at end of file diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp new file mode 100644 index 00000000..05b52748 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp @@ -0,0 +1,24 @@ +#include + +namespace Assets +{ + void IMaterialVertexDeclaration::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Assert_AssetStruct(Game::MaterialVertexDeclaration, 100); + + Utils::Stream* buffer = builder->GetBuffer(); + Game::MaterialVertexDeclaration* asset = header.vertexDecl; + Game::MaterialVertexDeclaration* dest = (Game::MaterialVertexDeclaration*)buffer->At(); + buffer->Save(asset, sizeof(Game::MaterialVertexDeclaration)); + + buffer->PushBlock(Game::XFILE_BLOCK_VIRTUAL); + + if (asset->name) + { + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); + dest->name = (char *)-1; + } + + buffer->PopBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp new file mode 100644 index 00000000..1ce7785c --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp @@ -0,0 +1,9 @@ +namespace Assets +{ + class IMaterialVertexDeclaration : public Components::AssetHandler::IAsset + { + virtual Game::XAssetType GetType() override { return Game::XAssetType::ASSET_TYPE_VERTEXDECL; }; + + virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + }; +} \ No newline at end of file diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp new file mode 100644 index 00000000..0f851bdf --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp @@ -0,0 +1,31 @@ +#include + +namespace Assets +{ + void IMaterialVertexShader::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Assert_AssetStruct(Game::MaterialVertexShader, 16); + + Utils::Stream* buffer = builder->GetBuffer(); + Game::MaterialVertexShader* asset = header.vertexShader; + Game::MaterialVertexShader* dest = (Game::MaterialVertexShader*)buffer->At(); + buffer->Save(asset, sizeof(Game::MaterialVertexShader)); + + buffer->PushBlock(Game::XFILE_BLOCK_VIRTUAL); + + if (asset->name) + { + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); + dest->name = (char *)-1; + } + + if (asset->loadDef.physicalPart) + { + buffer->Align(Utils::Stream::ALIGN_4); + buffer->Save(asset->loadDef.physicalPart, 4, asset->loadDef.cachedPartSize & 0xFFFF); + dest->loadDef.physicalPart = (char*)-1; + } + + buffer->PopBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp new file mode 100644 index 00000000..561f8ed1 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp @@ -0,0 +1,9 @@ +namespace Assets +{ + class IMaterialVertexShader : public Components::AssetHandler::IAsset + { + virtual Game::XAssetType GetType() override { return Game::XAssetType::ASSET_TYPE_VERTEXSHADER; }; + + virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + }; +} \ No newline at end of file diff --git a/src/Components/Modules/AssetInterfaces/IRawFile.cpp b/src/Components/Modules/AssetInterfaces/IRawFile.cpp index 8ce464fe..e7b34eb2 100644 --- a/src/Components/Modules/AssetInterfaces/IRawFile.cpp +++ b/src/Components/Modules/AssetInterfaces/IRawFile.cpp @@ -4,6 +4,8 @@ namespace Assets { void IRawFile::Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { + Assert_AssetStruct(Game::RawFile, 16); + Utils::Stream* buffer = builder->GetBuffer(); Game::RawFile* asset = header.rawfile; Game::RawFile* dest = (Game::RawFile*)buffer->At(); @@ -13,7 +15,7 @@ namespace Assets if (asset->name) { - buffer->SaveString(asset->name); + buffer->SaveString(builder->GetAssetName(this->GetType(), asset->name)); dest->name = (char *)-1; } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index b514f15d..b87258da 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -17,7 +17,7 @@ namespace Components { Localization::ClearTemp(); - ZoneBuilder::Zone::Assets.clear(); + ZoneBuilder::Zone::LoadedAssets.clear(); ZoneBuilder::Zone::ScriptStrings.clear(); ZoneBuilder::Zone::ScriptStringMap.clear(); } @@ -133,15 +133,15 @@ namespace Components // Handle script strings and referenced assets AssetHandler::ZoneMark(asset, this); - ZoneBuilder::Zone::Assets.push_back(asset); + ZoneBuilder::Zone::LoadedAssets.push_back(asset); return true; } int ZoneBuilder::Zone::FindAsset(Game::XAssetType type, const char* name) { - for (unsigned int i = 0; i < ZoneBuilder::Zone::Assets.size(); i++) + for (unsigned int i = 0; i < ZoneBuilder::Zone::LoadedAssets.size(); i++) { - Game::XAsset* asset = &ZoneBuilder::Zone::Assets[i]; + Game::XAsset* asset = &ZoneBuilder::Zone::LoadedAssets[i]; if (asset->type != type) continue; @@ -158,9 +158,9 @@ namespace Components Game::XAsset* ZoneBuilder::Zone::GetAsset(int index) { - if ((uint32_t)index < ZoneBuilder::Zone::Assets.size()) + if ((uint32_t)index < ZoneBuilder::Zone::LoadedAssets.size()) { - return &ZoneBuilder::Zone::Assets[index]; + return &ZoneBuilder::Zone::LoadedAssets[index]; } return nullptr; @@ -211,14 +211,14 @@ namespace Components Utils::WriteFile(outFile, outBuffer); Logger::Print("done.\n"); - Logger::Print("Zone '%s' written with %d assets\n", outFile.c_str(), ZoneBuilder::Zone::Assets.size()); + Logger::Print("Zone '%s' written with %d assets\n", outFile.c_str(), ZoneBuilder::Zone::LoadedAssets.size()); } void ZoneBuilder::Zone::SaveData() { // Add header Game::ZoneHeader zoneHeader = { 0 }; - zoneHeader.assetList.assetCount = Assets.size(); + zoneHeader.assetList.assetCount = ZoneBuilder::Zone::LoadedAssets.size(); zoneHeader.assetList.assets = (Game::XAsset *)-1; // Increment ScriptStrings count (for empty script string) if available @@ -260,7 +260,7 @@ namespace Components ZoneBuilder::Zone::IndexStart = ZoneBuilder::Zone::Buffer.GetBlockSize(Game::XFILE_BLOCK_VIRTUAL); // Mark AssetTable offset // AssetTable - for (auto asset : Assets) + for (auto asset : ZoneBuilder::Zone::LoadedAssets) { Game::XAsset entry; entry.type = asset.type; @@ -270,9 +270,10 @@ namespace Components } // Assets - for (auto asset : Assets) + for (auto asset : ZoneBuilder::Zone::LoadedAssets) { ZoneBuilder::Zone::Buffer.PushBlock(Game::XFILE_BLOCK_TEMP); + ZoneBuilder::Zone::Buffer.Align(Utils::Stream::ALIGN_4); AssetHandler::ZoneSave(asset, this); @@ -304,7 +305,7 @@ namespace Components Game::XAssetHeader header = { &branding }; Game::XAsset brandingAsset = { Game::XAssetType::ASSET_TYPE_RAWFILE, header }; - Assets.push_back(brandingAsset); + ZoneBuilder::Zone::LoadedAssets.push_back(brandingAsset); } // Check if the given pointer has already been mapped @@ -430,9 +431,24 @@ namespace Components return true; }); - + if (ZoneBuilder::IsEnabled()) { + // Prevent loading textures (preserves loaddef) + Utils::Hook::Set(0x51F4E0, 0xC3); + + //r_loadForrenderer = 0 + Utils::Hook::Set(0x519DDF, 0); + + //r_delayloadimage retn + Utils::Hook::Set(0x51F450, 0xC3); + + // r_registerDvars hack + Utils::Hook::Set(0x51B1CD, 0xC3); + + // Prevent destroying textures + Utils::Hook::Set(0x51F03D, 0xEB); + Command::Add("build", [] (Command::Params params) { if (params.Length() < 2) return; @@ -442,8 +458,34 @@ namespace Components Zone(zoneName).Build(); }); - } + Command::Add("listassets", [] (Command::Params params) + { + if (params.Length() < 2) return; + Game::XAssetType type = Game::DB_GetXAssetNameType(params[1]); + + if (type != Game::XAssetType::ASSET_TYPE_INVALID) + { + Game::DB_EnumXAssets(type, [] (Game::XAssetHeader header, void* data) + { + Logger::Print("%s\n", Game::DB_GetXAssetNameHandlers[*(Game::XAssetType*)data](&header)); + }, &type, false); + } + }); + } + //else //Utils::Hook(0x4546DF, TestZoneLoading, HOOK_CALL).Install()->Quick(); + + Command::Add("loadzone", [] (Command::Params params) + { + if (params.Length() < 2) return; + + Game::XZoneInfo info; + info.name = params[1]; + info.allocFlags = 0x01000000; + info.freeFlags = 0; + + Game::DB_LoadXAssets(&info, 1, true); + }); } } diff --git a/src/Components/Modules/ZoneBuilder.hpp b/src/Components/Modules/ZoneBuilder.hpp index 58e383c8..cbe3dd68 100644 --- a/src/Components/Modules/ZoneBuilder.hpp +++ b/src/Components/Modules/ZoneBuilder.hpp @@ -55,7 +55,7 @@ namespace Components std::string ZoneName; Utils::CSV DataMap; - std::vector Assets; + std::vector LoadedAssets; std::vector ScriptStrings; std::map ScriptStringMap; std::map RenameMap[Game::XAssetType::ASSET_TYPE_COUNT]; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 251f4660..144295cd 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -19,6 +19,7 @@ namespace Game Com_Milliseconds_t Com_Milliseconds = (Com_Milliseconds_t)0x42A660; Com_ParseExt_t Com_ParseExt = (Com_ParseExt_t)0x474D60; + DB_EnumXAssets_t DB_EnumXAssets = (DB_EnumXAssets_t)0x4B76D0; DB_FindXAssetHeader_t DB_FindXAssetHeader = (DB_FindXAssetHeader_t)0x407930; DB_GetXAssetNameHandler_t* DB_GetXAssetNameHandlers = (DB_GetXAssetNameHandler_t*)0x799328; DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers = (DB_GetXAssetSizeHandler_t*)0x799488; diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 34949345..3ece08d6 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -36,6 +36,9 @@ namespace Game typedef char* (__cdecl * Com_ParseExt_t)(const char**); extern Com_ParseExt_t Com_ParseExt; + typedef void(__cdecl * DB_EnumXAssets_t)(XAssetType type, void(*)(XAssetHeader, void *), void* userdata, bool overrides); + extern DB_EnumXAssets_t DB_EnumXAssets; + typedef XAssetHeader (__cdecl * DB_FindXAssetHeader_t)(XAssetType type, const char* name); extern DB_FindXAssetHeader_t DB_FindXAssetHeader; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 32e16055..245a334e 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -176,7 +176,7 @@ namespace Game short dimensions[3]; int format; // usually the compression Magic int dataSize; // set to zero to load from IWD - //char * data; + char data[1]; }; struct GfxImage @@ -202,7 +202,7 @@ namespace Game float floatTime; float *H0X; // Count = M * N float *H0Y; // Count = M * N - float *wTerm; // Count = M * N + //float *wTerm; // Count = M * N int M; int N; float Lx; @@ -215,6 +215,8 @@ namespace Game GfxImage *image; }; + #define SEMANTIC_WATER_MAP 11 + union MaterialTextureDefInfo { GfxImage *image; // MaterialTextureDef->semantic != SEMANTIC_WATER_MAP @@ -239,7 +241,7 @@ namespace Game short more; }; - struct VertexDecl + struct MaterialVertexDeclaration { const char* name; int unknown; @@ -247,27 +249,39 @@ namespace Game /*IDirect3DVertexDeclaration9**/void* declarations[16]; }; - struct PixelShader + struct GfxPixelShaderLoadDef { - const char* name; - /*IDirect3DPixelShader9*/void* shader; - DWORD* bytecode; - int codeLen; + char *cachedPart; + char *physicalPart; + unsigned __int16 cachedPartSize; + unsigned __int16 physicalPartSize; }; - struct VertexShader + struct MaterialPixelShader { const char* name; - void * /*IDirect3DVertexShader9**/ shader; - DWORD* bytecode; - int codeLen; + GfxPixelShaderLoadDef loadDef; + }; + + struct GfxVertexShaderLoadDef + { + char *cachedPart; + char *physicalPart; + unsigned __int16 cachedPartSize; + unsigned __int16 physicalPartSize; + }; + + struct MaterialVertexShader + { + const char* name; + GfxVertexShaderLoadDef loadDef; }; struct MaterialPass { - VertexDecl* vertexDecl; - VertexShader* vertexShader; - PixelShader* pixelShader; + MaterialVertexDeclaration* vertexDecl; + MaterialVertexShader* vertexShader; + MaterialPixelShader* pixelShader; char argCount1; char argCount2; char argCount3; @@ -1204,7 +1218,12 @@ namespace Game StringTable *stringTable; MapEnts* mapEnts; RawFile* rawfile; + GfxImage* image; Font* font; + MaterialTechniqueSet *materialTechset; + MaterialVertexDeclaration *vertexDecl; + MaterialVertexShader *vertexShader; + MaterialPixelShader *pixelShader; structuredDataDef_t* structuredData; }; diff --git a/src/Utils/Stream.hpp b/src/Utils/Stream.hpp index 27788901..c97d0e57 100644 --- a/src/Utils/Stream.hpp +++ b/src/Utils/Stream.hpp @@ -34,6 +34,10 @@ namespace Utils char* Save(const void * _str, size_t size, size_t count = 1); char* Save(Game::XFILE_BLOCK_TYPES stream, const void * _str, size_t size, size_t count); char* Save(Game::XFILE_BLOCK_TYPES stream, int value, size_t count); + template char* SaveArray(T* array, size_t count) + { + return Save(array, sizeof(T), count); + } char* SaveString(std::string string); char* SaveString(const char* string); diff --git a/src/Utils/Utils.hpp b/src/Utils/Utils.hpp index 1d01257f..077953f4 100644 --- a/src/Utils/Utils.hpp +++ b/src/Utils/Utils.hpp @@ -1,3 +1,5 @@ +#define ARR_SIZE(x) (sizeof(x) / sizeof(x[0])) + namespace Utils { const char *VA(const char *fmt, ...);