diff options
| author | robojumper <robojumper@gmail.com> | 2025-02-28 14:01:46 +0100 |
|---|---|---|
| committer | robojumper <robojumper@gmail.com> | 2025-02-28 14:01:46 +0100 |
| commit | c7d788117e399bdf7a4001f55f00d12499f128fe (patch) | |
| tree | 913f2916e501614931a3c59be1c036665bae14c0 /src/toBeSorted/nand_request_thread.cpp | |
| parent | c2b2d9700c47c1eb4c6026fee14d1d9b247f8fe8 (diff) | |
NandRequestThread
Diffstat (limited to 'src/toBeSorted/nand_request_thread.cpp')
| -rw-r--r-- | src/toBeSorted/nand_request_thread.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
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 <cstring> + +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<NandRequestCheck *>(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<NandRequestWrite *>(mpRequest)->mFailedWrite; +} |
