diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 0e775987..233b40f9 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -90685,26 +90685,26 @@ 0x00000071011fc9f4,OverlayArenaSystem::Struct1::destroy,268, 0x00000071011fcb00,OverlayArenaSystem::Struct1::dtorDelete,64,_ZN4ksys12OverlayArenaD0Ev 0x00000071011fcb40,OverlayArena::makeHeap,384,_ZN4ksys12OverlayArena4initERKNS0_7InitArgE? -0x00000071011fccc0,nullsub_4690,4, -0x00000071011fccc4,sub_71011FCCC4,48, -0x00000071011fccf4,OverlayArenaSystem::Struct1::callResMgrClearCacheForSync,180, -0x00000071011fcda8,OverlayArenaSystem::Struct1::x,12, -0x00000071011fcdb4,sub_71011FCDB4,16, -0x00000071011fcdc4,sub_71011FCDC4,8, -0x00000071011fcdcc,OverlayArenaSystem::Struct1::c,12, -0x00000071011fcdd8,sub_71011FCDD8,12, -0x00000071011fcde4,OverlayArena::hasIssues,168, +0x00000071011fccc0,nullsub_4690,4,_ZN4ksys12OverlayArena7stubbedEv +0x00000071011fccc4,sub_71011FCCC4,48,_ZN4ksys12OverlayArena11updateFlag8Eb +0x00000071011fccf4,OverlayArenaSystem::Struct1::callResMgrClearCacheForSync,180,_ZN4ksys12OverlayArena10clearUnitsEv +0x00000071011fcda8,OverlayArenaSystem::Struct1::x,12,_ZNK4ksys12OverlayArena10isFlag1SetEv +0x00000071011fcdb4,sub_71011FCDB4,16,_ZNK4ksys12OverlayArena10hasNoUnitsEv +0x00000071011fcdc4,sub_71011FCDC4,8,_ZNK4ksys12OverlayArena11getNumUnitsEv +0x00000071011fcdcc,OverlayArenaSystem::Struct1::c,12,_ZNK4ksys12OverlayArena11isFlag10SetEv +0x00000071011fcdd8,sub_71011FCDD8,12,_ZNK4ksys12OverlayArena10isFlag8SetEv +0x00000071011fcde4,OverlayArena::hasIssues,168,_ZNK4ksys12OverlayArena10checkIsOomEv 0x00000071011fce8c,OverlayArenaSystem::Struct1::setBloodyMoonReason,432, 0x00000071011fd03c,sub_71011FD03C,596, -0x00000071011fd290,OverlayArenaSystem::Struct1::makeDualHeap,320, +0x00000071011fd290,OverlayArenaSystem::Struct1::makeDualHeap,320,_ZN4ksys12OverlayArena12makeDualHeapEjRKN4sead14SafeStringBaseIcEENS1_4Heap13HeapDirectionEPNS_3res12ResourceUnitEb! 0x00000071011fd3d0,OverlayArenaSystem::Struct1::b,232, 0x00000071011fd4b8,sub_71011FD4B8,212, 0x00000071011fd58c,sub_71011FD58C,192, 0x00000071011fd64c,sub_71011FD64C,380, 0x00000071011fd7c8,OverlayArenaSystem::Struct1::a,160, 0x00000071011fd868,OverlayArenaSystem::Struct1::defragMemoryStuff,920, -0x00000071011fdc00,sub_71011FDC00,16, -0x00000071011fdc10,sub_71011FDC10,16, +0x00000071011fdc00,sub_71011FDC00,16,_ZN4ksys12OverlayArena7addSizeEi +0x00000071011fdc10,sub_71011FDC10,16,_ZN4ksys12OverlayArena8addSize2Ei 0x00000071011fdc20,OverlayArenaSystem::Struct1::calculateHeapSizeStuff,512, 0x00000071011fde20,OverlayArenaSystem::Struct1::y,364, 0x00000071011fdf8c,sub_71011FDF8C,648, @@ -90767,7 +90767,7 @@ 0x000000710120130c,ResourceBase::callOnDestroy,12,_ZN4ksys3res8Resource9onDestroyEv 0x0000007101201318,ResourceBase::callParse,24,_ZN4ksys3res8Resource5parseEPNS0_7ContextEPN4sead4HeapE 0x0000007101201330,ResourceBase::callM5,32,_ZN4ksys3res8Resource8finalizeEv -0x0000007101201350,ResourceBase::callM6AndClearField30,48,_ZN4ksys3res8Resource13finishParsingEv +0x0000007101201350,ResourceBase::callM6AndClearField30,48,_ZN4ksys3res8Resource13finishParsingEPNS0_7ContextE 0x0000007101201380,ResourceBase::callM7,12,_ZN4ksys3res8Resource2m7Ev 0x000000710120138c,ResourceBase::doCreate,4,_ZN4ksys3res8Resource9doCreate_EPhjPN4sead4HeapE 0x0000007101201390,ResourceBase::onDestroy,4,_ZN4ksys3res8Resource10onDestroy_Ev @@ -90897,72 +90897,72 @@ 0x0000007101206d74,res::ResourceMgrTask::calc_,288, 0x0000007101206e94,res::System::calc_,196, 0x0000007101206f58,res::ResourceMgrTask::oo,380, -0x00000071012070d4,res::ResourceMgrTask::isCompactionStopped,24, +0x00000071012070d4,res::ResourceMgrTask::isCompactionStopped,24,_ZNK4ksys3res15ResourceMgrTask19isCompactionStoppedEv 0x00000071012070ec,res::ResourceMgrTask::submitCalcRequest,36, 0x0000007101207110,res::ResourceMgrTask::postCalc,20, -0x0000007101207124,res::ResourceMgrTask::clearAllCaches,288, +0x0000007101207124,res::ResourceMgrTask::clearAllCaches,288,_ZN4ksys3res15ResourceMgrTask14clearAllCachesEPNS_12OverlayArenaE 0x0000007101207244,res::ResourceMgrTask::BinderArray::getTexHandleMgrArena,32, 0x0000007101207264,EventPlusString::RequestEx::dtor,24,_ZN4ksys3res18ControlTaskRequestD2Ev 0x000000710120727c,res::ResourceMgrTask::defragAllMemoryMgr,800, -0x000000710120759c,res::ResourceMgrTask::__auto7,20, -0x00000071012075b0,res::ResourceMgrTask::getDefragProgress,104, +0x000000710120759c,res::ResourceMgrTask::__auto7,20,_ZNK4ksys3res15ResourceMgrTask12isDefragDoneEv +0x00000071012075b0,res::ResourceMgrTask::getDefragProgress,104,_ZNK4ksys3res15ResourceMgrTask17getDefragProgressEv 0x00000071012076a8,res::ResourceMgrTask::getCacheIdx,956, 0x0000007101207a64,stringPathManipulationStuff,1284, -0x0000007101207f68,sub_7101207F68,680, -0x0000007101208210,res::ResourceMgrTask::__auto5,256, -0x0000007101208310,res::ResourceMgrTask::callMethodsOnThreads,96, -0x0000007101208370,res::ResourceMgrTask::__auto10,8, -0x0000007101208378,res::ResourceMgrTask::getMainFileDevice,16, -0x0000007101208388,res::ResourceMgrTask::getArchiveFileDev1,16, -0x00000071012083a8,res::ResourceMgrTask::__auto0,88, -0x000000710120842c,res::ResourceMgrTask::setField174Flag2000Or5000,36, +0x0000007101207f68,sub_7101207F68,680,_ZNK4sead8ObjArrayINS_14SafeStringBaseIcEEE12binarySearchEPKS2_? +0x0000007101208210,res::ResourceMgrTask::__auto5,256,_ZN4ksys3res15ResourceMgrTask11cancelTasksEv +0x0000007101208310,res::ResourceMgrTask::callMethodsOnThreads,96,_ZN4ksys3res15ResourceMgrTask24waitForTaskQueuesToEmptyEv +0x0000007101208370,res::ResourceMgrTask::__auto10,8,_ZNK4ksys3res15ResourceMgrTask35getNumActiveTasksOnResLoadingThreadEv +0x0000007101208378,res::ResourceMgrTask::getMainFileDevice,16,_ZNK4ksys3res15ResourceMgrTask23getOffsetReadFileDeviceEv +0x0000007101208388,res::ResourceMgrTask::getArchiveFileDev1,16,_ZN4ksys3res15ResourceMgrTask18getArchiveFileDev1Ev +0x00000071012083a8,res::ResourceMgrTask::__auto0,88,_ZN4ksys3res15ResourceMgrTask18controlField9c0d88Eb? +0x000000710120842c,res::ResourceMgrTask::setField174Flag2000Or5000,36,_ZN4ksys3res15ResourceMgrTask17setFlag2000Or5000Ei 0x0000007101208450,res::ResourceMgrTask::setSomePropertiesOnArgForLoad,960, 0x0000007101208810,res::ResourceMgrTask::getFactoryForExtensionAndFallBackToResBase,1008, -0x0000007101208c00,res::ResourceMgrTask::x,12, +0x0000007101208c00,res::ResourceMgrTask::x,12,_ZNK4ksys3res15ResourceMgrTask10isFlag4SetEv 0x0000007101208c0c,res::ResourceMgrTask::submitLoadRequest,1288, 0x0000007101209114,res::ResourceMgrTask::copyExtensionAndRemoveS,292, 0x0000007101209238,res::ResourceMgrTask::submitLoadForSyncRequest,2240, 0x0000007101209b08,res::ResourceMgrTask::submitUnloadRequest,332, -0x0000007101209dd8,res::ResourceMgrTask::a,128, -0x0000007101209e58,res::ResourceMgrTask::b,128, +0x0000007101209dd8,res::ResourceMgrTask::a,128,_ZN4ksys3res15ResourceMgrTask12registerUnitEPNS0_12ResourceUnitE +0x0000007101209e58,res::ResourceMgrTask::b,128,_ZN4ksys3res15ResourceMgrTask14deregisterUnitEPNS0_12ResourceUnitE 0x0000007101209ed8,res::ResourceMgrTask::clearCache,464, 0x000000710120a0a8,res::ResourceMgrTask::clearCacheForSync,524, -0x000000710120a2b4,res::ResourceMgrTask::n,144, -0x000000710120a344,res::ResourceMgrTask::deleteUnit,400, +0x000000710120a2b4,res::ResourceMgrTask::n,144,_ZN4ksys3res15ResourceMgrTask10deleteUnitERPNS0_12ResourceUnitEb +0x000000710120a344,res::ResourceMgrTask::deleteUnit,400,_ZN4ksys3res15ResourceMgrTask17requestDeleteUnitEPPNS0_12ResourceUnitE 0x000000710120a4d4,nullsub_4699,4,_ZN4ksys3res17MemoryTaskRequestD2Ev 0x000000710120a4d8,res::ResourceMgrTask::load,1292, -0x000000710120a9e4,canUseSdCard,8, -0x000000710120a9ec,return_0_0,8, -0x000000710120a9f4,res::ResourceMgrTask::dropSFromExtensionForBfevflBcamanimAndBarslist,756, -0x000000710120ace8,res::ResourceMgrTask::unloadSeadResource,84, -0x000000710120ad3c,res::ResourceMgrTask::getResourceSize,328, -0x000000710120ae84,res::ResourceMgrTask::insertIntoFileDeviceToPrefixMap,116, -0x000000710120aef8,res::ResourceMgrTask::eraseFromFileDeviceToPrefixMap,104, -0x000000710120af60,res::ResourceMgrTask::__auto3,164, -0x000000710120b004,res::ResourceMgrTask::__auto9,64, -0x000000710120b044,res::ResourceMgrTask::makeDualHeap,212, +0x000000710120a9e4,canUseSdCard,8,_ZNK4ksys3res15ResourceMgrTask12canUseSdCardEv +0x000000710120a9ec,return_0_0,8,_ZNK4ksys3res15ResourceMgrTask11returnFalseEv +0x000000710120a9f4,res::ResourceMgrTask::dropSFromExtensionForBfevflBcamanimAndBarslist,756,_ZNK4ksys3res15ResourceMgrTask26dropSFromExtensionIfNeededERKN4sead14SafeStringBaseIcEERNS2_22BufferedSafeStringBaseIcEEiS6_ +0x000000710120ace8,res::ResourceMgrTask::unloadSeadResource,84,_ZN4ksys3res15ResourceMgrTask18unloadSeadResourceEPN4sead8ResourceE +0x000000710120ad3c,res::ResourceMgrTask::getResourceSize,328,_ZNK4ksys3res15ResourceMgrTask15getResourceSizeERKN4sead14SafeStringBaseIcEEPNS2_10FileDeviceE +0x000000710120ae84,res::ResourceMgrTask::insertIntoFileDeviceToPrefixMap,116,_ZN4ksys3res15ResourceMgrTask24registerFileDevicePrefixERNS0_16FileDevicePrefixE +0x000000710120aef8,res::ResourceMgrTask::eraseFromFileDeviceToPrefixMap,104,_ZN4ksys3res15ResourceMgrTask26deregisterFileDevicePrefixERNS0_16FileDevicePrefixE +0x000000710120af60,res::ResourceMgrTask::__auto3,164,_ZN4ksys3res15ResourceMgrTask27callStubbedFunctionOnArenasEv +0x000000710120b004,res::ResourceMgrTask::__auto9,64,_ZN4ksys3res15ResourceMgrTask25updateResourceArenasFlag8Ev +0x000000710120b044,res::ResourceMgrTask::makeDualHeap,212,_ZN4ksys3res15ResourceMgrTask15makeHeapForUnitERKNS1_11MakeHeapArgE! 0x000000710120b118,res::ResourceMgrTask::__auto4,96, -0x000000710120b178,res::ResourceMgrTask::clearCachesAndGetBinder,568, +0x000000710120b178,res::ResourceMgrTask::clearCachesAndGetBinder,568,_ZN4ksys3res15ResourceMgrTask21clearCachesAndGetUnitERKNS1_10GetUnitArgE 0x000000710120b3b0,nullsub_4700,4, -0x000000710120b3b4,res::ResourceMgrTask::setActorCreateInitialiserThreads,24, -0x000000710120b3cc,res::ResourceMgrTask::clearActorCreateInitialiserThreads,20, -0x000000710120b3e0,res::ResourceMgrTask::__auto11,76, -0x000000710120b42c,sub_710120B42C,60, -0x000000710120b468,res::ResourceMgrTask::getParallelSzsDecompressor,60, -0x000000710120b4a4,res::ResourceMgrTask::unlockSzsDecompressorCS,8, -0x000000710120b4ac,res::ResourceMgrTask::getYaz0UncompressedSize,248, +0x000000710120b3b4,res::ResourceMgrTask::setActorCreateInitialiserThreads,24,_ZN4ksys3res15ResourceMgrTask32setActorCreateInitializerThreadsERKNS1_35SetActorCreateInitializerThreadsArgE +0x000000710120b3cc,res::ResourceMgrTask::clearActorCreateInitialiserThreads,20,_ZN4ksys3res15ResourceMgrTask34clearActorCreateInitializerThreadsEv +0x000000710120b3e0,res::ResourceMgrTask::__auto11,76,_ZN4ksys3res15ResourceMgrTask12pauseThreadsEv +0x000000710120b42c,sub_710120B42C,60,_ZN4ksys3res15ResourceMgrTask13resumeThreadsEv +0x000000710120b468,res::ResourceMgrTask::getParallelSzsDecompressor,60,_ZN4ksys3res15ResourceMgrTask18getSzsDecompressorEv +0x000000710120b4a4,res::ResourceMgrTask::unlockSzsDecompressorCS,8,_ZN4ksys3res15ResourceMgrTask23unlockSzsDecompressorCSEv +0x000000710120b4ac,res::ResourceMgrTask::getYaz0UncompressedSize,248,_ZNK4ksys3res15ResourceMgrTask19getUncompressedSizeEPjRKN4sead14SafeStringBaseIcEEPNS3_10FileDeviceE 0x000000710120b5a4,nullsub_4701,4, -0x000000710120b5a8,res::ResourceMgrTask::setCompactionStopped,104, +0x000000710120b5a8,res::ResourceMgrTask::setCompactionStopped,104,_ZN4ksys3res15ResourceMgrTask20setCompactionStoppedEb? 0x000000710120b648,res::ResourceMgrTask::setStruct10OnTempResLoader,60, 0x000000710120b684,res::ResourceMgrTask::repairAllHandlesForSync,24, -0x000000710120b6ac,sub_710120B6AC,8, -0x000000710120b704,res::ResourceMgrTask::__auto8,80, -0x000000710120ba64,res::ResourceMgrTask::queueClearAllCaches,288, -0x000000710120bb84,res::ResourceMgrTask::alwaysReturnOne,8, +0x000000710120b6ac,sub_710120B6AC,8,_ZN4ksys3res15ResourceMgrTask11returnTrue1Ev +0x000000710120b704,res::ResourceMgrTask::__auto8,80,_ZN4ksys3res15ResourceMgrTask27clearCacheWithFileExtensionERKN4sead14SafeStringBaseIcEE +0x000000710120ba64,res::ResourceMgrTask::queueClearAllCaches,288,_ZN4ksys3res15ResourceMgrTask27clearAllCachesSynchronouslyEPNS_12OverlayArenaE +0x000000710120bb84,res::ResourceMgrTask::alwaysReturnOne,8,_ZN4ksys3res15ResourceMgrTask10returnTrueEv 0x000000710120bb8c,res::ResourceMgrTask::getHeapSizeForResLoad,1708, 0x000000710120c238,res::getRequiredBufferSizeForFile,424, 0x000000710120c3e0,res::ResourceMgrTask::y,336, -0x000000710120c530,res::ResourceMgrTask::removeOverlayArena,152, +0x000000710120c530,res::ResourceMgrTask::removeOverlayArena,152,_ZN4ksys3res15ResourceMgrTask18removeOverlayArenaEPNS_12OverlayArenaE 0x000000710120c6dc,res::ResourceMgrTask::checkDerivedRuntimeTypeInfo,288, 0x000000710120c7fc,res::ResourceMgrTask::getRuntimeTypeInfo,92, 0x000000710120c858,EventPlusString::RequestEx::rtti1,204,_ZNK4ksys3res18ControlTaskRequest27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE @@ -91060,7 +91060,7 @@ 0x0000007101213278,res::texHandleMgrSetSomeFlags,24, 0x0000007101213290,return_1,8,_ZN4ksys3res18stubbedLogFunctionEv 0x0000007101213298,return_0_,8,_ZN4ksys3res11returnFalseEv -0x00000071012132a0,return_0_2,8,_ZN4ksys3res12returnFalse2Ev +0x00000071012132a0,return_0_2,8,_ZN4ksys3res12returnFalse2ERKN4sead14SafeStringBaseIcEE 0x00000071012132a8,nullsub_4703,4, 0x00000071012132ac,return_0__,8, 0x00000071012132b4,nullsub_4704,4, @@ -91070,7 +91070,7 @@ 0x00000071012132c4,nullsub_4708,4, 0x00000071012132c8,nullsub_4709,4, 0x00000071012132cc,return_0,8, -0x00000071012132d4,return_8,8, +0x00000071012132d4,return_8,8,_ZN4ksys3res19getDefaultAlignmentEv 0x00000071012132dc,return1,16, 0x00000071012132ec,ArchiveRes::ctor,60,_ZN4ksys3res7ArchiveC1Ev 0x0000007101213328,ArchiveRes::dtor,4,_ZN4ksys3res7ArchiveD1Ev @@ -93239,7 +93239,7 @@ 0x00000071012bc9d4,ResourceInfoContainer::dtor,20,_ZN4ksys3res21ResourceInfoContainerD1Ev 0x00000071012bc9e8,ResourceInfoContainer::dtorDelete,52,_ZN4ksys3res21ResourceInfoContainerD0Ev 0x00000071012bca1c,ResourceInfoContainer::loadSizeTable,500,_ZN4ksys3res21ResourceInfoContainer21loadResourceSizeTableEv? -0x00000071012bcc10,ResourceInfoContainer::getResourceSize,384,_ZN4ksys3res21ResourceInfoContainer15getResourceSizeERKN4sead14SafeStringBaseIcEE? +0x00000071012bcc10,ResourceInfoContainer::getResourceSize,384,_ZNK4ksys3res21ResourceInfoContainer15getResourceSizeERKN4sead14SafeStringBaseIcEE? 0x00000071012bcd90,sub_71012BCD90,180,_ZNK4ksys3res21ResourceInfoContainer14ResStringEntry7compareERKN4sead14SafeStringBaseIcEE 0x00000071012bce44,sub_71012BCE44,176,_ZN4ksys3res12_GLOBAL__N_114stringLessThanERKN4sead14SafeStringBaseIcEES6_ 0x00000071012bcef4,res::ResourceMgrTask::BinderArray::ctor,136,_ZN4ksys3res16ResourceUnitPoolC1Ev diff --git a/lib/sead b/lib/sead index b19dff33..46972404 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit b19dff3386d866b32f05d92bd1eb7ca93f1a398a +Subproject commit 469724042e81233bba78118548ddd8da5c3d890d diff --git a/src/KingSystem/Resource/resCache.cpp b/src/KingSystem/Resource/resCache.cpp index 901668d2..4b4e5dd0 100644 --- a/src/KingSystem/Resource/resCache.cpp +++ b/src/KingSystem/Resource/resCache.cpp @@ -146,11 +146,10 @@ void Cache::eraseUnit(ResourceUnit* unit) { } void Cache::removeUnitAndClearCache_(ResourceUnit* unit) { - ResourceMgrTask::ClearCacheArg arg{unit}; unit->mStatusFlags.reset(ResourceUnit::StatusFlag::_20000); if (unit->isStatusFlag8000Set()) { - ResourceMgrTask::instance()->eraseUnit(unit); - ResourceMgrTask::instance()->clearCache(arg); + ResourceMgrTask::instance()->deregisterUnit(unit); + ResourceMgrTask::instance()->requestClearCache(unit); } } diff --git a/src/KingSystem/Resource/resControlTask.h b/src/KingSystem/Resource/resControlTask.h index 1d69ff1a..13a68ecc 100644 --- a/src/KingSystem/Resource/resControlTask.h +++ b/src/KingSystem/Resource/resControlTask.h @@ -42,8 +42,7 @@ KSYS_CHECK_SIZE_NX150(ControlTask, 0x1f8); class ControlTaskRequest : public util::TaskRequest { SEAD_RTTI_OVERRIDE(ControlTaskRequest, util::TaskRequest) public: - ControlTaskRequest() = default; - ControlTaskRequest(bool has_handle) : TaskRequest(has_handle) {} + explicit ControlTaskRequest(bool has_handle = false) : TaskRequest(has_handle) {} bool mHasResLoadReq = false; ResourceUnit* mPackResUnit = nullptr; diff --git a/src/KingSystem/Resource/resInfoContainer.cpp b/src/KingSystem/Resource/resInfoContainer.cpp index f1669f80..00bf40b9 100644 --- a/src/KingSystem/Resource/resInfoContainer.cpp +++ b/src/KingSystem/Resource/resInfoContainer.cpp @@ -80,7 +80,7 @@ bool ResourceInfoContainer::loadResourceSizeTable() { } // NON_MATCHING: missing mStringEntries(string_entry_idx).res_size > 0 check -u32 ResourceInfoContainer::getResourceSize(const sead::SafeString& name) { +u32 ResourceInfoContainer::getResourceSize(const sead::SafeString& name) const { const u32 name_hash = sead::HashCRC32::calcStringHash(name.cstr()); const s32 entry_idx = mEntries.binarySearch({name_hash, 0}, ResEntry::compareT); diff --git a/src/KingSystem/Resource/resInfoContainer.h b/src/KingSystem/Resource/resInfoContainer.h index 096e43fc..0370ed5d 100644 --- a/src/KingSystem/Resource/resInfoContainer.h +++ b/src/KingSystem/Resource/resInfoContainer.h @@ -14,7 +14,13 @@ public: virtual ~ResourceInfoContainer(); bool loadResourceSizeTable(); - u32 getResourceSize(const sead::SafeString& name); + + u32 getResourceSize(const sead::SafeString& name) const; + + u32 getResourceSize(const sead::SafeString& prefix, const sead::SafeString& name) const { + sead::FormatFixedSafeString<128> canonical_name{"%s%s", prefix.cstr(), name.cstr()}; + return getResourceSize(canonical_name); + } private: struct ResEntry { diff --git a/src/KingSystem/Resource/resResourceMgrTask.cpp b/src/KingSystem/Resource/resResourceMgrTask.cpp index 2a7df32d..b4850a03 100644 --- a/src/KingSystem/Resource/resResourceMgrTask.cpp +++ b/src/KingSystem/Resource/resResourceMgrTask.cpp @@ -1,20 +1,39 @@ #include "KingSystem/Resource/resResourceMgrTask.h" #include #include +#include +#include #include +#include "KingSystem/Resource/resCache.h" #include "KingSystem/Resource/resCompactedHeap.h" #include "KingSystem/Resource/resEntryFactory.h" #include "KingSystem/Resource/resMemoryTask.h" #include "KingSystem/Resource/resSystem.h" #include "KingSystem/Resource/resTextureHandleList.h" #include "KingSystem/Resource/resTextureHandleMgr.h" +#include "KingSystem/System/OverlayArenaSystem.h" #include "KingSystem/Utils/SafeDelete.h" #include "KingSystem/Utils/Thread/GameTaskThread.h" #include "KingSystem/Utils/Thread/TaskMgr.h" +#include "KingSystem/Utils/Thread/TaskQueueBase.h" +#include "KingSystem/Utils/Thread/TaskQueueLock.h" #include "KingSystem/Utils/Thread/TaskThread.h" namespace ksys::res { +namespace { +class ClearCachesTaskData : public util::TaskData { + SEAD_RTTI_OVERRIDE(ClearCachesTaskData, util::TaskData) +public: + virtual ~ClearCachesTaskData() = default; + + bool _8; + s32 _c; + sead::SafeString mStr; +}; +KSYS_CHECK_SIZE_NX150(ClearCachesTaskData, 0x20); +} // namespace + void ResourceMgrTask::setInstance(ResourceMgrTask* task) { if (!sInstance) { sInstance = task; @@ -99,6 +118,191 @@ util::TaskThread* ResourceMgrTask::makeResourceLoadingThread(sead::Heap* heap, sead::MessageQueue::BlockType::Blocking, 0x7fffffff, 0xa000, 32); } +void ResourceMgrTask::clearAllCaches(OverlayArena* arena) { + mResourceControlThread->getTaskQueue()->waitForLaneToEmpty(u8(LaneId::_5)); + mResourceControlThread->getTaskQueue()->waitForLaneToEmpty(u8(LaneId::_4)); + mResourceControlThread->getTaskQueue()->waitForLaneToEmpty(u8(LaneId::_3)); + + MemoryTaskRequest req; + req.mLaneId = u8(LaneId::_9); + req.mHasHandle = true; + req.mSynchronous = false; + req.mThread = mResourceMemoryThread; + req.mDelegate = &mClearAllCachesFn; + req.mName = "ClearAllCaches"; + req.mData_8 = false; + req.mData_c = -1; + req.mData_mStr = arena->getHeap()->getName(); + + util::TaskMgrRequest task_mgr_request; + task_mgr_request.request = &req; + mResourceMemoryTaskMgr->submitRequest(task_mgr_request); +} + +bool ResourceMgrTask::isDefragDone() const { + return mTask2->getStatus() == util::Task::Status::PostFinishCallback; +} + +f32 ResourceMgrTask::getDefragProgress() const { + auto lock = sead::makeScopedLock(mArenasCS); + if (_4c8 == -1) + return 0; + return f32(_4cc) / f32(_4c8); +} + +void ResourceMgrTask::cancelTasks() { + stubbedLogFunction(); + stubbedLogFunction(); + mMovableMemoryThread->cancelTasks(u8(LaneId::_1)); + mMovableMemoryThread->cancelTasks(u8(LaneId::_0)); + mMovableMemoryThread->cancelTasks(u8(LaneId::_3)); + mMovableMemoryThread->cancelTasks(u8(LaneId::_4)); + + stubbedLogFunction(); + stubbedLogFunction(); + mResourceControlThread->cancelTasks(u8(LaneId::_0)); + mResourceControlThread->cancelTasks(u8(LaneId::_1)); + mResourceControlThread->cancelTasks(u8(LaneId::_2)); + + stubbedLogFunction(); + stubbedLogFunction(); + mResourceMemoryThread->cancelTasks(u8(LaneId::_1)); + mResourceMemoryThread->cancelTasks(u8(LaneId::_2)); + mResourceMemoryThread->cancelTasks(u8(LaneId::_3)); + mResourceMemoryThread->cancelTasks(u8(LaneId::_4)); + mResourceMemoryThread->cancelTasks(u8(LaneId::_5)); + mResourceMemoryThread->cancelTasks(u8(LaneId::_6)); + + stubbedLogFunction(); + stubbedLogFunction(); + mResourceLoadingThread->cancelTasks(u8(LaneId::_0)); + mResourceLoadingThread->cancelTasks(u8(LaneId::_1)); + mResourceLoadingThread->cancelTasks(u8(LaneId::_2)); + + stubbedLogFunction(); + stubbedLogFunction(); +} + +void ResourceMgrTask::waitForTaskQueuesToEmpty() { + if (mResourceControlThread->isPaused() || mResourceMemoryThread->isPaused() || + mResourceLoadingThread->isPaused()) { + return; + } + + mResourceControlThread->waitForQueueToEmpty(); + mResourceMemoryThread->waitForQueueToEmpty(); + mResourceLoadingThread->waitForQueueToEmpty(); +} + +s32 ResourceMgrTask::getNumActiveTasksOnResLoadingThread() const { + return mResourceLoadingThread->getNumActiveTasks(); +} + +OffsetReadFileDevice* ResourceMgrTask::getOffsetReadFileDevice() const { + return mOffsetReadFileDevice; +} + +sead::ArchiveFileDevice* ResourceMgrTask::getArchiveFileDev1() { + return &mArchiveFileDev1; +} + +void ResourceMgrTask::controlField9c0d88(bool off) { + if (off) { + _9c0d88.decrement(); + static_cast(_9c0d88.load()); + } else { + _9c0d88.increment(); + } + + mFlags.change(Flag::_400, _9c0d88 <= 0); +} + +void ResourceMgrTask::setFlag2000Or5000(s32 type) { + if (type != 0) { + mFlags.set(Flag::_1000); + mFlags.set(Flag::_4000); + stubbedLogFunction(); + } else { + mFlags.set(Flag::_2000); + } +} + +bool ResourceMgrTask::isFlag4Set() const { + return mFlags.isOn(Flag::_4); +} + +void ResourceMgrTask::registerUnit(ResourceUnit* unit) { + auto lock = sead::makeScopedLock(mUnitsCS); + mUnits.pushBack(unit); + if (res::returnFalse()) + stubbedLogFunction(); +} + +void ResourceMgrTask::deregisterUnit(ResourceUnit* unit) { + auto lock = sead::makeScopedLock(mUnitsCS); + if (unit->isLinkedToResourceMgr()) { + mUnits.erase(unit); + if (res::returnFalse()) + stubbedLogFunction(); + } +} + +void ResourceMgrTask::deleteUnit(ResourceUnit*& unit, bool sync) { + if (!unit) + return; + + const bool immediate = mResourceControlThread->isPaused() || sync; + if (!immediate && res::returnFalse()) + stubbedLogFunction(); + + unit->unloadArchiveRes(); + + if (immediate) { + mUnitPool.freeForSync(unit); + unit = nullptr; + } else { + mUnitPool.free(unit); + unit = nullptr; + if (res::returnFalse()) + stubbedLogFunction(); + } +} + +void ResourceMgrTask::requestDeleteUnit(ResourceUnit** p_unit) { + if (!p_unit || !*p_unit) { + stubbedLogFunction(); + return; + } + + if (mResourceControlThread->isPaused()) { + if (res::returnFalse()) + stubbedLogFunction(); + + deleteUnit(*p_unit, false); + + } else { + ControlTaskRequest req; + req.mHasHandle = false; + req.mSynchronous = false; + req.mLaneId = u8(LaneId::_5); + req.mThread = mResourceControlThread; + req.mDelegate = &mUnitDeleteFn; + req.mName = "DeleteUnit"; + req.mUserData = *p_unit; + (*p_unit)->mTask1.submitRequest(req); + } + + *p_unit = nullptr; +} + +bool ResourceMgrTask::canUseSdCard() const { + return false; +} + +bool ResourceMgrTask::returnFalse() const { + return false; +} + bool ResourceMgrTask::calc_(void*) { if (mCacheControlFlags.testAndClear(CacheControlFlag::ClearAllCachesRequested)) { MemoryTaskRequest req; @@ -121,4 +325,286 @@ bool ResourceMgrTask::calc_(void*) { return true; } +bool ResourceMgrTask::dropSFromExtensionIfNeeded(const sead::SafeString& path, + sead::BufferedSafeString& new_path, s32 dot_idx, + const sead::SafeString& extension) const { + if (extension == "sbfevfl" || extension == "sbcamanim" || extension == "sbarslist") { + new_path.copyAtWithTerminate(0, path, dot_idx); + new_path.appendWithFormat(".%s", &extension.at(1)); + return true; + } + return mExtensions2.binarySearch(&extension) != -1; +} + +void ResourceMgrTask::unloadSeadResource(sead::Resource* resource) { + if (res::returnFalse()) + stubbedLogFunction(); + + sead::ResourceMgr::instance()->unload(resource); + stubbedLogFunction(); + + if (res::returnFalse()) + stubbedLogFunction(); +} + +u32 ResourceMgrTask::getResourceSize(const sead::SafeString& name, + sead::FileDevice* file_device) const { + if (!file_device) + return mResourceInfoContainer.getResourceSize(name); + + mFileDevicePrefixesLock.readLock(); + + for (const auto& entry : mFileDevicePrefixes) { + if (entry.getFileDevice() == file_device) { + const u32 size = mResourceInfoContainer.getResourceSize(entry.getPrefix(), name); + if (size == 0 && entry.getField28()) + break; + + mFileDevicePrefixesLock.readUnlock(); + return size; + } + } + + mFileDevicePrefixesLock.readUnlock(); + return mResourceInfoContainer.getResourceSize(name); +} + +void ResourceMgrTask::registerFileDevicePrefix(FileDevicePrefix& prefix) { + mFileDevicePrefixesLock.writeLock(); + mFileDevicePrefixes.pushBack(&prefix); + mFileDevicePrefixesLock.writeUnlock(); +} + +void ResourceMgrTask::deregisterFileDevicePrefix(FileDevicePrefix& prefix) { + mFileDevicePrefixesLock.writeLock(); + mFileDevicePrefixes.erase(&prefix); + mFileDevicePrefixesLock.writeUnlock(); +} + +void ResourceMgrTask::callStubbedFunctionOnArenas() { + auto lock = sead::makeScopedLock(mArenasCS); + for (OverlayArena& arena : mArenas) { + if (arena.isFlag8Set()) + arena.stubbed(); + } +} + +void ResourceMgrTask::updateResourceArenasFlag8() { + mArenaForResourceS.updateFlag8(false); + mArenaForResourceL.updateFlag8(false); +} + +// NON_MATCHING: branching +sead::Heap* ResourceMgrTask::makeHeapForUnit(const MakeHeapArg& arg) { + const auto heap_size = arg.heap_size; + const auto path = arg.path; + + OverlayArena* arena = arg.arena; + if (!arena) { + if (heap_size > 0x80000) + arena = &mArenaForResourceL; + else + arena = &mArenaForResourceS; + } + + sead::Heap* const heap = + arena->makeDualHeap(heap_size, path, sead::Heap::cHeapDirection_Forward, arg.unit, false); + + if (!heap) { + static_cast(arena->isFlag10Set()); + *arg.out_arena1 = arena; + return nullptr; + } + + if (arg.out_arena2 == nullptr) + return heap; + + *arg.out_arena1 = arena; + *arg.out_arena2 = arena; + return heap; +} + +ResourceUnit* ResourceMgrTask::clearCachesAndGetUnit(const GetUnitArg& arg) { + auto* unit = mUnitPool.tryAlloc(); + + if (!unit) { + util::TaskQueueLock lock; + + auto* queue = mResourceControlThread->getTaskQueue(); + auto it = queue->activeTasksRobustBegin(&lock); + const auto end = queue->activeTasksRobustEnd(); + + while (it != end && it->getLaneId() >= u8(ResourceMgrTask::LaneId::_5)) { + it->removeFromQueue2(); + it->processOnCurrentThreadDirectly(mResourceControlThread); + ++it; + } + + unit = mUnitPool.tryAlloc(); + } + + if (!unit) { + ClearCachesTaskData data; + data._8 = true; + data._c = 100; + util::TaskRequest req; + req.mLaneId = u8(LaneId::_8); + req.mHasHandle = true; + req.mSynchronous = true; + req.mThread = mResourceMemoryThread; + req.mDelegate = &mClearCachesFn; + req.mUserData = &data; + req.mName = "ClearCaches"; + mTask3->submitRequest(req); + + unit = mUnitPool.tryAlloc(); + } + + if (!unit) { + util::TaskQueueLock lock; + + auto* queue = mResourceControlThread->getTaskQueue(); + auto it = queue->activeTasksRobustBegin(&lock); + const auto end = queue->activeTasksRobustEnd(); + + while (it != end && it->getLaneId() >= u8(ResourceMgrTask::LaneId::_5)) { + it->removeFromQueue2(); + it->processOnCurrentThreadDirectly(mResourceControlThread); + ++it; + } + + unit = mUnitPool.tryAlloc(); + } + + if (!unit->init(*arg.unit_init_arg)) + return nullptr; + + return unit; +} + +void ResourceMgrTask::setActorCreateInitializerThreads( + const SetActorCreateInitializerThreadsArg& arg) { + mFlags.set(Flag::_8); + mActorCreateInitializerThreads = arg.threads; + stubbedLogFunction(); +} + +void ResourceMgrTask::clearActorCreateInitializerThreads() { + mFlags.reset(Flag::_8); + mActorCreateInitializerThreads = nullptr; + stubbedLogFunction(); +} + +void ResourceMgrTask::pauseThreads() { + stubbedLogFunction(); + mMovableMemoryThread->pauseAndWaitForAck(); + mMovableMemoryThread->cancelTasks(3); + mResourceControlThread->pauseAndWaitForAck(); + mResourceMemoryThread->pauseAndWaitForAck(); + mResourceLoadingThread->pauseAndWaitForAck(); + stubbedLogFunction(); +} + +void ResourceMgrTask::resumeThreads() { + stubbedLogFunction(); + mResourceLoadingThread->resume(); + mResourceMemoryThread->resume(); + mResourceControlThread->resume(); + mMovableMemoryThread->resume(); +} + +sead::SZSDecompressor* ResourceMgrTask::getSzsDecompressor() { + mSzsDecompressorCS.lock(); + sead::SZSDecompressor* ptr = nullptr; + OverlayArenaSystem::instance()->getSzsDecompressor(&ptr); + return ptr; +} + +void ResourceMgrTask::unlockSzsDecompressorCS() { + mSzsDecompressorCS.unlock(); +} + +bool ResourceMgrTask::getUncompressedSize(u32* size, const sead::SafeString& path, + sead::FileDevice* device) const { + auto lock = sead::makeScopedLock(mSzsDecompressorCS); + + if (!device) + device = mSeadMainFileDevice; + + sead::FileHandle handle; + if (!device->tryOpen(&handle, path, sead::FileDevice::cFileOpenFlag_ReadOnly)) { + stubbedLogFunction(); + return false; + } + + u32 read_size = 0; + handle.tryRead(&read_size, mOffsetReadBuf, 0x10); + *size = sead::Mathu::roundUpPow2(sead::SZSDecompressor::getDecompSize(mOffsetReadBuf), 32); + return true; +} + +// NON_MATCHING: reordering +void ResourceMgrTask::setCompactionStopped(bool stopped) { + u32 old_counter; + if (stopped) + old_counter = mCompactionCounter.decrement(); + else + old_counter = mCompactionCounter.increment(); + + stubbedLogFunction(); + if (mCompactionCounter == 0 || old_counter == 0) + stubbedLogFunction(); +} + +bool ResourceMgrTask::isCompactionStopped() const { + return mCompactionCounter == 0; +} + +bool ResourceMgrTask::returnTrue1() { + return true; +} + +void ResourceMgrTask::clearCacheWithFileExtension(const sead::SafeString& extension) { + stubbedLogFunction(); + const s32 idx = getCacheIdx(extension); + stubbedLogFunction(); + mCaches[idx]->eraseUnits(); +} + +void ResourceMgrTask::clearAllCachesSynchronously(OverlayArena* arena) { + mResourceControlThread->getTaskQueue()->waitForLaneToEmpty(u8(LaneId::_5)); + mResourceControlThread->getTaskQueue()->waitForLaneToEmpty(u8(LaneId::_4)); + mResourceControlThread->getTaskQueue()->waitForLaneToEmpty(u8(LaneId::_3)); + + MemoryTaskRequest req; + req.mLaneId = u8(LaneId::_9); + req.mHasHandle = true; + req.mSynchronous = true; + req.mThread = mResourceMemoryThread; + req.mDelegate = &mClearAllCachesFn; + req.mName = "ClearAllCaches"; + req.mData_8 = false; + req.mData_c = -1; + req.mData_mStr = arena->getHeap()->getName(); + + util::TaskMgrRequest task_mgr_request; + task_mgr_request.request = &req; + mResourceMemoryTaskMgr->submitRequest(task_mgr_request); +} + +bool ResourceMgrTask::returnTrue() { + return true; +} + +void ResourceMgrTask::removeOverlayArena(OverlayArena* arena) { + mTask.removeFromQueue(); + + auto lock = sead::makeScopedLock(mArenasCS); + mArenaIdx = 0; + if (mArenas.isNodeLinked(arena)) { + mArenas.erase(arena); + stubbedLogFunction(); + } +} + } // namespace ksys::res diff --git a/src/KingSystem/Resource/resResourceMgrTask.h b/src/KingSystem/Resource/resResourceMgrTask.h index a90c8208..e9b091c0 100644 --- a/src/KingSystem/Resource/resResourceMgrTask.h +++ b/src/KingSystem/Resource/resResourceMgrTask.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -25,7 +27,9 @@ namespace sead { class Heap; -} +class Resource; +class SZSDecompressor; +} // namespace sead namespace ksys { class OverlayArena; @@ -52,26 +56,39 @@ class FileDevicePrefix { public: FileDevicePrefix() = default; - sead::FileDevice* getFileDevice() { return mFileDevice; } + sead::FileDevice* getFileDevice() const { return mFileDevice; } void setFileDevice(sead::FileDevice* device) { mFileDevice = device; } - const sead::SafeString& getPrefix() { return mPrefix; } + const sead::SafeString& getPrefix() const { return mPrefix; } void setPrefix(const sead::SafeString& prefix) { mPrefix = prefix; } + bool getField28() const { return _28; } + void setField28(bool value) { _28 = value; } + static constexpr size_t getListNodeOffset() { return offsetof(FileDevicePrefix, mListNode); } private: sead::ListNode mListNode; sead::FileDevice* mFileDevice = nullptr; sead::SafeString mPrefix; + bool _28 = false; }; -KSYS_CHECK_SIZE_NX150(FileDevicePrefix, 0x28); +KSYS_CHECK_SIZE_NX150(FileDevicePrefix, 0x30); -// FIXME: very, very incomplete. +// FIXME: very incomplete. class ResourceMgrTask : public sead::CalculateTask, public sead::hostio::Node { SEAD_RTTI_OVERRIDE(ResourceMgrTask, sead::CalculateTask) public: enum class LaneId { + _0 = 0, + _1 = 1, + _2 = 2, + _3 = 3, + _4 = 4, + _5 = 5, + _6 = 6, + _7 = 7, + _8 = 8, _9 = 9, _10 = 10, }; @@ -91,26 +108,141 @@ public: void prepare() override; void insertOverlayArena(OverlayArena* arena); - OverlayArena* getSomeArena() const; util::TaskThread* makeResourceLoadingThread(sead::Heap* heap, bool use_game_task_thread); + void clearAllCaches(OverlayArena* arena); + OverlayArena* getTexHandleMgrArena() const; + + void requestDefragAllMemoryMgr(); + bool isDefragDone() const; + f32 getDefragProgress() const; + + s32 getCacheIdx(const sead::SafeString& path) const; + + void cancelTasks(); + void waitForTaskQueuesToEmpty(); + s32 getNumActiveTasksOnResLoadingThread() const; + + OffsetReadFileDevice* getOffsetReadFileDevice() const; + sead::ArchiveFileDevice* getArchiveFileDev1(); + + void controlField9c0d88(bool off); + void setFlag2000Or5000(s32 type); + + void copyLoadRequest(ILoadRequest* request, const sead::SafeString& path, + const ILoadRequest& source_request); + + EntryFactoryBase* getFactoryForPath(const sead::SafeString& path) const; + + bool isFlag4Set() const; + + s32 requestLoad(Handle* handle, const sead::SafeString& path, const ILoadRequest& request); + void addSExtensionPrefix(sead::StringBuilder& builder) const; + s32 requestLoadForSync(Handle* handle, const sead::SafeString& path, + const ILoadRequest& request); + s32 requestUnload(Handle* handle, const sead::SafeString& path, const ILoadRequest& request); + + void registerUnit(ResourceUnit* unit); + void deregisterUnit(ResourceUnit* unit); + + void requestClearCache(ResourceUnit*& unit, void* x = nullptr); + void requestClearCacheForSync(ResourceUnit*& unit, bool clear_immediately, + bool delete_immediately); + + void deleteUnit(ResourceUnit*& unit, bool sync); + void requestDeleteUnit(ResourceUnit** p_unit); + + struct DirectLoadArg { + LoadRequest req; + sead::Heap* heap; + }; + sead::DirectResource* load(const DirectLoadArg& arg); + + bool canUseSdCard() const; + bool returnFalse() const; + + bool dropSFromExtensionIfNeeded(const sead::SafeString& path, + sead::BufferedSafeString& new_path, s32 dot_idx, + const sead::SafeString& extension) const; + + void unloadSeadResource(sead::Resource* resource); + + u32 getResourceSize(const sead::SafeString& name, sead::FileDevice* file_device) const; + + void registerFileDevicePrefix(FileDevicePrefix& prefix); + void deregisterFileDevicePrefix(FileDevicePrefix& prefix); + + void callStubbedFunctionOnArenas(); + void updateResourceArenasFlag8(); + + struct MakeHeapArg { + bool _0 = false; + u32 heap_size = 0; + ResourceUnit* unit = nullptr; + sead::SafeString path; + OverlayArena* arena = nullptr; + OverlayArena** out_arena1 = nullptr; + OverlayArena** out_arena2 = nullptr; + }; + KSYS_CHECK_SIZE_NX150(MakeHeapArg, 0x38); + sead::Heap* makeHeapForUnit(const MakeHeapArg& arg); + struct GetUnitArg { const ResourceUnit::InitArg* unit_init_arg; OverlayArena* arena; }; ResourceUnit* clearCachesAndGetUnit(const GetUnitArg& arg); - void eraseUnit(ResourceUnit* unit); - - struct ClearCacheArg { - ResourceUnit* unit; + struct SetActorCreateInitializerThreadsArg { + sead::PtrArray* threads; }; - void clearCache(ClearCacheArg& arg, void* x = nullptr); + void setActorCreateInitializerThreads(const SetActorCreateInitializerThreadsArg& arg); + void clearActorCreateInitializerThreads(); - bool dropSFromExtensionIfNeeded(const sead::SafeString& path, - sead::BufferedSafeString& new_path, s32 dot_idx, - const sead::SafeString& extension); + void pauseThreads(); + void resumeThreads(); + + sead::SZSDecompressor* getSzsDecompressor(); + void unlockSzsDecompressorCS(); + bool getUncompressedSize(u32* size, const sead::SafeString& path, + sead::FileDevice* device) const; + + void setCompactionStopped(bool stopped); + bool isCompactionStopped() const; + + bool returnTrue1(); + + void clearCacheWithFileExtension(const sead::SafeString& extension); + void clearAllCachesSynchronously(OverlayArena* arena); + + bool returnTrue(); + + struct ResourceSizeInfo { + bool is_archive_file_dev2; + u32 buffer_size; + u32 alloc_size; + sead::FileDevice* file_device; + }; + KSYS_CHECK_SIZE_NX150(ResourceSizeInfo, 0x18); + + struct GetResourceSizeInfoArg { + bool flag1; + bool flag4_try_decomp; + bool flag2; + u32 alloc_size; + sead::ArchiveRes* archive_res; + sead::FileDevice* file_device; + EntryFactoryBase* factory; + u32 load_data_alignment; + sead::SafeString str; // TODO: rename + sead::SafeString path; + }; + KSYS_CHECK_SIZE_NX150(GetResourceSizeInfoArg, 0x48); + + void getResourceSizeInfo(ResourceSizeInfo* info, const GetResourceSizeInfoArg& arg); + + void removeOverlayArena(OverlayArena* arena); util::TaskThread* getResourceLoadingThread() const { return mResourceLoadingThread; } util::TaskThread* getResourceControlThread() const { return mResourceControlThread; } @@ -122,7 +254,14 @@ public: private: enum class Flag { - + _1 = 1, + _2 = 2, + _4 = 4, + _8 = 8, + _400 = 0x400, + _1000 = 0x1000, + _2000 = 0x2000, + _4000 = 0x4000, }; enum class CacheControlFlag : u8 { @@ -168,10 +307,10 @@ private: EntryFactoryBase* mEntryFactoryBase = nullptr; EntryFactoryBase* mDefaultEntryFactory = nullptr; - sead::Buffer mCaches; + sead::Buffer mCaches; sead::FixedObjArray mThreadIds; u8* mOffsetReadBuf = nullptr; - sead::CriticalSection mSzsDecompressorCS; + mutable sead::CriticalSection mSzsDecompressorCS; sead::CriticalSection mFactoryCS; ResourceUnitDelegatePair mUnitInitLoadFn; @@ -197,10 +336,10 @@ private: ResourceUnitDelegate mUnitDeleteFn; s32 _4c8 = -1; - u32 _4cc = 0; + s32 _4cc = 0; ResourceUnitPool mUnitPool; - sead::CriticalSection mCritSection; + sead::CriticalSection mUnitsCS; sead::OffsetList mUnits; sead::OffsetList mSomeList; // TODO: fix the type and rename @@ -217,7 +356,7 @@ private: sead::ObjArray mExtensions2; // TODO: rename sead::OffsetList mArenas; - sead::CriticalSection mArenasCS; + mutable sead::CriticalSection mArenasCS; OverlayArena mArenaForResourceS; OverlayArena mArenaForResourceL; @@ -225,7 +364,7 @@ private: ResourceInfoContainer mResourceInfoContainer; sead::OffsetList mFileDevicePrefixes; - sead::ReadWriteLock mFileDevicePrefixesLock; + mutable sead::ReadWriteLock mFileDevicePrefixesLock; TextureHandleMgr* mTexHandleMgr = nullptr; TextureHandleList* mTexHandleList = nullptr; @@ -237,16 +376,16 @@ private: u8* mCompactedHeapMip0Buffer = nullptr; CompactedHeap* mCompactedHeapMip0 = nullptr; u8* mCompactedHeapMainBuffer2 = nullptr; - sead::Atomic mCompactionStopped = 0; + sead::Atomic mCompactionCounter = 0; sead::Atomic _9c0d3c = 0; sead::Atomic _9c0d40 = 0; sead::AnyDelegate2 mCompactionThreadFn; sead::DelegateThread* mCompactionThread = nullptr; Counter mCounter; - u32 _9c0d88 = 1; + sead::Atomic _9c0d88 = 1; u32 _9c0d8c = 0; - u32 _9c0d90 = 0; + u32 mArenaIdx = 0; u32 _9c0d94; u8 _9c0d98 = 1; size_t _9c0da0 = 500; diff --git a/src/KingSystem/Resource/resSystem.cpp b/src/KingSystem/Resource/resSystem.cpp index be87826c..71713a1c 100644 --- a/src/KingSystem/Resource/resSystem.cpp +++ b/src/KingSystem/Resource/resSystem.cpp @@ -10,8 +10,12 @@ bool returnFalse() { return false; } -bool returnFalse2() { +bool returnFalse2(const sead::SafeString&) { return false; } +s32 getDefaultAlignment() { + return 8; +} + } // namespace ksys::res diff --git a/src/KingSystem/Resource/resSystem.h b/src/KingSystem/Resource/resSystem.h index 4ce9a16d..9396d3b6 100644 --- a/src/KingSystem/Resource/resSystem.h +++ b/src/KingSystem/Resource/resSystem.h @@ -16,4 +16,6 @@ bool returnFalse(); // TODO: figure out what this is used for. Stubbed log function? bool returnFalse2(const sead::SafeString&); +s32 getDefaultAlignment(); + } // namespace ksys::res diff --git a/src/KingSystem/Resource/resUnit.h b/src/KingSystem/Resource/resUnit.h index b819f24c..84f133f3 100644 --- a/src/KingSystem/Resource/resUnit.h +++ b/src/KingSystem/Resource/resUnit.h @@ -145,8 +145,8 @@ public: /// Destroys the underlying resource and reallocates it for defragmentation purposes. void reallocate(); - u32 determineFileBufferSize(); - u32 determineFileBufferSize(const sead::SafeString& path, bool flag4, bool flag1, bool flag2); + u32 determineHeapSize(); + u32 determineHeapSize(const sead::SafeString& path, bool flag4, bool flag1, bool flag2); void detachFromHandle_(Handle* handle); @@ -165,6 +165,7 @@ public: private: friend class Cache; friend class Handle; + friend class ResourceMgrTask; enum class CacheFlag : u8 { IsLinkedToCache = 0x1, diff --git a/src/KingSystem/System/OverlayArena.cpp b/src/KingSystem/System/OverlayArena.cpp index 718480ea..6e2a09b5 100644 --- a/src/KingSystem/System/OverlayArena.cpp +++ b/src/KingSystem/System/OverlayArena.cpp @@ -3,12 +3,13 @@ #include "KingSystem/Resource/resResourceMgrTask.h" #include "KingSystem/Resource/resSystem.h" #include "KingSystem/Resource/resUnit.h" +#include "KingSystem/Utils/HeapUtil.h" namespace ksys { OverlayArena::OverlayArena() { mUnits.initOffset(res::ResourceUnit::getArenaUnitListNodeOffset()); - mOffsetList2.initOffset(res::ResourceUnit::getArenaUnitListNode2Offset()); + mUnits2.initOffset(res::ResourceUnit::getArenaUnitListNode2Offset()); } OverlayArena::~OverlayArena() { @@ -59,4 +60,110 @@ bool OverlayArena::init(const OverlayArena::InitArg& arg) { return true; } +void OverlayArena::stubbed() {} + +void OverlayArena::updateFlag8(bool on) { + if (on != mFlags.isOn(Flag::_8) && mHeap) + mFlags.change(Flag::_8, on); +} + +void OverlayArena::clearUnits() { + if (!mHeap) + return; + + res::stubbedLogFunction(); + auto lock = sead::makeScopedLock(mCS); + for (auto it = mUnits.robustBegin(), end = mUnits.robustEnd(); it != end; ++it) { + res::ResourceUnit* unit = std::addressof(*it); + res::stubbedLogFunction(); + res::ResourceMgrTask::instance()->deregisterUnit(unit); + res::ResourceMgrTask::instance()->requestClearCacheForSync(unit, true, false); + } + res::stubbedLogFunction(); +} + +bool OverlayArena::isFlag1Set() const { + return mFlags.isOn(Flag::_1); +} + +bool OverlayArena::hasNoUnits() const { + return mUnits.isEmpty(); +} + +s32 OverlayArena::getNumUnits() const { + return mUnits.size(); +} + +bool OverlayArena::isFlag10Set() const { + return mFlags.isOn(Flag::_10); +} + +bool OverlayArena::isFlag8Set() const { + return mFlags.isOn(Flag::_8); +} + +bool OverlayArena::checkIsOom() const { + if (!mHeap) + return false; + + const f32 used_size = mUsage1 + mUsage2; + const size_t heap_size = mHeap->getSize(); + const f32 free_percentage = + 100.0f * + std::max(1.0 - used_size / (heap_size - sead::ExpHeap::getManagementAreaSize(8)), 0); + + if (free_percentage < mMinFreePercentage) { + if (res::returnFalse()) + res::stubbedLogFunction(); + + setBloodyMoonReasonForOom_(); + return true; + } + + return false; +} + +// FIXME: figure out what sead function this is +bool seadCheckPointer(void* ptr); + +// NON_MATCHING: branching +util::DualHeap* OverlayArena::makeDualHeap(u32 size, const sead::SafeString& name, + sead::Heap::HeapDirection direction, + res::ResourceUnit* unit, bool) { + if (!mHeap) + return nullptr; + + const auto alignment = res::getDefaultAlignment(); + const auto lock = sead::makeScopedLock(mCS); + + auto* heap = util::DualHeap::tryCreate(size, name, mHeap, mHeap2, alignment, direction, false); + if (!heap) { + if (res::returnFalse()) + res::stubbedLogFunction(); + + if (!x_1(size)) + return nullptr; + + heap = util::DualHeap::tryCreate(size, name, mHeap, mHeap2, alignment, direction, false); + if (!heap) + return nullptr; + } + + if (unit && !seadCheckPointer(unit)) { + mUnits.pushBack(unit); + mFlags.set(Flag::_2); + } + + mFlags.set(Flag::_4); + return heap; +} + +void OverlayArena::addSize(s32 size) { + mSize += size; +} + +void OverlayArena::addSize2(s32 size) { + mUsage1 += size; +} + } // namespace ksys diff --git a/src/KingSystem/System/OverlayArena.h b/src/KingSystem/System/OverlayArena.h index 02d4073c..1f2f3607 100644 --- a/src/KingSystem/System/OverlayArena.h +++ b/src/KingSystem/System/OverlayArena.h @@ -3,22 +3,22 @@ #include #include #include +#include +#include #include #include #include #include "KingSystem/System/StringBoard.h" #include "KingSystem/Utils/Types.h" -namespace sead { -class ExpHeap; -class Heap; -} // namespace sead - namespace ksys { namespace res { class ResourceUnit; } +namespace util { +class DualHeap; +} class OverlayArena { public: @@ -43,11 +43,33 @@ public: virtual ~OverlayArena(); bool init(const InitArg& arg); + void stubbed(); + void updateFlag8(bool on); + + void clearUnits(); + bool isFlag1Set() const; + bool hasNoUnits() const; + s32 getNumUnits() const; + void destroy(); + bool isFlag10Set() const; + bool isFlag8Set() const; + + /// Checks whether this arena is running out of memory. + /// This will also update the panic blood moon reason for the ProductReporter if needed. + /// @return whether the arena is running OOM. + bool checkIsOom() const; + + util::DualHeap* makeDualHeap(u32 size, const sead::SafeString& name, + sead::Heap::HeapDirection direction, res::ResourceUnit* unit, + bool x); + void addSize(s32 size); void addSize2(s32 size); + sead::Heap* getHeap() const { return mHeap; } + sead::Heap* getHeap2() const { return mHeap2; } static constexpr size_t getListNodeOffset() { return offsetof(OverlayArena, mListNode); } private: @@ -62,6 +84,10 @@ private: _20 = 0x20, }; + void setBloodyMoonReasonForOom_() const; + + bool x_1(s32 size); + sead::ListNode mListNode; sead::TypedBitFlag mFlags = [] { decltype(mFlags) flags; @@ -73,12 +99,12 @@ private: f32 mMinFreePercentage = 0.0; sead::Heap* mHeap2 = nullptr; sead::OffsetList mUnits; - sead::OffsetList mOffsetList2; // FIXME: type + sead::OffsetList mUnits2; // TODO: rename sead::CriticalSection mCS; - void* mUsage2 = nullptr; + size_t mUsage2 = 0; void* _b0 = nullptr; - u32 _b8 = 0; - u32 mUsage1 = 0; + s32 mSize = 0; + s32 mUsage1 = 0; u32 mHeapFreeSize = 0; u32 _c4 = 0; u32 _c8 = 0; diff --git a/src/KingSystem/System/OverlayArenaSystem.cpp b/src/KingSystem/System/OverlayArenaSystem.cpp index 72620464..1731b491 100644 --- a/src/KingSystem/System/OverlayArenaSystem.cpp +++ b/src/KingSystem/System/OverlayArenaSystem.cpp @@ -319,9 +319,9 @@ void OverlayArenaSystem::createStubbed() {} void OverlayArenaSystem::createMovieHeap() { res::stubbedLogFunction(); - mMovieHeap = sead::ExpHeap::tryCreate(0x8c00000, "MovieHeap", - res::ResourceMgrTask::instance()->getSomeArena()->mHeap, - sizeof(void*), sead::Heap::cHeapDirection_Forward, false); + mMovieHeap = sead::ExpHeap::tryCreate( + 0x8c00000, "MovieHeap", res::ResourceMgrTask::instance()->getTexHandleMgrArena()->mHeap, + sizeof(void*), sead::Heap::cHeapDirection_Forward, false); res::stubbedLogFunction(); }