84
84
*/
85
85
86
86
#ifndef IS_SALAMANDER
87
+ static enum frontend_fork wiiu_fork_mode = FRONTEND_FORK_NONE ;
87
88
static bool have_libfat_usb = false;
88
89
static bool have_libfat_sdcard = false;
89
90
#endif
91
+ static bool in_exec = false;
90
92
91
93
static bool exists (char * path )
92
94
{
@@ -226,18 +228,154 @@ static int frontend_wiiu_parse_drive_list(void *data, bool load_content)
226
228
return 0 ;
227
229
}
228
230
231
+ static void frontend_wiiu_exec (const char * path , bool should_load_content )
232
+ {
233
+ /* goal: make one big buffer with all the argv's, seperated by NUL. we can
234
+ * then pass this thru sysapp! */
235
+ char * argv_buf ;
236
+ size_t n , argv_len = strlen (path ) + 1 ; /* argv[0] plus null */
237
+
238
+ #ifndef IS_SALAMANDER
239
+ const char * content = path_get (RARCH_PATH_CONTENT );
240
+ const char * content_args [2 ] = {content , NULL };
241
+ #ifdef HAVE_NETWORKING
242
+ const char * netplay_args [NETPLAY_FORK_MAX_ARGS ];
243
+ #endif
244
+ #endif
245
+ /* args will select between content_args, netplay_args, or no args (default) */
246
+ const char * * args = NULL ;
247
+
248
+ /* and some other stuff (C89) */
249
+ MochaRPXLoadInfo load_info = {0 };
250
+ MochaUtilsStatus ret ;
251
+ SYSStandardArgsIn std_args = {0 };
252
+
253
+ #ifndef IS_SALAMANDER
254
+ if (should_load_content )
255
+ {
256
+ #ifdef HAVE_NETWORKING
257
+ if (netplay_driver_ctl (RARCH_NETPLAY_CTL_GET_FORK_ARGS ,
258
+ (void * ) netplay_args ))
259
+ {
260
+ const char * * cur_arg = netplay_args ;
261
+
262
+ do
263
+ argv_len += strnlen (* cur_arg , PATH_MAX_LENGTH ) + 1 ;
264
+ while (* (++ cur_arg ));
265
+
266
+ args = netplay_args ;
267
+ } else
268
+ #endif
269
+ if (!string_is_empty (content ))
270
+ {
271
+ argv_len += strnlen (content , PATH_MAX_LENGTH ) + 1 ;
272
+ args = content_args ;
273
+ }
274
+ }
275
+ #endif
276
+
277
+ argv_buf = malloc (argv_len );
278
+ argv_buf [0 ] = '\0' ;
279
+
280
+ n = strlcpy (argv_buf , path , argv_len );
281
+ n ++ ; /* leave room for the NUL */
282
+ if (args )
283
+ {
284
+ const char * * cur_arg = args ;
285
+ do
286
+ {
287
+ n += strlcpy (argv_buf + n , * cur_arg , argv_len - n );
288
+ n ++ ;
289
+ } while (* (++ cur_arg ));
290
+ }
291
+
292
+ if (string_starts_with (path , "fs:/vol/external01/" ))
293
+ path_relative_to (load_info .path , path , "fs:/vol/external01/" , sizeof (load_info .path ));
294
+ else if (string_starts_with (path , "sd:/" ))
295
+ path_relative_to (load_info .path , path , "sd:/" , sizeof (load_info .path ));
296
+ else goto cleanup ; /* bail if not on the SD card */
297
+
298
+ /* Mocha might not be init'd (Salamander) */
299
+ if (Mocha_InitLibrary () != MOCHA_RESULT_SUCCESS )
300
+ goto cleanup ;
301
+
302
+ load_info .target = LOAD_RPX_TARGET_SD_CARD ;
303
+ ret = Mocha_PrepareRPXLaunch (& load_info );
304
+ if (ret != MOCHA_RESULT_SUCCESS )
305
+ goto cleanup ;
306
+
307
+ std_args .argString = argv_buf ;
308
+ std_args .size = argv_len ;
309
+ ret = Mocha_LaunchHomebrewWrapperEx (& std_args );
310
+ if (ret != MOCHA_RESULT_SUCCESS )
311
+ {
312
+ MochaRPXLoadInfo load_info_revert ;
313
+ load_info_revert .target = LOAD_RPX_TARGET_EXTRA_REVERT_PREPARE ;
314
+ Mocha_PrepareRPXLaunch (& load_info_revert );
315
+ goto cleanup ;
316
+ }
317
+
318
+ in_exec = true;
319
+
320
+ cleanup :
321
+ free (argv_buf );
322
+ argv_buf = NULL ;
323
+ }
324
+
325
+ static void frontend_wiiu_exitspawn (char * s , size_t len , char * args )
326
+ {
327
+ bool should_load_content = false;
328
+ #ifndef IS_SALAMANDER
329
+ if (wiiu_fork_mode == FRONTEND_FORK_NONE )
330
+ return ;
331
+
332
+ switch (wiiu_fork_mode )
333
+ {
334
+ case FRONTEND_FORK_CORE_WITH_ARGS :
335
+ should_load_content = true;
336
+ break ;
337
+ default :
338
+ break ;
339
+ }
340
+ #endif
341
+ frontend_wiiu_exec (s , should_load_content );
342
+ }
343
+
344
+ #ifndef IS_SALAMANDER
345
+ static bool frontend_wiiu_set_fork (enum frontend_fork fork_mode )
346
+ {
347
+ switch (fork_mode )
348
+ {
349
+ case FRONTEND_FORK_CORE :
350
+ case FRONTEND_FORK_CORE_WITH_ARGS :
351
+ wiiu_fork_mode = fork_mode ;
352
+ break ;
353
+ case FRONTEND_FORK_RESTART :
354
+ /* NOTE: We don't implement Salamander, so just turn
355
+ * this into FRONTEND_FORK_CORE. */
356
+ wiiu_fork_mode = FRONTEND_FORK_CORE ;
357
+ break ;
358
+ case FRONTEND_FORK_NONE :
359
+ default :
360
+ return false;
361
+ }
362
+
363
+ return true;
364
+ }
365
+ #endif
366
+
229
367
frontend_ctx_driver_t frontend_ctx_wiiu =
230
368
{
231
369
frontend_wiiu_get_env_settings ,
232
370
frontend_wiiu_init ,
233
371
frontend_wiiu_deinit ,
234
- NULL , /* exitspawn */
372
+ frontend_wiiu_exitspawn ,
235
373
NULL , /* process_args */
236
- NULL , /* exec */
374
+ frontend_wiiu_exec ,
237
375
#ifdef IS_SALAMANDER
238
376
NULL , /* set_fork */
239
377
#else
240
- NULL , /* set_fork */
378
+ frontend_wiiu_set_fork ,
241
379
#endif
242
380
frontend_wiiu_shutdown ,
243
381
NULL , /* get_name */
@@ -272,6 +410,7 @@ frontend_ctx_driver_t frontend_ctx_wiiu =
272
410
/* main() and its supporting functions */
273
411
274
412
static void main_setup (void );
413
+ static void get_arguments (int * argc , char * * * argv );
275
414
#ifndef IS_SALAMANDER
276
415
static void main_loop (void );
277
416
#endif
@@ -291,6 +430,7 @@ int main(int argc, char **argv)
291
430
{
292
431
proc_setup ();
293
432
main_setup ();
433
+ get_arguments (& argc , & argv );
294
434
295
435
#ifdef IS_SALAMANDER
296
436
int salamander_main (int argc , char * * argv );
@@ -328,9 +468,31 @@ static void main_teardown(void)
328
468
memoryRelease ();
329
469
}
330
470
471
+ // https://github.com/devkitPro/wut/blob/7d9fa9e416bffbcd747f1a8e5701fd6342f9bc3d/libraries/libwhb/src/proc.c
472
+
473
+ #define HBL_TITLE_ID (0x0005000013374842)
474
+ #define MII_MAKER_JPN_TITLE_ID (0x000500101004A000)
475
+ #define MII_MAKER_USA_TITLE_ID (0x000500101004A100)
476
+ #define MII_MAKER_EUR_TITLE_ID (0x000500101004A200)
477
+
478
+ static bool in_hbl = false;
331
479
static bool in_aroma = false;
480
+
332
481
static void proc_setup (void )
333
482
{
483
+ uint64_t titleID = OSGetTitleID ();
484
+
485
+ // Homebrew Launcher does not like the standard ProcUI application loop, sad!
486
+ if (titleID == HBL_TITLE_ID ||
487
+ titleID == MII_MAKER_JPN_TITLE_ID ||
488
+ titleID == MII_MAKER_USA_TITLE_ID ||
489
+ titleID == MII_MAKER_EUR_TITLE_ID )
490
+ {
491
+ // Important: OSEnableHomeButtonMenu must come before ProcUIInitEx.
492
+ OSEnableHomeButtonMenu (FALSE);
493
+ in_hbl = TRUE;
494
+ }
495
+
334
496
/* Detect Aroma explicitly (it's possible to run under H&S while using Tiramisu) */
335
497
OSDynLoad_Module rpxModule ;
336
498
if (OSDynLoad_Acquire ("homebrew_rpx_loader" , & rpxModule ) == OS_DYNLOAD_OK )
@@ -344,6 +506,29 @@ static void proc_setup(void)
344
506
345
507
static void proc_exit (void )
346
508
{
509
+ /* If we're doing a normal exit while running under HBL, we must SYSRelaunchTitle.
510
+ * If we're in an exec (i.e. launching mocha homebrew wrapper) we must *not* do that. yay! */
511
+ if (in_hbl && !in_exec )
512
+ SYSRelaunchTitle (0 , NULL );
513
+
514
+ /* Similar deal for Aroma, but exit to menu. */
515
+ if (!in_hbl && !in_exec )
516
+ SYSLaunchMenu ();
517
+
518
+ /* Now just tell the OS that we really are ok to exit */
519
+ if (!ProcUIInShutdown ())
520
+ {
521
+ for (;;)
522
+ {
523
+ ProcUIStatus status ;
524
+ status = ProcUIProcessMessages (TRUE);
525
+ if (status == PROCUI_STATUS_EXITING )
526
+ break ;
527
+ else if (status == PROCUI_STATUS_RELEASE_FOREGROUND )
528
+ ProcUIDrawDoneRelease ();
529
+ }
530
+ }
531
+
347
532
ProcUIShutdown ();
348
533
}
349
534
@@ -352,6 +537,54 @@ static void proc_save_callback(void)
352
537
OSSavesDone_ReadyToRelease ();
353
538
}
354
539
540
+ static void sysapp_arg_cb (SYSDeserializeArg * arg , void * usr )
541
+ {
542
+ SYSStandardArgs * std_args = (SYSStandardArgs * ) usr ;
543
+
544
+ if (_SYSDeserializeStandardArg (arg , std_args ))
545
+ return ;
546
+
547
+ if (strcmp (arg -> argName , "sys:pack" ) == 0 )
548
+ {
549
+ // Recurse
550
+ SYSDeserializeSysArgsFromBlock (arg -> data , arg -> size , sysapp_arg_cb , usr );
551
+ return ;
552
+ }
553
+ }
554
+
555
+ static void get_arguments (int * argc , char * * * argv )
556
+ {
557
+ #ifdef HAVE_NETWORKING
558
+ static char * _argv [1 + NETPLAY_FORK_MAX_ARGS ];
559
+ #else
560
+ static char * _argv [2 ];
561
+ #endif
562
+ int _argc = 0 ;
563
+ SYSStandardArgs std_args = {0 };
564
+
565
+ /* we could do something more rich with the content path and things here -
566
+ * but since there's not a great way to actually pass that info along to RA,
567
+ * just emulate argc/argv */
568
+ SYSDeserializeSysArgs (sysapp_arg_cb , & std_args );
569
+
570
+ char * argv_buf = std_args .anchorData ;
571
+ size_t argv_len = std_args .anchorSize ;
572
+ if (!argv_buf || argv_len == 0 )
573
+ return ;
574
+
575
+ size_t n = 0 ;
576
+ while (n < argv_len && _argc < ARRAY_SIZE (_argv ))
577
+ {
578
+ char * s = argv_buf + n ;
579
+ _argv [_argc ++ ] = s ;
580
+ n += strlen (s );
581
+ n ++ ; /* skip the null */
582
+ }
583
+
584
+ * argc = _argc ;
585
+ * argv = _argv ;
586
+ }
587
+
355
588
#ifndef IS_SALAMANDER
356
589
static bool swap_is_pending (void * start_time )
357
590
{
0 commit comments