diff --git a/Dockerfile b/Dockerfile index 582a63e..d6362a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM wiiuenv/devkitppc:20210101 COPY --from=wiiuenv/wiiupluginsystem:20210109 /artifacts $DEVKITPRO -COPY --from=wiiuenv/libromfs_wiiu:20210109133626639534 /artifacts $DEVKITPRO +COPY --from=wiiuenv/librpxloader:20210116 /artifacts $DEVKITPRO WORKDIR project \ No newline at end of file diff --git a/Makefile b/Makefile index e84cc46..7b860f5 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/wups/share/wups_rules WUT_ROOT := $(DEVKITPRO)/wut +WUMS_ROOT := $(DEVKITPRO)/wums #------------------------------------------------------------------------------- # TARGET is the name of the output @@ -38,15 +39,15 @@ CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__ CXXFLAGS := $(CFLAGS) ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) $(WUPSSPECS) +LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/librpxloader.ld $(WUPSSPECS) -LIBS := -lwups -lwut -lz -lromfs +LIBS := -lwups -lwut -lrpxloader #------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level # containing include and lib #------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUT_ROOT) $(WUT_ROOT)/usr +LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT) #------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional diff --git a/src/FileWrapper.cpp b/src/FileWrapper.cpp new file mode 100644 index 0000000..279e580 --- /dev/null +++ b/src/FileWrapper.cpp @@ -0,0 +1,70 @@ +#include "FileWrapper.h" +#include +#include "fileinfos.h" +#include +#include +#include +#include "utils/logger.h" +#include + +FileHandleWrapper gFileHandleWrapper[FILE_WRAPPER_SIZE] __attribute__((section(".data"))); + +int FileHandleWrapper_GetSlot() { + for (int i = 0; i < FILE_WRAPPER_SIZE; i++) { + if (!gFileHandleWrapper[i].inUse) { + gFileHandleWrapper[i].inUse = true; + DCFlushRange(&gFileHandleWrapper[i], sizeof(FileHandleWrapper)); + return i; + } + } + return -1; +} + +int OpenFileForID(int id, const char *filepath, int *handle) { + if (!mountRomfs(id)) { + return -1; + } + char romName[10]; + snprintf(romName, 10, "%08X", id); + + char *dyn_path = (char *) malloc(strlen(filepath) + 1); + char last = 0; + int j = 0; + for (int i = 0; filepath[i] != 0; i++) { + if (filepath[i] == '/') { + if (filepath[i] != last) { + dyn_path[j++] = filepath[i]; + } + } else { + dyn_path[j++] = filepath[i]; + } + last = filepath[i]; + } + dyn_path[j++] = 0; + + char completePath[256]; + snprintf(completePath, 256, "%s:/%s", romName, dyn_path); + free(dyn_path); + + uint32_t out_handle = 0; + if (RL_FileOpen(completePath, &out_handle) == 0) { + int handle_wrapper_slot = FileHandleWrapper_GetSlot(); + + if (handle_wrapper_slot < 0) { + DEBUG_FUNCTION_LINE("No free slot"); + RL_FileClose(out_handle); + return -2; + } + gFileHandleWrapper[handle_wrapper_slot].handle = out_handle; + *handle = 0xFF000000 | (id << 12) | (handle_wrapper_slot & 0x00000FFF); + gFileInfos[id].openedFiles++; + return 0; + } else { + if (gFileInfos[id].openedFiles == 0) { + DEBUG_FUNCTION_LINE("unmount"); + unmountRomfs(id); + } + } + + return -1; +} \ No newline at end of file diff --git a/src/FileWrapper.h b/src/FileWrapper.h new file mode 100644 index 0000000..9ed59d3 --- /dev/null +++ b/src/FileWrapper.h @@ -0,0 +1,12 @@ +#pragma once +#include + +typedef struct FileHandleWrapper_t { + uint32_t handle; + bool inUse; +} FileHandleWrapper; + +#define FILE_WRAPPER_SIZE 64 +extern FileHandleWrapper gFileHandleWrapper[FILE_WRAPPER_SIZE]; + +int OpenFileForID(int id, const char * path, int32_t * handle); \ No newline at end of file diff --git a/src/romfs_helper.cpp b/src/fileinfos.cpp similarity index 61% rename from src/romfs_helper.cpp rename to src/fileinfos.cpp index c8d8264..e2545d5 100644 --- a/src/romfs_helper.cpp +++ b/src/fileinfos.cpp @@ -1,8 +1,8 @@ -#include "romfs_helper.h" -#include "utils/logger.h" -#include "utils/StringTools.h" +#include #include -#include +#include +#include "utils/logger.h" +#include "fileinfos.h" FileInfos gFileInfos[FILE_INFO_SIZE] __attribute__((section(".data"))); @@ -23,7 +23,7 @@ void unmountRomfs(uint32_t id) { char romName[10]; snprintf(romName, 10, "%08X", id); DEBUG_FUNCTION_LINE("Unmounting %s", romName); - int res = romfsUnmount(romName); + int res = RL_UnmountBundle(romName); DEBUG_FUNCTION_LINE("res: %d", res); gFileInfos[id].romfsMounted = false; } @@ -47,7 +47,7 @@ bool mountRomfs(uint32_t id) { snprintf(romName, 10, "%08X", id); DEBUG_FUNCTION_LINE("Mount %s as %s", buffer, romName); int32_t res = 0; - if ((res = romfsMount(romName, buffer, RomfsSource_FileDescriptor_CafeOS)) == 0) { + if ((res = RL_MountBundle(romName, buffer, BundleSource_FileDescriptor_CafeOS)) == 0) { DEBUG_FUNCTION_LINE("Mounted successfully "); gFileInfos[id].romfsMounted = true; return true; @@ -57,40 +57,4 @@ bool mountRomfs(uint32_t id) { } } return true; -} - - -int32_t getRPXInfoForID(uint32_t id, romfs_fileInfo *info) { - if (!mountRomfs(id)) { - return -1; - } - DIR *dir; - struct dirent *entry; - char romName[10]; - snprintf(romName, 10, "%08X", id); - - char root[12]; - snprintf(root, 12, "%08X:/code/", id); - - if (!(dir = opendir(root))) { - return -2; - } - bool found = false; - int res = -3; - while ((entry = readdir(dir)) != NULL) { - if (StringTools::EndsWith(entry->d_name, ".rpx")) { - if (romfsGetFileInfoPerPath(romName, entry->d_name, info) >= 0) { - found = true; - res = 0; - } - break; - } - } - - closedir(dir); - - if (!found) { - return -4; - } - return res; -} +} \ No newline at end of file diff --git a/src/romfs_helper.h b/src/fileinfos.h similarity index 87% rename from src/romfs_helper.h rename to src/fileinfos.h index b810392..8f32555 100644 --- a/src/romfs_helper.h +++ b/src/fileinfos.h @@ -1,9 +1,8 @@ #pragma once + #include #include -#include - typedef struct WUT_PACKED FileInfos_ { char path[256]; char filename[256]; @@ -22,10 +21,8 @@ extern FileInfos gFileInfos[FILE_INFO_SIZE]; int32_t getIDByLowerTitleID(uint32_t lowerTitleID); -void unmountAllRomfs(); - void unmountRomfs(uint32_t id); -bool mountRomfs(uint32_t id); +void unmountAllRomfs(); -int32_t getRPXInfoForID(uint32_t id, romfs_fileInfo *info); +bool mountRomfs(uint32_t id); diff --git a/src/main.cpp b/src/main.cpp index 0176b30..13bdda6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,13 +12,13 @@ #include #include "utils/StringTools.h" #include -#include -#include "readFileWrapper.h" +#include "fileinfos.h" #include +#include #include "fs/FSUtils.h" -#include "romfs_helper.h" #include "filelist.h" #include "utils/ini.h" +#include "FileWrapper.h" typedef struct ACPMetaData { char bootmovie[80696]; @@ -48,7 +48,6 @@ INITIALIZE_PLUGIN() { memset((void *) ¤t_launched_title_info, 0, sizeof(current_launched_title_info)); memset((void *) &gLaunchXML, 0, sizeof(gLaunchXML)); memset((void *) &gFileInfos, 0, sizeof(gFileInfos)); - memset((void *) &gFileReadInformation, 0, sizeof(gFileReadInformation)); memset((void *) &gIconCache, 0, sizeof(gIconCache)); gHomebrewLaunched = FALSE; } @@ -69,8 +68,6 @@ ON_APPLICATION_START(args) { } ON_APPLICATION_END() { - DeInitAllFiles(); - unmountAllRomfs(); } void fillXmlForTitleID(uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml *out_buf) { @@ -122,12 +119,14 @@ static int handler(void *user, const char *section, const char *name, const char *value) { auto *fInfo = (FileInfos *) user; #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 + + DEBUG_FUNCTION_LINE("%s %s %s", section, name, value); if (MATCH("menu", "longname")) { - strncpy(fInfo->longname, value, 64-1); + strncpy(fInfo->longname, value, 64 - 1); } else if (MATCH("menu", "shortname")) { - strncpy(fInfo->shortname, value, 64-1); + strncpy(fInfo->shortname, value, 64 - 1); } else if (MATCH("menu", "author")) { - strncpy(fInfo->author, value, 64-1); + strncpy(fInfo->author, value, 64 - 1); } else { return 0; /* unknown section/name, error */ } @@ -160,6 +159,11 @@ void readCustomTitlesFromSD() { continue; } + //! skip wiiload temp files + if (strcasecmp(dirList.GetFilename(i), "temp2.wuhb") == 0) { + continue; + } + //! skip hidden linux and mac files if (dirList.GetFilename(i)[0] == '.' || dirList.GetFilename(i)[0] == '_') { continue; @@ -195,20 +199,37 @@ void readCustomTitlesFromSD() { // System apps don't have a splash screen. cur_title_info->appType = MCP_APP_TYPE_SYSTEM_APPS; - // Check if the have bootTvTex and bootDrcTex that could be shown. if (StringTools::EndsWith(gFileInfos[j].filename, ".wuhb")) { - if (romfsMount("romfscheck", dirList.GetFilepath(i), RomfsSource_FileDescriptor) == 0) { - if (ini_parse("romfscheck:/meta/meta.ini", handler, &gFileInfos[j]) < 0) { + if (RL_MountBundle("romfscheck", dirList.GetFilepath(i), BundleSource_FileDescriptor) == 0) { + uint32_t file_handle = 0; + if (RL_FileOpen("romfscheck:/meta/meta.ini", &file_handle) == 0) { + // this buffer should be big enough for our .ini + char ini_buffer[0x1000]; + memset(ini_buffer, 0, sizeof(ini_buffer)); + uint32_t offset = 0; + uint32_t toRead = sizeof(ini_buffer); + do { + int res = RL_FileRead(file_handle, reinterpret_cast(&ini_buffer[offset]), toRead); + if (res <= 0) { + break; + } + offset += res; + toRead -= res; + } while (offset < sizeof(ini_buffer)); - DEBUG_FUNCTION_LINE("Failed to load and parse meta.ini"); + if (ini_parse_string(ini_buffer, handler, &gFileInfos[j]) < 0) { + DEBUG_FUNCTION_LINE("Failed to parse ini") + } + + RL_FileClose(file_handle); } bool foundSplashScreens = true; - if (!FSUtils::CheckFile("romfscheck:/meta/bootTvTex.tga") && !FSUtils::CheckFile("romfscheck:/meta/bootTvTex.tga.gz")) { + if (!RL_FileExists("romfscheck:/meta/bootTvTex.tga")) { foundSplashScreens = false; } - if (!FSUtils::CheckFile("romfscheck:/meta/bootDrcTex.tga") && !FSUtils::CheckFile("romfscheck:/meta/bootDrcTex.tga.gz")) { + if (!RL_FileExists("romfscheck:/meta/bootDrcTex.tga")) { foundSplashScreens = false; } if (foundSplashScreens) { @@ -216,7 +237,7 @@ void readCustomTitlesFromSD() { // Show splash screens cur_title_info->appType = MCP_APP_TYPE_GAME; } - romfsUnmount("romfscheck"); + RL_UnmountBundle("romfscheck"); } else { DEBUG_FUNCTION_LINE("%s is not a valid .wuhb file", dirList.GetFilepath(i)); continue; @@ -274,30 +295,48 @@ DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType *t int32_t id = getIDByLowerTitleID(title->titleId & 0xFFFFFFFF); if (id >= 0) { DEBUG_FUNCTION_LINE("Starting a homebrew title"); - OSDynLoad_Module module; - - OSDynLoad_Error dyn_res = OSDynLoad_Acquire("homebrew_rpx_loader", &module); - if (dyn_res != OS_DYNLOAD_OK) { - OSFatal("Missing RPXLoader module"); - } - - bool (*loadRPXFromSDOnNextLaunch)(const std::string &path); - dyn_res = OSDynLoad_FindExport(module, false, "loadRPXFromSDOnNextLaunch", reinterpret_cast(&loadRPXFromSDOnNextLaunch)); - if (dyn_res != OS_DYNLOAD_OK) { - OSFatal("Failed to find export loadRPXFromSDOnNextLaunch"); - } fillXmlForTitleID((title->titleId & 0xFFFFFFFF00000000) >> 32, (title->titleId & 0xFFFFFFFF), &gLaunchXML); - romfs_fileInfo info; - int res = getRPXInfoForID(id, &info); - if (res >= 0) { - loadFileIntoBuffer((title->titleId & 0xFFFFFFFF), "meta/iconTex.tga", gIconCache, sizeof(gIconCache)); + std::string bundleFilePath = std::string("/vol/external01/") + gFileInfos[id].path; + + bool iconCached = false; + + if (RL_MountBundle("iconread", bundleFilePath.c_str(), BundleSource_FileDescriptor_CafeOS)) { + DEBUG_FUNCTION_LINE("Mounted file"); + uint32_t file_handle = 0; + if (RL_FileOpen("iconread:/meta/iconTex.tga", &file_handle) == 0) { + DEBUG_FUNCTION_LINE("Opened file"); + uint32_t offset = 0; + uint32_t toRead = sizeof(gIconCache); + do { + int res = RL_FileRead(file_handle, reinterpret_cast(&gIconCache[offset]), toRead); + DEBUG_FUNCTION_LINE("Read returned %d", res); + if (res <= 0) { + break; + } + offset += res; + toRead -= res; + } while (offset < sizeof(gIconCache)); + iconCached = true; + RL_FileClose(file_handle); + } else { + DEBUG_FUNCTION_LINE("failed to open") + } + DEBUG_FUNCTION_LINE("closed") + RL_UnmountBundle("iconread"); + } else { + DEBUG_FUNCTION_LINE("Failed to mount"); + } + + if (!iconCached) { + DEBUG_FUNCTION_LINE("Use default icon"); + memcpy(gIconCache, iconTex_tga, iconTex_tga_size); } gHomebrewLaunched = TRUE; - loadRPXFromSDOnNextLaunch(gFileInfos[id].path); + RL_LoadFromSDOnNextLaunch(gFileInfos[id].path); return 0; } else { DEBUG_FUNCTION_LINE("Failed to get the id for titleID %016llX", title->titleId); @@ -318,6 +357,7 @@ DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, if (StringTools::EndsWith(path, icon) || StringTools::EndsWith(path, sound)) { if (strncmp(path, start, strlen(start)) == 0) { int res = FS_STATUS_NOT_FOUND; + if (StringTools::EndsWith(path, iconTex)) { // fallback to dummy icon if loaded homebrew is no .wbf *handle = 0x13371338; @@ -333,19 +373,11 @@ DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, if (idVal < 0) { DEBUG_FUNCTION_LINE("Failed to find id for titleID %08X", lowerTitleID); } else { - if (FSOpenFile_for_ID(idVal, ending, handle) < 0) { + if (OpenFileForID(idVal, ending, handle) < 0) { return res; } } return FS_STATUS_OK; - } else if (gHomebrewLaunched) { - if (StringTools::EndsWith(path, iconTex)) { - *handle = 0x13371337; - return FS_STATUS_OK; - } else { - DEBUG_FUNCTION_LINE("%s", path); - } - } } @@ -354,35 +386,28 @@ DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, } DECL_FUNCTION(FSStatus, FSCloseFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t flags) { - if (handle == 0x13371337 || handle == 0x13371338) { + if (handle == 0x13371338) { return FS_STATUS_OK; - } - if ((handle & 0xFF000000) == 0xFF000000) { + } else if ((handle & 0xFF000000) == 0xFF000000) { int32_t fd = (handle & 0x00000FFF); int32_t romid = (handle & 0x00FFF000) >> 12; DEBUG_FUNCTION_LINE("Close %d %d", fd, romid); - DeInitFile(fd); + uint32_t rl_handle = gFileHandleWrapper[fd].handle; + RL_FileClose(rl_handle); if (gFileInfos[romid].openedFiles--) { + DCFlushRange(&gFileInfos[romid].openedFiles, 4); if (gFileInfos[romid].openedFiles <= 0) { DEBUG_FUNCTION_LINE("unmount romfs no more handles"); unmountRomfs(romid); } } - //unmountAllRomfs(); return FS_STATUS_OK; } return real_FSCloseFile(client, block, handle, flags); } DECL_FUNCTION(FSStatus, FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, uint32_t flags) { - if (handle == 0x13371337) { - uint32_t cpySize = size * count; - if (sizeof(gIconCache) < cpySize) { - cpySize = sizeof(gIconCache); - } - memcpy(buffer, gIconCache, cpySize); - return (FSStatus) (cpySize / size); - } else if (handle == 0x13371338) { + if (handle == 0x13371338) { uint32_t cpySize = size * count; if (iconTex_tga_size < cpySize) { cpySize = iconTex_tga_size; @@ -390,14 +415,15 @@ DECL_FUNCTION(FSStatus, FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t memcpy(buffer, iconTex_tga, cpySize); DEBUG_FUNCTION_LINE("DUMMY"); return (FSStatus) (cpySize / size); - } - if ((handle & 0xFF000000) == 0xFF000000) { + } else if ((handle & 0xFF000000) == 0xFF000000) { int32_t fd = (handle & 0x00000FFF); int32_t romid = (handle & 0x00FFF000) >> 12; - DEBUG_FUNCTION_LINE("READ %d from %d rom: %d", size * count, fd, romid); + uint32_t rl_handle = gFileHandleWrapper[fd].handle; - int readSize = readFile(fd, buffer, (size * count)); + DEBUG_FUNCTION_LINE("READ %d from %d (%08X) rom: %d", size * count, fd, rl_handle, romid); + + int readSize = RL_FileRead(rl_handle, buffer, (size * count)); return (FSStatus) (readSize / size); } diff --git a/src/readFileWrapper.cpp b/src/readFileWrapper.cpp deleted file mode 100644 index 4d03d52..0000000 --- a/src/readFileWrapper.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "readFileWrapper.h" -#include "fs/FSUtils.h" -#include "utils/logger.h" - -#include -#include -#include "romfs_helper.h" -#include - -fileReadInformation gFileReadInformation[FILE_READ_INFO_SIZE] __attribute__((section(".data"))); - -int readFile(int slot, uint8_t *buffer, uint32_t size) { - fileReadInformation *info = &gFileReadInformation[slot]; - if (!info->compressed) { - //DEBUG_FUNCTION_LINE("non compressed"); - return read(info->fd, buffer, size); - } else { - int startValue = info->strm.total_out; - uint32_t newSize = 0; - int ret = 0; - //DEBUG_FUNCTION_LINE("We want to read %d", size); - //DEBUG_FUNCTION_LINE("startValue %d ",startValue); - do { - int CHUNK = 0x1000; - uint32_t nextOut = CHUNK; - if (nextOut > size) { - nextOut = size; - } - //DEBUG_FUNCTION_LINE("nextOut = %d",nextOut); - if (info->strm.avail_in == 0) { - //DEBUG_FUNCTION_LINE("Reading %d from compressed stream",CHUNK); - info->strm.avail_in = read(info->fd, info->in, CHUNK); - if (info->strm.avail_in == 0) { - DEBUG_FUNCTION_LINE("strm.avail_in is 0"); - break; - } - info->strm.next_in = info->in; - } - //DEBUG_FUNCTION_LINE("info->strm.avail_in = %d",info->strm.avail_in); - //DEBUG_FUNCTION_LINE("info->strm.next_in = %d",info->strm.next_in); - - /* run inflate() on input until output buffer not full */ - do { - //DEBUG_FUNCTION_LINE("newSize %d, size %d, info->strm.avail_out %d", newSize, size, info->strm.avail_out); - - if (nextOut > size - newSize) { - nextOut = size - newSize; - } - - info->strm.avail_out = nextOut; - //DEBUG_FUNCTION_LINE("info->strm.avail_out = %d",info->strm.avail_out); - info->strm.next_out = (buffer + newSize); - //DEBUG_FUNCTION_LINE("info->strm.next_out = %08X",info->strm.next_out); - ret = inflate(&info->strm, Z_NO_FLUSH); - //DEBUG_FUNCTION_LINE("ret = %d",ret); - if (ret == Z_STREAM_ERROR) { - DEBUG_FUNCTION_LINE("Z_STREAM_ERROR"); - return 0; - } - - switch (ret) { - case Z_NEED_DICT: - DEBUG_FUNCTION_LINE("Z_NEED_DICT"); - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - DEBUG_FUNCTION_LINE("Z_MEM_ERROR or Z_DATA_ERROR"); - (void) inflateEnd(&info->strm); - return ret; - } - - //int canBeWritten = CHUNK - info->strm.avail_out; - //DEBUG_FUNCTION_LINE("canBeWritten = %d",canBeWritten); - - newSize = info->strm.total_out - startValue; - if (newSize == size) { - //DEBUG_FUNCTION_LINE("newSize was as wanted %d", newSize); - break; - } - nextOut = CHUNK; - if (newSize + nextOut >= (size)) { - nextOut = (size) - newSize; - } - //DEBUG_FUNCTION_LINE("newSize = %d",newSize); - //DEBUG_FUNCTION_LINE("nextOut = %d",nextOut); - } while (info->strm.avail_out == 0 && newSize < (size)); - - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END && newSize < size); - - return newSize; - } -} - - -bool DeInitFile(int slot) { - if (gFileReadInformation[slot].compressed && gFileReadInformation[slot].cInitDone) { - /* clean up and return */ - (void) inflateEnd(&(gFileReadInformation[slot].strm)); - } - - close(gFileReadInformation[slot].fd); - gFileReadInformation[slot].inUse = false; - memset(&gFileReadInformation[slot], 0, sizeof(fileReadInformation)); - return true; -} - - -void DeInitAllFiles() { - for (int i = 0; i < FILE_READ_INFO_SIZE; i++) { - fileReadInformation *info = &gFileReadInformation[i]; - if (info->inUse) { - DeInitFile(i); - } - } -} - -int fileReadInformation_getSlot() { - for (int i = 0; i < 32; i++) { - if (!gFileReadInformation[i].inUse) { - gFileReadInformation[i].inUse = true; - return i; - } - } - return -1; -} - - -bool initCompressedFileReadInformation(fileReadInformation *info) { - if (info == nullptr || !info->compressed) { - info->cInitDone = false; - return false; - } - if (info->cInitDone) { - return true; - } - /* allocate inflate state */ - info->strm.zalloc = Z_NULL; - info->strm.zfree = Z_NULL; - info->strm.opaque = Z_NULL; - info->strm.avail_in = 0; - info->strm.next_in = Z_NULL; - int ret = inflateInit2(&info->strm, MAX_WBITS | 16); //gzip - if (ret != Z_OK) { - DEBUG_FUNCTION_LINE("ret != Z_OK"); - info->cInitDone = false; - return false; - } - info->cInitDone = true; - return true; -} - - -int32_t loadFileIntoBuffer(uint32_t lowerTitleID, const char *filepath, char *buffer, int sizeToRead) { - int32_t id = getIDByLowerTitleID(lowerTitleID); - if (id < 0) { - DEBUG_FUNCTION_LINE("Failed to get id by titleid"); - return -3; - } - if (!mountRomfs(id)) { - return -1; - } - int handle = 0; - if (FSOpenFile_for_ID(id, filepath, &handle) != 0) { - return -2; - } - - int32_t fd = (handle & 0x00000FFF); - int32_t romid = (handle & 0x00FFF000) >> 12; - - DEBUG_FUNCTION_LINE("READ %d from %d rom: %d", sizeToRead, fd, romid); - - int readSize = readFile(fd, (uint8_t *) buffer, (sizeToRead)); - - DEBUG_FUNCTION_LINE("Close %d %d", fd, romid); - DeInitFile(fd); - if (gFileInfos[romid].openedFiles--) { - if (gFileInfos[romid].openedFiles <= 0) { - DEBUG_FUNCTION_LINE("unmount romfs no more handles"); - unmountRomfs(romid); - } - } - - return readSize; -} - - -int32_t FSOpenFile_for_ID(uint32_t id, const char *filepath, int *handle) { - if (!mountRomfs(id)) { - return -1; - } - char romName[10]; - snprintf(romName, 10, "%08X", id); - - char *test = (char *) malloc(strlen(filepath) + 1); - char last = 0; - int j = 0; - for (int i = 0; filepath[i] != 0; i++) { - if (filepath[i] == '/') { - if (filepath[i] != last) { - test[j++] = filepath[i]; - } - } else { - test[j++] = filepath[i]; - } - last = filepath[i]; - } - test[j++] = 0; - - char buffer[256]; - snprintf(buffer, 256, "%s:/%s.gz", romName, test); - - bool nonCompressed = false; - if (!FSUtils::CheckFile(buffer)) { - snprintf(buffer, 256, "%s:/%s", romName, test); - free(test); - if (!FSUtils::CheckFile(buffer)) { - return -3; - } - nonCompressed = true; - } - free(test); - - int fd = open(buffer, 0); - if (fd >= 0) { - DEBUG_FUNCTION_LINE("Opened %s from %s ", buffer, romName); - int slot = fileReadInformation_getSlot(); - if (slot < 0) { - DEBUG_FUNCTION_LINE("Failed to get a slot"); - close(fd); - return -5; - } - fileReadInformation *info = &gFileReadInformation[slot]; - info->fd = fd; - if (!nonCompressed) { - info->compressed = true; - initCompressedFileReadInformation(info); - DEBUG_FUNCTION_LINE("Init compressed, got slot %d", slot); - } else { - info->cInitDone = true; - } - *handle = 0xFF000000 | (id << 12) | (slot & 0x00000FFF); - gFileInfos[id].openedFiles++; - return 0; - } - return -2; -} diff --git a/src/readFileWrapper.h b/src/readFileWrapper.h deleted file mode 100644 index 53c36c3..0000000 --- a/src/readFileWrapper.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include -#include - -typedef struct { - bool inUse; - int fd; - bool compressed; - bool cInitDone; - bool cCloseDone; - z_stream strm; - unsigned char in[0x1000]; -} fileReadInformation; - -#define FILE_READ_INFO_SIZE 32 - -extern fileReadInformation gFileReadInformation[FILE_READ_INFO_SIZE]; - -bool initFile(int slot); - -int readFile(int slot, uint8_t *buffer, uint32_t size); - -bool DeInitFile(int slot); - -void DeInitAllFiles(); - -int32_t loadFileIntoBuffer(uint32_t lowerTitleID, const char *filepath, char *buffer, int sizeToRead); - -int32_t FSOpenFile_for_ID(uint32_t id, const char *filepath, int *handle); - -int fileReadInformation_getSlot(); - -bool initCompressedFileReadInformation(fileReadInformation *info); \ No newline at end of file