Zb export (#1033)
Co-authored-by: Louvenarde <louve@louve.systems> Co-authored-by: FutureRave <edoardo.sanguineti222@gmail.com>
This commit is contained in:
parent
9e036e5174
commit
8ec6441232
2
deps/iw4-open-formats
vendored
2
deps/iw4-open-formats
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 6d70c2ecfe3c34d9b3945fd87a90265e63763069
|
Subproject commit 4fee3813071b11a95533ab8be975785ec6262358
|
@ -40,6 +40,24 @@ namespace Assets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Isnd_alias_list_t::dump(Game::XAssetHeader header)
|
||||||
|
{
|
||||||
|
Components::ZoneBuilder::GetExporter()->write(Game::XAssetType::ASSET_TYPE_SOUND, header.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Isnd_alias_list_t::Isnd_alias_list_t()
|
||||||
|
{
|
||||||
|
Components::Command::Add("dumpSound", [this](const Components::Command::Params* param)
|
||||||
|
{
|
||||||
|
const auto header = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_SOUND, param->get(1));
|
||||||
|
if (header.data)
|
||||||
|
{
|
||||||
|
Components::ZoneBuilder::RefreshExporterWorkDirectory();
|
||||||
|
this->dump(header);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Isnd_alias_list_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
void Isnd_alias_list_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
||||||
{
|
{
|
||||||
AssertSize(Game::snd_alias_list_t, 12);
|
AssertSize(Game::snd_alias_list_t, 12);
|
||||||
|
@ -10,5 +10,8 @@ namespace Assets
|
|||||||
void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
|
void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
|
||||||
void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
|
void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
|
||||||
void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
|
void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
|
||||||
|
void dump(Game::XAssetHeader header) override;
|
||||||
|
|
||||||
|
Isnd_alias_list_t();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,8 @@ namespace Components
|
|||||||
Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(const std::string& name)
|
Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(const std::string& name)
|
||||||
{
|
{
|
||||||
Utils::Memory::Allocator allocator;
|
Utils::Memory::Allocator allocator;
|
||||||
FileSystem::FileReader model(std::format("models/{}", name));
|
const auto path = std::format("models/{}", name);
|
||||||
|
FileSystem::FileReader model(path);
|
||||||
|
|
||||||
if (!model.exists())
|
if (!model.exists())
|
||||||
{
|
{
|
||||||
@ -57,9 +58,18 @@ namespace Components
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (ZoneBuilder::IsEnabled())
|
||||||
|
{
|
||||||
|
Logger::Print("Loading model surface {} at path \"{}\" failed!", name, path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Logger::Error(Game::ERR_FATAL, "Loading model {} failed!", name);
|
Logger::Error(Game::ERR_FATAL, "Loading model {} failed!", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Game::CModelHeader header;
|
Game::CModelHeader header;
|
||||||
if (!model.read(&header, sizeof header))
|
if (!model.read(&header, sizeof header))
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,8 @@ namespace Components
|
|||||||
|
|
||||||
volatile bool ZoneBuilder::CommandThreadTerminate = false;
|
volatile bool ZoneBuilder::CommandThreadTerminate = false;
|
||||||
std::thread ZoneBuilder::CommandThread;
|
std::thread ZoneBuilder::CommandThread;
|
||||||
|
iw4of::api ZoneBuilder::ExporterAPI(GetExporterAPIParams());
|
||||||
|
std::string ZoneBuilder::DumpingZone{};
|
||||||
|
|
||||||
ZoneBuilder::Zone::Zone(const std::string& name) : indexStart(0), externalSize(0),
|
ZoneBuilder::Zone::Zone(const std::string& name) : indexStart(0), externalSize(0),
|
||||||
// Reserve 100MB by default.
|
// Reserve 100MB by default.
|
||||||
@ -757,6 +759,23 @@ namespace Components
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZoneBuilder::RefreshExporterWorkDirectory()
|
||||||
|
{
|
||||||
|
if (ZoneBuilder::DumpingZone.empty())
|
||||||
|
{
|
||||||
|
ExporterAPI.set_work_path(std::format("userraw/dump/stray"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExporterAPI.set_work_path(std::format("userraw/dump/{}", ZoneBuilder::DumpingZone));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iw4of::api* ZoneBuilder::GetExporter()
|
||||||
|
{
|
||||||
|
return &ExporterAPI;
|
||||||
|
}
|
||||||
|
|
||||||
iw4of::params_t ZoneBuilder::Zone::getIW4OfApiParams()
|
iw4of::params_t ZoneBuilder::Zone::getIW4OfApiParams()
|
||||||
{
|
{
|
||||||
iw4of::params_t params{};
|
iw4of::params_t params{};
|
||||||
@ -815,7 +834,7 @@ namespace Components
|
|||||||
void* data = Utils::Memory::GetAllocator()->allocate(size);
|
void* data = Utils::Memory::GetAllocator()->allocate(size);
|
||||||
std::memcpy(data, *loadDef, size);
|
std::memcpy(data, *loadDef, size);
|
||||||
|
|
||||||
image->texture.loadDef = reinterpret_cast<Game::GfxImageLoadDef *>(data);
|
image->texture.loadDef = static_cast<Game::GfxImageLoadDef*>(data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -857,7 +876,7 @@ namespace Components
|
|||||||
return GetCurrentThreadId() == Utils::Hook::Get<DWORD>(0x1CDE7FC);
|
return GetCurrentThreadId() == Utils::Hook::Get<DWORD>(0x1CDE7FC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Game::XZoneInfo baseZones_old[] =
|
static Game::XZoneInfo baseZones[] =
|
||||||
{
|
{
|
||||||
{ "code_pre_gfx_mp", Game::DB_ZONE_CODE, 0 },
|
{ "code_pre_gfx_mp", Game::DB_ZONE_CODE, 0 },
|
||||||
{ "localized_code_pre_gfx_mp", Game::DB_ZONE_CODE_LOC, 0 },
|
{ "localized_code_pre_gfx_mp", Game::DB_ZONE_CODE_LOC, 0 },
|
||||||
@ -869,17 +888,6 @@ namespace Components
|
|||||||
{ "localized_ui_mp", Game::DB_ZONE_GAME, 0 }
|
{ "localized_ui_mp", Game::DB_ZONE_GAME, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static Game::XZoneInfo baseZones[] =
|
|
||||||
{
|
|
||||||
{ "defaults", Game::DB_ZONE_CODE, 0 },
|
|
||||||
{ "techsets", Game::DB_ZONE_CODE, 0 },
|
|
||||||
{ "common_mp", Game::DB_ZONE_COMMON, 0 },
|
|
||||||
{ "localized_common_mp", Game::DB_ZONE_COMMON_LOC, 0 },
|
|
||||||
{ "ui_mp", Game::DB_ZONE_GAME, 0 },
|
|
||||||
{ "localized_ui_mp", Game::DB_ZONE_GAME, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void ZoneBuilder::Com_Quitf_t()
|
void ZoneBuilder::Com_Quitf_t()
|
||||||
{
|
{
|
||||||
ExitProcess(0);
|
ExitProcess(0);
|
||||||
@ -938,15 +946,7 @@ namespace Components
|
|||||||
Command::Add("quit", ZoneBuilder::Com_Quitf_t);
|
Command::Add("quit", ZoneBuilder::Com_Quitf_t);
|
||||||
|
|
||||||
// now load default assets and shaders
|
// now load default assets and shaders
|
||||||
if (FastFiles::Exists("defaults") && FastFiles::Exists("techsets"))
|
|
||||||
{
|
|
||||||
Game::DB_LoadXAssets(baseZones, ARRAYSIZE(baseZones), 0);
|
Game::DB_LoadXAssets(baseZones, ARRAYSIZE(baseZones), 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Missing new init zones (defaults.ff & techsets.ff). You will need to load fastfiles to manually obtain techsets.\n");
|
|
||||||
Game::DB_LoadXAssets(baseZones_old, ARRAYSIZE(baseZones_old), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::Print("Waiting for fastiles to load...\n");
|
Logger::Print("Waiting for fastiles to load...\n");
|
||||||
while (!Game::Sys_IsDatabaseReady())
|
while (!Game::Sys_IsDatabaseReady())
|
||||||
@ -983,6 +983,7 @@ namespace Components
|
|||||||
Logger::Print("\t-buildzone [zone]: builds a zone from a csv located in zone_source\n");
|
Logger::Print("\t-buildzone [zone]: builds a zone from a csv located in zone_source\n");
|
||||||
Logger::Print("\t-buildall: builds all zones in zone_source\n");
|
Logger::Print("\t-buildall: builds all zones in zone_source\n");
|
||||||
Logger::Print("\t-verifyzone [zone]: loads and verifies the specified zone\n");
|
Logger::Print("\t-verifyzone [zone]: loads and verifies the specified zone\n");
|
||||||
|
Logger::Print("\t-dumpzone [zone]: loads and dump the specified zone\n");
|
||||||
Logger::Print("\t-listassets [assettype]: lists all loaded assets of the specified type\n");
|
Logger::Print("\t-listassets [assettype]: lists all loaded assets of the specified type\n");
|
||||||
Logger::Print("\t-quit: quits the program\n");
|
Logger::Print("\t-quit: quits the program\n");
|
||||||
Logger::Print(" --------------------------------------------------------------------------------\n");
|
Logger::Print(" --------------------------------------------------------------------------------\n");
|
||||||
@ -1097,6 +1098,55 @@ namespace Components
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iw4of::params_t ZoneBuilder::GetExporterAPIParams()
|
||||||
|
{
|
||||||
|
iw4of::params_t params{};
|
||||||
|
|
||||||
|
params.write_only_once = true;
|
||||||
|
|
||||||
|
params.find_other_asset = [](int type, const std::string& name) -> void*
|
||||||
|
{
|
||||||
|
if (ZoneBuilder::DumpingZone.empty())
|
||||||
|
{
|
||||||
|
return Game::DB_FindXAssetHeader(static_cast<Game::XAssetType>(type), name.data()).data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not deadlock the DB
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
params.fs_read_file = [](const std::string& filename) -> std::string
|
||||||
|
{
|
||||||
|
auto file = FileSystem::File(filename);
|
||||||
|
if (file.exists())
|
||||||
|
{
|
||||||
|
return file.getBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
params.get_from_string_table = [](const unsigned int& id) -> std::string
|
||||||
|
{
|
||||||
|
return Game::SL_ConvertToString(static_cast<Game::scr_string_t>(id));
|
||||||
|
};
|
||||||
|
|
||||||
|
params.print = [](iw4of::params_t::print_type t, const std::string& message) -> void
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case iw4of::params_t::P_ERR:
|
||||||
|
Logger::Error(Game::ERR_FATAL, "{}", message);
|
||||||
|
break;
|
||||||
|
case iw4of::params_t::P_WARN:
|
||||||
|
Logger::Print("{}", message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
ZoneBuilder::ZoneBuilder()
|
ZoneBuilder::ZoneBuilder()
|
||||||
{
|
{
|
||||||
// ReSharper disable CppStaticAssertFailure
|
// ReSharper disable CppStaticAssertFailure
|
||||||
@ -1200,7 +1250,7 @@ namespace Components
|
|||||||
// don't remap techsets
|
// don't remap techsets
|
||||||
Utils::Hook::Nop(0x5BC791, 5);
|
Utils::Hook::Nop(0x5BC791, 5);
|
||||||
|
|
||||||
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader /*asset*/, const std::string& name, bool* /*restrict*/)
|
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, const std::string& name, bool* /*restrict*/)
|
||||||
{
|
{
|
||||||
if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current())
|
if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current())
|
||||||
{
|
{
|
||||||
@ -1209,6 +1259,44 @@ namespace Components
|
|||||||
OutputDebugStringA(Utils::String::Format("%s\n", name));
|
OutputDebugStringA(Utils::String::Format("%s\n", name));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ZoneBuilder::DumpingZone.empty())
|
||||||
|
{
|
||||||
|
if (ExporterAPI.is_type_supported(type) && name[0] != ',')
|
||||||
|
{
|
||||||
|
ExporterAPI.write(type, asset.data);
|
||||||
|
Components::Logger::Print(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Command::Add("dumpzone", [](const Command::Params* params)
|
||||||
|
{
|
||||||
|
if (params->size() < 2) return;
|
||||||
|
|
||||||
|
std::string zone = params->get(1);
|
||||||
|
ZoneBuilder::DumpingZone = zone;
|
||||||
|
ZoneBuilder::RefreshExporterWorkDirectory();
|
||||||
|
|
||||||
|
Game::XZoneInfo info;
|
||||||
|
info.name = zone.data();
|
||||||
|
info.allocFlags = Game::DB_ZONE_MOD;
|
||||||
|
info.freeFlags = 0;
|
||||||
|
|
||||||
|
Logger::Print("Dumping zone '{}'...\n", zone);
|
||||||
|
|
||||||
|
Game::DB_LoadXAssets(&info, 1, true);
|
||||||
|
AssetHandler::FindOriginalAsset(Game::ASSET_TYPE_RAWFILE, zone.data()); // Lock until zone is loaded
|
||||||
|
|
||||||
|
Logger::Print("Unloading zone '{}'...\n", zone);
|
||||||
|
info.freeFlags = Game::DB_ZONE_MOD;
|
||||||
|
info.allocFlags = 0;
|
||||||
|
info.name = nullptr;
|
||||||
|
|
||||||
|
Game::DB_LoadXAssets(&info, 1, true);
|
||||||
|
AssetHandler::FindOriginalAsset(Game::ASSET_TYPE_RAWFILE, "default"); // Lock until zone is unloaded
|
||||||
|
Logger::Print("Zone '{}' dumped", ZoneBuilder::DumpingZone);
|
||||||
|
ZoneBuilder::DumpingZone = std::string();
|
||||||
});
|
});
|
||||||
|
|
||||||
Command::Add("verifyzone", [](const Command::Params* params)
|
Command::Add("verifyzone", [](const Command::Params* params)
|
||||||
@ -1627,31 +1715,6 @@ namespace Components
|
|||||||
header.material->info.name, header.material->info.sortKey & 0xFF, header.material->info.gameFlags & 0xFF, header.material->stateFlags & 0xFF);
|
header.material->info.name, header.material->info.sortKey & 0xFF, header.material->info.gameFlags & 0xFF, header.material->stateFlags & 0xFF);
|
||||||
}, nullptr, false);
|
}, nullptr, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Command::Add("iwiDump", [](const Command::Params* params)
|
|
||||||
{
|
|
||||||
if (params->size() < 2) return;
|
|
||||||
|
|
||||||
auto path = std::format("{}\\mods\\{}\\images", (*Game::fs_basepath)->current.string, params->get(1));
|
|
||||||
auto images = FileSystem::GetSysFileList(path, "iwi", false);
|
|
||||||
|
|
||||||
for (auto i = images.begin(); i != images.end();)
|
|
||||||
{
|
|
||||||
*i = std::format("images/{}", *i);
|
|
||||||
|
|
||||||
if (FileSystem::File(*i).exists())
|
|
||||||
{
|
|
||||||
i = images.erase(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::Print("------------------- BEGIN IWI DUMP -------------------\n");
|
|
||||||
Logger::Print("{}\n", nlohmann::json(images).dump());
|
|
||||||
Logger::Print("------------------- END IWI DUMP -------------------\n");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +137,9 @@ namespace Components
|
|||||||
static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace();
|
static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace();
|
||||||
|
|
||||||
static Game::XAssetHeader GetEmptyAssetIfCommon(Game::XAssetType type, const std::string& name, Zone* builder);
|
static Game::XAssetHeader GetEmptyAssetIfCommon(Game::XAssetType type, const std::string& name, Zone* builder);
|
||||||
|
static void RefreshExporterWorkDirectory();
|
||||||
|
|
||||||
|
static iw4of::api* GetExporter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image);
|
static int StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image);
|
||||||
@ -155,6 +158,8 @@ namespace Components
|
|||||||
static bool IsThreadMainThreadHook();
|
static bool IsThreadMainThreadHook();
|
||||||
static Game::Sys_File Sys_CreateFile_Stub(const char* dir, const char* filename);
|
static Game::Sys_File Sys_CreateFile_Stub(const char* dir, const char* filename);
|
||||||
|
|
||||||
|
static iw4of::params_t GetExporterAPIParams();
|
||||||
|
|
||||||
static void Com_Quitf_t();
|
static void Com_Quitf_t();
|
||||||
|
|
||||||
static void CommandThreadCallback();
|
static void CommandThreadCallback();
|
||||||
@ -164,5 +169,7 @@ namespace Components
|
|||||||
|
|
||||||
static volatile bool CommandThreadTerminate;
|
static volatile bool CommandThreadTerminate;
|
||||||
static std::thread CommandThread;
|
static std::thread CommandThread;
|
||||||
|
static iw4of::api ExporterAPI;
|
||||||
|
static std::string DumpingZone;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2947,6 +2947,9 @@ namespace Components
|
|||||||
iw4Map->mapEnts = &codolMapEnts;
|
iw4Map->mapEnts = &codolMapEnts;
|
||||||
memcpy(&iw4Map->smodelNodeCount, &codolMap->smodelNodeCount, 48);
|
memcpy(&iw4Map->smodelNodeCount, &codolMap->smodelNodeCount, 48);
|
||||||
|
|
||||||
|
// unused on IW4
|
||||||
|
iw4Map->numLeafSurfaces = 0;
|
||||||
|
|
||||||
AssetHandler::Relocate(&cancerMap->info.numCPlanes, &iw4Map->planeCount, 8);
|
AssetHandler::Relocate(&cancerMap->info.numCPlanes, &iw4Map->planeCount, 8);
|
||||||
AssetHandler::Relocate(&cancerMap->numStaticModels, &iw4Map->numStaticModels, 8);
|
AssetHandler::Relocate(&cancerMap->numStaticModels, &iw4Map->numStaticModels, 8);
|
||||||
AssetHandler::Relocate(&cancerMap->info.numMaterials, &iw4Map->numMaterials, 24);
|
AssetHandler::Relocate(&cancerMap->info.numMaterials, &iw4Map->numMaterials, 24);
|
||||||
|
Loading…
Reference in New Issue
Block a user