diff --git a/librecomp/src/pak.cpp b/librecomp/src/pak.cpp index af3b138..f8d42c3 100644 --- a/librecomp/src/pak.cpp +++ b/librecomp/src/pak.cpp @@ -1,630 +1,189 @@ -#include -#include -#include -#include "ultramodern/ultra64.h" #include "ultramodern/ultramodern.hpp" -#include "recomp.h" #include "helpers.hpp" -#define PAK_DEBUG 0 -#define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) -#define MAX_FILES 16 - -#if PAK_DEBUG -#define TRACE_ENTRY() fprintf(stderr, "PAK_ENTRY(%s)\n", __func__); -#else -#define TRACE_ENTRY() -#endif - -typedef struct ControllerPak { - std::fstream header; - std::fstream file; -} ControllerPak; - -// extern std::filesystem::path config_path; -// const std::u8string save_folder = u8"saves"; -// std::filesystem::path save_folder_path = config_path / save_folder; - -void Pfs_PakHeader_Write(u32* file_size, u32* game_code, u16* company_code, u8* ext_name, u8* game_name, u8 fileIndex) { - ControllerPak pak; - - pak.header.open("controllerPak_header.sav", std::ios::binary | std::ios::in | std::ios::out); - - if (!pak.header.good()) { - assert(false); - } - if (!pak.header.is_open()) { - assert(false); - } - - /* Set file parameters to header */ - u32 seek = fileIndex * 0x20; - - // file_size - pak.header.seekp(seek + 0x0, std::ios::beg); - pak.header.write((char*) file_size, 4); - // game_code - pak.header.seekp(seek + 0x4, std::ios::beg); - pak.header.write((char*) game_code, 4); - // company_code - pak.header.seekp(seek + 0x08, std::ios::beg); - pak.header.write((char*) company_code, 2); - // ext_name - pak.header.seekp(seek + 0xC, std::ios::beg); - pak.header.write((char*) ext_name, 4); - // game_name - pak.header.seekp(seek + 0x10, std::ios::beg); - pak.header.write((char*) game_name, 16); - - pak.header.close(); -} - -void Pfs_PakHeader_Read(u32* file_size, u32* game_code, u16* company_code, u8* ext_name, u8* game_name, u8 fileIndex) { - ControllerPak pak; - - pak.header.open("controllerPak_header.sav", std::ios::binary | std::ios::in | std::ios::out); - - if (!pak.header.good()) { - assert(false); - } - if (!pak.header.is_open()) { - assert(false); - } - - /* Set file parameters to header */ - u32 seek = fileIndex * sizeof(OSPfsState); - - // file_size - pak.header.seekg(seek + 0x0, std::ios::beg); - pak.header.read((char*) file_size, 4); - // game_code - pak.header.seekg(seek + 0x4, std::ios::beg); - pak.header.read((char*) game_code, 4); - // company_code - pak.header.seekg(seek + 0x08, std::ios::beg); - pak.header.read((char*) company_code, 2); - // ext_name - pak.header.seekg(seek + 0xC, std::ios::beg); - pak.header.read((char*) ext_name, 4); - // game_name - pak.header.seekg(seek + 0x10, std::ios::beg); - pak.header.read((char*) game_name, 16); - - pak.header.close(); -} - -void Pfs_ByteSwapFile(u8* buffer, size_t size) { - uint8_t c0, c1, c2, c3; - - for (size_t i = 0; i < size; i += 4) { - c0 = buffer[i + 0]; - c1 = buffer[i + 1]; - c2 = buffer[i + 2]; - c3 = buffer[i + 3]; - - buffer[i + 3] = c0; - buffer[i + 2] = c1; - buffer[i + 1] = c2; - buffer[i + 0] = c3; - } -} - -void ByteSwapCopy(uint8_t* dst, uint8_t* src, size_t size_bytes) { - for (size_t i = 0; i < size_bytes; i++) { - dst[i] = src[i ^ 3]; - } -} - -extern "C" void osPfsGetLabel_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsIsPlug_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - - PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx); - PTR(u8) bitpattern = _arg<1, PTR(u8)>(rdram, ctx); - - MEM_B(0, bitpattern) = 0b0001; - - _return(ctx, 0); -} - -extern "C" void osPfsInit_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - int32_t queue = _arg<0, int32_t>(rdram, ctx); - OSPfs* pfs = _arg<1, OSPfs*>(rdram, ctx); - s32 channel = _arg<2, s32>(rdram, ctx); - - pfs->queue = queue; - pfs->channel = channel; - pfs->status = 0x1; - - ControllerPak pak; - - // If a header file doesn't exist, create it. - if (!std::filesystem::exists("controllerPak_header.sav")) { - pak.header.open("controllerPak_header.sav", std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc); - pak.header.close(); - } - - ctx->r2 = 0; // PFS_NO_ERROR -} - extern "C" void osPfsInitPak_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - int32_t queue = _arg<0, int32_t>(rdram, ctx); - OSPfs* pfs = _arg<1, OSPfs*>(rdram, ctx); - s32 channel = _arg<2, s32>(rdram, ctx); + PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx); + PTR(OSPfs) pfs = _arg<1, PTR(OSPfs)>(rdram, ctx); + int channel = _arg<2, int>(rdram, ctx); - pfs->queue = queue; - pfs->channel = channel; - pfs->status = 0x1; - - ControllerPak pak; - - // If a header file doesn't exist, create it. - if (!std::filesystem::exists("controllerPak_header.sav")) { - pak.header.open("controllerPak_header.sav", std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc); - pak.header.close(); - } - -// Test -#if PAK_DEBUG - u32 file_size_ = 0x01020304; - u32 game_code_ = 0x05060708; - u16 company_code_ = 0x0910; - u8 ext_name_[4] = { 0x11, 0x12, 0x13, 0x14 }; - u8 game_name_[16] = { 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24 }; - - Pfs_PakHeader_Write(&file_size_, &game_code_, &company_code_, ext_name_, game_name_, 0); - - Pfs_PakHeader_Read(&file_size_, &game_code_, &company_code_, ext_name_, game_name_, 0); - - printf("TEST\n"); - printf("file_size_: %x\n", file_size_); - printf("game_code: %x\n", game_code_); - printf("company_code: %x\n", company_code_); - - printf("ext_name: "); - for (size_t i = 0; i < 4; i++) { - printf("%x", ext_name_[i]); - } - printf("\n"); - - printf("game_name: "); - for (size_t i = 0; i < 16; i++) { - printf("%x", game_name_[i]); - } - printf("\n"); -#endif - - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsFreeBlocks_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - s32* bytes_not_used = _arg<1, s32*>(rdram, ctx); - - s32 usedSpace = 0; - for (size_t i = 0; i < MAX_FILES; i++) { - u32 file_size = 0; - u32 game_code = 0; - u16 company_code = 0; - u8 ext_name[4] = { 0 }; - u8 game_name[16] = { 0 }; - - Pfs_PakHeader_Read(&file_size, &game_code, &company_code, ext_name, game_name, i); - - if ((company_code == 0) || (game_code == 0)) { - continue; - } else { - usedSpace += file_size >> 8; - } - } - - *bytes_not_used = (123 - usedSpace) << 8; - - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsAllocateFile_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - u16 company_code = _arg<1, u16>(rdram, ctx); - u32 game_code = _arg<2, u32>(rdram, ctx); - u8* game_name = _arg<3, u8*>(rdram, ctx); - u8* ext_name = TO_PTR(u8, MEM_W(0x10, ctx->r29)); - u32 file_size = (s32) MEM_W(0x14, ctx->r29); - s32* file_no = TO_PTR(s32, MEM_W(0x18, ctx->r29)); - - if ((company_code == 0) || (game_code == 0)) { - ctx->r2 = 5; // PFS_ERR_INVALID - return; - } - - /* Search for a free slot */ - u8 freeFileIndex = 0; - for (size_t i = 0; i < MAX_FILES; i++) { - u32 file_size_ = 0; - u32 game_code_ = 0; - u16 company_code_ = 0; - u8 ext_name_[4] = { 0 }; - u8 game_name_[16] = { 0 }; - - Pfs_PakHeader_Read(&file_size_, &game_code_, &company_code_, ext_name_, game_name_, i); - - if ((company_code_ == 0) || (game_code_ == 0)) { - freeFileIndex = i; - break; - } - } - - if (freeFileIndex == MAX_FILES) { - ctx->r2 = 8; // PFS_DIR_FULL - return; - } - - Pfs_PakHeader_Write(&file_size, &game_code, &company_code, ext_name, game_name, freeFileIndex); - - /* Create empty file */ - - ControllerPak pak; - - char filename[100]; - sprintf(filename, "controllerPak_file_%d.sav", freeFileIndex); - pak.file.open(filename, std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc); - - file_size = (file_size + 31) & ~31; - - u8* zero_block = (u8*) malloc(file_size); - memset(zero_block, 0, file_size); - - pak.file.seekp(0, std::ios::beg); - pak.file.write((char*) zero_block, file_size); - - free(zero_block); - - pak.file.close(); - - *file_no = freeFileIndex; - - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsFileState_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - s32 file_no = _arg<1, s32>(rdram, ctx); - OSPfsState* state = _arg<2, OSPfsState*>(rdram, ctx); - - u32 file_size = 0; - u32 game_code = 0; - u16 company_code = 0; - u8 ext_name[4] = { 0 }; - u8 game_name[16] = { 0 }; - - // should pass the state of the requested file_no to the incoming state pointer, - // games call this function 16 times, once per file - // fills the incoming state with the information inside the header of the pak. - - char filename[100]; - sprintf(filename, "controllerPak_file_%d.sav", file_no); - if (!std::filesystem::exists(filename)) { - ctx->r2 = 5; - return; - } - - /* Read game info from pak */ - Pfs_PakHeader_Read(&file_size, &game_code, &company_code, ext_name, game_name, file_no); - - // Test code -#if 0 - for (size_t i = 0; i < 5; i++) { - ext_name[i] = i + 1; - } - - for (size_t i = 0; i < 16; i++) { - game_name[i] = i + 1; - } -#endif - -#if 1 - state->file_size = file_size; - state->company_code = company_code; - state->game_code = game_code; - - for (size_t j = 0; j < ARRAY_COUNT(game_name); j++) { - state->game_name[j] = game_name[j]; - } - for (size_t j = 0; j < ARRAY_COUNT(ext_name); j++) { - state->ext_name[j] = ext_name[j]; - } -#else - u8* ptr = (u8*) state; - *(u32*) &ptr[0] = file_size; - *(u32*) &ptr[0x4] = game_code; - *(u16*) &ptr[0xA] = company_code; - - // printf("*(u16*) &ptr[0x8] = company_code; : %x\n", ptr[0xA]); - - char* ext_name_ = (char*) &ptr[0xC]; - char* game_name_ = (char*) &ptr[0x10]; - - for (size_t j = 0; j < 4; j++) { - ext_name_[j] = ext_name[j]; - } - for (size_t j = 0; j < 16; j++) { - game_name_[j] = game_name[j]; - } -#endif - -#if PAK_DEBUG - if (file_no == 0) { - printf("osPfsFileState_recomp: STORE IN GAME PTR\n"); - printf("file_size: %x\n", state->file_size); - printf("company_code: %x\n", state->company_code); - printf("game_code: %x\n", state->game_code); - - printf("game_name: "); - for (size_t i = 0; i < 16; i++) { - printf("%x", game_name[i]); - } - printf("\n"); - - printf("ext_name: "); - for (size_t i = 0; i < 4; i++) { - printf("%x", ext_name[i]); - } - printf("\n"); - } -#endif - - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsFindFile_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - u16 company_code = _arg<1, u16>(rdram, ctx); - u32 game_code = _arg<2, u32>(rdram, ctx); - u8* game_name = _arg<3, u8*>(rdram, ctx); - u8* ext_name = TO_PTR(u8, MEM_W(0x10, ctx->r29)); - s32* file_no = TO_PTR(s32, MEM_W(0x14, ctx->r29)); - - for (size_t i = 0; i < MAX_FILES; i++) { - u32 file_size_ = 0; - u32 game_code_ = 0; - u16 company_code_ = 0; - u8 ext_name_[4] = { 0 }; - u8 game_name_[16] = { 0 }; - - Pfs_PakHeader_Read(&file_size_, &game_code_, &company_code_, ext_name_, game_name_, i); - - if ((company_code_ == 0) || (game_code_ == 0)) { - continue; - } else { - if ((game_code == game_code_) && (company_code == company_code_)) { - for (size_t i = 0; i < ARRAY_COUNT(game_name_); i++) { - if (game_name[i] != game_name_[i]) { - break; - } - } - for (size_t i = 0; i < ARRAY_COUNT(ext_name_); i++) { - if (ext_name[i] != ext_name_[i]) { - break; - } - } - // File found - *file_no = i; - ctx->r2 = 0; // PFS_NO_ERROR - return; - } - } - } - - // File not found - ctx->r2 = 5; // PFS_ERR_INVALID -} - -extern "C" void osPfsReadWriteFile_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - s32 file_no = _arg<1, s32>(rdram, ctx); - u8 flag = _arg<2, u8>(rdram, ctx); - s32 offset = _arg<3, s32>(rdram, ctx); - s32 size_in_bytes = (s32) MEM_W(0x10, ctx->r29); - u8* data_buffer = TO_PTR(u8, MEM_W(0x14, ctx->r29)); - - ControllerPak pak; - - char filename[100]; - sprintf(filename, "controllerPak_file_%d.sav", file_no); - pak.file.open(filename, std::ios::binary | std::ios::in | std::ios::out); - - if (!std::filesystem::exists(filename)) { - ctx->r2 = 5; // PFS_ERR_INVALID - return; - } - if (!pak.file.good()) { - ctx->r2 = 5; // PFS_ERR_INVALID - return; - } - if (!pak.file.is_open()) { - ctx->r2 = 5; // PFS_ERR_INVALID - return; - } - - u8* swapBuffer = (u8*) malloc(size_in_bytes); - if (flag == 0) { - pak.file.seekg(offset, std::ios::beg); - pak.file.read((char*) swapBuffer, size_in_bytes); - ByteSwapCopy(data_buffer, swapBuffer, size_in_bytes); - } else { - ByteSwapCopy(swapBuffer, data_buffer, size_in_bytes); - pak.file.seekp(offset, std::ios::beg); - pak.file.write((char*) swapBuffer, size_in_bytes); - } - free(swapBuffer); - - pak.file.close(); - - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsChecker_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsNumFiles_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - s32* max_files = _arg<1, s32*>(rdram, ctx); - s32* files_used = _arg<2, s32*>(rdram, ctx); - - u8 files = 0; - for (size_t i = 0; i < MAX_FILES; i++) { - u32 file_size = 0; - u32 game_code = 0; - u16 company_code = 0; - u8 ext_name[4] = { 0 }; - u8 game_name[16] = { 0 }; - - Pfs_PakHeader_Read(&file_size, &game_code, &company_code, ext_name, game_name, i); - - if ((company_code != 0) || (game_code != 0)) { - files++; - } - } - - *files_used = files; - *max_files = MAX_FILES; - - ctx->r2 = 0; // PFS_NO_ERROR -} - -extern "C" void osPfsDeleteFile_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - u16 company_code = _arg<1, u16>(rdram, ctx); - u32 game_code = _arg<2, u32>(rdram, ctx); - u8* game_name = _arg<3, u8*>(rdram, ctx); - u8* ext_name = TO_PTR(u8, MEM_W(0x10, ctx->r29)); - - // WORKAROUND! This shouldn't be necessary, there's something wrong with the OSPfsState struct - game_name += 2; - ext_name += 2; - -#if PAK_DEBUG - printf("osPfsDeleteFile_recomp: REQUEST\n"); - printf(" company_code: %x\n", company_code); - printf(" game_code: %x\n", game_code); - - printf(" ext_name: "); - for (size_t i = 0; i < 4; i++) { - printf("%x", ext_name[i]); - } - printf("\n"); - - printf(" game_name: "); - for (size_t i = 0; i < 16; i++) { - printf("%x", game_name[i]); - } - printf("\n"); -#endif - - if (company_code == 0 || game_code == 0) { - ctx->r2 = 5; // PFS_ERR_INVALID - return; - } - - ControllerPak pak; - - for (int i = 0; i < MAX_FILES; i++) { - u32 file_size_ = 0; - u32 game_code_ = 0; - u16 company_code_ = 0; - u8 ext_name_[4] = { 0 }; - u8 game_name_[16] = { 0 }; - - Pfs_PakHeader_Read(&file_size_, &game_code_, &company_code_, ext_name_, game_name_, i); - -#if PAK_DEBUG - if (i == 0) { - printf("osPfsDeleteFile_recomp: READ\n"); - printf("company_code: %x\n", company_code_); - printf("game_code: %x\n", game_code_); - - printf("ext_name_: "); - for (size_t i = 0; i < 4; i++) { - printf("%x", ext_name_[i]); - } - printf("\n"); - - printf("game_name_: "); - for (size_t i = 0; i < 16; i++) { - printf("%x", game_name_[i]); - } - printf("\n"); - } -#endif - - if ((company_code_ == 0) || (game_code_ == 0)) { - continue; - } else { - if ((game_code == game_code_) && (company_code == company_code_)) { - int gncount = 0; - int encount = 0; - - for (size_t i = 0; i < ARRAY_COUNT(game_name_); i++) { - if (game_name[i] == game_name_[i]) { - gncount++; - } - } - for (size_t i = 0; i < ARRAY_COUNT(ext_name_); i++) { - if (ext_name[i] == ext_name_[i]) { - encount++; - } - } - if ((gncount != 16) || encount != 4) { - continue; - } - // File found - - pak.header.open("controllerPak_header.sav", std::ios::binary | std::ios::in | std::ios::out); - - if (!pak.header.good()) { - assert(false); - } - if (!pak.header.is_open()) { - assert(false); - } - - u32 seek = i * sizeof(OSPfsState); - - // Zero out the header for this file. - u8* zero_block = (u8*) malloc(sizeof(OSPfsState)); - memset(zero_block, 0, sizeof(OSPfsState)); - pak.header.seekp(seek + 0x0, std::ios::beg); - pak.header.write((char*) zero_block, sizeof(OSPfsState)); - free(zero_block); - - pak.header.close(); - - char filename[100]; - sprintf(filename, "controllerPak_file_%d.sav", i); - remove(filename); - - ctx->r2 = 0; // PFS_NO_ERROR - return; - } - } - } - - // File not found - ctx->r2 = 5; // PFS_ERR_INVALID - return; + s32 ret = osPfsInitPak(PASS_RDRAM mq, pfs, channel); + _return(ctx, ret); } extern "C" void osPfsRepairId_recomp(uint8_t* rdram, recomp_context* ctx) { - TRACE_ENTRY() - _return(ctx, 0); // PFS_NO_ERROR + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + + s32 ret = osPfsRepairId(PASS_RDRAM pfs); + _return(ctx, ret); +} + +extern "C" void osPfsInit_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx); + PTR(OSPfs) pfs = _arg<1, PTR(OSPfs)>(rdram, ctx); + int channel = _arg<2, int>(rdram, ctx); + + s32 ret = osPfsInit(PASS_RDRAM mq, pfs, channel); + _return(ctx, ret); +} + +extern "C" void osPfsReFormat_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + PTR(OSMesgQueue) mq = _arg<1, PTR(OSMesgQueue)>(rdram, ctx); + int channel = _arg<2, int>(rdram, ctx); + + s32 ret = osPfsReFormat(PASS_RDRAM pfs, mq, channel); + _return(ctx, ret); +} + +extern "C" void osPfsChecker_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + + s32 ret = osPfsChecker(PASS_RDRAM pfs); + _return(ctx, ret); +} + +extern "C" void osPfsAllocateFile_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + u16 company_code = _arg<1, u16>(rdram, ctx); + u32 game_code = _arg<2, u32>(rdram, ctx); + PTR(u8) game_name = _arg<3, PTR(u8)>(rdram, ctx); + PTR(u8) ext_name = _arg<4, PTR(u8)>(rdram, ctx); + int file_size = _arg<5, int>(rdram, ctx); + PTR(s32) file_no = _arg<6, PTR(s32)>(rdram, ctx); + u8 game_name_proxy[PFS_FILE_NAME_LEN]; + u8 ext_name_proxy[PFS_FILE_EXT_LEN]; + + for (uint32_t i = 0; i < PFS_FILE_NAME_LEN; i++) { + game_name_proxy[i] = MEM_B(i, game_name); + } + for (uint32_t i = 0; i < PFS_FILE_EXT_LEN; i++) { + ext_name_proxy[i] = MEM_B(i, ext_name); + } + s32 ret = osPfsAllocateFile(PASS_RDRAM pfs, company_code, game_code, game_name_proxy, ext_name_proxy, file_size, file_no); + _return(ctx, ret); +} + +extern "C" void osPfsFindFile_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + u16 company_code = _arg<1, u16>(rdram, ctx); + u32 game_code = _arg<2, u32>(rdram, ctx); + PTR(u8) game_name = _arg<3, PTR(u8)>(rdram, ctx); + PTR(u8) ext_name = _arg<4, PTR(u8)>(rdram, ctx); + PTR(s32) file_no = _arg<5, PTR(s32)>(rdram, ctx); + u8 game_name_proxy[PFS_FILE_NAME_LEN]; + u8 ext_name_proxy[PFS_FILE_EXT_LEN]; + + for (uint32_t i = 0; i < PFS_FILE_NAME_LEN; i++) { + game_name_proxy[i] = MEM_B(i, game_name); + } + for (uint32_t i = 0; i < PFS_FILE_EXT_LEN; i++) { + ext_name_proxy[i] = MEM_B(i, ext_name); + } + s32 ret = osPfsFindFile(PASS_RDRAM pfs, company_code, game_code, game_name_proxy, ext_name_proxy, file_no); + _return(ctx, ret); +} + +extern "C" void osPfsDeleteFile_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + u16 company_code = _arg<1, u16>(rdram, ctx); + u32 game_code = _arg<2, u32>(rdram, ctx); + PTR(u8) game_name = _arg<3, PTR(u8)>(rdram, ctx); + PTR(u8) ext_name = _arg<4, PTR(u8)>(rdram, ctx); + u8 game_name_proxy[PFS_FILE_NAME_LEN]; + u8 ext_name_proxy[PFS_FILE_EXT_LEN]; + + for (uint32_t i = 0; i < PFS_FILE_NAME_LEN; i++) { + game_name_proxy[i] = MEM_B(i, game_name); + } + for (uint32_t i = 0; i < PFS_FILE_EXT_LEN; i++) { + ext_name_proxy[i] = MEM_B(i, ext_name); + } + s32 ret = osPfsDeleteFile(PASS_RDRAM pfs, company_code, game_code, game_name_proxy, ext_name_proxy); + _return(ctx, ret); +} + +extern "C" void osPfsReadWriteFile_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + s32 file_no = _arg<1, s32>(rdram, ctx); + u8 flag = _arg<2, u8>(rdram, ctx); + int offset = _arg<3, int>(rdram, ctx); + int nbytes = _arg<4, int>(rdram, ctx); + PTR(u8) data_buffer = _arg<5, PTR(u8)>(rdram, ctx); + std::vector data_buffer_proxy(nbytes); + + if (flag == PFS_WRITE) { + for (uint32_t i = 0; i < nbytes; i++) { + data_buffer_proxy[i] = MEM_B(i, data_buffer); + } + } + s32 ret = osPfsReadWriteFile(PASS_RDRAM pfs, file_no, flag, offset, nbytes, data_buffer_proxy.data()); + if (flag == PFS_READ) { + for (uint32_t i = 0; i < nbytes; i++) { + MEM_B(i, data_buffer) = data_buffer_proxy[i]; + } + } + _return(ctx, ret); +} + +extern "C" void osPfsFileState_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + s32 file_no = _arg<1, s32>(rdram, ctx); + PTR(OSPfsState) state = _arg<2, PTR(OSPfsState)>(rdram, ctx); + + s32 ret = osPfsFileState(PASS_RDRAM pfs, file_no, state); + _return(ctx, ret); +} + +extern "C" void osPfsGetLabel_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + PTR(u8) label = _arg<1, PTR(u8)>(rdram, ctx); + PTR(int) len = _arg<2, PTR(int)>(rdram, ctx); + u8 label_proxy[32]; + + s32 ret = osPfsGetLabel(PASS_RDRAM pfs, label_proxy, len); + for (uint32_t i = 0; i < 32; i++) { + MEM_B(i, label) = label_proxy[i]; + } + _return(ctx, ret); +} + +extern "C" void osPfsSetLabel_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + PTR(u8) label = _arg<1, PTR(u8)>(rdram, ctx); + u8 label_proxy[32]; + + for (uint32_t i = 0; i < 32; i++) { + label_proxy[i] = MEM_B(i, label); + } + s32 ret = osPfsSetLabel(PASS_RDRAM pfs, label_proxy); + _return(ctx, ret); +} + +extern "C" void osPfsIsPlug_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx); + PTR(u8) pattern = _arg<1, PTR(u8)>(rdram, ctx); + u8 pattern_proxy = 0; + + s32 ret = osPfsIsPlug(PASS_RDRAM mq, &pattern_proxy); + MEM_B(0, pattern) = pattern_proxy; + _return(ctx, ret); +} + +extern "C" void osPfsFreeBlocks_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + PTR(s32) bytes_not_used = _arg<1, PTR(s32)>(rdram, ctx); + + s32 ret = osPfsFreeBlocks(PASS_RDRAM pfs, bytes_not_used); + _return(ctx, ret); +} + +extern "C" void osPfsNumFiles_recomp(uint8_t* rdram, recomp_context* ctx) { + PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx); + PTR(s32) max_files = _arg<1, PTR(s32)>(rdram, ctx); + PTR(s32) files_used = _arg<2, PTR(s32)>(rdram, ctx); + + s32 ret = osPfsNumFiles(PASS_RDRAM pfs, max_files, files_used); + _return(ctx, ret); } diff --git a/ultramodern/include/ultramodern/ultra64.h b/ultramodern/include/ultramodern/ultra64.h index 4c5d432..8c743e7 100644 --- a/ultramodern/include/ultramodern/ultra64.h +++ b/ultramodern/include/ultramodern/ultra64.h @@ -74,6 +74,17 @@ typedef u64 OSTime; #define OS_EVENT_THREADSTATUS 13 /* CPU thread status: used by rmon */ #define OS_EVENT_PRENMI 14 /* Pre NMI interrupt */ +#define PFS_INODE_SIZE_PER_PAGE 128 +#define PFS_FILE_NAME_LEN 16 +#define PFS_FILE_EXT_LEN 4 +#define PFS_BLOCKSIZE 32 /* bytes */ +#define PFS_ONE_PAGE 8 /* blocks */ +#define PFS_MAX_BANKS 62 + +#define PFS_READ 0 +#define PFS_WRITE 1 +#define PFS_CREATE 2 + #define M_GFXTASK 1 #define M_AUDTASK 2 #define M_VIDTASK 3 @@ -322,6 +333,24 @@ s32 osMotorStop(RDRAM_ARG PTR(OSPfs)); s32 osMotorStart(RDRAM_ARG PTR(OSPfs)); s32 __osMotorAccess(RDRAM_ARG PTR(OSPfs), s32); +/* Controller PAK interface */ + +s32 osPfsInitPak(RDRAM_ARG PTR(OSMesgQueue) queue, PTR(OSPfs) pfs, int channel); +s32 osPfsRepairId(RDRAM_ARG PTR(OSPfs) pfs); +s32 osPfsInit(RDRAM_ARG PTR(OSMesgQueue) queue, PTR(OSPfs) pfs, int channel); +s32 osPfsReFormat(RDRAM_ARG PTR(OSPfs) pfs, PTR(OSMesgQueue) queue, int channel); +s32 osPfsChecker(RDRAM_ARG PTR(OSPfs) pfs); +s32 osPfsAllocateFile(RDRAM_ARG PTR(OSPfs) pfs, u16 company_code, u32 game_code, u8* game_name, u8* ext_name, int file_size_in_bytes, PTR(s32) file_no); +s32 osPfsFindFile(RDRAM_ARG PTR(OSPfs) pfs, u16 company_code, u32 game_code, u8* game_name, u8* ext_name, PTR(s32) file_no); +s32 osPfsDeleteFile(RDRAM_ARG PTR(OSPfs) pfs, u16 company_code, u32 game_code, u8* game_name, u8* ext_name); +s32 osPfsReadWriteFile(RDRAM_ARG PTR(OSPfs) pfs, s32 file_no, u8 flag, int offset, int size_in_bytes, u8* data_buffer); +s32 osPfsFileState(RDRAM_ARG PTR(OSPfs) pfs, s32 file_no, PTR(OSPfsState) state); +s32 osPfsGetLabel(RDRAM_ARG PTR(OSPfs) pfs, u8* label, PTR(int) len); +s32 osPfsSetLabel(RDRAM_ARG PTR(OSPfs) pfs, u8* label); +s32 osPfsIsPlug(RDRAM_ARG PTR(OSMesgQueue) mq, u8* pattern); +s32 osPfsFreeBlocks(RDRAM_ARG PTR(OSPfs) pfs, PTR(s32) bytes_not_used); +s32 osPfsNumFiles(RDRAM_ARG PTR(OSPfs) pfs, PTR(s32) max_files, PTR(s32) files_used); + #ifdef __cplusplus } // extern "C" #endif