Use the librpxloader for loading the bundle and it's meta data

This commit is contained in:
Maschell 2021-01-24 15:49:26 +01:00
parent 114139ce90
commit ceba975be1
9 changed files with 182 additions and 394 deletions

View File

@ -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

View File

@ -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

70
src/FileWrapper.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "FileWrapper.h"
#include <cstdlib>
#include "fileinfos.h"
#include <cstring>
#include <cstdio>
#include <rpxloader.h>
#include "utils/logger.h"
#include <coreinit/cache.h>
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;
}

12
src/FileWrapper.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <cstdint>
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);

View File

@ -1,8 +1,8 @@
#include "romfs_helper.h"
#include "utils/logger.h"
#include "utils/StringTools.h"
#include <cstring>
#include <stdio.h>
#include <sys/dir.h>
#include <rpxloader.h>
#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;
}
}

View File

@ -1,9 +1,8 @@
#pragma once
#include <cstdint>
#include <coreinit/mcp.h>
#include <romfs_dev.h>
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);

View File

@ -12,13 +12,13 @@
#include <utils/logger.h>
#include "utils/StringTools.h"
#include <fs/DirList.h>
#include <romfs_dev.h>
#include "readFileWrapper.h"
#include "fileinfos.h"
#include <whb/log_udp.h>
#include <rpxloader.h>
#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 *) &current_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<uint8_t *>(&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<void **>(&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<uint8_t *>(&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);
}

View File

@ -1,247 +0,0 @@
#include "readFileWrapper.h"
#include "fs/FSUtils.h"
#include "utils/logger.h"
#include <cstdio>
#include <fcntl.h>
#include "romfs_helper.h"
#include <cstdlib>
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;
}

View File

@ -1,35 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <zlib.h>
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);