Example #1
0
void main()
{
    clear_screens();

    if(mount_sd() != 0) {
        draw_loading("Failed to mount SD", "Make sure your SD card can be read correctly");
        return;
    }

    // This function already correctly draws error messages
    if (load_firm() != 0) return;

    if (load_cakes_info("/cakes/patches") != 0) {
        draw_loading("Failed to read some cakes", "Make sure your cakes are up to date\n  and your SD card can be read correctly");
        return;
    }

    load_config();

    // If the L button isn't pressed, autoboot.
    if (config->autoboot_enabled && *hid_regs ^ 0xFFF ^ key_l) {
        boot_cfw();
    }

    menu_main();
}
Example #2
0
int menu_firms()
{
    char firms[MAX_OPTIONS][_MAX_LFN + 1], dirpath[] = PATH_FIRMWARE_DIR;

    int pathlen = strlen(dirpath);
    int count = find_file_pattern(firms, dirpath, pathlen, MAX_OPTIONS, "firmware*.bin");

    if (!count) {
        draw_loading("Failed to load FIRM", "Make sure the encrypted FIRM is\n  located in the firmware directory");
        return 1;
    }

    char *options[count];
    for (int x = 0; x <= count; x++) options[x] = firms[x];

    int result = draw_menu("Select firmware", 0, count, options);
    if (result == -1) return 0;

    memcpy(config->firm_path, firms[result], _MAX_LFN + 1);

    reload_native_firm();
    load_cakes_info(PATH_PATCHES);

    return 0;
}
Example #3
0
void main()
{
    clear_screens();

    if(mount_sd() != 0) {
        draw_loading("Failed to mount SD", "Make sure your SD card can be read correctly");
        return;
    }

    load_config();

    // If the L button isn't pressed, autoboot.
    if (config->autoboot_enabled && *hid_regs ^ 0xFFF ^ key_l) {
        print("Autobooting...");

        if (read_file(firm_loc, PATH_PATCHED_FIRMWARE, FCRAM_SPACING) != 0 ||
                firm_loc->magic != FIRM_MAGIC) {
            print("Failed to load patched FIRM");
            draw_message("Failed to load patched FIRM", "The option to autoboot was selected,\n  but no valid FIRM could be found at:\n  " PATH_PATCHED_FIRMWARE);
        } else {
            if (read_file(memory_loc, PATH_MEMORY, FCRAM_SPACING) != 0) {
                print("Failed to load memory patches");
                draw_message("Failed to load memory patches", "The option to autoboot was selected,\n  but no valid memory patches could be found at:\n  " PATH_MEMORY);
            } else {
                if (config->firm_console == console_n3ds && config->firm_ver > 0x0F) {
                    slot0x11key96_init();
                }

                // boot_firm() requires current_firm->console and current_firm->version.
                struct firm_signature config_firm = {.console = config->firm_console,
                                                     .version = config->firm_ver};
                current_firm = &config_firm;

                boot_firm();
            }
        }
    }

    if (load_firms() != 0) {
        if(menu_firms() !=0) return;
    }

    print("Loading cakes");
    if (load_cakes_info(PATH_PATCHES) != 0) {
        draw_loading("Failed to read some cakes", "Make sure your cakes are up to date\n  and your SD card can be read correctly");
        return;
    }

    load_config_cakes();

    menu_main();
}
Example #4
0
int load_cakes_info(const char *dirpath)
{
    FRESULT fr;
    DIR dir;
    FILINFO fno;
    FIL handle;

    const int pathlen = strlen(dirpath);

    static char lfn[_MAX_LFN + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof(lfn);

    fr = f_opendir(&dir, dirpath);
    if (fr != FR_OK) goto error;

    static_assert(MAX_CAKES < 0x100000 / sizeof(struct cake_info),
                  "This function will overflow it's buffer");

    while (cake_count < MAX_CAKES) {
        fr = f_readdir(&dir, &fno);
        if (fr != FR_OK) {
            goto error;
        } else if (fno.fname[0] == 0) {
            break;
        }

        char *fn = *fno.lfname ? fno.lfname : fno.fname;

        // Build the path string
        memcpy(cake_list[cake_count].path, dirpath, pathlen);
        cake_list[cake_count].path[pathlen] = '/';
        strncpy(&cake_list[cake_count].path[pathlen + 1], fn, sizeof(cake_list->path) - pathlen - 1);

        // Recurse into subdirectories
        if (fno.fattrib & AM_DIR) {
            // Using the path stored in the current cake.
            fr = load_cakes_info(cake_list[cake_count].path);
            if (fr != FR_OK) return fr;
            continue;
        }

        // Make sure the filename ends in .cake
        if (!memsearch(cake_list[cake_count].path, ".cake",
                sizeof(cake_list[cake_count].path), 6)) {
            continue;
        }

        // Open the file
        fr = f_open(&handle, cake_list[cake_count].path, FA_READ);
        if (fr != FR_OK) goto error;

        // Get the header
        unsigned int bytes_read = 0;
        struct cake_header header;
        fr = f_read(&handle, &header, sizeof(header), &bytes_read);
        if (fr != FR_OK) goto error;

        // Only add patches applicable to the loaded firms
        struct firm_signature *current = NULL;
        switch (header.type) {
            case NATIVE_FIRM:
                current = current_firm;
                break;
            case AGB_FIRM:
                current = current_agb_firm;
                break;
            default:
                continue;
        }
        if (!current ||
                header.firm_ver != current->version ||
                header.console != current->console) {
            continue;
        }

        // Get the patch description
        const int desc_size = header.patches_offset - sizeof(header);
        fr = f_read(&handle, cake_list[cake_count].description, desc_size, &bytes_read);
        if (fr != FR_OK) goto error;

        fr = f_close(&handle);
        if (fr != FR_OK) goto error;

        cake_count++;
    }
    f_closedir(&dir);

    return 0;

error:
    f_close(&handle);
    f_closedir(&dir);
    return fr;
}