diff --git a/arm9/source/driveMenu.cpp b/arm9/source/driveMenu.cpp index 773dce9..32b2351 100644 --- a/arm9/source/driveMenu.cpp +++ b/arm9/source/driveMenu.cpp @@ -47,7 +47,7 @@ bool flashcardMountSkipped = true; static bool flashcardMountRan = true; static bool dmTextPrinted = false; static int dmCursorPosition = 0; -static int dmAssignedOp[6] = {-1}; +static int dmAssignedOp[7] = {-1}; static int dmMaxCursors = -1; static u8 gbaFixedValue = 0; @@ -116,7 +116,8 @@ void dm_drawTopScreen(void) { if ((sdMounted && nitroCurrentDrive==0) || (flashcardMounted && nitroCurrentDrive==1) || (ramdrive1Mounted && nitroCurrentDrive==2) - || (ramdrive2Mounted && nitroCurrentDrive==3)) + || (ramdrive2Mounted && nitroCurrentDrive==3) + || (nandMounted && nitroCurrentDrive==4)) { // Do nothing } @@ -131,6 +132,8 @@ void dm_drawTopScreen(void) { printf ("[ram1:] RAMDRIVE"); } else if (dmAssignedOp[i] == 6) { printf ("[ram2:] RAMDRIVE"); + } else if (dmAssignedOp[i] == 7) { + printf ("[nand:] SYSNAND"); } } } @@ -198,6 +201,11 @@ void dm_drawBottomScreen(void) { } else if (dmAssignedOp[dmCursorPosition] == 6) { printf ("[ram2:] RAMDRIVE\n"); printf ("(RAMdrive FAT, 16 MB)"); + } else if (dmAssignedOp[dmCursorPosition] == 7) { + printf ("[nand:] SYSNAND"); + printf ("\n(SysNAND FAT, "); + printDriveBytes(nandSize); + printf(")"); } } @@ -230,6 +238,10 @@ void driveMenu (void) { dmMaxCursors++; dmAssignedOp[dmMaxCursors] = 6; } + if (nandMounted) { + dmMaxCursors++; + dmAssignedOp[dmMaxCursors] = 7; + } if (expansionPakFound || (io_dldi_data->ioInterface.features & FEATURE_SLOT_GBA) || (isDSiMode() && !(REG_SCFG_MC & BIT(0)))) { @@ -320,7 +332,8 @@ void driveMenu (void) { if ((sdMounted && nitroCurrentDrive==0) || (flashcardMounted && nitroCurrentDrive==1) || (ramdrive1Mounted && nitroCurrentDrive==2) - || (ramdrive2Mounted && nitroCurrentDrive==3)) + || (ramdrive2Mounted && nitroCurrentDrive==3) + || (nandMounted && nitroCurrentDrive==4)) { dmTextPrinted = false; currentDrive = nitroCurrentDrive; @@ -343,6 +356,12 @@ void driveMenu (void) { chdir("ram2:/"); screenMode = 1; break; + } else if (dmAssignedOp[dmCursorPosition] == 7 && isDSiMode() && nandMounted) { + dmTextPrinted = false; + currentDrive = 4; + chdir("nand:/"); + screenMode = 1; + break; } } diff --git a/arm9/source/driveOperations.cpp b/arm9/source/driveOperations.cpp index 5ed5ed0..15859c8 100644 --- a/arm9/source/driveOperations.cpp +++ b/arm9/source/driveOperations.cpp @@ -10,6 +10,7 @@ #include "lzss.h" #include "ramd.h" #include "ramdrive-include.h" +#include "nand.h" #include "tonccpy.h" static sNDSHeader nds; @@ -18,6 +19,8 @@ u8 stored_SCFG_MC = 0; static bool slot1Enabled = true; +bool nandMounted = false; +bool nandMountedDone = false; bool sdMounted = false; bool sdMountedDone = false; // true if SD mount is successful once bool flashcardMounted = false; @@ -25,12 +28,13 @@ bool ramdrive1Mounted = false; bool ramdrive2Mounted = false; bool nitroMounted = false; -int currentDrive = 0; // 0 == SD card, 1 == Flashcard, 2 == RAMdrive 1, 3 == RAMdrive 2 +int currentDrive = 0; // 0 == SD card, 1 == Flashcard, 2 == RAMdrive 1, 3 == RAMdrive 2, 4 == NAND int nitroCurrentDrive = 0; char sdLabel[12]; char fatLabel[12]; +u32 nandSize = 0; u64 sdSize = 0; u64 fatSize = 0; @@ -81,6 +85,8 @@ const char* getDrivePath(void) { return "ram1:/"; case 3: return "ram2:/"; + case 4: + return "nand:/"; } return ""; } @@ -107,20 +113,16 @@ void fixLabel(bool fat) { } } +bool nandFound(void) { + return (access("nand:/", F_OK) == 0); +} + bool sdFound(void) { - if (access("sd:/", F_OK) == 0) { - return true; - } else { - return false; - } + return (access("sd:/", F_OK) == 0); } bool flashcardFound(void) { - if (access("fat:/", F_OK) == 0) { - return true; - } else { - return false; - } + return (access("fat:/", F_OK) == 0); } bool bothSDandFlashcard(void) { @@ -131,6 +133,25 @@ bool bothSDandFlashcard(void) { } } +TWL_CODE bool nandMount(void) { + fatMountSimple("nand", &io_nand); + if (nandFound()) { + nandMountedDone = true; + struct statvfs st; + if (statvfs("nand:/", &st) == 0) { + nandSize = st.f_bsize * st.f_blocks; + } + return true; + } + return false; +} + +TWL_CODE void nandUnmount(void) { + fatUnmount("nand"); + sdSize = 0; + nandMounted = false; +} + TWL_CODE bool sdMount(void) { fatMountSimple("sd", get_io_dsisd()); if (sdFound()) { diff --git a/arm9/source/driveOperations.h b/arm9/source/driveOperations.h index e92e609..70d1708 100644 --- a/arm9/source/driveOperations.h +++ b/arm9/source/driveOperations.h @@ -3,6 +3,8 @@ extern u8 stored_SCFG_MC; +extern bool nandMounted; +extern bool nandMountedDone; extern bool sdMounted; extern bool sdMountedDone; // true if SD mount is successful once extern bool flashcardMounted; @@ -10,21 +12,25 @@ extern bool ramdrive1Mounted; extern bool ramdrive2Mounted; extern bool nitroMounted; -extern int currentDrive; // 0 == SD card, 1 == Flashcard, 2 == RAMdrive 1, 3 == RAMdrive 2 +extern int currentDrive; // 0 == SD card, 1 == Flashcard, 2 == RAMdrive 1, 3 == RAMdrive 2, 4 == NAND extern int nitroCurrentDrive; extern char sdLabel[12]; extern char fatLabel[12]; +extern u32 nandSize; extern u64 sdSize; extern u64 fatSize; extern void printDriveBytes(u64 bytes); extern const char* getDrivePath(void); +extern bool nandFound(void); extern bool sdFound(void); extern bool flashcardFound(void); extern bool bothSDandFlashcard(void); +extern bool nandMount(void); +extern void nandUnmount(void); extern bool sdMount(void); extern void sdUnmount(void); extern bool flashcardMount(void); diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index 5c2678e..a41c132 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -107,7 +107,11 @@ void getDirectoryContents (vector& dirContents) { || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "argv") || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "ARGV") || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "dsi") - || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "DSI")) + || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "DSI") + || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "ids") + || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "IDS") + || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "app") + || (dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "APP")) { dirEntry.isApp = ((currentDrive == 0 && sdMounted) || (currentDrive == 1 && flashcardMounted)); } else if ((dirEntry.name.substr(dirEntry.name.find_last_of(".") + 1) == "firm") @@ -218,7 +222,13 @@ int fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { printf(" Boot file\n"); } if((entry->name.substr(entry->name.find_last_of(".") + 1) == "nds") - || (entry->name.substr(entry->name.find_last_of(".") + 1) == "NDS")) + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "NDS") + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "dsi") + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "DSI") + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "ids") + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "IDS") + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "app") + || (entry->name.substr(entry->name.find_last_of(".") + 1) == "APP")) { maxCursors++; assignedOp[maxCursors] = 3; diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index deb1267..1121277 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -205,6 +205,7 @@ int main(int argc, char **argv) { if (*(vu32*)(0x0DFFFE0C) == 0x474D3969) { ramdrive2Mount(); } + nandMounted = nandMount(); is3DS = ((access("sd:/Nintendo 3DS", F_OK) == 0) && (*(vu32*)(0x0DFFFE0C) == 0x474D3969)); } /*else if (isRegularDS) { *(vu32*)(0x08240000) = 1; diff --git a/arm9/source/nand.c b/arm9/source/nand.c new file mode 100644 index 0000000..e901c0b --- /dev/null +++ b/arm9/source/nand.c @@ -0,0 +1,55 @@ + +#include +#include +#include + +#define SECTOR_SIZE 512 + +static FILE* nandFile; + +bool nand_startup() { + nandFile = fopen("sd:/nand.bin", "rb"); + if (nandFile) { + return true; + } + return false; +} + +bool nand_is_inserted() { + if (nandFile) { + return true; + } + return false; +} + +bool nand_read_sectors(sec_t sector, sec_t numSectors, void *buffer) { + if (!nandFile) return false; + + fseek(nandFile, (sector << 9), SEEK_SET); + fread(buffer, 1, (numSectors << 9), nandFile); + return true; +} + +bool nand_write_sectors(sec_t sector, sec_t numSectors, const void *buffer) { + return false; +} + +bool nand_clear_status() { + return true; +} + +bool nand_shutdown() { + fclose(nandFile); + return true; +} + +const DISC_INTERFACE io_nand = { + ('N' << 24) | ('A' << 16) | ('N' << 8) | 'D', + FEATURE_MEDIUM_CANREAD, + nand_startup, + nand_is_inserted, + nand_read_sectors, + nand_write_sectors, + nand_clear_status, + nand_shutdown +}; diff --git a/arm9/source/nand.h b/arm9/source/nand.h new file mode 100644 index 0000000..e46ad46 --- /dev/null +++ b/arm9/source/nand.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +extern const DISC_INTERFACE io_nand;