mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
Autodetect SD removal and more bug fixes (#133)
* Autodetect SD removal, see desc Also: - Mark read-only drives as `[R]` - Detect and respect write protect on SD card - Don't attempt to remount SD card if not inserted - Fix repo link on startup screen * There are enough characters for `https` I didn't notice there was actually 1 more column usable Co-authored-by: RocketRobz <bobesh8@gmail.com>
This commit is contained in:
parent
b3bdcabec2
commit
2b8808ae6d
@ -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)) {
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,18 @@
|
||||
#include <nds/disc_io.h>
|
||||
#include "my_sd.h"
|
||||
|
||||
#include <nds/fifocommon.h>
|
||||
#include <nds/fifomessages.h>
|
||||
#include <nds/system.h>
|
||||
#include <nds/arm9/cache.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
20
arm9/source/my_sd.h
Normal file
20
arm9/source/my_sd.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <nds/disc_io.h>
|
||||
|
||||
#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
|
||||
Loading…
Reference in New Issue
Block a user