GodMode9Nrio/arm9/source/driveMenu.cpp
ApacheThunder 27d6c3c6c1 Further optimizations...
* Screenshot feature removed to free up more ram.
* SCFG register changes on startup moved to dedicated function run from
ITCM memory. This should hopefully reduce instances where program hangs
at startup. Bootstarp is still provided incase some people still have
that problem.
2024-03-20 16:10:48 -05:00

312 lines
10 KiB
C++

/*-----------------------------------------------------------------
Copyright (C) 2005 - 2013
Michael "Chishm" Chisholm
Dave "WinterMute" Murphy
Claudio "sverx"
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
------------------------------------------------------------------*/
#include <nds.h>
#include <nds/arm9/dldi.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include "main.h"
#include "config.h"
#include "date.h"
#include "driveOperations.h"
#include "fileOperations.h"
#include "font.h"
#include "language.h"
#include "my_sd.h"
#include "read_card.h"
#include "startMenu.h"
#define ENTRIES_START_ROW 1
#define ENTRY_PAGE_LENGTH 10
enum class DriveMenuOperation {
none,
sdCard,
flashcard,
nitroFs,
fatImage
};
bool flashcardMountSkipped = true;
static bool flashcardMountRan = true;
static int dmCursorPosition = 0;
static std::vector<DriveMenuOperation> dmOperations;
char romTitle[2][13] = {0};
u32 romSize[2], romSizeTrimmed;
static u8 stored_SCFG_MC = 0;
extern bool arm7SCFGLocked;
void dm_drawTopScreen(void) {
font->clear(true);
// Top bar
font->printf(firstCol, 0, true, alignStart, Palette::blackGreen, "%*c", 256 / font->width(), ' ');
font->print(firstCol, 0, true, STR_ROOT, alignStart, Palette::blackGreen);
// Print time
font->print(lastCol, 0, true, RetTime(), alignEnd, Palette::blackGreen);
if (dmOperations.size() == 0) {
font->print(firstCol, 1, true, STR_NO_DRIVES_FOUND, alignStart);
} else {
for (int i = 0; i < (int)dmOperations.size(); i++) {
Palette pal = dmCursorPosition == i ? Palette::white : Palette::gray;
switch(dmOperations[i]) {
case DriveMenuOperation::sdCard:
font->printf(firstCol, i + 1, true, alignStart, pal, STR_SDCARD_LABEL.c_str(), sdLabel[0] == 0 ? STR_UNTITLED.c_str() : sdLabel);
if(!driveWritable(Drive::sdCard))
font->print(lastCol, i + 1, true, "[R]", alignEnd, pal);
break;
case DriveMenuOperation::flashcard:
font->printf(firstCol, i + 1, true, alignStart, pal, STR_FLASHCARD_LABEL.c_str(), fatLabel[0] == 0 ? STR_UNTITLED.c_str() : fatLabel);
if(!driveWritable(Drive::flashcard))
font->print(lastCol, i + 1, true, "[R]", alignEnd, pal);
break;
case DriveMenuOperation::nitroFs:
font->print(firstCol, i + 1, true, STR_NITROFS_LABEL, alignStart, pal);
font->print(lastCol, i + 1, true, "[R]", alignEnd, pal);
break;
case DriveMenuOperation::fatImage:
font->printf(firstCol, i + 1, true, alignStart, pal, STR_FAT_LABEL.c_str(), imgLabel[0] == 0 ? STR_UNTITLED.c_str() : imgLabel);
font->print(lastCol, i + 1, true, "[R]", alignEnd, pal);
break;
case DriveMenuOperation::none:
break;
}
}
}
font->update(true);
}
void dm_drawBottomScreen(void) {
font->clear(false);
int row = -1;
if (!isDSiMode() && isRegularDS) {
font->print(firstCol, row--, false, STR_POWERTEXT_DS, alignStart);
} else if (is3DS) {
font->print(firstCol, row--, false, STR_HOMETEXT, alignStart);
font->print(firstCol, row--, false, STR_POWERTEXT_3DS, alignStart);
} else {
font->print(firstCol, row--, false, STR_POWERTEXT, alignStart);
}
font->print(firstCol, row--, false, STR_START_START_MENU, alignStart);
if ((isDSiMode() && memcmp(io_dldi_data->friendlyName, "Default", 7) == 0) || sdMountedDone) {
font->print(firstCol, row--, false, sdMounted ? STR_UNMOUNT_SDCARD : STR_REMOUNT_SDCARD, alignStart);
} else if(flashcardMounted) {
font->print(firstCol, row--, false, STR_UNMOUNT_FLASHCARD, alignStart);
}
if(dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs || dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage) {
font->print(firstCol, row--, false, STR_IMAGETEXT, alignStart);
}
font->print(firstCol, row--, false, titleName, alignStart);
switch(dmOperations[dmCursorPosition]) {
case DriveMenuOperation::sdCard:
font->printf(firstCol, 0, false, alignStart, Palette::white, STR_SDCARD_LABEL.c_str(), sdLabel[0] == 0 ? STR_UNTITLED.c_str() : sdLabel);
font->printf(firstCol, 1, false, alignStart, Palette::white, STR_SD_FAT.c_str(), getBytes(sdSize).c_str());
font->printf(firstCol, 2, false, alignStart, Palette::white, STR_N_FREE.c_str(), getBytes(driveSizeFree(Drive::sdCard)).c_str());
break;
case DriveMenuOperation::flashcard:
font->printf(firstCol, 0, false, alignStart, Palette::white, STR_FLASHCARD_LABEL.c_str(), fatLabel[0] == 0 ? STR_UNTITLED.c_str() : fatLabel);
font->printf(firstCol, 1, false, alignStart, Palette::white, STR_SLOT1_FAT.c_str(), getBytes(fatSize).c_str());
font->printf(firstCol, 2, false, alignStart, Palette::white, STR_N_FREE.c_str(), getBytes(driveSizeFree(Drive::flashcard)).c_str());
break;
case DriveMenuOperation::nitroFs:
font->print(firstCol, 0, false, STR_NITROFS_LABEL, alignStart);
font->print(firstCol, 1, false, STR_GAME_VIRTUAL, alignStart);
break;
case DriveMenuOperation::fatImage:
font->printf(firstCol, 0, false, alignStart, Palette::white, STR_FAT_LABEL.c_str(), imgLabel[0] == 0 ? STR_UNTITLED.c_str() : imgLabel);
font->printf(firstCol, 1, false, alignStart, Palette::white, STR_FAT_IMAGE.c_str(), getBytes(imgSize).c_str());
font->printf(firstCol, 2, false, alignStart, Palette::white, STR_N_FREE.c_str(), getBytes(driveSizeFree(Drive::fatImg)).c_str());
break;
case DriveMenuOperation::none:
break;
}
font->update(false);
}
void driveMenu (void) {
int pressed = 0;
int held = 0;
while (true) {
dmOperations.clear();
if (sdMounted && !sdRemoved)
dmOperations.push_back(DriveMenuOperation::sdCard);
if (flashcardMounted && !driveRemoved(Drive::flashcard))
dmOperations.push_back(DriveMenuOperation::flashcard);
if (imgMounted)
dmOperations.push_back(DriveMenuOperation::fatImage);
if (nitroMounted)
dmOperations.push_back(DriveMenuOperation::nitroFs);
if (romTitle[1][0] != 0) {
romTitle[1][0] = 0;
romSize[1] = 0;
}
if (romTitle[0][0] != 0) {
romTitle[0][0] = 0;
romSizeTrimmed = romSize[0] = 0;
}
if(dmCursorPosition >= (int)dmOperations.size())dmCursorPosition = dmOperations.size() - 1;
dm_drawBottomScreen();
dm_drawTopScreen();
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 {
scanKeys();
pressed = keysDownRepeat();
held = keysHeld();
swiWaitForVBlank();
if (isDSiMode()) {
if ((REG_SCFG_MC != stored_SCFG_MC) || (flashcardMounted && driveRemoved(Drive::flashcard)))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 | config->screenSwapKey())));
if(dmOperations.size() != 0) {
if (pressed & KEY_UP) {
dmCursorPosition -= 1;
if(dmCursorPosition < 0)
dmCursorPosition = dmOperations.size() - 1;
} else if (pressed & KEY_DOWN) {
dmCursorPosition += 1;
if(dmCursorPosition >= (int)dmOperations.size())
dmCursorPosition = 0;
} else if(pressed & KEY_LEFT) {
dmCursorPosition -= ENTRY_PAGE_LENGTH;
if(dmCursorPosition < 0)
dmCursorPosition = 0;
} else if(pressed & KEY_RIGHT) {
dmCursorPosition += ENTRY_PAGE_LENGTH;
if(dmCursorPosition >= (int)dmOperations.size())
dmCursorPosition = dmOperations.size() - 1;
}
}
if (pressed & KEY_A) {
if (dmOperations[dmCursorPosition] == DriveMenuOperation::sdCard && sdMounted) {
currentDrive = Drive::sdCard;
chdir("sd:/");
screenMode = 1;
break;
} else if (dmOperations[dmCursorPosition] == DriveMenuOperation::flashcard && flashcardMounted) {
currentDrive = Drive::flashcard;
chdir("fat:/");
screenMode = 1;
break;
} else if (dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs && nitroMounted) {
if ((sdMounted && nitroCurrentDrive == Drive::sdCard)
|| (flashcardMounted && nitroCurrentDrive == Drive::flashcard)
|| (imgMounted && nitroCurrentDrive == Drive::fatImg))
{
currentDrive = Drive::nitroFS;
chdir("nitro:/");
screenMode = 1;
break;
}
} if (dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage && imgMounted) {
if ((sdMounted && imgCurrentDrive == Drive::sdCard) || (flashcardMounted && imgCurrentDrive == Drive::flashcard)) {
currentDrive = Drive::fatImg;
chdir("img:/");
screenMode = 1;
break;
}
}
}
// Unmount/Remount FAT image
if ((held & KEY_R) && (pressed & KEY_X)) {
if (dmOperations[dmCursorPosition] == DriveMenuOperation::nitroFs) {
currentDrive = Drive::nitroFS;
chdir("nitro:/");
nitroUnmount();
} else if (dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage) {
currentDrive = Drive::fatImg;
chdir("img:/");
imgUnmount();
}
}
// Unmount/Remount SD card
if ((held & KEY_R) && (pressed & KEY_B)) {
if ((isDSiMode() && memcmp(io_dldi_data->friendlyName, "Default", 7) == 0) || sdMountedDone) {
if (sdMounted) {
currentDrive = Drive::sdCard;
chdir("sd:/");
sdUnmount();
} else if(!sdRemoved) {
sdMounted = sdMount();
}
} else {
if (flashcardMounted) {
currentDrive = Drive::flashcard;
chdir("fat:/");
flashcardUnmount();
}
}
}
if (pressed & KEY_START)startMenu();
// Swap screens
if (pressed & config->screenSwapKey()) {
screenSwapped = !screenSwapped;
screenSwapped ? lcdMainOnBottom() : lcdMainOnTop();
}
if (isDSiMode() && !flashcardMountSkipped) {
if (driveRemoved(Drive::flashcard)) {
if (flashcardMounted) {
flashcardUnmount();
flashcardMountRan = false;
}
} else if (!flashcardMountRan) {
flashcardMountRan = true;
flashcardMounted = flashcardMount(); // Try to mount flashcard
}
}
}
}