diff --git a/src/Cafe/Filesystem/fsc.cpp b/src/Cafe/Filesystem/fsc.cpp index 3b1565a8..b2500667 100644 --- a/src/Cafe/Filesystem/fsc.cpp +++ b/src/Cafe/Filesystem/fsc.cpp @@ -302,6 +302,15 @@ public: return true; } + bool fscRewindDir() override + { + if (!dirIterator) + return true; + + dirIterator->index = 0; + return true; + } + void addUniqueDirEntry(const FSCDirEntry& dirEntry) { // skip if already in list @@ -378,6 +387,7 @@ FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* { // return first found file cemu_assert_debug(HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE)); + fscVirtualFile->m_isAppend = HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::IS_APPEND); fscLeave(); return fscVirtualFile; } @@ -598,6 +608,9 @@ uint32 fsc_writeFile(FSCVirtualFile* fscFile, void* buffer, uint32 size) fscLeave(); return 0; } + if (fscFile->m_isAppend) + fsc_setFileSeek(fscFile, fsc_getFileSize(fscFile)); + uint32 fscStatus = fscFile->fscWriteData(buffer, size); fscLeave(); return fscStatus; diff --git a/src/Cafe/Filesystem/fsc.h b/src/Cafe/Filesystem/fsc.h index e34c74dd..2854a301 100644 --- a/src/Cafe/Filesystem/fsc.h +++ b/src/Cafe/Filesystem/fsc.h @@ -24,7 +24,10 @@ enum class FSC_ACCESS_FLAG : uint8 // which types can be opened // invalid operation if neither is set OPEN_DIR = (1 << 4), - OPEN_FILE = (1 << 5) + OPEN_FILE = (1 << 5), + + // Writing seeks to the end of the file if set + IS_APPEND = (1 << 6) }; DEFINE_ENUM_FLAG_OPERATORS(FSC_ACCESS_FLAG); @@ -149,7 +152,15 @@ struct FSCVirtualFile return false; } + virtual bool fscRewindDir() + { + cemu_assert_unimplemented(); + return false; + } + FSCDirIteratorState* dirIterator{}; + + bool m_isAppend{ false }; }; #define FSC_PRIORITY_BASE (0) diff --git a/src/Cafe/IOSU/fsa/fsa_types.h b/src/Cafe/IOSU/fsa/fsa_types.h index 2825e421..a7757486 100644 --- a/src/Cafe/IOSU/fsa/fsa_types.h +++ b/src/Cafe/IOSU/fsa/fsa_types.h @@ -17,9 +17,11 @@ enum class FS_RESULT : sint32 // aka FSStatus enum class FSA_RESULT : sint32 // aka FSError/FSAStatus { - SUCCESS = 0, - END_DIR = -0x30000 - 0x04, - END_FILE = -0x30000 - 0x05, + OK = 0, + NOT_INIT = -0x30000 - 0x01, + END_OF_DIRECTORY = -0x30000 - 0x04, + END_OF_FILE = -0x30000 - 0x05, + MAX_CLIENTS = -0x30000 - 0x12, MAX_FILES = -0x30000 - 0x13, MAX_DIRS = -0x30000 - 0x14, ALREADY_EXISTS = -0x30000 - 0x16, @@ -34,6 +36,7 @@ enum class FSA_RESULT : sint32 // aka FSError/FSAStatus INVALID_DIR_HANDLE = -0x30000 - 0x27, NOT_FILE = -0x30000 - 0x28, NOT_DIR = -0x30000 - 0x29, + OUT_OF_RESOURCES = -0x30000 - 0x2C, FATAL_ERROR = -0x30000 - 0x400, }; @@ -46,6 +49,7 @@ enum class FSA_CMD_OPERATION_TYPE : uint32 RENAME = 0x9, OPENDIR = 0xA, READDIR = 0xB, + REWINDDIR = 0xC, CLOSEDIR = 0xD, OPENFILE = 0xE, READ = 0xF, @@ -55,6 +59,7 @@ enum class FSA_CMD_OPERATION_TYPE : uint32 ISEOF = 0x13, GETSTATFILE = 0x14, CLOSEFILE = 0x15, + FLUSHFILE = 0x17, QUERYINFO = 0x18, APPENDFILE = 0x19, TRUNCATEFILE = 0x1A, @@ -81,6 +86,7 @@ enum class FSFlag : uint32 { NONE = 0, IS_DIR = 0x80000000, + IS_FILE = 0x01000000, }; DEFINE_ENUM_FLAG_OPERATORS(FSFlag); @@ -111,8 +117,18 @@ struct FSDirEntry_t static_assert(sizeof(FSDirEntry_t) == 0xE4); +struct FSADeviceInfo_t +{ + uint8 ukn0[0x8]; + uint64be deviceSizeInSectors; + uint32be deviceSectorSize; + uint8 ukn014[0x14]; +}; +static_assert(sizeof(FSADeviceInfo_t) == 0x28); + #pragma pack() // query types for QueryInfo #define FSA_QUERY_TYPE_FREESPACE 0 +#define FSA_QUERY_TYPE_DEVICE_INFO 4 #define FSA_QUERY_TYPE_STAT 5 diff --git a/src/Cafe/IOSU/fsa/iosu_fsa.cpp b/src/Cafe/IOSU/fsa/iosu_fsa.cpp index 17d86266..2c23ea71 100644 --- a/src/Cafe/IOSU/fsa/iosu_fsa.cpp +++ b/src/Cafe/IOSU/fsa/iosu_fsa.cpp @@ -54,7 +54,7 @@ namespace iosu FSA_RESULT FSA_convertFSCtoFSAStatus(sint32 fscError) { if (fscError == FSC_STATUS_OK) - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; else if (fscError == FSC_STATUS_FILE_NOT_FOUND) return FSA_RESULT::NOT_FOUND; else if (fscError == FSC_STATUS_ALREADY_EXISTS) @@ -175,7 +175,7 @@ namespace iosu it.isAllocated = true; uint32 handleVal = ((uint32)i << 16) | (uint32)checkValue; handleOut = (FSResHandle)handleVal; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } cemuLog_log(LogType::Force, "FSA: Ran out of file handles"); return FSA_RESULT::FATAL_ERROR; @@ -194,7 +194,7 @@ namespace iosu return FSA_RESULT::INVALID_FILE_HANDLE; it.fscFile = nullptr; it.isAllocated = false; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSCVirtualFile* GetByHandle(FSResHandle handle) @@ -229,10 +229,9 @@ namespace iosu accessModifier = FSC_ACCESS_FLAG::READ_PERMISSION; else if (strcmp(accessModifierStr, "r+") == 0) { - // r+ will create a new file if it doesn't exist // the cursor will be set to the beginning of the file // allows read and write access - accessModifier = FSC_ACCESS_FLAG::READ_PERMISSION | FSC_ACCESS_FLAG::WRITE_PERMISSION | FSC_ACCESS_FLAG::FILE_ALLOW_CREATE; // create if non exists, read, write + accessModifier = FSC_ACCESS_FLAG::READ_PERMISSION | FSC_ACCESS_FLAG::WRITE_PERMISSION; // read, write } else if (strcmp(accessModifierStr, "w") == 0) { @@ -252,10 +251,12 @@ namespace iosu } else if (strcmp(accessModifierStr, "a+") == 0) { - cemu_assert_debug(false); // a+ is kind of special. Writing always happens at the end but the read cursor can dynamically move - // but Cafe OS might not support this. Needs investigation. - // this also used to be FILE_ALWAYS_CREATE in 1.26.2 and before - accessModifier = FSC_ACCESS_FLAG::READ_PERMISSION | FSC_ACCESS_FLAG::WRITE_PERMISSION | FSC_ACCESS_FLAG::FILE_ALLOW_CREATE; + accessModifier = FSC_ACCESS_FLAG::READ_PERMISSION | FSC_ACCESS_FLAG::WRITE_PERMISSION | FSC_ACCESS_FLAG::FILE_ALLOW_CREATE | FSC_ACCESS_FLAG::IS_APPEND; + isAppend = true; + } + else if (strcmp(accessModifierStr, "a") == 0) + { + accessModifier = FSC_ACCESS_FLAG::WRITE_PERMISSION | FSC_ACCESS_FLAG::FILE_ALLOW_CREATE | FSC_ACCESS_FLAG::IS_APPEND; isAppend = true; } else @@ -275,7 +276,7 @@ namespace iosu fsc_setFileSeek(fscFile, fsc_getFileSize(fscFile)); FSResHandle fsFileHandle; FSA_RESULT r = sFileHandleTable.AllocateHandle(fsFileHandle, fscFile); - if (r != FSA_RESULT::SUCCESS) + if (r != FSA_RESULT::OK) { cemuLog_log(LogType::Force, "Exceeded maximum number of FSA file handles"); delete fscFile; @@ -283,7 +284,7 @@ namespace iosu } *fileHandle = fsFileHandle; cemuLog_log(LogType::CoreinitFile, "Open file {} (access: {} result: ok handle: 0x{})", path, accessModifierStr, (uint32)*fileHandle); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT __FSAOpenDirectory(FSAClient* client, std::string_view path, sint32* dirHandle) @@ -300,14 +301,14 @@ namespace iosu } FSResHandle fsDirHandle; FSA_RESULT r = sDirHandleTable.AllocateHandle(fsDirHandle, fscFile); - if (r != FSA_RESULT::SUCCESS) + if (r != FSA_RESULT::OK) { delete fscFile; return FSA_RESULT::MAX_DIRS; } *dirHandle = fsDirHandle; cemuLog_log(LogType::CoreinitFile, "Open directory {} (result: ok handle: 0x{})", path, (uint32)*dirHandle); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT __FSACloseFile(uint32 fileHandle) @@ -322,7 +323,7 @@ namespace iosu // unregister file sFileHandleTable.ReleaseHandle(fileHandle); // todo - use the error code of this fsc_close(fscFile); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_remove(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -383,7 +384,7 @@ namespace iosu return FSA_convertFSCtoFSAStatus(fscStatus); __FSA_GetStatFromFSCFile(fscFile, fsStatOut); delete fscFile; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_queryInfo(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -407,7 +408,16 @@ namespace iosu betype* fsStatSize = &shimBuffer->response.cmdQueryInfo.queryFreeSpace.freespace; *fsStatSize = 30ull * 1024 * 1024 * 1024; // placeholder value. How is this determined? delete fscFile; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; + } + else if (queryType == FSA_QUERY_TYPE_DEVICE_INFO) + { + FSADeviceInfo_t* deviceInfo = &shimBuffer->response.cmdQueryInfo.queryDeviceInfo.info; + // always report hardcoded values for now. + deviceInfo->deviceSectorSize = 512; + deviceInfo->deviceSizeInSectors = (32ull * 1024 * 1024 * 1024) / deviceInfo->deviceSectorSize; + cemu_assert_suspicious(); + return FSA_RESULT::OK; } else cemu_assert_unimplemented(); @@ -423,7 +433,7 @@ namespace iosu return FSA_RESULT::NOT_FOUND; cemu_assert_debug(fsc_isFile(fscFile)); __FSA_GetStatFromFSCFile(fscFile, statOut); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_read(FSAClient* client, FSAShimBuffer* shimBuffer, MEMPTR destPtr, uint32be transferSize) @@ -444,7 +454,7 @@ namespace iosu // todo: File permissions uint32 bytesSuccessfullyRead = fsc_readFile(fscFile, destPtr, bytesToRead); if (transferElementSize == 0) - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; LatteBufferCache_notifyDCFlush(destPtr.GetMPTR(), bytesToRead); @@ -485,7 +495,7 @@ namespace iosu if (!fscFile) return FSA_RESULT::INVALID_FILE_HANDLE; fsc_setFileSeek(fscFile, filePos); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_getPos(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -496,7 +506,7 @@ namespace iosu return FSA_RESULT::INVALID_FILE_HANDLE; uint32 filePos = fsc_getFileSeek(fscFile); shimBuffer->response.cmdGetPosFile.filePos = filePos; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_openFile(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -528,7 +538,7 @@ namespace iosu FSDirEntry_t* dirEntryOut = &shimBuffer->response.cmdReadDir.dirEntry; FSCDirEntry fscDirEntry; if (fsc_nextDir(fscFile, &fscDirEntry) == false) - return FSA_RESULT::END_DIR; + return FSA_RESULT::END_OF_DIRECTORY; strcpy(dirEntryOut->name, fscDirEntry.path); FSFlag statFlag = FSFlag::NONE; dirEntryOut->stat.size = 0; @@ -538,11 +548,12 @@ namespace iosu } else if (fscDirEntry.isFile) { + statFlag |= FSFlag::IS_FILE; dirEntryOut->stat.size = fscDirEntry.fileSize; } dirEntryOut->stat.flag = statFlag; dirEntryOut->stat.permissions = 0x777; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_closeDir(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -555,12 +566,31 @@ namespace iosu } sDirHandleTable.ReleaseHandle(shimBuffer->request.cmdReadDir.dirHandle); fsc_close(fscFile); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_flushQuota(FSAClient* client, FSAShimBuffer* shimBuffer) { - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; + } + + FSA_RESULT FSAProcessCmd_rewindDir(FSAClient* client, FSAShimBuffer* shimBuffer) + { + FSCVirtualFile* fscFile = sDirHandleTable.GetByHandle((sint32)shimBuffer->request.cmdRewindDir.dirHandle); + if (!fscFile) + { + cemuLog_logDebug(LogType::Force, "RewindDir: Invalid handle (0x{:08x})", (sint32)shimBuffer->request.cmdRewindDir.dirHandle); + return FSA_RESULT::INVALID_DIR_HANDLE; + } + if (!fscFile->fscRewindDir()) + return FSA_RESULT::FATAL_ERROR; + + return FSA_RESULT::OK; + } + + FSA_RESULT FSAProcessCmd_flushFile(FSAClient* client, FSAShimBuffer* shimBuffer) + { + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_appendFile(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -582,7 +612,7 @@ namespace iosu if (!fscFile) return FSA_RESULT::INVALID_FILE_HANDLE; fsc_setFileLength(fscFile, fsc_getFileSeek(fscFile)); - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_isEof(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -594,8 +624,8 @@ namespace iosu uint32 filePos = fsc_getFileSeek(fscFile); uint32 fileSize = fsc_getFileSize(fscFile); if (filePos >= fileSize) - return FSA_RESULT::END_FILE; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::END_OF_FILE; + return FSA_RESULT::OK; } FSA_RESULT FSAProcessCmd_getCwd(FSAClient* client, FSAShimBuffer* shimBuffer) @@ -764,17 +794,22 @@ namespace iosu fsaResult = FSAProcessCmd_flushQuota(client, shimBuffer); break; } + case FSA_CMD_OPERATION_TYPE::REWINDDIR: + { + fsaResult = FSAProcessCmd_rewindDir(client, shimBuffer); + break; + } + case FSA_CMD_OPERATION_TYPE::FLUSHFILE: + { + fsaResult = FSAProcessCmd_flushFile(client, shimBuffer); + break; + } case FSA_CMD_OPERATION_TYPE::READ: case FSA_CMD_OPERATION_TYPE::WRITE: { // These commands are IOCTLVs not IOCTL cemu_assert_error(); } - default: - { - cemu_assert_unimplemented(); - break; - } } IOS_ResourceReply(cmd, (IOS_ERROR)fsaResult); } diff --git a/src/Cafe/IOSU/fsa/iosu_fsa.h b/src/Cafe/IOSU/fsa/iosu_fsa.h index 8f8d2323..8181a4a8 100644 --- a/src/Cafe/IOSU/fsa/iosu_fsa.h +++ b/src/Cafe/IOSU/fsa/iosu_fsa.h @@ -111,10 +111,25 @@ namespace iosu { uint32be fileHandle; } cmdIsEof; + struct + { + uint32be dirHandle; + } cmdRewindDir; + struct + { + uint32be fileHandle; + } cmdFlushFile; + struct + { + uint8 path[FSA_CMD_PATH_MAX_LENGTH]; + uint32be mode1; + uint32be mode2; + } cmdChangeMode; }; }; static_assert(sizeof(FSARequest) == 0x520); +#pragma pack(1) struct FSAResponse { uint32be ukn0; @@ -158,11 +173,16 @@ namespace iosu { FSStat_t stat; } queryStat; + struct + { + FSADeviceInfo_t info; + } queryDeviceInfo; }; } cmdQueryInfo; }; }; - // static_assert(sizeof(FSAResponse) == 0x293); + static_assert(sizeof(FSAResponse) == 0x293); +#pragma pack() struct FSAShimBuffer { @@ -189,7 +209,7 @@ namespace iosu uint32 ukn0930; uint32 ukn0934; }; - // static_assert(sizeof(FSAShimBuffer) == 0x938); // exact size of this is not known + static_assert(sizeof(FSAShimBuffer) == 0x938); // exact size of this is not known void Initialize(); void Shutdown(); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp index 6a864cf2..6fba3a1d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp @@ -10,6 +10,7 @@ #include "Cafe/IOSU/iosu_ipc_common.h" #include "coreinit_IPC.h" #include "Cafe/Filesystem/fsc.h" +#include "coreinit_IPCBuf.h" #define FS_CB_PLACEHOLDER_FINISHCMD (MPTR)(0xF122330E) @@ -457,6 +458,26 @@ namespace coreinit } } + FSA_RESULT __FSADecodeIOSErrorToFSA(IOS_ERROR result) + { + return (FSA_RESULT)result; + } + + FSA_RESULT __FSAIPCSubmitCommand(iosu::fsa::FSAShimBuffer* shimBuffer) + { + if (shimBuffer->ipcReqType == 0) + { + IOS_ERROR result = IOS_Ioctl(shimBuffer->fsaDevHandle, shimBuffer->operationType, &shimBuffer->request, sizeof(shimBuffer->request), &shimBuffer->response, sizeof(shimBuffer->response)); + return __FSADecodeIOSErrorToFSA(result); + } + else if (shimBuffer->ipcReqType == 1) + { + IOS_ERROR result = IOS_Ioctlv(shimBuffer->fsaDevHandle, shimBuffer->operationType, shimBuffer->ioctlvVecIn, shimBuffer->ioctlvVecOut, shimBuffer->ioctlvVec); + return __FSADecodeIOSErrorToFSA(result); + } + return FSA_RESULT::FATAL_ERROR; + } + void __FSUpdateQueue(FSCmdQueue* cmdQueue) { FSLockMutex(); @@ -586,12 +607,12 @@ namespace coreinit } switch (err) { - case FSA_RESULT::SUCCESS: + case FSA_RESULT::OK: { return FS_RESULT::SUCCESS; } - case FSA_RESULT::END_DIR: - case FSA_RESULT::END_FILE: + case FSA_RESULT::END_OF_DIRECTORY: + case FSA_RESULT::END_OF_FILE: { return FS_RESULT::END_ITERATION; } @@ -627,6 +648,9 @@ namespace coreinit case FSA_RESULT::INVALID_PATH: case FSA_RESULT::INVALID_BUFFER: case FSA_RESULT::INVALID_ALIGNMENT: + case FSA_RESULT::NOT_INIT: + case FSA_RESULT::MAX_CLIENTS: + case FSA_RESULT::OUT_OF_RESOURCES: case FSA_RESULT::FATAL_ERROR: { return FS_RESULT::FATAL_ERROR; @@ -863,7 +887,7 @@ namespace coreinit fsaShimBuffer->response.cmdOpenFile.fileHandleOutput = 0xFFFFFFFF; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSOpenFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* outFileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -901,7 +925,7 @@ namespace coreinit fsCmdBlockBody->returnValues.cmdOpenFile.handlePtr = &outFileHandle->fileHandle; FSA_RESULT prepareResult = __FSPrepareCmd_OpenFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, path, mode, createMode, openFlag, preallocSize); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -919,14 +943,15 @@ namespace coreinit FSA_RESULT __FSPrepareCmd_CloseFile(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle fsaHandle, uint32 fileHandle) { if (fsaShimBuffer == nullptr) - { return FSA_RESULT::INVALID_BUFFER; - } + fsaShimBuffer->fsaDevHandle = fsaHandle; fsaShimBuffer->ipcReqType = 0; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::CLOSEFILE; + fsaShimBuffer->request.cmdCloseFile.fileHandle = fileHandle; - return FSA_RESULT::SUCCESS; + + return FSA_RESULT::OK; } sint32 FSCloseFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -934,7 +959,7 @@ namespace coreinit _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_CloseFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -949,6 +974,40 @@ namespace coreinit return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling); } + FSA_RESULT __FSPrepareCmd_FlushFile(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle fsaHandle, uint32 fileHandle) + { + if (fsaShimBuffer == nullptr) + return FSA_RESULT::INVALID_BUFFER; + + fsaShimBuffer->fsaDevHandle = fsaHandle; + fsaShimBuffer->ipcReqType = 0; + fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::FLUSHFILE; + + fsaShimBuffer->request.cmdFlushFile.fileHandle = fileHandle; + + return FSA_RESULT::OK; + } + + sint32 FSFlushFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) + { + _FSCmdIntro(); + + FSA_RESULT prepareResult = __FSPrepareCmd_FlushFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle); + if (prepareResult != FSA_RESULT::OK) + return (FSStatus)_FSAStatusToFSStatus(prepareResult); + + __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); + return (FSStatus)FS_RESULT::SUCCESS; + } + + sint32 FSFlushFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling) + { + StackAllocator asyncParams; + __FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams); + sint32 fsAsyncRet = FSFlushFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, asyncParams); + return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling); + } + FSA_RESULT __FSPrepareCmd_ReadFile(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle fsaHandle, void* dest, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag) { if (fsaShimBuffer == NULL || dest == NULL) @@ -980,7 +1039,7 @@ namespace coreinit fsaShimBuffer->request.cmdReadFile.fileHandle = fileHandle; fsaShimBuffer->request.cmdReadFile.flag = flag; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } SysAllocator _tempFSSpace; @@ -1009,7 +1068,7 @@ namespace coreinit flag &= ~FSA_CMD_FLAG_SET_POS; FSA_RESULT prepareResult = __FSPrepareCmd_ReadFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dest, size, count, filePos, fileHandle, flag); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1076,7 +1135,7 @@ namespace coreinit fsaShimBuffer->request.cmdWriteFile.fileHandle = fileHandle; fsaShimBuffer->request.cmdWriteFile.flag = flag; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 __FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dest, uint32 size, uint32 count, bool useFilePos, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1103,7 +1162,7 @@ namespace coreinit flag &= ~FSA_CMD_FLAG_SET_POS; FSA_RESULT prepareResult = __FSPrepareCmd_WriteFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dest, size, count, filePos, fileHandle, flag); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1146,14 +1205,14 @@ namespace coreinit fsaShimBuffer->request.cmdSetPosFile.fileHandle = fileHandle; fsaShimBuffer->request.cmdSetPosFile.filePos = filePos; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::SETPOS; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSSetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) { _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_SetPosFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle, filePos); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); return (FSStatus)FS_RESULT::SUCCESS; @@ -1176,7 +1235,7 @@ namespace coreinit fsaShimBuffer->ipcReqType = 0; fsaShimBuffer->request.cmdGetPosFile.fileHandle = fileHandle; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::GETPOS; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSGetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1185,7 +1244,7 @@ namespace coreinit _FSCmdIntro(); fsCmdBlockBody->returnValues.cmdGetPosFile.filePosPtr = returnedFilePos; FSA_RESULT prepareResult = __FSPrepareCmd_GetPosFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); return (FSStatus)FS_RESULT::SUCCESS; @@ -1224,7 +1283,7 @@ namespace coreinit fsaShimBuffer->response.cmdOpenDir.dirHandleOutput = -1; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSOpenDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1233,7 +1292,7 @@ namespace coreinit cemu_assert(dirHandleOut && path); fsCmdBlockBody->returnValues.cmdOpenDir.handlePtr = dirHandleOut.GetMPTR(); FSA_RESULT prepareResult = __FSPrepareCmd_OpenDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, path); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); return (FSStatus)FS_RESULT::SUCCESS; @@ -1255,14 +1314,14 @@ namespace coreinit fsaShimBuffer->ipcReqType = 0; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::READDIR; fsaShimBuffer->request.cmdReadDir.dirHandle = dirHandle; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSReadDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) { _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_ReadDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); fsCmdBlockBody->returnValues.cmdReadDir.dirEntryPtr = dirEntryOut; __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1285,14 +1344,14 @@ namespace coreinit fsaShimBuffer->ipcReqType = 0; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::CLOSEDIR; fsaShimBuffer->request.cmdCloseDir.dirHandle = dirHandle; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSCloseDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) { _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_CloseDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1307,6 +1366,39 @@ namespace coreinit return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask); } + FSA_RESULT __FSPrepareCmd_RewindDir(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle fsaHandle, FSDirHandle2 dirHandle) + { + if (fsaShimBuffer == nullptr) + return FSA_RESULT::INVALID_BUFFER; + + fsaShimBuffer->fsaDevHandle = fsaHandle; + fsaShimBuffer->ipcReqType = 0; + fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::REWINDDIR; + + fsaShimBuffer->request.cmdRewindDir.dirHandle = dirHandle; + + return FSA_RESULT::OK; + } + + sint32 FSRewindDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) + { + _FSCmdIntro(); + FSA_RESULT prepareResult = __FSPrepareCmd_RewindDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirHandle); + if (prepareResult != FSA_RESULT::OK) + return (FSStatus)_FSAStatusToFSStatus(prepareResult); + + __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); + return (FSStatus)FS_RESULT::SUCCESS; + } + + sint32 FSRewindDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask) + { + StackAllocator asyncParams; + __FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams); + sint32 fsAsyncRet = FSRewindDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, asyncParams); + return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask); + } + FSA_RESULT __FSPrepareCmd_AppendFile(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle fsaHandle, uint32 fileHandle, uint32 size, uint32 count, uint32 uknParam) { if (fsaShimBuffer == nullptr) @@ -1320,14 +1412,14 @@ namespace coreinit fsaShimBuffer->request.cmdAppendFile.size = count; fsaShimBuffer->request.cmdAppendFile.uknParam = uknParam; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSAppendFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 size, uint32 count, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) { _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_AppendFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle, size, count, 0); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1352,14 +1444,14 @@ namespace coreinit fsaShimBuffer->request.cmdTruncateFile.fileHandle = fileHandle; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSTruncateFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) { _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_TruncateFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1410,7 +1502,7 @@ namespace coreinit } fsaShimBuffer->request.cmdRename.dstPath[stringLen] = '\0'; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSRenameAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1423,7 +1515,7 @@ namespace coreinit return -0x400; } FSA_RESULT prepareResult = __FSPrepareCmd_Rename(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, srcPath, dstPath); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1461,7 +1553,7 @@ namespace coreinit } fsaShimBuffer->request.cmdRemove.path[pathLen] = '\0'; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSRemoveAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1474,7 +1566,7 @@ namespace coreinit return -0x400; } FSA_RESULT prepareResult = __FSPrepareCmd_Remove(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, filePath); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1513,7 +1605,7 @@ namespace coreinit fsaShimBuffer->request.cmdMakeDir.path[pathLen] = '\0'; fsaShimBuffer->request.cmdMakeDir.uknParam = uknVal660; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSMakeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const uint8* dirPath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1526,7 +1618,7 @@ namespace coreinit return -0x400; } FSA_RESULT prepareResult = __FSPrepareCmd_MakeDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirPath, 0x660); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1563,7 +1655,7 @@ namespace coreinit fsaShimBuffer->request.cmdChangeDir.path[pathLen] = '\0'; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSChangeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1575,7 +1667,7 @@ namespace coreinit return -0x400; } FSA_RESULT prepareResult = __FSPrepareCmd_ChangeDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, (uint8*)path); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1599,7 +1691,7 @@ namespace coreinit fsaShimBuffer->ipcReqType = 0; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::GETCWD; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSGetCwdAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1610,7 +1702,7 @@ namespace coreinit fsCmdBlockBody->returnValues.cmdGetCwd.transferSize = dirPathMaxLen; FSA_RESULT prepareResult = __FSPrepareCmd_GetCwd(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1647,7 +1739,7 @@ namespace coreinit fsaShimBuffer->request.cmdFlushQuota.path[i] = path[i]; fsaShimBuffer->request.cmdFlushQuota.path[pathLen] = '\0'; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSFlushQuotaAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1655,7 +1747,7 @@ namespace coreinit _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_FlushQuota(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, path); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1697,7 +1789,7 @@ namespace coreinit fsaShimBuffer->request.cmdQueryInfo.query[stringLen] = '\0'; fsaShimBuffer->request.cmdQueryInfo.queryType = queryType; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 __FSQueryInfoAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* queryString, uint32 queryType, void* queryResult, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1707,7 +1799,7 @@ namespace coreinit fsCmdBlockBody->returnValues.cmdQueryInfo.queryResultPtr = queryResult; FSA_RESULT prepareResult = __FSPrepareCmd_QueryInfo(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, queryString, queryType); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1729,16 +1821,18 @@ namespace coreinit return ret; } - FSA_RESULT __FSPrepareCmd_GetStatFile(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle devHandle, FSFileHandle2 fileHandle, FSStat_t* statOut) + FSA_RESULT __FSPrepareCmd_GetStatFile(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle devHandle, FSFileHandle2 fileHandle) { if (fsaShimBuffer == NULL) return FSA_RESULT::INVALID_BUFFER; fsaShimBuffer->fsaDevHandle = devHandle; fsaShimBuffer->ipcReqType = 0; - fsaShimBuffer->request.cmdGetStatFile.fileHandle = fileHandle; fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::GETSTATFILE; - return FSA_RESULT::SUCCESS; + + fsaShimBuffer->request.cmdGetStatFile.fileHandle = fileHandle; + + return FSA_RESULT::OK; } sint32 FSGetStatFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1747,8 +1841,8 @@ namespace coreinit cemu_assert(statOut); // statOut must not be null fsCmdBlockBody->returnValues.cmdStatFile.resultPtr = statOut; - FSA_RESULT prepareResult = __FSPrepareCmd_GetStatFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle, statOut); - if (prepareResult != FSA_RESULT::SUCCESS) + FSA_RESULT prepareResult = __FSPrepareCmd_GetStatFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle); + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1789,7 +1883,7 @@ namespace coreinit fsaShimBuffer->request.cmdIsEof.fileHandle = fileHandle; - return FSA_RESULT::SUCCESS; + return FSA_RESULT::OK; } sint32 FSIsEofAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams) @@ -1798,7 +1892,7 @@ namespace coreinit _FSCmdIntro(); FSA_RESULT prepareResult = __FSPrepareCmd_IsEof(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle); - if (prepareResult != FSA_RESULT::SUCCESS) + if (prepareResult != FSA_RESULT::OK) return (FSStatus)_FSAStatusToFSStatus(prepareResult); __FSQueueCmd(&fsClientBody->fsCmdQueue, fsCmdBlockBody, RPLLoader_MakePPCCallable(export___FSQueueDefaultFinishFunc)); @@ -1862,6 +1956,681 @@ namespace coreinit return 0; // no error } + std::vector s_fsa_activeClients; + std::mutex s_fsa_activeClientsMutex; + + FSAClientHandle FSAAddClientEx(void* data) + { + if (data != NULL) + { + // TODO + cemu_assert_unimplemented(); + } + + IOSDevHandle handle = IOS_Open("/dev/fsa", 0); + if (handle < IOS_ERROR::IOS_ERROR_OK) + { + return (FSAClientHandle)FSA_RESULT::PERMISSION_ERROR; + } + + s_fsa_activeClientsMutex.lock(); + s_fsa_activeClients.push_back((FSAClientHandle)handle); + s_fsa_activeClientsMutex.unlock(); + + return (FSAClientHandle)handle; + } + + FSAClientHandle FSAAddClient(void* data) + { + return FSAAddClientEx(data); + } + + FSA_RESULT FSADelClient(FSAClientHandle clientHandle) + { + if (clientHandle == 0) + { + return FSA_RESULT::INVALID_CLIENT_HANDLE; + } + s_fsa_activeClientsMutex.lock(); + + auto it = std::find(s_fsa_activeClients.begin(), s_fsa_activeClients.end(), clientHandle); + if (it != s_fsa_activeClients.end()) + { + IOS_Close(clientHandle); + s_fsa_activeClients.erase(it); + } + + s_fsa_activeClientsMutex.unlock(); + + return FSA_RESULT::OK; + } + + SysAllocator s_fsaIpcPool; + SysAllocator s_fsaIpcPoolBuffer; + SysAllocator s_fsaIpcPoolBufferNumItems; + + std::mutex sFSAIPCBufferLock; + bool s_fsaInitDone = false; + + void FSAInit() + { + if (!s_fsaInitDone) + { + s_fsaIpcPool = IPCBufPoolCreate(s_fsaIpcPoolBuffer.GetPtr(), s_fsaIpcPoolBuffer.GetByteSize(), sizeof(iosu::fsa::FSAShimBuffer), &s_fsaIpcPoolBufferNumItems, 0); + s_fsaInitDone = true; + } + } + + bool FSAShimCheckClientHandle(FSAClientHandle clientHandle) + { + std::scoped_lock lock(s_fsa_activeClientsMutex); + if (std::find(s_fsa_activeClients.begin(), s_fsa_activeClients.end(), clientHandle) != s_fsa_activeClients.end()) + { + return true; + } + return false; + } + + FSA_RESULT FSAShimAllocateBuffer(MEMPTR> outBuffer) + { + if (!s_fsaInitDone) + return FSA_RESULT::NOT_INIT; + + sFSAIPCBufferLock.lock(); + auto ptr = IPCBufPoolAllocate(s_fsaIpcPool, sizeof(iosu::fsa::FSAShimBuffer)); + sFSAIPCBufferLock.unlock(); + + if (!ptr) + return FSA_RESULT::OUT_OF_RESOURCES; + + std::memset(ptr, 0, sizeof(iosu::fsa::FSAShimBuffer)); + outBuffer[0] = reinterpret_cast(ptr); + return FSA_RESULT::OK; + } + + FSA_RESULT FSAShimFreeBuffer(iosu::fsa::FSAShimBuffer* buffer) + { + sFSAIPCBufferLock.lock(); + IPCBufPoolFree(s_fsaIpcPool, (uint8_t*)buffer); + sFSAIPCBufferLock.unlock(); + return FSA_RESULT::OK; + } + + FSA_RESULT FSACloseFile(FSAClientHandle client, uint32 fileHandle) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_CloseFile(shimBuffer->GetPtr(), client, fileHandle); + if (result == FSA_RESULT::OK) + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAFlushFile(FSAClientHandle client, uint32_t fileHandle) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_FlushFile(shimBuffer->GetPtr(), client, fileHandle); + if (result == FSA_RESULT::OK) + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAMakeDir(FSAClientHandle client, const uint8* path, uint32 uknVal660) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_MakeDir(shimBuffer->GetPtr(), client, path, uknVal660); + if (result == FSA_RESULT::OK) + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSARename(FSAClientHandle client, char* oldPath, char* newPath) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_Rename(shimBuffer->GetPtr(), client, oldPath, newPath); + if (result == FSA_RESULT::OK) + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAChangeDir(FSAClientHandle client, char* path) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_ChangeDir(shimBuffer->GetPtr(), client, (uint8_t*)path); + if (result == FSA_RESULT::OK) + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAReadDir(FSAClientHandle client, FSDirHandle2 dirHandle, MEMPTR directoryEntry) + { + if (directoryEntry.IsNull()) + return FSA_RESULT::INVALID_BUFFER; + + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_ReadDir(shimBuffer->GetPtr(), client, dirHandle); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + if (result == FSA_RESULT::OK) + { + *directoryEntry = shimBuffer->GetPtr()->response.cmdReadDir.dirEntry; + } + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAOpenDir(FSAClientHandle client, char* path, MEMPTR dirHandle) + { + if (dirHandle.IsNull()) + return FSA_RESULT::INVALID_BUFFER; + + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_OpenDir(shimBuffer->GetPtr(), client, path); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + if (result == FSA_RESULT::OK) + { + *dirHandle = shimBuffer->GetPtr()->response.cmdOpenDir.dirHandleOutput; + } + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSACloseDir(FSAClientHandle client, FSDirHandle2 dirHandle) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_CloseDir(shimBuffer->GetPtr(), client, dirHandle); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSARewindDir(FSAClientHandle client, FSDirHandle2 dirHandle) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_RewindDir(shimBuffer->GetPtr(), client, dirHandle); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAOpenFileEx(FSAClientHandle client, char* path, char* mode, uint32 createMode, uint32 openFlag, uint32_t preallocSize, MEMPTR outFileHandle) + { + if (outFileHandle.IsNull()) + return FSA_RESULT::INVALID_BUFFER; + + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_OpenFile(shimBuffer->GetPtr(), client, path, mode, createMode, openFlag, preallocSize); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + if (result == FSA_RESULT::OK) + { + *outFileHandle = shimBuffer->GetPtr()->response.cmdOpenFile.fileHandleOutput; + } + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAGetStatFile(FSAClientHandle client, FSFileHandle2 fileHandle, MEMPTR outStat) + { + if (outStat.IsNull()) + return FSA_RESULT::INVALID_BUFFER; + + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_GetStatFile(shimBuffer->GetPtr(), client, fileHandle); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + if (result == FSA_RESULT::OK) + { + *outStat = shimBuffer->GetPtr()->response.cmdStatFile.statOut; + } + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSASetPosFile(FSAClientHandle client, FSFileHandle2 fileHandle, uint32_t pos) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_SetPosFile(shimBuffer->GetPtr(), client, fileHandle, pos); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSATruncateFile(FSAClientHandle client, FSFileHandle2 fileHandle) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_TruncateFile(shimBuffer->GetPtr(), client, fileHandle); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSARemove(FSAClientHandle client, char* path) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_Remove(shimBuffer->GetPtr(), client, (uint8_t*)path); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT __FSPrepareCmd_ChangeMode(iosu::fsa::FSAShimBuffer* fsaShimBuffer, IOSDevHandle fsaHandle, uint8_t* path, uint32 permission, uint32 permissionMask) + { + if (fsaShimBuffer == nullptr) + return FSA_RESULT::INVALID_BUFFER; + if (path == nullptr) + return FSA_RESULT::INVALID_PATH; + + fsaShimBuffer->fsaDevHandle = fsaHandle; + fsaShimBuffer->ipcReqType = 0; + fsaShimBuffer->operationType = (uint32)FSA_CMD_OPERATION_TYPE::REWINDDIR; + + size_t pathLen = strlen((char*)path); + + for (sint32 i = 0; i < pathLen; i++) + fsaShimBuffer->request.cmdChangeMode.path[i] = path[i]; + for (size_t i = pathLen; i < FSA_CMD_PATH_MAX_LENGTH; i++) + fsaShimBuffer->request.cmdChangeMode.path[i] = '\0'; + + fsaShimBuffer->request.cmdChangeMode.mode1 = permission; + fsaShimBuffer->request.cmdChangeMode.mode2 = permissionMask; + + return FSA_RESULT::OK; + } + + FSA_RESULT FSAChangeMode(FSAClientHandle client, const char* path, uint32 permission) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_ChangeMode(shimBuffer->GetPtr(), client, (uint8_t*)path, permission, 0x666); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAReadFile(FSAClientHandle client, void* buffer, uint32_t size, uint32_t count, FSFileHandle2 handle, uint32_t flags) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_ReadFile(shimBuffer->GetPtr(), client, buffer, size, count, 0, handle, flags & ~0x2); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAWriteFile(FSAClientHandle client, void* buffer, uint32_t size, uint32_t count, FSFileHandle2 handle, uint32_t flags) + { + if (!FSAShimCheckClientHandle(client)) + return FSA_RESULT::INVALID_CLIENT_HANDLE; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_WriteFile(shimBuffer->GetPtr(), client, buffer, size, count, 0, handle, flags & ~0x2); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAGetInfoByQuery(FSAClientHandle client, char* path, uint32_t queryType, MEMPTR outData) + { + if (outData.IsNull()) + return FSA_RESULT::INVALID_BUFFER; + + StackAllocator, 1> shimBuffer; + FSA_RESULT result = FSAShimAllocateBuffer(shimBuffer.GetPointer()); + if (result != FSA_RESULT::OK) + return result; + + result = __FSPrepareCmd_QueryInfo(shimBuffer->GetPtr(), client, (uint8_t*)path, queryType); + if (result == FSA_RESULT::OK) + { + result = __FSAIPCSubmitCommand(shimBuffer->GetPtr()); + if (result == FSA_RESULT::OK) + { + if (queryType == FSA_QUERY_TYPE_FREESPACE) + { + *MEMPTR(outData.GetMPTR()) = shimBuffer->GetPtr()->response.cmdQueryInfo.queryFreeSpace.freespace; + } + else if (queryType == FSA_QUERY_TYPE_DEVICE_INFO) + { + *MEMPTR(outData.GetMPTR()) = shimBuffer->GetPtr()->response.cmdQueryInfo.queryDeviceInfo.info; + } + else if (queryType == FSA_QUERY_TYPE_STAT) + { + *MEMPTR(outData.GetMPTR()) = shimBuffer->GetPtr()->response.cmdQueryInfo.queryStat.stat; + } + else + { + // TODO: implement other query types + cemu_assert_unimplemented(); + result = FSA_RESULT::FATAL_ERROR; + } + } + } + + FSAShimFreeBuffer(shimBuffer->GetPtr()); + return result; + } + + FSA_RESULT FSAGetStat(FSAClientHandle client, char* path, FSStat_t* outStat) + { + return FSAGetInfoByQuery(client, path, FSA_QUERY_TYPE_STAT, outStat); + } + + FSA_RESULT FSAGetFreeSpaceSize(FSAClientHandle client, char* path, uint64* outSize) + { + return FSAGetInfoByQuery(client, path, FSA_QUERY_TYPE_DEVICE_INFO, outSize); + } + + FSA_RESULT FSAGetDeviceInfo(FSAClientHandle client, char* path, void* outSize) + { + return FSAGetInfoByQuery(client, path, FSA_QUERY_TYPE_FREESPACE, outSize); + } + + SysAllocator s_fsaStr_OK("FSA_STATUS_OK"); + SysAllocator s_fsaStr_NOT_INIT("FSA_STATUS_NOT_INIT"); + SysAllocator s_fsaStr_END_OF_DIRECTORY("FSA_STATUS_END_OF_DIRECTORY"); + SysAllocator s_fsaStr_END_OF_FILE("FSA_STATUS_END_OF_FILE"); + SysAllocator s_fsaStr_MAX_CLIENTS("FSA_STATUS_MAX_CLIENTS"); + SysAllocator s_fsaStr_MAX_FILES("FSA_STATUS_MAX_FILES"); + SysAllocator s_fsaStr_MAX_DIRS("FSA_STATUS_MAX_DIRS"); + SysAllocator s_fsaStr_ALREADY_EXISTS("FSA_STATUS_ALREADY_EXISTS"); + SysAllocator s_fsaStr_NOT_FOUND("FSA_STATUS_NOT_FOUND"); + SysAllocator s_fsaStr_PERMISSION_ERROR("FSA_STATUS_PERMISSION_ERROR"); + SysAllocator s_fsaStr_INVALID_PARAM("FSA_STATUS_INVALID_PARAM"); + SysAllocator s_fsaStr_INVALID_PATH("FSA_STATUS_INVALID_PATH"); + SysAllocator s_fsaStr_INVALID_BUFFER("FSA_STATUS_INVALID_BUFFER"); + SysAllocator s_fsaStr_INVALID_ALIGNMENT("FSA_STATUS_INVALID_ALIGNMENT"); + SysAllocator s_fsaStr_INVALID_CLIENT_HANDLE("FSA_STATUS_INVALID_CLIENT_HANDLE"); + SysAllocator s_fsaStr_INVALID_FILE_HANDLE("FSA_STATUS_INVALID_FILE_HANDLE"); + SysAllocator s_fsaStr_INVALID_DIR_HANDLE("FSA_STATUS_INVALID_DIR_HANDLE"); + SysAllocator s_fsaStr_NOT_FILE("FSA_STATUS_NOT_FILE"); + SysAllocator s_fsaStr_NOT_DIR("FSA_STATUS_NOT_DIR"); + SysAllocator s_fsaStr_OUT_OF_RESOURCES("FSA_STATUS_OUT_OF_RESOURCES"); + SysAllocator s_fsaStr_UNKNOWN("FSA_STATUS_???"); + + const char* FSAGetStatusStr(FSA_RESULT status) + { + switch (status) + { + case FSA_RESULT::OK: + { + return s_fsaStr_OK.GetPtr(); + } + case FSA_RESULT::NOT_INIT: + { + return s_fsaStr_NOT_INIT.GetPtr(); + } + case FSA_RESULT::END_OF_DIRECTORY: + { + return s_fsaStr_END_OF_DIRECTORY.GetPtr(); + } + case FSA_RESULT::END_OF_FILE: + { + return s_fsaStr_END_OF_FILE.GetPtr(); + } + case FSA_RESULT::MAX_CLIENTS: + { + return s_fsaStr_MAX_CLIENTS.GetPtr(); + } + case FSA_RESULT::MAX_FILES: + { + return s_fsaStr_MAX_FILES.GetPtr(); + } + case FSA_RESULT::MAX_DIRS: + { + return s_fsaStr_MAX_DIRS.GetPtr(); + } + case FSA_RESULT::ALREADY_EXISTS: + { + return s_fsaStr_ALREADY_EXISTS.GetPtr(); + } + case FSA_RESULT::NOT_FOUND: + { + return s_fsaStr_NOT_FOUND.GetPtr(); + } + case FSA_RESULT::PERMISSION_ERROR: + { + return s_fsaStr_PERMISSION_ERROR.GetPtr(); + } + case FSA_RESULT::INVALID_PARAM: + { + return s_fsaStr_INVALID_PARAM.GetPtr(); + } + case FSA_RESULT::INVALID_PATH: + { + return s_fsaStr_INVALID_PATH.GetPtr(); + } + case FSA_RESULT::INVALID_BUFFER: + { + return s_fsaStr_INVALID_BUFFER.GetPtr(); + } + case FSA_RESULT::INVALID_ALIGNMENT: + { + return s_fsaStr_INVALID_ALIGNMENT.GetPtr(); + } + case FSA_RESULT::INVALID_CLIENT_HANDLE: + { + return s_fsaStr_INVALID_CLIENT_HANDLE.GetPtr(); + } + case FSA_RESULT::INVALID_FILE_HANDLE: + { + return s_fsaStr_INVALID_FILE_HANDLE.GetPtr(); + } + case FSA_RESULT::INVALID_DIR_HANDLE: + { + return s_fsaStr_INVALID_DIR_HANDLE.GetPtr(); + } + case FSA_RESULT::NOT_FILE: + { + return s_fsaStr_NOT_FILE.GetPtr(); + } + case FSA_RESULT::NOT_DIR: + { + return s_fsaStr_NOT_DIR.GetPtr(); + } + case FSA_RESULT::OUT_OF_RESOURCES: + { + return s_fsaStr_OUT_OF_RESOURCES.GetPtr(); + } + case FSA_RESULT::FATAL_ERROR: + { + return s_fsaStr_UNKNOWN.GetPtr(); + } + } + cemu_assert_unimplemented(); + return s_fsaStr_UNKNOWN.GetPtr(); + } + + FSA_RESULT FSAMount(FSAClientHandle client, const char* source, const char* target, uint32 flags, void* arg_buf, uint32_t arg_len) + { + if ("/dev/sdcard01" == std::string_view(source) && "/vol/external01" == std::string_view(target) && flags == 0 && arg_buf == nullptr && arg_len == 0) + { + mountSDCard(); + return FSA_RESULT::OK; + } + else + { + cemu_assert_unimplemented(); + } + + return FSA_RESULT::FATAL_ERROR; + } + + FSA_RESULT FSAUnmount(FSAClientHandle client, + const char* mountedTarget, + uint32 flags) + { + return FSA_RESULT::OK; + } + void InitializeFS() { cafeExportRegister("coreinit", FSInit, LogType::CoreinitFile); @@ -1957,6 +2726,36 @@ namespace coreinit cafeExportRegister("coreinit", FSGetErrorCodeForViewer, LogType::Placeholder); cafeExportRegister("coreinit", FSGetLastErrorCodeForViewer, LogType::Placeholder); + cafeExportRegister("coreinit", FSAMakeDir, LogType::Placeholder); + cafeExportRegister("coreinit", FSAInit, LogType::Placeholder); + cafeExportRegister("coreinit", FSAAddClient, LogType::Placeholder); + cafeExportRegister("coreinit", FSADelClient, LogType::Placeholder); + cafeExportRegister("coreinit", FSARewindDir, LogType::Placeholder); + cafeExportRegister("coreinit", FSAGetDeviceInfo, LogType::Placeholder); + cafeExportRegister("coreinit", FSARename, LogType::Placeholder); + + cafeExportRegister("coreinit", FSAChangeDir, LogType::Placeholder); + + cafeExportRegister("coreinit", FSAMount, LogType::Placeholder); + cafeExportRegister("coreinit", FSAUnmount, LogType::Placeholder); + + cafeExportRegister("coreinit", FSAChangeMode, LogType::Placeholder); + cafeExportRegister("coreinit", FSAReadDir, LogType::Placeholder); + cafeExportRegister("coreinit", FSAOpenDir, LogType::Placeholder); + cafeExportRegister("coreinit", FSACloseDir, LogType::Placeholder); + cafeExportRegister("coreinit", FSACloseFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSAFlushFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSAOpenFileEx, LogType::Placeholder); + cafeExportRegister("coreinit", FSAGetStatFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSAGetFreeSpaceSize, LogType::Placeholder); + cafeExportRegister("coreinit", FSASetPosFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSATruncateFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSARemove, LogType::Placeholder); + cafeExportRegister("coreinit", FSAReadFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSAWriteFile, LogType::Placeholder); + cafeExportRegister("coreinit", FSAGetStat, LogType::Placeholder); + cafeExportRegister("coreinit", FSAGetStatusStr, LogType::Placeholder); + g_fsRegisteredClientBodies = nullptr; } } // namespace coreinit diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.h b/src/Cafe/OS/libs/coreinit/coreinit_FS.h index e6b7a29c..74cbeec7 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.h @@ -12,6 +12,8 @@ typedef struct typedef MEMPTR> FSDirHandlePtr; +typedef uint32 FSAClientHandle; + typedef struct { MEMPTR userCallback; diff --git a/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.cpp b/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.cpp index 33f3e7c2..9345d58f 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.cpp @@ -1,40 +1,9 @@ #include "Cafe/OS/common/OSCommon.h" #include "Cafe/OS/libs/coreinit/coreinit_Thread.h" +#include "coreinit_IPCBuf.h" namespace coreinit { - - struct FIFOEntry_t - { - MEMPTR p; - }; - - struct IPCFifo_t - { - uint32be writeIndex; - uint32be readIndex; - uint32be availableEntries; // number of available entries - uint32be entryCount; - MEMPTR entryArray; - }; - - struct IPCBufPool_t - { - /* +0x00 */ uint32be magic; - /* +0x04 */ MEMPTR fullBufferPtr; - /* +0x08 */ uint32be fullBufferSize; - /* +0x0C */ uint32be uknFromParamR7; // boolean? - /* +0x10 */ uint32be ukn10; // set to zero on init - /* +0x14 */ uint32be entrySize1; - /* +0x18 */ uint32be entrySize2; // set to same value as entrySize1 - /* +0x1C */ uint32be entryCount; // actual number of used entries - /* +0x20 */ MEMPTR entryStartPtr; - /* +0x24 */ uint32be entryCountMul4; - /* +0x28 */ IPCFifo_t fifo; - /* +0x3C */ coreinit::OSMutex mutex; - // full size is 0x68 - }; - void FIFOInit(IPCFifo_t* fifo, uint32 entryCount, void* entryArray) { fifo->entryCount = entryCount; @@ -90,8 +59,6 @@ namespace coreinit return (uint8*)v; } - static_assert(sizeof(IPCBufPool_t) == 0x68); - IPCBufPool_t* IPCBufPoolCreate(uint8* bufferArea, uint32 bufferSize, uint32 entrySize, uint32be* entryCountOutput, uint32 uknR7) { memset(bufferArea, 0, bufferSize); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.h b/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.h index 004fb178..bfb29397 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_IPCBuf.h @@ -2,5 +2,43 @@ namespace coreinit { + struct FIFOEntry_t + { + MEMPTR p; + }; + + struct IPCFifo_t + { + uint32be writeIndex; + uint32be readIndex; + uint32be availableEntries; // number of available entries + uint32be entryCount; + MEMPTR entryArray; + }; + + struct IPCBufPool_t + { + /* +0x00 */ uint32be magic; + /* +0x04 */ MEMPTR fullBufferPtr; + /* +0x08 */ uint32be fullBufferSize; + /* +0x0C */ uint32be uknFromParamR7; // boolean? + /* +0x10 */ uint32be ukn10; // set to zero on init + /* +0x14 */ uint32be entrySize1; + /* +0x18 */ uint32be entrySize2; // set to same value as entrySize1 + /* +0x1C */ uint32be entryCount; // actual number of used entries + /* +0x20 */ MEMPTR entryStartPtr; + /* +0x24 */ uint32be entryCountMul4; + /* +0x28 */ IPCFifo_t fifo; + /* +0x3C */ coreinit::OSMutex mutex; + /* +0x68 */ uint32 ukn68; + // full size is 0x6C + }; + + static_assert(sizeof(IPCBufPool_t) == 0x6C); + + uint8* IPCBufPoolAllocate(IPCBufPool_t* ipcBufPool, uint32 size); + IPCBufPool_t* IPCBufPoolCreate(uint8* bufferArea, uint32 bufferSize, uint32 entrySize, uint32be* entryCountOutput, uint32 uknR7); + sint32 IPCBufPoolFree(IPCBufPool_t* ipcBufPool, uint8* entry); + void InitializeIPCBuf(); -} +} // namespace coreinit diff --git a/src/Common/SysAllocator.h b/src/Common/SysAllocator.h index a9bc0da1..7930a16b 100644 --- a/src/Common/SysAllocator.h +++ b/src/Common/SysAllocator.h @@ -49,6 +49,13 @@ public: m_tempData.insert(m_tempData.end(), count - l.size(), T()); } + template + SysAllocator(const char(&str)[N]) + { + m_tempData.reserve(count); + m_tempData.insert(m_tempData.begin(), str, str + N); + } + constexpr uint32 GetCount() const { return count; @@ -135,6 +142,9 @@ private: std::vector m_tempData; }; +template +SysAllocator(const char(&str)[N]) -> SysAllocator; + template class SysAllocator : public SysAllocatorBase {