From 8b120cb8b892a515efb9f4340d1728c4dbfbd77f Mon Sep 17 00:00:00 2001 From: RektInator Date: Sun, 12 Jan 2020 00:57:09 +0100 Subject: [PATCH] GfxImage / Material / Techset support for xbox --- src/IW4/Assets/GfxImage.cpp | 135 ++++++++++++++----- src/IW4/Assets/GfxImage.hpp | 4 - src/IW4/Assets/Material.cpp | 210 +++++++++++++++++++++++++----- src/IW4/Assets/RawFile.cpp | 2 +- src/IW4/Assets/Techset.cpp | 171 +++++++++++++----------- src/IW4/Structs.hpp | 169 ++++++++++++++++++++++++ src/IW4/Zone.cpp | 75 ++++++++--- src/IW5/Assets/RawFile.cpp | 2 +- src/ZoneTool/ZoneTool.cpp | 1 + src/ZoneUtils/Utils/PakFile.cpp | 51 ++++++++ src/ZoneUtils/Utils/PakFile.hpp | 26 ++++ src/ZoneUtils/Zone/ZoneBuffer.cpp | 72 +++++++--- src/ZoneUtils/Zone/ZoneBuffer.hpp | 18 +++ src/ZoneUtils/ZoneUtils.hpp | 10 +- 14 files changed, 763 insertions(+), 183 deletions(-) create mode 100644 src/ZoneUtils/Utils/PakFile.cpp create mode 100644 src/ZoneUtils/Utils/PakFile.hpp diff --git a/src/IW4/Assets/GfxImage.cpp b/src/IW4/Assets/GfxImage.cpp index baa6df2..7cd7e35 100644 --- a/src/IW4/Assets/GfxImage.cpp +++ b/src/IW4/Assets/GfxImage.cpp @@ -13,14 +13,6 @@ namespace ZoneTool { namespace IW4 { - IGfxImage::IGfxImage() - { - } - - IGfxImage::~IGfxImage() - { - } - std::string IGfxImage::clean_name(const std::string& name) { auto newName = name; @@ -158,44 +150,123 @@ namespace ZoneTool void IGfxImage::write(IZone* zone, ZoneBuffer* buf) { - IW5::IGfxImage::dump_iwi(this->name()); - - auto data = this->asset_; - auto dest = buf->write(data); + if (zone->get_target() == zone_target::pc) + { + IW5::IGfxImage::dump_iwi(this->name()); + + auto data = this->asset_; + auto dest = buf->write(data); - // sizeof GfxImage; - - buf->push_stream(3); - START_LOG_STREAM; + buf->push_stream(3); + START_LOG_STREAM; - dest->name = buf->write_str(this->name()); + dest->name = buf->write_str(this->name()); - // set loaded to false - dest->loaded = false; + // set loaded to false + dest->loaded = false; - buf->push_stream(0); - if (data->texture) + buf->push_stream(0); + if (data->texture) + { + buf->align(3); + + auto desttext = buf->at(); + buf->write_stream(data->texture, sizeof GfxImageLoadDef - sizeof std::uintptr_t); + + if (isMapImage && desttext->dataSize) + { + buf->write_stream(&data->texture->texture, data->texture->dataSize); + } + else + { + desttext->dataSize = 0; + } + + ZoneBuffer::ClearPointer(&dest->texture); + } + buf->pop_stream(); + + END_LOG_STREAM; + buf->pop_stream(); + } + else { - buf->align(3); + alpha::GfxImage alpha_image = {}; - auto desttext = buf->at(); - buf->write_stream(data->texture, sizeof GfxImageLoadDef - sizeof std::uintptr_t); + // transform iwi + if (!FileSystem::FileExists(va("images/%s.iwi", this->name().data()))) + { + ZONETOOL_FATAL("Image %s is missing!", this->name().data()); + } - if (isMapImage && desttext->dataSize) + std::vector pixels; + auto fp = FileSystem::FileOpen(va("images/%s.iwi", this->name().data()), "rb"); + if (fp) { - buf->write_stream(&data->texture->texture, data->texture->dataSize); + auto file_size = FileSystem::FileSize(fp); + auto img_data = FileSystem::ReadBytes(fp, file_size); + + auto iwi_header = (GfxImageFileHeader*)img_data.data(); + + auto pixel_data = img_data.data() + 32; + auto pixel_data_size = img_data.size() - 32; + + pixels.resize(pixel_data_size); + memcpy(&pixels[0], pixel_data, pixel_data_size); + + // add image to imagepak + // buf->add_image(pixels); + + // dunno + alpha_image.cached = false; + alpha_image.format = 0x1A200154; // iwi_header->format; + alpha_image.width = iwi_header->dimensions[0]; + alpha_image.height = iwi_header->dimensions[1]; + alpha_image.depth = iwi_header->dimensions[2]; + alpha_image.levelCount = 1; + alpha_image.mapType = 3; + alpha_image.category = 3; + alpha_image.cardMemory.platform[0] = pixels.size(); } else { - desttext->dataSize = 0; + ZONETOOL_FATAL("Cannot open image %s!", this->name().data()); } + - ZoneBuffer::ClearPointer(&dest->texture); - } - buf->pop_stream(); + auto data = &alpha_image; + auto dest = buf->write(data); - END_LOG_STREAM; - buf->pop_stream(); + buf->push_stream(3); + + dest->name = buf->write_str(this->name()); + + buf->push_stream(1); + if (pixels.size()) + { + buf->align(4095); + buf->write(pixels.data(), pixels.size()); + ZoneBuffer::ClearPointer(&dest->pixels); + } + else + { + dest->pixels = nullptr; + } + buf->pop_stream(); + + buf->pop_stream(); + + if (zone->get_target() != zone_target::pc) + { + endian_convert(&dest->name); + endian_convert(&dest->format); + endian_convert(&dest->width); + endian_convert(&dest->height); + endian_convert(&dest->depth); + endian_convert(&dest->pixels); + endian_convert(&dest->cardMemory.platform[0]); + } + } } // Legacy cancer code diff --git a/src/IW4/Assets/GfxImage.hpp b/src/IW4/Assets/GfxImage.hpp index 1027450..a8cd679 100644 --- a/src/IW4/Assets/GfxImage.hpp +++ b/src/IW4/Assets/GfxImage.hpp @@ -23,10 +23,6 @@ namespace ZoneTool GfxImage* parse(const std::string& name, ZoneMemory* mem); public: - IGfxImage(); - ~IGfxImage(); - - void init(const std::string& name, ZoneMemory* mem) override; void init(void* asset, ZoneMemory* mem) override; diff --git a/src/IW4/Assets/Material.cpp b/src/IW4/Assets/Material.cpp index dd755f0..5f9c8a6 100644 --- a/src/IW4/Assets/Material.cpp +++ b/src/IW4/Assets/Material.cpp @@ -397,60 +397,198 @@ namespace ZoneTool void IMaterial::write(IZone* zone, ZoneBuffer* buf) { - sizeof Material; - - auto dest = buf->at(); - auto data = this->asset_; + // sizeof Material; - buf->write(data); - buf->push_stream(3); - START_LOG_STREAM; + if (zone->get_target() == zone_target::pc) + { + auto dest = buf->at(); + auto data = this->asset_; - dest->name = buf->write_str(this->name()); + buf->write(data); + buf->push_stream(3); + START_LOG_STREAM; - if (data->techniqueSet) - { - dest->techniqueSet = reinterpret_cast(zone->get_asset_pointer( - techset, data->techniqueSet->name)); - } + dest->name = buf->write_str(this->name()); + + if (data->techniqueSet) + { + dest->techniqueSet = reinterpret_cast(zone->get_asset_pointer( + techset, data->techniqueSet->name)); + } + + if (data->maps) + { + buf->align(3); + auto destmaps = buf->write(data->maps, data->numMaps); + + for (int i = 0; i < data->numMaps; i++) + { + if (data->maps[i].semantic == 11) + { + ZONETOOL_ERROR("Watermaps are not supported."); + destmaps[i].image = nullptr; + } + else + { + if (data->maps[i].image) + { + destmaps[i].image = reinterpret_cast(zone->get_asset_pointer( + image, data->maps[i].image->name)); + } + } + } + + ZoneBuffer::ClearPointer(&dest->maps); + } + + if (data->constantTable) + { + dest->constantTable = buf->write_s(15, data->constantTable, data->constantCount); + } + + if (data->stateMap) + { + dest->stateMap = buf->write_s(3, data->stateMap, data->stateBitsCount); + } - if (data->maps) + END_LOG_STREAM; + buf->pop_stream(); + } + else { - buf->align(3); - auto destmaps = buf->write(data->maps, data->numMaps); + alpha::Material alpha_material = {}; + + // transform data + memcpy(&alpha_material.info, this->asset_, sizeof alpha::MaterialInfo); + memcpy(&alpha_material.textureCount, &this->asset_->numMaps, 5); + memcpy(&alpha_material.techniqueSet, &this->asset_->techniqueSet, 16); + alpha_material.subMaterials = nullptr; - for (int i = 0; i < data->numMaps; i++) + std::unordered_map actual_meme = { - if (data->maps[i].semantic == 11) + { TECHNIQUE_DEPTH_PREPASS, alpha::TECHNIQUE_DEPTH_PREPASS }, + { TECHNIQUE_BUILD_FLOAT_Z, alpha::TECHNIQUE_BUILD_FLOAT_Z }, + { TECHNIQUE_BUILD_SHADOWMAP_DEPTH, alpha::TECHNIQUE_BUILD_SHADOWMAP_DEPTH }, + { TECHNIQUE_BUILD_SHADOWMAP_COLOR, alpha::TECHNIQUE_BUILD_SHADOWMAP_COLOR }, + { TECHNIQUE_UNLIT, alpha::TECHNIQUE_UNLIT }, + { TECHNIQUE_EMISSIVE, alpha::TECHNIQUE_EMISSIVE }, + { TECHNIQUE_EMISSIVE_DFOG, alpha::TECHNIQUE_EMISSIVE_DFOG }, + { TECHNIQUE_EMISSIVE_SHADOW, alpha::TECHNIQUE_EMISSIVE_SHADOW }, + { TECHNIQUE_EMISSIVE_SHADOW_DFOG, alpha::TECHNIQUE_EMISSIVE_SHADOW_DFOG }, + { TECHNIQUE_LIT, alpha::TECHNIQUE_LIT }, + { TECHNIQUE_LIT_DFOG, alpha::TECHNIQUE_LIT_DFOG }, + { TECHNIQUE_LIT_SUN, alpha::TECHNIQUE_LIT_SUN }, + { TECHNIQUE_LIT_SUN_DFOG, alpha::TECHNIQUE_LIT_SUN_DFOG }, + { TECHNIQUE_LIT_SUN_SHADOW, alpha::TECHNIQUE_LIT_SUN_SHADOW }, + { TECHNIQUE_LIT_SUN_SHADOW_DFOG, alpha::TECHNIQUE_LIT_SUN_SHADOW_DFOG }, + { TECHNIQUE_LIT_SPOT, alpha::TECHNIQUE_LIT_SPOT }, + { TECHNIQUE_LIT_SPOT_DFOG, alpha::TECHNIQUE_LIT_SPOT_DFOG }, + { TECHNIQUE_LIT_SPOT_SHADOW, alpha::TECHNIQUE_LIT_SPOT_SHADOW }, + { TECHNIQUE_LIT_SPOT_SHADOW_DFOG, alpha::TECHNIQUE_LIT_SPOT_SHADOW_DFOG }, + { TECHNIQUE_LIT_OMNI, alpha::TECHNIQUE_LIT_OMNI }, + { TECHNIQUE_LIT_OMNI_DFOG, alpha::TECHNIQUE_LIT_OMNI_DFOG }, + { TECHNIQUE_LIT_OMNI_SHADOW, alpha::TECHNIQUE_LIT_OMNI_SHADOW }, + { TECHNIQUE_LIT_OMNI_SHADOW_DFOG, alpha::TECHNIQUE_LIT_OMNI_SHADOW_DFOG }, + { TECHNIQUE_LIGHT_SPOT, alpha::TECHNIQUE_LIGHT_SPOT }, + { TECHNIQUE_LIGHT_OMNI, alpha::TECHNIQUE_LIGHT_OMNI }, + { TECHNIQUE_LIGHT_SPOT_SHADOW, alpha::TECHNIQUE_LIGHT_SPOT_SHADOW }, + { TECHNIQUE_FAKELIGHT_NORMAL, alpha::TECHNIQUE_FAKELIGHT_NORMAL }, + { TECHNIQUE_FAKELIGHT_VIEW, alpha::TECHNIQUE_FAKELIGHT_VIEW }, + { TECHNIQUE_SUNLIGHT_PREVIEW, alpha::TECHNIQUE_SUNLIGHT_PREVIEW }, + { TECHNIQUE_CASE_TEXTURE, alpha::TECHNIQUE_CASE_TEXTURE }, + { TECHNIQUE_WIREFRAME_SOLID, alpha::TECHNIQUE_WIREFRAME_SOLID }, + { TECHNIQUE_WIREFRAME_SHADED, alpha::TECHNIQUE_WIREFRAME_SHADED }, + { TECHNIQUE_DEBUG_BUMPMAP, alpha::TECHNIQUE_DEBUG_BUMPMAP }, + }; + + for (auto i = 0u; i < 48; i++) + { + const auto itr = actual_meme.find(MaterialTechniqueType(i)); + if (itr != actual_meme.end()) { - ZONETOOL_ERROR("Watermaps are not supported."); - destmaps[i].image = nullptr; + alpha_material.stateBitsEntry[itr->second] = this->asset_->stateBitsEntry[i]; } - else + } + + auto data = &alpha_material; + auto dest = buf->write(data); + + buf->push_stream(3); + + dest->info.name = buf->write_str(this->name()); + + if (data->techniqueSet) + { + dest->techniqueSet = reinterpret_cast(zone->get_asset_pointer( + techset, data->techniqueSet->name)); + } + + if (data->textureTable) + { + buf->align(3); + auto destmaps = buf->write(data->textureTable, data->textureCount); + + for (int i = 0; i < data->textureCount; i++) { - if (data->maps[i].image) + if (data->textureTable[i].semantic == 11) + { + ZONETOOL_ERROR("Watermaps are not supported."); + destmaps[i].image = nullptr; + } + else { - destmaps[i].image = reinterpret_cast(zone->get_asset_pointer( - image, data->maps[i].image->name)); + if (data->textureTable[i].image) + { + destmaps[i].image = reinterpret_cast(zone->get_asset_pointer( + image, data->textureTable[i].image->name)); + } } + + endian_convert(&destmaps[i].image); + endian_convert(&destmaps[i].typeHash); } + + ZoneBuffer::ClearPointer(&dest->textureTable); } - ZoneBuffer::ClearPointer(&dest->maps); - } + if (data->constantTable) + { + MaterialConstantDef* destConstantTable = nullptr; + dest->constantTable = buf->write_s(15, data->constantTable, data->constantCount, sizeof MaterialConstantDef, &destConstantTable); - if (data->constantTable) - { - dest->constantTable = buf->write_s(15, data->constantTable, data->constantCount); - } + for (auto i = 0u; i < data->stateBitsCount; i++) + { + endian_convert(&destConstantTable[i].name); + endian_convert(&destConstantTable[i].nameHash); + endian_convert(&destConstantTable[i].literal[0]); + endian_convert(&destConstantTable[i].literal[1]); + endian_convert(&destConstantTable[i].literal[2]); + endian_convert(&destConstantTable[i].literal[3]); + } + } - if (data->stateMap) - { - dest->stateMap = buf->write_s(3, data->stateMap, data->stateBitsCount); - } + if (data->stateBitsTable) + { + GfxStateBits* destStateBits = nullptr; + dest->stateBitsTable = buf->write_s(3, data->stateBitsTable, data->stateBitsCount, sizeof GfxStateBits, &destStateBits); - END_LOG_STREAM; - buf->pop_stream(); + for (auto i = 0u; i < data->stateBitsCount; i++) + { + endian_convert(&destStateBits[i].loadBits[0]); + endian_convert(&destStateBits[i].loadBits[1]); + } + } + + buf->pop_stream(); + + endian_convert(&dest->info.name); + endian_convert(&dest->info.surfaceTypeBits); + endian_convert(&dest->info.drawSurf.packed); + endian_convert(&dest->techniqueSet); + endian_convert(&dest->textureTable); + endian_convert(&dest->constantTable); + endian_convert(&dest->stateBitsTable); + } } void IMaterial::dump(Material* asset) diff --git a/src/IW4/Assets/RawFile.cpp b/src/IW4/Assets/RawFile.cpp index 97616b0..1acc653 100644 --- a/src/IW4/Assets/RawFile.cpp +++ b/src/IW4/Assets/RawFile.cpp @@ -9,7 +9,7 @@ #include "stdafx.hpp" #include -#define ZONETOOL_BRANDING "Compiled using ZoneTool by RektInator, localhost & X3RX35." +#define ZONETOOL_BRANDING "Compiled using ZoneTool by RektInator." namespace ZoneTool { diff --git a/src/IW4/Assets/Techset.cpp b/src/IW4/Assets/Techset.cpp index 263ca33..62eeff3 100644 --- a/src/IW4/Assets/Techset.cpp +++ b/src/IW4/Assets/Techset.cpp @@ -261,7 +261,7 @@ namespace ZoneTool if (!this->asset_) { - ZONETOOL_FATAL("Current zone is depending on missing techset \"%s\", zone may not work correctly!", name.data()); + // ZONETOOL_FATAL("Current zone is depending on missing techset \"%s\", zone may not work correctly!", name.data()); this->m_parsed = false; this->asset_ = DB_FindXAssetHeader(this->type(), &this->name()[0]).techset; @@ -278,27 +278,30 @@ namespace ZoneTool void ITechset::load_depending(IZone* zone) { - auto data = this->asset_; - - for (std::int32_t technique = 0; technique < 48; technique++) + if (zone->get_target() == zone_target::pc) { - if (data->techniques[technique]) + auto data = this->asset_; + + for (std::int32_t technique = 0; technique < 48; technique++) { - for (std::int32_t pass = 0; pass < data->techniques[technique]->hdr.numPasses; pass++) + if (data->techniques[technique]) { - auto& techniquePass = data->techniques[technique]->pass[pass]; - - if (techniquePass.vertexDecl) - { - zone->add_asset_of_type(vertexdecl, techniquePass.vertexDecl->name); - } - if (techniquePass.vertexShader) - { - zone->add_asset_of_type(vertexshader, techniquePass.vertexShader->name); - } - if (techniquePass.pixelShader) + for (std::int32_t pass = 0; pass < data->techniques[technique]->hdr.numPasses; pass++) { - zone->add_asset_of_type(pixelshader, techniquePass.pixelShader->name); + auto& techniquePass = data->techniques[technique]->pass[pass]; + + if (techniquePass.vertexDecl) + { + zone->add_asset_of_type(vertexdecl, techniquePass.vertexDecl->name); + } + if (techniquePass.vertexShader) + { + zone->add_asset_of_type(vertexshader, techniquePass.vertexShader->name); + } + if (techniquePass.pixelShader) + { + zone->add_asset_of_type(pixelshader, techniquePass.pixelShader->name); + } } } } @@ -317,86 +320,104 @@ namespace ZoneTool void ITechset::write(IZone* zone, ZoneBuffer* buf) { - auto data = this->asset_; - auto dest = buf->write(data); - - buf->push_stream(3); - START_LOG_STREAM; - - dest->name = buf->write_str(this->name()); - dest->remappedTechniques = static_cast(zone->get_asset_pointer(techset, this->name())); - - for (std::int32_t technique = 0; technique < 48; technique++) + if (zone->get_target() == zone_target::pc) { - if (!data->techniques[technique]) - { - continue; - } + auto data = this->asset_; + auto dest = buf->write(data); - buf->align(3); + buf->push_stream(3); + START_LOG_STREAM; - auto techniqueHeader = buf->write(&data->techniques[technique]->hdr); - auto techniquePasses = buf->write(data->techniques[technique]->pass, techniqueHeader->numPasses); + dest->name = buf->write_str(this->name()); + dest->remappedTechniques = static_cast(zone->get_asset_pointer(techset, this->name())); - for (std::int32_t pass = 0; pass < techniqueHeader->numPasses; pass++) + for (std::int32_t technique = 0; technique < 48; technique++) { - if (techniquePasses[pass].vertexDecl) + if (!data->techniques[technique]) { - techniquePasses[pass].vertexDecl = - reinterpret_cast(zone->get_asset_pointer( - vertexdecl, techniquePasses[pass].vertexDecl->name)); + continue; } - if (techniquePasses[pass].vertexShader) - { - techniquePasses[pass].vertexShader = - reinterpret_cast(zone->get_asset_pointer( - vertexshader, techniquePasses[pass].vertexShader->name)); - } + buf->align(3); - if (techniquePasses[pass].pixelShader) - { - techniquePasses[pass].pixelShader = - reinterpret_cast(zone->get_asset_pointer( - pixelshader, techniquePasses[pass].pixelShader->name)); - } + auto techniqueHeader = buf->write(&data->techniques[technique]->hdr); + auto techniquePasses = buf->write(data->techniques[technique]->pass, techniqueHeader->numPasses); - if (techniquePasses[pass].argumentDef) + for (std::int32_t pass = 0; pass < techniqueHeader->numPasses; pass++) { - buf->align(3); - auto destArgs = buf->write(techniquePasses[pass].argumentDef, - techniquePasses[pass].perPrimArgCount + - techniquePasses[pass].perObjArgCount + - techniquePasses[pass].stableArgCount); - - for (auto arg = 0; arg < - techniquePasses[pass].perPrimArgCount + - techniquePasses[pass].perObjArgCount + - techniquePasses[pass].stableArgCount; arg++) + if (techniquePasses[pass].vertexDecl) { - auto curArg = &techniquePasses[pass].argumentDef[arg]; + techniquePasses[pass].vertexDecl = + reinterpret_cast(zone->get_asset_pointer( + vertexdecl, techniquePasses[pass].vertexDecl->name)); + } + + if (techniquePasses[pass].vertexShader) + { + techniquePasses[pass].vertexShader = + reinterpret_cast(zone->get_asset_pointer( + vertexshader, techniquePasses[pass].vertexShader->name)); + } - if (curArg->type == 1 || curArg->type == 7) + if (techniquePasses[pass].pixelShader) + { + techniquePasses[pass].pixelShader = + reinterpret_cast(zone->get_asset_pointer( + pixelshader, techniquePasses[pass].pixelShader->name)); + } + + if (techniquePasses[pass].argumentDef) + { + buf->align(3); + auto destArgs = buf->write(techniquePasses[pass].argumentDef, + techniquePasses[pass].perPrimArgCount + + techniquePasses[pass].perObjArgCount + + techniquePasses[pass].stableArgCount); + + for (auto arg = 0; arg < + techniquePasses[pass].perPrimArgCount + + techniquePasses[pass].perObjArgCount + + techniquePasses[pass].stableArgCount; arg++) { - if (destArgs[arg].u.literalConst) + auto curArg = &techniquePasses[pass].argumentDef[arg]; + + if (curArg->type == 1 || curArg->type == 7) { - destArgs[arg].u.literalConst = buf->write_s(3, destArgs[arg].u.literalConst, 4); + if (destArgs[arg].u.literalConst) + { + destArgs[arg].u.literalConst = buf->write_s(3, destArgs[arg].u.literalConst, 4); + } } } - } - ZoneBuffer::ClearPointer(&techniquePasses[pass].argumentDef); + ZoneBuffer::ClearPointer(&techniquePasses[pass].argumentDef); + } } + + buf->write_str(techniqueHeader->name); + + ZoneBuffer::ClearPointer(&techniqueHeader->name); + ZoneBuffer::ClearPointer(&dest->techniques[technique]); } - buf->write_str(techniqueHeader->name); - - ZoneBuffer::ClearPointer(&techniqueHeader->name); - ZoneBuffer::ClearPointer(&dest->techniques[technique]); + END_LOG_STREAM; + buf->pop_stream(); } + else + { + alpha::MaterialTechniqueSet alpha_techset = {}; + + auto data = &alpha_techset; + auto dest = buf->write(data); + + buf->push_stream(3); + START_LOG_STREAM; - END_LOG_STREAM; - buf->pop_stream(); + dest->name = buf->write_str(va(",%s", this->name().data()).data()); + + END_LOG_STREAM; + buf->pop_stream(); + } } char* ITechset::parse_statebits(const std::string& techset, ZoneMemory* mem) diff --git a/src/IW4/Structs.hpp b/src/IW4/Structs.hpp index 3021695..5722875 100644 --- a/src/IW4/Structs.hpp +++ b/src/IW4/Structs.hpp @@ -284,6 +284,175 @@ namespace ZoneTool GfxImage* image; // Image* actually }; + namespace alpha + { + enum MaterialTechniqueType + { + TECHNIQUE_DEPTH_PREPASS = 0x0, + TECHNIQUE_BUILD_FLOAT_Z = 0x1, + TECHNIQUE_BUILD_SHADOWMAP_DEPTH = 0x2, + TECHNIQUE_BUILD_SHADOWMAP_COLOR = 0x3, + TECHNIQUE_UNLIT = 0x4, + TECHNIQUE_EMISSIVE = 0x5, + TECHNIQUE_EMISSIVE_DFOG = 0x6, + TECHNIQUE_EMISSIVE_SHADOW = 0x7, + TECHNIQUE_EMISSIVE_SHADOW_DFOG = 0x8, + TECHNIQUE_LIT_BEGIN = 0x9, + TECHNIQUE_LIT = 0x9, + TECHNIQUE_LIT_DFOG = 0xA, + TECHNIQUE_LIT_SUN = 0xB, + TECHNIQUE_LIT_SUN_DFOG = 0xC, + TECHNIQUE_LIT_SUN_SHADOW = 0xD, + TECHNIQUE_LIT_SUN_SHADOW_DFOG = 0xE, + TECHNIQUE_LIT_SPOT = 0xF, + TECHNIQUE_LIT_SPOT_DFOG = 0x10, + TECHNIQUE_LIT_SPOT_SHADOW = 0x11, + TECHNIQUE_LIT_SPOT_SHADOW_DFOG = 0x12, + TECHNIQUE_LIT_OMNI = 0x13, + TECHNIQUE_LIT_OMNI_DFOG = 0x14, + TECHNIQUE_LIT_OMNI_SHADOW = 0x15, + TECHNIQUE_LIT_OMNI_SHADOW_DFOG = 0x16, + TECHNIQUE_LIT_END = 0x17, + TECHNIQUE_LIGHT_SPOT = 0x17, + TECHNIQUE_LIGHT_OMNI = 0x18, + TECHNIQUE_LIGHT_SPOT_SHADOW = 0x19, + TECHNIQUE_FAKELIGHT_NORMAL = 0x1A, + TECHNIQUE_FAKELIGHT_VIEW = 0x1B, + TECHNIQUE_SUNLIGHT_PREVIEW = 0x1C, + TECHNIQUE_CASE_TEXTURE = 0x1D, + TECHNIQUE_WIREFRAME_SOLID = 0x1E, + TECHNIQUE_WIREFRAME_SHADED = 0x1F, + TECHNIQUE_DEBUG_BUMPMAP = 0x20, + TECHNIQUE_COUNT = 0x21, + TECHNIQUE_TOTAL_COUNT = 0x22, + TECHNIQUE_NONE = 0x23, + }; + + struct MaterialPass + { + VertexDecl* vertexDecl; + VertexShader* vertexShaderArray[15]; + VertexShader* vertexShader; + PixelShader* pixelShader; + char perPrimArgCount; + char perObjArgCount; + char stableArgCount; + char customSamplerFlags; + char precompiledIndex; + ShaderArgumentDef* args; + }; + + struct MaterialTechnique + { + const char* name; + unsigned __int16 flags; + unsigned __int16 passCount; + MaterialPass passArray[1]; + }; + +#pragma pack(push, 4) + struct MaterialTechniqueSet + { + const char* name; + char worldVertFormat; + char unused[2]; + MaterialTechniqueSet* remappedTechniqueSet; + MaterialTechnique* techniques[33]; + }; +#pragma pack(pop) + + struct D3DTexture + { + //DWORD Common; + //DWORD Fence; + //DWORD BaseFlush; + //DWORD MipFlush; + //DWORD Format; + char unk[52]; + }; + + struct CardMemory + { + int platform[1]; + }; + + struct GfxImageStreamData + { + unsigned __int16 width; + unsigned __int16 height; + unsigned int pixelSize; + }; + +#pragma pack(push, 4) + struct GfxImage + { + D3DTexture texture; + int format; + char mapType; + char semantic; + char category; + CardMemory cardMemory; + unsigned __int16 width; + unsigned __int16 height; + unsigned __int16 depth; + char levelCount; + char cached; + char* pixels; + GfxImageStreamData streams[4]; + const char* name; + }; +#pragma pack(pop) + + struct GfxDrawSurfFields + { + unsigned __int64 objectId : 16; + unsigned __int64 reflectionProbeIndex : 8; + unsigned __int64 hasGfxEntIndex : 1; + unsigned __int64 customIndex : 5; + unsigned __int64 materialSortedIndex : 12; + unsigned __int64 prepass : 2; + unsigned __int64 useHeroLighting : 1; + unsigned __int64 sceneLightIndex : 8; + unsigned __int64 surfType : 4; + unsigned __int64 primarySortKey : 6; + unsigned __int64 unused : 1; + }; + + union GfxDrawSurf + { + GfxDrawSurfFields fields; + unsigned __int64 packed; + }; + + struct __declspec(align(8)) MaterialInfo + { + const char* name; + char gameFlags; + char sortKey; + char textureAtlasRowCount; + char textureAtlasColumnCount; + GfxDrawSurf drawSurf; + unsigned int surfaceTypeBits; + }; + + struct __declspec(align(8)) Material + { + MaterialInfo info; + char stateBitsEntry[33]; + char textureCount; + char constantCount; + char stateBitsCount; + char stateFlags; + char cameraRegion; + char layerCount; + MaterialTechniqueSet* techniqueSet; + MaterialImage* textureTable; + MaterialConstantDef* constantTable; + GfxStateBits* stateBitsTable; + const char** subMaterials; + }; + } + struct Material { const char* name; // 0 diff --git a/src/IW4/Zone.cpp b/src/IW4/Zone.cpp index 8d4f3dd..1b2b34c 100644 --- a/src/IW4/Zone.cpp +++ b/src/IW4/Zone.cpp @@ -31,7 +31,7 @@ namespace ZoneTool { if (m_assets[idx]->type() == type && m_assets[idx]->name() == name) { - auto ptr = reinterpret_cast((3 << ((target_ == zone_target::pc) ? 28 : 29)) | ((this->m_assetbase + (8 * idx) + 4) & 0x0FFFFFFF) + 1); + auto ptr = reinterpret_cast((3 << 28) | ((this->m_assetbase + (8 * idx) + 4) & 0x0FFFFFFF) + 1); return ptr; } } @@ -147,6 +147,17 @@ namespace ZoneTool // init streams properly buf->init_streams(target_ == zone_target::pc ? 8 : 6); + if (target_ != zone_target::pc) + { + auto pak_version = 269; + if (target_version_ == zone_target_version::iw4_alpha_482) + { + pak_version = 253; + } + + buf->alloc_image_pak(pak_version); + } + const auto start_time = GetTickCount64(); // make a folder in main, for the map images @@ -266,13 +277,17 @@ namespace ZoneTool zone->externalsize = 0; // Update stream data - for (int i = 0; i < num_streams; i++) + for (int i = 0; i < (target_ != zone_target::pc ? 6 : 8); i++) { zone->streams[i] = buf->stream_offset(i); } + auto streamed_files = buf->stream_files(); + if (target_ != zone_target::pc) { + mem_ptr->streams[5] = 1352; + endian_convert(&mem_ptr->size); endian_convert(&mem_ptr->externalsize); for (auto& stream : mem_ptr->streams) @@ -295,42 +310,72 @@ namespace ZoneTool if (target_ == zone_target::xbox360 || target_ == zone_target::ps3) { + auto pak_version = 269; if (target_version_ == zone_target_version::iw4_alpha_482) { - header->version = 253; - } - else - { - header->version = 269; + pak_version = 253; } - + + header->version = pak_version; endian_convert(&header->version); } + // fix entry count + if (streamed_files.size()) + { + XAssetStreamFile meme = {}; + memset(&meme, 0, sizeof XAssetStreamFile); + + const auto needed_entries = 4 - (streamed_files.size() % 4); + for (auto i = 0u; i < needed_entries; i++) + { + streamed_files.push_back(meme); + } + } + // Save fastfile - ZoneBuffer fastfile(buf_compressed.size() + ((target_ == zone_target::xbox360 || target_ == zone_target::ps3) ? 37 : 21)); + ZoneBuffer fastfile(buf_compressed.size() + ((target_ == zone_target::xbox360 || target_ == zone_target::ps3) ? 37 : 21) + (streamed_files.size() * 12)); fastfile.init_streams(1); fastfile.write_stream(header, 21); if (target_ == zone_target::xbox360 || target_ == zone_target::ps3) - { + { auto language = 1; - auto entry_count = 0; - + auto entry_count = streamed_files.size(); + endian_convert(&language); endian_convert(&entry_count); fastfile.write_stream(&language, 4); fastfile.write_stream(&entry_count, 4); + + // write streamed files + for (auto& stream_file : streamed_files) + { + auto file = fastfile.at(); + fastfile.write_stream(&stream_file, sizeof XAssetStreamFile, 1); + + endian_convert(&file->fileIndex); + endian_convert(&file->offset); + endian_convert(&file->offsetEnd); + } + fastfile.write_stream(&mem_ptr->size, 4); fastfile.write_stream(&mem_ptr->size, 4); } fastfile.write(buf_compressed.data(), buf_compressed.size()); - // rekto - // fastfile.save("zone\\pluto\\common\\" + this->name_ + ".ff"); - fastfile.save("zone\\english\\" + this->name_ + ".ff"); + // buf->save_image_pak("imagefile5.pakm"); + + if (target_version_ == zone_target_version::iw4_alpha_482) + { + fastfile.save("zone\\english\\" + this->name_ + ".ffm"); + } + else + { + fastfile.save("zone\\english\\" + this->name_ + ".ff"); + } ZONETOOL_INFO("Successfully compiled fastfile \"%s\"!", this->name_.data()); ZONETOOL_INFO("Compiling took %u msec.", GetTickCount64() - start_time); diff --git a/src/IW5/Assets/RawFile.cpp b/src/IW5/Assets/RawFile.cpp index 45ae6ad..4ece700 100644 --- a/src/IW5/Assets/RawFile.cpp +++ b/src/IW5/Assets/RawFile.cpp @@ -9,7 +9,7 @@ #include "stdafx.hpp" #include -#define ZONETOOL_BRANDING "Compiled using ZoneTool by RektInator, localhost & X3RX35." +#define ZONETOOL_BRANDING "Compiled using ZoneTool by RektInator." namespace ZoneTool { diff --git a/src/ZoneTool/ZoneTool.cpp b/src/ZoneTool/ZoneTool.cpp index ac00817..d06d009 100644 --- a/src/ZoneTool/ZoneTool.cpp +++ b/src/ZoneTool/ZoneTool.cpp @@ -462,6 +462,7 @@ namespace ZoneTool { ZONETOOL_INFO("ZoneTool initialization complete!"); ZONETOOL_INFO("Welcome to ZoneTool v" ZONETOOL_VERSION " written by RektInator."); + ZONETOOL_INFO(" \"No matter how hard or unlikely, if it's possible, it will be done.\""); ZONETOOL_INFO("Special thanks to: Laupetin, NTAuthority, momo5502, TheApadayo, localhost, X3RX35 & homura."); if (linker) diff --git a/src/ZoneUtils/Utils/PakFile.cpp b/src/ZoneUtils/Utils/PakFile.cpp new file mode 100644 index 0000000..69c56d5 --- /dev/null +++ b/src/ZoneUtils/Utils/PakFile.cpp @@ -0,0 +1,51 @@ +// ======================= ZoneTool ======================= +// zonetool, a fastfile linker for various +// Call of Duty titles. +// +// Project: https://github.com/ZoneTool/zonetool +// Author: RektInator (https://github.com/RektInator) +// License: GNU GPL v3.0 +// ======================================================== +#include "stdafx.hpp" + +namespace ZoneTool +{ + PakFile::PakFile(const std::uint32_t version) + { + this->buffer_ = std::make_shared(1024 * 1024 * 100); + this->buffer_->init_streams(1); + + // write header + this->buffer_->write_stream("IWffu100", 8, 1); + auto dest_version = this->buffer_->write(&version); + + // endian convert version + endian_convert(dest_version); + } + + std::pair PakFile::add_entry(const std::vector& pixels) const + { + // get start position + auto start_location = this->buffer_->size(); + + // write image data + auto compressed = ZoneBuffer::compress_zlib(pixels); + this->buffer_->write_stream(compressed.data(), compressed.size(), 1); + + // get end position + auto end_location = this->buffer_->size(); + + return { start_location, end_location }; + } + + void PakFile::save(const std::string& filename) + { + this->buffer_->save(filename); + } + + std::size_t PakFile::size() + { + return this->buffer_->size(); + } + +} diff --git a/src/ZoneUtils/Utils/PakFile.hpp b/src/ZoneUtils/Utils/PakFile.hpp new file mode 100644 index 0000000..1ea3d1f --- /dev/null +++ b/src/ZoneUtils/Utils/PakFile.hpp @@ -0,0 +1,26 @@ +// ======================= ZoneTool ======================= +// zonetool, a fastfile linker for various +// Call of Duty titles. +// +// Project: https://github.com/ZoneTool/zonetool +// Author: RektInator (https://github.com/RektInator) +// License: GNU GPL v3.0 +// ======================================================== +#pragma once + +namespace ZoneTool +{ + class PakFile + { + public: + PakFile(const std::uint32_t version); + + [[nodiscard]] std::pair add_entry(const std::vector& pixels) const; + void save(const std::string& filename); + std::size_t size(); + + private: + std::shared_ptr buffer_; + + }; +} diff --git a/src/ZoneUtils/Zone/ZoneBuffer.cpp b/src/ZoneUtils/Zone/ZoneBuffer.cpp index 9737b48..a9c2472 100644 --- a/src/ZoneUtils/Zone/ZoneBuffer.cpp +++ b/src/ZoneUtils/Zone/ZoneBuffer.cpp @@ -76,6 +76,27 @@ namespace ZoneTool this->m_zonepointers.clear(); } + void ZoneBuffer::alloc_image_pak(const std::uint32_t version) + { + image_pak_ = std::make_shared(version); + } + PakFile* ZoneBuffer::image_pak() + { + return image_pak_.get(); + } + + void ZoneBuffer::add_image(const std::vector& pixels) + { + const auto stream_data = this->image_pak()->add_entry(pixels); + + XAssetStreamFile stream_file = {}; + stream_file.fileIndex = 5; + stream_file.offset = stream_data.first; + stream_file.offsetEnd = stream_data.second; + + this->stream_files_.push_back(stream_file); + } + void ZoneBuffer::init_streams(std::size_t streams) { this->m_numstreams = streams; @@ -226,51 +247,66 @@ namespace ZoneTool _fb.close(); } - std::vector ZoneBuffer::compress_zstd() + void ZoneBuffer::save_image_pak(const std::string& filename) + { + this->image_pak()->save(filename); + } + + std::vector ZoneBuffer::compress_zlib(const std::uint8_t* data, const std::size_t data_size) { + auto compressBound = [](unsigned long sourceLen) + { + return static_cast((ceil(sourceLen * 1.001)) + 12); + }; + // calculate buffer size needed for current zone - auto size = ZSTD_compressBound(this->m_pos); + auto size = compressBound(data_size); // alloc array for compressed data std::vector compressed; compressed.resize(size); // compress buffer - auto destsize = ZSTD_compress(compressed.data(), size, this->m_buf.data(), this->m_pos, 11); - compressed.resize(destsize); - - if (ZSTD_isError(destsize)) - { - ZONETOOL_ERROR("An error occured while compressing the fastfile: %s", ZSTD_getErrorName(destsize)); - return {}; - } + auto status = compress2(compressed.data(), &size, data, data_size, ZLIB_BEST_COMPRESSION); + compressed.resize(size); // return compressed buffer return compressed; } - std::vector ZoneBuffer::compress_zlib() + std::vector ZoneBuffer::compress_zlib(const std::vector& data) { - auto compressBound = [](unsigned long sourceLen) - { - return static_cast((ceil(sourceLen * 1.001)) + 12); - }; + return ZoneBuffer::compress_zlib(data.data(), data.size()); + } + std::vector ZoneBuffer::compress_zstd() + { // calculate buffer size needed for current zone - auto size = compressBound(this->m_pos); + auto size = ZSTD_compressBound(this->m_pos); // alloc array for compressed data std::vector compressed; compressed.resize(size); // compress buffer - auto status = compress2(compressed.data(), &size, this->m_buf.data(), this->m_pos, ZLIB_BEST_COMPRESSION); - compressed.resize(size); + auto destsize = ZSTD_compress(compressed.data(), size, this->m_buf.data(), this->m_pos, 11); + compressed.resize(destsize); + + if (ZSTD_isError(destsize)) + { + ZONETOOL_ERROR("An error occured while compressing the fastfile: %s", ZSTD_getErrorName(destsize)); + return {}; + } // return compressed buffer return compressed; } + std::vector ZoneBuffer::compress_zlib() + { + return ZoneBuffer::compress_zlib(this->m_buf.data(), this->m_pos); + } + void GenerateKeys(XZoneKey* key) { srand(time(nullptr)); diff --git a/src/ZoneUtils/Zone/ZoneBuffer.hpp b/src/ZoneUtils/Zone/ZoneBuffer.hpp index 5bae92c..01f7857 100644 --- a/src/ZoneUtils/Zone/ZoneBuffer.hpp +++ b/src/ZoneUtils/Zone/ZoneBuffer.hpp @@ -84,6 +84,7 @@ namespace ZoneTool std::uint8_t iv[16]; }; + class PakFile; class ZoneBuffer { protected: @@ -137,13 +138,26 @@ namespace ZoneTool std::unordered_map m_zonepointers; + std::shared_ptr image_pak_; + std::vector stream_files_; + public: ZoneBuffer(); ~ZoneBuffer(); + PakFile* image_pak(); + ZoneBuffer(std::vector data); ZoneBuffer(std::size_t size); + void add_image(const std::vector& pixels); + void alloc_image_pak(const std::uint32_t version); + + std::vector stream_files() + { + return stream_files_; + } + std::uintptr_t get_stream_pos() { return this->m_zonestreams[this->m_stream]; @@ -332,7 +346,11 @@ namespace ZoneTool } void save(const std::string& filename); + void save_image_pak(const std::string& filename); + static std::vector compress_zlib(const std::uint8_t* data, const std::size_t size); + static std::vector compress_zlib(const std::vector& data); + std::vector compress_zstd(); std::vector compress_zlib(); void encrypt(); diff --git a/src/ZoneUtils/ZoneUtils.hpp b/src/ZoneUtils/ZoneUtils.hpp index de685cc..29f2c82 100644 --- a/src/ZoneUtils/ZoneUtils.hpp +++ b/src/ZoneUtils/ZoneUtils.hpp @@ -47,6 +47,13 @@ namespace ZoneTool std::uint32_t streams[num_streams]; }; + struct XAssetStreamFile + { + unsigned int fileIndex; + unsigned int offset; + unsigned int offsetEnd; + }; + struct XZoneInfo { const char* zone; @@ -122,7 +129,7 @@ namespace ZoneTool } template static void endian_convert(T* data) { - return endian_convert(data, sizeof T); + return endian_convert((void*)data, sizeof T); } #pragma push(pop) } @@ -131,6 +138,7 @@ namespace ZoneTool #include "CSV.hpp" #include "Zone/ZoneMemory.hpp" #include "Zone/ZoneBuffer.hpp" +#include "Utils/PakFile.hpp" #include "Zone/Zone.hpp" #include "IAsset.hpp" #include "Utils/FileReader.hpp"