Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Horizon nand-dumper Switch: Difference between revisions

From GameBrew
(Created page with "{{Infobox Switch Homebrews |title=Horizon nand-dumper |image=horizonnanddumperswitch.png |description=Open source horizon nand-dumper. |author=asdfaaasssdddfff |lastupdated=2018/09/15 |type=PC Utilities |version=2018 |license=Mixed |download=https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch.7z |website=https://gbatemp.net/threads/open-source-horizon-nand-dumper.518095/ |source= |donation= }} {{#seo: |title=Switch Homebrew PC Tools (PC Utilities) - GameBr...")
 
No edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
{{Infobox Switch Homebrews
{{Infobox Switch Homebrews
|title=Horizon nand-dumper
|title=Horizon nand-dumper
|image=horizonnanddumperswitch.png
|image=switch-logo.png
|description=Open source horizon nand-dumper.
|description=Open source horizon nand-dumper.
|author=asdfaaasssdddfff
|author=asdfaaasssdddfff
|lastupdated=2018/09/15
|lastupdated=2018/09/15
|type=PC Utilities
|type=PC Utilities
|version=2018
|version=2018
|license=Mixed
|license=MIT
|download=https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch.7z
|download=https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumpernx.7z Source Only
|website=https://gbatemp.net/threads/open-source-horizon-nand-dumper.518095/
|website=https://gbatemp.net/threads/open-source-horizon-nand-dumper.518095/
|source=
|source=
|donation=
|donation=
}}
}}
{{#seo:
An open source tool which dumps the nand from horizon, similar to what [[ReiNX_Toolkit_Switch|reinx-toolbox]] does.
|title=Switch Homebrew PC Tools (PC Utilities) - GameBrew
 
|title_mode=append
It's mostly a direct port of this [https://github.com/reswitched/pegaswitch/blob/master/usefulscripts/DumpBIS.js pegaswitch-script].
|image=horizonnanddumperswitch.png
 
|image_alt=Horizon nand-dumper
It will dump boot0+1, prodinfo and the rawnand to the root of the sdcard, automatically splitting the file if on a fat32-sdcard (source below).
}}
 
{{cleanup|article|Needs cleanup}}
'''Warning:''' This may or may not result in a corrupted backup, the author takes no responsibility whatsoever for bricks. If you want a proper backup use hekate which has proper backup-verification.
Open source horizon nand-dumper.
 
<pre>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <switch.h>
 
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
 
/*
This is basically a port of this pegaswitch-script:
https://github.com/reswitched/pegaswitch/blob/master/usefulscripts/DumpBIS.js
*/
 
int partitionIds[] = {0, 10, 27, 20};
char *partitionNames[] = {"BOOT0", "BOOT1", "PRODINFO", "rawnand"};
 
#define BufSize 0x500000
 
long GetAvailableSpace(const char *path)
{
    struct statvfs stat;
 
    if (statvfs(path, &stat) != 0)
    {
        // error happens, just quits here
        return -1;
    }
 
    // the available size is f_bsize * f_bavail
    return stat.f_bsize * stat.f_bavail;
}
 
int dumpPartition(int partitionIndex)
{
    printf("\n%s\n", partitionNames[partitionIndex]);
    int id = partitionIds[partitionIndex];
 
    char *buffer = malloc(BufSize);
 
    FsStorage partition;
    fsOpenBisStorage(&partition, id);
    u64 size = 0;
    fsStorageGetSize(&partition, &size);
 
    if (GetAvailableSpace("/") < size)
    {
        consoleClear();
        fsStorageClose(&partition);
        printf("Not enough space left on the sd!\n");
        while (appletMainLoop())
        {
 
            hidScanInput();
            u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
 
            if (kDown & KEY_PLUS)
                break;
 
            gfxFlushBuffers();
            gfxSwapBuffers();
        }
        return -1;
    }
 
    int file_num = 0;
 
    char filename[100];
    sprintf(filename, "/%s.bin", partitionNames[partitionIndex]);
 
    FILE *partitionfile = fopen(filename, "wb");
 
    u64 curPos = 0;
 
    bool isFat32 = false;
 
    // dump loop
    while (appletMainLoop())
    {
        u64 readSize = MIN(size - curPos, BufSize);
        if (readSize == 0)
            break;
 
        fsStorageRead(&partition, curPos, buffer, readSize);
 
        u64 sucessfullyWriten = fwrite(buffer, 1, readSize, partitionfile);
 
        curPos += sucessfullyWriten;
 
        if (sucessfullyWriten < readSize)
        {
            fclose(partitionfile);
            // Filesystem doesn't support big files
            if(!isFat32) {
                char oldFilename[100];
                strcpy(oldFilename, filename);
                sprintf(filename, "/%s_%d.bin", partitionNames[partitionIndex], file_num++);
                rename(oldFilename, filename);
                isFat32 = true;
            }
            sprintf(filename, "/%s_%d.bin", partitionNames[partitionIndex], file_num++);
            partitionfile = fopen(filename, "wb");
        }
 
 
        printf("\r%lu/%lu", curPos, size);
 
        gfxFlushBuffers();
        gfxSwapBuffers();
    }
    fclose(partitionfile);
    fsStorageClose(&partition);
    free(buffer);
 
    return 0;
}
 
