From 8436e724aa45bf111d6b98b39d75d6d705fa4b0e Mon Sep 17 00:00:00 2001 From: 2gifts Date: Fri, 25 Sep 2026 21:51:12 -0400 Subject: [PATCH] Match nw4r ut_list, ut_LinkList and ut_binaryFileFormat Co-Authored-By: Claude Opus 5.5 --- config/RSBE01_02/splits.txt | 9 +++ config/RSBE01_02/symbols.txt | 22 +++--- configure.py | 3 + src/nw4r/ut/ut_LinkList.cpp | 54 ++++++++++++++ src/nw4r/ut/ut_binaryFileFormat.cpp | 23 ++++++ src/nw4r/ut/ut_list.cpp | 108 ++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+), 11 deletions(-) create mode 100644 src/nw4r/ut/ut_LinkList.cpp create mode 100644 src/nw4r/ut/ut_binaryFileFormat.cpp create mode 100644 src/nw4r/ut/ut_list.cpp diff --git a/config/RSBE01_02/splits.txt b/config/RSBE01_02/splits.txt index afd89c83d..f1112c332 100644 --- a/config/RSBE01_02/splits.txt +++ b/config/RSBE01_02/splits.txt @@ -337,6 +337,15 @@ sora/st/st_data_container_multi.cpp: sora/st/st_data_container_magic.cpp: .sdata start:0x8059E860 end:0x8059E864 +nw4r/ut/ut_list.cpp: + .text start:0x8015BF9C end:0x8015C238 + +nw4r/ut/ut_LinkList.cpp: + .text start:0x8015C238 end:0x8015C3A4 + +nw4r/ut/ut_binaryFileFormat.cpp: + .text start:0x8015C3A4 end:0x8015C418 + Runtime.PPCEABI.H/__init_cpp_exceptions.cpp: .text start:0x803F1A08 end:0x803F1A78 .ctors start:0x804064E0 end:0x804064E4 rename:.ctors$10 diff --git a/config/RSBE01_02/symbols.txt b/config/RSBE01_02/symbols.txt index fedea1b01..0c902ffee 100644 --- a/config/RSBE01_02/symbols.txt +++ b/config/RSBE01_02/symbols.txt @@ -6521,19 +6521,19 @@ getContainerDataNum__20stDataMultiContainerFUlUl = .text:0x8015BEF4; // type:fun getExtParam__20stDataMultiContainerCFv = .text:0x8015BF78; // type:function size:0xC getVersion__20stDataMultiContainerCFv = .text:0x8015BF84; // type:function size:0xC __sinit_\st_data_container_multi_cpp = .text:0x8015BF90; // type:function size:0xC scope:local -fn_8015BF9C = .text:0x8015BF9C; // type:function size:0x18 -fn_8015BFB4 = .text:0x8015BFB4; // type:function size:0x70 -fn_8015C024 = .text:0x8015C024; // type:function size:0x120 -fn_8015C144 = .text:0x8015C144; // type:function size:0x6C -fn_8015C1B0 = .text:0x8015C1B0; // type:function size:0x20 -fn_8015C1D0 = .text:0x8015C1D0; // type:function size:0x1C -fn_8015C1EC = .text:0x8015C1EC; // type:function size:0x4C -fn_8015C238 = .text:0x8015C238; // type:function size:0x84 -fn_8015C2BC = .text:0x8015C2BC; // type:function size:0x48 -fn_8015C304 = .text:0x8015C304; // type:function size:0x44 +List_Init__Q24nw4r2utFPQ34nw4r2ut4ListUs = .text:0x8015BF9C; // type:function size:0x18 +List_Append__Q24nw4r2utFPQ34nw4r2ut4ListPv = .text:0x8015BFB4; // type:function size:0x70 +List_Insert__Q24nw4r2utFPQ34nw4r2ut4ListPvPv = .text:0x8015C024; // type:function size:0x120 +List_Remove__Q24nw4r2utFPQ34nw4r2ut4ListPv = .text:0x8015C144; // type:function size:0x6C +List_GetNext__Q24nw4r2utFPCQ34nw4r2ut4ListPCv = .text:0x8015C1B0; // type:function size:0x20 +List_GetPrev__Q24nw4r2utFPCQ34nw4r2ut4ListPCv = .text:0x8015C1D0; // type:function size:0x1C +List_GetNth__Q24nw4r2utFPCQ34nw4r2ut4ListUs = .text:0x8015C1EC; // type:function size:0x4C +__dt__Q44nw4r2ut6detail12LinkListImplFv = .text:0x8015C238; // type:function size:0x84 +Erase__Q44nw4r2ut6detail12LinkListImplFQ54nw4r2ut6detail12LinkListImpl8Iterator = .text:0x8015C2BC; // type:function size:0x48 +Clear__Q44nw4r2ut6detail12LinkListImplFv = .text:0x8015C304; // type:function size:0x44 Insert__Q44nw4r2ut6detail12LinkListImplFQ54nw4r2ut6detail12LinkListImpl8IteratorPQ34nw4r2ut12LinkListNode = .text:0x8015C348; // type:function size:0x2C Erase__Q44nw4r2ut6detail12LinkListImplFPQ34nw4r2ut12LinkListNode = .text:0x8015C374; // type:function size:0x30 -fn_8015C3A4 = .text:0x8015C3A4; // type:function size:0x74 +IsValidBinaryFile__Q24nw4r2utFPCQ34nw4r2ut16BinaryFileHeaderUlUsUs = .text:0x8015C3A4; // type:function size:0x74 fn_8015C418 = .text:0x8015C418; // type:function size:0x78 fn_8015C490 = .text:0x8015C490; // type:function size:0x1C fn_8015C4AC = .text:0x8015C4AC; // type:function size:0x1C diff --git a/configure.py b/configure.py index d44984a5b..9f07c57c5 100755 --- a/configure.py +++ b/configure.py @@ -361,6 +361,9 @@ def MatchingFor(*versions): Object(Matching, "sora/st/st_data_container.cpp"), Object(Matching, "sora/st/st_data_container_multi.cpp"), Object(Matching, "sora/st/st_data_container_magic.cpp"), + Object(Matching, "nw4r/ut/ut_list.cpp", extra_cflags=["-RTTI off"]), + Object(Matching, "nw4r/ut/ut_LinkList.cpp", extra_cflags=["-RTTI off"]), + Object(Matching, "nw4r/ut/ut_binaryFileFormat.cpp", extra_cflags=["-RTTI off"]), ], }, # Common REL units diff --git a/src/nw4r/ut/ut_LinkList.cpp b/src/nw4r/ut/ut_LinkList.cpp new file mode 100644 index 000000000..3605711b6 --- /dev/null +++ b/src/nw4r/ut/ut_LinkList.cpp @@ -0,0 +1,54 @@ +#include + +namespace nw4r { +namespace ut { +namespace detail { + +inline LinkListImpl::Iterator LinkListImpl::Erase(Iterator first, Iterator last) { + LinkListNode* node = first.mNode; + LinkListNode* end = last.mNode; + while (node != end) { + node = Erase(node).mNode; + } + return last; +} + +LinkListImpl::~LinkListImpl() { + Clear(); +} + +LinkListImpl::Iterator LinkListImpl::Erase(Iterator it) { + Iterator next = it; + ++next; + return Erase(it, next); +} + +void LinkListImpl::Clear() { + Erase(GetBeginIter(), GetEndIter()); +} + +LinkListImpl::Iterator LinkListImpl::Insert(Iterator it, LinkListNode* node) { + LinkListNode* next = it.mNode; + LinkListNode* prev = next->mPrev; + node->mNext = next; + node->mPrev = prev; + next->mPrev = node; + prev->mNext = node; + ++mSize; + return Iterator(node); +} + +LinkListImpl::Iterator LinkListImpl::Erase(LinkListNode* node) { + LinkListNode* next = node->GetNext(); + LinkListNode* prev = node->GetPrev(); + next->mPrev = prev; + prev->mNext = next; + --mSize; + node->mNext = nullptr; + node->mPrev = nullptr; + return Iterator(next); +} + +} // namespace detail +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_binaryFileFormat.cpp b/src/nw4r/ut/ut_binaryFileFormat.cpp new file mode 100644 index 000000000..84c7b5c14 --- /dev/null +++ b/src/nw4r/ut/ut_binaryFileFormat.cpp @@ -0,0 +1,23 @@ +#include + +namespace nw4r { +namespace ut { + +bool IsValidBinaryFile(const BinaryFileHeader* pHeader, u32 signature, u16 version, u16 minBlocks) { + if (pHeader->signature != signature) { + return false; + } + if (pHeader->byteOrder != NW4R_BYTEORDER_BIG) { + return false; + } + if (pHeader->version != version) { + return false; + } + if (pHeader->fileSize < sizeof(BinaryFileHeader) + minBlocks * sizeof(BinaryBlockHeader)) { + return false; + } + return pHeader->dataBlocks >= minBlocks; +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_list.cpp b/src/nw4r/ut/ut_list.cpp new file mode 100644 index 000000000..1969eec30 --- /dev/null +++ b/src/nw4r/ut/ut_list.cpp @@ -0,0 +1,108 @@ +#include + +namespace nw4r { +namespace ut { + +void List_Init(List* list, u16 offset) { + list->offset = offset; + list->headObject = nullptr; + list->tailObject = nullptr; + list->numObjects = 0; +} + +static inline void SetFirstObject(List* list, void* object) { // Name unknown + Link* link = NW4R_UT_LIST_GET_LINK(*list, object); + link->prevObject = link->nextObject = nullptr; + list->headObject = object; + list->tailObject = object; + ++list->numObjects; +} + +void List_Append(List* list, void* object) { + if (list->headObject == nullptr) { + SetFirstObject(list, object); + } else { + Link* link = NW4R_UT_LIST_GET_LINK(*list, object); + link->prevObject = list->tailObject; + link->nextObject = nullptr; + NW4R_UT_LIST_GET_LINK(*list, list->tailObject)->nextObject = object; + list->tailObject = object; + ++list->numObjects; + } +} + +inline void List_Prepend(List* list, void* object) { + if (list->headObject == nullptr) { + SetFirstObject(list, object); + } else { + Link* link = NW4R_UT_LIST_GET_LINK(*list, object); + link->prevObject = nullptr; + link->nextObject = list->headObject; + NW4R_UT_LIST_GET_LINK(*list, list->headObject)->prevObject = object; + list->headObject = object; + ++list->numObjects; + } +} + +void List_Insert(List* list, void* target, void* object) { + if (target == nullptr) { + List_Append(list, object); + } else if (target == list->headObject) { + List_Prepend(list, object); + } else { + void* prev = NW4R_UT_LIST_GET_LINK(*list, target)->prevObject; + Link* link = NW4R_UT_LIST_GET_LINK(*list, object); + Link* prevLink = NW4R_UT_LIST_GET_LINK(*list, prev); + link->prevObject = prev; + link->nextObject = target; + prevLink->nextObject = object; + NW4R_UT_LIST_GET_LINK(*list, target)->prevObject = object; + ++list->numObjects; + } +} + +void List_Remove(List* list, void* object) { + Link* link = NW4R_UT_LIST_GET_LINK(*list, object); + if (link->prevObject == nullptr) { + list->headObject = link->nextObject; + } else { + NW4R_UT_LIST_GET_LINK(*list, link->prevObject)->nextObject = link->nextObject; + } + if (link->nextObject == nullptr) { + list->tailObject = link->prevObject; + } else { + NW4R_UT_LIST_GET_LINK(*list, link->nextObject)->prevObject = link->prevObject; + } + link->prevObject = nullptr; + link->nextObject = nullptr; + --list->numObjects; +} + +void* List_GetNext(const List* list, const void* object) { + if (object == nullptr) { + return list->headObject; + } + return NW4R_UT_LIST_GET_LINK(*list, object)->nextObject; +} + +void* List_GetPrev(const List* list, const void* object) { + if (object == nullptr) { + return list->tailObject; + } + return NW4R_UT_LIST_GET_LINK(*list, object)->prevObject; +} + +void* List_GetNth(const List* list, u16 n) { + int index = 0; + void* object = nullptr; + while ((object = List_GetNext(list, object)) != nullptr) { + if (n == index) { + return object; + } + ++index; + } + return nullptr; +} + +} // namespace ut +} // namespace nw4r