diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 233b40f9..829d4387 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -90925,8 +90925,8 @@ 0x0000007101209b08,res::ResourceMgrTask::submitUnloadRequest,332, 0x0000007101209dd8,res::ResourceMgrTask::a,128,_ZN4ksys3res15ResourceMgrTask12registerUnitEPNS0_12ResourceUnitE 0x0000007101209e58,res::ResourceMgrTask::b,128,_ZN4ksys3res15ResourceMgrTask14deregisterUnitEPNS0_12ResourceUnitE -0x0000007101209ed8,res::ResourceMgrTask::clearCache,464, -0x000000710120a0a8,res::ResourceMgrTask::clearCacheForSync,524, +0x0000007101209ed8,res::ResourceMgrTask::clearCache,464,_ZN4ksys3res15ResourceMgrTask17requestClearCacheEPPNS0_12ResourceUnitEPNS_4util4TaskE +0x000000710120a0a8,res::ResourceMgrTask::clearCacheForSync,524,_ZN4ksys3res15ResourceMgrTask24requestClearCacheForSyncEPPNS0_12ResourceUnitEbb 0x000000710120a2b4,res::ResourceMgrTask::n,144,_ZN4ksys3res15ResourceMgrTask10deleteUnitERPNS0_12ResourceUnitEb 0x000000710120a344,res::ResourceMgrTask::deleteUnit,400,_ZN4ksys3res15ResourceMgrTask17requestDeleteUnitEPPNS0_12ResourceUnitE 0x000000710120a4d4,nullsub_4699,4,_ZN4ksys3res17MemoryTaskRequestD2Ev diff --git a/src/KingSystem/Resource/resCache.cpp b/src/KingSystem/Resource/resCache.cpp index 4b4e5dd0..d59ab29e 100644 --- a/src/KingSystem/Resource/resCache.cpp +++ b/src/KingSystem/Resource/resCache.cpp @@ -149,7 +149,7 @@ void Cache::removeUnitAndClearCache_(ResourceUnit* unit) { unit->mStatusFlags.reset(ResourceUnit::StatusFlag::_20000); if (unit->isStatusFlag8000Set()) { ResourceMgrTask::instance()->deregisterUnit(unit); - ResourceMgrTask::instance()->requestClearCache(unit); + ResourceMgrTask::instance()->requestClearCache(&unit); } } diff --git a/src/KingSystem/Resource/resResourceMgrTask.cpp b/src/KingSystem/Resource/resResourceMgrTask.cpp index b4850a03..d0a96b21 100644 --- a/src/KingSystem/Resource/resResourceMgrTask.cpp +++ b/src/KingSystem/Resource/resResourceMgrTask.cpp @@ -247,6 +247,80 @@ void ResourceMgrTask::deregisterUnit(ResourceUnit* unit) { } } +void ResourceMgrTask::requestClearCache(ResourceUnit** p_unit, util::Task* task) { + if (!p_unit || !*p_unit || !(*p_unit)->isStatusFlag8000Set()) { + stubbedLogFunction(); + return; + } + + if ((*p_unit)->getRefCount() > 0 || (*p_unit)->isStatus1() || (*p_unit)->isStatusFlag10000Set()) + return; + + (*p_unit)->setStatusFlag10000(); + + { + ControlTaskRequest req; + req.mHasHandle = true; + req.mSynchronous = false; + req.mLaneId = u8(LaneId::_4); + req.mThread = mResourceControlThread; + req.mDelegate = &mUnitClearCacheForSyncFn.fn; + req.mPostRunCallback = &mUnitClearCacheForSyncFn.cb; + req.mUserData = *p_unit; + req.mName = "ClearCache"; + if (task) + task->submitRequest(req); + else + (*p_unit)->mTask3.submitRequest(req); + } + *p_unit = nullptr; +} + +void ResourceMgrTask::requestClearCacheForSync(ResourceUnit** p_unit, bool clear_immediately, + bool delete_immediately) { + if (!p_unit || !*p_unit || !(*p_unit)->isStatusFlag8000Set()) { + goto fail; + } + + if ((*p_unit)->isStatus1() || !(*p_unit)->mCache || (*p_unit)->getRefCount() > 0) + return; + + if ((*p_unit)->isStatusFlag10000Set()) { + fail: + stubbedLogFunction(); + return; + } + + (*p_unit)->setStatusFlag10000(); + + if (clear_immediately) { + (*p_unit)->removeTask3FromQueue(); + (*p_unit)->clearCacheForSync(true); + (*p_unit)->clearCache(nullptr); + static_cast((*p_unit)->getStatus()); + ResourceUnit* ptr = *p_unit; + if (delete_immediately) + deleteUnit(ptr, true); + else + requestDeleteUnit(&ptr); + + } else { + ControlTaskRequest req; + req.mHasHandle = true; + req.mSynchronous = true; + req.mLaneId = u8(LaneId::_4); + req.mThread = mResourceControlThread; + req.mDelegate = &mUnitClearCacheForSyncFn.fn; + req.mUserData = *p_unit; + req.mName = "ClearCache(ForSync)"; + (*p_unit)->mTask3.submitRequest(req); + } + *p_unit = nullptr; +} + +#ifdef MATCHING_HACK_NX_CLANG +[[gnu::noinline]] +#endif void ResourceMgrTask::deleteUnit(ResourceUnit*& unit, bool sync) { if (!unit) return; diff --git a/src/KingSystem/Resource/resResourceMgrTask.h b/src/KingSystem/Resource/resResourceMgrTask.h index e9b091c0..99c06edb 100644 --- a/src/KingSystem/Resource/resResourceMgrTask.h +++ b/src/KingSystem/Resource/resResourceMgrTask.h @@ -146,8 +146,8 @@ public: void registerUnit(ResourceUnit* unit); void deregisterUnit(ResourceUnit* unit); - void requestClearCache(ResourceUnit*& unit, void* x = nullptr); - void requestClearCacheForSync(ResourceUnit*& unit, bool clear_immediately, + void requestClearCache(ResourceUnit** p_unit, util::Task* task = nullptr); + void requestClearCacheForSync(ResourceUnit** p_unit, bool clear_immediately, bool delete_immediately); void deleteUnit(ResourceUnit*& unit, bool sync); diff --git a/src/KingSystem/Resource/resUnit.h b/src/KingSystem/Resource/resUnit.h index 84f133f3..20e6f85e 100644 --- a/src/KingSystem/Resource/resUnit.h +++ b/src/KingSystem/Resource/resUnit.h @@ -212,10 +212,10 @@ private: void requestPrepareLoad(util::TaskPostRunResult* result, const util::TaskPostRunContext& ctx); void unloadForSync(); - void clearCacheForSync(); + void clearCacheForSync(bool x); void unload(); - void clearCache(); + void clearCache(void* x); void requestClearCache(util::TaskPostRunResult* result, const util::TaskPostRunContext& ctx); sead::TypedBitFlag mCacheFlags; diff --git a/src/KingSystem/System/OverlayArena.cpp b/src/KingSystem/System/OverlayArena.cpp index 6e2a09b5..62ae8a8c 100644 --- a/src/KingSystem/System/OverlayArena.cpp +++ b/src/KingSystem/System/OverlayArena.cpp @@ -77,7 +77,7 @@ void OverlayArena::clearUnits() { res::ResourceUnit* unit = std::addressof(*it); res::stubbedLogFunction(); res::ResourceMgrTask::instance()->deregisterUnit(unit); - res::ResourceMgrTask::instance()->requestClearCacheForSync(unit, true, false); + res::ResourceMgrTask::instance()->requestClearCacheForSync(&unit, true, false); } res::stubbedLogFunction(); }