#include #define NOD_ATHENA 1 #include "DNAMP1.hpp" #include "STRG.hpp" #include "MLVL.hpp" #include "../DNACommon/TXTR.hpp" #include "CMDL.hpp" #include "ANCS.hpp" namespace Retro { namespace DNAMP1 { LogVisor::LogModule Log("Retro::DNAMP1"); PAKBridge::PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node) : m_project(project), m_node(node), m_pak(false) { NOD::AthenaPartReadStream rs(node.beginReadStream()); m_pak.read(rs); /* Append Level String */ for (const PAK::Entry& entry : m_pak.m_entries) { if (entry.type == FOURCC('MLVL')) { PAKEntryReadStream rs = entry.beginReadStream(m_node); MLVL mlvl; mlvl.read(rs); const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); if (nameEnt) { PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); STRG mlvlName; mlvlName.read(rs); if (m_levelString.size()) m_levelString += _S(", "); m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0); } } } } UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry) { UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND; bool foundOneLayer = false; UniqueID32 areaId; unsigned layerIdx; for (const auto& pair : m_areaDeps) { unsigned l=0; for (const auto& layer : pair.second.layers) { if (layer.resources.find(entry.id) != layer.resources.end()) { if (foundOneLayer) { if (areaId == pair.first) result = UniqueResult::UNIQUE_AREA; else return {UniqueResult::UNIQUE_LEVEL}; continue; } else result = UniqueResult::UNIQUE_LAYER; areaId = pair.first; layerIdx = l; foundOneLayer = true; } ++l; } if (pair.second.resources.find(entry.id) != pair.second.resources.end()) { if (foundOneLayer) { if (areaId == pair.first) result = UniqueResult::UNIQUE_AREA; else return {UniqueResult::UNIQUE_LEVEL}; continue; } else result = UniqueResult::UNIQUE_AREA; areaId = pair.first; foundOneLayer = true; } } UniqueResult retval = {result}; if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA) { const PAKBridge::Area& area = m_areaDeps[areaId]; retval.areaName = &area.name; if (result == UniqueResult::UNIQUE_LAYER) { const PAKBridge::Area::Layer& layer = area.layers[layerIdx]; retval.layerName = &layer.name; } } return retval; } static HECL::SystemString LayerName(const std::string& name) { #if HECL_UCS2 HECL::SystemString ret = HECL::UTF8ToWide(mlvl.layerNames[layerIdx++]); #else HECL::SystemString ret = name; #endif for (auto& ch : ret) if (ch == _S('/') || ch == _S('\\')) ch = _S('-'); return ret; } void PAKBridge::build() { /* First pass: build per-area/per-layer dependency map */ for (const PAK::Entry& entry : m_pak.m_entries) { if (entry.type == FOURCC('MLVL')) { PAKEntryReadStream rs = entry.beginReadStream(m_node); MLVL mlvl; mlvl.read(rs); m_areaDeps.reserve(mlvl.areaCount); unsigned layerIdx = 0; for (const MLVL::Area& area : mlvl.areas) { Area& areaDeps = m_areaDeps[area.areaMREAId]; const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId); if (areaNameEnt) { STRG areaName; PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node); areaName.read(rs); areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); } if (areaDeps.name.empty()) { #if HECL_UCS2 areaDeps.name = _S("MREA_") + HECL::UTF8ToWide(area.areaMREAId.toString()); #else areaDeps.name = "MREA_" + area.areaMREAId.toString(); #endif } areaDeps.layers.reserve(area.depLayerCount-1); unsigned r=0; for (unsigned l=1 ; l PAKBridge::LookupExtractor(const PAK::Entry& entry) { switch (entry.type) { case SBIG('STRG'): return {STRG::Extract, nullptr, {".yaml"}}; case SBIG('TXTR'): return {TXTR::Extract, nullptr, {".png"}}; case SBIG('CMDL'): return {nullptr, CMDL::Extract, {".blend"}, 2}; case SBIG('ANCS'): return {nullptr, ANCS::Extract, {".yaml", ".blend"}, 1}; case SBIG('MLVL'): return {MLVL::Extract, nullptr, {".yaml"}}; } return {}; } } }