Improve unmounting and various other bug fixes (#137)

* Various improvements to drive unmounting drives

* Add mounting DSiWare saves

They're FAT12 images, but libfat doens't like them without a little tweak since they don't have the 'FAT' identifier text

* Don't try to send DSi SD card status on regular DS

Fixes X and Y buttons being unresponsive
This commit is contained in:
Pk11 2022-01-03 21:08:43 -06:00 committed by GitHub
parent e8c3a8596b
commit a9a29204ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 159 additions and 93 deletions

View File

@ -191,7 +191,8 @@ int main() {
resyncClock();
// Send SD status
fifoSendValue32(FIFO_USER_04, SD_IRQ_STATUS);
if(isDSiMode() || *(u16*)(0x4004700) != 0)
fifoSendValue32(FIFO_USER_04, SD_IRQ_STATUS);
// Dump EEPROM save
if(fifoCheckAddress(FIFO_USER_01)) {

View File

@ -64,6 +64,7 @@ static char romTitle[13] = {0};
static u32 romSize, romSizeTrimmed;
static u8 gbaFixedValue = 0;
static u8 stored_SCFG_MC = 0;
extern bool arm7SCFGLocked;
@ -103,27 +104,11 @@ void dm_drawTopScreen(void) {
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);
font->print(-1, i + 1, true, "[R]", Alignment::right, pal);
break;
case DriveMenuOperation::fatImage:
if ((sdMounted && imgCurrentDrive == Drive::sdCard)
|| (flashcardMounted && imgCurrentDrive == Drive::flashcard)
|| (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);
}
font->printf(0, i + 1, true, Alignment::left, pal, STR_FAT_LABEL.c_str(), imgLabel[0] == 0 ? STR_UNTITLED.c_str() : imgLabel);
font->print(-1, i + 1, true, "[R]", Alignment::right, pal);
break;
case DriveMenuOperation::gbaCart:
font->printf(0, i + 1, true, Alignment::left, pal, STR_GBA_GAMECART.c_str(), romTitle);
@ -164,7 +149,8 @@ void dm_drawBottomScreen(void) {
font->print(0, row--, false, STR_SCREENSHOTTEXT);
}
font->print(0, row--, false, STR_IMAGETEXT);
if(dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs || dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage)
font->print(0, row--, false, STR_IMAGETEXT);
font->print(0, row--, false, titleName);
switch(dmOperations[dmCursorPosition]) {
@ -201,7 +187,7 @@ void dm_drawBottomScreen(void) {
font->printf(0, 2, false, Alignment::left, Palette::white, STR_N_FREE.c_str(), getDriveBytes(getBytesFree("nand:/")).c_str());
break;
case DriveMenuOperation::fatImage:
font->print(0, 0, false, STR_FAT_LABEL);
font->printf(0, 0, false, Alignment::left, Palette::white, STR_FAT_LABEL.c_str(), imgLabel[0] == 0 ? STR_UNTITLED.c_str() : imgLabel);
font->printf(0, 1, false, Alignment::left, Palette::white, STR_FAT_IMAGE.c_str(), getDriveBytes(imgSize).c_str());
break;
case DriveMenuOperation::none:
@ -221,11 +207,11 @@ void driveMenu (void) {
}
dmOperations.clear();
if (sdMounted)
if (sdMounted && !sdRemoved)
dmOperations.push_back(DriveMenuOperation::sdCard);
if (nandMounted)
dmOperations.push_back(DriveMenuOperation::sysNand);
if (flashcardMounted)
if (flashcardMounted && !driveRemoved(Drive::flashcard))
dmOperations.push_back(DriveMenuOperation::flashcard);
if (ramdriveMounted)
dmOperations.push_back(DriveMenuOperation::ramDrive);
@ -268,6 +254,9 @@ void driveMenu (void) {
romSizeTrimmed = romSize = 0;
}
if(dmCursorPosition >= (int)dmOperations.size())
dmCursorPosition = dmOperations.size() - 1;
dm_drawBottomScreen();
dm_drawTopScreen();
@ -289,7 +278,7 @@ void driveMenu (void) {
break;
}
} else if (isDSiMode()) {
if (REG_SCFG_MC != stored_SCFG_MC) {
if ((REG_SCFG_MC != stored_SCFG_MC) || (flashcardMounted && driveRemoved(Drive::flashcard))) {
break;
}
if (sdMounted && sdRemoved) {
@ -378,11 +367,11 @@ void driveMenu (void) {
// Unmount/Remount FAT image
if ((held & KEY_R) && (pressed & KEY_X)) {
if (nitroMounted) {
if (dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs) {
currentDrive = Drive::nitroFS;
chdir("nitro:/");
nitroUnmount();
} else if (imgMounted) {
} else if (dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage) {
currentDrive = Drive::fatImg;
chdir("img:/");
imgUnmount();
@ -427,15 +416,16 @@ void driveMenu (void) {
screenshot();
}
if (isDSiMode() && !flashcardMountSkipped && !pressed && !held) {
if (REG_SCFG_MC == 0x11) {
if (isDSiMode() && !flashcardMountSkipped) {
if (driveRemoved(Drive::flashcard)) {
if (flashcardMounted) {
flashcardUnmount();
flashcardMountRan = false;
}
} else if (!flashcardMountRan) {
flashcardMountRan = true;
flashcardMounted = flashcardMount(); // Try to mount flashcard
}
flashcardMountRan = false;
}
}
}

View File

@ -2,6 +2,7 @@
#include <nds.h>
#include <nds/arm9/dldi.h>
#include <dirent.h>
#include <fat.h>
#include <stdio.h>
#include <string>
@ -25,8 +26,6 @@
static sNDSHeader nds;
u8 stored_SCFG_MC = 0;
static bool slot1Enabled = true;
bool nandMounted = false;
@ -176,6 +175,11 @@ u64 getBytesFree(const char* drivePath) {
}
void sdUnmount(void) {
if(imgMounted && imgCurrentDrive == Drive::sdCard)
imgUnmount();
if(nitroMounted && nitroCurrentDrive == Drive::sdCard)
nitroUnmount();
fatUnmount("sd");
my_sdio_Shutdown();
sdLabel[0] = '\0';
@ -327,6 +331,11 @@ bool flashcardMount(void) {
}
void flashcardUnmount(void) {
if(imgMounted && imgCurrentDrive == Drive::flashcard)
imgUnmount();
if(nitroMounted && nitroCurrentDrive == Drive::flashcard)
nitroUnmount();
fatUnmount("fat");
fatLabel[0] = '\0';
fatSize = 0;
@ -400,15 +409,19 @@ void ramdriveMount(bool ram32MB) {
}
void nitroUnmount(void) {
if(imgMounted && imgCurrentDrive == Drive::nitroFS)
imgUnmount();
ownNitroFSMounted = 2;
fatUnmount("nitro");
nitroMounted = false;
}
bool imgMount(const char* imgName) {
extern const char* currentImgName;
bool imgMount(const char* imgName, bool dsiwareSave) {
extern char currentImgName[PATH_MAX];
currentImgName = imgName;
fatMountSimple("img", &io_img);
strcpy(currentImgName, imgName);
fatMountSimple("img", dsiwareSave ? &io_dsiware_save : &io_img);
if (imgFound()) {
fatGetVolumeLabel("img", imgLabel);
fixLabel(imgLabel);
@ -422,7 +435,11 @@ bool imgMount(const char* imgName) {
}
void imgUnmount(void) {
if(nitroMounted && nitroCurrentDrive == Drive::fatImg)
nitroUnmount();
fatUnmount("img");
img_shutdown();
imgLabel[0] = '\0';
imgSize = 0;
imgMounted = false;
@ -446,3 +463,22 @@ bool driveWritable(Drive drive) {
return false;
}
bool driveRemoved(Drive drive) {
switch(drive) {
case Drive::sdCard:
return sdRemoved;
case Drive::flashcard:
return REG_SCFG_MC & BIT(0);
case Drive::ramDrive:
return !ramdriveMounted;
case Drive::nand:
return !nandMounted;
case Drive::nitroFS:
return driveRemoved(nitroCurrentDrive);
case Drive::fatImg:
return driveRemoved(imgCurrentDrive);
}
return false;
}

View File

@ -13,8 +13,6 @@ enum class Drive : u8 {
fatImg
};
extern u8 stored_SCFG_MC;
extern bool nandMounted;
extern bool sdMounted;
extern bool sdMountedDone; // true if SD mount is successful once
@ -53,9 +51,10 @@ extern bool flashcardMount(void);
extern void flashcardUnmount(void);
extern void ramdriveMount(bool ram32MB);
extern void nitroUnmount(void);
extern bool imgMount(const char* imgName);
extern bool imgMount(const char* imgName, bool dsiwareSave);
extern void imgUnmount(void);
extern u64 getBytesFree(const char* drivePath);
extern bool driveWritable(Drive drive);
extern bool driveRemoved(Drive drive);
#endif //FLASHCARD_H

View File

@ -180,15 +180,19 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
}
}
if(extension(entry->name, {"nds", "dsi", "ids", "app"})) {
operations.push_back(FileOperation::mountNitroFS);
if(extension(entry->name, {"nds", "dsi", "ids", "app", "srl"})) {
if(currentDrive != Drive::nitroFS)
operations.push_back(FileOperation::mountNitroFS);
operations.push_back(FileOperation::ndsInfo);
operations.push_back(FileOperation::trimNds);
} else if(extension(entry->name, {"sav", "sav1", "sav2", "sav3", "sav4", "sav5", "sav6", "sav7", "sav8", "sav9"})) {
}
if(extension(entry->name, {"sav", "sav1", "sav2", "sav3", "sav4", "sav5", "sav6", "sav7", "sav8", "sav9"})) {
operations.push_back(FileOperation::restoreSave);
} else if(extension(entry->name, {"img", "sd"})) {
}
if(currentDrive != Drive::fatImg && extension(entry->name, {"img", "sd", "sav", "pub", "pu1", "pu2", "pu3", "pu4", "pu5", "pu6", "pu7", "pu8", "pu9", "prv", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7", "pr8", "pr9"})) {
operations.push_back(FileOperation::mountImg);
} else if(extension(entry->name, {"frf"})) {
}
if(extension(entry->name, {"frf"})) {
operations.push_back(FileOperation::loadFont);
}
@ -282,7 +286,7 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
held = keysHeld();
swiWaitForVBlank();
if(currentDrive == Drive::sdCard && sdRemoved)
if(driveRemoved(currentDrive))
return FileOperation::none;
} while (!(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L))
#ifdef SCREENSWAP
@ -378,6 +382,9 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
chdir(sourceFolder); // For after copying a folder
break;
} case FileOperation::mountNitroFS: {
if(nitroMounted)
nitroUnmount();
ownNitroFSMounted = 2;
nitroMounted = nitroFSInit(entry->name.c_str());
if (nitroMounted) {
@ -396,7 +403,10 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
changeFileAttribs(entry);
break;
} case FileOperation::mountImg: {
imgMounted = imgMount(entry->name.c_str());
if(imgMounted)
imgUnmount();
imgMounted = imgMount(entry->name.c_str(), !extension(entry->name, {"img", "sd"}));
if (imgMounted) {
chdir("img:/");
imgCurrentDrive = currentDrive;
@ -639,8 +649,6 @@ std::string browseForFile (void) {
fileBrowse_drawBottomScreen(entry);
showDirectoryContents(dirContents, fileOffset, screenOffset);
stored_SCFG_MC = REG_SCFG_MC;
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
do {
// Print time
@ -652,22 +660,12 @@ std::string browseForFile (void) {
held = keysHeld();
swiWaitForVBlank();
if (REG_SCFG_MC != stored_SCFG_MC) {
break;
}
if(currentDrive == Drive::sdCard && sdRemoved) {
if(driveRemoved(currentDrive)) {
screenMode = 0;
return "null";
}
} while (!(pressed & ~(KEY_R | KEY_TOUCH | KEY_LID)));
if (isDSiMode() && !pressed && currentDrive == Drive::flashcard && REG_SCFG_MC == 0x11 && flashcardMounted) {
flashcardUnmount();
screenMode = 0;
return "null";
}
if (pressed & KEY_UP) {
fileOffset--;
if(fileOffset < 0)

View File

@ -289,7 +289,7 @@ void hexEditor(const char *path, Drive drive) {
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
font->update(true);
if(currentDrive == Drive::sdCard && sdRemoved)
if(driveRemoved(currentDrive))
return;
} while(!held);

View File

@ -1,44 +1,57 @@
#include "tonccpy.h"
#include <nds.h>
#include <nds/disc_io.h>
#include <stdio.h>
#include <dirent.h>
#define SECTOR_SIZE 512
// #define WRITABLE
const char* currentImgName;
static FILE* imgFile[2];
char currentImgName[PATH_MAX];
static FILE* imgFile;
bool img_startup() {
imgFile[0] = fopen(currentImgName, "rb");
if (imgFile[0]) {
//imgFile[1] = fopen(currentImgName, "wb");
return true;
}
return false;
#ifdef WRITABLE
imgFile = fopen(currentImgName, "rb+");
#else
imgFile = fopen(currentImgName, "rb");
#endif
return imgFile != NULL;
}
bool img_is_inserted() {
if (imgFile[0]) {
return true;
}
return false;
return imgFile != NULL;
}
bool img_read_sectors(sec_t sector, sec_t numSectors, void *buffer) {
if (!imgFile[0]) return false;
if (!imgFile) return false;
fseek(imgFile[0], (sector << 9), SEEK_SET);
fread(buffer, 1, (numSectors << 9), imgFile[0]);
fseek(imgFile, (sector << 9), SEEK_SET);
fread(buffer, 1, (numSectors << 9), imgFile);
return true;
}
bool dsiware_read_sectors(sec_t sector, sec_t numSectors, void *buffer) {
if(!img_read_sectors(sector, numSectors, buffer)) return false;
// DSiWare saves are FAT12 images, however they don't have the 'FAT' text
// in the bootsector so libfat rejects them
if (sector == 0) tonccpy(buffer + 0x36, "FAT", 3);
return true;
}
bool img_write_sectors(sec_t sector, sec_t numSectors, const void *buffer) {
/*if (!imgFile[1]) return false;
#ifdef WRITABLE
if (!imgFile) return false;
fseek(imgFile[1], (sector << 9), SEEK_SET);
fwrite(buffer, 1, (numSectors << 9), imgFile[1]);
return true;*/
fseek(imgFile, (sector << 9), SEEK_SET);
fwrite(buffer, 1, (numSectors << 9), imgFile);
return true;
#else
return false;
#endif
}
bool img_clear_status() {
@ -46,15 +59,20 @@ bool img_clear_status() {
}
bool img_shutdown() {
fclose(imgFile[0]);
fclose(imgFile[1]);
if (imgFile) {
fclose(imgFile);
imgFile = NULL;
}
return true;
}
const DISC_INTERFACE io_img = {
('I' << 24) | ('M' << 16) | ('G' << 8) | 'F',
//FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE,
#ifdef WRITABLE
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE,
#else
FEATURE_MEDIUM_CANREAD,
#endif
img_startup,
img_is_inserted,
img_read_sectors,
@ -62,3 +80,18 @@ const DISC_INTERFACE io_img = {
img_clear_status,
img_shutdown
};
const DISC_INTERFACE io_dsiware_save = {
('I' << 24) | ('M' << 16) | ('G' << 8) | 'F',
#ifdef WRITABLE
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE,
#else
FEATURE_MEDIUM_CANREAD,
#endif
img_startup,
img_is_inserted,
dsiware_read_sectors,
img_write_sectors,
img_clear_status,
img_shutdown
};

View File

@ -3,4 +3,15 @@
#include <nds.h>
#include <nds/disc_io.h>
#ifdef __cplusplus
extern "C" {
#endif
bool img_shutdown();
extern const DISC_INTERFACE io_img;
extern const DISC_INTERFACE io_dsiware_save;
#ifdef __cplusplus
}
#endif

View File

@ -42,8 +42,7 @@ STRING(FLASHCARD_LABEL, "[fat:] FLASHCARD (%s)")
STRING(RAMDRIVE_LABEL, "[ram:] RAMDRIVE")
STRING(SYSNAND_LABEL, "[nand:] SYSNAND")
STRING(NITROFS_LABEL, "[nitro:] NDS GAME IMAGE")
STRING(FAT_LABEL_NAMED, "[nitro:] FAT IMAGE (%s)")
STRING(FAT_LABEL, "[nitro:] FAT IMAGE")
STRING(FAT_LABEL, "[img:] FAT IMAGE (%s)")
STRING(GBA_GAMECART, "GBA GAMECART (%s)")
STRING(NDS_GAMECARD, "NDS GAMECARD (%s)")

View File

@ -188,15 +188,15 @@ int main(int argc, char **argv) {
// Try to init NitroFS
ownNitroFSMounted = 0;
if (argc > 0 && nitroFSInit(argv[0]));
else if (nitroFSInit("GodMode9i.nds"));
else if (nitroFSInit("GodMode9i.dsi"));
else if (nitroFSInit("sd:/GodMode9i.nds"));
else if (nitroFSInit("sd:/GodMode9i.dsi"));
else if (nitroFSInit("fat:/GodMode9i.nds"));
else if (nitroFSInit("fat:/GodMode9i.dsi"));
nitroMounted = true;
if (argc > 0 && nitroFSInit(argv[0])) nitroCurrentDrive = argv[0][0] == 's' ? Drive::sdCard : Drive::flashcard;
else if (nitroFSInit("sd:/GodMode9i.nds")) nitroCurrentDrive = Drive::sdCard;
else if (nitroFSInit("sd:/GodMode9i.dsi")) nitroCurrentDrive = Drive::sdCard;
else if (nitroFSInit("fat:/GodMode9i.nds")) nitroCurrentDrive = Drive::flashcard;
else if (nitroFSInit("fat:/GodMode9i.dsi")) nitroCurrentDrive = Drive::flashcard;
else {
ownNitroFSMounted = 1;
nitroMounted = false;
font->print(-2, -3, false, "NitroFS init failed...", Alignment::right);
font->update(false);
for (int i = 0; i < 30; i++)

View File

@ -41,8 +41,7 @@ FLASHCARD_LABEL=[fat:] FLASHCARD (%s)
RAMDRIVE_LABEL=[ram:] RAMDRIVE
SYSNAND_LABEL=[nand:] SYSNAND
NITROFS_LABEL=[nitro:] NDS GAME IMAGE
FAT_LABEL_NAMED=[nitro:] FAT IMAGE (%s)
FAT_LABEL=[nitro:] FAT IMAGE
FAT_LABEL=[img:] FAT IMAGE (%s)
GBA_GAMECART=GBA GAMECART (%s)
NDS_GAMECARD=NDS GAMECARD (%s)