#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "backup.hpp" #include "easter_egg.hpp" #include "input.hpp" #include "main.hpp" #include "screens.hpp" #include "swap.hpp" #include "unlink.hpp" #include "utils.hpp" unsigned int USER_ID; // The current user persistant ID. bool INKAY_EXISTS; // Whether the Inkay plugin config exists. std::string NNID_BACKUP; // The backup path to the Nintendo Network ID account.dat. std::string PNID_BACKUP; // The backup path to the Pretendo Network ID account.dat. std::string MII_NICKNAME; // The current user's Mii nickname. std::string ACCOUNT_FILE; // The path to the current account.dat. std::string INKAY_CONFIG; // The path to the Inkay configuration file. SDL_Window* window = nullptr; // Global window variable. SDL_Renderer* renderer = nullptr; // Global renderer variable. int client_handle = 0; // The client handle for flushing the filesystem. void get_user_information() { // Grab the user's Mii name and persistent ID. nn::act::Initialize(); int16_t mii_name[256]; nn::act::GetMiiName(mii_name); MII_NICKNAME = std::string(mii_name, mii_name + sizeof(mii_name) / sizeof(mii_name[0])); USER_ID = nn::act::GetPersistentId(); // Set the account file path. char user_id_hex[9]; sprintf(user_id_hex, "%08x", USER_ID); ACCOUNT_FILE = "storage_mlc:/usr/save/system/act/" + std::string(user_id_hex) + "/account.dat"; // Set the backup file paths. NNID_BACKUP = "fs:/vol/external01/wiiu/accounts/" + std::string(user_id_hex) + "/nnid_account.dat"; PNID_BACKUP = "fs:/vol/external01/wiiu/accounts/" + std::string(user_id_hex) + "/pnid_account.dat"; // Set the Inkay configuration file path. char environment_path_buffer[0x100]; Mocha_GetEnvironmentPath(environment_path_buffer, sizeof(environment_path_buffer)); INKAY_CONFIG = std::string(environment_path_buffer) + std::string("/plugins/config/inkay.json"); // Check if the Inkay configuration file exists. INKAY_EXISTS = std::ifstream(INKAY_CONFIG).good(); } void deinitialize() { FSAFlushVolume(client_handle, "storage_mlc"); FSAFlushVolume(client_handle, ""); FSADelClient(client_handle); nn::act::Finalize(); Mocha_UnmountFS("storage_mlc"); Mocha_DeInitLibrary(); WHBLogConsoleFree(); VPADShutdown(); KPADShutdown(); AXQuit(); if (renderer != nullptr) SDL_DestroyRenderer(renderer); if (window != nullptr) SDL_DestroyWindow(window); close_fonts(); TTF_Quit(); SDL_Quit(); } bool initialize_program() { WHBProcInit(); VPADInit(); // Wii U GamePad support. KPADInit(); // External controller support. WPADEnableURCC(1); // Allow Pro Controller input. WHBLogConsoleInit(); // Initialize the log console. FSAInit(); // Allows for flushing the filesystem. AXInit(); // Disable playing audio. // Initialize the Mocha library. if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) { return false; } // Initialize the FSA handler to flush the filesystem. client_handle = FSAAddClient(NULL); if (client_handle == 0) { return false; } Mocha_MountFS("storage_mlc", NULL, "/vol/storage_mlc01"); get_user_information(); return true; } bool initialize_graphics() { SDL_Init(SDL_INIT_VIDEO); TTF_Init(); window = SDL_CreateWindow("Wii U Account Swap", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, \ SCREEN_WIDTH, SCREEN_HEIGHT, 0); if (!window) return false; renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (!renderer) return false; return true; } bool check_initialization(bool condition, const char* error_message) { if (!condition) { WHBLogConsoleSetColor(0x99000000); WHBLogPrint(error_message); WHBLogConsoleDraw(); OSSleepTicks(OSMillisecondsToTicks(5000)); SYSLaunchMenu(); return true; } return false; } int main() { bool error_occurred = false; error_occurred = check_initialization(initialize_program(), "Error initializing program!") || check_initialization(initialize_graphics(), "Error initializing graphics!"); int selected_option = 0; const int NUM_OPTIONS = 4; while (WHBProcIsRunning()) { if (!error_occurred) draw_menu_screen(selected_option); int button = read_input(); // Watch the controllers for input. OSEnableHomeButtonMenu(1); if (button & VPAD_BUTTON_UP) { selected_option--; if (selected_option < 0) selected_option = NUM_OPTIONS - 1; } else if (button & VPAD_BUTTON_DOWN) { selected_option++; if (selected_option >= NUM_OPTIONS) selected_option = 0; } else if (button & VPAD_BUTTON_A) { switch (selected_option) { case 0: if (swap_account(NNID_BACKUP.c_str(), "Nintendo")) { OSForceFullRelaunch(); SYSLaunchMenu(); } break; case 1: if (swap_account(PNID_BACKUP.c_str(), "Pretendo")) { OSForceFullRelaunch(); SYSLaunchMenu(); } break; case 2: while (WHBProcIsRunning()) { OSEnableHomeButtonMenu(0); draw_backup_menu(); button = read_input(); if (button & VPAD_BUTTON_A) { backup_account(); break; } else if (button & VPAD_BUTTON_B) break; } break; case 3: OSEnableHomeButtonMenu(0); while (WHBProcIsRunning()) { draw_unlink_menu(); button = read_input(); if (button & VPAD_BUTTON_A) { if (unlink_account()) { OSForceFullRelaunch(); SYSLaunchMenu(); } break; } else if (button & VPAD_BUTTON_B) break; } break; } } else if (button & VPAD_BUTTON_SYNC) { play_easter_egg(); } } deinitialize(); WHBProcShutdown(); return 0; }