diff --git a/arm7/source/main.c b/arm7/source/main.c index 16a3d09..31515f7 100644 --- a/arm7/source/main.c +++ b/arm7/source/main.c @@ -32,6 +32,8 @@ #include "gba.h" +#define SD_IRQ_STATUS (*(vu32*)0x400481C) + void my_installSystemFIFO(void); void my_sdmmc_get_cid(int devicenumber, u32 *cid); @@ -177,9 +179,11 @@ int main() { my_sdmmc_get_cid(true, (u32*)0x2FFD7BC); // Get eMMC CID *(u32*)(0x2FFFD0C) = 0; } - *(u8*)(0x2FFFD08) = ((*(vu32*)(0x400481C) & BIT(3)) || !(*(vu32*)(0x400481C) & BIT(5))); // Set if there's no SD inserted resyncClock(); + // Send SD status + fifoSendValue32(FIFO_USER_04, SD_IRQ_STATUS); + // Dump EEPROM save if(fifoCheckAddress(FIFO_USER_01)) { switch(fifoGetValue32(FIFO_USER_01)) { diff --git a/arm7/source/my_sdmmc.c b/arm7/source/my_sdmmc.c index 8388a9f..a9f1e19 100644 --- a/arm7/source/my_sdmmc.c +++ b/arm7/source/my_sdmmc.c @@ -250,26 +250,31 @@ int my_sdmmc_cardinserted() { static bool my_sdmmc_controller_initialised = false; +static bool my_nand_controller_initialised = false; //--------------------------------------------------------------------------------- void my_sdmmc_controller_init( bool force_init ) { //--------------------------------------------------------------------------------- - if (!force_init && my_sdmmc_controller_initialised) return; + if (!force_init && my_sdmmc_controller_initialised && my_nand_controller_initialised) return; - deviceSD.isSDHC = 0; - deviceSD.SDOPT = 0; - deviceSD.res = 0; - deviceSD.initarg = 0; - deviceSD.clk = 0x80; - deviceSD.devicenumber = 0; + if(true||!my_sdmmc_controller_initialised) { + deviceSD.isSDHC = 0; + deviceSD.SDOPT = 0; + deviceSD.res = 0; + deviceSD.initarg = 0; + deviceSD.clk = 0x80; + deviceSD.devicenumber = 0; + } - deviceNAND.isSDHC = 0; - deviceNAND.SDOPT = 0; - deviceNAND.res = 0; - deviceNAND.initarg = 1; - deviceNAND.clk = 0x80; - deviceNAND.devicenumber = 1; + if(!my_nand_controller_initialised) { + deviceNAND.isSDHC = 0; + deviceNAND.SDOPT = 0; + deviceNAND.res = 0; + deviceNAND.initarg = 1; + deviceNAND.clk = 0x80; + deviceNAND.devicenumber = 1; + } *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xF7FFu; *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xEFFFu; @@ -308,6 +313,7 @@ void my_sdmmc_controller_init( bool force_init ) { *(vu16*)(SDMMC_BASE + REG_SDSTOP) = 0; my_sdmmc_controller_initialised = true; + my_nand_controller_initialised = true; my_setTarget(&deviceSD); } @@ -594,7 +600,7 @@ int my_sdmmc_nand_startup() { //--------------------------------------------------------------------------------- int my_sdmmc_sd_startup() { //--------------------------------------------------------------------------------- - my_sdmmc_controller_init(true); + my_sdmmc_controller_init(false); return my_sdmmc_sdcard_init(); } @@ -627,6 +633,7 @@ void my_sdmmcValueHandler(u32 value, void* user_data) { break; case SDMMC_SD_STOP: + my_sdmmc_controller_initialised = false; break; case SDMMC_NAND_SIZE: diff --git a/arm9/source/driveMenu.cpp b/arm9/source/driveMenu.cpp index 4eab364..398c846 100644 --- a/arm9/source/driveMenu.cpp +++ b/arm9/source/driveMenu.cpp @@ -35,6 +35,7 @@ #include "fileOperations.h" #include "font.h" #include "language.h" +#include "my_sd.h" #include "read_card.h" #include "startMenu.h" @@ -84,24 +85,33 @@ void dm_drawTopScreen(void) { switch(dmOperations[i]) { case DriveMenuOperation::sdCard: font->printf(0, i + 1, true, Alignment::left, pal, STR_SDCARD_LABEL.c_str(), sdLabel[0] == 0 ? STR_UNTITLED.c_str() : sdLabel); + if(!driveWritable(Drive::sdCard)) + font->print(-1, i + 1, true, "[R]", Alignment::right, pal); break; case DriveMenuOperation::flashcard: font->printf(0, i + 1, true, Alignment::left, pal, STR_FLASHCARD_LABEL.c_str(), fatLabel[0] == 0 ? STR_UNTITLED.c_str() : fatLabel); + if(!driveWritable(Drive::flashcard)) + font->print(-1, i + 1, true, "[R]", Alignment::right, pal); break; case DriveMenuOperation::ramDrive: font->print(0, i + 1, true, STR_RAMDRIVE_LABEL, Alignment::left, pal); break; case DriveMenuOperation::sysNand: font->print(0, i + 1, true, STR_SYSNAND_LABEL, Alignment::left, pal); + if(!driveWritable(Drive::nand)) + font->print(-1, i + 1, true, "[R]", Alignment::right, pal); break; case DriveMenuOperation::nitroFs: font->print(0, i + 1, true, STR_NITROFS_LABEL, Alignment::left, pal); + if (!((sdMounted && nitroCurrentDrive == Drive::sdCard) || (flashcardMounted && nitroCurrentDrive == Drive::flashcard) || (ramdriveMounted && nitroCurrentDrive == Drive::ramDrive) || (nandMounted && nitroCurrentDrive == Drive::nand) || (imgMounted && nitroCurrentDrive == Drive::fatImg))) font->print(-1, i + 1, true, "[x]", Alignment::right, pal); + else + font->print(-1, i + 1, true, "[R]", Alignment::right, pal); break; case DriveMenuOperation::fatImage: if ((sdMounted && imgCurrentDrive == Drive::sdCard) @@ -109,6 +119,7 @@ void dm_drawTopScreen(void) { || (ramdriveMounted && imgCurrentDrive == Drive::ramDrive) || (nandMounted && imgCurrentDrive == Drive::nand)) { font->printf(0, i + 1, true, Alignment::left, pal, STR_FAT_LABEL_NAMED.c_str(), imgLabel[0] == 0 ? STR_UNTITLED.c_str() : imgLabel); + font->print(-1, i + 1, true, "[R]", Alignment::right, pal); } else { font->print(0, i + 1, true, STR_FAT_LABEL, Alignment::left, pal); font->print(-1, i + 1, true, "[x]", Alignment::right, pal); @@ -186,7 +197,7 @@ void dm_drawBottomScreen(void) { break; case DriveMenuOperation::sysNand: font->print(0, 0, false, STR_SYSNAND_LABEL); - font->printf(0, 1, false, Alignment::left, Palette::white, STR_SYSNAND_FAT.c_str(), getDriveBytes(fatSize).c_str()); + font->printf(0, 1, false, Alignment::left, Palette::white, STR_SYSNAND_FAT.c_str(), getDriveBytes(nandSize).c_str()); font->printf(0, 2, false, Alignment::left, Palette::white, STR_N_FREE.c_str(), getDriveBytes(getBytesFree("nand:/")).c_str()); break; case DriveMenuOperation::fatImage: @@ -281,6 +292,12 @@ void driveMenu (void) { if (REG_SCFG_MC != stored_SCFG_MC) { break; } + if (sdMounted && sdRemoved) { + currentDrive = Drive::sdCard; + chdir("sd:/"); + sdUnmount(); + break; + } } } while (!(pressed & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT | KEY_A | KEY_B | KEY_X | KEY_L | KEY_START #ifdef SCREENSWAP @@ -379,7 +396,7 @@ void driveMenu (void) { currentDrive = Drive::sdCard; chdir("sd:/"); sdUnmount(); - } else { + } else if(!sdRemoved) { sdMounted = sdMount(); } } else { diff --git a/arm9/source/driveOperations.cpp b/arm9/source/driveOperations.cpp index 8721667..cc860e3 100644 --- a/arm9/source/driveOperations.cpp +++ b/arm9/source/driveOperations.cpp @@ -12,6 +12,7 @@ #include "dldi-include.h" #include "lzss.h" #include "ramd.h" +#include "my_sd.h" #include "nandio.h" #include "imgio.h" #include "tonccpy.h" @@ -154,9 +155,7 @@ TWL_CODE void nandUnmount(void) { } bool sdMount(void) { - extern const DISC_INTERFACE __my_io_dsisd; - - fatMountSimple("sd", &__my_io_dsisd); + fatMountSimple("sd", __my_io_dsisd()); if (sdFound()) { sdMountedDone = true; fatGetVolumeLabel("sd", sdLabel); @@ -178,6 +177,7 @@ u64 getBytesFree(const char* drivePath) { void sdUnmount(void) { fatUnmount("sd"); + my_sdio_Shutdown(); sdLabel[0] = '\0'; sdSize = 0; sdMounted = false; @@ -418,3 +418,22 @@ void imgUnmount(void) { imgSize = 0; imgMounted = false; } + +bool driveWritable(Drive drive) { + switch(drive) { + case Drive::sdCard: + return __my_io_dsisd()->features & FEATURE_MEDIUM_CANWRITE; + case Drive::flashcard: + return dldiGetInternal()->features & FEATURE_MEDIUM_CANWRITE; + case Drive::ramDrive: + return io_ram_drive.features & FEATURE_MEDIUM_CANWRITE; + case Drive::nand: + return io_dsi_nand.features & FEATURE_MEDIUM_CANWRITE; + case Drive::nitroFS: + return false; + case Drive::fatImg: + return io_img.features & FEATURE_MEDIUM_CANWRITE; + } + + return false; +} diff --git a/arm9/source/driveOperations.h b/arm9/source/driveOperations.h index e50bd27..4763e32 100644 --- a/arm9/source/driveOperations.h +++ b/arm9/source/driveOperations.h @@ -13,8 +13,6 @@ enum class Drive : u8 { fatImg }; -#define DRIVE_WRITABLE(drive) (drive < Drive::nand) - extern u8 stored_SCFG_MC; extern bool nandMounted; @@ -58,5 +56,6 @@ extern void nitroUnmount(void); extern bool imgMount(const char* imgName); extern void imgUnmount(void); extern u64 getBytesFree(const char* drivePath); +extern bool driveWritable(Drive drive); #endif //FLASHCARD_H diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index 082a06f..aea95ed 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -40,6 +40,7 @@ #include "dumpOperations.h" #include "font.h" #include "hexEditor.h" +#include "my_sd.h" #include "keyboard.h" #include "ndsInfo.h" #include "startMenu.h" @@ -280,6 +281,9 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { pressed = keysDownRepeat(); held = keysHeld(); swiWaitForVBlank(); + + if(currentDrive == Drive::sdCard && sdRemoved) + return FileOperation::none; } while (!(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L)) #ifdef SCREENSWAP && !(pressed & KEY_TOUCH) @@ -647,6 +651,11 @@ std::string browseForFile (void) { if (REG_SCFG_MC != stored_SCFG_MC) { break; } + + if(currentDrive == Drive::sdCard && sdRemoved) { + screenMode = 0; + return "null"; + } } while (!(pressed & ~(KEY_R | KEY_TOUCH | KEY_LID))); if (isDSiMode() && !pressed && currentDrive == Drive::flashcard && REG_SCFG_MC == 0x11 && flashcardMounted) { diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index f88c3ca..45791a9 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -5,6 +5,7 @@ #include "font.h" #include "keyboard.h" #include "language.h" +#include "my_sd.h" #include "screenshot.h" #include "tonccpy.h" @@ -216,7 +217,7 @@ u32 search(u32 offset, FILE *file) { } void hexEditor(const char *path, Drive drive) { - FILE *file = fopen(path, DRIVE_WRITABLE(drive) ? "rb+" : "rb"); + FILE *file = fopen(path, driveWritable(drive) ? "rb+" : "rb"); if(!file) return; @@ -287,6 +288,9 @@ void hexEditor(const char *path, Drive drive) { // Print time font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen); font->update(true); + + if(currentDrive == Drive::sdCard && sdRemoved) + return; } while(!held); if(mode == 0) { @@ -339,7 +343,7 @@ void hexEditor(const char *path, Drive drive) { if((int)cursorPosition < bytesPerLine * maxLines - 1) cursorPosition = std::min(cursorPosition + 1, fileSize - offset - 1); } else if(pressed & KEY_A) { - if(DRIVE_WRITABLE(drive)) { + if(driveWritable(drive)) { mode = 2; } } else if(pressed & KEY_B) { diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 3e38049..15194bf 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -37,6 +37,7 @@ #include "fileOperations.h" #include "font.h" #include "language.h" +#include "my_sd.h" #include "nitrofs.h" #include "tonccpy.h" #include "version.h" @@ -110,8 +111,8 @@ int main(int argc, char **argv) { tonccpy(BG_PALETTE, gm9i_logoPal, gm9i_logoPalLen); font->print(1, 1, false, titleName); - font->print(1, 2, false, "---------------------------------------"); - font->print(1, 3, false, "https:/github.com/DS-Homebrew/GodMode9i"); + font->print(1, 2, false, "----------------------------------------"); + font->print(1, 3, false, "https://github.com/DS-Homebrew/GodMode9i"); fifoWaitValue32(FIFO_USER_06); if (fifoGetValue32(FIFO_USER_03) == 0) arm7SCFGLocked = true; @@ -138,15 +139,16 @@ int main(int argc, char **argv) { font->clear(false); font->print(1, 1, false, titleName); - font->print(1, 2, false, "---------------------------------------"); - font->print(1, 3, false, "https:/github.com/DS-Homebrew/GodMode9i"); + font->print(1, 2, false, "----------------------------------------"); + font->print(1, 3, false, "https://github.com/DS-Homebrew/GodMode9i"); font->print(-2, -2, false, "Mounting drive(s)...", Alignment::right); font->update(false); sysSetCartOwner (BUS_OWNER_ARM9); // Allow arm9 to access GBA ROM if (isDSiMode() || !isRegularDS) { - if (*(u8*)(0x2FFFD08) == 0) { + fifoSetValue32Handler(FIFO_USER_04, sdStatusHandler, nullptr); + if (!sdRemoved) { sdMounted = sdMount(); } } diff --git a/arm9/source/my_sd.c b/arm9/source/my_sd.c index 0be3397..1e07877 100644 --- a/arm9/source/my_sd.c +++ b/arm9/source/my_sd.c @@ -1,9 +1,18 @@ -#include +#include "my_sd.h" + #include #include #include #include +volatile bool sdRemoved = false; +volatile bool sdWriteLocked = false; + +void sdStatusHandler(u32 sdIrqStatus, void *userdata) { + sdRemoved = (sdIrqStatus & BIT(5)) == 0; + sdWriteLocked = (sdIrqStatus & BIT(7)) == 0; +} + //--------------------------------------------------------------------------------- bool my_sdio_Startup() { //--------------------------------------------------------------------------------- @@ -58,6 +67,9 @@ bool my_sdio_ReadSectors(sec_t sector, sec_t numSectors,void* buffer) { //--------------------------------------------------------------------------------- bool my_sdio_WriteSectors(sec_t sector, sec_t numSectors,const void* buffer) { //--------------------------------------------------------------------------------- + if(sdWriteLocked) + return false; + FifoMessage msg; DC_FlushRange(buffer,numSectors * 512); @@ -86,10 +98,16 @@ bool my_sdio_ClearStatus() { //--------------------------------------------------------------------------------- bool my_sdio_Shutdown() { //--------------------------------------------------------------------------------- - return true; + fifoSendValue32(FIFO_SDMMC,SDMMC_SD_STOP); + + fifoWaitValue32(FIFO_SDMMC); + + int result = fifoGetValue32(FIFO_SDMMC); + + return result == 1; } -const DISC_INTERFACE __my_io_dsisd = { +const DISC_INTERFACE __my_io_dsisd_rw = { DEVICE_TYPE_DSI_SD, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE, (FN_MEDIUM_STARTUP)&my_sdio_Startup, @@ -99,3 +117,18 @@ const DISC_INTERFACE __my_io_dsisd = { (FN_MEDIUM_CLEARSTATUS)&my_sdio_ClearStatus, (FN_MEDIUM_SHUTDOWN)&my_sdio_Shutdown }; + +const DISC_INTERFACE __my_io_dsisd_r = { + DEVICE_TYPE_DSI_SD, + FEATURE_MEDIUM_CANREAD, + (FN_MEDIUM_STARTUP)&my_sdio_Startup, + (FN_MEDIUM_ISINSERTED)&my_sdio_IsInserted, + (FN_MEDIUM_READSECTORS)&my_sdio_ReadSectors, + (FN_MEDIUM_WRITESECTORS)&my_sdio_WriteSectors, + (FN_MEDIUM_CLEARSTATUS)&my_sdio_ClearStatus, + (FN_MEDIUM_SHUTDOWN)&my_sdio_Shutdown +}; + +const DISC_INTERFACE *__my_io_dsisd() { + return sdWriteLocked ? &__my_io_dsisd_r : &__my_io_dsisd_rw; +} diff --git a/arm9/source/my_sd.h b/arm9/source/my_sd.h new file mode 100644 index 0000000..3eb6bfc --- /dev/null +++ b/arm9/source/my_sd.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern volatile bool sdRemoved; +extern volatile bool sdWriteLocked; + +void sdStatusHandler(u32 sdIrqStatus, void *userdata); + +bool my_sdio_Shutdown(); + +const DISC_INTERFACE *__my_io_dsisd(); + +#ifdef __cplusplus +} +#endif