mirror of
https://github.com/wiiu-env/homebrew_on_menu_plugin.git
synced 2024-11-22 10:39:16 +01:00
Use the librpxloader for loading the bundle and it's meta data
This commit is contained in:
parent
114139ce90
commit
ceba975be1
@ -1,6 +1,6 @@
|
|||||||
FROM wiiuenv/devkitppc:20210101
|
FROM wiiuenv/devkitppc:20210101
|
||||||
|
|
||||||
COPY --from=wiiuenv/wiiupluginsystem:20210109 /artifacts $DEVKITPRO
|
COPY --from=wiiuenv/wiiupluginsystem:20210109 /artifacts $DEVKITPRO
|
||||||
COPY --from=wiiuenv/libromfs_wiiu:20210109133626639534 /artifacts $DEVKITPRO
|
COPY --from=wiiuenv/librpxloader:20210116 /artifacts $DEVKITPRO
|
||||||
|
|
||||||
WORKDIR project
|
WORKDIR project
|
7
Makefile
7
Makefile
@ -11,6 +11,7 @@ TOPDIR ?= $(CURDIR)
|
|||||||
include $(DEVKITPRO)/wups/share/wups_rules
|
include $(DEVKITPRO)/wups/share/wups_rules
|
||||||
|
|
||||||
WUT_ROOT := $(DEVKITPRO)/wut
|
WUT_ROOT := $(DEVKITPRO)/wut
|
||||||
|
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# TARGET is the name of the output
|
# TARGET is the name of the output
|
||||||
@ -38,15 +39,15 @@ CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__
|
|||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS)
|
||||||
|
|
||||||
ASFLAGS := -g $(ARCH)
|
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
|
# list of directories containing libraries, this must be the top level
|
||||||
# containing include and lib
|
# 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
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
70
src/FileWrapper.cpp
Normal file
70
src/FileWrapper.cpp
Normal 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
12
src/FileWrapper.h
Normal 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);
|
@ -1,8 +1,8 @@
|
|||||||
#include "romfs_helper.h"
|
#include <cstring>
|
||||||
#include "utils/logger.h"
|
|
||||||
#include "utils/StringTools.h"
|
|
||||||
#include <stdio.h>
|
#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")));
|
FileInfos gFileInfos[FILE_INFO_SIZE] __attribute__((section(".data")));
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ void unmountRomfs(uint32_t id) {
|
|||||||
char romName[10];
|
char romName[10];
|
||||||
snprintf(romName, 10, "%08X", id);
|
snprintf(romName, 10, "%08X", id);
|
||||||
DEBUG_FUNCTION_LINE("Unmounting %s", romName);
|
DEBUG_FUNCTION_LINE("Unmounting %s", romName);
|
||||||
int res = romfsUnmount(romName);
|
int res = RL_UnmountBundle(romName);
|
||||||
DEBUG_FUNCTION_LINE("res: %d", res);
|
DEBUG_FUNCTION_LINE("res: %d", res);
|
||||||
gFileInfos[id].romfsMounted = false;
|
gFileInfos[id].romfsMounted = false;
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ bool mountRomfs(uint32_t id) {
|
|||||||
snprintf(romName, 10, "%08X", id);
|
snprintf(romName, 10, "%08X", id);
|
||||||
DEBUG_FUNCTION_LINE("Mount %s as %s", buffer, romName);
|
DEBUG_FUNCTION_LINE("Mount %s as %s", buffer, romName);
|
||||||
int32_t res = 0;
|
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 ");
|
DEBUG_FUNCTION_LINE("Mounted successfully ");
|
||||||
gFileInfos[id].romfsMounted = true;
|
gFileInfos[id].romfsMounted = true;
|
||||||
return true;
|
return true;
|
||||||
@ -58,39 +58,3 @@ bool mountRomfs(uint32_t id) {
|
|||||||
}
|
}
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
@ -1,9 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <coreinit/mcp.h>
|
#include <coreinit/mcp.h>
|
||||||
|
|
||||||
#include <romfs_dev.h>
|
|
||||||
|
|
||||||
typedef struct WUT_PACKED FileInfos_ {
|
typedef struct WUT_PACKED FileInfos_ {
|
||||||
char path[256];
|
char path[256];
|
||||||
char filename[256];
|
char filename[256];
|
||||||
@ -22,10 +21,8 @@ extern FileInfos gFileInfos[FILE_INFO_SIZE];
|
|||||||
|
|
||||||
int32_t getIDByLowerTitleID(uint32_t lowerTitleID);
|
int32_t getIDByLowerTitleID(uint32_t lowerTitleID);
|
||||||
|
|
||||||
void unmountAllRomfs();
|
|
||||||
|
|
||||||
void unmountRomfs(uint32_t id);
|
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);
|
138
src/main.cpp
138
src/main.cpp
@ -12,13 +12,13 @@
|
|||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
#include "utils/StringTools.h"
|
#include "utils/StringTools.h"
|
||||||
#include <fs/DirList.h>
|
#include <fs/DirList.h>
|
||||||
#include <romfs_dev.h>
|
#include "fileinfos.h"
|
||||||
#include "readFileWrapper.h"
|
|
||||||
#include <whb/log_udp.h>
|
#include <whb/log_udp.h>
|
||||||
|
#include <rpxloader.h>
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
#include "romfs_helper.h"
|
|
||||||
#include "filelist.h"
|
#include "filelist.h"
|
||||||
#include "utils/ini.h"
|
#include "utils/ini.h"
|
||||||
|
#include "FileWrapper.h"
|
||||||
|
|
||||||
typedef struct ACPMetaData {
|
typedef struct ACPMetaData {
|
||||||
char bootmovie[80696];
|
char bootmovie[80696];
|
||||||
@ -48,7 +48,6 @@ INITIALIZE_PLUGIN() {
|
|||||||
memset((void *) ¤t_launched_title_info, 0, sizeof(current_launched_title_info));
|
memset((void *) ¤t_launched_title_info, 0, sizeof(current_launched_title_info));
|
||||||
memset((void *) &gLaunchXML, 0, sizeof(gLaunchXML));
|
memset((void *) &gLaunchXML, 0, sizeof(gLaunchXML));
|
||||||
memset((void *) &gFileInfos, 0, sizeof(gFileInfos));
|
memset((void *) &gFileInfos, 0, sizeof(gFileInfos));
|
||||||
memset((void *) &gFileReadInformation, 0, sizeof(gFileReadInformation));
|
|
||||||
memset((void *) &gIconCache, 0, sizeof(gIconCache));
|
memset((void *) &gIconCache, 0, sizeof(gIconCache));
|
||||||
gHomebrewLaunched = FALSE;
|
gHomebrewLaunched = FALSE;
|
||||||
}
|
}
|
||||||
@ -69,8 +68,6 @@ ON_APPLICATION_START(args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ON_APPLICATION_END() {
|
ON_APPLICATION_END() {
|
||||||
DeInitAllFiles();
|
|
||||||
unmountAllRomfs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillXmlForTitleID(uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml *out_buf) {
|
void fillXmlForTitleID(uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml *out_buf) {
|
||||||
@ -122,6 +119,8 @@ static int handler(void *user, const char *section, const char *name,
|
|||||||
const char *value) {
|
const char *value) {
|
||||||
auto *fInfo = (FileInfos *) user;
|
auto *fInfo = (FileInfos *) user;
|
||||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
#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")) {
|
if (MATCH("menu", "longname")) {
|
||||||
strncpy(fInfo->longname, value, 64 - 1);
|
strncpy(fInfo->longname, value, 64 - 1);
|
||||||
} else if (MATCH("menu", "shortname")) {
|
} else if (MATCH("menu", "shortname")) {
|
||||||
@ -160,6 +159,11 @@ void readCustomTitlesFromSD() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! skip wiiload temp files
|
||||||
|
if (strcasecmp(dirList.GetFilename(i), "temp2.wuhb") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//! skip hidden linux and mac files
|
//! skip hidden linux and mac files
|
||||||
if (dirList.GetFilename(i)[0] == '.' || dirList.GetFilename(i)[0] == '_') {
|
if (dirList.GetFilename(i)[0] == '.' || dirList.GetFilename(i)[0] == '_') {
|
||||||
continue;
|
continue;
|
||||||
@ -195,20 +199,37 @@ void readCustomTitlesFromSD() {
|
|||||||
// System apps don't have a splash screen.
|
// System apps don't have a splash screen.
|
||||||
cur_title_info->appType = MCP_APP_TYPE_SYSTEM_APPS;
|
cur_title_info->appType = MCP_APP_TYPE_SYSTEM_APPS;
|
||||||
|
|
||||||
|
|
||||||
// Check if the have bootTvTex and bootDrcTex that could be shown.
|
// Check if the have bootTvTex and bootDrcTex that could be shown.
|
||||||
if (StringTools::EndsWith(gFileInfos[j].filename, ".wuhb")) {
|
if (StringTools::EndsWith(gFileInfos[j].filename, ".wuhb")) {
|
||||||
if (romfsMount("romfscheck", dirList.GetFilepath(i), RomfsSource_FileDescriptor) == 0) {
|
if (RL_MountBundle("romfscheck", dirList.GetFilepath(i), BundleSource_FileDescriptor) == 0) {
|
||||||
if (ini_parse("romfscheck:/meta/meta.ini", handler, &gFileInfos[j]) < 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;
|
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;
|
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;
|
foundSplashScreens = false;
|
||||||
}
|
}
|
||||||
if (foundSplashScreens) {
|
if (foundSplashScreens) {
|
||||||
@ -216,7 +237,7 @@ void readCustomTitlesFromSD() {
|
|||||||
// Show splash screens
|
// Show splash screens
|
||||||
cur_title_info->appType = MCP_APP_TYPE_GAME;
|
cur_title_info->appType = MCP_APP_TYPE_GAME;
|
||||||
}
|
}
|
||||||
romfsUnmount("romfscheck");
|
RL_UnmountBundle("romfscheck");
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("%s is not a valid .wuhb file", dirList.GetFilepath(i));
|
DEBUG_FUNCTION_LINE("%s is not a valid .wuhb file", dirList.GetFilepath(i));
|
||||||
continue;
|
continue;
|
||||||
@ -274,30 +295,48 @@ DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType *t
|
|||||||
int32_t id = getIDByLowerTitleID(title->titleId & 0xFFFFFFFF);
|
int32_t id = getIDByLowerTitleID(title->titleId & 0xFFFFFFFF);
|
||||||
if (id >= 0) {
|
if (id >= 0) {
|
||||||
DEBUG_FUNCTION_LINE("Starting a homebrew title");
|
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);
|
fillXmlForTitleID((title->titleId & 0xFFFFFFFF00000000) >> 32, (title->titleId & 0xFFFFFFFF), &gLaunchXML);
|
||||||
|
|
||||||
romfs_fileInfo info;
|
std::string bundleFilePath = std::string("/vol/external01/") + gFileInfos[id].path;
|
||||||
int res = getRPXInfoForID(id, &info);
|
|
||||||
if (res >= 0) {
|
bool iconCached = false;
|
||||||
loadFileIntoBuffer((title->titleId & 0xFFFFFFFF), "meta/iconTex.tga", gIconCache, sizeof(gIconCache));
|
|
||||||
|
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;
|
gHomebrewLaunched = TRUE;
|
||||||
|
|
||||||
loadRPXFromSDOnNextLaunch(gFileInfos[id].path);
|
RL_LoadFromSDOnNextLaunch(gFileInfos[id].path);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Failed to get the id for titleID %016llX", title->titleId);
|
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 (StringTools::EndsWith(path, icon) || StringTools::EndsWith(path, sound)) {
|
||||||
if (strncmp(path, start, strlen(start)) == 0) {
|
if (strncmp(path, start, strlen(start)) == 0) {
|
||||||
int res = FS_STATUS_NOT_FOUND;
|
int res = FS_STATUS_NOT_FOUND;
|
||||||
|
|
||||||
if (StringTools::EndsWith(path, iconTex)) {
|
if (StringTools::EndsWith(path, iconTex)) {
|
||||||
// fallback to dummy icon if loaded homebrew is no .wbf
|
// fallback to dummy icon if loaded homebrew is no .wbf
|
||||||
*handle = 0x13371338;
|
*handle = 0x13371338;
|
||||||
@ -333,19 +373,11 @@ DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path,
|
|||||||
if (idVal < 0) {
|
if (idVal < 0) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to find id for titleID %08X", lowerTitleID);
|
DEBUG_FUNCTION_LINE("Failed to find id for titleID %08X", lowerTitleID);
|
||||||
} else {
|
} else {
|
||||||
if (FSOpenFile_for_ID(idVal, ending, handle) < 0) {
|
if (OpenFileForID(idVal, ending, handle) < 0) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FS_STATUS_OK;
|
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) {
|
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;
|
return FS_STATUS_OK;
|
||||||
}
|
} else if ((handle & 0xFF000000) == 0xFF000000) {
|
||||||
if ((handle & 0xFF000000) == 0xFF000000) {
|
|
||||||
int32_t fd = (handle & 0x00000FFF);
|
int32_t fd = (handle & 0x00000FFF);
|
||||||
int32_t romid = (handle & 0x00FFF000) >> 12;
|
int32_t romid = (handle & 0x00FFF000) >> 12;
|
||||||
DEBUG_FUNCTION_LINE("Close %d %d", fd, romid);
|
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--) {
|
if (gFileInfos[romid].openedFiles--) {
|
||||||
|
DCFlushRange(&gFileInfos[romid].openedFiles, 4);
|
||||||
if (gFileInfos[romid].openedFiles <= 0) {
|
if (gFileInfos[romid].openedFiles <= 0) {
|
||||||
DEBUG_FUNCTION_LINE("unmount romfs no more handles");
|
DEBUG_FUNCTION_LINE("unmount romfs no more handles");
|
||||||
unmountRomfs(romid);
|
unmountRomfs(romid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//unmountAllRomfs();
|
|
||||||
return FS_STATUS_OK;
|
return FS_STATUS_OK;
|
||||||
}
|
}
|
||||||
return real_FSCloseFile(client, block, handle, flags);
|
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) {
|
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) {
|
if (handle == 0x13371338) {
|
||||||
uint32_t cpySize = size * count;
|
|
||||||
if (sizeof(gIconCache) < cpySize) {
|
|
||||||
cpySize = sizeof(gIconCache);
|
|
||||||
}
|
|
||||||
memcpy(buffer, gIconCache, cpySize);
|
|
||||||
return (FSStatus) (cpySize / size);
|
|
||||||
} else if (handle == 0x13371338) {
|
|
||||||
uint32_t cpySize = size * count;
|
uint32_t cpySize = size * count;
|
||||||
if (iconTex_tga_size < cpySize) {
|
if (iconTex_tga_size < cpySize) {
|
||||||
cpySize = iconTex_tga_size;
|
cpySize = iconTex_tga_size;
|
||||||
@ -390,14 +415,15 @@ DECL_FUNCTION(FSStatus, FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t
|
|||||||
memcpy(buffer, iconTex_tga, cpySize);
|
memcpy(buffer, iconTex_tga, cpySize);
|
||||||
DEBUG_FUNCTION_LINE("DUMMY");
|
DEBUG_FUNCTION_LINE("DUMMY");
|
||||||
return (FSStatus) (cpySize / size);
|
return (FSStatus) (cpySize / size);
|
||||||
}
|
} else if ((handle & 0xFF000000) == 0xFF000000) {
|
||||||
if ((handle & 0xFF000000) == 0xFF000000) {
|
|
||||||
int32_t fd = (handle & 0x00000FFF);
|
int32_t fd = (handle & 0x00000FFF);
|
||||||
int32_t romid = (handle & 0x00FFF000) >> 12;
|
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);
|
return (FSStatus) (readSize / size);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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);
|
|
Loading…
Reference in New Issue
Block a user