diff options
Diffstat (limited to 'src/Game/DLC/aocManager.cpp')
| -rw-r--r-- | src/Game/DLC/aocManager.cpp | 546 |
1 files changed, 0 insertions, 546 deletions
diff --git a/src/Game/DLC/aocManager.cpp b/src/Game/DLC/aocManager.cpp deleted file mode 100644 index bb7ca50c..00000000 --- a/src/Game/DLC/aocManager.cpp +++ /dev/null @@ -1,546 +0,0 @@ -#include "Game/DLC/aocManager.h" -#include <container/seadBuffer.h> -#include <filedevice/seadFileDeviceMgr.h> -#include <prim/seadStringBuilder.h> -#include <resource/seadSharcArchiveRes.h> -#include "KingSystem/Resource/resLoadRequest.h" -#include "KingSystem/Resource/resResourceMgrTask.h" -#include "KingSystem/Utils/InitTimeInfo.h" -#include "KingSystem/Utils/SafeDelete.h" - -#ifdef NNSDK -#include <filedevice/nin/seadNinAocFileDeviceNin.h> -#include <nn/aoc.h> -#include <nn/fs.h> -#include <prim/seadStringUtil.h> -#endif - -namespace uking::aoc { - -namespace { - -struct DungeonInfo { - int number; - sead::SafeString flag; -}; - -ksys::util::InitConstants sInitConstants; -DungeonInfo sDungeonInfoData[] = { - {120, "Defeat_OneHitDungeon001"}, - {121, "BalladOfHeroGerudo_AppearDungeon03"}, - {122, "Defeat_OneHitDungeon002"}, - {123, "Defeat_OneHitDungeon003"}, - {124, "BalladOfHeroZora_AppearDungeon01"}, - {125, "BalladOfHeroZora_AppearDungeon02"}, - {126, "BalladOfHeroZora_AppearDungeon03"}, - {127, "BalladOfHeroRito_TargetHittingSuccess"}, - {128, "BalladOfHeroRito_AppearDungeon03"}, - {129, "BalladOfHeroRito_AppearDungeon02"}, - {130, "BalladOfHeroGoron_FirstKillGolemR"}, - {131, "BalladOfHeroGoron_AppearDungeon01"}, - {132, "BalladOfHeroGoron_AppearDungeon03"}, - {133, "BalladOfHeroGerudo_AppearDungeon02"}, - {134, "BalladOfHeroGerudo_AppearDungeon01"}, - {135, "Defeat_OneHitDungeon004"}, -}; -sead::Buffer<DungeonInfo> sDungeonInfo{sDungeonInfoData}; -constexpr int NumDungeons = 16; - -} // namespace - -SEAD_SINGLETON_DISPOSER_IMPL(Manager) - -Manager::Manager() : mVersionFile(), mGdtReinitSlot{this, &Manager::onGdtReinit} { - resetFlags(); -} - -Manager::~Manager() { - if (auto* gdm = ksys::gdt::Manager::instance()) - gdm->removeReinitCallback(mGdtReinitSlot); - - mAocMainFieldPackPrefix.deregister(); - mAocPackPrefix.deregister(); - mVersionFileDevPrefix.deregister(); - - if (mFileDevice) { - sead::FileDeviceMgr::instance()->unmount("aoc"); - ksys::util::safeDelete(mFileDevice); - } - -#ifdef NNSDK - if (mAocFsCache) { - nn::fs::Unmount("aoc"); - ksys::util::safeDelete(mAocFsCache); - } -#endif -} - -void Manager::resetFlags() { - mFlagAocVerAtLastPlay = ksys::gdt::InvalidHandle; - mFlagLatestAocVerPlayed = ksys::gdt::InvalidHandle; - mFlagHasAocVer1 = ksys::gdt::InvalidHandle; - mFlagHasAocVer2 = ksys::gdt::InvalidHandle; - mFlagHasAocVer3 = ksys::gdt::InvalidHandle; -} - -void Manager::init(sead::Heap* heap) { -#ifdef NNSDK - std::array<int, 2> dlc_info; - if (nn::aoc::ListAddOnContent(dlc_info.data(), 0, dlc_info.size()) == dlc_info.size() && - (dlc_info[0] == 1 || dlc_info[1] == 1)) { - size_t cache_size = 0; - nn::fs::QueryMountAddOnContentCacheSize(&cache_size, 1); - const size_t cache_size_ = cache_size; - mAocFsCache = static_cast<u8*>(heap->tryAlloc(cache_size_, sizeof(void*))); - - nn::fs::MountAddOnContent("aoc", 1, mAocFsCache, cache_size); - - mFileDevice = new (heap) sead::NinAocFileDevice("aoc"); - sead::FileDeviceMgr::instance()->mount(mFileDevice, "aoc"); - loadVersionFile(); - } -#endif -} - -void Manager::loadVersionFile() { - if (!mFileDevice) - return; - - mVersionFileDevPrefix.registerPrefix("Aoc/0010/", mFileDevice, false); - - ksys::res::LoadRequest req; - req.mRequester = "aocManager"; - req._26 = false; - req.mAocFileDevice = mFileDevice; - const sead::SafeString path = "System/AocVersion.txt"; - mVersionFile.file_handle.requestLoad(path, &req); -} - -void Manager::loadAocMainFieldPack(ksys::OverlayArena* arena) { - if (!hasAoc3()) - return; - - auto* device = mFileDevice; - if (!device) - return; - - ksys::res::LoadRequest req; - req.mRequester = "aocManager"; - req._8 = true; - req._26 = false; - req.mAocFileDevice = device; - req.mArena = arena; - mAocMainFieldPack.requestLoad("Pack/AocMainField.pack", &req); -} - -void Manager::registerAocMainFieldPack() { - mAocMainFieldPack.waitForReady(); - mAocMainFieldPack.parseResource(nullptr); - if (mAocMainFieldPack.isSuccess()) - mAocMainFieldPackPrefix.registerPrefix("Aoc/0010/", mAocMainFieldPack.getResource(), false); -} - -void Manager::unloadAocMainFieldPack() { - mAocMainFieldPackPrefix.deregister(); - mAocMainFieldPack.requestUnload(); -} - -sead::FileDevice* Manager::getFileDeviceForMapFile(const sead::SafeString& path) const { - if (!hasAoc2()) - return nullptr; - - auto* device = mFileDevice; - - if (aocPackHasFile(path)) - return nullptr; - - if (path.startsWith("Map/MainField/")) - return device; - - if (hasAoc3() && path.startsWith("Map/MainFieldDungeon/")) - return device; - - if (isAocFile(path, "Map/", "Map/AocField/", "Map/MainFieldDungeon/", "Map/CDungeon/")) - return device; - - return nullptr; -} - -bool Manager::getFileDeviceForMap(sead::FileDevice** p_file_device, ksys::res::Handle** p_handle, - const sead::SafeString& path) { - if (!hasAoc2()) - return false; - - auto* device = mFileDevice; - - if (path.startsWith("Map/MainField/")) { - if (mAocMainFieldPack.isSuccess()) - *p_handle = &mAocMainFieldPack; - else - *p_file_device = device; - return true; - } - - if (aocPackHasFile(path)) - return false; - - if (hasAoc3() && path.startsWith("Map/MainFieldDungeon/")) { - *p_file_device = device; - return true; - } - - if (isAocFile(path, "Map/", "Map/AocField/", "Map/MainFieldDungeon/", "Map/CDungeon/")) { - *p_file_device = device; - return true; - } - - return false; -} - -sead::FileDevice* Manager::getFileDeviceForStaticCompound(const sead::SafeString& path) const { - if (!hasAoc2()) - return nullptr; - - auto* device = mFileDevice; - - if (aocPackHasFile(path)) - return nullptr; - - if (isAocFile(path, "Physics/StaticCompound/", "Physics/StaticCompound/AocField/", - "Physics/StaticCompound/MainFieldDungeon/", "Physics/StaticCompound/CDungeon/")) { - return device; - } - - return nullptr; -} - -sead::FileDevice* Manager::getFileDeviceForTeraMesh(const sead::SafeString& path) const { - if (!hasAoc2()) - return nullptr; - - if (path.startsWith("Physics/TeraMeshRigidBody/AocField/")) - return mFileDevice; - - return nullptr; -} - -sead::FileDevice* Manager::getFileDeviceForNavMesh(const sead::SafeString& path) const { - if (!hasAoc2()) - return nullptr; - - auto* device = mFileDevice; - - if (aocPackHasFile(path)) - return nullptr; - - if (isAocFile(path, "NavMesh/", "NavMesh/AocField/", "NavMesh/MainFieldDungeon/", - "NavMesh/CDungeon/")) { - return device; - } - - return nullptr; -} - -sead::FileDevice* Manager::getFileDeviceForTerrain(const sead::SafeString& path) const { - if (!hasAoc2()) - return nullptr; - - if (path.startsWith("Terrain/A/AocField")) - return mFileDevice; - - return nullptr; -} - -sead::FileDevice* Manager::getFileDeviceForGame(const sead::SafeString& path) const { - if (!hasAoc2()) - return nullptr; - - if (path.startsWith("Game/AocField/")) - return mFileDevice; - - return nullptr; -} - -sead::FileDevice* Manager::getFileDeviceForUI(const sead::SafeString& path) const { - if (!hasAoc3()) - return nullptr; - - if (path.startsWith("UI/StaffRollDLC/")) - return mFileDevice; - - return nullptr; -} - -bool Manager::isAocFile(const sead::SafeString& path, const sead::SafeString& dir, - const sead::SafeString& dir_aoc_field, - const sead::SafeString& dir_main_field_dungeon, - const sead::SafeString& dir_cdungeon) const { - if (!path.startsWith(dir)) - return false; - - if (path.startsWith(dir_aoc_field)) - return true; - - if (path.startsWith(dir_main_field_dungeon)) { - const auto rel_path = path.getPart(dir_main_field_dungeon.calcLength()); - if (rel_path.startsWith("RemainsElectric")) - return false; - if (rel_path.startsWith("RemainsFire")) - return false; - if (rel_path.startsWith("RemainsWater")) - return false; - if (rel_path.startsWith("RemainsWind")) - return false; - return true; - } - - if (path.startsWith(dir_cdungeon)) { - const auto rel_path = path.getPart(dir_cdungeon.calcLength()); - return isAocDungeon(rel_path); - } - - return false; -} - -static bool isAocDungeonNumber(const sead::SafeString& number) { - int num; - sead::FixedSafeString<4> buffer; - buffer.copy(number, 3); - return sead::StringUtil::tryParseS32(&num, buffer, sead::StringUtil::CardinalNumber::Base10) && - num >= 120; -} - -bool Manager::isAocDungeon(const sead::SafeString& map_name) { - if (!map_name.startsWith("Dungeon")) - return true; - const auto number = map_name.getPart(sead::SafeString("Dungeon").calcLength()); - return isAocDungeonNumber(number); -} - -bool Manager::isAocMap(const sead::SafeString& map_type, const sead::SafeString& map_name) { - if (isAocField(map_type)) - return true; - - if (map_type == "MainFieldDungeon") { - if (map_name == "RemainsElectric") - return false; - if (map_name == "RemainsFire") - return false; - if (map_name == "RemainsWater") - return false; - if (map_name == "RemainsWind") - return false; - return true; - } - - if (map_type == "CDungeon") - return isAocDungeon(map_name); - - return false; -} - -bool Manager::isAocField(const sead::SafeString& map_type) { - return map_type == "AocField"; -} - -sead::FileDevice* Manager::getFileDeviceForDungeonPack(const sead::SafeString& path) const { - if (!hasAoc3()) - return nullptr; - - auto* device = mFileDevice; - - const sead::SafeString prefix = "Pack/"; - const auto prefix_len = prefix.calcLength(); - - if (!path.startsWith(prefix)) - return nullptr; - - const auto rel_path = path.getPart(prefix_len); - - if (rel_path.startsWith("Dungeon") && !isAocDungeon(rel_path)) - device = nullptr; - - return device; -} - -void Manager::registerAocPack(ksys::res::Handle* pack) { - mAocPack = pack; - if (pack) { - mAocPackPrefix.registerPrefix("Aoc/0010/", pack->getResource(), true); - } else { - mAocPackPrefix.deregister(); - } -} - -bool Manager::aocPackHasFile(const sead::SafeString& path) const { - if (!mAocPack) - return false; - - const auto* res = sead::DynamicCast<sead::SharcArchiveRes>(mAocPack->getResource()); - if (!res) - return false; - - sead::FixedStringBuilder<0x81> builder; - builder.copy(path.cstr()); - ksys::res::ResourceMgrTask::instance()->addSExtensionPrefix(builder); - return res->isExistFile(builder); -} - -bool Manager::changeMoviePath(sead::BufferedSafeString& path) const { - if (!hasAoc3()) - return false; - - const sead::SafeString prefix = "Movie/"; - const auto prefix_len = prefix.calcLength(); - if (!path.startsWith(prefix)) - return false; - - const auto rel_path = path.getPart(prefix_len); - if (!rel_path.startsWith("Demo6")) - return false; - - path.prepend("aoc://"); - return true; -} - -bool Manager::parseVersion() { - if (!mVersionFile.readVersion()) - return false; - - if (mVersionFile.string.isEmpty()) { - mVersion = 0; - return true; - } - - { - const int dot_index = mVersionFile.string.findIndex("."); - const int minor_index = dot_index + 1; - if (dot_index <= 0 || minor_index >= mVersionFile.string.calcLength()) { - mVersionFile.string.clear(); - mVersion = 0; - return true; - } - - u32 major, minor; - const auto parse = [&] { - sead::FixedSafeString<16> major_str; - major_str.copy(mVersionFile.string, dot_index); - - constexpr auto base = sead::StringUtil::CardinalNumber::Base10; - if (!sead::StringUtil::tryParseU32(&major, major_str, base)) - return false; - - const auto minor_str = mVersionFile.string.getPart(minor_index); - if (!sead::StringUtil::tryParseU32(&minor, minor_str, base)) - return false; - - return true; - }; - - if (!parse()) { - mVersionFile.string.clear(); - mVersion = 0; - return true; - } - - mVersion = (major << 8) + minor; - } - - checkVersion(); - return true; -} - -// NON_MATCHING: stack and duplicated branch -- volatile variables are painful -void Manager::checkVersion() { - if (mVersion == 0) - return; - - const auto fail = [this](VersionError error) { - mVersionFlags.setBit(error); - mVersion = 0; - }; - - if (mVersion < 0x300) { - fail(VersionError::TooOld); - } else if (mVersion >= 0x400) { - fail(VersionError::TooNew); - } - - mVersionFlags.isOnBit(VersionError(VersionError::TooOld)); - mVersionFlags.isOnBit(VersionError(VersionError::TooNew)); -} - -bool Manager::VersionFile::readVersion() { - if (!file_handle.requestedLoad()) - return true; - - if (file_handle.isSuccess()) { - auto* res = sead::DynamicCast<sead::DirectResource>(file_handle.getResource()); - string.copy(reinterpret_cast<const char*>(res->getRawData()), res->getRawSize()); - } else { - if (!file_handle.checkLoadStatus()) - return false; - string.clear(); - } - - file_handle.requestUnload(); - return true; -} - -void Manager::initGameData() { - reinitFlags(); - ksys::gdt::Manager::instance()->addReinitCallback(mGdtReinitSlot); -} - -static const sead::SafeString& getDungeonFlag(int number) { - for (auto it = sDungeonInfo.begin(); it != sDungeonInfo.end(); ++it) { - if (it->number == number) - return it->flag; - } - return sead::SafeString::cEmptyString; -} - -void Manager::reinitFlags() { - mFlagAocVerAtLastPlay = ksys::gdt::Manager::instance()->getS32Handle("AoCVerAtLastPlay"); - mFlagLatestAocVerPlayed = ksys::gdt::Manager::instance()->getS32Handle("LatestAoCVerPlayed"); - mFlagHasAocVer1 = - ksys::gdt::Manager::instance()->getBoolHandle(GameDataFlag::text(GameDataFlag::HasAoCVer1)); - mFlagHasAocVer2 = - ksys::gdt::Manager::instance()->getBoolHandle(GameDataFlag::text(GameDataFlag::HasAoCVer2)); - mFlagHasAocVer3 = - ksys::gdt::Manager::instance()->getBoolHandle(GameDataFlag::text(GameDataFlag::HasAoCVer3)); - - for (int i = 0; i < mDLCPositions.size(); ++i) { - ksys::gdt::FlagHandle handle = ksys::gdt::InvalidHandle; - - if (i < NumDungeons) { - if (mDLCPositions[i].flag_handle == ksys::gdt::InvalidHandle) - continue; - - handle = ksys::gdt::Manager::instance()->getBoolHandle(getDungeonFlag(i + 120)); - } - - mDLCPositions[i].flag_handle = handle; - } -} - -void Manager::setGameDataFlags() const { - ksys::gdt::Manager::instance()->setS32(mVersion, mFlagAocVerAtLastPlay); - - s32 latest_ver; - if (ksys::gdt::Manager::instance()->getS32(mFlagLatestAocVerPlayed, &latest_ver)) { - if (u32(latest_ver) < mVersion) - ksys::gdt::Manager::instance()->setS32(mVersion, mFlagLatestAocVerPlayed); - } - - const auto ver = mVersion; - ksys::gdt::Manager::instance()->setBool(ver >= 0x100, mFlagHasAocVer1); - ksys::gdt::Manager::instance()->setBool(ver >= 0x200, mFlagHasAocVer2); - ksys::gdt::Manager::instance()->setBool(ver >= 0x300, mFlagHasAocVer3); -} - -void Manager::onGdtReinit(ksys::gdt::Manager::ReinitEvent* event) { - reinitFlags(); -} - -} // namespace uking::aoc |
