From de0d1a7d0be631255df9b2bb8025ad03e880b6f9 Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Thu, 18 Jun 2026 23:46:01 +0200 Subject: [PATCH 1/4] hostio: add `SEAD_HOSTIO_NONVIRTUAL` flag --- include/controller/nin/seadNinJoyNpadDevice.h | 4 ++++ include/hostio/seadHostIONode.h | 2 ++ include/hostio/seadHostIOReflexible.h | 2 ++ include/seadVersion.h | 21 +++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/include/controller/nin/seadNinJoyNpadDevice.h b/include/controller/nin/seadNinJoyNpadDevice.h index 22b7066a..88f18d90 100644 --- a/include/controller/nin/seadNinJoyNpadDevice.h +++ b/include/controller/nin/seadNinJoyNpadDevice.h @@ -31,7 +31,11 @@ class NinJoyNpadDevice : public ControlDevice CriticalSection mCS; }; +#if SEAD_HOSTIO_NONVIRTUAL + static_assert(sizeof(VibrationThread) == 0x290); +#else static_assert(sizeof(VibrationThread) == 0x298); +#endif struct SixAxisState { diff --git a/include/hostio/seadHostIONode.h b/include/hostio/seadHostIONode.h index b3edc0c8..8b61beb1 100644 --- a/include/hostio/seadHostIONode.h +++ b/include/hostio/seadHostIONode.h @@ -8,7 +8,9 @@ namespace sead::hostio class Node : public Reflexible { public: +#if not SEAD_HOSTIO_NONVIRTUAL NodeClassType getNodeClassType() const override { return Reflexible::NodeClassType::Node; } +#endif #ifdef SEAD_DEBUG public: diff --git a/include/hostio/seadHostIOReflexible.h b/include/hostio/seadHostIOReflexible.h index bbb77f14..aa06946e 100644 --- a/include/hostio/seadHostIOReflexible.h +++ b/include/hostio/seadHostIOReflexible.h @@ -26,7 +26,9 @@ class Reflexible : public NodeEventListener Other = 2, }; +#if not SEAD_HOSTIO_NONVIRTUAL virtual NodeClassType getNodeClassType() const { return NodeClassType::Reflexible; } +#endif enum class AllocFlg { diff --git a/include/seadVersion.h b/include/seadVersion.h index 4d0cc607..8430ea44 100644 --- a/include/seadVersion.h +++ b/include/seadVersion.h @@ -5,6 +5,7 @@ #define SEAD_VERSION_SPL3 3 #define SEAD_VERSION_TOTK 4 #define SEAD_VERSION_SMBW 5 +#define SEAD_VERSION_SMM2 6 #define SEAD_VERSION_CUSTOM 0 #ifndef SEAD_VERSION @@ -39,6 +40,8 @@ /// Make most functions in sead::ArchiveRes const /// SEAD_HASHCRC_WITHCONTEXT: /// Add calcHashWithContext and calcStringHashWithContext to HashCRC16/32 +/// SEAD_HOSTIO_NONVIRTUAL: +/// Removes getNodeClassType() and the vtable from hostio::Reflexible and ::Node #if SEAD_VERSION == SEAD_VERSION_BOTW #define SEAD_SAFESTRING_NONVIRTUAL 0 @@ -54,6 +57,7 @@ #define SEAD_ARCHIVERES_ISEXISTFILEIMPL 1 #define SEAD_ARCHIVERES_ISCONST 1 #define SEAD_HASHCRC_WITHCONTEXT 1 +#define SEAD_HOSTIO_NONVIRTUAL 0 #elif SEAD_VERSION == SEAD_VERSION_SMO #define SEAD_SAFESTRING_NONVIRTUAL 0 #define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 @@ -68,6 +72,7 @@ #define SEAD_ARCHIVERES_ISEXISTFILEIMPL 0 #define SEAD_ARCHIVERES_ISCONST 0 #define SEAD_HASHCRC_WITHCONTEXT 0 +#define SEAD_HOSTIO_NONVIRTUAL 0 #elif SEAD_VERSION == SEAD_VERSION_SPL3 or SEAD_VERSION == SEAD_VERSION_TOTK or \ SEAD_VERSION == SEAD_VERSION_SMBW #define SEAD_SAFESTRING_NONVIRTUAL 1 @@ -83,6 +88,22 @@ #define SEAD_ARCHIVERES_ISEXISTFILEIMPL 1 #define SEAD_ARCHIVERES_ISCONST 1 #define SEAD_HASHCRC_WITHCONTEXT 1 +#define SEAD_HOSTIO_NONVIRTUAL 0 +#elif SEAD_VERSION == SEAD_VERSION_SMM2 +#define SEAD_SAFESTRING_NONVIRTUAL 0 // TODO: figure this out +#define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 // TODO: figure this out +#define SEAD_CRITICALSECTION_PURE 0 +#define SEAD_THREADMGR_MOVED_SINGLETON_DISPOSER 0 // TODO: figure this out +#define SEAD_HEAP_FREEANDGETALLOCATABLESIZE_VIRTUAL 0 // TODO: figure this out +#define SEAD_RTTI_CHECKDERIVEDRUNTIMETYPEINFO_RETURNS_INSTANCE 0 // TODO: figure this out +#define SEAD_THREAD_GETFIBER 0 // TODO: figure this out +#define SEAD_DELEGATE_ISNODUMMY 1 // TODO: figure this out +#define SEAD_FRAMEBUFFER_BINDCLEAR_UNBIND 0 // TODO: figure this out +#define SEAD_ARCHIVERES_TRYGETFILEPATH 0 // TODO: figure this out +#define SEAD_ARCHIVERES_ISEXISTFILEIMPL 1 // TODO: figure this out +#define SEAD_ARCHIVERES_ISCONST 1 // TODO: figure this out +#define SEAD_HASHCRC_WITHCONTEXT 1 // TODO: figure this out +#define SEAD_HOSTIO_NONVIRTUAL 1 #endif /// feature-specific macros From 6df116757c1f1de0833205e50666d08363a241db Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Fri, 19 Jun 2026 00:00:45 +0200 Subject: [PATCH 2/4] heap: add flag to fix two bugs on `FindContainHeapCache` --- include/seadVersion.h | 6 ++++++ include/thread/seadThread.h | 17 +++++++++++++++++ modules/src/heap/seadHeapMgr.cpp | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/include/seadVersion.h b/include/seadVersion.h index 8430ea44..7bc4b956 100644 --- a/include/seadVersion.h +++ b/include/seadVersion.h @@ -42,6 +42,8 @@ /// Add calcHashWithContext and calcStringHashWithContext to HashCRC16/32 /// SEAD_HOSTIO_NONVIRTUAL: /// Removes getNodeClassType() and the vtable from hostio::Reflexible and ::Node +/// SEAD_FINDCONTAINHEAPCACHE_FIXED: +/// Fixes two bugs on FindContainHeapCache (incomplete locks and 64-bit pointers) #if SEAD_VERSION == SEAD_VERSION_BOTW #define SEAD_SAFESTRING_NONVIRTUAL 0 @@ -58,6 +60,7 @@ #define SEAD_ARCHIVERES_ISCONST 1 #define SEAD_HASHCRC_WITHCONTEXT 1 #define SEAD_HOSTIO_NONVIRTUAL 0 +#define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 #elif SEAD_VERSION == SEAD_VERSION_SMO #define SEAD_SAFESTRING_NONVIRTUAL 0 #define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 @@ -73,6 +76,7 @@ #define SEAD_ARCHIVERES_ISCONST 0 #define SEAD_HASHCRC_WITHCONTEXT 0 #define SEAD_HOSTIO_NONVIRTUAL 0 +#define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 #elif SEAD_VERSION == SEAD_VERSION_SPL3 or SEAD_VERSION == SEAD_VERSION_TOTK or \ SEAD_VERSION == SEAD_VERSION_SMBW #define SEAD_SAFESTRING_NONVIRTUAL 1 @@ -89,6 +93,7 @@ #define SEAD_ARCHIVERES_ISCONST 1 #define SEAD_HASHCRC_WITHCONTEXT 1 #define SEAD_HOSTIO_NONVIRTUAL 0 +#define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 #elif SEAD_VERSION == SEAD_VERSION_SMM2 #define SEAD_SAFESTRING_NONVIRTUAL 0 // TODO: figure this out #define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 // TODO: figure this out @@ -104,6 +109,7 @@ #define SEAD_ARCHIVERES_ISCONST 1 // TODO: figure this out #define SEAD_HASHCRC_WITHCONTEXT 1 // TODO: figure this out #define SEAD_HOSTIO_NONVIRTUAL 1 +#define SEAD_FINDCONTAINHEAPCACHE_FIXED 1 #endif /// feature-specific macros diff --git a/include/thread/seadThread.h b/include/thread/seadThread.h index c635f19a..2202e71c 100644 --- a/include/thread/seadThread.h +++ b/include/thread/seadThread.h @@ -155,6 +155,22 @@ class ThreadMgr : public hostio::Node CriticalSection* getListCS() { return &mListCS; } +#if SEAD_FINDCONTAINHEAPCACHE_FIXED + bool tryRemoveFromFindContainHeapCache(Heap* heap) + { + ScopedLock lock(getListCS()); + const auto end = mList.end(); + bool found = false; + for (auto it = mList.begin(); it != end; ++it) + { + bool result = !(*it)->getFindContainHeapCache()->tryRemoveHeap(heap); + found |= result; + if (found) + break; + } + return found; + } +#else bool tryRemoveFromFindContainHeapCache(Heap* heap) { const auto end = mList.end(); @@ -169,6 +185,7 @@ class ThreadMgr : public hostio::Node } return found; } +#endif #ifdef SEAD_DEBUG void initHostIO(); diff --git a/modules/src/heap/seadHeapMgr.cpp b/modules/src/heap/seadHeapMgr.cpp index f388a493..3adfdd59 100644 --- a/modules/src/heap/seadHeapMgr.cpp +++ b/modules/src/heap/seadHeapMgr.cpp @@ -195,6 +195,10 @@ bool FindContainHeapCache::tryRemoveHeap(Heap* heap) uintptr_t original; if (mHeap.compareExchange(uintptr_t(heap), 0, &original)) return true; +#if SEAD_FINDCONTAINHEAPCACHE_FIXED + return (original & ~1ul) != uintptr_t(heap); +#else return (original & ~1u) != uintptr_t(heap); +#endif } } // namespace sead From 25894e2c1eadc85c58328b832a198841c4473df5 Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Fri, 19 Jun 2026 00:06:35 +0200 Subject: [PATCH 3/4] thread: add version flag for reloading affinity from member --- include/seadVersion.h | 6 ++++++ modules/src/thread/nin/seadThreadNin.cpp | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/include/seadVersion.h b/include/seadVersion.h index 7bc4b956..1bfcca6c 100644 --- a/include/seadVersion.h +++ b/include/seadVersion.h @@ -44,6 +44,8 @@ /// Removes getNodeClassType() and the vtable from hostio::Reflexible and ::Node /// SEAD_FINDCONTAINHEAPCACHE_FIXED: /// Fixes two bugs on FindContainHeapCache (incomplete locks and 64-bit pointers) +/// SEAD_THREAD_SETAFFINITY_RELOAD: +/// Store new affinity into member, then reload instead of reusing parameter #if SEAD_VERSION == SEAD_VERSION_BOTW #define SEAD_SAFESTRING_NONVIRTUAL 0 @@ -61,6 +63,7 @@ #define SEAD_HASHCRC_WITHCONTEXT 1 #define SEAD_HOSTIO_NONVIRTUAL 0 #define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 +#define SEAD_THREAD_SETAFFINITY_RELOAD 1 #elif SEAD_VERSION == SEAD_VERSION_SMO #define SEAD_SAFESTRING_NONVIRTUAL 0 #define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 @@ -77,6 +80,7 @@ #define SEAD_HASHCRC_WITHCONTEXT 0 #define SEAD_HOSTIO_NONVIRTUAL 0 #define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 +#define SEAD_THREAD_SETAFFINITY_RELOAD 1 #elif SEAD_VERSION == SEAD_VERSION_SPL3 or SEAD_VERSION == SEAD_VERSION_TOTK or \ SEAD_VERSION == SEAD_VERSION_SMBW #define SEAD_SAFESTRING_NONVIRTUAL 1 @@ -94,6 +98,7 @@ #define SEAD_HASHCRC_WITHCONTEXT 1 #define SEAD_HOSTIO_NONVIRTUAL 0 #define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 +#define SEAD_THREAD_SETAFFINITY_RELOAD 1 #elif SEAD_VERSION == SEAD_VERSION_SMM2 #define SEAD_SAFESTRING_NONVIRTUAL 0 // TODO: figure this out #define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 // TODO: figure this out @@ -110,6 +115,7 @@ #define SEAD_HASHCRC_WITHCONTEXT 1 // TODO: figure this out #define SEAD_HOSTIO_NONVIRTUAL 1 #define SEAD_FINDCONTAINHEAPCACHE_FIXED 1 +#define SEAD_THREAD_SETAFFINITY_RELOAD 0 #endif /// feature-specific macros diff --git a/modules/src/thread/nin/seadThreadNin.cpp b/modules/src/thread/nin/seadThreadNin.cpp index d80463fc..1f785730 100644 --- a/modules/src/thread/nin/seadThreadNin.cpp +++ b/modules/src/thread/nin/seadThreadNin.cpp @@ -112,8 +112,13 @@ s32 Thread::getPriority() const void Thread::setAffinity(const CoreIdMask& affinity) { +#if SEAD_THREAD_SETAFFINITY_RELOAD mAffinity = affinity; u64 mask = mAffinity; +#else + u64 mask = affinity; + mAffinity = affinity; +#endif const auto available_mask = nn::os::GetThreadAvailableCoreMask(); SEAD_ASSERT_MSG((~u32(available_mask) & mask) == 0, "invalid core mask. ( mask = %ld )", mask); nn::os::SetThreadCoreMask(mThreadInner, -1, mask); From e48b5626ec80ecb91edf5fb1530892c6c276df28 Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Fri, 19 Jun 2026 00:36:02 +0200 Subject: [PATCH 4/4] clang-format --- include/seadVersion.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/seadVersion.h b/include/seadVersion.h index 1bfcca6c..e485907c 100644 --- a/include/seadVersion.h +++ b/include/seadVersion.h @@ -100,19 +100,19 @@ #define SEAD_FINDCONTAINHEAPCACHE_FIXED 0 #define SEAD_THREAD_SETAFFINITY_RELOAD 1 #elif SEAD_VERSION == SEAD_VERSION_SMM2 -#define SEAD_SAFESTRING_NONVIRTUAL 0 // TODO: figure this out +#define SEAD_SAFESTRING_NONVIRTUAL 0 // TODO: figure this out #define SEAD_RESOURCEMGR_TRYCREATE_NO_FACTORY_NAME 0 // TODO: figure this out #define SEAD_CRITICALSECTION_PURE 0 -#define SEAD_THREADMGR_MOVED_SINGLETON_DISPOSER 0 // TODO: figure this out -#define SEAD_HEAP_FREEANDGETALLOCATABLESIZE_VIRTUAL 0 // TODO: figure this out +#define SEAD_THREADMGR_MOVED_SINGLETON_DISPOSER 0 // TODO: figure this out +#define SEAD_HEAP_FREEANDGETALLOCATABLESIZE_VIRTUAL 0 // TODO: figure this out #define SEAD_RTTI_CHECKDERIVEDRUNTIMETYPEINFO_RETURNS_INSTANCE 0 // TODO: figure this out -#define SEAD_THREAD_GETFIBER 0 // TODO: figure this out -#define SEAD_DELEGATE_ISNODUMMY 1 // TODO: figure this out -#define SEAD_FRAMEBUFFER_BINDCLEAR_UNBIND 0 // TODO: figure this out -#define SEAD_ARCHIVERES_TRYGETFILEPATH 0 // TODO: figure this out -#define SEAD_ARCHIVERES_ISEXISTFILEIMPL 1 // TODO: figure this out -#define SEAD_ARCHIVERES_ISCONST 1 // TODO: figure this out -#define SEAD_HASHCRC_WITHCONTEXT 1 // TODO: figure this out +#define SEAD_THREAD_GETFIBER 0 // TODO: figure this out +#define SEAD_DELEGATE_ISNODUMMY 1 // TODO: figure this out +#define SEAD_FRAMEBUFFER_BINDCLEAR_UNBIND 0 // TODO: figure this out +#define SEAD_ARCHIVERES_TRYGETFILEPATH 0 // TODO: figure this out +#define SEAD_ARCHIVERES_ISEXISTFILEIMPL 1 // TODO: figure this out +#define SEAD_ARCHIVERES_ISCONST 1 // TODO: figure this out +#define SEAD_HASHCRC_WITHCONTEXT 1 // TODO: figure this out #define SEAD_HOSTIO_NONVIRTUAL 1 #define SEAD_FINDCONTAINHEAPCACHE_FIXED 1 #define SEAD_THREAD_SETAFFINITY_RELOAD 0