| 1 | //-------------------------------------------------------------- | 
 
 
 
 
 | 2 | //File name:    loader.c | 
 
 
 
 
 | 3 | //-------------------------------------------------------------- | 
 
 
 
 
 | 4 | //dlanor: This subprogram has been modified to minimize the code | 
 
 
 
 
 | 5 | //dlanor: size of the resident loader portion. Some of the parts | 
 
 
 
 
 | 6 | //dlanor: that were moved into the main program include loading | 
 
 
 
 
 | 7 | //dlanor: of all IRXs and mounting pfs0: for ELFs on hdd. | 
 
 
 
 
 | 8 | //dlanor: Another change was to skip threading in favor of ExecPS2 | 
 
 
 
 
 | 9 | /*================================================================== | 
 
 
 
 
 | 10 | ==                                                                                      == | 
 
 
 
 
 | 11 | ==      Copyright(c)2004  Adam Metcalf(gamblore_@hotmail.com)           == | 
 
 
 
 
 | 12 | ==      Copyright(c)2004  Thomas Hawcroft(t0mb0la@yahoo.com)            == | 
 
 
 
 
 | 13 | ==      This file is subject to terms and conditions shown in the       == | 
 
 
 
 
 | 14 | ==      file LICENSE which should be kept in the top folder of  == | 
 
 
 
 
 | 15 | ==      this distribution.                                                      == | 
 
 
 
 
 | 16 | ==                                                                                      == | 
 
 
 
 
 | 17 | ==      Portions of this code taken from PS2Link:                               == | 
 
 
 
 
 | 18 | ==                              pkoLoadElf                                              == | 
 
 
 
 
 | 19 | ==                              wipeUserMemory                                  == | 
 
 
 
 
 | 20 | ==                              (C) 2003 Tord Lindstrom (pukko@home.se) == | 
 
 
 
 
 | 21 | ==                              (C) 2003 adresd (adresd_ps2dev@yahoo.com)       == | 
 
 
 
 
 | 22 | ==      Portions of this code taken from Independence MC exploit        == | 
 
 
 
 
 | 23 | ==                              tLoadElf                                                == | 
 
 
 
 
 | 24 | ==                              LoadAndRunHDDElf                                        == | 
 
 
 
 
 | 25 | ==                              (C) 2003 Marcus Brown <mrbrown@0xd6.org>        == | 
 
 
 
 
 | 26 | ==                                                                                      == | 
 
 
 
 
 | 27 | ==================================================================*/ | 
 
 
 
 
 | 28 | #include "tamtypes.h" | 
 
 
 
 
 | 29 | #include "debug.h" | 
 
 
 
 
 | 30 | #include "kernel.h" | 
 
 
 
 
 | 31 | #include "sifrpc.h" | 
 
 
 
 
 | 32 | #include "loadfile.h" | 
 
 
 
 
 | 33 | #include "fileio.h" | 
 
 
 
 
 | 34 | #include "iopcontrol.h" | 
 
 
 
 
 | 35 | #include "stdarg.h" | 
 
 
 
 
 | 36 | #include "stdio.h" // Iritscen: added this for printf() | 
 
 
 
 
 | 37 | #include "string.h" | 
 
 
 
 
 | 38 | #include "malloc.h" | 
 
 
 
 
 | 39 | #include "libmc.h" | 
 
 
 
 
 | 40 | #include "iopheap.h" | 
 
 
 
 
 | 41 | #include "sys/fcntl.h" | 
 
 
 
 
 | 42 | #include "sys/stat.h" | 
 
 
 
 
 | 43 | #include "sys/ioctl.h" | 
 
 
 
 
 | 44 | #include "fileXio_rpc.h" | 
 
 
 
 
 | 45 | #include "errno.h" | 
 
 
 
 
 | 46 | #include "libhdd.h" | 
 
 
 
 
 | 47 | #include "sbv_patches.h" | 
 
 
 
 
 | 48 | //-------------------------------------------------------------- | 
 
 
 
 
 | 49 | //#define DEBUG | 
 
 
 
 
 | 50 | #ifdef DEBUG | 
 
 
 
 
 | 51 | #define dbgprintf(args...) scr_printf(args) | 
 
 
 
 
 | 52 | #define dbginit_scr() init_scr() | 
 
 
 
 
 | 53 | #else | 
 
 
 
 
 | 54 | #define dbgprintf(args...) do { } while(0) | 
 
 
 
 
 | 55 | #define dbginit_scr() do { } while(0) | 
 
 
 
 
 | 56 | #endif | 
 
 
 
 
 | 57 |  | 
 
 
 
 
 | 58 | // ELF-header structures and identifiers | 
 
 
 
 
 | 59 | #define ELF_MAGIC       0x464c457f | 
 
 
 
 
 | 60 | #define ELF_PT_LOAD     1 | 
 
 
 
 
 | 61 |  | 
 
 
 
 
 | 62 | //-------------------------------------------------------------- | 
 
 
 
 
 | 63 | typedef struct | 
 
 
 
 
 | 64 | { | 
 
 
 
 
 | 65 | u8      ident[16]; | 
 
 
 
 
 | 66 | u16     type; | 
 
 
 
 
 | 67 | u16     machine; | 
 
 
 
 
 | 68 | u32     version; | 
 
 
 
 
 | 69 | u32     entry; | 
 
 
 
 
 | 70 | u32     phoff; | 
 
 
 
 
 | 71 | u32     shoff; | 
 
 
 
 
 | 72 | u32     flags; | 
 
 
 
 
 | 73 | u16     ehsize; | 
 
 
 
 
 | 74 | u16     phentsize; | 
 
 
 
 
 | 75 | u16     phnum; | 
 
 
 
 
 | 76 | u16     shentsize; | 
 
 
 
 
 | 77 | u16     shnum; | 
 
 
 
 
 | 78 | u16     shstrndx; | 
 
 
 
 
 | 79 | } elf_header_t; | 
 
 
 
 
 | 80 | //-------------------------------------------------------------- | 
 
 
 
 
 | 81 | typedef struct | 
 
 
 
 
 | 82 | { | 
 
 
 
 
 | 83 | u32     type; | 
 
 
 
 
 | 84 | u32     offset; | 
 
 
 
 
 | 85 | void    *vaddr; | 
 
 
 
 
 | 86 | u32     paddr; | 
 
 
 
 
 | 87 | u32     filesz; | 
 
 
 
 
 | 88 | u32     memsz; | 
 
 
 
 
 | 89 | u32     flags; | 
 
 
 
 
 | 90 | u32     align; | 
 
 
 
 
 | 91 | } elf_pheader_t; | 
 
 
 
 
 | 92 | //-------------------------------------------------------------- | 
 
 
 
 
 | 93 | t_ExecData elfdata; | 
 
 
 
 
 | 94 |  | 
 
 
 
 
 | 95 | int fileMode =  FIO_S_IRUSR | FIO_S_IWUSR | FIO_S_IXUSR | FIO_S_IRGRP | FIO_S_IWGRP | FIO_S_IXGRP | FIO_S_IROTH | FIO_S_IWOTH | FIO_S_IXOTH; | 
 
 
 
 
 | 96 | char HDDpath[256]; | 
 
 
 
 
 | 97 | char partition[128]; | 
 
 
 
 
 | 98 |  | 
 
 
 
 
 | 99 | static int pkoLoadElf(char *path); | 
 
 
 
 
 | 100 |  | 
 
 
 
 
 | 101 | int userThreadID = 0; | 
 
 
 
 
 | 102 | ////static char userThreadStack[16*1024] __attribute__((aligned(16))); | 
 
 
 
 
 | 103 |  | 
 
 
 
 
 | 104 | #define MAX_ARGS 16 | 
 
 
 
 
 | 105 | #define MAX_ARGLEN 256 | 
 
 
 
 
 | 106 |  | 
 
 
 
 
 | 107 | struct argData | 
 
 
 
 
 | 108 | { | 
 
 
 
 
 | 109 | int flag;                     // Contains thread id atm | 
 
 
 
 
 | 110 | int argc; | 
 
 
 
 
 | 111 | char *argv[MAX_ARGS]; | 
 
 
 
 
 | 112 | } __attribute__((packed)) userArgs; | 
 
 
 
 
 | 113 | //-------------------------------------------------------------- | 
 
 
 
 
 | 114 | //End of data declarations | 
 
 
 
 
 | 115 | //-------------------------------------------------------------- | 
 
 
 
 
 | 116 | //Start of function code: | 
 
 
 
 
 | 117 | //-------------------------------------------------------------- | 
 
 
 
 
 | 118 | // Read ELF from hard drive to required location(s) in memory. | 
 
 
 
 
 | 119 | // Modified version of loader from Independence | 
 
 
 
 
 | 120 | //      (C) 2003 Marcus R. Brown <mrbrown@0xd6.org> | 
 
 
 
 
 | 121 | //-------------------------------------------------------------- | 
 
 
 
 
 | 122 | static int tLoadElf(char *filename) | 
 
 
 
 
 | 123 | { | 
 
 
 
 
 | 124 | u8 *boot_elf = (u8 *)0x1800000; | 
 
 
 
 
 | 125 | elf_header_t *eh = (elf_header_t *)boot_elf; | 
 
 
 
 
 | 126 | elf_pheader_t *eph; | 
 
 
 
 
 | 127 |  | 
 
 
 
 
 | 128 | int fd, size, i; | 
 
 
 
 
 | 129 |  | 
 
 
 
 
 | 130 | //NB: Coming here means pfs0: was mounted correctly earlier | 
 
 
 
 
 | 131 | if ((fd = fileXioOpen(filename, O_RDONLY, fileMode)) < 0) | 
 
 
 
 
 | 132 | { | 
 
 
 
 
 | 133 | dbgprintf("Failed in fileXioOpen %s\n",filename); | 
 
 
 
 
 | 134 | goto error; | 
 
 
 
 
 | 135 | } | 
 
 
 
 
 | 136 | dbgprintf("Opened file %s\n",filename); | 
 
 
 
 
 | 137 | size = fileXioLseek(fd, 0, SEEK_END); | 
 
 
 
 
 | 138 | dbgprintf("File size = %i\n",size); | 
 
 
 
 
 | 139 | if (!size) | 
 
 
 
 
 | 140 | { | 
 
 
 
 
 | 141 | dbgprintf("Failed in fileXioLseek\n"); | 
 
 
 
 
 | 142 | fileXioClose(fd); | 
 
 
 
 
 | 143 | goto error; | 
 
 
 
 
 | 144 | } | 
 
 
 
 
 | 145 | fileXioLseek(fd, 0, SEEK_SET); | 
 
 
 
 
 | 146 | fileXioRead(fd, boot_elf, sizeof(elf_header_t)); | 
 
 
 
 
 | 147 | dbgprintf("Read elf header from file\n"); | 
 
 
 
 
 | 148 | fileXioLseek(fd, eh->phoff, SEEK_SET); | 
 
 
 
 
 | 149 | eph = (elf_pheader_t *)(boot_elf + eh->phoff); | 
 
 
 
 
 | 150 | size=eh->phnum*eh->phentsize; | 
 
 
 
 
 | 151 | size=fileXioRead(fd, (void *)eph, size); | 
 
 
 
 
 | 152 | dbgprintf("Read %i bytes of program header(s) from file\n",size); | 
 
 
 
 
 | 153 | for (i = 0; i < eh->phnum; i++) | 
 
 
 
 
 | 154 | { | 
 
 
 
 
 | 155 | if (eph[i].type != ELF_PT_LOAD) | 
 
 
 
 
 | 156 | continue; | 
 
 
 
 
 | 157 |  | 
 
 
 
 
 | 158 | fileXioLseek(fd, eph[i].offset, SEEK_SET); | 
 
 
 
 
 | 159 | size=eph[i].filesz; | 
 
 
 
 
 | 160 | size=fileXioRead(fd, eph[i].vaddr, size); | 
 
 
 
 
 | 161 | dbgprintf("Read %i bytes to %x\n", size, eph[i].vaddr); | 
 
 
 
 
 | 162 | if (eph[i].memsz > eph[i].filesz) | 
 
 
 
 
 | 163 | memset(eph[i].vaddr + eph[i].filesz, 0, | 
 
 
 
 
 | 164 | eph[i].memsz - eph[i].filesz); | 
 
 
 
 
 | 165 | } | 
 
 
 
 
 | 166 |  | 
 
 
 
 
 | 167 | fileXioClose(fd); | 
 
 
 
 
 | 168 | //      fileXioUmount("pfs0:");         We leave the filesystem mounted now for fakehost | 
 
 
 
 
 | 169 |  | 
 
 
 
 
 | 170 | if (_lw((u32)&eh->ident) != ELF_MAGIC)          // this should have already been | 
 
 
 
 
 | 171 | {                                         // done by menu, but a double-check | 
 
 
 
 
 | 172 | dbgprintf("Not a recognised ELF.\n");   // doesn't do any harm | 
 
 
 
 
 | 173 | goto error; | 
 
 
 
 
 | 174 | } | 
 
 
 
 
 | 175 |  | 
 
 
 
 
 | 176 | dbgprintf("entry=%x\n",eh->entry); | 
 
 
 
 
 | 177 | elfdata.epc=eh->entry; | 
 
 
 
 
 | 178 | return 0; | 
 
 
 
 
 | 179 | error: | 
 
 
 
 
 | 180 | elfdata.epc=0; | 
 
 
 
 
 | 181 | return -1; | 
 
 
 
 
 | 182 | } | 
 
 
 
 
 | 183 | //-------------------------------------------------------------- | 
 
 
 
 
 | 184 | //End of func:  int tLoadElf(char *filename) | 
 
 
 
 
 | 185 | //-------------------------------------------------------------- | 
 
 
 
 
 | 186 | // Load the actual elf, and create a thread for it | 
 
 
 
 
 | 187 | // Return the thread id | 
 
 
 
 
 | 188 | // PS2Link (C) 2003 Tord Lindstrom (pukko@home.se) | 
 
 
 
 
 | 189 | //         (C) 2003 adresd (adresd_ps2dev@yahoo.com) | 
 
 
 
 
 | 190 | //-------------------------------------------------------------- | 
 
 
 
 
 | 191 | static int pkoLoadElf(char *path) | 
 
 
 
 
 | 192 | { | 
 
 
 
 
 | 193 | ee_thread_t th_attr; | 
 
 
 
 
 | 194 | int ret=0; | 
 
 
 
 
 | 195 | int pid; | 
 
 
 
 
 | 196 |  | 
 
 
 
 
 | 197 | if(!strncmp(path, "host", 4)) ret = SifLoadElf(path, &elfdata); | 
 
 
 
 
 | 198 | else if(!strncmp(path, "mc", 2)) ret = SifLoadElf(path, &elfdata); | 
 
 
 
 
 | 199 | else if(!strncmp(path, "cdrom", 5)) ret = SifLoadElf(path, &elfdata); | 
 
 
 
 
 | 200 | else if(!strncmp(path, "cdfs", 4)) ret = SifLoadElf(path, &elfdata); | 
 
 
 
 
 | 201 | else if(!strncmp(path, "pfs0", 4)) ret = tLoadElf(path); | 
 
 
 
 
 | 202 | else if(!strncmp(path, "vmc", 3)) ret = tLoadElf(path); | 
 
 
 
 
 | 203 | else ret = SifLoadElf(path, &elfdata); | 
 
 
 
 
 | 204 |  | 
 
 
 
 
 | 205 | FlushCache(0); | 
 
 
 
 
 | 206 | FlushCache(2); | 
 
 
 
 
 | 207 |  | 
 
 
 
 
 | 208 | dbgprintf("EE: LoadElf returned %d\n", ret); | 
 
 
 
 
 | 209 |  | 
 
 
 
 
 | 210 | dbgprintf("EE: Creating user thread (ent: %x, gp: %x, st: %x)\n", | 
 
 
 
 
 | 211 | elfdata.epc, elfdata.gp, elfdata.sp); | 
 
 
 
 
 | 212 |  | 
 
 
 
 
 | 213 | if (elfdata.epc == 0) { | 
 
 
 
 
 | 214 | dbgprintf("EE: Could not load file\n"); | 
 
 
 
 
 | 215 | return -1; | 
 
 
 
 
 | 216 | } | 
 
 
 
 
 | 217 |  | 
 
 
 
 
 | 218 | th_attr.func = (void *)elfdata.epc; | 
 
 
 
 
 | 219 | ////    th_attr.stack = userThreadStack; | 
 
 
 
 
 | 220 | ////    th_attr.stack_size = sizeof(userThreadStack); | 
 
 
 
 
 | 221 | th_attr.gp_reg = (void *)elfdata.gp; | 
 
 
 
 
 | 222 | th_attr.initial_priority = 64; | 
 
 
 
 
 | 223 |  | 
 
 
 
 
 | 224 | pid = 1; ////CreateThread(&th_attr); | 
 
 
 
 
 | 225 | if (pid < 0) { | 
 
 
 
 
 | 226 | dbgprintf("EE: Create user thread failed %d\n", pid); | 
 
 
 
 
 | 227 | return -1; | 
 
 
 
 
 | 228 | } | 
 
 
 
 
 | 229 | dbgprintf("EE: Created user thread: %d\n", pid); | 
 
 
 
 
 | 230 |  | 
 
 
 
 
 | 231 | return pid; | 
 
 
 
 
 | 232 | } | 
 
 
 
 
 | 233 | //-------------------------------------------------------------- | 
 
 
 
 
 | 234 | //End of func:  static int pkoLoadElf(char *path) | 
 
 
 
 
 | 235 | //-------------------------------------------------------------- | 
 
 
 
 
 | 236 | // Clear user memory | 
 
 
 
 
 | 237 | // PS2Link (C) 2003 Tord Lindstrom (pukko@home.se) | 
 
 
 
 
 | 238 | //         (C) 2003 adresd (adresd_ps2dev@yahoo.com) | 
 
 
 
 
 | 239 | //-------------------------------------------------------------- | 
 
 
 
 
 | 240 | void wipeUserMem(void) | 
 
 
 
 
 | 241 | { | 
 
 
 
 
 | 242 | int i; | 
 
 
 
 
 | 243 | for (i = 0x100000; i < 0x2000000 ; i += 64) { | 
 
 
 
 
 | 244 | asm ( | 
 
 
 
 
 | 245 | "\tsq $0, 0(%0) \n" | 
 
 
 
 
 | 246 | "\tsq $0, 16(%0) \n" | 
 
 
 
 
 | 247 | "\tsq $0, 32(%0) \n" | 
 
 
 
 
 | 248 | "\tsq $0, 48(%0) \n" | 
 
 
 
 
 | 249 | :: "r" (i) ); | 
 
 
 
 
 | 250 | } | 
 
 
 
 
 | 251 | } | 
 
 
 
 
 | 252 | //-------------------------------------------------------------- | 
 
 
 
 
 | 253 | //End of func:  void wipeUserMem(void) | 
 
 
 
 
 | 254 | //-------------------------------------------------------------- | 
 
 
 
 
 | 255 | // C standard strrchr func.. returns pointer to the last occurance of a | 
 
 
 
 
 | 256 | // character in a string, or NULL if not found | 
 
 
 
 
 | 257 | // PS2Link (C) 2003 Tord Lindstrom (pukko@home.se) | 
 
 
 
 
 | 258 | //         (C) 2003 adresd (adresd_ps2dev@yahoo.com) | 
 
 
 
 
 | 259 | //-------------------------------------------------------------- | 
 
 
 
 
 | 260 | char *strrchr(const char *sp, int i) | 
 
 
 
 
 | 261 | { | 
 
 
 
 
 | 262 | const char *last = NULL; | 
 
 
 
 
 | 263 | char c = i; | 
 
 
 
 
 | 264 |  | 
 
 
 
 
 | 265 | while (*sp) | 
 
 
 
 
 | 266 | { | 
 
 
 
 
 | 267 | if (*sp == c) | 
 
 
 
 
 | 268 | { | 
 
 
 
 
 | 269 | last = sp; | 
 
 
 
 
 | 270 | } | 
 
 
 
 
 | 271 | sp++; | 
 
 
 
 
 | 272 | } | 
 
 
 
 
 | 273 |  | 
 
 
 
 
 | 274 | if (*sp == c) | 
 
 
 
 
 | 275 | { | 
 
 
 
 
 | 276 | last = sp; | 
 
 
 
 
 | 277 | } | 
 
 
 
 
 | 278 |  | 
 
 
 
 
 | 279 | return (char *) last; | 
 
 
 
 
 | 280 | } | 
 
 
 
 
 | 281 | //-------------------------------------------------------------- | 
 
 
 
 
 | 282 | //End of func:  char *strrchr(const char *sp, int i) | 
 
 
 
 
 | 283 | //-------------------------------------------------------------- | 
 
 
 
 
 | 284 | // *** MAIN *** | 
 
 
 
 
 | 285 | //-------------------------------------------------------------- | 
 
 
 
 
 | 286 | int main(int argc, char *argv[]) | 
 
 
 
 
 | 287 | { | 
 
 
 
 
 | 288 | char s[256],fakepart[128], *ptr; | 
 
 
 
 
 | 289 | int pid=-1; | 
 
 
 
 
 | 290 |  | 
 
 
 
 
 | 291 | // Initialize | 
 
 
 
 
 | 292 | SifInitRpc(0); | 
 
 
 
 
 | 293 | dbginit_scr(); | 
 
 
 
 
 | 294 | wipeUserMem(); | 
 
 
 
 
 | 295 | dbgprintf("Welcome to Loader of LaunchELF v3.50\nPlease wait...loading.\n"); | 
 
 
 
 
 | 296 |  | 
 
 
 
 
 | 297 | strcpy(s,argv[0]); | 
 
 
 
 
 | 298 | dbgprintf("argv[0] = %s\n",s); | 
 
 
 
 
 | 299 | /*if (argc==1) // Iritscen: Commented this out and changed "(argc==2)" to "(argc>=2)" below in order to allow add'l args | 
 
 
 
 
 | 300 | {                                               // should be two params passed by menu | 
 
 
 
 
 | 301 | while(1);                               // leave this here for adding mc0, host or other | 
 
 
 
 
 | 302 | // to be added in future | 
 
 
 
 
 | 303 | }*/ | 
 
 
 
 
 | 304 | if (argc>=2)                            // if call came from hddmenu.elf | 
 
 
 
 
 | 305 | {                                               // arg1=path to ELF, arg2=partition to mount | 
 
 
 
 
 | 306 | strcpy(partition,argv[1]); | 
 
 
 
 
 | 307 | dbgprintf("argv[1] = %s\n", partition); | 
 
 
 
 
 | 308 | strcpy(HDDpath,s); | 
 
 
 
 
 | 309 | } | 
 
 
 
 
 | 310 | dbgprintf("Loading %s\n",HDDpath); | 
 
 
 
 
 | 311 | pid = pkoLoadElf(HDDpath); | 
 
 
 
 
 | 312 | dbgprintf("pkoLoadElf returned %i\n",pid); | 
 
 
 
 
 | 313 | ////    if (pid < 0) | 
 
 
 
 
 | 314 | ////    { | 
 
 
 
 
 | 315 | ////            dbgprintf("failed\n"); | 
 
 
 
 
 | 316 | ////            dbgprintf("Could not execute file %s\n", HDDpath); | 
 
 
 
 
 | 317 | ////            return -1; | 
 
 
 
 
 | 318 | ////    } | 
 
 
 
 
 | 319 | if(!strncmp(HDDpath, "pfs0", 4)) | 
 
 
 
 
 | 320 | { | 
 
 
 
 
 | 321 | strcpy(fakepart,HDDpath); | 
 
 
 
 
 | 322 | ptr=strrchr(fakepart,'/'); | 
 
 
 
 
 | 323 | if(ptr==NULL) strcpy(fakepart,"pfs0:"); | 
 
 
 
 
 | 324 | else | 
 
 
 
 
 | 325 | { | 
 
 
 
 
 | 326 | ptr++; | 
 
 
 
 
 | 327 | *ptr='\0'; | 
 
 
 
 
 | 328 | } | 
 
 
 
 
 | 329 | ptr=strrchr(s,'/'); | 
 
 
 
 
 | 330 | if(ptr==NULL) ptr=strrchr(s,':'); | 
 
 
 
 
 | 331 | if(ptr!=NULL) | 
 
 
 
 
 | 332 | { | 
 
 
 
 
 | 333 | ptr++; | 
 
 
 
 
 | 334 | strcpy(HDDpath,"host:"); | 
 
 
 
 
 | 335 | strcat(HDDpath,ptr); | 
 
 
 
 
 | 336 | } | 
 
 
 
 
 | 337 | } | 
 
 
 
 
 | 338 |  | 
 
 
 
 
 | 339 | ////    FlushCache(0); | 
 
 
 
 
 | 340 | ////    FlushCache(2); | 
 
 
 
 
 | 341 |  | 
 
 
 
 
 | 342 | userThreadID = pid; | 
 
 
 
 
 | 343 |  | 
 
 
 
 
 | 344 | // Iritscen: Copy extra arguments in argv[] to userArgs | 
 
 
 
 
 | 345 | if (argc > 2) | 
 
 
 
 
 | 346 | { | 
 
 
 
 
 | 347 | printf("uLaunchELF loader: Received %d launch argument(s) for the game:\n", argc - 2); | 
 
 
 
 
 | 348 | userArgs.argc = argc - 1; | 
 
 
 
 
 | 349 | userArgs.argv[0] = HDDpath; | 
 
 
 
 
 | 350 | int a; | 
 
 
 
 
 | 351 | for (a = 0; a < argc - 2; a++) | 
 
 
 
 
 | 352 | { | 
 
 
 
 
 | 353 | userArgs.argv[a + 1] = argv[a + 2]; | 
 
 
 
 
 | 354 | printf("   %s\n", argv[a + 2]); | 
 
 
 
 
 | 355 | } | 
 
 
 
 
 | 356 | } | 
 
 
 
 
 | 357 | userArgs.flag = (int)&userThreadID; | 
 
 
 
 
 | 358 |  | 
 
 
 
 
 | 359 | ////    ret = StartThread(userThreadID, &userArgs); | 
 
 
 
 
 | 360 | ////    if (ret < 0) | 
 
 
 
 
 | 361 | ////    { | 
 
 
 
 
 | 362 | ////            dbgprintf("failed\n"); | 
 
 
 
 
 | 363 | ////            dbgprintf("EE: Start user thread failed %d\n", ret); | 
 
 
 
 
 | 364 | ////            DeleteThread(userThreadID); | 
 
 
 
 
 | 365 | ////            return -1; | 
 
 
 
 
 | 366 | ////    } | 
 
 
 
 
 | 367 | ////    SleepThread(); | 
 
 
 
 
 | 368 |  | 
 
 
 
 
 | 369 | __asm__ __volatile__( | 
 
 
 
 
 | 370 | ".set  noreorder\n\t" | 
 
 
 
 
 | 371 | "jal     FlushCache\n\t" | 
 
 
 
 
 | 372 | "li      $a0, 0\n\t" | 
 
 
 
 
 | 373 | "jal     FlushCache\n\t" | 
 
 
 
 
 | 374 | "li      $a0, 2\n\t" | 
 
 
 
 
 | 375 | "lui     $sp, 0x000a\n\t" | 
 
 
 
 
 | 376 | "nop\n\t" | 
 
 
 
 
 | 377 | "addiu   $sp, $sp, 0x8000\n\t" | 
 
 
 
 
 | 378 | "nop\n\t" | 
 
 
 
 
 | 379 | ".set  reorder\n\t" | 
 
 
 
 
 | 380 | ); | 
 
 
 
 
 | 381 | ExecPS2((void *)elfdata.epc, (void *)elfdata.gp, userArgs.argc, userArgs.argv); | 
 
 
 
 
 | 382 | return 0; | 
 
 
 
 
 | 383 | } | 
 
 
 
 
 | 384 | //-------------------------------------------------------------- | 
 
 
 
 
 | 385 | //End of func:  int main(int argc, char *argv[]) | 
 
 
 
 
 | 386 | //-------------------------------------------------------------- | 
 
 
 
 
 | 387 | //End of file:  loader.c | 
 
 
 
 
 | 388 | //-------------------------------------------------------------- |