remove const from TPL_OpenTPLFromMemory since the memory is altered
[libogc.git] / libogc / wiilaunch.c
blob5bda934c973e12af34ad991b9af8e056ed81bfb6
1 /*-------------------------------------------------------------
3 wiilaunch.c -- Wii NAND title launching and argument passing
5 Copyright (C) 2008
6 Hector Martin (marcan)
8 This software is provided 'as-is', without any express or implied
9 warranty. In no event will the authors be held liable for any
10 damages arising from the use of this software.
12 Permission is granted to anyone to use this software for any
13 purpose, including commercial applications, and to alter it and
14 redistribute it freely, subject to the following restrictions:
16 1. The origin of this software must not be misrepresented; you
17 must not claim that you wrote the original software. If you use
18 this software in a product, an acknowledgment in the product
19 documentation would be appreciated but is not required.
21 2. Altered source versions must be plainly marked as such, and
22 must not be misrepresented as being the original software.
24 3. This notice may not be removed or altered from any source
25 distribution.
27 -------------------------------------------------------------*/
29 #if defined(HW_RVL)
31 #include <string.h>
32 #include <malloc.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include "ipc.h"
37 #include "asm.h"
38 #include "processor.h"
39 #include "es.h"
40 #include "video.h"
41 #include "network.h"
42 #include "wiilaunch.h"
44 static char __nandbootinfo[] ATTRIBUTE_ALIGN(32) = "/shared2/sys/NANDBOOTINFO";
45 static char __stateflags[] ATTRIBUTE_ALIGN(32) = "/title/00000001/00000002/data/state.dat";
47 static int __initialized = 0;
49 typedef struct {
50 u32 checksum;
51 u32 argsoff;
52 u8 unk1;
53 u8 unk2;
54 u8 apptype;
55 u8 titletype;
56 u32 launchcode;
57 u32 unknown[2];
58 u64 launcher;
59 u8 argbuf[0x1000];
60 } NANDBootInfo;
62 typedef struct {
63 u32 checksum;
64 u8 flags;
65 u8 type;
66 u8 discstate;
67 u8 returnto;
68 u32 unknown[6];
69 } StateFlags;
71 #define TYPE_RETURN 3
72 #define TYPE_NANDBOOT 4
73 #define TYPE_SHUTDOWNSYSTEM 5
74 #define RETURN_TO_MENU 0
75 #define RETURN_TO_SETTINGS 1
76 #define RETURN_TO_ARGS 2
79 static NANDBootInfo nandboot ATTRIBUTE_ALIGN(32);
81 static StateFlags stateflags ATTRIBUTE_ALIGN(32);
83 static u32 __CalcChecksum(u32 *buf, int len)
85 u32 sum = 0;
86 int i;
87 len = (len/4);
89 for(i=1; i<len; i++)
90 sum += buf[i];
92 return sum;
95 static void __SetChecksum(void *buf, int len)
97 u32 *p = (u32*)buf;
98 p[0] = __CalcChecksum(p, len);
101 static int __ValidChecksum(void *buf, int len)
103 u32 *p = (u32*)buf;
104 return p[0] == __CalcChecksum(p, len);
107 static s32 __WII_ReadStateFlags(void)
109 int fd;
110 int ret;
112 fd = IOS_Open(__stateflags,IPC_OPEN_READ);
113 if(fd < 0) {
114 memset(&stateflags,0,sizeof(stateflags));
115 return WII_EINTERNAL;
118 ret = IOS_Read(fd, &stateflags, sizeof(stateflags));
119 IOS_Close(fd);
120 if(ret != sizeof(stateflags)) {
121 memset(&stateflags,0,sizeof(stateflags));
122 return WII_EINTERNAL;
124 if(!__ValidChecksum(&stateflags, sizeof(stateflags))) {
125 memset(&stateflags,0,sizeof(stateflags));
126 return WII_ECHECKSUM;
128 return 0;
131 static s32 __WII_ReadNANDBootInfo(void)
133 int fd;
134 int ret;
136 fd = IOS_Open(__nandbootinfo,IPC_OPEN_READ);
137 if(fd < 0) {
138 memset(&nandboot,0,sizeof(nandboot));
139 return WII_EINTERNAL;
142 ret = IOS_Read(fd, &nandboot, sizeof(nandboot));
143 IOS_Close(fd);
144 if(ret != sizeof(nandboot)) {
145 memset(&nandboot,0,sizeof(nandboot));
146 return WII_EINTERNAL;
148 if(!__ValidChecksum(&nandboot, sizeof(nandboot))) {
149 memset(&nandboot,0,sizeof(nandboot));
150 return WII_ECHECKSUM;
152 return 0;
155 static s32 __WII_WriteStateFlags(void)
157 int fd;
158 int ret;
160 __SetChecksum(&stateflags, sizeof(stateflags));
162 fd = IOS_Open(__stateflags,IPC_OPEN_READ|IPC_OPEN_WRITE);
163 if(fd < 0) {
164 return WII_EINTERNAL;
167 ret = IOS_Write(fd, &stateflags, sizeof(stateflags));
168 IOS_Close(fd);
169 if(ret != sizeof(stateflags)) {
170 return WII_EINTERNAL;
172 return 0;
175 static s32 __WII_WriteNANDBootInfo(void)
177 int fd;
178 int ret;
180 __SetChecksum(&nandboot, sizeof(nandboot));
182 fd = IOS_Open(__nandbootinfo,IPC_OPEN_READ|IPC_OPEN_WRITE);
183 if(fd < 0) {
184 return WII_EINTERNAL;
187 ret = IOS_Write(fd, &nandboot, sizeof(nandboot));
188 IOS_Close(fd);
189 if(ret != sizeof(nandboot)) {
190 return WII_EINTERNAL;
192 return 0;
195 s32 WII_Initialize(void)
197 __WII_ReadStateFlags();
198 __WII_ReadNANDBootInfo();
199 __initialized = 1;
200 return 0;
203 s32 __WII_SetArgs(const char **argv)
205 int argslen = 0;
206 int buflen = 0;
207 int argvp, argp;
208 int argc = 0;
209 int i;
211 if(!__initialized)
212 return WII_ENOTINIT;
214 for(i=0; argv[i] != NULL; i++) {
215 argslen += strlen(argv[i]) + 1;
216 argc++;
218 buflen = (argslen + 3) & ~3;
219 buflen += 4 * argc;
220 buflen += 8;
222 if(buflen > 0x1000)
223 return WII_E2BIG;
225 argp = 0x1000 - argslen;
226 argvp = 0x1000 - buflen;
228 memset(&nandboot.argbuf, 0, sizeof(nandboot.argbuf));
230 nandboot.argsoff = 0x1000 + argvp;
231 *((u32*)&nandboot.argbuf[argvp]) = argc;
232 argvp += 4;
234 for(i=0; i<argc; i++) {
235 strcpy((char*)&nandboot.argbuf[argp], argv[i]);
236 *((u32*)&nandboot.argbuf[argvp]) = argp + 0x1000;
237 argvp += 4;
238 argp += strlen(argv[i]) + 1;
240 *((u32*)&nandboot.argbuf[argvp]) = 0;
242 return 0;
245 s32 WII_LaunchTitle(u64 titleID)
247 s32 res;
248 u32 numviews;
249 STACK_ALIGN(tikview,views,4,32);
251 if(!__initialized)
252 return WII_ENOTINIT;
254 res = ES_GetNumTicketViews(titleID, &numviews);
255 if(res < 0) {
256 return res;
258 if(numviews > 4) {
259 return WII_EINTERNAL;
261 res = ES_GetTicketViews(titleID, views, numviews);
262 if(res < 0)
263 return res;
265 net_wc24cleanup();
267 VIDEO_SetBlack(1);
268 VIDEO_Flush();
270 res = ES_LaunchTitle(titleID, &views[0]);
271 if(res < 0)
272 return res;
273 return WII_EINTERNAL;
276 s32 WII_LaunchTitleWithArgs(u64 titleID, int launchcode, ...)
278 char argv0[20];
279 const char *argv[256];
280 int argc = 1;
281 va_list args;
283 if(!__initialized)
284 return WII_ENOTINIT;
286 sprintf(argv0, "%016llx", titleID);
288 argv[0] = argv0;
290 va_start(args, launchcode);
292 do {
293 argv[argc++] = va_arg(args, const char *);
294 } while(argv[argc - 1] != NULL);
296 va_end(args);
298 if(ES_GetTitleID(&nandboot.launcher) < 0)
299 nandboot.launcher = 0x100000002LL;
301 if(titleID == 0x100000002LL)
302 nandboot.titletype = 4;
303 else
304 nandboot.titletype = 2;
305 nandboot.apptype = 0x80;
306 nandboot.launchcode = launchcode;
308 stateflags.type = TYPE_RETURN;
309 stateflags.returnto = RETURN_TO_ARGS;
311 __WII_SetArgs(argv);
313 __WII_WriteStateFlags();
314 __WII_WriteNANDBootInfo();
316 return WII_LaunchTitle(titleID);
319 s32 WII_ReturnToMenu(void)
321 if(!__initialized)
322 return WII_ENOTINIT;
323 stateflags.type = TYPE_RETURN;
324 stateflags.returnto = RETURN_TO_MENU;
325 __WII_WriteStateFlags();
326 return WII_LaunchTitle(0x100000002LL);
329 s32 WII_ReturnToSettings(void)
331 if(!__initialized)
332 return WII_ENOTINIT;
333 stateflags.type = TYPE_RETURN;
334 stateflags.returnto = RETURN_TO_SETTINGS;
335 __WII_WriteStateFlags();
336 return WII_LaunchTitle(0x100000002LL);
339 s32 WII_ReturnToSettingsPage(const char *page)
341 if(!__initialized)
342 return WII_ENOTINIT;
344 return WII_LaunchTitleWithArgs(0x100000002LL, 1, page, NULL);
347 s32 WII_OpenURL(const char *url)
349 u32 tmdsize;
350 u64 tid = 0;
351 u64 *list;
352 u32 titlecount;
353 s32 ret;
354 u32 i;
356 if(!__initialized)
357 return WII_ENOTINIT;
359 ret = ES_GetNumTitles(&titlecount);
360 if(ret < 0)
361 return WII_EINTERNAL;
363 list = memalign(32, titlecount * sizeof(u64) + 32);
365 ret = ES_GetTitles(list, titlecount);
366 if(ret < 0) {
367 free(list);
368 return WII_EINTERNAL;
371 for(i=0; i<titlecount; i++) {
372 if((list[i] & ~0xFF) == 0x1000148414400LL) {
373 tid = list[i];
374 break;
377 free(list);
379 if(!tid)
380 return WII_EINSTALL;
382 if(ES_GetStoredTMDSize(tid, &tmdsize) < 0)
383 return WII_EINSTALL;
385 return WII_LaunchTitleWithArgs(tid, 0, url, NULL);
388 #endif