From 9bf17b0b41cd0f21b11ebdea545b92befab1b73d Mon Sep 17 00:00:00 2001 From: GRAnimated Date: Sat, 11 Jul 2026 06:03:34 +0000 Subject: [PATCH 1/5] SMO matching and cleanup changes --- include/container/seadTreeMap.h | 5 +- include/controller/seadControllerMgr.h | 2 +- include/filedevice/seadFileDeviceMgr.h | 2 +- include/framework/seadGameFramework.h | 4 +- include/framework/seadMethodTree.h | 12 +- include/mc/seadJobQueue.h | 11 +- include/prim/seadDelegateEventSlot.h | 2 + modules/src/basis/seadNew.cpp | 10 +- modules/src/container/seadPtrArray.cpp | 43 +++++- modules/src/container/seadTreeNode.cpp | 32 ++--- modules/src/controller/seadControllerMgr.cpp | 13 +- .../nin/seadNinFileDeviceBaseNin.cpp | 29 +++- .../src/filedevice/seadArchiveFileDevice.cpp | 4 +- modules/src/filedevice/seadFileDevice.cpp | 2 +- modules/src/filedevice/seadFileDeviceMgr.cpp | 14 +- modules/src/filedevice/seadPath.cpp | 7 +- modules/src/framework/seadFramework.cpp | 2 +- modules/src/framework/seadGameFramework.cpp | 8 +- modules/src/framework/seadMethodTree.cpp | 4 +- modules/src/gfx/nvn/seadDebugFontMgrNvn.cpp | 111 ++++++++------- modules/src/gfx/seadColor.cpp | 11 +- modules/src/hostio/seadHostIOCurve.cpp | 103 +++++++++----- modules/src/math/seadMatrix.cpp | 63 +++++++++ modules/src/mc/seadCoreInfo.cpp | 12 +- modules/src/mc/seadJobQueue.cpp | 127 +++++++++--------- modules/src/prim/seadBitFlag.cpp | 21 ++- modules/src/prim/seadSafeString.cpp | 115 ++++++++-------- modules/src/prim/seadStringBuilder.cpp | 78 ++++++----- modules/src/resource/seadSZSDecompressor.cpp | 76 +++++------ modules/src/thread/seadThread.cpp | 126 ++--------------- modules/src/time/seadCalendarTime.cpp | 14 +- modules/src/time/seadDateUtil.cpp | 30 +++-- 32 files changed, 573 insertions(+), 520 deletions(-) diff --git a/include/container/seadTreeMap.h b/include/container/seadTreeMap.h index 0ee17a7f..7db461df 100644 --- a/include/container/seadTreeMap.h +++ b/include/container/seadTreeMap.h @@ -452,7 +452,7 @@ inline TreeMapNode* TreeMapImpl::findMin(Node* node) return node; } -// NON_MATCHING: this version matches the LLRB tree implementation and is better optimized +// The compiler barrier preserves the original recursive-result store schedule. template inline TreeMapNode* TreeMapImpl::eraseMin(Node* node) { @@ -462,10 +462,11 @@ inline TreeMapNode* TreeMapImpl::eraseMin(Node* node) if (!isRed(node->mLeft) && !isRed(node->mLeft->mLeft)) node = moveRedLeft(node); - node->mLeft = eraseMin(node->mLeft); + Node* newLeft = eraseMin(node->mLeft); #ifdef MATCHING_HACK_NX_CLANG asm(""); #endif + node->mLeft = newLeft; return fixUp(node); } diff --git a/include/controller/seadControllerMgr.h b/include/controller/seadControllerMgr.h index abf76103..f253efe3 100644 --- a/include/controller/seadControllerMgr.h +++ b/include/controller/seadControllerMgr.h @@ -24,7 +24,7 @@ class ControllerMgr : public CalculateTask class ConstructArg : public TaskConstructArg { public: - ConstructArg() : TaskConstructArg(), mHeapArray() { heap_array = &mHeapArray; } + ConstructArg() : TaskConstructArg() { heap_array = &mHeapArray; } private: HeapArray mHeapArray; diff --git a/include/filedevice/seadFileDeviceMgr.h b/include/filedevice/seadFileDeviceMgr.h index 89c2ece3..f6ca7b41 100644 --- a/include/filedevice/seadFileDeviceMgr.h +++ b/include/filedevice/seadFileDeviceMgr.h @@ -72,7 +72,7 @@ class FileDeviceMgr #elif defined(NNSDK) u8* mRomCache = nullptr; bool mMountedHost = false; - bool mMountedSd = false; + bool mMountedSd; #endif }; diff --git a/include/framework/seadGameFramework.h b/include/framework/seadGameFramework.h index 752db08a..3ba7a7b5 100644 --- a/include/framework/seadGameFramework.h +++ b/include/framework/seadGameFramework.h @@ -7,6 +7,8 @@ namespace sead { +class Thread; + class GameFramework : public Framework { SEAD_RTTI_OVERRIDE(GameFramework, Framework); @@ -42,7 +44,7 @@ class GameFramework : public Framework sead::SafeString mUnk1 = ""; sead::SafeString mUnk2 = ""; sead::SafeString mUnk3 = ""; - [[maybe_unused]] void* mUnk4 = nullptr; // TODO: remove [[maybe_unused]] once mUnk4 is used + Thread* mUnk4 = nullptr; void (*mUnk5)(bool) = nullptr; void (*mUnk6)(bool); }; diff --git a/include/framework/seadMethodTree.h b/include/framework/seadMethodTree.h index 98684972..8e6621f3 100644 --- a/include/framework/seadMethodTree.h +++ b/include/framework/seadMethodTree.h @@ -16,7 +16,7 @@ class CriticalSection; template class IDelegate2; -class MethodTreeNode : public IDisposer, public TTreeNode, public INamable +class MethodTreeNode : public TTreeNode, public INamable, public IDisposer { SEAD_RTTI_BASE(MethodTreeNode) @@ -31,13 +31,13 @@ class MethodTreeNode : public IDisposer, public TTreeNode, publ using PauseEventDelegate = IDelegate2; - // NON_MATCHING: stores for mPauseFlag, mPauseEventDelegate, mUserID - explicit MethodTreeNode(CriticalSection* cs) : TTreeNode(this) + explicit MethodTreeNode(CriticalSection* cs) : TTreeNode(this), INamable("") { - mCriticalSection = cs; mPauseEventDelegate = nullptr; - mUserID = nullptr; + mCriticalSection = cs; mDelegateHolder.construct(sead::Delegate()); + mUserID = nullptr; + mPauseFlag = cPause_None; setPauseFlag(cPause_Both); } @@ -78,7 +78,7 @@ class MethodTreeNode : public IDisposer, public TTreeNode, publ StorageFor mDelegateHolder; mutable CriticalSection* mCriticalSection; [[maybe_unused]] u32 mPriority; - BitFlag32 mPauseFlag; + u32 mPauseFlag; PauseEventDelegate* mPauseEventDelegate; void* mUserID; }; diff --git a/include/mc/seadJobQueue.h b/include/mc/seadJobQueue.h index b3b10143..f23e2320 100644 --- a/include/mc/seadJobQueue.h +++ b/include/mc/seadJobQueue.h @@ -36,9 +36,9 @@ class PerfJobQueue void detachProcessMeter(); private: - Buffer> mBars; + Buffer mBars; Buffer mInts; - MultiProcessMeterBar<1> mProcessMeterBar; + SafeString mProcessMeterBar; }; class JobQueueLock @@ -112,15 +112,13 @@ class JobQueue : public hostio::Node, public INamable CoreIdMask mMask; Event mFinishEvent{true}; SafeArray mGranularity; - SafeArray mCoreEnabled; + SafeArray mCoreEnabled; Atomic mNumDoneJobs = 0; Atomic mStatus = Status::_0; const char* mDescription = "NoName"; -#ifdef SEAD_DEBUG PerfJobQueue mPerf; -#endif }; class FixedSizeJQ : public JobQueue @@ -155,4 +153,7 @@ class FixedSizeJQ : public JobQueue u32 mNumProcessedJobs; bool _230; }; +static_assert(sizeof(PerfJobQueue) == 0x30); +static_assert(sizeof(JobQueue) == 0xB0); +static_assert(sizeof(FixedSizeJQ) == 0xD0); } // namespace sead diff --git a/include/prim/seadDelegateEventSlot.h b/include/prim/seadDelegateEventSlot.h index 666240b8..38293f81 100644 --- a/include/prim/seadDelegateEventSlot.h +++ b/include/prim/seadDelegateEventSlot.h @@ -61,6 +61,8 @@ class DelegateEvent bool mConnectedToDelegateEvent = false; }; + DelegateEvent() {} + virtual ~DelegateEvent() { auto it = mList.begin(); diff --git a/modules/src/basis/seadNew.cpp b/modules/src/basis/seadNew.cpp index 1ae07c67..a983ed0d 100644 --- a/modules/src/basis/seadNew.cpp +++ b/modules/src/basis/seadNew.cpp @@ -26,15 +26,7 @@ void* NewImpl(Heap* heap, size_t size, s32 alignment, bool abortOnFailure) } } - void* result = heap->tryAlloc(size, alignment); - if (!result && abortOnFailure) - { - SEAD_ASSERT_MSG( - false, "alloc failed. size: %zu, allocatable size: %zu, alignment: %d, heap: %s", size, - heap->getMaxAllocatableSize(alignment), alignment, heap->getName().cstr()); - return nullptr; - } - return result; + return heap->tryAlloc(size, alignment); } void DeleteImpl(void* ptr) diff --git a/modules/src/container/seadPtrArray.cpp b/modules/src/container/seadPtrArray.cpp index 87ea5435..a499b497 100644 --- a/modules/src/container/seadPtrArray.cpp +++ b/modules/src/container/seadPtrArray.cpp @@ -93,10 +93,10 @@ void PtrArrayImpl::erase(s32 pos, s32 count) mPtrNum -= count; } -// NON_MATCHING: semantically equivalent void PtrArrayImpl::reverse() { - for (s32 i = 0; i < mPtrNum / 2; ++i) + const s32 half = mPtrNum / 2; + for (s32 i = 0; i < half; ++i) swap(mPtrNum - i - 1, i); } @@ -145,8 +145,43 @@ bool PtrArrayImpl::checkInsert(s32 pos, s32 num) void PtrArrayImpl::sort(CompareCallbackImpl cmp) { - // Note: Nintendo did not use - std::sort(mPtrs, mPtrs + size(), [&](const void* a, const void* b) { return cmp(a, b) < 0; }); + if (mPtrNum < 2) + return; + + void** ptrs = mPtrs; + s32 begin = 0; + s32 end = mPtrNum - 1; + do + { + s32 last = begin; + for (s32 i = begin; i < end; ++i) + { + if (cmp(ptrs[i], ptrs[i + 1]) > 0) + { + void* tmp = ptrs[i + 1]; + ptrs[i + 1] = ptrs[i]; + ptrs[i] = tmp; + last = i; + } + } + + end = last; + if (begin == end) + break; + + last = end; + for (s32 i = end; i > begin; --i) + { + if (cmp(ptrs[i], ptrs[i - 1]) < 0) + { + void* tmp = ptrs[i - 1]; + ptrs[i - 1] = ptrs[i]; + ptrs[i] = tmp; + last = i; + } + } + begin = last; + } while (begin != end); } // TODO: PtrArrayImpl::heapSort diff --git a/modules/src/container/seadTreeNode.cpp b/modules/src/container/seadTreeNode.cpp index 7779662e..89c13a0d 100644 --- a/modules/src/container/seadTreeNode.cpp +++ b/modules/src/container/seadTreeNode.cpp @@ -78,34 +78,18 @@ void TreeNode::detachSubTree() TreeNode* TreeNode::findRoot() { - if (!mParent) - return this; - - TreeNode* p = mParent; - TreeNode* root; - do - { - root = p; - SEAD_ASSERT(p != this); - p = p->mParent; - } while (p); - return root; + TreeNode* node = this; + while (node->mParent) + node = node->mParent; + return node; } const TreeNode* TreeNode::findRoot() const { - if (!mParent) - return this; - - TreeNode* p = mParent; - TreeNode* root; - do - { - root = p; - SEAD_ASSERT(p != this); - p = p->mParent; - } while (p); - return root; + const TreeNode* node = this; + while (node->mParent) + node = node->mParent; + return node; } void TreeNode::insertAfterSelf(TreeNode* node) diff --git a/modules/src/controller/seadControllerMgr.cpp b/modules/src/controller/seadControllerMgr.cpp index 2ab8039f..c7df3150 100644 --- a/modules/src/controller/seadControllerMgr.cpp +++ b/modules/src/controller/seadControllerMgr.cpp @@ -10,7 +10,6 @@ namespace sead { SEAD_TASK_SINGLETON_IMPL(ControllerMgr) -// NON_MATCHING: storing too much 00s into stack (for ConstructArg) ControllerMgr::ControllerMgr() : CalculateTask(ConstructArg(), "sead::ControllerMgr") { mDevices.initOffset(offsetof(ControlDevice, mListNode)); @@ -67,15 +66,11 @@ void ControllerMgr::initializeDefault(Heap* heap) void ControllerMgr::finalizeDefault() { #ifdef NNSDK - // NON_MATCHING: missing cbz instruction within loop - for (auto& device : mDevices) + ControlDevice* device = getControlDevice(ControllerDefine::DeviceId(13)); + if (device) { - if (device.getId() == 13) - { - mDevices.erase(&device); - delete &device; - break; - } + mDevices.erase(device); + delete device; } #endif // cafe diff --git a/modules/src/filedevice/nin/seadNinFileDeviceBaseNin.cpp b/modules/src/filedevice/nin/seadNinFileDeviceBaseNin.cpp index 4caeab51..eb1c8641 100644 --- a/modules/src/filedevice/nin/seadNinFileDeviceBaseNin.cpp +++ b/modules/src/filedevice/nin/seadNinFileDeviceBaseNin.cpp @@ -24,7 +24,9 @@ NinFileDeviceBase::NinFileDeviceBase(const SafeString& name, const SafeString& m { } -// NON_MATCHING: inverted branching for should_set_size +// NON_MATCHING: every instruction matches except retail uses CBZ w8 for the is-file test while LLVM +// selects TBZ w8,#0. Signedness and source-branch inversion emitted identical code and were reverted; +// next hypothesis is the original integer/range-producing helper that prevents bit-test folding. FileDevice* NinFileDeviceBase::doOpen_(FileHandle* handle, const SafeString& path, FileDevice::FileOpenFlag flag) { @@ -64,14 +66,14 @@ FileDevice* NinFileDeviceBase::doOpen_(FileHandle* handle, const SafeString& pat return nullptr; } - should_set_size = flag == cFileOpenFlag_Create || !is_file; - if (flag == cFileOpenFlag_Create || !is_file) + if (flag == cFileOpenFlag_Create) { if (is_file) { mLastError = nn::fs::ResultPathAlreadyExists(); return nullptr; } + const auto create_result = nn::fs::CreateFile(fs_path.cstr(), 0); if (create_result.IsFailure()) { @@ -83,6 +85,27 @@ FileDevice* NinFileDeviceBase::doOpen_(FileHandle* handle, const SafeString& pat return nullptr; } } + else + { + if (is_file) + { + should_set_size = false; + } + else + { + const auto create_result = nn::fs::CreateFile(fs_path.cstr(), 0); + if (create_result.IsFailure()) + { + SEAD_WARN( + "nn::fs::CreateFile failed. module = %d desc = %d inner_value = 0x%08x " + "path = %s", + create_result.GetModule(), create_result.GetDescription(), + create_result.GetInnerValueForDebug(), fs_path.cstr()); + mLastError = create_result; + return nullptr; + } + } + } } auto* handle_inner = getFileHandleInner_(handle, true); diff --git a/modules/src/filedevice/seadArchiveFileDevice.cpp b/modules/src/filedevice/seadArchiveFileDevice.cpp index 7b9bc1f2..94d9431f 100644 --- a/modules/src/filedevice/seadArchiveFileDevice.cpp +++ b/modules/src/filedevice/seadArchiveFileDevice.cpp @@ -184,7 +184,7 @@ u8* ArchiveFileDevice::doLoadWithEntryID_(s32 entry_id, LoadArg& arg) if (!buffer) { const s32 aligment_sign = Mathi::sign(arg.alignment); - const s32 alignment = std::max(Mathi::abs(arg.alignment), 32); + const s32 alignment = Mathi::abs(arg.alignment) > 32 ? Mathi::abs(arg.alignment) : 32; buffer = new (arg.heap, alignment * aligment_sign) u8[buffer_size]; buffer_allocated = true; } @@ -199,8 +199,8 @@ u8* ArchiveFileDevice::doLoadWithEntryID_(s32 entry_id, LoadArg& arg) } arg.read_size = bytes_read; - arg.need_unload = buffer_allocated; arg.roundup_size = buffer_size; + arg.need_unload = buffer_allocated; return buffer; } diff --git a/modules/src/filedevice/seadFileDevice.cpp b/modules/src/filedevice/seadFileDevice.cpp index 30459447..f1bceedc 100644 --- a/modules/src/filedevice/seadFileDevice.cpp +++ b/modules/src/filedevice/seadFileDevice.cpp @@ -268,7 +268,7 @@ u8* FileDevice::doLoad_(LoadArg& arg) { const s32 sign = (arg.alignment < 0) ? -1 : 1; s32 alignment = Mathi::abs(arg.alignment); - alignment = sign * ((alignment < cBufferMinAlignment) ? cBufferMinAlignment : alignment); + alignment = sign * ((alignment > cBufferMinAlignment) ? alignment : cBufferMinAlignment); Heap* heap = arg.heap; if (!heap) diff --git a/modules/src/filedevice/seadFileDeviceMgr.cpp b/modules/src/filedevice/seadFileDeviceMgr.cpp index 7af51f9a..443775d5 100644 --- a/modules/src/filedevice/seadFileDeviceMgr.cpp +++ b/modules/src/filedevice/seadFileDeviceMgr.cpp @@ -339,19 +339,9 @@ bool FileDeviceMgr::trySave(FileDevice::SaveArg& arg) } #ifdef NNSDK -void FileDeviceMgr::mountSaveDataForDebug(Heap*) -{ - const auto result = nn::fs::MountSaveDataForDebug("save"); - SEAD_ASSERT_MSG( - result.IsSuccess(), - "nn::fs::MountSaveDataForDebug() failed. module = %d desc = %d innervalue = 0x%08x", - result.GetModule(), result.GetDescription(), result.GetInnerValueForDebug()); -} +void FileDeviceMgr::mountSaveDataForDebug(Heap*) {} -void FileDeviceMgr::unmountSaveDataForDebug() -{ - nn::fs::Unmount("save"); -} +void FileDeviceMgr::unmountSaveDataForDebug() {} #endif #ifdef cafe diff --git a/modules/src/filedevice/seadPath.cpp b/modules/src/filedevice/seadPath.cpp index 7dcac9e8..d6f92162 100644 --- a/modules/src/filedevice/seadPath.cpp +++ b/modules/src/filedevice/seadPath.cpp @@ -49,15 +49,16 @@ char getLastChar(const SafeString& str) } } // namespace -// NON_MATCHING: redundant checks for dot_index < 0 in SafeString::getPart() are optimized out +// NON_MATCHING: Exact size and repeated getPart guards are restored with an unsigned index. +// Search-loop register lifetimes and final slice formation still differ. bool Path::getExt(BufferedSafeString* ext, const SafeString& path) { SEAD_ASSERT_MSG(ext, "destination buffer is null"); ext->trim(0); - const s32 dot_index = rfindCharIndex(path, '.'); - if (dot_index < 0) + const u32 dot_index = rfindCharIndex(path, '.'); + if (dot_index == u32(-1)) return false; if (path.getPart(dot_index).include('/') || path.getPart(dot_index).include('\\')) diff --git a/modules/src/framework/seadFramework.cpp b/modules/src/framework/seadFramework.cpp index ed94c205..9bee9271 100644 --- a/modules/src/framework/seadFramework.cpp +++ b/modules/src/framework/seadFramework.cpp @@ -8,7 +8,7 @@ namespace sead { Framework::CreateSystemTaskArg::CreateSystemTaskArg() - : hostio_parameter(NULL), infloop_detection_span() + : hostio_parameter(nullptr), heap(nullptr), infloop_detection_span(), infloop_unk(0x1000) { } diff --git a/modules/src/framework/seadGameFramework.cpp b/modules/src/framework/seadGameFramework.cpp index de4dfb53..9b8c9562 100644 --- a/modules/src/framework/seadGameFramework.cpp +++ b/modules/src/framework/seadGameFramework.cpp @@ -10,6 +10,7 @@ #include #include #include