diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 1350427a..2d73b966 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -81674,7 +81674,7 @@ 0x0000007100f3a8d8,ksys::PreInitializeApp,2276, 0x0000007100f3b1bc,checkPreInitializeResourcesStillLoading,132, 0x0000007100f3b240,ksys::InitializeApp,7612, -0x0000007100f3cffc,BaseProcMgr::createInstanceAndInit,388, +0x0000007100f3cffc,BaseProcMgr::createInstanceAndInit,388,_ZN4ksys15initBaseProcMgrEPN4sead4HeapE 0x0000007100f3d180,deleteInstanceForNFPAwarenessAndKingEditor,52, 0x0000007100f3d1b4,waitForResourceCreation1,80, 0x0000007100f3d204,nullsub_4162,4, @@ -91696,7 +91696,7 @@ 0x00000071011ba194,ActorBase::freeLinkData,24,_ZN4ksys3act8BaseProc12freeLinkDataEv 0x00000071011ba1ac,ActorBase::isSpecialJobType,84,_ZN4ksys3act8BaseProc17isSpecialJobType_ENS0_7JobTypeE 0x00000071011ba200,ActorBase::x,112,_ZN4ksys3act8BaseProc16isSpecialJobTypeENS0_7JobTypeE -0x00000071011ba270,ActorBase::queueExtraJobPush,68,_ZN4ksys3act8BaseProc18queueExtraJobPush_ENS0_7JobTypeE +0x00000071011ba270,ActorBase::queueExtraJobPush,68,_ZN4ksys3act8BaseProc18queueExtraJobPush_ENS0_7JobTypeEi 0x00000071011ba2b4,ActorBase::shouldSkipJobPush,144,_ZN4ksys3act8BaseProc17shouldSkipJobPushENS0_7JobTypeE 0x00000071011ba344,ActorBase::getConnectedCalcParent,32,_ZNK4ksys3act8BaseProc22getConnectedCalcParentEv 0x00000071011ba364,ActorBase::jobInvoked,564,_ZN4ksys3act8BaseProc10jobInvokedENS0_7JobTypeE @@ -91815,44 +91815,44 @@ 0x00000071011be59c,BaseProcMgr::deleteAllActors,136,_ZN4ksys3act11BaseProcMgr14deleteAllProcsEv 0x00000071011be624,BaseProcMgr::hasFinishedDeletingAllActors,124,_ZN4ksys3act11BaseProcMgr27hasFinishedDeletingAllProcsEv 0x00000071011be6a0,BaseProcMgr::isGameThreadOrHavokThread,148,_ZNK4ksys3act11BaseProcMgr20isHighPriorityThreadEv -0x00000071011be734,BaseProcMgr::checkGetActorOk,328, -0x00000071011be87c,BaseProcMgr::requestActorCreate,8, -0x00000071011be884,BaseProcMgr::createActor,8, +0x00000071011be734,BaseProcMgr::checkGetActorOk,328,_ZNK4ksys3act11BaseProcMgr19isAccessingProcSafeEPNS0_8BaseProcES3_ +0x00000071011be87c,BaseProcMgr::requestActorCreate,8,_ZN4ksys3act11BaseProcMgr17requestCreateProcERKNS0_21BaseProcCreateRequestE +0x00000071011be884,BaseProcMgr::createActor,8,_ZN4ksys3act11BaseProcMgr10createProcERKNS0_21BaseProcCreateRequestE 0x00000071011be88c,BaseProcMgr::getNextActor,532, -0x00000071011beaa0,sub_71011BEAA0,464, -0x00000071011bec70,sub_71011BEC70,252, -0x00000071011bed6c,BaseProcMgr::invokeForEachActor,140, -0x00000071011bedf8,sub_71011BEDF8,812, -0x00000071011bf124,BaseProcMgr::__auto25,32, -0x00000071011bf144,BaseProcMgr::callThreadC,8, -0x00000071011bf14c,BaseProcMgr::stopThreads,8, -0x00000071011bf154,BaseProcMgr::__auto28,8, -0x00000071011bf15c,BaseProcMgr::__auto0,40, -0x00000071011bf184,BaseProcMgr::__auto29,8, -0x00000071011bf18c,BaseProcMgr::__auto10,8, -0x00000071011bf194,BaseProcMgr::clearMessageQueueMaybe,40, -0x00000071011bf1bc,BaseProcMgr::__auto9,8, -0x00000071011bf1c4,BaseProcMgr::startActorCreateThread,8, -0x00000071011bf1cc,BaseProcMgr::clearInitializerMessageQueuesMaybe,8, -0x00000071011bf1d4,BaseProcMgr::getActorCreateInitializerQueueSize,12, -0x00000071011bf1e0,BaseProcMgr::getActorCreateInitializerQueueSizeEx,8, -0x00000071011bf1e8,BaseProcMgr::invokeOnActorCreateInitializerThreadMaybe,8, -0x00000071011bf1f0,BaseProcMgr::setActorGenerationEnabled,12, +0x00000071011beaa0,sub_71011BEAA0,464,_ZN4ksys3act11BaseProcMgr7getProcERKN4sead14SafeStringBaseIcEENS2_12TypedBitFlagINS1_10ProcFilterEiEE +0x00000071011bec70,sub_71011BEC70,252,_ZN4ksys3act11BaseProcMgr7getProcERKjN4sead12TypedBitFlagINS1_10ProcFilterEiEE +0x00000071011bed6c,BaseProcMgr::invokeForEachActor,140,_ZN4ksys3act11BaseProcMgr11forEachProcERN4sead10IDelegate1IPNS0_8BaseProcEEENS2_12TypedBitFlagINS1_10ProcFilterEiEE? +0x00000071011bedf8,sub_71011BEDF8,812,_ZN4ksys3act11BaseProcMgr11forEachProcERKN4sead14SafeStringBaseIcEERNS2_10IDelegate1IPNS0_8BaseProcEEENS2_12TypedBitFlagINS1_10ProcFilterEiEE +0x00000071011bf124,BaseProcMgr::__auto25,32,_ZNK4ksys3act11BaseProcMgr25areInitializerThreadsIdleEv +0x00000071011bf144,BaseProcMgr::callThreadC,8,_ZN4ksys3act11BaseProcMgr30waitForInitializerQueueToEmptyEv +0x00000071011bf14c,BaseProcMgr::stopThreads,8,_ZN4ksys3act11BaseProcMgr22cancelInitializerTasksEv +0x00000071011bf154,BaseProcMgr::__auto28,8,_ZN4ksys3act11BaseProcMgr21blockInitializerTasksEv +0x00000071011bf15c,BaseProcMgr::__auto0,40,_ZN4ksys3act11BaseProcMgr25restartInitializerThreadsEv +0x00000071011bf184,BaseProcMgr::__auto29,8,_ZN4ksys3act11BaseProcMgr23pauseInitializerThreadsEv +0x00000071011bf18c,BaseProcMgr::__auto10,8,_ZN4ksys3act11BaseProcMgr24resumeInitializerThreadsEv +0x00000071011bf194,BaseProcMgr::clearMessageQueueMaybe,40,_ZN4ksys3act11BaseProcMgr22unblockInitDeleteTasksEv +0x00000071011bf1bc,BaseProcMgr::__auto9,8,_ZN4ksys3act11BaseProcMgr26pauseInitializerMainThreadEv +0x00000071011bf1c4,BaseProcMgr::startActorCreateThread,8,_ZN4ksys3act11BaseProcMgr27resumeInitializerMainThreadEv +0x00000071011bf1cc,BaseProcMgr::clearInitializerMessageQueuesMaybe,8,_ZNK4ksys3act11BaseProcMgr28isAnyInitializerThreadActiveEv +0x00000071011bf1d4,BaseProcMgr::getActorCreateInitializerQueueSize,12,_ZNK4ksys3act11BaseProcMgr23getInitializerQueueSizeEv +0x00000071011bf1e0,BaseProcMgr::getActorCreateInitializerQueueSizeEx,8,_ZNK4ksys3act11BaseProcMgr25getInitializerQueueSizeExEi +0x00000071011bf1e8,BaseProcMgr::invokeOnActorCreateInitializerThreadMaybe,8,_ZN4ksys3act11BaseProcMgr24removeInitializerTasksIfERN4sead11IDelegate1RIPNS_4util4TaskEbEE +0x00000071011bf1f0,BaseProcMgr::setActorGenerationEnabled,12,_ZN4ksys3act11BaseProcMgr25setActorGenerationEnabledEb 0x00000071011bf1fc,BaseProcMgr::incrementField167,24,_ZN4ksys3act11BaseProcMgr13incrementUnk3Ev 0x00000071011bf214,BaseProcMgr::decrementField167,20,_ZN4ksys3act11BaseProcMgr13decrementUnk3Ev 0x00000071011bf228,BaseProcMgr::writeResidentActorsCsv,732, 0x00000071011bf504,appendToResidentActorsList,84, -0x00000071011bf558,BaseProcMgr::queueExtraJobPush,68, -0x00000071011bf59c,BaseProcMgr::moveExtraJobsToOtherBuffer,164, +0x00000071011bf558,BaseProcMgr::queueExtraJobPush,68,_ZN4ksys3act11BaseProcMgr17queueExtraJobPushEPNS0_15BaseProcJobLinkE? +0x00000071011bf59c,BaseProcMgr::moveExtraJobsToOtherBuffer,164,_ZN4ksys3act11BaseProcMgr26moveExtraJobsToOtherBufferENS0_7JobTypeE! 0x00000071011bf640,BaseProcMgr::hasExtraJob,80,_ZN4ksys3act11BaseProcMgr15hasExtraJobLinkEPNS0_15BaseProcJobLinkEi 0x00000071011bf690,BaseProcMgr::clearExtraJobArrays,40,_ZN4ksys3act11BaseProcMgr19clearExtraJobArraysEv 0x00000071011bf6b8,StringMap::doInsert,576,_ZN4sead11TreeMapImplIN4ksys4util13StrTreeMapKeyEE6insertEPNS_11TreeMapNodeIS3_EES7_ 0x00000071011bf8f8,StringMap::erase,1532,_ZN4sead11TreeMapImplIN4ksys4util13StrTreeMapKeyEE5eraseEPNS_11TreeMapNodeIS3_EERKS3_ 0x00000071011bfef4,StringMap::x_0,436,_ZN4sead11TreeMapImplIN4ksys4util13StrTreeMapKeyEE8eraseMinEPNS_11TreeMapNodeIS3_EE? -0x00000071011c00a8,frm::invokedForEachActor,192, -0x00000071011c0168,StringMap::forEach,116, -0x00000071011c01dc,sub_71011C01DC,48, -0x00000071011c020c,sub_71011C020C,92, +0x00000071011c00a8,frm::invokedForEachActor,192,_ZN4ksys3act18ProcForEachContext7forEachEPNS_4util14StrTreeMapNodeE +0x00000071011c0168,StringMap::forEach,116,_ZN4sead11TreeMapImplIN4ksys4util13StrTreeMapKeyEE7forEachIZNKS_16IntrusiveTreeMapIS3_NS1_3act15BaseProcMapNodeEE7forEachINS_9Delegate1INS7_18ProcForEachContextEPNS2_14StrTreeMapNodeEEEEEvRKT_EUlPSG_E_EEvPNS_11TreeMapNodeIS3_EESI_ +0x00000071011c01dc,sub_71011C01DC,48,_ZN4sead9Delegate1IN4ksys3act18ProcForEachContextEPNS1_4util14StrTreeMapNodeEE6invokeES6_ +0x00000071011c020c,sub_71011C020C,92,_ZNK4sead9Delegate1IN4ksys3act18ProcForEachContextEPNS1_4util14StrTreeMapNodeEE5cloneEPNS_4HeapE 0x00000071011c0268,sub_71011C0268,8,_ZNK4sead10IDelegate1IPN4ksys4util14StrTreeMapNodeEE9isNoDummyEv 0x00000071011c0270,sub_71011C0270,8,_ZNK4sead10IDelegate1IPN4ksys4util14StrTreeMapNodeEE5cloneEPNS_4HeapE 0x00000071011c0278,sub_71011C0278,32,_GLOBAL__sub_I_actBaseProcJob.cpp diff --git a/expected/_ZN4ksys3act11BaseProcMgr11forEachProcERN4sead10IDelegate1IPNS0_8BaseProcEEENS2_12TypedBitFlagINS1_10ProcFilterEiEE.bin b/expected/_ZN4ksys3act11BaseProcMgr11forEachProcERN4sead10IDelegate1IPNS0_8BaseProcEEENS2_12TypedBitFlagINS1_10ProcFilterEiEE.bin new file mode 100644 index 00000000..cbe2f9d7 Binary files /dev/null and b/expected/_ZN4ksys3act11BaseProcMgr11forEachProcERN4sead10IDelegate1IPNS0_8BaseProcEEENS2_12TypedBitFlagINS1_10ProcFilterEiEE.bin differ diff --git a/lib/agl b/lib/agl index 1c390c91..92c56335 160000 --- a/lib/agl +++ b/lib/agl @@ -1 +1 @@ -Subproject commit 1c390c9183f0c37496b9544bcc0fa78d736e9d7d +Subproject commit 92c5633549da576da3168d6c8f988207de639e5c diff --git a/src/KingSystem/ActorSystem/actBaseProc.cpp b/src/KingSystem/ActorSystem/actBaseProc.cpp index 4342a9d9..528766d3 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.cpp +++ b/src/KingSystem/ActorSystem/actBaseProc.cpp @@ -229,7 +229,7 @@ bool BaseProc::canWakeUp_() { return true; } -void BaseProc::queueExtraJobPush_(JobType type) { +void BaseProc::queueExtraJobPush_(JobType type, int idx) { if (!isDeletedOrDeleting()) BaseProcMgr::instance()->queueExtraJobPush(&getJobHandler(type)->getLink()); } diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h index 95097aee..6a55c2fb 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.h +++ b/src/KingSystem/ActorSystem/actBaseProc.h @@ -98,11 +98,11 @@ public: bool isInit() const { return mState == State::Init; } bool isCalc() const { return mState == State::Calc; } bool isSleep() const { return mState == State::Sleep; } + bool isDelete() const { return mState == State::Delete; } bool isDeletedOrDeleting() const { return mState == State::Delete || mStateFlags.isOn(StateFlags::RequestDelete); } - bool isInitialized() const { return mFlags.isOn(Flags::Initialized); } /// For BaseProcLink or ActorLinkConstDataAccess. bool acquire(ActorLinkConstDataAccess& accessor); BaseProcLinkData* getBaseProcLinkData() const { return mBaseProcLinkData; } @@ -138,6 +138,10 @@ public: void setInitializedFlag() { mFlags.set(Flags::Initialized); } bool requestDeleteProcUnit() { return setStateFlag(StateFlags::RequestDeleteProcUnit); } + bool isInitialized() const { return mFlags.isOn(Flags::Initialized); } + bool isDeleting() const { return mFlags.isOn(Flags::PreDeleteStarted); } + bool isDeleteRequested() const { return mStateFlags.isOn(StateFlags::RequestDelete); } + protected: friend class BaseProcLinkDataMgr; friend class BaseProcMgr; @@ -256,7 +260,7 @@ protected: virtual IsSpecialJobTypeResult isSpecialJobType_(JobType type); virtual bool canWakeUp_(); - virtual void queueExtraJobPush_(JobType type); + virtual void queueExtraJobPush_(JobType type, int idx); virtual bool hasJobType_(JobType type); /// Called after processStateUpdate() is called for all actors in the update state list. virtual void afterUpdateState_(); diff --git a/src/KingSystem/ActorSystem/actBaseProcInitializer.h b/src/KingSystem/ActorSystem/actBaseProcInitializer.h index fef07cb6..649e0002 100644 --- a/src/KingSystem/ActorSystem/actBaseProcInitializer.h +++ b/src/KingSystem/ActorSystem/actBaseProcInitializer.h @@ -22,7 +22,7 @@ class BaseProc; struct BaseProcCreateRequest; struct BaseProcInitializerArgs { - u32 queue_size = 1024; + u32 queue_size; sead::SafeString thread_name = "BaseProcCreate"; util::TaskSelectionDelegate* task_selector = nullptr; }; diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp index 0aaaaf69..bd228de3 100644 --- a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp +++ b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp @@ -339,7 +339,8 @@ void BaseProcMgr::unlockProcMap() { } void BaseProcMgr::deleteAllProcs() { - auto procs = getProcs(ProcFilter::_1 | ProcFilter::_4 | ProcFilter::_8); + auto procs = + getProcs(ProcFilter::Sleeping | ProcFilter::Initializing | ProcFilter::SkipAccessCheck); while (auto* proc = procs.next()) { if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete)) proc->deleteLater(BaseProc::DeleteReason::BaseProcMgrDeleteAll); @@ -347,7 +348,8 @@ void BaseProcMgr::deleteAllProcs() { } bool BaseProcMgr::hasFinishedDeletingAllProcs() { - auto procs = getProcs(ProcFilter::_1 | ProcFilter::_2 | ProcFilter::_4 | ProcFilter::_8); + auto procs = getProcs(ProcFilter::Sleeping | ProcFilter::DeletedOrDeleting | + ProcFilter::Initializing | ProcFilter::SkipAccessCheck); while (auto* proc = procs.next()) { if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete)) return false; @@ -369,6 +371,227 @@ bool BaseProcMgr::isHighPriorityThread() const { return id == mMainThreadId || id == mHavokThreadId1 || id == mHavokThreadId2; } +bool BaseProcMgr::isAccessingProcSafe(BaseProc* proc, BaseProc* other) const { + [[maybe_unused]] const auto current_thread = sead::ThreadMgr::instance()->getCurrentThread(); + + if (!isHighPriorityThread()) + return true; + + if (mUnk2) + return true; + + if (other) { + if (other == proc) + return true; + if (other->getConnectedCalcChild() == proc) + return true; + if (other->getConnectedCalcParent() == proc) + return true; + } + + if (!mIsPushingJobs) + return true; + + const auto type = mJobType; + + if (type == JobType::Invalid || mStatus != Status::ProcessingActorJobs) { +#ifdef MATCHING_HACK_NX_CLANG + if (proc->isInit()) { + fail: + return false; + } + return true; +#else + return !proc->isInit(); +#endif + } + + if (auto* handler = proc->getJobHandler(type)) { + u8 priority = handler->getLink().getPriority(); + while ((proc = proc->getConnectedCalcParent())) { + if (auto* h = proc->getJobHandler(type)) + priority = h->getLink().getPriority(); + } + if (mCurrentlyProcessingPrio != priority) + return true; + } else if (!proc->isInit()) { + return true; + } +#ifdef MATCHING_HACK_NX_CLANG + goto fail; +#else + return false; +#endif +} + +bool BaseProcMgr::requestCreateProc(const BaseProcCreateRequest& req) { + return mProcInitializer->requestCreateBaseProc(req); +} + +BaseProc* BaseProcMgr::createProc(const BaseProcCreateRequest& req) { + return mProcInitializer->createBaseProc(req); +} + +struct ProcForEachContextData { + inline void handle(BaseProcMapNode* node) const { + if (BaseProcMgr::instance()->checkFilters(node->proc(), filters)) + callback->invoke(node->proc()); + } + + BaseProcMgr::ProcFilters filters; + sead::IDelegate1* callback{}; +}; + +struct ProcForEachContext { + void forEach(util::StrTreeMapNode* node) { // NOLINT(readability-make-member-function-const) + for (auto it = static_cast(node); it; it = it->next()) + data->handle(it); + } + + ProcForEachContextData* data; +}; + +inline bool BaseProcMgr::checkFilters(BaseProc* proc, ProcFilters filters) const { + if (proc->isDeleting() && filters.isOff(ProcFilter::Deleting)) + return false; + + if (!proc->isInitialized() && filters.isOff(ProcFilter::Uninitialized)) + return false; + + if (proc->isSleep() && filters.isOff(ProcFilter::Sleeping)) + return false; + + if (proc->isDeletedOrDeleting() && filters.isOff(ProcFilter::DeletedOrDeleting)) + return false; + + if (proc->isInit() && filters.isOff(ProcFilter::Initializing)) + return false; + + return !filters.isOff(ProcFilter::SkipAccessCheck) || isAccessingProcSafe(proc, nullptr); +} + +BaseProc* BaseProcMgr::getProc(const sead::SafeString& name, BaseProcMgr::ProcFilters filters) { + const auto lock = sead::makeScopedLock(mProcMapCS); + + if (auto* node = mProcMap.find(name)) { + auto* proc = node->proc(); + if (checkFilters(proc, filters)) + return proc; + } + + return nullptr; +} + +BaseProc* BaseProcMgr::getProc(const u32& id, BaseProcMgr::ProcFilters filters) { + auto* cs = lockProcMap(); + auto guard = sead::makeScopeGuard([this] { unlockProcMap(); }); + + BaseProc* proc = nullptr; + do { + proc = getNextProc(cs, proc, filters); + if (proc && proc->getId() == id) { + if (!checkFilters(proc, filters)) + proc = nullptr; + break; + } + } while (proc); + return proc; +} + +// NON_MATCHING: stack +void BaseProcMgr::forEachProc(sead::IDelegate1& callback, ProcFilters filters) { + const auto lock = sead::makeScopedLock(mProcMapCS); + + ProcForEachContextData data; + ProcForEachContext context; + context.data = &data; + data.filters = filters; + data.callback = &callback; + + mProcMap.forEach(sead::Delegate1( + &context, &ProcForEachContext::forEach)); +} + +void BaseProcMgr::forEachProc(const sead::SafeString& proc_name, + sead::IDelegate1& callback, + BaseProcMgr::ProcFilters filters) { + const auto lock = sead::makeScopedLock(mProcMapCS); + + BaseProc* proc = nullptr; + if (auto* node = mProcMap.find(proc_name)) + proc = node->proc(); + + while (proc) { + if (checkFilters(proc, filters)) + callback.invoke(proc); + + auto* next = proc->mMapNode.next(); + proc = next ? next->proc() : nullptr; + } +} + +bool BaseProcMgr::areInitializerThreadsIdle() const { + return !mProcInitializer->isAnyThreadActive(); +} + +void BaseProcMgr::waitForInitializerQueueToEmpty() { + mProcInitializer->waitForTaskQueuesToEmpty(); +} + +void BaseProcMgr::cancelInitializerTasks() { + mProcInitializer->cancelTasks(); +} + +void BaseProcMgr::blockInitializerTasks() { + mProcInitializer->blockPendingTasks(); +} + +void BaseProcMgr::restartInitializerThreads() { + blockInitializerTasks(); + mProcInitializer->restartThreads(); +} + +void BaseProcMgr::pauseInitializerThreads() { + mProcInitializer->pauseThreads(); +} + +void BaseProcMgr::resumeInitializerThreads() { + mProcInitializer->resumeThreads(); +} + +void BaseProcMgr::unblockInitDeleteTasks() { + mProcDeleter->unblockTasks(); + mProcInitializer->unblockPendingTasks(); +} + +void BaseProcMgr::pauseInitializerMainThread() { + mProcInitializer->pauseMainThread(); +} + +void BaseProcMgr::resumeInitializerMainThread() { + mProcInitializer->resumeMainThread(); +} + +bool BaseProcMgr::isAnyInitializerThreadActive() const { + return mProcInitializer->isAnyThreadActive(); +} + +int BaseProcMgr::getInitializerQueueSize() const { + return mProcInitializer->getQueueSize(); +} + +int BaseProcMgr::getInitializerQueueSizeEx(int x) const { + return mProcInitializer->getQueueSize(x); +} + +void BaseProcMgr::removeInitializerTasksIf(sead::IDelegate1R& predicate) { + mProcInitializer->removeTasksIf(predicate); +} + +void BaseProcMgr::setActorGenerationEnabled(bool enabled) { + mProcInitializer->setActorGenerationEnabled(enabled); +} + void BaseProcMgr::incrementUnk3() { if (mUnk3 != 0xFF) ++mUnk3; @@ -379,6 +602,21 @@ void BaseProcMgr::decrementUnk3() { --mUnk3; } +// NON_MATCHING: reorderings +void BaseProcMgr::queueExtraJobPush(BaseProcJobLink* job_link) { + getExtraJobs().pushBack(job_link); +} + +// NON_MATCHING: ??? +void BaseProcMgr::moveExtraJobsToOtherBuffer(JobType type) { + const auto old_idx = mCurrentExtraJobArrayIdx; + swapExtraJobArray(); + auto& array = mExtraJobLinkArrays.ref()[old_idx]; + for (auto& link : array) { + link.getProc()->queueExtraJobPush_(type, mCurrentExtraJobArrayIdx); + } +} + bool BaseProcMgr::hasExtraJobLink(BaseProcJobLink* job_link, s32 idx) { for (auto& ptr : mExtraJobLinkArrays.ref()[idx]) { if (&ptr == job_link) diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.h b/src/KingSystem/ActorSystem/actBaseProcMgr.h index fce3b9a0..c4d8f209 100644 --- a/src/KingSystem/ActorSystem/actBaseProcMgr.h +++ b/src/KingSystem/ActorSystem/actBaseProcMgr.h @@ -59,13 +59,13 @@ public: }; enum class ProcFilter { - _1 = 1 << 0, - _2 = 1 << 1, - _4 = 1 << 2, - _8 = 1 << 3, + Sleeping = 1 << 0, + DeletedOrDeleting = 1 << 1, + Initializing = 1 << 2, + SkipAccessCheck = 1 << 3, _10 = 1 << 4, - _20 = 1 << 5, - _40 = 1 << 6, + Deleting = 1 << 5, + Uninitialized = 1 << 6, }; using ProcFilters = sead::TypedBitFlag; @@ -86,7 +86,6 @@ public: BaseProc* mProc{}; }; - static void createInstanceAndInit(sead::Heap* heap); static u32 getConstant0() { return sConstant0; } static u32 getConstant1() { return sConstant1; } static u32 getConstant2() { return sConstant2; } @@ -112,10 +111,6 @@ public: void eraseFromUpdateStateList(BaseProc& proc); void processPreDeleteList(); - void forEachProc(const sead::IDelegate1& callback, u32 flags); - void deleteAllProcs(); - bool hasFinishedDeletingAllProcs(); - // endregion bool requestPreDelete(BaseProc& proc); @@ -133,7 +128,7 @@ public: void swapExtraJobArray(); void queueExtraJobPush(BaseProcJobLink* job_link); - void moveExtraJobsToOtherBuffer(); + void moveExtraJobsToOtherBuffer(JobType type); bool hasExtraJobLink(BaseProcJobLink* job_link, s32 idx); void clearExtraJobArrays(); @@ -145,8 +140,12 @@ public: void setJobType(JobType type); void setActorJobTypeAndPrio(JobType type, s32 prio, bool); void goIdle(); - void clearMode(); void calc(); + void clearMode(); + sead::CriticalSection* lockProcMap(); + void unlockProcMap(); + void deleteAllProcs(); + bool hasFinishedDeletingAllProcs(); void jobInvoked(BaseProcJobLink* link, s32 required_calc_rounds); // endregion @@ -162,7 +161,7 @@ public: /// Returns true if and only if the calling thread is the game thread or a Havok thread. bool isHighPriorityThread() const; /// Returns true if and only if it is safe to access the specified BaseProc. - bool isAccessingProcSafe(BaseProc* proc, BaseProc* other); + bool isAccessingProcSafe(BaseProc* proc, BaseProc* other) const; // region BaseProc creation @@ -171,17 +170,35 @@ public: // endregion + // region BaseProc iteration + + BaseProc* getNextProc(sead::CriticalSection* cs, BaseProc* proc, ProcFilters filters); + BaseProc* getProc(const sead::SafeString& name, ProcFilters filters); + BaseProc* getProc(const u32& id, ProcFilters filters); + void forEachProc(sead::IDelegate1& callback, ProcFilters filters); + void forEachProc(const sead::SafeString& proc_name, sead::IDelegate1& callback, + ProcFilters filters); + ProcIteratorContext getProcs(ProcFilter filters) { return {*this, filters}; } + bool checkFilters(BaseProc* proc, ProcFilters filters) const; + + // endregion + // region Actor initializer control - void resumeThreadMaybe(); - void stopThreads(); - void clearMessageQueueMaybe(); - void startActorCreateThread(); - - void clearInitializerMessageQueuesMaybe(); - s32 getActorCreateInitializerQueueSize(); - s32 getActorCreateInitializerQueueSizeEx(s32 x); - void invokeOnActorCreateInitializerThreadMaybe(void* delegate); + bool areInitializerThreadsIdle() const; + void waitForInitializerQueueToEmpty(); + void cancelInitializerTasks(); + void blockInitializerTasks(); + void restartInitializerThreads(); + void pauseInitializerThreads(); + void resumeInitializerThreads(); + void unblockInitDeleteTasks(); + void pauseInitializerMainThread(); + void resumeInitializerMainThread(); + bool isAnyInitializerThreadActive() const; + int getInitializerQueueSize() const; + int getInitializerQueueSizeEx(int x = -1) const; + void removeInitializerTasksIf(sead::IDelegate1R& predicate); void setActorGenerationEnabled(bool enabled); // endregion @@ -203,16 +220,10 @@ public: BaseProcJobLists& getJobLists(JobType type) { return mJobLists[u32(type)]; } bool isPushingJobs() const { return mIsPushingJobs; } - bool checkGetActorOk(BaseProc* proc, void* a2); - - // region BaseProc iteration - - sead::CriticalSection* lockProcMap(); - void unlockProcMap(); - BaseProc* getNextProc(sead::CriticalSection* cs, BaseProc* proc, ProcFilters filters); - ProcIteratorContext getProcs(ProcFilter filters) { return {*this, filters}; } - - // endregion + static u32 sConstant0; + static u32 sConstant1; + static u32 sConstant2; + static u32 sConstant4; private: void doAddToUpdateStateList_(BaseProc& proc); @@ -220,10 +231,6 @@ private: bool checkJobPushState() const; static sead::BufferedSafeString* sResidentActorListStr; - static u32 sConstant0; - static u32 sConstant1; - static u32 sConstant2; - static u32 sConstant4; Status mStatus = Status::Idle; sead::SizedEnum mJobType = JobType::Invalid; diff --git a/src/KingSystem/CMakeLists.txt b/src/KingSystem/CMakeLists.txt index 15a1f8b7..4b452fb9 100644 --- a/src/KingSystem/CMakeLists.txt +++ b/src/KingSystem/CMakeLists.txt @@ -13,3 +13,8 @@ add_subdirectory(System) add_subdirectory(Terrain) add_subdirectory(Utils) add_subdirectory(World) + +target_sources(uking PRIVATE + ksys.cpp + ksys.h +) diff --git a/src/KingSystem/ksys.cpp b/src/KingSystem/ksys.cpp new file mode 100644 index 00000000..e370b003 --- /dev/null +++ b/src/KingSystem/ksys.cpp @@ -0,0 +1,32 @@ +#include "KingSystem/ksys.h" +#include +#include +#include "KingSystem/ActorSystem/actBaseProcCreateTaskSelector.h" +#include "KingSystem/ActorSystem/actBaseProcInitializer.h" +#include "KingSystem/ActorSystem/actBaseProcMgr.h" +#include "KingSystem/System/HavokWorkerMgr.h" + +namespace ksys { + +void initBaseProcMgr(sead::Heap* heap) { + sead::ScopedCurrentHeapSetter setter(heap); + + act::BaseProcMgr::createInstance(heap); + act::BaseProcCreateTaskSelector::createInstance(heap); + auto* worker_mgr = HavokWorkerMgr::instance(); + + act::BaseProcInitializerArgs args{}; + args.queue_size = 1024; + args.thread_name = "ActorCreate"; + args.task_selector = &act::BaseProcCreateTaskSelector::instance()->getDelegate(); + act::BaseProcMgr::instance()->init( + heap, u32(act::JobType::Invalid), sead::ThreadMgr::instance()->getMainThread()->getId(), + worker_mgr->getWorkerThreadId(1), worker_mgr->getWorkerThreadId(2), args); + + act::BaseProcMgr::sConstant0 = u32(act::JobType::PreCalc); + act::BaseProcMgr::sConstant1 = u32(act::JobType::Calc1); + act::BaseProcMgr::sConstant2 = u32(act::JobType::Calc2); + act::BaseProcMgr::sConstant4 = u32(act::JobType::Calc4); +} + +} // namespace ksys diff --git a/src/KingSystem/ksys.h b/src/KingSystem/ksys.h new file mode 100644 index 00000000..535e0df5 --- /dev/null +++ b/src/KingSystem/ksys.h @@ -0,0 +1,11 @@ +#pragma once + +namespace sead { +class Heap; +} + +namespace ksys { + +void initBaseProcMgr(sead::Heap* heap); + +} // namespace ksys