int main(int argc, char **argv)
{
    gfxInitDefault();
    consoleInit(NULL);
 
    printf("ATTENTION, DO NOT USE THIS AS YOUR PRIMARY BACKUP!\n");
    printf("I'm serious: I'll not be responsible for any bricks because of this!\n");
    printf("Press + if you want to continue\n");
 
    while (appletMainLoop())
    {
        hidScanInput();
        u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
 
        if (kDown & KEY_PLUS)
            break;
 
        gfxFlushBuffers();
        gfxSwapBuffers();
    }
   
    consoleClear();
 
    for (int i = 0; i < (sizeof(partitionIds) / sizeof(int)); i++)
    {
        if(dumpPartition(i) != 0)
            return 0;
    }


    printf("\nDump complete!\nPress + to exit");


==Media==
    while (appletMainLoop())
<youtube></youtube>
    {
        hidScanInput();
        u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);


        if (kDown & KEY_PLUS)
            break;


==Screenshots==
        gfxFlushBuffers();
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-01.png
        gfxSwapBuffers();
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-02.png
    }
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-03.png
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-04.png
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-05.png
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-06.png
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-07.png
https://dlhb.gamebrew.org/switchhomebrews/horizonnanddumperswitch-08.png


==Changelog==
    gfxExit();
'''v.1.0'''
    return 0;
* First Release.
}
</pre>


== External links ==
== External links ==
* Gbatemp - https://gbatemp.net/threads/open-source-horizon-nand-dumper.518095/
* GBAtemp - https://gbatemp.net/threads/open-source-horizon-nand-dumper.518095/
* Github -
* Reddit -

Latest revision as of 01:55, 7 Haziran 2023

Horizon nand-dumper
Switch-logo.png
General
Authorasdfaaasssdddfff
TypePC Utilities
Version2018
LicenseMIT License
Last Updated2018/09/15
Links
Source Only Download
Website

An open source tool which dumps the nand from horizon, similar to what reinx-toolbox does.

It's mostly a direct port of this pegaswitch-script.

It will dump boot0+1, prodinfo and the rawnand to the root of the sdcard, automatically splitting the file if on a fat32-sdcard (source below).

Warning: This may or may not result in a corrupted backup, the author takes no responsibility whatsoever for bricks. If you want a proper backup use hekate which has proper backup-verification.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <switch.h>

#define MIN(x, y) (((x) < (y)) ? (x) : (y))

/*
This is basically a port of this pegaswitch-script:
https://github.com/reswitched/pegaswitch/blob/master/usefulscripts/DumpBIS.js
*/

int partitionIds[] = {0, 10, 27, 20};
char *partitionNames[] = {"BOOT0", "BOOT1", "PRODINFO", "rawnand"};

#define BufSize 0x500000

long GetAvailableSpace(const char *path)
{
    struct statvfs stat;

    if (statvfs(path, &stat) != 0)
    {
        // error happens, just quits here
        return -1;
    }

    // the available size is f_bsize * f_bavail
    return stat.f_bsize * stat.f_bavail;
}

int dumpPartition(int partitionIndex)
{
    printf("\n%s\n", partitionNames[partitionIndex]);
    int id = partitionIds[partitionIndex];

    char *buffer = malloc(BufSize);

    FsStorage partition;
    fsOpenBisStorage(&partition, id);
    u64 size = 0;
    fsStorageGetSize(&partition, &size);

    if (GetAvailableSpace("/") < size)
    {
        consoleClear();
        fsStorageClose(&partition);
        printf("Not enough space left on the sd!\n");
        while (appletMainLoop())
        {

            hidScanInput();
            u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);

            if (kDown & KEY_PLUS)
                break;

            gfxFlushBuffers();
            gfxSwapBuffers();
        }
        return -1;
    }

    int file_num = 0;

    char filename[100];
    sprintf(filename, "/%s.bin", partitionNames[partitionIndex]);

    FILE *partitionfile = fopen(filename, "wb");

    u64 curPos = 0;

    bool isFat32 = false;

    // dump loop
    while (appletMainLoop())
    {
        u64 readSize = MIN(size - curPos, BufSize);
        if (readSize == 0)
            break;

        fsStorageRead(&partition, curPos, buffer, readSize);

        u64 sucessfullyWriten = fwrite(buffer, 1, readSize, partitionfile);

        curPos += sucessfullyWriten;

        if (sucessfullyWriten < readSize)
        {
            fclose(partitionfile);
            // Filesystem doesn't support big files
            if(!isFat32) {
                char oldFilename[100];
                strcpy(oldFilename, filename);
                sprintf(filename, "/%s_%d.bin", partitionNames[partitionIndex], file_num++);
                rename(oldFilename, filename);
                isFat32 = true;
            }
            sprintf(filename, "/%s_%d.bin", partitionNames[partitionIndex], file_num++);
            partitionfile = fopen(filename, "wb");
        }


        printf("\r%lu/%lu", curPos, size);

        gfxFlushBuffers();
        gfxSwapBuffers();
    }
    fclose(partitionfile);
    fsStorageClose(&partition);
    free(buffer);

    return 0;
}

int main(int argc, char **argv)
{
    gfxInitDefault();
    consoleInit(NULL);

    printf("ATTENTION, DO NOT USE THIS AS YOUR PRIMARY BACKUP!\n");
    printf("I'm serious: I'll not be responsible for any bricks because of this!\n");
    printf("Press + if you want to continue\n");

    while (appletMainLoop())
    {
        hidScanInput();
        u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);

        if (kDown & KEY_PLUS)
            break;

        gfxFlushBuffers();
        gfxSwapBuffers();
    }
    
    consoleClear();

    for (int i = 0; i < (sizeof(partitionIds) / sizeof(int)); i++)
    {
        if(dumpPartition(i) != 0)
            return 0;
    }

    printf("\nDump complete!\nPress + to exit");

    while (appletMainLoop())
    {
        hidScanInput();
        u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);

        if (kDown & KEY_PLUS)
            break;

        gfxFlushBuffers();
        gfxSwapBuffers();
    }

    gfxExit();
    return 0;
}

External links

Advertising: