void ProcessGameQueue() { // Create the tickets folder if we're in ticket mode char empty_titleVersion[2] = {0x00, 0x00}; std::vector<game_item>::iterator game = game_queue.begin(); while(aptMainLoop() && game != game_queue.end()) { std::string selected_titleid = (*game).titleid; std::string selected_enckey = (*game).titlekey; std::string selected_name = (*game).name; std::string selected_region = (*game).region; if (config.GetMode() == CConfig::Mode::INSTALL_TICKET) { CreateTicket(selected_titleid, selected_enckey, empty_titleVersion, "/CIAngel/tmp/ticket"); InstallTicket("/CIAngel/tmp/ticket", selected_titleid); } else { Result res = DownloadTitle(selected_titleid, selected_enckey, selected_name, selected_region); if (R_FAILED(res)) { printf("Error processing queue. Returning to menu\n"); break; } } game = game_queue.erase(game); } wait_key_specific("Press A to continue.\n", KEY_A); }
TER transact_CreateTicket ( SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine) { return CreateTicket (txn, params, engine).apply (); }
// Search menu keypress callback bool menu_search_keypress(int selected, u32 key, void* data) { std::vector<game_item>* cb_data = (std::vector<game_item>*)data; // If key is 0, it means aptMainLoop() returned false, so we're exiting // Go back to the previous menu which will handle quitting if (!key) { return true; } // B goes back a screen if (key & KEY_B) { return true; } // A triggers the default action on the selected title if (key & KEY_A) { // Clean up the console since we'll be using it consoleClear(); // Fetch the title data and start downloading std::string selected_titleid = (*cb_data)[selected].titleid; std::string selected_enckey = (*cb_data)[selected].titlekey; std::string selected_name = (*cb_data)[selected].name; std::string selected_region = (*cb_data)[selected].region; printf("OK - %s\n", selected_name.c_str()); //removes any problem chars, not sure if whitespace is a problem too...? removeForbiddenChar(&selected_name); if(config.GetMode() == CConfig::Mode::INSTALL_TICKET) { char empty_titleVersion[2] = {0x00, 0x00}; CreateTicket(selected_titleid, selected_enckey, empty_titleVersion, "/CIAngel/tmp/ticket"); InstallTicket("/CIAngel/tmp/ticket", selected_titleid); } else { DownloadTitle(selected_titleid, selected_enckey, selected_name, selected_region); } wait_key_specific("\nPress A to continue.\n", KEY_A); return true; } // X triggers adding items to the download queue if (key & KEY_X) { consoleClear(); std::string titleid = (*cb_data)[selected].titleid; if (std::find_if(game_queue.begin(), game_queue.end(), find_game_item(titleid)) == game_queue.end()) { game_queue.push_back((*cb_data)[selected]); printf("Game added to queue.\n"); } else { printf("Game already in queue.\n"); } printf("Queue size: %d\n", game_queue.size()); wait_key_specific("\nPress A to continue.\n", KEY_A); return true; } return false; }
Result DownloadTitle(std::string titleId, std::string encTitleKey, std::string titleName, std::string region) { // Convert the titleid to a u64 for later use char* nTitleId = parse_string(titleId); u64 uTitleId = u8_to_u64((u8*)nTitleId, BIG_ENDIAN); free (nTitleId); // Wait for wifi to be available u32 wifi = 0; Result ret = 0; Result res = 0; while(R_SUCCEEDED(ret = ACU_GetWifiStatus(&wifi)) && wifi == 0) { hidScanInput(); if (hidKeysDown() & KEY_B) { ret = -1; break; } } if (R_FAILED(ret)) { printf("Unable to access internet.\n"); return ret; } std::string outputDir = "/CIAngel"; if (titleName.length() == 0) { titleName = titleId; } // Include region in filename if (region.length() > 0) { titleName = titleName + " (" + region + ")"; } std::string mode_text; if(config.GetMode() == CConfig::Mode::DOWNLOAD_CIA) { mode_text = "create"; } else if(config.GetMode() == CConfig::Mode::INSTALL_CIA) { mode_text = "install"; } printf("Starting - %s\n", titleName.c_str()); // If in install mode, download/install the SEED entry if (config.GetMode() == CConfig::Mode::INSTALL_CIA) { // Download and install the SEEDDB entry if install mode // Code based on code from FBI: https://github.com/Steveice10/FBI/blob/master/source/core/util.c#L254 // Copyright (C) 2015 Steveice10 u8 seed[16]; static const char* regionStrings[] = {"JP", "US", "GB", "GB", "HK", "KR", "TW"}; u8 region = CFG_REGION_USA; CFGU_GetSystemLanguage(®ion); if(region <= CFG_REGION_TWN) { char url[128]; snprintf(url, 128, SEED_URL "0x%016llX/ext_key?country=%s", uTitleId, regionStrings[region]); httpcContext context; if(R_SUCCEEDED(res = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 1))) { httpcSetSSLOpt(&context, SSLCOPT_DisableVerify); u32 responseCode = 0; if(R_SUCCEEDED(res = httpcBeginRequest(&context)) && R_SUCCEEDED(res = httpcGetResponseStatusCode(&context, &responseCode, 0))) { if(responseCode == 200) { u32 pos = 0; u32 bytesRead = 0; while(pos < sizeof(seed) && (R_SUCCEEDED(res = httpcDownloadData(&context, &seed[pos], sizeof(seed) - pos, &bytesRead)) || (u32)res == HTTPC_RESULTCODE_DOWNLOADPENDING)) { pos += bytesRead; } } else { res = -1; } } httpcCloseContext(&context); } if (R_SUCCEEDED(res)) { res = InstallSeed(uTitleId, seed); if (R_FAILED(res)) { printf("Error installing SEEDDB entry: 0x%lx\n", res); } } } } // Make sure the CIA doesn't already exist std::string cp = outputDir + "/" + titleName + ".cia"; if (config.GetMode() == CConfig::Mode::DOWNLOAD_CIA && FileExists(cp.c_str())) { printf("%s already exists.\n", cp.c_str()); return 0; } std::ofstream ofs; FILE *oh = fopen((outputDir + "/tmp/tmd").c_str(), "wb"); if (!oh) { printf("Error opening %s/tmp/tmd\n", outputDir.c_str()); return -1; } res = DownloadFile((NUS_URL + titleId + "/tmd").c_str(), oh, false); fclose(oh); if (res != 0) { printf("Could not download TMD. Internet/Title ID is OK?\n"); return res; } // Read version std::ifstream tmdfs; tmdfs.open(outputDir + "/tmp/tmd", std::ofstream::out | std::ofstream::in | std::ofstream::binary); char titleVersion[2]; tmdfs.seekg(top+0x9C, std::ios::beg); tmdfs.read(titleVersion, 0x2); tmdfs.close(); CreateTicket(titleId, encTitleKey, titleVersion, outputDir + "/tmp/ticket"); printf("Now %s the CIA...\n", mode_text.c_str()); res = ProcessCIA(outputDir + "/tmp", titleName); if (res != 0) { printf("Could not %s the CIA.\n", mode_text.c_str()); return res; } if (config.GetMode() == CConfig::Mode::DOWNLOAD_CIA) { rename((outputDir + "/tmp/" + titleName + ".cia").c_str(), (outputDir + "/" + titleName + ".cia").c_str()); } printf(" DONE!\n"); return res; }