diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 84d009fd..e53f45a2 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -243,6 +243,10 @@ toBeSorted/time_area_mgr.cpp: .sbss start:0x805753C0 end:0x805753D0 .sdata2 start:0x805798D0 end:0x80579928 +toBeSorted/nand_request_thread.cpp: + .text start:0x800BC980 end:0x800BD604 + .data start:0x80510B30 end:0x80510B70 + d/flag/flag_managers.cpp: .text start:0x800BD8C0 end:0x800C0650 .data start:0x80510B88 end:0x80510D10 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index bafbdc61..5caf17dc 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -4028,35 +4028,35 @@ fn_800BC8A0 = .text:0x800BC8A0; // type:function size:0x50 fn_800BC8F0 = .text:0x800BC8F0; // type:function size:0x24 fn_800BC920 = .text:0x800BC920; // type:function size:0x8 dTimeArea__sinit = .text:0x800BC930; // type:function size:0x48 -NandRequestThread__ctor = .text:0x800BC980; // type:function size:0xC8 -fn_800BCA50 = .text:0x800BCA50; // type:function size:0x60 -NandRequestThread__start = .text:0x800BCAB0; // type:function size:0x84 -fn_800BCB40 = .text:0x800BCB40; // type:function size:0x84 -fn_800BCBD0 = .text:0x800BCBD0; // type:function size:0x7C -fn_800BCC50 = .text:0x800BCC50; // type:function size:0x7C -NandRequestThread__waitForMessage = .text:0x800BCCD0; // type:function size:0x38 -NandRequestThread__sendMsg = .text:0x800BCD10; // type:function size:0x10 -NandRequestThread__enqueueRequest = .text:0x800BCD20; // type:function size:0x58 -NandRequestThread__popReadCmd = .text:0x800BCD80; // type:function size:0xBC -fn_800BCE40 = .text:0x800BCE40; // type:function size:0x78 -allocateNandRequestMaybe = .text:0x800BCEC0; // type:function size:0x20 -fn_800BCEE0 = .text:0x800BCEE0; // type:function size:0x1C -fn_800BCF00 = .text:0x800BCF00; // type:function size:0x8 -fn_800BCF10 = .text:0x800BCF10; // type:function size:0x34 -fn_800BCF50 = .text:0x800BCF50; // type:function size:0x40 -fn_800BCF90 = .text:0x800BCF90; // type:function size:0xE4 -fn_800BD080 = .text:0x800BD080; // type:function size:0x50 -fn_800BD0D0 = .text:0x800BD0D0; // type:function size:0x16C -fn_800BD240 = .text:0x800BD240; // type:function size:0xE8 -fn_800BD330 = .text:0x800BD330; // type:function size:0xE0 -fn_800BD410 = .text:0x800BD410; // type:function size:0x1C -fn_800BD430 = .text:0x800BD430; // type:function size:0x18 -fn_800BD450 = .text:0x800BD450; // type:function size:0x60 -fn_800BD4B0 = .text:0x800BD4B0; // type:function size:0x5C -fn_800BD510 = .text:0x800BD510; // type:function size:0xC -fn_800BD520 = .text:0x800BD520; // type:function size:0x5C -fn_800BD580 = .text:0x800BD580; // type:function size:0x5C -fn_800BD5E0 = .text:0x800BD5E0; // type:function size:0xC +__ct__17NandRequestThreadFiPQ23EGG4HeapPvUlPvPQ23EGG4Heap = .text:0x800BC980; // type:function size:0xC8 +__dt__17NandRequestThreadFv = .text:0x800BCA50; // type:function size:0x60 +run__17NandRequestThreadFv = .text:0x800BCAB0; // type:function size:0x84 +checkRequest__17NandRequestThreadFUlUl = .text:0x800BCB40; // type:function size:0x84 +createRequest__17NandRequestThreadFPCcUcUc = .text:0x800BCBD0; // type:function size:0x7C +writeRequest__17NandRequestThreadFPCcPvUl = .text:0x800BCC50; // type:function size:0x7C +waitForMessage__17NandRequestThreadFv = .text:0x800BCCD0; // type:function size:0x38 +sendMessage__17NandRequestThreadFv = .text:0x800BCD10; // type:function size:0x10 +enqueueRequest__17NandRequestThreadFP11NandRequest = .text:0x800BCD20; // type:function size:0x58 +dequeueRequest__17NandRequestThreadFv = .text:0x800BCD80; // type:function size:0xBC +create__17NandRequestThreadFiPQ23EGG4HeapPvUlPvPQ23EGG4Heap = .text:0x800BCE40; // type:function size:0x78 +__nw__11NandRequestFUl = .text:0x800BCEC0; // type:function size:0x20 +free__11NandRequestFP11NandRequest = .text:0x800BCEE0; // type:function size:0x1C +getStatus__11NandRequestCFv = .text:0x800BCF00; // type:function size:0x8 +__ct__16NandRequestCheckFUlUl = .text:0x800BCF10; // type:function size:0x34 +execute__16NandRequestCheckFv = .text:0x800BCF50; // type:function size:0x40 +__ct__17NandRequestCreateFPCcUcUc = .text:0x800BCF90; // type:function size:0xE4 +splitComponent__FPCcPcUl = .text:0x800BD080; // type:function size:0x50 +execute__17NandRequestCreateFv = .text:0x800BD0D0; // type:function size:0x16C +__ct__16NandRequestWriteFPCcPvUl = .text:0x800BD240; // type:function size:0xE8 +execute__16NandRequestWriteFv = .text:0x800BD330; // type:function size:0xE0 +isCompleted__21NandRequestHolderBaseCFv = .text:0x800BD410; // type:function size:0x1C +getStatus__21NandRequestHolderBaseCFv = .text:0x800BD430; // type:function size:0x18 +runToCompletion__21NandRequestHolderBaseFv = .text:0x800BD450; // type:function size:0x60 +check__22NandRequestCheckHolderFUlUl = .text:0x800BD4B0; // type:function size:0x5C +getCheckResult__22NandRequestCheckHolderFv = .text:0x800BD510; // type:function size:0xC +create__23NandRequestCreateHolderFPCcUcUc = .text:0x800BD520; // type:function size:0x5C +write__22NandRequestWriteHolderFPCcPvUl = .text:0x800BD580; // type:function size:0x5C +failedWrite__22NandRequestWriteHolderFv = .text:0x800BD5E0; // type:function size:0xC onExit__Q23EGG6ThreadFv = .text:0x800BD5F0; // type:function size:0x4 onEnter__Q23EGG6ThreadFv = .text:0x800BD600; // type:function size:0x4 fn_800BD610 = .text:0x800BD610; // type:function size:0x34 @@ -31009,10 +31009,10 @@ someVtable = .data:0x80510A78; // type:object size:0x30 lbl_80510AA8 = .data:0x80510AA8; // type:object size:0x30 lbl_80510AD8 = .data:0x80510AD8; // type:object size:0x2C lbl_80510B04 = .data:0x80510B04; // type:object size:0x2C -NandRequestThread__vtable = .data:0x80510B30; // type:object size:0x18 -lbl_80510B48 = .data:0x80510B48; // type:object size:0xC -lbl_80510B54 = .data:0x80510B54; // type:object size:0xC -lbl_80510B60 = .data:0x80510B60; // type:object size:0x10 +__vt__17NandRequestThread = .data:0x80510B30; // type:object size:0x18 +__vt__16NandRequestWrite = .data:0x80510B48; // type:object size:0xC +__vt__17NandRequestCreate = .data:0x80510B54; // type:object size:0xC +__vt__16NandRequestCheck = .data:0x80510B60; // type:object size:0xC lbl_80510B70 = .data:0x80510B70; // type:object size:0x18 __vt__32MyFlagManager<15ItemflagManager> = .data:0x80510B88; // type:object size:0x3C scope:weak __vt__33MyFlagManager<16StoryflagManager> = .data:0x80510BC4; // type:object size:0x3C scope:weak @@ -40069,7 +40069,7 @@ lbl_805753BC = .sbss:0x805753BC; // type:object size:0x4 data:4byte sInstance__14dTimeAreaMgr_c = .sbss:0x805753C0; // type:object size:0x4 data:4byte TIMESHIFT_TRANSITION_BORDER_COLOR = .sbss:0x805753C4; // type:object size:0x1 data:byte CURR_TIMESHIFT_STONE_ACTIVE = .sbss:0x805753C8; // type:object size:0x8 data:4byte -NAND_REQUEST_THREAD = .sbss:0x805753D0; // type:object size:0x8 data:4byte +sInstance__17NandRequestThread = .sbss:0x805753D0; // type:object size:0x8 data:4byte lbl_805753D8 = .sbss:0x805753D8; // type:object size:0x8 data:4byte sInstance__16SceneflagManager = .sbss:0x805753E0; // type:object size:0x4 data:4byte sTempFlags__16SceneflagManager = .sbss:0x805753E8; // type:object size:0x8 diff --git a/configure.py b/configure.py index ed55ef46..11790704 100644 --- a/configure.py +++ b/configure.py @@ -364,6 +364,7 @@ config.libs = [ Object(NonMatching, "toBeSorted/attention.cpp"), Object(NonMatching, "toBeSorted/dowsing_target.cpp"), Object(NonMatching, "toBeSorted/time_area_mgr.cpp"), + Object(NonMatching, "toBeSorted/nand_request_thread.cpp"), Object(Matching, "toBeSorted/save_file.cpp"), Object(Matching, "toBeSorted/counters/counter.cpp"), Object(Matching, "toBeSorted/counters/rupee_counter.cpp"), diff --git a/include/egg/core/eggThread.h b/include/egg/core/eggThread.h index 9b6c4564..87b56ab9 100644 --- a/include/egg/core/eggThread.h +++ b/include/egg/core/eggThread.h @@ -28,7 +28,7 @@ public: /* 0x38 */ u32 mStackSize; /* 0x3C */ Heap *mAllocatableHeap; // TODO from the usage in eggThread this really looks like - // it's stashed thread that's restored when switching threads + // it's a stashed heap that's restored when switching threads /* 0x40 */ Heap *mCurrentHeap; /* 0x44 */ nw4r::ut::Node mLink; diff --git a/include/toBeSorted/nand_request_thread.h b/include/toBeSorted/nand_request_thread.h new file mode 100644 index 00000000..7b96c3fe --- /dev/null +++ b/include/toBeSorted/nand_request_thread.h @@ -0,0 +1,140 @@ +#ifndef NAND_REQUEST_H +#define NAND_REQUEST_H + +#include "common.h" +#include "egg/core/eggHeap.h" +#include "egg/core/eggThread.h" +#include "rvl/NAND/nand.h" +#include "rvl/OS/OSMessage.h" +#include "rvl/OS/OSMutex.h" +#include "sized_string.h" +#include "toBeSorted/tlist.h" + +struct NandRequest { + NandRequest() : mStatus(NAND_RESULT_BUSY), bHandled(false) {} + ~NandRequest() {} + virtual bool execute() = 0; + + /* 0x04 */ TListNode mNode; + /* 0x0C */ NANDResult mStatus; + /* 0x10 */ bool bHandled; + + static void *operator new(size_t size); + static void free(NandRequest *); + + NANDResult getStatus() const; +}; + +struct NandRequestCheck : public NandRequest { + NandRequestCheck(u32 neededBlocks, u32 neededFiles); + + virtual bool execute() override; + + /* 0x14 */ u32 mNeededBlocks; + /* 0x18 */ u32 mNeededFiles; + /* 0x1C */ u32 mResult; +}; + +struct NandRequestCreate : public NandRequest { + NandRequestCreate(const char *filePath, u8 perm, u8 attr); + + virtual bool execute() override; + + // cursed offsets + /* 0x11 */ SizedString<64> mFilePath; + /* 0x51 */ u8 mPerm; + /* 0x52 */ u8 mAttr; +}; + +struct NandRequestWrite : public NandRequest { + NandRequestWrite(const char *str, void *data, size_t dataSize); + + virtual bool execute() override; + + /* 0x11 */ SizedString<64> mFilePath; + /* 0x54 */ void *mData; + /* 0x58 */ size_t mDataSize; + /* 0x5C */ bool mFailedWrite; +}; + +struct NandRequestHolderBase { + NandRequestHolderBase(NandRequest *req) : mpRequest(req) {} + NandRequest *mpRequest; + + bool isCompleted() const; + NANDResult getStatus() const; + bool runToCompletion(); +}; + +struct NandRequestCheckHolder : public NandRequestHolderBase { + NandRequestCheckHolder(NandRequestCheck *req) : NandRequestHolderBase(req) {} + + bool check(u32 neededBlocks, u32 neededFiles); + u32 getCheckResult(); +}; + +struct NandRequestCreateHolder : public NandRequestHolderBase { + NandRequestCreateHolder(NandRequestCreate *req) : NandRequestHolderBase(req) {} + + bool create(const char *filePath, u8 perm, u8 attr); +}; + +struct NandRequestWriteHolder : public NandRequestHolderBase { + NandRequestWriteHolder(NandRequestWrite *req) : NandRequestHolderBase(req) {} + bool failedWrite(); + + bool write(const char *filePath, void *data, size_t dataSize); +}; + +class NandRequestThread : EGG::Thread { + friend NandRequest; + +public: + NandRequestThread( + int priority, EGG::Heap *commandHeap, void *bufFromGameHeap, size_t bufSize, void *mThreadArg, EGG::Heap *heap + ); + virtual ~NandRequestThread(); + + virtual void *run() override; + void enqueueRequest(NandRequest *request); + NandRequest *dequeueRequest(); + + static NandRequestThread *create( + int priority, EGG::Heap *commandHeap, void *bufFromGameHeap, size_t bufSize, void *mThreadArg, EGG::Heap *heap + ); + + static NandRequestThread *getInstance() { + return sInstance; + } + + void *getBuf() { + return mBufFromGameHeap; + } + + size_t getBufSize() { + return mBufSize; + } + + NandRequestCheck *checkRequest(u32 neededBlocks, u32 neededFiles); + NandRequestCreate *createRequest(const char *filePath, u8 perm, u8 attr); + NandRequestWrite *writeRequest(const char *filePath, void *data, size_t dataSize); + +private: + typedef TList NandRequestList; + static NandRequestThread *sInstance; + + bool waitForMessage(); + void sendMessage(); + + u8 field_0x4C[0x368 - 0x4C]; + /* 0x368 */ OSMessageQueue mMessageQueue; + /* 0x388 */ OSMessage mMessageBuffer; + /* 0x38C */ OSMutex mMutex; + /* 0x3A4 */ NandRequestList mRequestList; + /* 0x3B0 */ EGG::Heap *mpCommandHeap; + /* 0x3B4 */ void *mBufFromGameHeap; + /* 0x3B8 */ size_t mBufSize; + /* 0x3BC */ UNKWORD field_0x3BC; +}; + +#endif diff --git a/include/toBeSorted/tlist.h b/include/toBeSorted/tlist.h index bcb6b1ed..3fae072e 100644 --- a/include/toBeSorted/tlist.h +++ b/include/toBeSorted/tlist.h @@ -124,6 +124,16 @@ public: mCount--; } + T* GetFirst() { + return GetPtrFromNode(&mStartEnd); + } + + void RemoveFirst() { + if (mCount != 0) { + remove(GetFirst()); + } + } + TNode mStartEnd; s32 mCount; }; diff --git a/src/toBeSorted/nand_request_thread.cpp b/src/toBeSorted/nand_request_thread.cpp new file mode 100644 index 00000000..ff1ace2f --- /dev/null +++ b/src/toBeSorted/nand_request_thread.cpp @@ -0,0 +1,321 @@ +#include "toBeSorted/nand_request_thread.h" + +#include "common.h" +#include "egg/core/eggAssertHeap.h" // IWYU pragma: export +#include "egg/core/eggThread.h" +#include "m/m_heap.h" +#include "rvl/NAND/NANDCheck.h" +#include "rvl/NAND/NANDCore.h" +#include "rvl/NAND/nand.h" +#include "rvl/OS/OSMessage.h" +#include "rvl/OS/OSMutex.h" +#include "rvl/OS/OSThread.h" + +#include + +extern "C" void fn_802F2920(OSThread *, size_t); + +NandRequestThread::NandRequestThread( + int priority, EGG::Heap *commandHeap, void *bufFromGameHeap, size_t bufSize, void *mThreadArg, EGG::Heap *heap +) + : EGG::Thread(0x4000, 0, priority, heap), mMessageBuffer(nullptr) { + // TODO suffers from TList ctor + sInstance = this; + + mpCommandHeap = commandHeap; + mBufFromGameHeap = bufFromGameHeap; + mBufSize = bufSize; + + setThreadCurrentHeap(mHeap::g_assertHeap); + fn_802F2920(mOSThread, bufSize); + OSInitMessageQueue(&mMessageQueue, &mMessageBuffer, 1); + OSInitMutex(&mMutex); + OSResumeThread(mOSThread); +} + +NandRequestThread::~NandRequestThread() { + sInstance = nullptr; +} + +void *NandRequestThread::run() { + NandRequest *req; + while (waitForMessage()) { + while (mRequestList.mCount != 0) { + req = dequeueRequest(); + req->execute(); + req->bHandled = true; + } + } + return nullptr; +} + +NandRequestCheck *NandRequestThread::checkRequest(u32 neededBlocks, u32 neededFiles) { + NandRequestCheck *req = new NandRequestCheck(neededBlocks, neededFiles); + if (req != nullptr) { + enqueueRequest(req); + } + return req; +} + +NandRequestCreate *NandRequestThread::createRequest(const char *filePath, u8 perm, u8 attr) { + NandRequestCreate *req = new NandRequestCreate(filePath, perm, attr); + if (req != nullptr) { + enqueueRequest(req); + } + return req; +} + +NandRequestWrite *NandRequestThread::writeRequest(const char *filePath, void *data, size_t dataSize) { + NandRequestWrite *req = new NandRequestWrite(filePath, data, dataSize); + if (req != nullptr) { + enqueueRequest(req); + } + return req; +} + +bool NandRequestThread::waitForMessage() { + return OSReceiveMessage(&mMessageQueue, nullptr, OS_MSG_PERSISTENT); +} + +void NandRequestThread::sendMessage() { + OSSendMessage(&mMessageQueue, nullptr, 0); +} + +void NandRequestThread::enqueueRequest(NandRequest *request) { + mRequestList.insert(request); + sendMessage(); +} + +NandRequest *NandRequestThread::dequeueRequest() { + // TODO TList + NandRequest *req = mRequestList.GetFirst(); + + OSLockMutex(&mMutex); + mRequestList.RemoveFirst(); + OSUnlockMutex(&mMutex); + + sendMessage(); + return req; +} + +NandRequestThread *NandRequestThread::create( + int priority, EGG::Heap *commandHeap, void *bufFromGameHeap, size_t bufSize, void *mThreadArg, EGG::Heap *heap +) { + return new (heap, 0x04) NandRequestThread(priority, commandHeap, bufFromGameHeap, bufSize, mThreadArg, heap); +} + +void *NandRequest::operator new(size_t size) { + return NandRequestThread::sInstance->mpCommandHeap->alloc(size, -4); +} + +void NandRequest::free(NandRequest *ptr) { + return NandRequestThread::sInstance->mpCommandHeap->free(ptr); +} + +NANDResult NandRequest::getStatus() const { + return mStatus; +} + +NandRequestCheck::NandRequestCheck(u32 neededBlocks, u32 neededFiles) { + mResult = 0; + mNeededBlocks = neededBlocks; + mNeededFiles = neededFiles; +} + +bool NandRequestCheck::execute() { + mStatus = NANDCheck(mNeededBlocks, mNeededFiles, &mResult); + return true; +} + +NandRequestCreate::NandRequestCreate(const char *filePath, u8 perm, u8 attr) { + mPerm = perm; + mAttr = attr; + mFilePath = filePath; +} + +const char *splitComponent(const char *inPath, char *outPath, size_t size) { + char *end = outPath + size - 1; + while (true) { + if (outPath >= end) { + break; + } + char curr = inPath[0]; + char next = inPath[1]; + inPath++; + *outPath = curr; + outPath++; + if (next == '\0' || next == '/') { + break; + } + } + + *outPath = '\0'; + char curr = *inPath; + if (curr != '/') { + return inPath; + } + return inPath + 1; +} + +extern "C" NANDResult NANDChangeDir(const char *path); +extern "C" NANDResult NANDCreateDir(const char *path, u8 perm, u8 attr); + +bool NandRequestCreate::execute() { + char homeDir[64]; + char pathComponent[64]; + + mStatus = NANDGetHomeDir(homeDir); + if (mStatus != NAND_RESULT_OK) { + return true; + } + + const char *ptr = mFilePath; + if (ptr[0] == '/') { + ptr = splitComponent(ptr, pathComponent, sizeof(pathComponent)); + } else { + std::strncpy(pathComponent, homeDir, sizeof(pathComponent)); + } + + mStatus = NANDChangeDir(pathComponent); + if (mStatus != NAND_RESULT_OK) { + return true; + } + + const char *component = splitComponent(ptr, pathComponent, sizeof(pathComponent)); + while (component[0] != '\0') { + mStatus = NANDCreateDir(pathComponent, mPerm, mAttr); + if (mStatus != NAND_RESULT_OK && mStatus != NAND_RESULT_EXISTS) { + return true; + } + mStatus = NANDChangeDir(pathComponent); + if (mStatus != NAND_RESULT_OK) { + return true; + } + component = splitComponent(component, pathComponent, sizeof(pathComponent)); + } + + mStatus = NANDChangeDir(homeDir); + if (mStatus != NAND_RESULT_OK) { + return true; + } + + mStatus = NANDCreate(mFilePath, mPerm, mAttr); + return mStatus == NAND_RESULT_OK || mStatus == NAND_RESULT_EXISTS; +} + +NandRequestWrite::NandRequestWrite(const char *someString, void *data, size_t dataSize) { + mData = data; + mDataSize = dataSize; + mFailedWrite = false; + mFilePath = someString; +} + +extern "C" NANDResult NANDSimpleSafeOpen(const char *path, NANDFileInfo *outInfo, int, void *buf, size_t bufLen); +extern "C" NANDResult NANDSimpleSafeCancel(NANDFileInfo *info); +extern "C" NANDResult NANDSimpleSafeClose(NANDFileInfo *info); + +bool NandRequestWrite::execute() { + NANDFileInfo info; + mStatus = NANDSimpleSafeOpen( + mFilePath, &info, 2, NandRequestThread::getInstance()->getBuf(), NandRequestThread::getInstance()->getBufSize() + ); + if (mStatus != NAND_RESULT_OK) { + NANDResult res = NANDSimpleSafeCancel(&info); + if (res != NAND_RESULT_OK) { + mStatus = res; + } + return true; + } + + mStatus = NANDWrite(&info, mData, mDataSize); + if (mStatus == NAND_RESULT_ECC_CRIT || mStatus == NAND_RESULT_AUTHENTICATION) { + mStatus = NANDSimpleSafeCancel(&info); + if (mStatus == NAND_RESULT_OK) { + mFailedWrite = true; + } + return true; + } + + NANDResult res = NANDSimpleSafeClose(&info); + if (mStatus != mDataSize) { + mFailedWrite = true; + } else { + mStatus = res; + } + + return true; +} + +bool NandRequestHolderBase::isCompleted() const { + if (mpRequest != nullptr) { + return mpRequest->bHandled; + } + return true; +} + +NANDResult NandRequestHolderBase::getStatus() const { + if (mpRequest != nullptr) { + return mpRequest->getStatus(); + } + return NAND_RESULT_BUSY; +} + +bool NandRequestHolderBase::runToCompletion() { + if (mpRequest == nullptr) { + return true; + } + + do { + } while (!isCompleted()); + NandRequest::free(mpRequest); + mpRequest = nullptr; + + return true; +} + +bool NandRequestCheckHolder::check(u32 neededBlocks, u32 neededFiles) { + if (mpRequest != nullptr) { + return false; + } + + NandRequestCheck *req = NandRequestThread::getInstance()->checkRequest(neededBlocks, neededFiles); + if (req == nullptr) { + return false; + } + mpRequest = req; + return true; +} + +u32 NandRequestCheckHolder::getCheckResult() { + return static_cast(mpRequest)->mResult; +} + +bool NandRequestCreateHolder::create(const char *filePath, u8 perm, u8 attr) { + if (mpRequest != nullptr) { + return false; + } + + NandRequestCreate *req = NandRequestThread::getInstance()->createRequest(filePath, perm, attr); + if (req == nullptr) { + return false; + } + mpRequest = req; + return true; +} + +bool NandRequestWriteHolder::write(const char *filePath, void *data, size_t dataSize) { + if (mpRequest != nullptr) { + return false; + } + + NandRequestWrite *req = NandRequestThread::getInstance()->writeRequest(filePath, data, dataSize); + if (req == nullptr) { + return false; + } + mpRequest = req; + return true; +} + +bool NandRequestWriteHolder::failedWrite() { + return static_cast(mpRequest)->mFailedWrite; +} diff --git a/tools/custom/apply_objdiff_mappings.py b/tools/custom/apply_objdiff_mappings.py new file mode 100644 index 00000000..f7aaa367 --- /dev/null +++ b/tools/custom/apply_objdiff_mappings.py @@ -0,0 +1,52 @@ +# Thanks KooShnoo! https://discord.com/channels/727908905392275526/1024871155804426310/1329716224971767891 + +""" +objdiff allows one to map symbols from the target binary to the source binary. +this script will take those symbols you have mapped, and write them to `symbols.txt`. + +use case: say you have changed the signature/name of a function. +now, your source file says `foo_Ful`, but symbols.txt says `bar__Fl`. +objdiff allows you to map the `foo_Ful` in the target object to `bar__Fl` in the source object. +this script allows you to replace `foo_Ful` with `bar__Fl` in `symbols.txt`. +""" + +import json + +with open("./objdiff.json") as f: + objdiff_config = json.load(f) + +# lol python has types. it's typython. typescript all over again +units: list = objdiff_config["units"] +symbol_mappings_list = list( + filter(None, [unit.get("symbol_mappings") for unit in units]) +) + +symbol_mappings = {} +for unit in units: + symbol_mapping = unit.get("symbol_mappings") + if symbol_mapping is None: + continue + symbol_mappings.update(symbol_mapping) + del unit['symbol_mappings'] + + +with open("./config/SOUE01/symbols.txt") as f: + symbols = f.readlines() + +for i, line in enumerate(symbols): + tokens = line.split() + old_symbol = tokens[0] + + new_symbol = symbol_mappings.get(old_symbol) + + if new_symbol is None: + continue + + tokens[0] = new_symbol + symbols[i] = " ".join(tokens) + "\n" + +with open("./config/SOUE01/symbols.txt", "w") as f: + f.writelines(symbols) + +with open("./objdiff.json", "w") as f: + json.dump(objdiff_config, f)