smb improvements (rodries)
[libogc.git] / libogc / wiilaunch.c
blobf7a20684c9513c39b5f5b00376358e70583b8518
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 memset(&nandboot,0,sizeof(NANDBootInfo));
268 nandboot.apptype = 0x80;
269 if(titleID == 0x100000002LL)
270 nandboot.titletype = 4;
271 else
272 nandboot.titletype = 2;
273 if(ES_GetTitleID(&nandboot.launcher) < 0)
274 nandboot.launcher = 0x0000000100000002LL;
275 nandboot.checksum = __CalcChecksum((u32*)&nandboot,sizeof(NANDBootInfo));
276 __WII_WriteNANDBootInfo();
278 VIDEO_SetBlack(1);
279 VIDEO_Flush();
281 res = ES_LaunchTitle(titleID, &views[0]);
282 if(res < 0)
283 return res;
284 return WII_EINTERNAL;
287 s32 WII_LaunchTitleWithArgs(u64 titleID, int launchcode, ...)
289 char argv0[20];
290 const char *argv[256];
291 int argc = 1;
292 va_list args;
294 if(!__initialized)
295 return WII_ENOTINIT;
297 sprintf(argv0, "%016llx", titleID);
299 argv[0] = argv0;
301 va_start(args, launchcode);
303 do {
304 argv[argc++] = va_arg(args, const char *);
305 } while(argv[argc - 1] != NULL);
307 va_end(args);
309 if(ES_GetTitleID(&nandboot.launcher) < 0)
310 nandboot.launcher = 0x100000002LL;
312 if(titleID == 0x100000002LL)
313 nandboot.titletype = 4;
314 else
315 nandboot.titletype = 2;
316 nandboot.apptype = 0x80;
317 nandboot.launchcode = launchcode;
319 stateflags.type = TYPE_RETURN;
320 stateflags.returnto = RETURN_TO_ARGS;
322 __WII_SetArgs(argv);
324 __WII_WriteStateFlags();
325 __WII_WriteNANDBootInfo();
327 return WII_LaunchTitle(titleID);
330 s32 WII_ReturnToMenu(void)
332 if(!__initialized)
333 return WII_ENOTINIT;
334 stateflags.type = TYPE_RETURN;
335 stateflags.returnto = RETURN_TO_MENU;
336 __WII_WriteStateFlags();
337 return WII_LaunchTitle(0x100000002LL);
340 s32 WII_ReturnToSettings(void)
342 if(!__initialized)
343 return WII_ENOTINIT;
344 stateflags.type = TYPE_RETURN;
345 stateflags.returnto = RETURN_TO_SETTINGS;
346 __WII_WriteStateFlags();
347 return WII_LaunchTitle(0x100000002LL);
350 s32 WII_ReturnToSettingsPage(const char *page)
352 if(!__initialized)
353 return WII_ENOTINIT;
355 return WII_LaunchTitleWithArgs(0x100000002LL, 1, page, NULL);
358 s32 WII_OpenURL(const char *url)
360 u32 tmdsize;
361 u64 tid = 0;
362 u64 *list;
363 u32 titlecount;
364 s32 ret;
365 u32 i;
367 if(!__initialized)
368 return WII_ENOTINIT;
370 ret = ES_GetNumTitles(&titlecount);
371 if(ret < 0)
372 return WII_EINTERNAL;
374 list = memalign(32, titlecount * sizeof(u64) + 32);
376 ret = ES_GetTitles(list, titlecount);
377 if(ret < 0) {
378 free(list);
379 return WII_EINTERNAL;
382 for(i=0; i<titlecount; i++) {
383 if((list[i] & ~0xFF) == 0x1000148414400LL) {
384 tid = list[i];
385 break;
388 free(list);
390 if(!tid)
391 return WII_EINSTALL;
393 if(ES_GetStoredTMDSize(tid, &tmdsize) < 0)
394 return WII_EINSTALL;
396 return WII_LaunchTitleWithArgs(tid, 0, url, NULL);
399 #endif