mirror of
https://gitlab.com/Nanolx/homebrewfilter.git
synced 2024-12-01 05:24:21 +01:00
234 lines
4.8 KiB
C++
234 lines
4.8 KiB
C++
#include <malloc.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ogc/machine/processor.h>
|
|
#include <wiiuse/wpad.h>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <sys/dir.h>
|
|
|
|
#include "main.h"
|
|
#include "dolloader.h"
|
|
#include "elfloader.h"
|
|
#include "filelist.h"
|
|
#include "DiskOperations/di2.h"
|
|
#include "Tools/load_channel.h"
|
|
#include "Tools/parser.h"
|
|
|
|
#define BLOCKSIZE 70*1024 //70KB
|
|
#define MAX_CMDLINE 4096
|
|
#define MAX_ARGV 1000
|
|
|
|
#define GC_DOL_MAGIC "gchomebrew dol"
|
|
#define GC_MAGIC_BUF (char *) 0x807FFFE0
|
|
#define GC_DOL_BUF (u8 *)0x80800000
|
|
#define BC 0x0000000100000100ULL
|
|
|
|
struct __argv args;
|
|
char cmdline[MAX_CMDLINE];
|
|
char *a_argv[MAX_ARGV];
|
|
char *meta_buf = NULL;
|
|
static u8 *homebrewbuffer = (u8 *) 0x92000000;
|
|
static u32 homebrewsize = 0;
|
|
std::string filepath;
|
|
|
|
void arg_init()
|
|
{
|
|
memset(&args, 0, sizeof(args));
|
|
memset(cmdline, 0, sizeof(cmdline));
|
|
memset(a_argv, 0, sizeof(a_argv));
|
|
args.argvMagic = ARGV_MAGIC;
|
|
args.length = 1; // double \0\0
|
|
args.argc = 0;
|
|
args.commandLine = cmdline;
|
|
args.argv = a_argv;
|
|
args.endARGV = a_argv;
|
|
}
|
|
|
|
char* strcopy(char *dest, const char *src, int size)
|
|
{
|
|
strncpy(dest,src,size);
|
|
dest[size-1] = 0;
|
|
return dest;
|
|
}
|
|
|
|
int arg_add(const char *arg)
|
|
{
|
|
int len = strlen(arg);
|
|
if (args.argc >= MAX_ARGV) return -1;
|
|
if (args.length + len + 1 > MAX_CMDLINE) return -1;
|
|
strcopy(cmdline + args.length - 1, arg, len+1);
|
|
args.length += len + 1; // 0 term.
|
|
cmdline[args.length - 1] = 0; // double \0\0
|
|
args.argc++;
|
|
args.endARGV = args.argv + args.argc;
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* FileSize
|
|
*
|
|
* Get filesize in bytes. u64 for files bigger than 4GB
|
|
***************************************************************************/
|
|
u64 FileSize(const char * filepath)
|
|
{
|
|
struct stat filestat;
|
|
|
|
if (stat(filepath, &filestat) != 0)
|
|
return 0;
|
|
|
|
return filestat.st_size;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* LoadFileToMem
|
|
*
|
|
* Load up the file into a block of memory
|
|
***************************************************************************/
|
|
int LoadFileToMem(const char *filepath, u8 **inbuffer, u64 *size)
|
|
{
|
|
int ret = -1;
|
|
u64 filesize = FileSize(filepath);
|
|
char * filename = strrchr(filepath, '/');
|
|
if(filename)
|
|
filename++;
|
|
|
|
*inbuffer = NULL;
|
|
*size = 0;
|
|
|
|
FILE *file = fopen(filepath, "rb");
|
|
|
|
if (file == NULL)
|
|
return -1;
|
|
|
|
u8 *buffer = (u8 *) malloc(filesize);
|
|
if (buffer == NULL)
|
|
{
|
|
fclose(file);
|
|
return -2;
|
|
}
|
|
|
|
u64 done = 0;
|
|
u32 blocksize = BLOCKSIZE;
|
|
|
|
do
|
|
{
|
|
|
|
if(blocksize > filesize-done)
|
|
blocksize = filesize-done;
|
|
|
|
ret = fread(buffer+done, 1, blocksize, file);
|
|
if(ret < 0)
|
|
{
|
|
free(buffer);
|
|
fclose(file);
|
|
return -3;
|
|
}
|
|
else if(ret == 0)
|
|
{
|
|
//we are done
|
|
break;
|
|
}
|
|
|
|
done += ret;
|
|
|
|
}
|
|
while(done < filesize);
|
|
|
|
fclose(file);
|
|
|
|
if (done != filesize)
|
|
{
|
|
free(buffer);
|
|
return -3;
|
|
}
|
|
|
|
*inbuffer = buffer;
|
|
*size = filesize;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len)
|
|
{
|
|
homebrewsize += len;
|
|
memcpy((homebrewbuffer)+pos, temp, len);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int LoadHomebrew(const char * path)
|
|
{
|
|
filepath = path;
|
|
u8 *buffer = NULL;
|
|
u64 filesize = 0;
|
|
int ret = LoadFileToMem(path, &buffer, &filesize);
|
|
if(ret < 0)
|
|
return ret;
|
|
|
|
ret = CopyHomebrewMemory(buffer, 0, filesize);
|
|
if(buffer) {
|
|
free(buffer);
|
|
buffer = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int BootHomebrew()
|
|
{
|
|
if(homebrewsize == 0)
|
|
return -1;
|
|
|
|
entrypoint entry;
|
|
u32 cpu_isr;
|
|
|
|
arg_init();
|
|
arg_add(filepath.c_str()); // argv[0] = filepath
|
|
while(parser(Settings.forwarder_arg, "<arg>", "</arg>") != "")
|
|
{
|
|
arg_add(parser(Settings.forwarder_arg, "<arg>", "</arg>").c_str());
|
|
Settings.forwarder_arg.erase(0, Settings.forwarder_arg.find("</arg>") +1);
|
|
}
|
|
|
|
if ( valid_elf_image(homebrewbuffer) == 1 )
|
|
entry = (entrypoint) load_elf_image(homebrewbuffer);
|
|
else
|
|
entry = (entrypoint) load_dol(homebrewbuffer, &args);
|
|
|
|
if (!entry)
|
|
return -1;
|
|
|
|
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
|
_CPU_ISR_Disable (cpu_isr);
|
|
__exception_closeall();
|
|
entry();
|
|
_CPU_ISR_Restore (cpu_isr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int BootGameCubeHomebrew()
|
|
{
|
|
if(homebrewsize == 0)
|
|
return -1;
|
|
|
|
static tikview view ATTRIBUTE_ALIGN(32);
|
|
|
|
DI2_Init();
|
|
DI2_Reset();
|
|
DI2_ReadDiscID((u64 *) 0x80000000);
|
|
DI2_Mount();
|
|
|
|
strcpy(GC_MAGIC_BUF, GC_DOL_MAGIC);
|
|
DCFlushRange(GC_MAGIC_BUF, 32);
|
|
memcpy(GC_DOL_BUF, homebrewbuffer, homebrewsize);
|
|
DCFlushRange(GC_DOL_BUF, homebrewsize);
|
|
*(vu32 *) 0xCC003024 |= 0x07;
|
|
|
|
ES_GetTicketViews(BC, &view, 1);
|
|
int ret = ES_LaunchTitle(BC, &view);
|
|
|
|
return ret;
|
|
}
|