Пример #1
0
void action_toggle_install()
{
    consoleClear();
    CConfig::Mode nextMode = CConfig::Mode::INSTALL_CIA;

    switch (config.GetMode())
    {
        case CConfig::Mode::DOWNLOAD_CIA:
            nextMode = CConfig::Mode::INSTALL_CIA;
        break;
        case CConfig::Mode::INSTALL_CIA:
            nextMode = CConfig::Mode::INSTALL_TICKET;
        break;
        case CConfig::Mode::INSTALL_TICKET:
            nextMode = CConfig::Mode::DOWNLOAD_CIA;
        break;
    }
    
    if (nextMode == CConfig::Mode::INSTALL_TICKET || nextMode == CConfig::Mode::INSTALL_CIA)
    {
        if (!bSvcHaxAvailable)
        {
            nextMode = CConfig::Mode::DOWNLOAD_CIA;
            printf(CONSOLE_RED "Kernel access not available.\nCan't enable Install modes.\nYou can only make a CIA.\n" CONSOLE_RESET);
            wait_key_specific("\nPress A to continue.", KEY_A);
        }
    }

    config.SetMode(nextMode);
}
Пример #2
0
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);
}
Пример #3
0
Result ProcessCIA(std::string dir, std::string titleName)
{
    FILE *tik = fopen((dir + "/ticket").c_str(), "rb");
    if (!tik) 
    {
        return -1;
    }
    TIK_CONTEXT tik_context = process_tik(tik);

    FILE *tmd = fopen((dir + "/tmd").c_str(),"rb");
    if (!tmd) 
    {
        fclose(tik);
        return -1;
    }
    TMD_CONTEXT tmd_context = process_tmd(tmd);

    if(tik_context.result != 0 || tmd_context.result != 0){
        printf("[!] Input files could not be processed successfully\n");
        free(tmd_context.content_struct);
        fclose(tik);
        fclose(tmd);
        return -1;
    }

    int result;
    if (config.GetMode() == CConfig::Mode::INSTALL_CIA)
    {
        result = install_cia(tmd_context, tik_context);
    }
    else
    {
        FILE *output = fopen((dir + "/" + titleName + ".cia").c_str(),"wb");
        if (!output) 
        {
            result = -2;
        }
        else
        {
            result = generate_cia(tmd_context, tik_context, output);
            if(result != 0)
            {
                remove((dir + "/" + titleName + ".cia").c_str());
            }
        }
    }

    // free allocated memory/handles
    free(tmd_context.content_struct);
    fclose(tik);
    fclose(tmd);

    // Clean up temp files
    remove((dir + "/ticket").c_str());
    remove((dir + "/tmd").c_str());
    return result;
}
Пример #4
0
void action_prompt_queue()
{
    consoleClear();

    std::string mode_text;
    switch (config.GetMode())
    {
        case CConfig::Mode::DOWNLOAD_CIA:
            mode_text = "download";
        break;
        case CConfig::Mode::INSTALL_CIA:
            mode_text = "install";
        break;
        case CConfig::Mode::INSTALL_TICKET:
            mode_text = "create tickets for";
        break;
    }

    printf("Queue contains %d items.\n", game_queue.size());
    printf("Press A to %s queue.\n", mode_text.c_str());
    printf("Press B to return to menu.\n");
    printf("Press X to clear queue.\n");

    while (aptMainLoop())
    {
        u32 key = wait_key();
        if (key & KEY_B)
        {
            break;
        }

        if (key & KEY_X)
        {
            game_queue.clear();
            break;
        }

        if (key & KEY_A)
        {
            ProcessGameQueue();
            break;
        }
    }

}
Пример #5
0
// Draw the main menu
void menu_main()
{
    const char *options[] = {
        "Search for a title by name",
        "Search for a title by serial",
        "Process download queue",
        "Enter a title key/ID pair",
        "Fetch title key/ID from input.txt",
        "Download wings.json",
        "About CIAngel",
        "Exit",
    };
    char footer[50];

    while (!bExit && aptMainLoop())
    {
        std::string mode_text;
        switch (config.GetMode())
        {
            case CConfig::Mode::DOWNLOAD_CIA:
                mode_text = "Create CIA";
            break;
            case CConfig::Mode::INSTALL_CIA:
                mode_text = "Install CIA";
            break;
            case CConfig::Mode::INSTALL_TICKET:
                mode_text = "Create Ticket";
            break;
        }

        // We have to update the footer every draw, incase the user switches install mode or region
        sprintf(footer, "Mode (L):%s Region (R):%s Queue: %d", mode_text.c_str(), config.GetRegionFilter().c_str(), game_queue.size());

        menu_multkey_draw("CIAngel by cearp and Drakia", footer, 0, sizeof(options) / sizeof(char*), options, NULL, menu_main_keypress);

        clear_screen(GFX_BOTTOM);
    }
}
Пример #6
0
/* Menu Action Functions */
void action_search(bool (*match)(std::string &searchString, Json::Value &gameData, int &outScore))
{
    HB_Keyboard sHBKB;
    bool bKBCancelled = false;

    consoleClear();

    printf("Please enter text to search for:\n");
    std::string searchString = getInput(&sHBKB, bKBCancelled);
    if (bKBCancelled)
    {
        return;
    }

    // User has entered their input, so let's scrap the keyboard
    clear_screen(GFX_BOTTOM);

    std::vector<game_item> display_output;
    int outScore;
    
    for (unsigned int i = 0; i < sourceData.size(); i++) {
        // Check the region filter
        std::string regionFilter = config.GetRegionFilter();
        if(regionFilter != "off" && sourceData[i]["region"].asString() != regionFilter) {
            continue;
        }

        // Check that the encTitleKey isn't null
        if (sourceData[i]["encTitleKey"].isNull())
        {
            continue;
        }

        // Create an ASCII version of the name if one doesn't exist yet
        if (sourceData[i]["ascii_name"].isNull())
        {
            // Normalize the name down to ASCII
            utf8proc_option_t options = (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT | UTF8PROC_STRIPMARK | UTF8PROC_STRIPCC);
            utf8proc_uint8_t* szName;
            utf8proc_uint8_t *str = (utf8proc_uint8_t*)sourceData[i]["name"].asCString();
            utf8proc_map(str, 0, &szName, options);

            sourceData[i]["ascii_name"] = (const char*)szName;

            free(szName);
        }

        if (match(searchString, sourceData[i], outScore))
        {

            game_item item;
            item.score = outScore;
            item.index = i;

            switch(sourceDataType) {
            case JSON_TYPE_WINGS:
              item.titleid = sourceData[i]["titleid"].asString();
              item.titlekey = sourceData[i]["enckey"].asString();
              item.name = sourceData[i]["ascii_name"].asString();
              item.region = sourceData[i]["region"].asString();
              item.code = sourceData[i]["code"].asString();
              break;
            case JSON_TYPE_ONLINE:
              item.titleid = sourceData[i]["titleID"].asString();
              item.titlekey = sourceData[i]["encTitleKey"].asString();
              item.name = sourceData[i]["ascii_name"].asString();
              item.region = sourceData[i]["region"].asString();
              item.code = sourceData[i]["serial"].asString();
              break;
            }

            std::string typeCheck = item.titleid.substr(4,4);
            //if title id belongs to gameapp/dlc/update/dsiware, use it. if not, ignore. case sensitve of course
            if(typeCheck == "0000" || typeCheck == "008c" || typeCheck == "000e" || typeCheck == "8004"){
                display_output.push_back(item);
            }
        }
    }

    unsigned int display_amount = display_output.size();

    // We technically have 30 rows to work with, minus 2 for header/footer. But stick with 20 entries for now

    if (display_amount == 0)
    {
        printf("No matching titles found.\n");
        wait_key_specific("\nPress A to return.\n", KEY_A);
        return;
    }

    // sort similar names by fuzzy score
    if(display_amount>1) {
        std::sort(display_output.begin(), display_output.end(), compareByScore);
    }
    
    std::string mode_text;
    switch (config.GetMode())
    {
        case CConfig::Mode::DOWNLOAD_CIA:
            mode_text = "Create CIA";
        break;
        case CConfig::Mode::INSTALL_CIA:
            mode_text = "Install CIA";
        break;
        case CConfig::Mode::INSTALL_TICKET:
            mode_text = "Create Ticket";
        break;
    }

    char footer[51];
    char header[51];
    sprintf(header, "Select a Title (found %i results)", display_amount);
    sprintf(footer, "Press A to %s. Press X to queue.", mode_text.c_str());
    titles_multkey_draw(header, footer, 1, &display_output, &display_output, menu_search_keypress);
}
Пример #7
0
// 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;
}
Пример #8
0
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(&region);

        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;
}