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:
Pk11 2022-01-02 13:38:55 -06:00 committed by GitHub
parent b3bdcabec2
commit 2b8808ae6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 146 additions and 32 deletions

View File

@ -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)) {

View File

@ -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:

View File

@ -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 {

View File

@ -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;
}

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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();
}
}

View File

@ -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
View 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