diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 7baa36b7..e2347d7a 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -53195,9 +53195,9 @@ 0x000000710090add8,sub_710090ADD8,8, 0x000000710090ade0,sub_710090ADE0,40, 0x000000710090ae08,sub_710090AE08,384, -0x000000710090af88,sub_710090AF88,28, -0x000000710090afa4,nullsub_2648,4, -0x000000710090afa8,j__ZdlPv_413,4, +0x000000710090af88,sub_710090AF88,28,_ZN4ksys14SystemPauseMgrC1Ev +0x000000710090afa4,nullsub_2648,4,_ZN4ksys14SystemPauseMgrD1Ev +0x000000710090afa8,j__ZdlPv_413,4,_ZN4ksys14SystemPauseMgrD0Ev 0x000000710090afac,j_nullsub_3106,4, 0x000000710090afb0,sub_710090AFB0,152, 0x000000710090b048,sub_710090B048,224, @@ -82544,30 +82544,30 @@ 0x0000007100fddc64,sub_7100FDDC64,164, 0x0000007100fddd08,sub_7100FDDD08,444, 0x0000007100fddec4,sub_7100FDDEC4,1108, -0x0000007100fde318,sub_7100FDE318,100, -0x0000007100fde37c,sub_7100FDE37C,108, -0x0000007100fde3e8,OverlayArenaSystem::createInstance,260, -0x0000007100fde4ec,sub_7100FDE4EC,160, -0x0000007100fde58c,sub_7100FDE58C,136, -0x0000007100fde614,sub_7100FDE614,36, -0x0000007100fde638,OverlayArenaSystem::init,580, +0x0000007100fde318,sub_7100FDE318,100,_ZN4ksys18OverlayArenaSystem18SingletonDisposer_D2Ev +0x0000007100fde37c,sub_7100FDE37C,108,_ZN4ksys18OverlayArenaSystem18SingletonDisposer_D0Ev +0x0000007100fde3e8,OverlayArenaSystem::createInstance,260,_ZN4ksys18OverlayArenaSystem14createInstanceEPN4sead4HeapE +0x0000007100fde4ec,sub_7100FDE4EC,160,_ZN4ksys18OverlayArenaSystemD1Ev +0x0000007100fde58c,sub_7100FDE58C,136,_ZN4ksys18OverlayArenaSystem12destroyHeapsEv +0x0000007100fde614,sub_7100FDE614,36,_ZN4ksys18OverlayArenaSystemD0Ev +0x0000007100fde638,OverlayArenaSystem::init,580,_ZN4ksys18OverlayArenaSystem4initERKNS0_7InitArgEPN4sead4HeapE? 0x0000007100fde87c,sub_7100FDE87C,88, 0x0000007100fde8d4,OverlayArenaSystem::__auto0,192, 0x0000007100fde994,OverlayArenaSystem::__auto2,32, -0x0000007100fde9b4,OverlayArenaSystem::getSzsDecompressor,16, -0x0000007100fde9c4,OverlayArenaSystem::getS1ForOverlayArena,8, -0x0000007100fde9cc,OverlayArenaSystem::getS1TeraSzsWork,8, -0x0000007100fde9d4,OverlayArenaSystem::getS1ForAudioOverlayArena,8, -0x0000007100fde9dc,OverlayArenaSystem::getS1ForUnknown,8, +0x0000007100fde9b4,OverlayArenaSystem::getSzsDecompressor,16,_ZNK4ksys18OverlayArenaSystem18getSzsDecompressorEPPN4sead15SZSDecompressorE +0x0000007100fde9c4,OverlayArenaSystem::getS1ForOverlayArena,8,_ZNK4ksys18OverlayArenaSystem8getArenaEv +0x0000007100fde9cc,OverlayArenaSystem::getS1TeraSzsWork,8,_ZNK4ksys18OverlayArenaSystem19getTeraSzsWorkArenaEv +0x0000007100fde9d4,OverlayArenaSystem::getS1ForAudioOverlayArena,8,_ZNK4ksys18OverlayArenaSystem13getAudioArenaEv +0x0000007100fde9dc,OverlayArenaSystem::getS1ForUnknown,8,_ZNK4ksys18OverlayArenaSystem15getUnknownArenaEv 0x0000007100fde9e4,OverlayArenaSystem::__auto1,232, -0x0000007100fdeacc,OverlayArenaSystem::moreInit,368, +0x0000007100fdeacc,OverlayArenaSystem::moreInit,368,_ZN4ksys18OverlayArenaSystem11createHeapsEv 0x0000007100fdec3c,OverlayArenaSystem::createSzsDecompressor,276, -0x0000007100fded50,OverlayArenaSystem::makeS1ForOverlayArena,264, -0x0000007100fdee58,OverlayArenaSystem::makeS1TeraSzsWork,264, -0x0000007100fdef60,OverlayArenaSystem::makeS1AudioOverlayArena,260, -0x0000007100fdf064,OverlayArenaSystem::makeHeapForTeraWork,164, -0x0000007100fdf108,nullsub_4269,4, -0x0000007100fdf10c,OverlayArenaSystem::createMovieHeap,120, +0x0000007100fded50,OverlayArenaSystem::makeS1ForOverlayArena,264,_ZN4ksys18OverlayArenaSystem11createArenaEv +0x0000007100fdee58,OverlayArenaSystem::makeS1TeraSzsWork,264,_ZN4ksys18OverlayArenaSystem22createTeraSzsWorkArenaEv +0x0000007100fdef60,OverlayArenaSystem::makeS1AudioOverlayArena,260,_ZN4ksys18OverlayArenaSystem16createAudioArenaEv +0x0000007100fdf064,OverlayArenaSystem::makeHeapForTeraWork,164,_ZN4ksys18OverlayArenaSystem18createTeraWorkHeapEv +0x0000007100fdf108,nullsub_4269,4,_ZN4ksys18OverlayArenaSystem13createStubbedEv +0x0000007100fdf10c,OverlayArenaSystem::createMovieHeap,120,_ZN4ksys18OverlayArenaSystem15createMovieHeapEv 0x0000007100fdf184,sub_7100FDF184,92, 0x0000007100fdf1e0,sub_7100FDF1E0,96, 0x0000007100fdf240,sub_7100FDF240,56, @@ -90678,11 +90678,11 @@ 0x00000071011fc754,sub_71011FC754,204, 0x00000071011fc820,sub_71011FC820,92, 0x00000071011fc87c,sub_71011FC87C,140, -0x00000071011fc908,OverlayArena::ctor,184, -0x00000071011fc9c0,OverlayArenaSystem::Struct1::dtor,52, +0x00000071011fc908,OverlayArena::ctor,184,_ZN4ksys12OverlayArenaC1Ev +0x00000071011fc9c0,OverlayArenaSystem::Struct1::dtor,52,_ZN4ksys12OverlayArenaD1Ev 0x00000071011fc9f4,OverlayArenaSystem::Struct1::destroy,268, -0x00000071011fcb00,OverlayArenaSystem::Struct1::dtorDelete,64, -0x00000071011fcb40,OverlayArena::makeHeap,384, +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, @@ -90785,7 +90785,7 @@ 0x0000007101201724,ResourceLoadArg::ctor2,112, 0x0000007101201794,ResourceLoadArg2::ctor,64, 0x00000071012017d4,ResourceLoadArg3::ctor,60, -0x0000007101201810,Res::ctor,72, +0x0000007101201810,Res::ctor,72,_ZN4ksys3res6HandleC1Ev 0x0000007101201858,Res::dtor,156, 0x00000071012018f4,Res::unload,136, 0x000000710120197c,Res::dtorDelete,164, diff --git a/lib/sead b/lib/sead index ad85ebd3..1993212e 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit ad85ebd3bf275f35c8ed16383ab66ff736ea7d6f +Subproject commit 1993212edd22edcd3e7f89efadd16c27a508eeb8 diff --git a/src/KingSystem/CMakeLists.txt b/src/KingSystem/CMakeLists.txt index 9d78cb77..86d6d781 100644 --- a/src/KingSystem/CMakeLists.txt +++ b/src/KingSystem/CMakeLists.txt @@ -2,3 +2,5 @@ add_subdirectory(ActorSystem) add_subdirectory(Map) add_subdirectory(MessageSystem) add_subdirectory(Resource) +add_subdirectory(Sound) +add_subdirectory(System) diff --git a/src/KingSystem/Resource/CMakeLists.txt b/src/KingSystem/Resource/CMakeLists.txt index a018382f..645a074c 100644 --- a/src/KingSystem/Resource/CMakeLists.txt +++ b/src/KingSystem/Resource/CMakeLists.txt @@ -86,6 +86,8 @@ target_sources(uking PRIVATE resCurrentResNameMgr.h resEntryFactory.cpp resEntryFactory.h + resHandle.cpp + resHandle.h resResource.cpp resResource.h @@ -105,4 +107,6 @@ target_sources(uking PRIVATE resResourceLod.h resResourceRecipe.cpp resResourceRecipe.h + + resSystem.h ) diff --git a/src/KingSystem/Resource/resHandle.cpp b/src/KingSystem/Resource/resHandle.cpp new file mode 100644 index 00000000..67024b14 --- /dev/null +++ b/src/KingSystem/Resource/resHandle.cpp @@ -0,0 +1,7 @@ +#include "KingSystem/Resource/resHandle.h" + +namespace ksys::res { + +Handle::Handle() = default; + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resHandle.h b/src/KingSystem/Resource/resHandle.h new file mode 100644 index 00000000..186cb4ab --- /dev/null +++ b/src/KingSystem/Resource/resHandle.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include "KingSystem/Utils/Thread/ManagedTaskHandle.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::res { + +class ResourceUnit; + +// FIXME: incomplete +class Handle { + SEAD_RTTI_BASE(Handle) +public: + enum class Status { + _0 = 0, + }; + + Handle(); + virtual ~Handle(); + + Status getStatus() const; + +private: + enum class Flag : u8 { + _1 = 0x1, + }; + + sead::TypedBitFlag mFlags = Flag::_1; + Status mStatus = Status::_0; + ResourceUnit* mUnit = nullptr; + util::ManagedTaskHandle mTaskHandle; + void* _40 = nullptr; + void* _48 = nullptr; +}; +KSYS_CHECK_SIZE_NX150(Handle, 0x50); + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resResourceMgrTask.cpp b/src/KingSystem/Resource/resResourceMgrTask.cpp new file mode 100644 index 00000000..c5b53de1 --- /dev/null +++ b/src/KingSystem/Resource/resResourceMgrTask.cpp @@ -0,0 +1 @@ +#include "KingSystem/Resource/resResourceMgrTask.h" diff --git a/src/KingSystem/Resource/resResourceMgrTask.h b/src/KingSystem/Resource/resResourceMgrTask.h new file mode 100644 index 00000000..e9bdd2db --- /dev/null +++ b/src/KingSystem/Resource/resResourceMgrTask.h @@ -0,0 +1,21 @@ +#pragma once + +namespace ksys { +class OverlayArena; +} + +namespace ksys::res { + +// FIXME: very, very incomplete. +class ResourceMgrTask { +public: + static ResourceMgrTask* instance() { return sInstance; } + + void insertOverlayArena(OverlayArena* arena); + OverlayArena* getSomeArena() const; + +private: + static ResourceMgrTask* sInstance; +}; + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resSystem.h b/src/KingSystem/Resource/resSystem.h new file mode 100644 index 00000000..4c27f2b4 --- /dev/null +++ b/src/KingSystem/Resource/resSystem.h @@ -0,0 +1,13 @@ +#pragma once + +namespace ksys::res { + +// In release builds, the only thing this function does is return 1. +// TODO: figure out what this is used for. Stubbed log function? +bool stubbedLogFunction(); + +// In release builds, the only thing this function does is return 0. +// TODO: figure out what this is used for. Stubbed log function? +bool returnFalse(); + +} // namespace ksys::res diff --git a/src/KingSystem/Sound/CMakeLists.txt b/src/KingSystem/Sound/CMakeLists.txt new file mode 100644 index 00000000..fb85aff9 --- /dev/null +++ b/src/KingSystem/Sound/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(uking PRIVATE + sndResource.h +) diff --git a/src/KingSystem/Sound/sndResource.h b/src/KingSystem/Sound/sndResource.h new file mode 100644 index 00000000..c17e570a --- /dev/null +++ b/src/KingSystem/Sound/sndResource.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "KingSystem/Utils/Types.h" + +namespace ksys::snd { + +// FIXME: incomplete +class SoundResource { + SEAD_SINGLETON_DISPOSER(SoundResource) + virtual ~SoundResource(); + +public: + sead::Heap* getSoundDebugHeap() const { return mSoundDebugHeap; } + +private: + sead::Heap* mSoundResourceHeap; + void* _30; + sead::Heap* mSoundDebugHeap; +}; +KSYS_CHECK_SIZE_NX150(SoundResource, 0x40); + +} // namespace ksys::snd diff --git a/src/KingSystem/System/CMakeLists.txt b/src/KingSystem/System/CMakeLists.txt new file mode 100644 index 00000000..f2a045ba --- /dev/null +++ b/src/KingSystem/System/CMakeLists.txt @@ -0,0 +1,11 @@ +target_sources(uking PRIVATE + OverlayArena.cpp + OverlayArena.h + OverlayArenaSystem.cpp + OverlayArenaSystem.h + OverlayArenaSystemS1.h + OverlayArenaSystemS2.h + StringBoard.h + SystemPauseMgr.cpp + SystemPauseMgr.h +) diff --git a/src/KingSystem/System/OverlayArena.cpp b/src/KingSystem/System/OverlayArena.cpp new file mode 100644 index 00000000..3e612cbf --- /dev/null +++ b/src/KingSystem/System/OverlayArena.cpp @@ -0,0 +1,62 @@ +#include "KingSystem/System/OverlayArena.h" +#include +#include "KingSystem/Resource/resResourceMgrTask.h" +#include "KingSystem/Resource/resSystem.h" + +namespace ksys { + +OverlayArena::OverlayArena() { + // FIXME: these should use offsetof() + mUnits.initOffset(0xc0); + mOffsetList2.initOffset(0xd0); +} + +OverlayArena::~OverlayArena() { + destroy(); +} + +// NON_MATCHING: branching at the end (csel instead of a branch) +bool OverlayArena::init(const OverlayArena::InitArg& arg) { + if (!arg.heap) { + res::stubbedLogFunction(); + return false; + } + + if (arg.size == 0) + res::stubbedLogFunction(); + + mFlags.change(Flag::_1, arg.set_flag_1); + + mHeap = sead::ExpHeap::create(arg.size, arg.name, arg.heap, arg.alignment, + sead::Heap::cHeapDirection_Forward, true); + + if (arg.use_best_fit_alloc_mode) + mHeap->setAllocMode(sead::ExpHeap::AllocMode::BestFit); + + mHeapSize = mHeap->getSize(); + _cc = 0; + mHeapFreeSize = mHeap->getFreeSize(); + mHeapName = mHeap->getName(); + mUsagePercentage = 0.0; + _c8 = 0; + mMinFreePercentage = arg.min_free_percentage; + + if (res::ResourceMgrTask::instance()) + res::ResourceMgrTask::instance()->insertOverlayArena(this); + + mFlags.change(Flag::_20, arg.set_flag_20); + mFlags.change(Flag::_10, arg.set_flag_10); + + struct UnusedTemp { + sead::SafeString str; + void* _10 = nullptr; + }; + [[maybe_unused]] UnusedTemp temp; + temp.str = arg.name; + + mFlags.change(Flag::_8, arg.set_flag_8); + + return true; +} + +} // namespace ksys diff --git a/src/KingSystem/System/OverlayArena.h b/src/KingSystem/System/OverlayArena.h new file mode 100644 index 00000000..ef64b723 --- /dev/null +++ b/src/KingSystem/System/OverlayArena.h @@ -0,0 +1,89 @@ +#pragma once + +#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; +} + +class OverlayArena { +public: + struct InitArg { + bool set_flag_1 = false; + bool set_flag_8 = false; + bool use_best_fit_alloc_mode = false; + u8 _3 = false; + bool set_flag_10 = true; + bool set_flag_20 = false; + u8 _6 = 1; + u32 alignment = 8; + u32 size = 0; + f32 min_free_percentage = 0.0; + sead::Heap* heap = nullptr; + sead::Heap* heap2 = nullptr; + sead::SafeString name; + }; + KSYS_CHECK_SIZE_NX150(InitArg, 0x38); + + OverlayArena(); + virtual ~OverlayArena(); + + bool init(const InitArg& arg); + void destroy(); + +private: + friend class OverlayArenaSystem; + + enum class Flag : u8 { + _1 = 0x1, + _2 = 0x2, + _4 = 0x4, + _8 = 0x8, + _10 = 0x10, + _20 = 0x20, + }; + + sead::ListNode mListNode; + sead::TypedBitFlag mFlags = [] { + decltype(mFlags) flags; + flags.set(Flag::_2); + flags.set(Flag::_4); + return flags; + }(); + sead::ExpHeap* mHeap = nullptr; + f32 mMinFreePercentage = 0.0; + sead::Heap* mHeap2 = nullptr; + sead::OffsetList mUnits; + sead::OffsetList mOffsetList2; // FIXME: type + sead::CriticalSection mCS; + void* mUsage2 = nullptr; + void* _b0 = nullptr; + u32 _b8 = 0; + u32 mUsage1 = 0; + u32 mHeapFreeSize = 0; + u32 _c4 = 0; + u32 _c8 = 0; + u32 _cc = 0; + u32 mHeapSize = 0; + sead::SafeString mHeapName; + f32 mUsagePercentage = 0.0; + StringBoard mStringBoard; + u8 _f8 = 0; +}; +KSYS_CHECK_SIZE_NX150(OverlayArena, 0x100); + +} // namespace ksys diff --git a/src/KingSystem/System/OverlayArenaSystem.cpp b/src/KingSystem/System/OverlayArenaSystem.cpp new file mode 100644 index 00000000..0dd00733 --- /dev/null +++ b/src/KingSystem/System/OverlayArenaSystem.cpp @@ -0,0 +1,330 @@ +#include "KingSystem/System/OverlayArenaSystem.h" +#include +#include +#include +#include +#include "KingSystem/Resource/resSystem.h" +#include "KingSystem/Sound/sndResource.h" +#include "KingSystem/System/OverlayArena.h" +#include "KingSystem/System/SystemPauseMgr.h" +#include "KingSystem/Terrain/teraSystem.h" +#include "KingSystem/Utils/Thread/Task.h" +#include "KingSystem/Utils/Thread/TaskThread.h" + +namespace ksys { + +SEAD_SINGLETON_DISPOSER_IMPL(OverlayArenaSystem) + +OverlayArenaSystem::OverlayArenaSystem() + : mEvent(nullptr, sead::IDisposer::HeapNullOption::DoNotAppendDisposerIfNoHeapSpecified, true) { + mEvent.resetSignal(); +} + +OverlayArenaSystem::~OverlayArenaSystem() { + destroyHeaps(); + + if (mSzsDecompressorInstHeap) + mSzsDecompressorInstHeap->destroy(); + + if (mTask) + delete mTask; + mTask = nullptr; + + if (mPrepareThread) { + mPrepareThread->quitAndWaitDoneSingleThread(false); + if (mPrepareThread) + delete mPrepareThread; + mPrepareThread = nullptr; + } +} + +void OverlayArenaSystem::destroyHeaps() { + res::stubbedLogFunction(); + if (mGameDataWorkHeap) { + mGameDataWorkHeap->destroy(); + mGameDataWorkHeap = nullptr; + } + res::stubbedLogFunction(); + + res::stubbedLogFunction(); + if (mFixedHeap) { + mFixedHeap->destroy(); + mFixedHeap = nullptr; + } + res::stubbedLogFunction(); + + res::stubbedLogFunction(); + if (mMovableMemoryHeap) { + mMovableMemoryHeap->destroy(); + mMovableMemoryHeap = nullptr; + } + res::stubbedLogFunction(); + + mFlags.set(Flag::_2); +} + +// NON_MATCHING: reordering for TaskThread::InitArg +bool OverlayArenaSystem::init(const InitArg& arg, sead::Heap* heap) { + mSystemPauseMgr = arg.system_pause_mgr; + + mPrepareThread = new (heap) util::TaskThread( + "OverlayArena Prepare", heap, sead::ThreadUtil::ConvertPrioritySeadToPlatform(17), + sead::MessageQueue::BlockType::Blocking, 0x7fffffff, 0x14000, 32); + + { + util::TaskThread::InitArg arg_; + arg_.batch_size = 0; + arg_.queue = nullptr; + arg_.num_lanes = 1; + arg_.heap = heap; + mPrepareThread->init(arg_); + mPrepareThread->setAffinity(sead::CoreIdMask(sead::CoreId::cMain)); + mPrepareThread->start(); + } + + mDelegate = {this, &OverlayArenaSystem::delegatedFunction}; + + { + mTask = new (heap) util::Task(heap); + util::TaskDelegateSetter setter; + mTask->setDelegate(setter); + } + + { + OverlayArenaSystemS2::InitArg arg_; + arg_.s1 = &mS1; + arg_.system_pause_mgr = mSystemPauseMgr; + mS2.init(arg_); + } + + mSzsDecompressorInstHeap = sead::ExpHeap::create( + sead::ExpHeap::getManagementAreaSize(8) + 0x1e20, "SZSDecompressorInst", heap, + sizeof(void*), sead::Heap::cHeapDirection_Forward, true); + + if (heap) { + mFlags.reset(Flag::_2); + mFixedHeap = sead::ExpHeap::tryCreate(0x17600000, "FixedHeap", heap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, false); + if (mFixedHeap) { + createHeaps(); + mMovableMemoryHeap = + sead::ExpHeap::tryCreate(0x100000, "MovableMemoryHeap", heap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, false); + } + } + + res::stubbedLogFunction(); + mS1.init(); + res::stubbedLogFunction(); + + if (mSystemPauseMgr) { + res::stubbedLogFunction(); + mSystemPauseMgr->m2(); + res::stubbedLogFunction(); + } + + return true; +} + +void OverlayArenaSystem::getSzsDecompressor(sead::SZSDecompressor** decompressor) const { + if (decompressor) + *decompressor = mSzsDecompressor; +} + +OverlayArena* OverlayArenaSystem::getArena() const { + return mArena; +} + +OverlayArena* OverlayArenaSystem::getTeraSzsWorkArena() const { + return mTeraSzsWorkArena; +} + +OverlayArena* OverlayArenaSystem::getAudioArena() const { + return mAudioArena; +} + +OverlayArena* OverlayArenaSystem::getUnknownArena() const { + return mUnknownArena; +} + +void OverlayArenaSystem::createHeaps() { + res::stubbedLogFunction(); + + res::stubbedLogFunction(); + mGameDataWorkHeap = + sead::ExpHeap::tryCreate(0x400000, "GameDataWork", mFixedHeap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, true); + if (!mGameDataWorkHeap) + return; + + res::stubbedLogFunction(); + + createSzsDecompressor(); + createTexArcWorkHeap(); + createArena(); + createTeraSzsWorkArena(); + createAudioArena(); + createJpegHeap(); + createTeraWorkHeap(); + createPlacementTreeHeap(); + + res::stubbedLogFunction(); +} + +void OverlayArenaSystem::createTexArcWorkHeap() { + res::stubbedLogFunction(); + + if (mTexArcWorkHeap) + return; + + if (!mFixedHeap) + return; + + mTexArcWorkHeap = sead::ExpHeap::tryCreate(0xc000000, "TexArcWork", mFixedHeap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, true); + if (mTexArcWorkHeap) + res::stubbedLogFunction(); +} + +void OverlayArenaSystem::createArena() { + res::stubbedLogFunction(); + + if (mArena) + return; + + if (!mFixedHeap) + return; + + mArena = new (mFixedHeap, std::nothrow) OverlayArena; + if (!mArena) { + mArena = nullptr; + return; + } + + OverlayArena::InitArg arg; + arg.size = 0x3affee0; + arg.set_flag_1 = true; + arg.set_flag_8 = true; + arg.use_best_fit_alloc_mode = false; + arg.name = "ForOverlayArena"; + arg.heap = mFixedHeap; + arg.heap2 = nullptr; + arg._6 = false; + arg.set_flag_10 = false; + if (mArena->init(arg)) + res::stubbedLogFunction(); +} + +void OverlayArenaSystem::createTeraSzsWorkArena() { + res::stubbedLogFunction(); + + if (mTeraSzsWorkArena) + return; + + if (!mFixedHeap) + return; + + mTeraSzsWorkArena = new (mFixedHeap, std::nothrow) OverlayArena; + if (!mTeraSzsWorkArena) { + mTeraSzsWorkArena = nullptr; + return; + } + + OverlayArena::InitArg arg; + arg.size = 0x9ffee0; + arg.set_flag_1 = true; + arg.set_flag_8 = true; + arg.use_best_fit_alloc_mode = false; + arg.name = "TeraSZSWork"; + arg.heap = mFixedHeap; + arg.heap2 = nullptr; + arg._6 = false; + arg.set_flag_10 = false; + if (mTeraSzsWorkArena->init(arg)) + res::stubbedLogFunction(); +} + +void OverlayArenaSystem::createAudioArena() { + res::stubbedLogFunction(); + + if (mAudioArena) + return; + + if (!mFixedHeap) + return; + + mAudioArena = new (mFixedHeap, std::nothrow) OverlayArena; + if (!mAudioArena) { + mAudioArena = nullptr; + return; + } + + OverlayArena::InitArg arg; + arg.size = 0x2e00000; + arg.set_flag_8 = true; + arg.use_best_fit_alloc_mode = false; + arg.name = "Audio(OverlayArena)"; + arg.heap = mFixedHeap; + arg.heap2 = snd::SoundResource::instance()->getSoundDebugHeap(); + arg.alignment = 0x1000; + if (mAudioArena->init(arg)) + res::stubbedLogFunction(); +} + +void OverlayArenaSystem::createJpegHeap() { + res::stubbedLogFunction(); + + if (mJpegHeap) + return; + + if (!mFixedHeap) + return; + + mJpegHeap = sead::ExpHeap::tryCreate(0x900000, "JPEG", mFixedHeap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, true); + if (mJpegHeap) + res::stubbedLogFunction(); +} + +void OverlayArenaSystem::createTeraWorkHeap() { + res::stubbedLogFunction(); + + if (tera::System::instance()) { + if (mTeraWorkHeap) + return; + + mTeraWorkHeap = sead::ExpHeap::tryCreate(0, "TeraWork", mFixedHeap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, false); + if (mTeraWorkHeap) { + tera::System::instance()->allocateApertureMapsCollectorImage(mTeraWorkHeap); + mTeraWorkHeap->adjust(); + res::stubbedLogFunction(); + } + } else { + res::stubbedLogFunction(); + } +} + +void OverlayArenaSystem::createPlacementTreeHeap() { + res::stubbedLogFunction(); + + if (mPlacementTreeHeap) + return; + + mPlacementTreeHeap = + sead::ExpHeap::tryCreate(0x700000, "PlacementTree", mFixedHeap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, false); + res::stubbedLogFunction(); +} + +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); + res::stubbedLogFunction(); +} + +} // namespace ksys diff --git a/src/KingSystem/System/OverlayArenaSystem.h b/src/KingSystem/System/OverlayArenaSystem.h new file mode 100644 index 00000000..46dc9b88 --- /dev/null +++ b/src/KingSystem/System/OverlayArenaSystem.h @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include +#include +#include "KingSystem/Resource/resHandle.h" +#include "KingSystem/System/OverlayArenaSystemS1.h" +#include "KingSystem/System/OverlayArenaSystemS2.h" +#include "KingSystem/Utils/Thread/Event.h" +#include "KingSystem/Utils/Types.h" + +namespace sead { +class Heap; +class SZSDecompressor; +} // namespace sead + +namespace ksys { + +namespace util { +class Task; +class TaskThread; +} // namespace util + +class OverlayArena; +class SystemPauseMgr; + +// FIXME: incomplete +class OverlayArenaSystem { + SEAD_SINGLETON_DISPOSER(OverlayArenaSystem) + + OverlayArenaSystem(); + virtual ~OverlayArenaSystem(); + +public: + struct InitArg { + SystemPauseMgr* system_pause_mgr; + }; + + bool init(const InitArg& arg, sead::Heap* heap); + + void getSzsDecompressor(sead::SZSDecompressor** decompressor) const; + OverlayArena* getArena() const; + OverlayArena* getTeraSzsWorkArena() const; + OverlayArena* getAudioArena() const; + OverlayArena* getUnknownArena() const; + + void createTeraWorkHeap(); + void createStubbed(); + void createMovieHeap(); + +private: + enum class Flag { + _1 = 0x1, + _2 = 0x2, + }; + + void createHeaps(); + void destroyHeaps(); + + void createSzsDecompressor(); + void createTexArcWorkHeap(); + void createArena(); + void createTeraSzsWorkArena(); + void createAudioArena(); + void createJpegHeap(); + void createPlacementTreeHeap(); + + bool delegatedFunction(); + + sead::TypedBitFlag mFlags; + u32 _2c = 0; + sead::Heap* mFixedHeap = nullptr; + sead::Heap* mMovableMemoryHeap = nullptr; + sead::Heap* mGameDataWorkHeap = nullptr; + sead::Heap* mMovieHeap = nullptr; + sead::Heap* mPlacementTreeHeap = nullptr; + sead::Heap* mTeraWorkHeap = nullptr; + sead::Heap* mSzsDecompressorInstHeap = nullptr; + sead::Heap* mSzsHeap = nullptr; + sead::SZSDecompressor* mSzsDecompressor = nullptr; + sead::Heap* mTexArcWorkHeap = nullptr; + OverlayArena* mArena = nullptr; + OverlayArena* mTeraSzsWorkArena = nullptr; + OverlayArena* mAudioArena = nullptr; + OverlayArena* mUnknownArena = nullptr; + sead::Heap* mJpegHeap = nullptr; + SystemPauseMgr* mSystemPauseMgr = nullptr; + OverlayArenaSystemS1 mS1; + u32 _b8 = 0; + util::TaskThread* mPrepareThread = nullptr; + util::Task* mTask = nullptr; + sead::DelegateR mDelegate; + OverlayArenaSystemS2 mS2; + sead::Atomic _130 = 0; + sead::Atomic _134 = 0; + res::Handle mResHandle; + util::Event mEvent; +}; +KSYS_CHECK_SIZE_NX150(OverlayArenaSystem, 0x1c8); + +} // namespace ksys diff --git a/src/KingSystem/System/OverlayArenaSystemS1.h b/src/KingSystem/System/OverlayArenaSystemS1.h new file mode 100644 index 00000000..f2adce58 --- /dev/null +++ b/src/KingSystem/System/OverlayArenaSystemS1.h @@ -0,0 +1,39 @@ +#pragma once + +#include "KingSystem/Utils/Types.h" + +namespace ksys { + +// FIXME: incomplete +// Unknown struct seen in OverlayArenaSystem. +class OverlayArenaSystemS1 final { +public: + OverlayArenaSystemS1(); + virtual ~OverlayArenaSystemS1(); + + // TODO: figure out if this is the same interface as SystemPauseMgr. + // Both have the exact same number of virtual functions and some of the functions + // look somewhat similar (suspending threads, looping while waiting for their status to change). + + virtual void init(); + // Resume resource compaction + virtual void m3(); + virtual void m4(); + // Resume resource compaction + EventMgr + virtual void m5(); + // Stop threads, clear cache, etc. + virtual void m6(); + virtual bool m7(); + virtual void m8(); + virtual void m9(); + // Does nothing + virtual void m10(); + virtual bool m11(); + virtual void m12(); + virtual void m13(); + // Does nothing + virtual void m14(); +}; +KSYS_CHECK_SIZE_NX150(OverlayArenaSystemS1, 0x8); + +} // namespace ksys diff --git a/src/KingSystem/System/OverlayArenaSystemS2.h b/src/KingSystem/System/OverlayArenaSystemS2.h new file mode 100644 index 00000000..2a43c72a --- /dev/null +++ b/src/KingSystem/System/OverlayArenaSystemS2.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include "KingSystem/Utils/Types.h" + +namespace ksys { + +class OverlayArenaSystemS1; +class SystemPauseMgr; + +// FIXME: incomplete +class OverlayArenaSystemS2 { +public: + struct InitArg { + OverlayArenaSystemS1* s1; + SystemPauseMgr* system_pause_mgr; + }; + + OverlayArenaSystemS2(); + + void init(const InitArg& arg); + +private: + u32 _0 = 0; + sead::Delegate1 mDelegate; + u32 _28 = 1; + void* _30 = nullptr; + void* _38 = nullptr; +}; +KSYS_CHECK_SIZE_NX150(OverlayArenaSystemS2, 0x40); + +} // namespace ksys diff --git a/src/KingSystem/System/StringBoard.h b/src/KingSystem/System/StringBoard.h new file mode 100644 index 00000000..df275ab2 --- /dev/null +++ b/src/KingSystem/System/StringBoard.h @@ -0,0 +1,14 @@ +#pragma once + +#include "KingSystem/Utils/Types.h" + +namespace ksys { + +// Stubbed in release builds +class StringBoard { +public: + virtual ~StringBoard() = default; +}; +KSYS_CHECK_SIZE_NX150(StringBoard, 0x8); + +} // namespace ksys diff --git a/src/KingSystem/System/SystemPauseMgr.cpp b/src/KingSystem/System/SystemPauseMgr.cpp new file mode 100644 index 00000000..ce8ddbdf --- /dev/null +++ b/src/KingSystem/System/SystemPauseMgr.cpp @@ -0,0 +1,9 @@ +#include "KingSystem/System/SystemPauseMgr.h" + +namespace ksys { + +SystemPauseMgr::SystemPauseMgr() = default; + +SystemPauseMgr::~SystemPauseMgr() = default; + +} // namespace ksys diff --git a/src/KingSystem/System/SystemPauseMgr.h b/src/KingSystem/System/SystemPauseMgr.h new file mode 100644 index 00000000..43ca4efc --- /dev/null +++ b/src/KingSystem/System/SystemPauseMgr.h @@ -0,0 +1,33 @@ +#pragma once + +#include "KingSystem/Utils/Types.h" + +namespace ksys { + +class SystemPauseMgr { +public: + SystemPauseMgr(); + virtual ~SystemPauseMgr(); + + virtual void m2(); + virtual void m3(); + virtual void m4(); + virtual void m5(); + virtual void m6(); + virtual bool m7(); + virtual void m8(); + virtual void m9(); + virtual void m10(); + virtual bool m11(); + virtual void m12(); + virtual void m13(); + virtual void m14(); + + bool get8() const { return _8; } + +private: + bool _8 = true; +}; +KSYS_CHECK_SIZE_NX150(SystemPauseMgr, 0x10); + +} // namespace ksys diff --git a/src/KingSystem/Terrain/teraSystem.h b/src/KingSystem/Terrain/teraSystem.h index a3aab5d2..e940fe00 100644 --- a/src/KingSystem/Terrain/teraSystem.h +++ b/src/KingSystem/Terrain/teraSystem.h @@ -1,5 +1,9 @@ #pragma once +namespace sead { +class Heap; +} + namespace ksys::tera { // TODO: @@ -23,6 +27,9 @@ class Scene { void exportFileBinary(); }; class System { +public: + static System* instance(); + void allocateApertureMapsCollectorImage(sead::Heap* heap); void loadScene(); }; class Water { diff --git a/src/KingSystem/Utils/Thread/Task.h b/src/KingSystem/Utils/Thread/Task.h index df54db8e..3f076d0b 100644 --- a/src/KingSystem/Utils/Thread/Task.h +++ b/src/KingSystem/Utils/Thread/Task.h @@ -131,7 +131,7 @@ protected: friend class TaskQueueBase; friend class TaskThread; - enum class Flag { + enum class Flag : u8 { DeleteDelegate = 0x1, DoNotDeleteDelegate = 0x2, NeedsToSignalEvent = 0x4, @@ -173,7 +173,7 @@ protected: } u8 mLaneId = 0; - sead::TypedBitFlag mFlags = Flag::DoNotDeleteDelegate; + sead::TypedBitFlag mFlags = Flag::DoNotDeleteDelegate; bool mDelegateResult = false; TaskDelegate* mDelegate = nullptr; void* mUserData = nullptr; diff --git a/src/KingSystem/Utils/Thread/TaskQueueBase.cpp b/src/KingSystem/Utils/Thread/TaskQueueBase.cpp index 430fdbf2..b6303ccb 100644 --- a/src/KingSystem/Utils/Thread/TaskQueueBase.cpp +++ b/src/KingSystem/Utils/Thread/TaskQueueBase.cpp @@ -57,7 +57,6 @@ void TaskQueueBase::clear() { mQueueEmptyEvent.wait(); } -// NON_MATCHING: swapped operands for a csel. The arg.set_flag1 check looks suspicious. bool TaskQueueBase::init(const InitArg& arg) { if (arg.max_num_threads == 0) return false; @@ -65,10 +64,7 @@ bool TaskQueueBase::init(const InitArg& arg) { if (!mThreads.tryAllocBuffer(arg.max_num_threads, arg.heap)) return false; - if (!arg.enable_locks) - mFlags.reset(Flag::Lock); - else - mFlags.set(Flag::Lock); + mFlags.change(Flag::Lock, arg.enable_locks); if (arg.num_lanes <= 0 || arg.num_lanes > 0x100) return false; diff --git a/src/KingSystem/Utils/Thread/TaskQueueBase.h b/src/KingSystem/Utils/Thread/TaskQueueBase.h index 3d4b44cf..bdc7503f 100644 --- a/src/KingSystem/Utils/Thread/TaskQueueBase.h +++ b/src/KingSystem/Utils/Thread/TaskQueueBase.h @@ -88,7 +88,7 @@ public: void fetchTask(Task** out_task); protected: - enum class Flag { + enum class Flag : u8 { Lock = 0x1, PreventThreadPoolChanges = 0x2, }; @@ -145,7 +145,7 @@ protected: void notifyThreadsForNewTasks(); - sead::TypedBitFlag mFlags; + sead::TypedBitFlag mFlags; sead::OffsetList mActiveTasks; sead::Buffer mLanes; Event mQueueEmptyEvent;