#include #include #include #include #include #include #include #include #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_add(parser(Settings.forwarder_arg, "", "").c_str()); Settings.forwarder_arg.erase(0, Settings.forwarder_arg.find("") +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); if(ret < 0) LoadHBC(); return ret; }