mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-06 03:58:02 +08:00
159 lines
4.5 KiB
C
159 lines
4.5 KiB
C
#include <malloc.h>
|
|
#include <stdio.h>
|
|
|
|
#include <3ds.h>
|
|
|
|
#include "../error.h"
|
|
#include "../progressbar.h"
|
|
#include "../prompt.h"
|
|
#include "../../screen.h"
|
|
|
|
typedef struct {
|
|
Handle in;
|
|
Handle out;
|
|
u64 offset;
|
|
u64 size;
|
|
|
|
u8 buffer[1024 * 1024];
|
|
} dump_nand_data;
|
|
|
|
static void dumpnand_done_onresponse(ui_view* view, void* data, bool response) {
|
|
prompt_destroy(view);
|
|
}
|
|
|
|
static void dumpnand_update(ui_view* view, void* data, float* progress, char* progressText) {
|
|
dump_nand_data* dumpData = (dump_nand_data*) data;
|
|
|
|
if(hidKeysDown() & KEY_B) {
|
|
if(dumpData->in != 0) {
|
|
FSFILE_Close(dumpData->in);
|
|
dumpData->in = 0;
|
|
}
|
|
|
|
if(dumpData->out != 0) {
|
|
FSFILE_Close(dumpData->out);
|
|
dumpData->out = 0;
|
|
}
|
|
|
|
progressbar_destroy(view);
|
|
ui_pop();
|
|
|
|
ui_push(prompt_create("Failure", "Dump cancelled.", COLOR_TEXT, false, data, NULL, NULL, dumpnand_done_onresponse));
|
|
|
|
free(data);
|
|
|
|
return;
|
|
}
|
|
|
|
Result res = 0;
|
|
|
|
u32 bytesRead = 0;
|
|
u32 bytesWritten = 0;
|
|
if(R_SUCCEEDED(res = FSFILE_Read(dumpData->in, &bytesRead, dumpData->offset, dumpData->buffer, sizeof(dumpData->buffer))) && R_SUCCEEDED(res = FSFILE_Write(dumpData->out, &bytesWritten, dumpData->offset, dumpData->buffer, bytesRead, 0)) && bytesRead == bytesWritten) {
|
|
dumpData->offset += bytesRead;
|
|
}
|
|
|
|
if(R_FAILED(res)) {
|
|
if(dumpData->in != 0) {
|
|
FSFILE_Close(dumpData->in);
|
|
dumpData->in = 0;
|
|
}
|
|
|
|
if(dumpData->out != 0) {
|
|
FSFILE_Close(dumpData->out);
|
|
dumpData->out = 0;
|
|
}
|
|
|
|
progressbar_destroy(view);
|
|
ui_pop();
|
|
|
|
error_display_res(NULL, NULL, res, "Failed to dump NAND.");
|
|
|
|
free(data);
|
|
} else if(bytesRead != bytesWritten) {
|
|
if(dumpData->in != 0) {
|
|
FSFILE_Close(dumpData->in);
|
|
dumpData->in = 0;
|
|
}
|
|
|
|
if(dumpData->out != 0) {
|
|
FSFILE_Close(dumpData->out);
|
|
dumpData->out = 0;
|
|
}
|
|
|
|
progressbar_destroy(view);
|
|
ui_pop();
|
|
|
|
error_display(NULL, NULL, "Failed to dump NAND: Read/Write size mismatch.");
|
|
|
|
free(data);
|
|
} else if(dumpData->offset >= dumpData->size) {
|
|
if(dumpData->in != 0) {
|
|
FSFILE_Close(dumpData->in);
|
|
dumpData->in = 0;
|
|
}
|
|
|
|
if(dumpData->out != 0) {
|
|
FSFILE_Close(dumpData->out);
|
|
dumpData->out = 0;
|
|
}
|
|
|
|
progressbar_destroy(view);
|
|
ui_pop();
|
|
|
|
ui_push(prompt_create("Success", "NAND dumped.", COLOR_TEXT, false, NULL, NULL, NULL, dumpnand_done_onresponse));
|
|
|
|
free(data);
|
|
} else {
|
|
*progress = (float) dumpData->offset / (float) dumpData->size;
|
|
snprintf(progressText, PROGRESS_TEXT_MAX, "%.2f MB / %.2f MB", dumpData->offset / 1024.0f / 1024.0f, dumpData->size / 1024.0f / 1024.0f);
|
|
}
|
|
}
|
|
|
|
static void dumpnand_onresponse(ui_view* view, void* data, bool response) {
|
|
prompt_destroy(view);
|
|
|
|
if(response) {
|
|
dump_nand_data* dumpData = (dump_nand_data*) data;
|
|
|
|
Result res = 0;
|
|
|
|
FS_Archive wnandArchive = {ARCHIVE_NAND_W_FS, fsMakePath(PATH_EMPTY, "")};
|
|
if(R_SUCCEEDED(res = FSUSER_OpenFileDirectly(&dumpData->in, wnandArchive, fsMakePath(PATH_UTF16, u"/"), FS_OPEN_READ, 0)) && R_SUCCEEDED(res = FSFILE_GetSize(dumpData->in, &dumpData->size))) {
|
|
FS_Archive sdmcArchive = {ARCHIVE_SDMC, {PATH_BINARY, 0, (u8*) ""}};
|
|
if(R_SUCCEEDED(res = FSUSER_OpenFileDirectly(&dumpData->out, sdmcArchive, fsMakePath(PATH_ASCII, "/NAND.bin"), FS_OPEN_CREATE | FS_OPEN_WRITE, 0))) {
|
|
dumpData->offset = 0;
|
|
|
|
ui_push(progressbar_create("Dumping NAND", "Press B to cancel.", data, dumpnand_update, NULL));
|
|
}
|
|
}
|
|
|
|
if(R_FAILED(res)) {
|
|
if(dumpData->in != 0) {
|
|
FSFILE_Close(dumpData->in);
|
|
dumpData->in = 0;
|
|
}
|
|
|
|
if(dumpData->out != 0) {
|
|
FSFILE_Close(dumpData->out);
|
|
dumpData->out = 0;
|
|
}
|
|
|
|
error_display_res(NULL, NULL, res, "Failed to prepare for NAND dump.");
|
|
|
|
free(data);
|
|
}
|
|
} else {
|
|
free(data);
|
|
}
|
|
}
|
|
|
|
void dump_nand() {
|
|
dump_nand_data* data = (dump_nand_data*) calloc(1, sizeof(dump_nand_data));
|
|
data->in = 0;
|
|
data->out = 0;
|
|
data->offset = 0;
|
|
data->size = 0;
|
|
|
|
ui_push(prompt_create("Confirmation", "Dump raw NAND image to the SD card?", COLOR_TEXT, true, data, NULL, NULL, dumpnand_onresponse));
|
|
} |