#include #include #include #include "defines.h" #include "booter/external_booter.hpp" #include "channel/nand.hpp" #include "channel/nand_save.hpp" #include "devicemounter/DeviceHandler.hpp" #include "gecko/gecko.hpp" #include "gui/video.hpp" #include "gui/text.hpp" #include "homebrew/homebrew.h" #include "loader/alt_ios_gen.h" #include "loader/wdvd.h" #include "loader/alt_ios.h" #include "loader/sys.h" #include "loader/wbfs.h" #include "loader/cios.h" #include "loader/nk.h" #include "menu/menu.hpp" #include "memory/memory.h" bool isWiiVC = false; bool useMainIOS = true; volatile bool NANDemuView = false; volatile bool networkInit = false; /* quick check if we will be using a USB device. */ /* if not then we can skip the 20 second cycle trying to connect a USB device. */ /* this is nice for SD only users */ bool isUsingUSB() { if(isWiiVC) return false; /* First check if the app path exists on the SD card, if not then we're using USB */ struct stat dummy; string appPath = fmt("%s:/%s", DeviceName[SD], APPS_DIR); if(DeviceHandle.IsInserted(SD) && DeviceHandle.GetFSType(SD) != PART_FS_WBFS && stat(appPath.c_str(), &dummy) != 0) { // No app path exists on SD card, so assuming we're using USB. return true; } /* Check that the config file exists, or we can't do the following checks */ string configPath = fmt("%s/" CFG_FILENAME, appPath.c_str()); if(stat(configPath.c_str(), &dummy) != 0) { // The app path is on SD but no config file exists, so assuming we might need USB. return true; } /* Load the config file */ Config m_cfg;// = new Config(); if(!m_cfg.load(configPath.c_str())) { // The app path is on SD and a config file exists, but we can't load it, so assuming we might need USB. return true; } /* If any of the sections have partition set > 0, we're on USB */ const char *domains[] = {WII_DOMAIN, GC_DOMAIN, CHANNEL_DOMAIN, PLUGIN_DOMAIN, HOMEBREW_DOMAIN}; for(int i = 0; i < 5; i++) { if(!m_cfg.getBool(domains[i], "disable", false) && m_cfg.getInt(domains[i], "partition", SD) != SD) { // a domain is enabled and partition is not SD, so assuming we're using USB. return true; } } /* if sd_only is false, then we're using USB */ if(!m_cfg.getBool("general", "sd_only", true)) { // sd_only is false, so assuming we're using USB. return true; } gprintf("using SD only, no need for USB mounting.\n"); return false; } int main(int argc, char **argv) { MEM_init(); //Inits both mem1lo and mem2 mainIOS = DOL_MAIN_IOS;// 249 __exception_setreload(10); Gecko_Init(); //USB Gecko and SD/WiFi buffer #ifdef COMMITHASH gprintf(" \nWelcome to %s %s %s!\nThis is the debug output.\n", APP_NAME, APP_VERSION, COMMITHASH); #else gprintf(" \nWelcome to %s %s!\nThis is the debug output.\n", APP_NAME, APP_VERSION); #endif char *gameid = NULL; bool showFlashImg = true; bool wait_loop = false; char wait_dir[256]; memset(&wait_dir, 0, sizeof(wait_dir)); for(u8 i = 0; i < argc; i++) { if(argv[i] != NULL && strcasestr(argv[i], "ios=") != NULL && strlen(argv[i]) > 4) { while(argv[i][0] && !isdigit(argv[i][0])) argv[i]++; if(atoi(argv[i]) < 254 && atoi(argv[i]) > 0) mainIOS = atoi(argv[i]); } else if(strcasestr(argv[i], "waitdir=") != NULL) { char *ptr = strcasestr(argv[i], "waitdir="); strncpy(wait_dir, ptr+strlen("waitdir="), sizeof(wait_dir) - 1); } else if(strcasestr(argv[i], "Waitloop") != NULL) wait_loop = true; else if(strcasestr(argv[i], "noflash") != NULL) showFlashImg = false; else if(strlen(argv[i]) == 6) { gameid = argv[i]; for(u8 i = 0; i < 5; i++) { if(!isalnum(gameid[i])) gameid = NULL; } } } /* Init video */ m_vid.init(); if(showFlashImg) m_vid.startImage(); /* check if WiiVC */ WiiDRC_Init(); isWiiVC = WiiDRC_Inited(); if(IsOnWiiU()) { gprintf("WiiU\n"); if(isWiiVC) gprintf("WiiVC\n"); else gprintf("vWii Mode\n"); } else gprintf("Real Wii\n"); gprintf("AHBPROT disabled = %s\n", AHBPROT_Patched() ? "yes" : "no"); IOS_GetCurrentIOSInfo(); /* Init device partition handlers */ DeviceHandle.Init(); /* Init NAND handlers */ NandHandle.Init(); if(isWiiVC) { NandHandle.Init_ISFS(); IOS_GetCurrentIOSInfo(); DeviceHandle.SetModes(); } else { NandHandle.Init_ISFS(); /* load and check wiiflow save for possible new IOS and Port settings */ if(InternalSave.CheckSave()) InternalSave.LoadSettings(); /* Handle (c)IOS Loading */ if(useMainIOS && CustomIOS(IOS_GetType(mainIOS)))// load cios { NandHandle.DeInit_ISFS(); NandHandle.Patch_AHB(); IOS_ReloadIOS(mainIOS); NandHandle.Init_ISFS(); gprintf("AHBPROT disabled after IOS Reload: %s\n", AHBPROT_Patched() ? "yes" : "no"); gprintf("Now using ");// gprintf finished in IOS_GetCurrentIOSInfo() } else gprintf("Using IOS58\n");// stay on IOS58. no reload to cIOS IOS_GetCurrentIOSInfo(); if(CurrentIOS.Type == IOS_TYPE_HERMES) load_ehc_module_ex(); else if(CurrentIOS.Type == IOS_TYPE_WANIN && CurrentIOS.Revision >= 18) load_dip_249(); DeviceHandle.SetModes(); WDVD_Init(); } /* mount SD */ DeviceHandle.MountSD();// mount SD before calling isUsingUSB() duh! /* mount USB if needed */ DeviceHandle.SetMountUSB(isUsingUSB()); bool usb_mounted = DeviceHandle.MountAllUSB();// only mounts any USB if isUsingUSB() /* init wait images and show wait animation */ m_vid.setCustomWaitImgs(wait_dir, wait_loop); m_vid.waitMessage(0.15f); /* init controllers for input */ Open_Inputs();// WPAD_SetVRes() is called later in mainMenu.init() during cursor init which gets the theme pointer images /* sys inits */ Sys_Init();// set reset and power button callbacks bool startup_successful = false; /* init configs, folders, coverflow, gui and more */ if(mainMenu.init(usb_mounted)) { startup_successful = true; if(!isWiiVC) writeStub();// copy return stub to memory if(!isWiiVC && gameid != NULL && strlen(gameid) == 6)// if argv game ID then launch it mainMenu.directlaunch(gameid); else mainMenu.main();// start wiiflow with main menu displayed } // at this point either wiiflow bootup failed or the user is exiting wiiflow ShutdownBeforeExit();// unmount devices and close inputs if(startup_successful)// use wiiflow's exit choice Sys_Exit(); return 0;// otherwise just exit to loader (system menu or hbc). }