Co-authored-by: Louvenarde <louve@louve.systems>
Co-authored-by: FutureRave <edoardo.sanguineti222@gmail.com>
This commit is contained in:
Louve 2023-05-14 13:21:31 +02:00 committed by GitHub
parent 9e036e5174
commit 8ec6441232
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 155 additions and 51 deletions

@ -1 +1 @@
Subproject commit 6d70c2ecfe3c34d9b3945fd87a90265e63763069
Subproject commit 4fee3813071b11a95533ab8be975785ec6262358

View File

@ -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)
{
AssertSize(Game::snd_alias_list_t, 12);

View File

@ -10,5 +10,8 @@ namespace Assets
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 mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
void dump(Game::XAssetHeader header) override;
Isnd_alias_list_t();
};
}

View File

@ -39,7 +39,8 @@ namespace Components
Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(const std::string& name)
{
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())
{
@ -57,9 +58,18 @@ namespace Components
}
#endif
if (ZoneBuilder::IsEnabled())
{
Logger::Print("Loading model surface {} at path \"{}\" failed!", name, path);
}
else
{
Logger::Error(Game::ERR_FATAL, "Loading model {} failed!", name);
}
return nullptr;
}
Game::CModelHeader header;
if (!model.read(&header, sizeof header))
{

View File

@ -18,6 +18,8 @@ namespace Components
volatile bool ZoneBuilder::CommandThreadTerminate = false;
std::thread ZoneBuilder::CommandThread;
iw4of::api ZoneBuilder::ExporterAPI(GetExporterAPIParams());
std::string ZoneBuilder::DumpingZone{};
ZoneBuilder::Zone::Zone(const std::string& name) : indexStart(0), externalSize(0),
// Reserve 100MB by default.
@ -757,6 +759,23 @@ namespace Components
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 params{};
@ -815,7 +834,7 @@ namespace Components
void* data = Utils::Memory::GetAllocator()->allocate(size);
std::memcpy(data, *loadDef, size);
image->texture.loadDef = reinterpret_cast<Game::GfxImageLoadDef *>(data);
image->texture.loadDef = static_cast<Game::GfxImageLoadDef*>(data);
return 0;
}
@ -857,7 +876,7 @@ namespace Components
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 },
{ "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 }
};
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()
{
ExitProcess(0);
@ -938,15 +946,7 @@ namespace Components
Command::Add("quit", ZoneBuilder::Com_Quitf_t);
// now load default assets and shaders
if (FastFiles::Exists("defaults") && FastFiles::Exists("techsets"))
{
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");
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-buildall: builds all zones in zone_source\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-quit: quits the program\n");
Logger::Print(" --------------------------------------------------------------------------------\n");
@ -1097,6 +1098,55 @@ namespace Components
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()
{
// ReSharper disable CppStaticAssertFailure
@ -1200,7 +1250,7 @@ namespace Components
// don't remap techsets
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())
{
@ -1209,6 +1259,44 @@ namespace Components
OutputDebugStringA(Utils::String::Format("%s\n", name));
#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)
@ -1627,31 +1715,6 @@ namespace Components
header.material->info.name, header.material->info.sortKey & 0xFF, header.material->info.gameFlags & 0xFF, header.material->stateFlags & 0xFF);
}, 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");
});
}
}

View File

@ -137,6 +137,9 @@ namespace Components
static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace();
static Game::XAssetHeader GetEmptyAssetIfCommon(Game::XAssetType type, const std::string& name, Zone* builder);
static void RefreshExporterWorkDirectory();
static iw4of::api* GetExporter();
private:
static int StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image);
@ -155,6 +158,8 @@ namespace Components
static bool IsThreadMainThreadHook();
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 CommandThreadCallback();
@ -164,5 +169,7 @@ namespace Components
static volatile bool CommandThreadTerminate;
static std::thread CommandThread;
static iw4of::api ExporterAPI;
static std::string DumpingZone;
};
}

View File

@ -2947,6 +2947,9 @@ namespace Components
iw4Map->mapEnts = &codolMapEnts;
memcpy(&iw4Map->smodelNodeCount, &codolMap->smodelNodeCount, 48);
// unused on IW4
iw4Map->numLeafSurfaces = 0;
AssetHandler::Relocate(&cancerMap->info.numCPlanes, &iw4Map->planeCount, 8);
AssetHandler::Relocate(&cancerMap->numStaticModels, &iw4Map->numStaticModels, 8);
AssetHandler::Relocate(&cancerMap->info.numMaterials, &iw4Map->numMaterials, 24);