forked from Mirror/GodMode9
Added ability to format SD cards
This commit is contained in:
parent
bf38dbc63b
commit
a7b511687b
@ -55,7 +55,7 @@
|
||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_LABEL 0
|
||||
#define _USE_LABEL 1
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
@ -154,7 +154,7 @@
|
||||
/ the drive ID strings are: A-Z and 0-9. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0
|
||||
#define _MULTI_PARTITION 1
|
||||
/* This option switches multi-partition feature. By default (0), each logical drive
|
||||
/ number is bound to the same physical drive number and only an FAT volume found on
|
||||
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
|
||||
|
64
source/fs.c
64
source/fs.c
@ -3,6 +3,7 @@
|
||||
#include "virtual.h"
|
||||
#include "image.h"
|
||||
#include "sha.h"
|
||||
#include "sdmmc.h"
|
||||
#include "ff.h"
|
||||
|
||||
#define MAIN_BUFFER ((u8*)0x21200000)
|
||||
@ -11,6 +12,12 @@
|
||||
#define NORM_FS 10
|
||||
#define VIRT_FS 4
|
||||
|
||||
// Volume2Partition resolution table
|
||||
PARTITION VolToPart[] = {
|
||||
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0},
|
||||
{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}
|
||||
};
|
||||
|
||||
// don't use this area for anything else!
|
||||
static FATFS* fs = (FATFS*)0x20316000;
|
||||
|
||||
@ -78,6 +85,63 @@ bool IsMountedFS(const char* path) {
|
||||
return ((fsnum >= 0) && (fsnum < NORM_FS)) ? fs_mounted[fsnum] : false;
|
||||
}
|
||||
|
||||
uint64_t GetSDCardSize() {
|
||||
if (sdmmc_sdcard_init() != 0) return 0;
|
||||
return (u64) getMMCDevice(1)->total_size * 512;
|
||||
}
|
||||
|
||||
bool FormatSDCard(u32 hidden_mb) {
|
||||
u8 mbr[0x200] = { 0 };
|
||||
u8 mbrdata[0x42] = {
|
||||
0x80, 0x01, 0x01, 0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x80, 0x01, 0x01, 0x00, 0x1C, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x55, 0xAA
|
||||
};
|
||||
u32 sd_size = getMMCDevice(1)->total_size;
|
||||
u32* fat_sector = (u32*) (mbrdata + 0x08);
|
||||
u32* fat_size = (u32*) (mbrdata + 0x0C);
|
||||
u32* emu_sector = (u32*) (mbrdata + 0x18);
|
||||
u32* emu_size = (u32*) (mbrdata + 0x1C);
|
||||
|
||||
*emu_sector = 1;
|
||||
*emu_size = hidden_mb * (1024 * 1024) / 512;
|
||||
*fat_sector = align(*emu_sector + *emu_size, 0x2000); // align to 4MB
|
||||
if (sd_size < *fat_sector + 0x80000) { // minimum free space: 256MB
|
||||
ShowPrompt(false, "ERROR: SD card is too small");
|
||||
return false;
|
||||
}
|
||||
*fat_size = sd_size - *fat_sector;
|
||||
sd_size = *fat_size;
|
||||
|
||||
// build the MBR
|
||||
memcpy(mbr + 0x1BE, mbrdata, 0x42);
|
||||
if (hidden_mb) memcpy(mbr, "GATEWAYNAND", 12);
|
||||
else memset(mbr + 0x1CE, 0, 0x10);
|
||||
|
||||
// one last warning....
|
||||
if (!ShowUnlockSequence(3, "!WARNING!\n \nProceeding will format this SD.\nThis will irreversibly delete\nALL data on it.\n"))
|
||||
return false;
|
||||
ShowString("Formatting SD, please wait...", hidden_mb);
|
||||
|
||||
// write the MBR to disk
|
||||
// !this assumes a fully deinitialized file system!
|
||||
if ((sdmmc_sdcard_init() != 0) || (sdmmc_sdcard_writesectors(0, 1, mbr) != 0)) {
|
||||
ShowPrompt(false, "ERROR: SD card i/o failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
// format the SD card
|
||||
// cluster size: auto (<= 4GB) / 32KiB (<= 8GB) / 64 KiB (> 8GB)
|
||||
InitSDCardFS();
|
||||
UINT c_size = (sd_size < 0x800000) ? 0 : (sd_size < 0x1000000) ? 32768 : 65536;
|
||||
bool ret = (f_mkfs("0:", 0, c_size) == FR_OK) && (f_setlabel("0:GM9SD") == FR_OK);
|
||||
DeinitSDCardFS();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CheckWritePermissions(const char* path) {
|
||||
char area_name[16];
|
||||
int pdrv = PathToNumFS(path);
|
||||
|
@ -39,6 +39,12 @@ bool InitExtFS();
|
||||
void DeinitExtFS();
|
||||
void DeinitSDCardFS();
|
||||
|
||||
/** Return total size of SD card **/
|
||||
uint64_t GetSDCardSize();
|
||||
|
||||
/** Format the SD card **/
|
||||
bool FormatSDCard(u32 hidden_mb);
|
||||
|
||||
/** Check if writing to this path is allowed **/
|
||||
bool CheckWritePermissions(const char* path);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "virtual.h"
|
||||
#include "image.h"
|
||||
|
||||
#define VERSION "0.5.8"
|
||||
#define VERSION "0.5.9"
|
||||
|
||||
#define N_PANES 2
|
||||
#define IMG_DRV "789I"
|
||||
@ -166,6 +166,36 @@ void DrawDirContents(DirStruct* contents, u32 cursor, u32* scroll) {
|
||||
} else DrawRectangle(BOT_SCREEN, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, SCREEN_HEIGHT, COLOR_STD_BG);
|
||||
}
|
||||
|
||||
u32 SdFormatMenu(void) {
|
||||
const u32 emunand_size_table[6] = { 0x0, 0x0, 0x3AF, 0x4D8, 0x400, 0x800 };
|
||||
const char* optionstr[6] = { "No EmuNAND", "O3DS NAND size", "N3DS NAND size", "1GB (legacy size)", "2GB (legacy size)", "User input..." };
|
||||
u64 sdcard_size_mb = 0;
|
||||
u64 emunand_size_mb = (u64) -1;
|
||||
|
||||
// check actual SD card size
|
||||
sdcard_size_mb = GetSDCardSize() / 0x100000;
|
||||
if (!sdcard_size_mb) {
|
||||
ShowPrompt(false, "ERROR: SD card not detected.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 user_select = ShowSelectPrompt(6, optionstr, "Format SD card (%lluGB)?\nChoose EmuNAND size:", sdcard_size_mb / 1024);
|
||||
if (user_select && (user_select < 6)) {
|
||||
emunand_size_mb = emunand_size_table[user_select];
|
||||
} else if (user_select == 6) do {
|
||||
emunand_size_mb = ShowNumberPrompt(0, "SD card size is %lluMB.\nEnter EmuNAND size (MB) below:", sdcard_size_mb);
|
||||
if (emunand_size_mb == (u64) -1) break;
|
||||
} while (emunand_size_mb > sdcard_size_mb);
|
||||
if (emunand_size_mb == (u64) -1) return 1;
|
||||
|
||||
if (!FormatSDCard((u32) emunand_size_mb)) {
|
||||
ShowPrompt(false, "Format SD: failed!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 HexViewer(const char* path) {
|
||||
static const u32 max_data = (SCREEN_HEIGHT / 8) * 16;
|
||||
static u32 mode = 0;
|
||||
@ -588,11 +618,17 @@ u32 GodMode() {
|
||||
DeinitSDCardFS();
|
||||
clipboard->n_entries = 0;
|
||||
memset(panedata, 0x00, N_PANES * sizeof(PaneData));
|
||||
ShowPrompt(false, "SD card unmounted, you can eject now.\nPut it back in before you press <A>.");
|
||||
while (!InitSDCardFS()) {
|
||||
if (!ShowPrompt(true, "Reinitialising SD card failed! Retry?"))
|
||||
return exit_mode;
|
||||
ShowString("SD card unmounted, you can eject now.\n \n<R+Y+\x1B> for format menu\n<A> to remount SD card");
|
||||
while (true) {
|
||||
u32 pad_choice = InputWait();
|
||||
if ((pad_choice & (BUTTON_R1|BUTTON_Y|BUTTON_LEFT)) == (BUTTON_R1|BUTTON_Y|BUTTON_LEFT))
|
||||
SdFormatMenu();
|
||||
else if (pad_choice & (BUTTON_B|BUTTON_START)) return exit_mode;
|
||||
else if (!(pad_choice & BUTTON_A)) continue;
|
||||
if (InitSDCardFS()) break;
|
||||
ShowString("Reinitialising SD card failed!\n \n<R+Y+\x1B> for format menu\n<A> to retry, <B> to reboot");
|
||||
}
|
||||
ClearScreenF(true, false, COLOR_STD_BG);
|
||||
InitEmuNandBase();
|
||||
InitExtFS();
|
||||
GetDirContents(current_dir, current_path);
|
||||
|
17
source/ui.c
17
source/ui.c
@ -469,6 +469,23 @@ u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
u64 ShowNumberPrompt(u64 start_val, const char *format, ...) {
|
||||
const char* alphabet = "0123456789";
|
||||
char inputstr[20 + 1] = { 0 };
|
||||
u64 ret = 0;
|
||||
va_list va;
|
||||
|
||||
snprintf(inputstr, 20 + 1, "%llu", start_val);
|
||||
|
||||
va_start(va, format);
|
||||
if (ShowInputPrompt(inputstr, 20 + 1, 1, alphabet, format, va)) {
|
||||
sscanf(inputstr, "%llu", &ret);
|
||||
} else ret = (u64) -1;
|
||||
va_end(va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...) {
|
||||
const char* alphabet = "0123456789ABCDEF";
|
||||
char inputstr[128 + 1] = { 0 }; // maximum size of data: 64 byte
|
||||
|
@ -73,5 +73,6 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
|
||||
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
||||
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
||||
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);
|
||||
u64 ShowNumberPrompt(u64 start_val, const char *format, ...);
|
||||
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...);
|
||||
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
||||
|
Loading…
x
Reference in New Issue
Block a user