mirror of
https://github.com/wiiu-env/homebrew_on_menu_plugin.git
synced 2024-11-25 20:06:53 +01:00
Reimplement the data structure and file reading
This commit is contained in:
parent
74560db545
commit
15ab8b4c3b
86
src/FileInfos.h
Normal file
86
src/FileInfos.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include <coreinit/mcp.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <wuhb_utils/utils.h>
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
class FileInfos {
|
||||||
|
public:
|
||||||
|
explicit FileInfos(const std::string &relativePath) : relativeFilepath(relativePath) {
|
||||||
|
this->lowerTitleID = hash_string(relativePath.c_str());
|
||||||
|
}
|
||||||
|
~FileInfos() {
|
||||||
|
std::lock_guard<std::mutex> lock(mountLock);
|
||||||
|
if (isMounted) {
|
||||||
|
UnmountBundle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool MountBundle(const std::string &romfsName) {
|
||||||
|
if (isMounted) {
|
||||||
|
if (mountPath != romfsName) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Can't mount as %s because it's already mounted with a different name (%s)", romfsName.c_str(), mountPath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!isBundle) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Mounting not possible, is not a bundle");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto fullMountPath = std::string("/vol/external01/").append(this->relativeFilepath);
|
||||||
|
int32_t outRes = -1;
|
||||||
|
if (WUHBUtils_MountBundle(romfsName.c_str(), fullMountPath.c_str(), BundleSource_FileDescriptor_CafeOS, &outRes) != WUHB_UTILS_RESULT_SUCCESS || outRes < 0) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to mount bundle: %s", romfsName.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Succesfully mounted %s", romfsName.c_str());
|
||||||
|
this->isMounted = true;
|
||||||
|
mountPath = romfsName;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnmountBundle() {
|
||||||
|
if (!isBundle) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Skip unmounting, is not a bundle");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!isMounted) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Skip unmounting, is not mounted");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int32_t outRes = -1;
|
||||||
|
if (WUHBUtils_UnmountBundle(mountPath.c_str(), &outRes) != WUHB_UTILS_RESULT_SUCCESS || outRes < 0) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to unmount bundle: %s", mountPath.c_str());
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Successfully unmounted bundle %s", this->mountPath.c_str());
|
||||||
|
}
|
||||||
|
this->isMounted = false;
|
||||||
|
this->mountPath.clear();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string relativeFilepath;
|
||||||
|
std::string filename;
|
||||||
|
|
||||||
|
std::string longname;
|
||||||
|
std::string shortname;
|
||||||
|
std::string author;
|
||||||
|
|
||||||
|
uint32_t lowerTitleID;
|
||||||
|
MCPTitleListType titleInfo{};
|
||||||
|
|
||||||
|
int32_t fileCount = 0;
|
||||||
|
|
||||||
|
bool isBundle = false;
|
||||||
|
|
||||||
|
std::mutex accessLock;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mountLock;
|
||||||
|
std::string mountPath;
|
||||||
|
bool isMounted = false;
|
||||||
|
};
|
@ -1,97 +0,0 @@
|
|||||||
#include "FileWrapper.h"
|
|
||||||
#include "fileinfos.h"
|
|
||||||
#include "utils/StringTools.h"
|
|
||||||
#include "utils/logger.h"
|
|
||||||
#include <coreinit/cache.h>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <mutex>
|
|
||||||
#include <wuhb_utils/utils.h>
|
|
||||||
|
|
||||||
FileHandleWrapper gFileHandleWrapper[FILE_WRAPPER_SIZE] __attribute__((section(".data")));
|
|
||||||
|
|
||||||
std::mutex fileWrapperMutex;
|
|
||||||
|
|
||||||
int FileHandleWrapper_GetSlot() {
|
|
||||||
std::lock_guard<std::mutex> lock(fileWrapperMutex);
|
|
||||||
int res = -1;
|
|
||||||
for (int i = 0; i < FILE_WRAPPER_SIZE; i++) {
|
|
||||||
if (!gFileHandleWrapper[i].inUse) {
|
|
||||||
gFileHandleWrapper[i].inUse = true;
|
|
||||||
res = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OSMemoryBarrier();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileHandleWrapper_FreeSlot(uint32_t slot) {
|
|
||||||
if (slot >= FILE_WRAPPER_SIZE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::lock_guard<std::mutex> lock(fileWrapperMutex);
|
|
||||||
gFileHandleWrapper[slot].handle = 0;
|
|
||||||
gFileHandleWrapper[slot].inUse = false;
|
|
||||||
OSMemoryBarrier();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileHandleWrapper_FreeAll() {
|
|
||||||
std::lock_guard<std::mutex> lock(fileWrapperMutex);
|
|
||||||
for (int i = 0; i < FILE_WRAPPER_SIZE; i++) {
|
|
||||||
FileHandleWrapper_FreeSlot(i);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpenFileForID(int id, const char *filepath, uint32_t *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;
|
|
||||||
|
|
||||||
auto completePath = string_format("%s:/%s", romName, dyn_path);
|
|
||||||
|
|
||||||
WUHBFileHandle fileHandle = 0;
|
|
||||||
if (WUHBUtils_FileOpen(completePath.c_str(), &fileHandle) == WUHB_UTILS_RESULT_SUCCESS) {
|
|
||||||
int handle_wrapper_slot = FileHandleWrapper_GetSlot();
|
|
||||||
|
|
||||||
if (handle_wrapper_slot < 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("No free slot");
|
|
||||||
if (WUHBUtils_FileClose(fileHandle) != WUHB_UTILS_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to close file %08X", fileHandle);
|
|
||||||
}
|
|
||||||
unmountRomfs(id);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
gFileHandleWrapper[handle_wrapper_slot].handle = fileHandle;
|
|
||||||
*handle = 0xFF000000 | (id << 12) | (handle_wrapper_slot & 0x00000FFF);
|
|
||||||
gFileInfos[id].openedFiles++;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to open file %s", filepath);
|
|
||||||
if (gFileInfos[id].openedFiles == 0) {
|
|
||||||
unmountRomfs(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#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, uint32_t *handle);
|
|
||||||
bool FileHandleWrapper_FreeAll();
|
|
@ -71,7 +71,7 @@ void initSaveData() {
|
|||||||
DECL_FUNCTION(int32_t, LoadConsoleAccount__Q2_2nn3actFUc13ACTLoadOptionPCcb, nn::act::SlotNo slot, nn::act::ACTLoadOption unk1, char const *unk2, bool unk3) {
|
DECL_FUNCTION(int32_t, LoadConsoleAccount__Q2_2nn3actFUc13ACTLoadOptionPCcb, nn::act::SlotNo slot, nn::act::ACTLoadOption unk1, char const *unk2, bool unk3) {
|
||||||
int32_t result = real_LoadConsoleAccount__Q2_2nn3actFUc13ACTLoadOptionPCcb(slot, unk1, unk2, unk3);
|
int32_t result = real_LoadConsoleAccount__Q2_2nn3actFUc13ACTLoadOptionPCcb(slot, unk1, unk2, unk3);
|
||||||
if (result >= 0 && gInWiiUMenu) {
|
if (result >= 0 && gInWiiUMenu) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Changed account, we need to init the save data");
|
DEBUG_FUNCTION_LINE("Changed account, we need to init the save data");
|
||||||
// If the account has changed, we need to init save data for this account
|
// If the account has changed, we need to init save data for this account
|
||||||
// Calls our function replacement.
|
// Calls our function replacement.
|
||||||
SAVEInit();
|
SAVEInit();
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
#include "fileinfos.h"
|
|
||||||
#include "utils/logger.h"
|
|
||||||
#include <coreinit/cache.h>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <mutex>
|
|
||||||
#include <wuhb_utils/utils.h>
|
|
||||||
|
|
||||||
FileInfos gFileInfos[FILE_INFO_SIZE] __attribute__((section(".data")));
|
|
||||||
std::mutex fileinfoMutex;
|
|
||||||
|
|
||||||
int32_t getIDByLowerTitleID(uint32_t lowerTitleID) {
|
|
||||||
std::lock_guard<std::mutex> lock(fileinfoMutex);
|
|
||||||
int res = -1;
|
|
||||||
for (int i = 0; i < FILE_INFO_SIZE; i++) {
|
|
||||||
if (strlen(gFileInfos[i].path) > 0 && gFileInfos[i].lowerTitleID == lowerTitleID) {
|
|
||||||
res = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OSMemoryBarrier();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unmountRomfs(uint32_t id) {
|
|
||||||
if (id >= FILE_INFO_SIZE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::lock_guard<std::mutex> lock(fileinfoMutex);
|
|
||||||
if (gFileInfos[id].romfsMounted) {
|
|
||||||
char romName[10];
|
|
||||||
snprintf(romName, 10, "%08X", id);
|
|
||||||
int32_t outRes;
|
|
||||||
if (WUHBUtils_UnmountBundle(romName, &outRes) || outRes != 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to unmount \"%s\"", romName);
|
|
||||||
}
|
|
||||||
gFileInfos[id].romfsMounted = false;
|
|
||||||
}
|
|
||||||
OSMemoryBarrier();
|
|
||||||
}
|
|
||||||
|
|
||||||
void unmountAllRomfs() {
|
|
||||||
for (int i = 0; i < FILE_INFO_SIZE; i++) {
|
|
||||||
unmountRomfs(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mountRomfs(uint32_t id) {
|
|
||||||
if (id >= FILE_INFO_SIZE) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("HANDLE WAS TOO BIG %d", id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::lock_guard<std::mutex> lock(fileinfoMutex);
|
|
||||||
bool result = false;
|
|
||||||
if (!gFileInfos[id].romfsMounted) {
|
|
||||||
char buffer[256];
|
|
||||||
snprintf(buffer, 256, "/vol/external01/%s", gFileInfos[id].path);
|
|
||||||
char romName[10];
|
|
||||||
snprintf(romName, 10, "%08X", id);
|
|
||||||
DEBUG_FUNCTION_LINE("Mount %s as %s", buffer, romName);
|
|
||||||
int32_t res = 0;
|
|
||||||
if (WUHBUtils_MountBundle(romName, buffer, BundleSource_FileDescriptor_CafeOS, &res) == WUHB_UTILS_RESULT_SUCCESS && res == 0) {
|
|
||||||
DEBUG_FUNCTION_LINE("Mounted successfully ");
|
|
||||||
gFileInfos[id].romfsMounted = true;
|
|
||||||
result = true;
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Mounting failed %d", res);
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OSMemoryBarrier();
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <coreinit/mcp.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
extern std::mutex fileinfoMutex;
|
|
||||||
|
|
||||||
typedef struct WUT_PACKED FileInfos_ {
|
|
||||||
char path[256];
|
|
||||||
char filename[256];
|
|
||||||
char shortname[64];
|
|
||||||
char longname[64];
|
|
||||||
char author[64];
|
|
||||||
int32_t source;
|
|
||||||
uint32_t lowerTitleID;
|
|
||||||
bool romfsMounted;
|
|
||||||
int openedFiles;
|
|
||||||
MCPTitleListType titleInfo;
|
|
||||||
} FileInfos;
|
|
||||||
|
|
||||||
#define FILE_INFO_SIZE 300
|
|
||||||
extern FileInfos gFileInfos[FILE_INFO_SIZE];
|
|
||||||
|
|
||||||
int32_t getIDByLowerTitleID(uint32_t lowerTitleID);
|
|
||||||
|
|
||||||
void unmountRomfs(uint32_t id);
|
|
||||||
|
|
||||||
void unmountAllRomfs();
|
|
||||||
|
|
||||||
bool mountRomfs(uint32_t id);
|
|
@ -62,7 +62,7 @@ BOOL DirList::LoadPath(const std::string &folder, const char *filter, uint32_t f
|
|||||||
std::string folderpath(folder);
|
std::string folderpath(folder);
|
||||||
uint32_t length = folderpath.size();
|
uint32_t length = folderpath.size();
|
||||||
|
|
||||||
//! clear path of double slashes
|
//! clear relativeFilepath of double slashes
|
||||||
StringTools::RemoveDoubleSlashs(folderpath);
|
StringTools::RemoveDoubleSlashs(folderpath);
|
||||||
|
|
||||||
//! remove last slash if exists
|
//! remove last slash if exists
|
||||||
|
@ -132,7 +132,7 @@ int32_t FSUtils::CreateSubfolder(const char *fullpath) {
|
|||||||
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
||||||
CFile file(path, CFile::WriteOnly);
|
CFile file(path, CFile::WriteOnly);
|
||||||
if (!file.isOpen()) {
|
if (!file.isOpen()) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to open %s\n", path);
|
DEBUG_FUNCTION_LINE_ERR("Failed to open %s\n", path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int32_t written = file.write((const uint8_t *) buffer, size);
|
int32_t written = file.write((const uint8_t *) buffer, size);
|
||||||
@ -147,13 +147,13 @@ bool FSUtils::copyFile(const std::string &in, const std::string &out) {
|
|||||||
|
|
||||||
int source = open(in.c_str(), O_RDONLY, 0);
|
int source = open(in.c_str(), O_RDONLY, 0);
|
||||||
if (source < 0) {
|
if (source < 0) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to open source %s", in.c_str());
|
DEBUG_FUNCTION_LINE_ERR("Failed to open source %s", in.c_str());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int dest = open(out.c_str(), 0x602, 0644);
|
int dest = open(out.c_str(), 0x602, 0644);
|
||||||
if (dest < 0) {
|
if (dest < 0) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to open dest %s", out.c_str());
|
DEBUG_FUNCTION_LINE_ERR("Failed to open dest %s", out.c_str());
|
||||||
close(source);
|
close(source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ bool FSUtils::copyFile(const std::string &in, const std::string &out) {
|
|||||||
auto bufferSize = 128 * 1024;
|
auto bufferSize = 128 * 1024;
|
||||||
char *buf = (char *) malloc(bufferSize);
|
char *buf = (char *) malloc(bufferSize);
|
||||||
if (buf == nullptr) {
|
if (buf == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to alloc buffer");
|
DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
src/fs/FileReader.cpp
Normal file
54
src/fs/FileReader.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "FileReader.h"
|
||||||
|
#include "../utils/logger.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
int64_t FileReader::read(uint8_t *buffer, uint32_t size) {
|
||||||
|
if (isReadFromBuffer) {
|
||||||
|
if (input_buffer == nullptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t toRead = size;
|
||||||
|
if (toRead > input_size - input_pos) {
|
||||||
|
toRead = input_size - input_pos;
|
||||||
|
}
|
||||||
|
if (toRead == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(buffer, &input_buffer[input_pos], toRead);
|
||||||
|
input_pos += toRead;
|
||||||
|
return toRead;
|
||||||
|
} else if (isReadFromFile) {
|
||||||
|
int res = ::read(file_fd, buffer, size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReader::FileReader(std::string &path) {
|
||||||
|
int fd;
|
||||||
|
if ((fd = open(path.c_str(), O_RDONLY)) >= 0) {
|
||||||
|
this->isReadFromFile = true;
|
||||||
|
this->isReadFromBuffer = false;
|
||||||
|
this->file_fd = fd;
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE("## INFO ## Failed to open file %s", path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReader::~FileReader() {
|
||||||
|
if (isReadFromFile) {
|
||||||
|
::close(this->file_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReader::FileReader(uint8_t *buffer, uint32_t size) {
|
||||||
|
this->input_buffer = buffer;
|
||||||
|
this->input_size = size;
|
||||||
|
this->input_pos = 0;
|
||||||
|
this->isReadFromBuffer = true;
|
||||||
|
this->isReadFromFile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileReader::isReady() {
|
||||||
|
return this->isReadFromFile || this->isReadFromBuffer;
|
||||||
|
}
|
37
src/fs/FileReader.h
Normal file
37
src/fs/FileReader.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
class FileReader {
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileReader(uint8_t *buffer, uint32_t size);
|
||||||
|
|
||||||
|
explicit FileReader(std::string &path);
|
||||||
|
|
||||||
|
virtual ~FileReader();
|
||||||
|
|
||||||
|
virtual int64_t read(uint8_t *buffer, uint32_t size);
|
||||||
|
|
||||||
|
virtual bool isReady();
|
||||||
|
|
||||||
|
virtual uint32_t getHandle(){
|
||||||
|
return reinterpret_cast<uint32_t>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FileReader() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isReadFromBuffer = false;
|
||||||
|
uint8_t *input_buffer = nullptr;
|
||||||
|
uint32_t input_size = 0;
|
||||||
|
uint32_t input_pos = 0;
|
||||||
|
|
||||||
|
bool isReadFromFile = false;
|
||||||
|
int file_fd = 0;
|
||||||
|
};
|
79
src/fs/FileReaderWUHB.cpp
Normal file
79
src/fs/FileReaderWUHB.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include "FileReaderWUHB.h"
|
||||||
|
#include "utils/StringTools.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include <coreinit/cache.h>
|
||||||
|
#include <wuhb_utils/utils.h>
|
||||||
|
|
||||||
|
FileReaderWUHB::FileReaderWUHB(const std::shared_ptr<FileInfos>& info, const std::string &relativeFilepath, bool autoUnmount) {
|
||||||
|
if (!info) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Info was NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!info->isBundle) {
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to init file reader for %s, is not a bundle.", info->relativeFilepath.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->autoUnmount = autoUnmount;
|
||||||
|
this->info = info;
|
||||||
|
std::lock_guard<std::mutex> lock(info->accessLock);
|
||||||
|
|
||||||
|
auto romfsName = string_format("%08X", info->lowerTitleID);
|
||||||
|
|
||||||
|
if (!info->MountBundle(romfsName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filepath = romfsName.append(":/").append(relativeFilepath);
|
||||||
|
|
||||||
|
WUHBUtilsStatus status;
|
||||||
|
if ((status = WUHBUtils_FileOpen(filepath.c_str(), &this->fileHandle)) != WUHB_UTILS_RESULT_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to open file in bundle: %s error: %d", filepath.c_str(), status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->info->fileCount++;
|
||||||
|
|
||||||
|
this->initDone = true;
|
||||||
|
OSMemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReaderWUHB::~FileReaderWUHB() {
|
||||||
|
if (!this->initDone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(info->accessLock);
|
||||||
|
|
||||||
|
if (this->fileHandle != 0) {
|
||||||
|
if (WUHBUtils_FileClose(this->fileHandle) != WUHB_UTILS_RESULT_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("WUHBUtils_FileClose failed for %08X", this->fileHandle);
|
||||||
|
}
|
||||||
|
this->fileHandle = 0;
|
||||||
|
info->fileCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoUnmount && info->fileCount <= 0) {
|
||||||
|
if (!info->UnmountBundle()) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to unmount");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Filecount is %d, we don't want to unmount yet", info->fileCount);
|
||||||
|
}
|
||||||
|
OSMemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t FileReaderWUHB::read(uint8_t *buffer, uint32_t size) {
|
||||||
|
if (!this->initDone) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("read file but init was not successful");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int32_t outRes = -1;
|
||||||
|
if (WUHBUtils_FileRead(this->fileHandle, buffer, size, &outRes) == WUHB_UTILS_RESULT_SUCCESS) {
|
||||||
|
return outRes;
|
||||||
|
}
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("WUHBUtils_FileRead failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileReaderWUHB::isReady() {
|
||||||
|
return this->initDone;
|
||||||
|
}
|
18
src/fs/FileReaderWUHB.h
Normal file
18
src/fs/FileReaderWUHB.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../FileInfos.h"
|
||||||
|
#include "FileReader.h"
|
||||||
|
#include <wuhb_utils/utils.h>
|
||||||
|
|
||||||
|
|
||||||
|
class FileReaderWUHB : public FileReader {
|
||||||
|
bool initDone = false;
|
||||||
|
std::shared_ptr<FileInfos> info;
|
||||||
|
WUHBFileHandle fileHandle = 0;
|
||||||
|
bool autoUnmount = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FileReaderWUHB(const std::shared_ptr<FileInfos>& info, const std::string &relativeFilepath, bool autoUnmount);
|
||||||
|
~FileReaderWUHB() override;
|
||||||
|
int64_t read(uint8_t *buffer, uint32_t size) override;
|
||||||
|
bool isReady() override;
|
||||||
|
};
|
284
src/main.cpp
284
src/main.cpp
@ -1,8 +1,9 @@
|
|||||||
#include "FileWrapper.h"
|
#include "FileInfos.h"
|
||||||
#include "SaveRedirection.h"
|
#include "SaveRedirection.h"
|
||||||
#include "fileinfos.h"
|
|
||||||
#include "filelist.h"
|
#include "filelist.h"
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
|
#include "fs/FileReader.h"
|
||||||
|
#include "fs/FileReaderWUHB.h"
|
||||||
#include "utils/StringTools.h"
|
#include "utils/StringTools.h"
|
||||||
#include "utils/ini.h"
|
#include "utils/ini.h"
|
||||||
#include <content_redirection/redirection.h>
|
#include <content_redirection/redirection.h>
|
||||||
@ -14,10 +15,12 @@
|
|||||||
#include <coreinit/systeminfo.h>
|
#include <coreinit/systeminfo.h>
|
||||||
#include <coreinit/title.h>
|
#include <coreinit/title.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <forward_list>
|
||||||
#include <fs/DirList.h>
|
#include <fs/DirList.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <nn/acp.h>
|
#include <nn/acp.h>
|
||||||
|
#include <optional>
|
||||||
#include <rpxloader/rpxloader.h>
|
#include <rpxloader/rpxloader.h>
|
||||||
#include <sdutils/sdutils.h>
|
#include <sdutils/sdutils.h>
|
||||||
#include <sysapp/launch.h>
|
#include <sysapp/launch.h>
|
||||||
@ -38,13 +41,19 @@ WUPS_PLUGIN_AUTHOR("Maschell");
|
|||||||
WUPS_PLUGIN_LICENSE("GPL");
|
WUPS_PLUGIN_LICENSE("GPL");
|
||||||
|
|
||||||
#define UPPER_TITLE_ID_HOMEBREW 0x0005000F
|
#define UPPER_TITLE_ID_HOMEBREW 0x0005000F
|
||||||
|
|
||||||
#define TITLE_ID_HOMEBREW_MASK (((uint64_t) UPPER_TITLE_ID_HOMEBREW) << 32)
|
#define TITLE_ID_HOMEBREW_MASK (((uint64_t) UPPER_TITLE_ID_HOMEBREW) << 32)
|
||||||
|
|
||||||
ACPMetaXml gLaunchXML __attribute__((section(".data")));
|
ACPMetaXml gLaunchXML __attribute__((section(".data")));
|
||||||
MCPTitleListType current_launched_title_info __attribute__((section(".data")));
|
MCPTitleListType current_launched_title_info __attribute__((section(".data")));
|
||||||
BOOL gHomebrewLaunched __attribute__((section(".data")));
|
BOOL gHomebrewLaunched __attribute__((section(".data")));
|
||||||
|
|
||||||
|
|
||||||
|
std::mutex fileInfosMutex;
|
||||||
|
std::forward_list<std::shared_ptr<FileInfos>> fileInfos;
|
||||||
|
|
||||||
|
std::mutex fileReaderListMutex;
|
||||||
|
std::forward_list<std::unique_ptr<FileReader>> openFileReaders;
|
||||||
|
|
||||||
void readCustomTitlesFromSD();
|
void readCustomTitlesFromSD();
|
||||||
|
|
||||||
WUPS_USE_WUT_DEVOPTAB();
|
WUPS_USE_WUT_DEVOPTAB();
|
||||||
@ -52,8 +61,6 @@ WUPS_USE_WUT_DEVOPTAB();
|
|||||||
INITIALIZE_PLUGIN() {
|
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 *) &gFileHandleWrapper, 0, sizeof(gFileHandleWrapper));
|
|
||||||
gHomebrewLaunched = FALSE;
|
gHomebrewLaunched = FALSE;
|
||||||
|
|
||||||
// Use libwuhbutils.
|
// Use libwuhbutils.
|
||||||
@ -82,6 +89,18 @@ bool sSDUtilsInitDone = false;
|
|||||||
bool sSDIsMounted = false;
|
bool sSDIsMounted = false;
|
||||||
bool sTitleRebooting = false;
|
bool sTitleRebooting = false;
|
||||||
|
|
||||||
|
|
||||||
|
void Cleanup() {
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock1(fileReaderListMutex);
|
||||||
|
openFileReaders.clear();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock(fileInfosMutex);
|
||||||
|
fileInfos.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SDAttachedHandler([[maybe_unused]] SDUtilsAttachStatus status) {
|
void SDAttachedHandler([[maybe_unused]] SDUtilsAttachStatus status) {
|
||||||
if (!sTitleRebooting) {
|
if (!sTitleRebooting) {
|
||||||
_SYSLaunchTitleWithStdArgsInNoSplash(OSGetTitleID(), nullptr);
|
_SYSLaunchTitleWithStdArgsInNoSplash(OSGetTitleID(), nullptr);
|
||||||
@ -90,35 +109,31 @@ void SDAttachedHandler([[maybe_unused]] SDUtilsAttachStatus status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ON_APPLICATION_START() {
|
ON_APPLICATION_START() {
|
||||||
|
Cleanup();
|
||||||
initLogging();
|
initLogging();
|
||||||
|
|
||||||
if (OSGetTitleID() == 0x0005001010040000L || // Wii U Menu JPN
|
if (OSGetTitleID() == 0x0005001010040000L || // Wii U Menu JPN
|
||||||
OSGetTitleID() == 0x0005001010040100L || // Wii U Menu USA
|
OSGetTitleID() == 0x0005001010040100L || // Wii U Menu USA
|
||||||
OSGetTitleID() == 0x0005001010040200L) { // Wii U Menu EUR
|
OSGetTitleID() == 0x0005001010040200L) { // Wii U Menu EUR
|
||||||
|
gInWiiUMenu = true;
|
||||||
|
|
||||||
if (SDUtils_Init() >= 0) {
|
if (SDUtils_Init() >= 0) {
|
||||||
sSDUtilsInitDone = true;
|
sSDUtilsInitDone = true;
|
||||||
sTitleRebooting = false;
|
sTitleRebooting = false;
|
||||||
SDUtils_AddAttachHandler(SDAttachedHandler);
|
SDUtils_AddAttachHandler(SDAttachedHandler);
|
||||||
}
|
}
|
||||||
if (SDUtils_IsSdCardMounted(&sSDIsMounted) >= 0 && sSDIsMounted) {
|
|
||||||
readCustomTitlesFromSD();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
gInWiiUMenu = false;
|
gInWiiUMenu = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) {
|
if (_SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY) != OSGetTitleID()) {
|
||||||
DEBUG_FUNCTION_LINE("gHomebrewLaunched to FALSE");
|
|
||||||
gHomebrewLaunched = FALSE;
|
gHomebrewLaunched = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ON_APPLICATION_ENDS() {
|
ON_APPLICATION_ENDS() {
|
||||||
|
Cleanup();
|
||||||
SaveRedirectionCleanUp();
|
SaveRedirectionCleanUp();
|
||||||
unmountAllRomfs();
|
|
||||||
memset((void *) &gFileInfos, 0, sizeof(gFileInfos));
|
|
||||||
FileHandleWrapper_FreeAll();
|
|
||||||
deinitLogging();
|
deinitLogging();
|
||||||
gInWiiUMenu = false;
|
gInWiiUMenu = false;
|
||||||
if (sSDUtilsInitDone) {
|
if (sSDUtilsInitDone) {
|
||||||
@ -129,19 +144,29 @@ ON_APPLICATION_ENDS() {
|
|||||||
sSDIsMounted = false;
|
sSDIsMounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<FileInfos>> getIDByLowerTitleID(uint32_t titleid_lower) {
|
||||||
|
std::lock_guard<std::mutex> lock(fileInfosMutex);
|
||||||
|
for (auto &cur : fileInfos) {
|
||||||
|
if (cur->lowerTitleID == titleid_lower) {
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
int32_t id = getIDByLowerTitleID(titleid_lower);
|
auto titleIdInfoOpt = getIDByLowerTitleID(titleid_lower);
|
||||||
if (id < 0) {
|
if (!titleIdInfoOpt.has_value()) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get id by titleid");
|
DEBUG_FUNCTION_LINE_ERR("Failed to get info by titleid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id >= FILE_INFO_SIZE) {
|
auto &titleInfo = titleIdInfoOpt.value();
|
||||||
return;
|
|
||||||
}
|
out_buf->title_id = (((uint64_t) titleid_upper) << 32) + titleid_lower;
|
||||||
out_buf->title_id = ((uint64_t) titleid_upper * 0x100000000) + titleid_lower;
|
strncpy(out_buf->longname_en, titleInfo->longname.c_str(), sizeof(out_buf->longname_en) - 1);
|
||||||
strncpy(out_buf->longname_en, gFileInfos[id].longname, 64);
|
strncpy(out_buf->shortname_en, titleInfo->shortname.c_str(), sizeof(out_buf->shortname_en) - 1);
|
||||||
strncpy(out_buf->shortname_en, gFileInfos[id].shortname, 64);
|
strncpy(out_buf->publisher_en, titleInfo->author.c_str(), sizeof(out_buf->publisher_en) - 1);
|
||||||
strncpy(out_buf->publisher_en, gFileInfos[id].author, 64);
|
|
||||||
out_buf->e_manual = 1;
|
out_buf->e_manual = 1;
|
||||||
out_buf->e_manual_version = 0;
|
out_buf->e_manual_version = 0;
|
||||||
out_buf->title_version = 1;
|
out_buf->title_version = 1;
|
||||||
@ -157,34 +182,22 @@ void fillXmlForTitleID(uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXm
|
|||||||
out_buf->reserved_flag0 = 0x00010001;
|
out_buf->reserved_flag0 = 0x00010001;
|
||||||
out_buf->reserved_flag6 = 0x00000003;
|
out_buf->reserved_flag6 = 0x00000003;
|
||||||
out_buf->pc_usk = 128;
|
out_buf->pc_usk = 128;
|
||||||
strncpy(out_buf->product_code, "WUP-P-HBLD", strlen("WUP-P-HBLD") + 1);
|
strncpy(out_buf->product_code, "WUP-P-HBLD", sizeof(out_buf->product_code) - 1);
|
||||||
strncpy(out_buf->content_platform, "WUP", strlen("WUP") + 1);
|
strncpy(out_buf->content_platform, "WUP", sizeof(out_buf->content_platform) - 1);
|
||||||
strncpy(out_buf->company_code, "0001", strlen("0001") + 1);
|
strncpy(out_buf->company_code, "0001", sizeof(out_buf->company_code) - 1);
|
||||||
}
|
|
||||||
|
|
||||||
/* hash: compute hash value of string */
|
|
||||||
unsigned int hash(char *str) {
|
|
||||||
unsigned int h;
|
|
||||||
unsigned char *p;
|
|
||||||
|
|
||||||
h = 0;
|
|
||||||
for (p = (unsigned char *) str; *p != '\0'; p++) {
|
|
||||||
h = 37 * h + *p;
|
|
||||||
}
|
|
||||||
return h; // or, h % ARRAY_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handler(void *user, const char *section, const char *name,
|
static int handler(void *user, const char *section, const char *name,
|
||||||
const char *value) {
|
const char *value) {
|
||||||
auto *fInfo = (FileInfos *) user;
|
auto *fInfo = (std::shared_ptr<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
|
||||||
|
|
||||||
if (MATCH("menu", "longname")) {
|
if (MATCH("menu", "longname")) {
|
||||||
strncpy(fInfo->longname, value, 64 - 1);
|
fInfo->operator->()->longname = value;
|
||||||
} else if (MATCH("menu", "shortname")) {
|
} else if (MATCH("menu", "shortname")) {
|
||||||
strncpy(fInfo->shortname, value, 64 - 1);
|
fInfo->operator->()->shortname = value;
|
||||||
} else if (MATCH("menu", "author")) {
|
} else if (MATCH("menu", "author")) {
|
||||||
strncpy(fInfo->author, value, 64 - 1);
|
fInfo->operator->()->author = value;
|
||||||
} else {
|
} else {
|
||||||
return 0; /* unknown section/name, error */
|
return 0; /* unknown section/name, error */
|
||||||
}
|
}
|
||||||
@ -194,20 +207,16 @@ static int handler(void *user, const char *section, const char *name,
|
|||||||
|
|
||||||
bool CheckFileExistsHelper(const char *path);
|
bool CheckFileExistsHelper(const char *path);
|
||||||
void readCustomTitlesFromSD() {
|
void readCustomTitlesFromSD() {
|
||||||
|
std::lock_guard<std::mutex> lock(fileInfosMutex);
|
||||||
|
if (!fileInfos.empty()) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Using cached value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Reset current infos
|
// Reset current infos
|
||||||
unmountAllRomfs();
|
|
||||||
memset((void *) &gFileInfos, 0, sizeof(gFileInfos));
|
|
||||||
|
|
||||||
DirList dirList("fs:/vol/external01/wiiu/apps", ".rpx,.wuhb", DirList::Files | DirList::CheckSubfolders, 1);
|
DirList dirList("fs:/vol/external01/wiiu/apps", ".rpx,.wuhb", DirList::Files | DirList::CheckSubfolders, 1);
|
||||||
dirList.SortList();
|
dirList.SortList();
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < dirList.GetFilecount(); i++) {
|
for (int i = 0; i < dirList.GetFilecount(); i++) {
|
||||||
if (j >= FILE_INFO_SIZE) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("TOO MANY TITLES");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! skip wiiload temp files
|
//! skip wiiload temp files
|
||||||
if (strcasecmp(dirList.GetFilename(i), "temp.rpx") == 0) {
|
if (strcasecmp(dirList.GetFilename(i), "temp.rpx") == 0) {
|
||||||
continue;
|
continue;
|
||||||
@ -228,48 +237,61 @@ void readCustomTitlesFromSD() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto repl = "fs:/vol/external01/";
|
auto repl = "fs:/vol/external01/";
|
||||||
auto input = dirList.GetFilepath(i);
|
auto input = dirList.GetFilepath(i);
|
||||||
|
const char * relativeFilepath;
|
||||||
|
|
||||||
if (std::string_view(input).starts_with(repl)) {
|
if (std::string_view(input).starts_with(repl)) {
|
||||||
strncpy(gFileInfos[j].path, &input[strlen(repl)], sizeof(gFileInfos[j].path));
|
relativeFilepath = &input[strlen(repl)];
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Skip %s, Path doesn't start with %s (This should never happen", input, repl);
|
DEBUG_FUNCTION_LINE_ERR("Skip %s, Path doesn't start with %s (This should never happen", input, repl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
gFileInfos[j].lowerTitleID = hash(gFileInfos[j].path);
|
auto fileInfo = make_shared_nothrow<FileInfos>(relativeFilepath);
|
||||||
|
if (!fileInfo) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("No more memory");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
MCPTitleListType *cur_title_info = &(gFileInfos[j].titleInfo);
|
std::lock_guard<std::mutex> infoLock(fileInfo->accessLock);
|
||||||
|
|
||||||
snprintf(cur_title_info->path, sizeof(cur_title_info->path), "/custom/%08X%08X", UPPER_TITLE_ID_HOMEBREW, gFileInfos[j].lowerTitleID);
|
auto *cur_title_info = &(fileInfo->titleInfo);
|
||||||
|
|
||||||
strncpy(gFileInfos[j].filename, dirList.GetFilename(i), sizeof(gFileInfos[j].filename));
|
snprintf(cur_title_info->path, sizeof(cur_title_info->path), "/custom/%08X%08X", UPPER_TITLE_ID_HOMEBREW, fileInfo->lowerTitleID);
|
||||||
strncpy(gFileInfos[j].longname, dirList.GetFilename(i), sizeof(gFileInfos[j].longname));
|
|
||||||
strncpy(gFileInfos[j].shortname, dirList.GetFilename(i), sizeof(gFileInfos[j].shortname));
|
|
||||||
strncpy(gFileInfos[j].author, dirList.GetFilename(i), sizeof(gFileInfos[j].author));
|
|
||||||
gFileInfos[j].source = 0; //SD Card;
|
|
||||||
|
|
||||||
const char *indexedDevice = "mlc";
|
const char *indexedDevice = "mlc";
|
||||||
strncpy(cur_title_info->indexedDevice, indexedDevice, sizeof(cur_title_info->indexedDevice));
|
strncpy(cur_title_info->indexedDevice, indexedDevice, sizeof(cur_title_info->indexedDevice) - 1);
|
||||||
|
|
||||||
|
fileInfo->filename = dirList.GetFilename(i);
|
||||||
|
fileInfo->longname = dirList.GetFilename(i);
|
||||||
|
fileInfo->shortname = dirList.GetFilename(i);
|
||||||
|
fileInfo->author = dirList.GetFilename(i);
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Check %s", fileInfo->filename.c_str());
|
||||||
|
|
||||||
// Check if the bootTvTex and bootDrcTex exists
|
// Check if the bootTvTex and bootDrcTex exists
|
||||||
if (std::string_view(gFileInfos[j].filename).ends_with(".wuhb")) {
|
if (std::string_view(fileInfo->filename).ends_with(".wuhb")) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
#define TMP_BUNDLE_NAME "romfscheck"
|
#define TMP_BUNDLE_NAME "romfscheck"
|
||||||
|
|
||||||
if (WUHBUtils_MountBundle(TMP_BUNDLE_NAME, dirList.GetFilepath(i), BundleSource_FileDescriptor, &result) == WUHB_UTILS_RESULT_SUCCESS && result >= 0) {
|
if (WUHBUtils_MountBundle(TMP_BUNDLE_NAME, dirList.GetFilepath(i), BundleSource_FileDescriptor, &result) == WUHB_UTILS_RESULT_SUCCESS && result >= 0) {
|
||||||
|
fileInfo->isBundle = true;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
uint32_t bufferSize;
|
uint32_t bufferSize;
|
||||||
|
|
||||||
auto readRes = WUHBUtils_ReadWholeFile(TMP_BUNDLE_NAME ":/meta/meta.ini", &buffer, &bufferSize);
|
auto readRes = WUHBUtils_ReadWholeFile(TMP_BUNDLE_NAME ":/meta/meta.ini", &buffer, &bufferSize);
|
||||||
if (readRes == WUHB_UTILS_RESULT_SUCCESS) {
|
if (readRes == WUHB_UTILS_RESULT_SUCCESS) {
|
||||||
buffer[bufferSize - 1] = '\0';
|
buffer[bufferSize - 1] = '\0';
|
||||||
if (ini_parse_string((const char *) buffer, handler, &gFileInfos[j]) < 0) {
|
if (ini_parse_string((const char *) buffer, handler, &fileInfo) < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to parse meta.ini");
|
DEBUG_FUNCTION_LINE_ERR("Failed to parse meta.ini");
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@ -283,6 +305,7 @@ void readCustomTitlesFromSD() {
|
|||||||
if (CheckFileExistsHelper(bootTvTexPath) && CheckFileExistsHelper(bootDrcTexPath)) {
|
if (CheckFileExistsHelper(bootTvTexPath) && CheckFileExistsHelper(bootDrcTexPath)) {
|
||||||
// Show splash screens
|
// Show splash screens
|
||||||
cur_title_info->appType = MCP_APP_TYPE_GAME;
|
cur_title_info->appType = MCP_APP_TYPE_GAME;
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Title has splashscreen");
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t unmountRes;
|
int32_t unmountRes;
|
||||||
@ -294,12 +317,12 @@ void readCustomTitlesFromSD() {
|
|||||||
DEBUG_FUNCTION_LINE_ERR("Failed to unmount \"%s\"", TMP_BUNDLE_NAME);
|
DEBUG_FUNCTION_LINE_ERR("Failed to unmount \"%s\"", TMP_BUNDLE_NAME);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("%s is not a .wuhb file: %d", dirList.GetFilepath(i), result);
|
DEBUG_FUNCTION_LINE_ERR("%s is not a valid .wuhb file: %d", dirList.GetFilepath(i), result);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_title_info->titleId = TITLE_ID_HOMEBREW_MASK | gFileInfos[j].lowerTitleID;
|
cur_title_info->titleId = TITLE_ID_HOMEBREW_MASK | fileInfo->lowerTitleID;
|
||||||
cur_title_info->titleVersion = 1;
|
cur_title_info->titleVersion = 1;
|
||||||
cur_title_info->groupId = 0x400;
|
cur_title_info->groupId = 0x400;
|
||||||
|
|
||||||
@ -307,7 +330,7 @@ void readCustomTitlesFromSD() {
|
|||||||
cur_title_info->sdkVersion = __OSGetProcessSDKVersion();
|
cur_title_info->sdkVersion = __OSGetProcessSDKVersion();
|
||||||
cur_title_info->unk0x60 = 0;
|
cur_title_info->unk0x60 = 0;
|
||||||
|
|
||||||
j++;
|
fileInfos.push_front(fileInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,38 +351,42 @@ bool CheckFileExistsHelper(const char *path) {
|
|||||||
|
|
||||||
DECL_FUNCTION(int32_t, MCP_TitleList, uint32_t handle, uint32_t *outTitleCount, MCPTitleListType *titleList, uint32_t size) {
|
DECL_FUNCTION(int32_t, MCP_TitleList, uint32_t handle, uint32_t *outTitleCount, MCPTitleListType *titleList, uint32_t size) {
|
||||||
int32_t result = real_MCP_TitleList(handle, outTitleCount, titleList, size);
|
int32_t result = real_MCP_TitleList(handle, outTitleCount, titleList, size);
|
||||||
uint32_t titlecount = *outTitleCount;
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(fileinfoMutex);
|
if (!gInWiiUMenu) {
|
||||||
for (auto &gFileInfo : gFileInfos) {
|
DEBUG_FUNCTION_LINE_VERBOSE("Not in Wii U Menu");
|
||||||
if (gFileInfo.lowerTitleID == 0) {
|
return result;
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(&(titleList[titlecount]), &(gFileInfo.titleInfo), sizeof(gFileInfo.titleInfo));
|
|
||||||
titlecount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*outTitleCount = titlecount;
|
uint32_t titleCount = *outTitleCount;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(fileInfosMutex);
|
||||||
|
readCustomTitlesFromSD();
|
||||||
|
|
||||||
|
for (auto &gFileInfo : fileInfos) {
|
||||||
|
memcpy(&(titleList[titleCount]), &(gFileInfo->titleInfo), sizeof(MCPTitleListType));
|
||||||
|
titleCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outTitleCount = titleCount;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType *title, uint32_t u2) {
|
DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType *title, uint32_t u2) {
|
||||||
if ((title->titleId & TITLE_ID_HOMEBREW_MASK) == TITLE_ID_HOMEBREW_MASK) {
|
if ((title->titleId & TITLE_ID_HOMEBREW_MASK) == TITLE_ID_HOMEBREW_MASK) {
|
||||||
int32_t id = getIDByLowerTitleID(title->titleId & 0xFFFFFFFF);
|
std::lock_guard<std::mutex> lock(fileInfosMutex);
|
||||||
if (id >= 0) {
|
auto fileInfo = getIDByLowerTitleID(title->titleId & 0xFFFFFFFF);
|
||||||
|
if (fileInfo.has_value()) {
|
||||||
DEBUG_FUNCTION_LINE("Starting a homebrew title");
|
DEBUG_FUNCTION_LINE("Starting a homebrew title");
|
||||||
|
|
||||||
fillXmlForTitleID((title->titleId & 0xFFFFFFFF00000000) >> 32, (title->titleId & 0xFFFFFFFF), &gLaunchXML);
|
fillXmlForTitleID((title->titleId & 0xFFFFFFFF00000000) >> 32, (title->titleId & 0xFFFFFFFF), &gLaunchXML);
|
||||||
|
|
||||||
std::string bundleFilePath = std::string("/vol/external01/") + gFileInfos[id].path;
|
|
||||||
|
|
||||||
gHomebrewLaunched = TRUE;
|
gHomebrewLaunched = TRUE;
|
||||||
|
|
||||||
RPXLoader_LoadFromSDOnNextLaunch(gFileInfos[id].path);
|
RPXLoader_LoadFromSDOnNextLaunch(fileInfo.value()->relativeFilepath.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get the id for titleID %016llX", title->titleId);
|
DEBUG_FUNCTION_LINE_ERR("Failed to get info for titleID %016llX", title->titleId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,42 +394,43 @@ DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType *t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, uint32_t *handle, int error) {
|
DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, uint32_t *handle, int error) {
|
||||||
const char *start = "/vol/storage_mlc01/sys/title/0005000F";
|
const char *start = "/vol/storage_mlc01/sys/title/0005000F";
|
||||||
const char *icon = ".tga";
|
const char *tga = ".tga";
|
||||||
const char *iconTex = "iconTex.tga";
|
const char *iconTex = "iconTex.tga";
|
||||||
const char *sound = ".btsnd";
|
const char *sound = ".btsnd";
|
||||||
|
|
||||||
std::string_view pathStr = path;
|
std::string_view pathStr = path;
|
||||||
|
|
||||||
if (pathStr.ends_with(icon) || pathStr.ends_with(sound)) {
|
if (pathStr.starts_with(start)) {
|
||||||
if (strncmp(path, start, strlen(start)) == 0) {
|
std::unique_ptr<FileReader> reader;
|
||||||
int res = FS_STATUS_NOT_FOUND;
|
if (pathStr.ends_with(tga) || pathStr.ends_with(sound)) {
|
||||||
|
|
||||||
if (pathStr.ends_with(iconTex)) {
|
|
||||||
// fallback to dummy icon if loaded homebrew is no .wuhb
|
|
||||||
*handle = 0x13371338;
|
|
||||||
res = FS_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lowerTitleID;
|
|
||||||
char *id = path + 1 + strlen(start);
|
char *id = path + 1 + strlen(start);
|
||||||
id[8] = 0;
|
id[8] = 0;
|
||||||
char *ending = id + 9;
|
char *relativePath = id + 9;
|
||||||
sscanf(id, "%08X", &lowerTitleID);
|
auto lowerTitleID = strtoul(id, 0, 16);
|
||||||
int32_t idVal = getIDByLowerTitleID(lowerTitleID);
|
auto fileInfo = getIDByLowerTitleID(lowerTitleID);
|
||||||
if (idVal >= 0) {
|
if (fileInfo.has_value()) {
|
||||||
if (!std::string_view(gFileInfos[idVal].filename).ends_with(".wuhb")) {
|
reader = make_unique_nothrow<FileReaderWUHB>(fileInfo.value(), relativePath, !gHomebrewLaunched);
|
||||||
return res;
|
if (reader && !reader->isReady()) {
|
||||||
|
reader.reset();
|
||||||
}
|
}
|
||||||
if (OpenFileForID(idVal, ending, handle) >= 0) {
|
}
|
||||||
|
}
|
||||||
|
// If the icon is requested and loading it from a bundle failed, we fall back to a default one.
|
||||||
|
if (reader == nullptr && pathStr.ends_with(iconTex)) {
|
||||||
|
reader = make_unique_nothrow<FileReader>((uint8_t *) iconTex_tga, iconTex_tga_size);
|
||||||
|
if (reader && !reader->isReady()) {
|
||||||
|
reader.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reader) {
|
||||||
|
std::lock_guard<std::mutex> lock(fileReaderListMutex);
|
||||||
|
*handle = reader->getHandle();
|
||||||
|
openFileReaders.push_front(std::move(reader));
|
||||||
return FS_STATUS_OK;
|
return FS_STATUS_OK;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to find id for titleID %08X", lowerTitleID);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = real_FSOpenFile(client, block, path, mode, handle, error);
|
int result = real_FSOpenFile(client, block, path, mode, handle, error);
|
||||||
@ -410,48 +438,18 @@ 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 == 0x13371338) {
|
if (remove_locked_first_if(fileReaderListMutex, openFileReaders, [handle](auto &cur) { return cur->getHandle() == handle; })) {
|
||||||
return FS_STATUS_OK;
|
|
||||||
} else if ((handle & 0xFF000000) == 0xFF000000) {
|
|
||||||
int32_t fd = (handle & 0x00000FFF);
|
|
||||||
int32_t romid = (handle & 0x00FFF000) >> 12;
|
|
||||||
std::lock_guard<std::mutex> lock(fileinfoMutex);
|
|
||||||
uint32_t rl_handle = gFileHandleWrapper[fd].handle;
|
|
||||||
if (WUHBUtils_FileClose(rl_handle) != WUHB_UTILS_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to close file %08X", rl_handle);
|
|
||||||
}
|
|
||||||
if (gFileInfos[romid].openedFiles--) {
|
|
||||||
DCFlushRange(&gFileInfos[romid].openedFiles, 4);
|
|
||||||
if (gFileInfos[romid].openedFiles <= 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("unmount romfs no more handles");
|
|
||||||
unmountRomfs(romid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 == 0x13371338) {
|
const std::lock_guard<std::mutex> lock(fileReaderListMutex);
|
||||||
uint32_t cpySize = size * count;
|
for (auto &reader : openFileReaders) {
|
||||||
if (iconTex_tga_size < cpySize) {
|
if ((uint32_t) reader.get() == (uint32_t) handle) {
|
||||||
cpySize = iconTex_tga_size;
|
return (FSStatus) (reader->read(buffer, size * count) / size);
|
||||||
}
|
|
||||||
memcpy(buffer, iconTex_tga, cpySize);
|
|
||||||
return (FSStatus) (cpySize / size);
|
|
||||||
} else if ((handle & 0xFF000000) == 0xFF000000) {
|
|
||||||
uint32_t fd = (handle & 0x00000FFF);
|
|
||||||
[[maybe_unused]] uint32_t romid = (handle & 0x00FFF000) >> 12;
|
|
||||||
|
|
||||||
uint32_t rl_handle = gFileHandleWrapper[fd].handle;
|
|
||||||
|
|
||||||
int readSize = 0;
|
|
||||||
if (WUHBUtils_FileRead(rl_handle, buffer, (size * count), &readSize) == WUHB_UTILS_RESULT_SUCCESS) {
|
|
||||||
return (FSStatus) (readSize / size);
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to read file");
|
|
||||||
OSFatal("Failed to read file");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FSStatus result = real_FSReadFile(client, block, buffer, size, count, handle, unk1, flags);
|
FSStatus result = real_FSReadFile(client, block, buffer, size, count, handle, unk1, flags);
|
||||||
@ -604,9 +602,9 @@ DECL_FUNCTION(uint32_t, MCPGetTitleInternal, uint32_t mcp_handle, void *input, u
|
|||||||
if (input != nullptr) {
|
if (input != nullptr) {
|
||||||
auto *inputPtrAsU32 = (uint32_t *) input;
|
auto *inputPtrAsU32 = (uint32_t *) input;
|
||||||
if (inputPtrAsU32[0] == UPPER_TITLE_ID_HOMEBREW && out_cnt >= 1) {
|
if (inputPtrAsU32[0] == UPPER_TITLE_ID_HOMEBREW && out_cnt >= 1) {
|
||||||
for (auto &gFileInfo : gFileInfos) {
|
for (auto &gFileInfo : fileInfos) {
|
||||||
if (gFileInfo.lowerTitleID == inputPtrAsU32[1]) {
|
if (gFileInfo->lowerTitleID == inputPtrAsU32[1]) {
|
||||||
memcpy(&titles[0], &(gFileInfo.titleInfo), sizeof(MCPTitleListType));
|
memcpy(&titles[0], &(gFileInfo->titleInfo), sizeof(MCPTitleListType));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ const char *StringTools::FullpathToFilename(const char *path) {
|
|||||||
void StringTools::RemoveDoubleSlashs(std::string &str) {
|
void StringTools::RemoveDoubleSlashs(std::string &str) {
|
||||||
uint32_t length = str.size();
|
uint32_t length = str.size();
|
||||||
|
|
||||||
//! clear path of double slashes
|
//! clear relativeFilepath of double slashes
|
||||||
for (uint32_t i = 1; i < length; ++i) {
|
for (uint32_t i = 1; i < length; ++i) {
|
||||||
if (str[i - 1] == '/' && str[i] == '/') {
|
if (str[i - 1] == '/' && str[i] == '/') {
|
||||||
str.erase(i, 1);
|
str.erase(i, 1);
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
#include "utils/logger.h"
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <whb/log.h>
|
|
||||||
|
|
||||||
// https://gist.github.com/ccbrown/9722406
|
|
||||||
void dumpHex(const void *data, size_t size) {
|
|
||||||
char ascii[17];
|
|
||||||
size_t i, j;
|
|
||||||
ascii[16] = '\0';
|
|
||||||
DEBUG_FUNCTION_LINE_WRITE("0x%08X (0x0000): ", data);
|
|
||||||
for (i = 0; i < size; ++i) {
|
|
||||||
WHBLogWritef("%02X ", ((unsigned char *) data)[i]);
|
|
||||||
if (((unsigned char *) data)[i] >= ' ' && ((unsigned char *) data)[i] <= '~') {
|
|
||||||
ascii[i % 16] = ((unsigned char *) data)[i];
|
|
||||||
} else {
|
|
||||||
ascii[i % 16] = '.';
|
|
||||||
}
|
|
||||||
if ((i + 1) % 8 == 0 || i + 1 == size) {
|
|
||||||
WHBLogWritef(" ");
|
|
||||||
if ((i + 1) % 16 == 0) {
|
|
||||||
WHBLogPrintf("| %s ", ascii);
|
|
||||||
if (i + 1 < size) {
|
|
||||||
DEBUG_FUNCTION_LINE_WRITE("0x%08X (0x%04X); ", data + i + 1, i + 1);
|
|
||||||
}
|
|
||||||
} else if (i + 1 == size) {
|
|
||||||
ascii[(i + 1) % 16] = '\0';
|
|
||||||
if ((i + 1) % 16 <= 8) {
|
|
||||||
WHBLogWritef(" ");
|
|
||||||
}
|
|
||||||
for (j = (i + 1) % 16; j < 16; ++j) {
|
|
||||||
WHBLogWritef(" ");
|
|
||||||
}
|
|
||||||
WHBLogPrintf("| %s ", ascii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
13
src/utils/utils.cpp
Normal file
13
src/utils/utils.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* hash: compute hash value of string */
|
||||||
|
unsigned int hash_string(const char *str) {
|
||||||
|
unsigned int h;
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
for (p = (unsigned char *) str; *p != '\0'; p++) {
|
||||||
|
h = 37 * h + *p;
|
||||||
|
}
|
||||||
|
return h; // or, h % ARRAY_SIZE;
|
||||||
|
}
|
@ -1,36 +1,32 @@
|
|||||||
#ifndef __UTILS_H_
|
#pragma once
|
||||||
#define __UTILS_H_
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <forward_list>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
uint32_t hash_string(const char *);
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LIMIT(x, min, max) \
|
template<class T, class... Args>
|
||||||
({ \
|
std::unique_ptr<T> make_unique_nothrow(Args &&...args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
|
||||||
typeof(x) _x = x; \
|
return std::unique_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
|
||||||
typeof(min) _min = min; \
|
}
|
||||||
typeof(max) _max = max; \
|
|
||||||
(((_x) < (_min)) ? (_min) : ((_x) > (_max)) ? (_max) \
|
template<class T, class... Args>
|
||||||
: (_x)); \
|
std::shared_ptr<T> make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
|
||||||
})
|
return std::shared_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
#define DegToRad(a) ((a) *0.01745329252f)
|
|
||||||
#define RadToDeg(a) ((a) *57.29577951f)
|
template<typename T, class Allocator, class Predicate>
|
||||||
|
bool remove_locked_first_if(std::mutex &mutex, std::forward_list<T, Allocator> &list, Predicate pred) {
|
||||||
#define ALIGN4(x) (((x) + 3) & ~3)
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
#define ALIGN32(x) (((x) + 31) & ~31)
|
auto oit = list.before_begin(), it = std::next(oit);
|
||||||
|
while (it != list.end()) {
|
||||||
#define le16(i) ((((uint16_t) ((i) &0xFF)) << 8) | ((uint16_t) (((i) &0xFF00) >> 8)))
|
if (pred(*it)) {
|
||||||
#define le32(i) ((((uint32_t) le16((i) &0xFFFF)) << 16) | ((uint32_t) le16(((i) &0xFFFF0000) >> 16)))
|
list.erase_after(oit);
|
||||||
#define le64(i) ((((uint64_t) le32((i) &0xFFFFFFFFLL)) << 32) | ((uint64_t) le32(((i) &0xFFFFFFFF00000000LL) >> 32)))
|
return true;
|
||||||
|
}
|
||||||
//Needs to have log_init() called beforehand.
|
oit = it++;
|
||||||
void dumpHex(const void *data, size_t size);
|
}
|
||||||
|
return false;
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __UTILS_H_
|
|
||||||
|
Loading…
Reference in New Issue
Block a user