From eef975f585f4cca8bbba89fc097d91dc620565ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 14 Mar 2021 17:41:55 +0100 Subject: [PATCH] ksys/act: Add more BaseProcMgr functions --- data/uking_functions.csv | 46 +-- src/KingSystem/ActorSystem/actBaseProc.h | 1 + .../ActorSystem/actBaseProcInitializer.h | 2 + src/KingSystem/ActorSystem/actBaseProcJob.h | 5 +- .../ActorSystem/actBaseProcJobQue.h | 2 + src/KingSystem/ActorSystem/actBaseProcMgr.cpp | 299 ++++++++++++++++-- src/KingSystem/ActorSystem/actBaseProcMgr.h | 67 +++- 7 files changed, 362 insertions(+), 60 deletions(-) diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 4ed8c3ff..1350427a 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -91776,44 +91776,44 @@ 0x00000071011bcffc,sub_71011BCFFC,100,_ZN4ksys3act11BaseProcMgr18SingletonDisposer_D2Ev 0x00000071011bd060,sub_71011BD060,108,_ZN4ksys3act11BaseProcMgr18SingletonDisposer_D0Ev 0x00000071011bd0cc,BaseProcMgr::createInstance,372,_ZN4ksys3act11BaseProcMgr14createInstanceEPN4sead4HeapE -0x00000071011bd240,sub_71011BD240,164, -0x00000071011bd2e4,sub_71011BD2E4,36, -0x00000071011bd308,BaseProcMgr::init,680, +0x00000071011bd240,sub_71011BD240,164,_ZN4ksys3act11BaseProcMgrD1Ev +0x00000071011bd2e4,sub_71011BD2E4,36,_ZN4ksys3act11BaseProcMgrD0Ev +0x00000071011bd308,BaseProcMgr::init,680,_ZN4ksys3act11BaseProcMgr4initEPN4sead4HeapEijjjRKNS0_23BaseProcInitializerArgsE? 0x00000071011bd5b0,BaseProcMgr::generateActorId,28,_ZN4ksys3act11BaseProcMgr14generateProcIdEPj 0x00000071011bd5cc,BaseProcMgr::registerActor,156,_ZN4ksys3act11BaseProcMgr12registerProcERNS0_8BaseProcE 0x00000071011bd668,StringMap::insert,316,_ZN4ksys3act11BaseProcMap6insertEPNS0_15BaseProcMapNodeE 0x00000071011bd7a4,BaseProcMgr::unregisterActor,188,_ZN4ksys3act11BaseProcMgr14unregisterProcERNS0_8BaseProcE -0x00000071011bd860,BaseProcMgr::requestPreDelete,8, -0x00000071011bd868,BaseProcMgr::requestUnloadActorParam,8, +0x00000071011bd860,BaseProcMgr::requestPreDelete,8,_ZN4ksys3act11BaseProcMgr16requestPreDeleteERNS0_8BaseProcE +0x00000071011bd868,BaseProcMgr::requestUnloadActorParam,8,_ZN4ksys3act11BaseProcMgr23requestUnloadActorParamEPNS0_10ActorParamE 0x00000071011bd870,BaseProcMgr::addToPreDeleteList,84,_ZN4ksys3act11BaseProcMgr18addToPreDeleteListERNS0_8BaseProcE 0x00000071011bd8c4,BaseProcMgr::eraseFromPreDeleteList,96,_ZN4ksys3act11BaseProcMgr22eraseFromPreDeleteListERNS0_8BaseProcE -0x00000071011bd924,BaseProcMgr::pushJob,144, -0x00000071011bd9b4,BaseProcMgr::pushJobForAllTypes,156, -0x00000071011bda50,BaseProcMgr::eraseJob,60, -0x00000071011bda8c,BaseProcMgr::eraseJobForAllTypes,112, +0x00000071011bd924,BaseProcMgr::pushJob,144,_ZN4ksys3act11BaseProcMgr7pushJobERNS0_8BaseProcENS0_7JobTypeE +0x00000071011bd9b4,BaseProcMgr::pushJobForAllTypes,156,_ZN4ksys3act11BaseProcMgr8pushJobsERNS0_8BaseProcE +0x00000071011bda50,BaseProcMgr::eraseJob,60,_ZN4ksys3act11BaseProcMgr8eraseJobERNS0_8BaseProcENS0_7JobTypeE +0x00000071011bda8c,BaseProcMgr::eraseJobForAllTypes,112,_ZN4ksys3act11BaseProcMgr9eraseJobsERNS0_8BaseProcE 0x00000071011bdafc,BaseProcMgr::addToUpdateStateList,108,_ZN4ksys3act11BaseProcMgr23doAddToUpdateStateList_ERNS0_8BaseProcE 0x00000071011bdb68,BaseProcMgr::removeFromUpdateStateList,96,_ZN4ksys3act11BaseProcMgr24eraseFromUpdateStateListERNS0_8BaseProcE 0x00000071011bdbc8,BaseProcMgr::processPreDeleteList,128,_ZN4ksys3act11BaseProcMgr20processPreDeleteListEv 0x00000071011bdc48,BaseProcMgr::processExtraJobsDirectly,628, -0x00000071011bdebc,BaseProcMgr::getExtraJobs,32, -0x00000071011bdedc,BaseProcMgr::swapExtraJobArray,56, -0x00000071011bdf14,BaseProcMgr::pushJobQueues,604, -0x00000071011be170,BaseProcMgr::pushExtraJobsEx,148, -0x00000071011be204,BaseProcMgr::pushExtraJobsForCurrentTypeAndPrio,76, -0x00000071011be250,BaseProcMgr::setActorJobType,20, -0x00000071011be264,BaseProcMgr::pushPreCalcJobs,128, +0x00000071011bdebc,BaseProcMgr::getExtraJobs,32,_ZN4ksys3act11BaseProcMgr12getExtraJobsEv +0x00000071011bdedc,BaseProcMgr::swapExtraJobArray,56,_ZN4ksys3act11BaseProcMgr17swapExtraJobArrayEv +0x00000071011bdf14,BaseProcMgr::pushJobQueues,604,_ZN4ksys3act11BaseProcMgr13pushJobQueuesEPN4sead9WorkerMgrENS0_7JobTypeEb +0x00000071011be170,BaseProcMgr::pushExtraJobsEx,148,_ZN4ksys3act11BaseProcMgr15pushExtraJobsExEPN4sead11FixedSizeJQENS0_7JobTypeEhbb +0x00000071011be204,BaseProcMgr::pushExtraJobsForCurrentTypeAndPrio,76,_ZN4ksys3act11BaseProcMgr34pushExtraJobsForCurrentTypeAndPrioEPN4sead11FixedSizeJQEPN3agl3utl13FixedPtrArrayINS0_15BaseProcJobLinkELi512EEE +0x00000071011be250,BaseProcMgr::setActorJobType,20,_ZN4ksys3act11BaseProcMgr10setJobTypeENS0_7JobTypeE +0x00000071011be264,BaseProcMgr::pushPreCalcJobs,128,_ZN4ksys3act11BaseProcMgr15pushPreCalcJobsEPN4sead11FixedSizeJQENS0_7JobTypeEhbb 0x00000071011be2e4,BaseProcMgr::setActorJobTypeAndPrio,28,_ZN4ksys3act11BaseProcMgr22setActorJobTypeAndPrioENS0_7JobTypeEib 0x00000071011be300,BaseProcMgr::goIdle,32,_ZN4ksys3act11BaseProcMgr6goIdleEv -0x00000071011be320,BaseProcMgr::jobInvoked,212, -0x00000071011be3f4,BaseProcMgr::isSpecialJobType,28, -0x00000071011be410,BaseProcMgr::setSpecialJobTypesMask,16, -0x00000071011be420,BaseProcMgr::clearSpecialJobTypesMask,16, -0x00000071011be430,BaseProcMgr::calc,304, +0x00000071011be320,BaseProcMgr::jobInvoked,212,_ZN4ksys3act11BaseProcMgr10jobInvokedEPNS0_15BaseProcJobLinkEi +0x00000071011be3f4,BaseProcMgr::isSpecialJobType,28,_ZNK4ksys3act11BaseProcMgr16isSpecialJobTypeENS0_7JobTypeE +0x00000071011be410,BaseProcMgr::setSpecialJobTypesMask,16,_ZN4ksys3act11BaseProcMgr18addSpecialJobTypesEt +0x00000071011be420,BaseProcMgr::clearSpecialJobTypesMask,16,_ZN4ksys3act11BaseProcMgr21removeSpecialJobTypesEt +0x00000071011be430,BaseProcMgr::calc,304,_ZN4ksys3act11BaseProcMgr4calcEv 0x00000071011be560,BaseProcMgr::clearMode,8,_ZN4ksys3act11BaseProcMgr9clearModeEv 0x00000071011be568,BaseProcMgr::lockCriticalSection,40,_ZN4ksys3act11BaseProcMgr11lockProcMapEv 0x00000071011be590,BaseProcMgr::unlockCriticalSection,12,_ZN4ksys3act11BaseProcMgr13unlockProcMapEv -0x00000071011be59c,BaseProcMgr::deleteAllActors,136, -0x00000071011be624,BaseProcMgr::hasFinishedDeletingAllActors,124, +0x00000071011be59c,BaseProcMgr::deleteAllActors,136,_ZN4ksys3act11BaseProcMgr14deleteAllProcsEv +0x00000071011be624,BaseProcMgr::hasFinishedDeletingAllActors,124,_ZN4ksys3act11BaseProcMgr27hasFinishedDeletingAllProcsEv 0x00000071011be6a0,BaseProcMgr::isGameThreadOrHavokThread,148,_ZNK4ksys3act11BaseProcMgr20isHighPriorityThreadEv 0x00000071011be734,BaseProcMgr::checkGetActorOk,328, 0x00000071011be87c,BaseProcMgr::requestActorCreate,8, diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h index c2712ed7..95097aee 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.h +++ b/src/KingSystem/ActorSystem/actBaseProc.h @@ -41,6 +41,7 @@ public: _0 = 0, _1 = 1, _2 = 2, + BaseProcMgrDeleteAll = 4, _f = 0xf, _15 = 0x15, _16 = 0x16, diff --git a/src/KingSystem/ActorSystem/actBaseProcInitializer.h b/src/KingSystem/ActorSystem/actBaseProcInitializer.h index bd410fb9..fef07cb6 100644 --- a/src/KingSystem/ActorSystem/actBaseProcInitializer.h +++ b/src/KingSystem/ActorSystem/actBaseProcInitializer.h @@ -71,6 +71,8 @@ public: void removeTasksIf(sead::IDelegate1R& predicate); void setActorGenerationEnabled(bool enabled); + util::TaskQueue* getTaskQueue() const { return mTaskQueue; } + private: sead::Buffer mThreads; util::TaskMgr* mTaskMgr = nullptr; diff --git a/src/KingSystem/ActorSystem/actBaseProcJob.h b/src/KingSystem/ActorSystem/actBaseProcJob.h index 705bbb38..41debba6 100644 --- a/src/KingSystem/ActorSystem/actBaseProcJob.h +++ b/src/KingSystem/ActorSystem/actBaseProcJob.h @@ -64,6 +64,9 @@ struct BaseProcJobList { class BaseProcJobLists { public: + BaseProcJobLists() = default; + ~BaseProcJobLists() { ; } + void pushJob(BaseProcJobLink& link); void eraseJob(BaseProcJobLink& link); sead::TListNode* getJobWithTopPriority() const; @@ -73,7 +76,7 @@ public: const BaseProcJobList& getList(int idx) const { return mLists[idx]; } private: - sead::SafeArray mLists; + sead::SafeArray mLists{}; }; class BaseProcJob final : public sead::Job { diff --git a/src/KingSystem/ActorSystem/actBaseProcJobQue.h b/src/KingSystem/ActorSystem/actBaseProcJobQue.h index 9a5dc27a..6d2aaf54 100644 --- a/src/KingSystem/ActorSystem/actBaseProcJobQue.h +++ b/src/KingSystem/ActorSystem/actBaseProcJobQue.h @@ -31,6 +31,8 @@ public: bool pushExtraJobs(sead::FixedSizeJQ* queue, const agl::utl::AtomicPtrArray& links); + void clear() { mNumExtraJobs = 0; } + private: bool pushJobs(sead::FixedSizeJQ* queue, BaseProcJobLists* lists, int priority, bool should_reset_job_idx, JobType type); diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp index 9f0044f7..0aaaaf69 100644 --- a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp +++ b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp @@ -1,6 +1,14 @@ #include "KingSystem/ActorSystem/actBaseProcMgr.h" +#include #include #include +#include "KingSystem/ActorSystem/actActorSystem.h" +#include "KingSystem/ActorSystem/actBaseProcDeleter.h" +#include "KingSystem/ActorSystem/actBaseProcHeapMgr.h" +#include "KingSystem/ActorSystem/actBaseProcInitializer.h" +#include "KingSystem/ActorSystem/actBaseProcJobHandler.h" +#include "KingSystem/ActorSystem/actBaseProcJobQue.h" +#include "KingSystem/ActorSystem/actBaseProcLink.h" namespace ksys::act { @@ -11,6 +19,54 @@ BaseProcMgr::BaseProcMgr() { mProcUpdateStateList.initOffset(offsetof(BaseProc, mUpdateStateListNode)); } +BaseProcMgr::~BaseProcMgr() { + if (mProcJobQue) { + delete mProcJobQue; + mProcJobQue = nullptr; + } + + mJobLists.freeBuffer(); + + if (mProcInitializer) { + delete mProcInitializer; + mProcInitializer = nullptr; + } + + if (mProcDeleter) { + delete mProcDeleter; + mProcDeleter = nullptr; + } + + BaseProcHeapMgr::deleteInstance(); +} + +// NON_MATCHING: mJobLists.allocBufferAssert - BaseProcJobLists ctor +void BaseProcMgr::init(sead::Heap* heap, s32 num_job_types, u32 main_thread_id, + u32 havok_thread_id1, u32 havok_thread_id2, + const BaseProcInitializerArgs& initializer_args) { + mProcJobQue = new (heap) BaseProcJobQue; + mProcJobQue->init(heap); + + mJobLists.allocBufferAssert(num_job_types, heap); + + mProcInitializer = new (heap) BaseProcInitializer; + mProcInitializer->init(heap, initializer_args); + + mProcDeleter = new (heap) BaseProcDeleter; + BaseProcDeleter::InitArg deleter_arg; + deleter_arg.heap = heap; + deleter_arg.task_queue = mProcInitializer->getTaskQueue(); + deleter_arg.task_queue_size = 2048; + mProcDeleter->init(deleter_arg); + + mMainThreadId = main_thread_id; + mHavokThreadId1 = havok_thread_id1; + mHavokThreadId2 = havok_thread_id2; + + BaseProcHeapMgr::createInstance(heap); + BaseProcLinkDataMgr::createInstance(heap); +} + void BaseProcMgr::generateProcId(u32* id) { *id = mCreatedProcCounter.increment(); } @@ -29,11 +85,52 @@ void BaseProcMgr::unregisterProc(BaseProc& proc) { mProcMap.erase(&proc.mMapNode); } +bool BaseProcMgr::requestPreDelete(BaseProc& proc) { + return mProcDeleter->requestPreDelete(&proc); +} + +void BaseProcMgr::requestUnloadActorParam(ActorParam* param) { + return mProcDeleter->requestUnloadActorParam(param); +} + void BaseProcMgr::addToPreDeleteList(BaseProc& proc) { auto lock = sead::makeScopedLock(mProcPreDeleteListCS); mProcPreDeleteList.pushFront(&proc); } +void BaseProcMgr::eraseFromPreDeleteList(BaseProc& proc) { + auto lock = sead::makeScopedLock(mProcPreDeleteListCS); + if (mProcPreDeleteList.isNodeLinked(&proc)) + mProcPreDeleteList.erase(&proc); +} + +void BaseProcMgr::pushJob(BaseProc& proc, JobType type) { + if (proc.isSleep() || !proc.hasJobType_(type)) + return; + + getJobLists(type).pushJob(proc.getJobHandler(type)->getLink()); +} + +void BaseProcMgr::pushJobs(BaseProc& proc) { + for (u32 i = 0; i < u32(mJobLists.size()); ++i) { + pushJob(proc, JobType(i)); + } +} + +void BaseProcMgr::eraseJob(BaseProc& proc, JobType type) { + auto* handler = proc.getJobHandler(type); + if (handler) + getJobLists(type).eraseJob(handler->getLink()); +} + +void BaseProcMgr::eraseJobs(BaseProc& proc) { + for (u32 i = 0; i < u32(mJobLists.size()); ++i) { + auto* handler = proc.getJobHandler(JobType(i)); + if (handler) + mJobLists[i].eraseJob(handler->getLink()); + } +} + void BaseProcMgr::doAddToUpdateStateList_(BaseProc& proc) { if (mProcUpdateStateList.isNodeLinked(&proc)) return; @@ -46,12 +143,6 @@ void BaseProcMgr::doAddToUpdateStateList_(BaseProc& proc) { } } -void BaseProcMgr::eraseFromPreDeleteList(BaseProc& proc) { - auto lock = sead::makeScopedLock(mProcPreDeleteListCS); - if (mProcPreDeleteList.isNodeLinked(&proc)) - mProcPreDeleteList.erase(&proc); -} - void BaseProcMgr::eraseFromUpdateStateList(BaseProc& proc) { auto lock = sead::makeScopedLock(mProcUpdateStateListCS); if (mProcUpdateStateList.isNodeLinked(&proc)) @@ -68,17 +159,100 @@ void BaseProcMgr::processPreDeleteList() { mStatus = Status::Idle; } -bool BaseProcMgr::hasExtraJobLink(BaseProcJobLink* job_link, s32 idx) { - for (auto& ptr : mExtraJobLinkArrays.ref()[idx]) { - if (&ptr == job_link) - return true; - } - return false; +BaseProcMgr::ExtraJobLinkArray& BaseProcMgr::getExtraJobs() { + return mExtraJobLinkArrays.ref()[mCurrentExtraJobArrayIdx]; } -void BaseProcMgr::clearExtraJobArrays() { - mExtraJobLinkArrays.ref()[0].clear(); - mExtraJobLinkArrays.ref()[1].clear(); +void BaseProcMgr::swapExtraJobArray() { + mCurrentExtraJobArrayIdx ^= 1; + getExtraJobs().clear(); +} + +bool BaseProcMgr::checkJobPushState() const { + return mEnableExtraJobPush && mUnk4 != 1; +} + +void BaseProcMgr::pushJobQueues(sead::WorkerMgr* mgr, JobType type, bool x) { + if (!checkJobPushState()) + return; + + mJobType = type; + const auto type_ = mJobType; + mStatus = Status::ProcessingActorJobs; + mIsPushingJobs = true; + mUnk2 = x; + + int i = 0; + do { + mPushActorJobType3InsteadOf6 = false; + + auto& lists = getJobLists(type_); + for (int priority = 0; priority < 8; ++priority) { + mCurrentlyProcessingPrio = priority; + if (mProcJobQue->pushJobQueue(mgr, &lists, priority, type_)) { + mgr->run(); + mgr->sync(); + } + } + + mCurrentlyProcessingPrio = 8; + ++i; + } while (mPushActorJobType3InsteadOf6 && i < 8); + + mIsPushingJobs = false; + mUnk2 = false; + mStatus = Status::Idle; + mJobType = JobType::Invalid; +} + +bool BaseProcMgr::pushExtraJobsEx(sead::FixedSizeJQ* jq, JobType type, u8 priority, bool x, + bool y) { + if (!checkJobPushState()) + return false; + + if (x) { + mUnk2 = y; + auto* queue = mProcJobQue; + mStatus = Status::ProcessingActorJobs; + mJobType = type; + mCurrentlyProcessingPrio = priority; + queue->clear(); + } + + const auto type_ = JobType(u8(type)); + mIsPushingJobs = true; + mProcJobQue->pushExtraJobs(jq, &getJobLists(type_), priority, type_); + return true; +} + +bool BaseProcMgr::pushExtraJobsForCurrentTypeAndPrio(sead::FixedSizeJQ* jq, + ExtraJobLinkArray* array) { + if (!checkJobPushState()) + return false; + if (array) + mProcJobQue->pushExtraJobs(jq, *array); + return true; +} + +void BaseProcMgr::setJobType(JobType type) { + mProcJobQue->clear(); + mJobType = type; +} + +bool BaseProcMgr::pushPreCalcJobs(sead::FixedSizeJQ* jq, JobType type, u8 prio, bool x, bool y) { + if (!checkJobPushState()) + return false; + + if (x) { + mStatus = Status::ProcessingActorJobs; + mJobType = type; + mCurrentlyProcessingPrio = prio; + mUnk2 = y; + } + + const auto type_ = JobType(u8(type)); + mProcJobQue->pushExtraJobs(jq, &getJobLists(type_), prio, type_); + return true; } void BaseProcMgr::setActorJobTypeAndPrio(JobType type, s32 prio, bool x) { @@ -97,10 +271,90 @@ void BaseProcMgr::goIdle() { mCurrentlyProcessingPrio = 8; } +void BaseProcMgr::jobInvoked(BaseProcJobLink* link, s32 required_calc_rounds) { + if (required_calc_rounds == 1) { + link->getProc()->jobInvoked(mJobType); + return; + } + + const auto& lists = getJobLists(mJobType); + for (int i = 0; link && [&] { return i < required_calc_rounds; }(); ++i) { + link->getProc()->jobInvoked(mJobType); + link = static_cast(lists.getNextJob(link)); + } +} + +bool BaseProcMgr::isSpecialJobType(JobType type) const { + return mSpecialJobTypesMask.isOnBit(int(type)); +} + +void BaseProcMgr::addSpecialJobTypes(u16 mask) { + mSpecialJobTypesMask.set(mask); +} + +void BaseProcMgr::removeSpecialJobTypes(u16 mask) { + mSpecialJobTypesMask.reset(mask); +} + +void BaseProcMgr::calc() { + ActorSystem::instance()->onBaseProcMgrCalc(); + mProcInitializer->deleteThreadIfPaused(); + + if (mIsInitialisingQuestMgrMaybe) + return; + + if (!mProcUpdateStateList.isEmpty()) { + const auto lock = sead::makeScopedLock(mProcUpdateStateListCS); + mStatus = Status::ProcessingUpdateStateList; + + for (auto& proc : mProcUpdateStateList) + proc.processStateUpdate(mCounter); + + for (auto it = mProcUpdateStateList.robustBegin(), end = mProcUpdateStateList.robustEnd(); + it != end; ++it) { + it->afterUpdateState_(); + if (it->mStateFlags.isZero()) { + mProcUpdateStateList.erase(std::addressof(*it)); + } + } + + mStatus = Status::Idle; + } + + ++mCounter; +} + void BaseProcMgr::clearMode() { mMode = Mode::_0; } +sead::CriticalSection* BaseProcMgr::lockProcMap() { + mProcMapCS.lock(); + return &mProcMapCS; +} + +void BaseProcMgr::unlockProcMap() { + mLastProcMapNode = nullptr; + mProcMapCS.unlock(); +} + +void BaseProcMgr::deleteAllProcs() { + auto procs = getProcs(ProcFilter::_1 | ProcFilter::_4 | ProcFilter::_8); + while (auto* proc = procs.next()) { + if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete)) + proc->deleteLater(BaseProc::DeleteReason::BaseProcMgrDeleteAll); + } +} + +bool BaseProcMgr::hasFinishedDeletingAllProcs() { + auto procs = getProcs(ProcFilter::_1 | ProcFilter::_2 | ProcFilter::_4 | ProcFilter::_8); + while (auto* proc = procs.next()) { + if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete)) + return false; + } + return mNumPendingDeletions == 0; +} + bool BaseProcMgr::isHighPriorityThread() const { const auto current_thread = sead::ThreadMgr::instance()->getCurrentThread(); @@ -125,14 +379,17 @@ void BaseProcMgr::decrementUnk3() { --mUnk3; } -sead::CriticalSection* BaseProcMgr::lockProcMap() { - mProcMapCS.lock(); - return &mProcMapCS; +bool BaseProcMgr::hasExtraJobLink(BaseProcJobLink* job_link, s32 idx) { + for (auto& ptr : mExtraJobLinkArrays.ref()[idx]) { + if (&ptr == job_link) + return true; + } + return false; } -void BaseProcMgr::unlockProcMap() { - mLastProcMapNode = nullptr; - mProcMapCS.unlock(); +void BaseProcMgr::clearExtraJobArrays() { + mExtraJobLinkArrays.ref()[0].clear(); + mExtraJobLinkArrays.ref()[1].clear(); } } // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.h b/src/KingSystem/ActorSystem/actBaseProcMgr.h index 752da5b5..cbd6dddf 100644 --- a/src/KingSystem/ActorSystem/actBaseProcMgr.h +++ b/src/KingSystem/ActorSystem/actBaseProcMgr.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -20,13 +21,12 @@ namespace sead { class FixedSizeJQ; -template -class IFunction; class WorkerMgr; } // namespace sead namespace ksys::act { +class ActorParam; class BaseProcCreateTaskData; class BaseProcDeleter; class BaseProcInitializer; @@ -57,8 +57,34 @@ public: _0 = 0, }; + enum class ProcFilter { + _1 = 1 << 0, + _2 = 1 << 1, + _4 = 1 << 2, + _8 = 1 << 3, + _10 = 1 << 4, + _20 = 1 << 5, + _40 = 1 << 6, + }; + + using ProcFilters = sead::TypedBitFlag; using ExtraJobLinkArray = agl::utl::FixedPtrArray; + /// Wrapper to simplify BaseProc iteration. + class ProcIteratorContext { + public: + ProcIteratorContext(BaseProcMgr& mgr, ProcFilters filters) + : mMgr(mgr), mCS(mgr.lockProcMap()), mFilters(filters) {} + ~ProcIteratorContext() { mMgr.unlockProcMap(); } + BaseProc* next() { return mProc = mMgr.getNextProc(mCS, mProc, mFilters); } + + private: + BaseProcMgr& mMgr; + sead::CriticalSection* mCS{}; + ProcFilters mFilters{}; + BaseProc* mProc{}; + }; + static void createInstanceAndInit(sead::Heap* heap); static u32 getConstant0() { return sConstant0; } static u32 getConstant1() { return sConstant1; } @@ -92,7 +118,7 @@ public: // endregion bool requestPreDelete(BaseProc& proc); - void requestUnloadActorParam(void*); + void requestUnloadActorParam(ActorParam* param); // region Job processing @@ -110,12 +136,12 @@ public: bool hasExtraJobLink(BaseProcJobLink* job_link, s32 idx); void clearExtraJobArrays(); - void pushJobQueues(sead::WorkerMgr* mgr, JobType type, bool); - bool pushExtraJobsEx(sead::FixedSizeJQ* jq, JobType type, bool, bool); - bool pushExtraJobsForCurrentTypeAndPrio(sead::FixedSizeJQ* jq, ExtraJobLinkArray& array); - bool pushPreCalcJobs(sead::FixedSizeJQ* jq, JobType type, s32 prio, bool, bool); + void pushJobQueues(sead::WorkerMgr* mgr, JobType type, bool x); + bool pushExtraJobsEx(sead::FixedSizeJQ* jq, JobType type, u8 priority, bool x, bool y); + bool pushExtraJobsForCurrentTypeAndPrio(sead::FixedSizeJQ* jq, ExtraJobLinkArray* array); + bool pushPreCalcJobs(sead::FixedSizeJQ* jq, JobType type, u8 prio, bool x, bool y); - void setActorJobType(JobType type); + void setJobType(JobType type); void setActorJobTypeAndPrio(JobType type, s32 prio, bool); void goIdle(); void clearMode(); @@ -172,17 +198,25 @@ public: Status getStatus() const { return mStatus; } JobType getJobType() const { return mJobType; } - u32 getNumJobTypes() const { return mNumJobTypes; } + u32 getNumJobTypes() const { return mJobLists.size(); } + BaseProcJobLists& getJobLists(JobType type) { return mJobLists[u32(type)]; } bool isPushingJobs() const { return mIsPushingJobs; } bool checkGetActorOk(BaseProc* proc, void* a2); -private: - void doAddToUpdateStateList_(BaseProc& proc); + // region BaseProc iteration sead::CriticalSection* lockProcMap(); void unlockProcMap(); - void getNextActor(sead::CriticalSection* cs, BaseProc* proc, u32 flags); + BaseProc* getNextProc(sead::CriticalSection* cs, BaseProc* proc, ProcFilters filters); + ProcIteratorContext getProcs(ProcFilter filters) { return {*this, filters}; } + + // endregion + +private: + void doAddToUpdateStateList_(BaseProc& proc); + + bool checkJobPushState() const; static sead::BufferedSafeString* sResidentActorListStr; static u32 sConstant0; @@ -196,8 +230,7 @@ private: u8 mCounter = 0; sead::CriticalSection mProcMapCS; sead::OffsetList mProcPreDeleteList; - u32 mNumJobTypes = 0; - BaseProcJobLists* mJobLists = nullptr; + sead::Buffer mJobLists; BaseProcMap mProcMap; sead::OffsetList mProcUpdateStateList; sead::CriticalSection mProcUpdateStateListCS; @@ -214,7 +247,7 @@ private: Mode mMode = Mode::_0; bool mUnk2 = false; bool mIsInitialisingQuestMgrMaybe = false; - u8 mCurrentExtraJobArrayIdx = 0; + s8 mCurrentExtraJobArrayIdx = 0; u8 mUnk3 = 0; sead::BitFlag16 mSpecialJobTypesMask = 0; u32 mMainThreadId = 0; @@ -226,6 +259,10 @@ private: }; KSYS_CHECK_SIZE_NX150(BaseProcMgr, 0x21a0); +constexpr auto operator|(BaseProcMgr::ProcFilter a, BaseProcMgr::ProcFilter b) { + return BaseProcMgr::ProcFilter(u32(a) | u32(b)); +} + inline bool BaseProcMgr::setProcFlag(BaseProc& proc, BaseProc::StateFlags flag) { auto lock = sead::makeScopedLock(mProcUpdateStateListCS); doAddToUpdateStateList_(proc);