#pragma once #include #include #include #include #include "KingSystem/ActorSystem/actBaseProcCreateTask.h" #include "KingSystem/Utils/Types.h" namespace ksys::act { class BaseProc; class BaseProcCreateTask; class BaseProcUnit; class BaseProcHandle { public: BaseProcHandle(); ~BaseProcHandle() { deleteProc(); } BaseProcHandle(const BaseProcHandle&) = delete; BaseProcHandle(BaseProcHandle&&) = delete; auto operator=(const BaseProcHandle&) = delete; auto operator=(BaseProcHandle&&) = delete; bool isProcReady() const; bool hasProcCreationFailed() const; bool isProcCreationCancelled() const; bool isAllocatedOrFailed() const { return mUnit || mFailed; } void deleteProcIfFailed(); void deleteProc(); BaseProc* getProc() const; BaseProc* releaseProc(); BaseProc* releaseAndWakeProc(); BaseProcCreateTask* getCreateTask() const; BaseProcUnit* getUnit() const { return mUnit; } bool allocUnit(); bool hasFailed() const { return mFailed; } void setFailed(bool failed) { mFailed = failed; } private: BaseProcUnit* mUnit = nullptr; bool mFailed = false; }; KSYS_CHECK_SIZE_NX150(BaseProcHandle, 0x10); /// Glue code between a BaseProcHandle and its associated BaseProc. /// Used while a BaseProc is being created. class BaseProcUnit { public: enum class Status : u32 { Unused = 0, Initializing = 1, Ready = 2, NoProc = 3, _4 = 4, Cancelled = 5, }; BaseProcUnit() = default; ~BaseProcUnit(); BaseProcUnit(const BaseProcUnit&) = delete; BaseProcUnit(BaseProcUnit&&) = delete; auto operator=(const BaseProcUnit&) = delete; auto operator=(BaseProcUnit&&) = delete; bool deleteProc(u32, BaseProcHandle* handle); bool setProc(BaseProc* proc); void unlinkProc(BaseProc* proc); void cleanUp(BaseProc* proc, bool is_cancellation); bool isParentHandleDefault() const; Status getStatus() const { return mStatus; } BaseProc* getProc() const { return mProc; } BaseProcCreateTask& getCreateTask() { return mCreateTask; } const BaseProcCreateTask& getCreateTask() const { return mCreateTask; } sead::CriticalSection& getCS() { return mCS; } bool isReady() const { return mStatus == Status::Ready; } bool compareExchangeHandle(BaseProcHandle* expected, BaseProcHandle* desired) { return mHandle.compareExchange(expected, desired); } void setInitializingStatus() { mStatus = Status::Initializing; } private: void reset(); BaseProcHandle* getHandle() const { return mHandle.load(); } sead::Atomic mStatus = Status::Unused; sead::Atomic mHandle; BaseProc* mProc{}; BaseProcCreateTask mCreateTask{nullptr}; sead::CriticalSection mCS; }; KSYS_CHECK_SIZE_NX150(BaseProcUnit, 0x2f0); struct BaseProcUnitPool { struct Impl { sead::SafeArray array; } units{}; int next = 0; BaseProcUnit* alloc(BaseProcHandle* handle); }; extern BaseProcUnitPool gUnitPool; extern BaseProcHandle gDummyProcHandle; } // namespace ksys::act