diff --git a/compile.sh b/compile.sh old mode 100644 new mode 100755 diff --git a/quickmenu/arm9/source/common/dsimenusettings.cpp b/quickmenu/arm9/source/common/dsimenusettings.cpp index d1c470c75b..e0813790e0 100644 --- a/quickmenu/arm9/source/common/dsimenusettings.cpp +++ b/quickmenu/arm9/source/common/dsimenusettings.cpp @@ -18,20 +18,20 @@ TWLSettings::TWLSettings() wifiLed = true; sdRemoveDetect = true; showMicroSd = false; - gbar2DldiAccess = false; + gbar2DldiAccess = false; showMainMenu = true; theme = 0; subtheme = 0; dsiMusic = 1; - showNds = true; - showRvid = true; - showNes = true; - showGb = true; - showSmsGg = true; - showMd = true; - showSnes = true; - updateRecentlyPlayedList = true; + showNds = true; + showRvid = true; + showNes = true; + showGb = true; + showSmsGg = true; + showMd = true; + showSnes = true; + updateRecentlyPlayedList = true; sortMethod = 0; showDirectories = true; showHidden = false; @@ -42,9 +42,9 @@ TWLSettings::TWLSettings() secondaryAccess = false; previousUsedDevice = false; secondaryDevice = false; - fcSaveOnSd = false; + fcSaveOnSd = false; - flashcard = EDSTTClone; + flashcard = 0; slot1LaunchMethod = EDirect; diff --git a/quickmenu/arm9/source/common/dsimenusettings.h b/quickmenu/arm9/source/common/dsimenusettings.h index b785c861c8..471b195abf 100644 --- a/quickmenu/arm9/source/common/dsimenusettings.h +++ b/quickmenu/arm9/source/common/dsimenusettings.h @@ -30,24 +30,28 @@ class TWLSettings }; /* - 0: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE - 1: R4DS (Original Non-SDHC version)/ M3 Simply - 2: R4iDSN/R4i Gold RTS/R4 Ultra - 3: Acekard 2(i)/Galaxy Eagle/M3DS Real - 4: Acekard RPG - 5: Ace 3DS+/Gateway Blue Card/R4iTT - 6: SuperCard DSTWO + 0: Unknown/None + 1: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE + 2: R4DS (Original Non-SDHC version)/ M3 Simply + 3: R4iDSN/R4i Gold RTS/R4 Ultra + 4: Acekard 2(i)/Galaxy Eagle/M3DS Real + 5: Acekard RPG + 6: Ace 3DS+/Gateway Blue Card/R4iTT + 7: SuperCard DSTWO + 8: CycloDS iEvolution */ enum TFlashCard { - EDSTTClone = 0, - ER4Original = 1, - ER4iGoldClone = 2, - EAcekard2i = 3, - EAcekardRPG = 4, - EGatewayBlue = 5, - ESupercardDSTWO = 6 + EUnknown = 0, + EDSTTClone = 1, + ER4Original = 2, + ER4iGoldClone = 3, + EAcekard2i = 4, + EAcekardRPG = 5, + EGatewayBlue = 6, + ESupercardDSTWO = 7, + ECycloDSi = 8 }; // Do not reorder these, just add to the end diff --git a/quickmenu/arm9/source/main.cpp b/quickmenu/arm9/source/main.cpp index 3ac9136bfb..3cfd29d28e 100644 --- a/quickmenu/arm9/source/main.cpp +++ b/quickmenu/arm9/source/main.cpp @@ -1,2672 +1,2684 @@ -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "date.h" -#include "fileCopy.h" -#include "nand/nandio.h" - -#include "graphics/graphics.h" - -#include "common/tonccpy.h" -#include "common/nitrofs.h" -#include "read_card.h" -#include "flashcard.h" -#include "ndsheaderbanner.h" -#include "gbaswitch.h" -#include "nds_loader_arm9.h" -#include "perGameSettings.h" -#include "errorScreen.h" - -#include "iconTitle.h" -#include "graphics/fontHandler.h" - -#include "common/inifile.h" -#include "tool/stringtool.h" - -#include "language.h" - -#include "cheat.h" -#include "crc.h" - -#include "soundbank.h" -#include "soundbank_bin.h" - -#include "donorMap.h" -#include "mpuMap.h" -#include "speedBumpExcludeMap.h" -#include "saveMap.h" - -#include "sr_data_srllastran.h" // For rebooting into the game - -#define gbamodeText "Start GBA game." -#define featureUnavailableText "This feature is unavailable." - -bool useTwlCfg = false; - -bool whiteScreen = true; -bool fadeType = false; // false = out, true = in -bool fadeSpeed = true; // false = slow (for DSi launch effect), true = fast -bool controlTopBright = true; -bool controlBottomBright = true; -bool widescreenEffects = false; -int fps = 60; -int colorMode = 0; -int blfLevel = 0; - -bool cardEjected = false; -static bool cardRefreshed = false; - -extern void ClearBrightness(); -extern int boxArtType[2]; - -const char* settingsinipath = "sd:/_nds/TWiLightMenu/settings.ini"; -const char* bootstrapinipath = "sd:/_nds/nds-bootstrap.ini"; - -std::string romPath[2]; -std::string dsiWareSrlPath; -std::string dsiWarePubPath; -std::string dsiWarePrvPath; - -const char *charUnlaunchBg; -std::string unlaunchBg = "default.gif"; -bool removeLauncherPatches = true; - -const char *unlaunchAutoLoadID = "AutoLoadInfo"; -static char hiyaNdsPath[14] = {'s','d','m','c',':','/','h','i','y','a','.','d','s','i'}; -char unlaunchDevicePath[256]; - -static char pictochatPath[256]; -static char dlplayPath[256]; - -bool arm7SCFGLocked = false; -int consoleModel = 0; -/* 0 = Nintendo DSi (Retail) - 1 = Nintendo DSi (Dev/Panda) - 2 = Nintendo 3DS - 3 = New Nintendo 3DS */ -bool isRegularDS = true; -bool isDSLite = false; - -extern bool showdialogbox; - -bool extention(const std::string& filename, const char* ext) { - if(strcasecmp(filename.c_str() + filename.size() - strlen(ext), ext)) { - return false; - } else { - return true; - } -} - -/** - * Remove trailing slashes from a pathname, if present. - * @param path Pathname to modify. - */ -void RemoveTrailingSlashes(std::string& path) -{ - while (!path.empty() && path[path.size()-1] == '/') { - path.resize(path.size()-1); - } -} - -/** - * Remove trailing spaces from a cheat code line, if present. - * @param path Code line to modify. - */ -/*static void RemoveTrailingSpaces(std::string& code) -{ - while (!code.empty() && code[code.size()-1] == ' ') { - code.resize(code.size()-1); - } -}*/ - -std::string romfolder[2]; - -// These are used by flashcard functions and must retain their trailing slash. -static const std::string slashchar = "/"; -static const std::string woodfat = "fat0:/"; -static const std::string dstwofat = "fat1:/"; - -int mpuregion = 0; -int mpusize = 0; -bool ceCached = true; - -bool applaunch = false; -bool showCursor = true; -bool startMenu = false; -bool gotosettings = false; - -bool slot1Launched = false; -int launchType[2] = {0}; // 0 = Slot-1, 1 = SD/Flash card, 2 = SD/Flash card (Direct boot), 3 = DSiWare, 4 = NES, 5 = (S)GB(C), 6 = SMS/GG -int slot1LaunchMethod = 1; // 0 == Reboot, 1 == Direct, 2 == Unlaunch -bool useBootstrap = true; -bool bootstrapFile = false; -bool homebrewBootstrap = false; -bool homebrewHasWide = false; -bool show12hrClock = true; -//bool snesEmulator = true; -bool smsGgInRam = false; -bool fcSaveOnSd = false; -bool wideScreen = false; - -bool pictochatFound = false; -bool dlplayFound = false; -bool pictochatReboot = false; -bool dlplayReboot = false; -bool sdRemoveDetect = true; -bool useGbarunner = false; -bool gbar2DldiAccess = false; // false == ARM9, true == ARM7 -int theme = 0; -int subtheme = 0; -int showMd = 3; -int cursorPosition[2] = {0}; -int startMenu_cursorPosition = 0; -int pagenum[2] = {0}; -bool showDirectories = true; -int showBoxArt = 1 + isDSiMode(); -bool animateDsiIcons = false; -int launcherApp = -1; -int sysRegion = -1; - -int guiLanguage = -1; -int gameLanguage = -1; -int titleLanguage = -1; -bool boostCpu = false; // false == NTR, true == TWL -bool boostVram = false; -int bstrap_dsiMode = 0; -int bstrap_extendedMemory = 0; -bool forceSleepPatch = false; -bool dsiWareBooter = false; - -void LoadSettings(void) { - useBootstrap = isDSiMode(); - - // GUI - CIniFile settingsini( settingsinipath ); - - // UI settings. - consoleModel = settingsini.GetInt("SRLOADER", "CONSOLE_MODEL", 0); - - showMd = settingsini.GetInt("SRLOADER", "SHOW_MDGEN", showMd); - - // Customizable UI settings. - fps = settingsini.GetInt("SRLOADER", "FRAME_RATE", fps); - colorMode = settingsini.GetInt("SRLOADER", "COLOR_MODE", 0); - blfLevel = settingsini.GetInt("SRLOADER", "BLUE_LIGHT_FILTER_LEVEL", 0); - guiLanguage = settingsini.GetInt("SRLOADER", "LANGUAGE", -1); - titleLanguage = settingsini.GetInt("SRLOADER", "TITLELANGUAGE", titleLanguage); - sdRemoveDetect = settingsini.GetInt("SRLOADER", "SD_REMOVE_DETECT", 1); - useGbarunner = settingsini.GetInt("SRLOADER", "USE_GBARUNNER2", 0); - if (!isRegularDS) useGbarunner = true; - gbar2DldiAccess = settingsini.GetInt("SRLOADER", "GBAR2_DLDI_ACCESS", gbar2DldiAccess); - theme = settingsini.GetInt("SRLOADER", "THEME", 0); - subtheme = settingsini.GetInt("SRLOADER", "SUB_THEME", 0); - showDirectories = settingsini.GetInt("SRLOADER", "SHOW_DIRECTORIES", 1); - showBoxArt = settingsini.GetInt("SRLOADER", "SHOW_BOX_ART", showBoxArt); - animateDsiIcons = settingsini.GetInt("SRLOADER", "ANIMATE_DSI_ICONS", 0); - if (consoleModel < 2) { - launcherApp = settingsini.GetInt("SRLOADER", "LAUNCHER_APP", launcherApp); - } - - previousUsedDevice = settingsini.GetInt("SRLOADER", "PREVIOUS_USED_DEVICE", previousUsedDevice); - secondaryDevice = bothSDandFlashcard() ? settingsini.GetInt("SRLOADER", "SECONDARY_DEVICE", secondaryDevice) : flashcardFound(); - fcSaveOnSd = settingsini.GetInt("SRLOADER", "FC_SAVE_ON_SD", fcSaveOnSd); - - slot1LaunchMethod = settingsini.GetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); - useBootstrap = settingsini.GetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); - bootstrapFile = settingsini.GetInt("SRLOADER", "BOOTSTRAP_FILE", 0); - //snesEmulator = settingsini.GetInt("SRLOADER", "SNES_EMULATOR", snesEmulator); - smsGgInRam = settingsini.GetInt("SRLOADER", "SMS_GG_IN_RAM", smsGgInRam); - - show12hrClock = settingsini.GetInt("SRLOADER", "SHOW_12H_CLOCK", show12hrClock); - - unlaunchBg = settingsini.GetString("SRLOADER", "UNLAUNCH_BG", unlaunchBg); - charUnlaunchBg = unlaunchBg.c_str(); - removeLauncherPatches = settingsini.GetInt("SRLOADER", "UNLAUNCH_PATCH_REMOVE", removeLauncherPatches); - - // Default nds-bootstrap settings - gameLanguage = settingsini.GetInt("NDS-BOOTSTRAP", "LANGUAGE", -1); - boostCpu = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_CPU", 0); - boostVram = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); - bstrap_dsiMode = settingsini.GetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); - bstrap_extendedMemory = settingsini.GetInt("NDS-BOOTSTRAP", "EXTENDED_MEMORY", 0); - - forceSleepPatch = settingsini.GetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", 0); - dsiWareBooter = settingsini.GetInt("SRLOADER", "DSIWARE_BOOTER", dsiWareBooter); - - dsiWareSrlPath = settingsini.GetString("SRLOADER", "DSIWARE_SRL", dsiWareSrlPath); - dsiWarePubPath = settingsini.GetString("SRLOADER", "DSIWARE_PUB", dsiWarePubPath); - dsiWarePrvPath = settingsini.GetString("SRLOADER", "DSIWARE_PRV", dsiWarePrvPath); - launchType[0] = settingsini.GetInt("SRLOADER", "LAUNCH_TYPE", launchType[0]); - launchType[1] = settingsini.GetInt("SRLOADER", "SECONDARY_LAUNCH_TYPE", launchType[1]); - romPath[0] = settingsini.GetString("SRLOADER", "ROM_PATH", romPath[0]); - romPath[1] = settingsini.GetString("SRLOADER", "SECONDARY_ROM_PATH", romPath[1]); - - wideScreen = settingsini.GetInt("SRLOADER", "WIDESCREEN", wideScreen); -} - -void SaveSettings(void) { - // GUI - CIniFile settingsini( settingsinipath ); - - // UI settings. - if (!gotosettings) { - settingsini.SetString("SRLOADER", "DSIWARE_SRL", dsiWareSrlPath); - settingsini.SetString("SRLOADER", "DSIWARE_PUB", dsiWarePubPath); - settingsini.SetString("SRLOADER", "DSIWARE_PRV", dsiWarePrvPath); - settingsini.SetInt("SRLOADER", "SLOT1_LAUNCHED", slot1Launched); - settingsini.SetInt("SRLOADER", "LAUNCH_TYPE", launchType[0]); - settingsini.SetInt("SRLOADER", "SECONDARY_LAUNCH_TYPE", launchType[1]); - settingsini.SetInt("SRLOADER", "HOMEBREW_BOOTSTRAP", homebrewBootstrap); - settingsini.SetInt("SRLOADER", "HOMEBREW_HAS_WIDE", homebrewHasWide); - } - //settingsini.SetInt("SRLOADER", "THEME", theme); - //settingsini.SetInt("SRLOADER", "SUB_THEME", subtheme); - settingsini.SaveIniFile(settingsinipath); -} - -bool isDSPhat(void) { - return (isRegularDS && !isDSLite); -} - -bool useBackend = false; - -using namespace std; - -bool showbubble = false; -bool showSTARTborder = false; - -bool titleboxXmoveleft = false; -bool titleboxXmoveright = false; - -bool applaunchprep = false; - -int spawnedtitleboxes = 0; - -//char usernameRendered[10]; -//bool usernameRenderedDone = false; - -touchPosition touch; - -//--------------------------------------------------------------------------------- -void stop (void) { -//--------------------------------------------------------------------------------- - while (1) { - swiWaitForVBlank(); - } -} - -/** - * Set donor SDK version for a specific game. - */ -int SetDonorSDK(const char* filename) { - FILE *f_nds_file = fopen(filename, "rb"); - - char game_TID[5]; - grabTID(f_nds_file, game_TID); - fclose(f_nds_file); - game_TID[4] = 0; - game_TID[3] = 0; - - for (auto i : donorMap) { - if (i.first == 5 && game_TID[0] == 'V') - return 5; - - if (i.second.find(game_TID) != i.second.cend()) - return i.first; - } - - return 0; -} - -/** - * Set MPU settings for a specific game. - */ -void SetMPUSettings(const char* filename) { - FILE *f_nds_file = fopen(filename, "rb"); - - char game_TID[5]; - fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); - fread(game_TID, 1, 4, f_nds_file); - game_TID[4] = 0; - game_TID[3] = 0; - fclose(f_nds_file); - - scanKeys(); - int pressed = keysHeld(); - - if (pressed & KEY_B) { - mpuregion = 1; - } else if (pressed & KEY_X) { - mpuregion = 2; - } else if (pressed & KEY_Y) { - mpuregion = 3; - } else { - mpuregion = 0; - } - - if(pressed & KEY_RIGHT) { - mpusize = 3145728; - } else if(pressed & KEY_LEFT) { - mpusize = 1; - } else { - mpusize = 0; - } - - // Check for games that need an MPU size of 3 MB. - // TODO: If the list gets large enough, switch to bsearch(). - for (unsigned int i = 0; i < sizeof(mpu_3MB_list)/sizeof(mpu_3MB_list[0]); i++) { - if (!memcmp(game_TID, mpu_3MB_list[i], 3)) { - // Found a match. - mpuregion = 1; - mpusize = 3145728; - break; - } - } -} - -/** - * Move nds-bootstrap's cardEngine_arm9 to cached memory region for some games. - */ -void SetSpeedBumpExclude(const char* filename) { - if (!isDSiMode() || (perGameSettings_heapShrink >= 0 && perGameSettings_heapShrink < 2)) { - ceCached = perGameSettings_heapShrink; - return; - } - - FILE *f_nds_file = fopen(filename, "rb"); - - char game_TID[5]; - fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); - fread(game_TID, 1, 4, f_nds_file); - fclose(f_nds_file); - - // TODO: If the list gets large enough, switch to bsearch(). - for (unsigned int i = 0; i < sizeof(sbeList2)/sizeof(sbeList2[0]); i++) { - if (memcmp(game_TID, sbeList2[i], 3) == 0) { - // Found match - ceCached = false; - } - } -} - -/** - * Fix AP for some games. - */ -std::string setApFix(const char *filename) { - remove("fat:/_nds/nds-bootstrap/apFix.ips"); - - bool ipsFound = false; - char ipsPath[256]; - snprintf(ipsPath, sizeof(ipsPath), "%s:/_nds/TWiLightMenu/apfix/%s.ips", sdFound() ? "sd" : "fat", filename); - ipsFound = (access(ipsPath, F_OK) == 0); - - if (!ipsFound) { - FILE *f_nds_file = fopen(filename, "rb"); - - char game_TID[5]; - u16 headerCRC16 = 0; - fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); - fread(game_TID, 1, 4, f_nds_file); - fseek(f_nds_file, offsetof(sNDSHeaderExt, headerCRC16), SEEK_SET); - fread(&headerCRC16, sizeof(u16), 1, f_nds_file); - fclose(f_nds_file); - game_TID[4] = 0; - - snprintf(ipsPath, sizeof(ipsPath), "%s:/_nds/TWiLightMenu/apfix/%s-%X.ips", sdFound() ? "sd" : "fat", game_TID, headerCRC16); - ipsFound = (access(ipsPath, F_OK) == 0); - } - - if (ipsFound) { - if (secondaryDevice && sdFound()) { - mkdir("fat:/_nds", 0777); - mkdir("fat:/_nds/nds-bootstrap", 0777); - fcopy(ipsPath, "fat:/_nds/nds-bootstrap/apFix.ips"); - return "fat:/_nds/nds-bootstrap/apFix.ips"; - } - return ipsPath; - } - - return ""; -} - -/** - * Enable widescreen for some games. - */ -void SetWidescreen(const char *filename) { - remove("/_nds/nds-bootstrap/wideCheatData.bin"); - - bool useWidescreen = (perGameSettings_wideScreen == -1 ? wideScreen : perGameSettings_wideScreen); - - if ((isDSiMode() && arm7SCFGLocked) || consoleModel < 2 || !useWidescreen - || (access("sd:/luma/sysmodules/TwlBg.cxi", F_OK) != 0)) { - homebrewHasWide = false; - return; - } - - bool wideCheatFound = false; - char wideBinPath[256]; - if (launchType[secondaryDevice] == 1) { - snprintf(wideBinPath, sizeof(wideBinPath), "sd:/_nds/TWiLightMenu/widescreen/%s.bin", filename); - wideCheatFound = (access(wideBinPath, F_OK) == 0); - } - - if (slot1Launched) { - // Reset Slot-1 to allow reading card header - sysSetCardOwner (BUS_OWNER_ARM9); - disableSlot1(); - for(int i = 0; i < 25; i++) { swiWaitForVBlank(); } - enableSlot1(); - for(int i = 0; i < 15; i++) { swiWaitForVBlank(); } - - cardReadHeader((uint8*)&ndsCardHeader); - - char game_TID[5]; - tonccpy(game_TID, ndsCardHeader.gameCode, 4); - game_TID[4] = 0; - - snprintf(wideBinPath, sizeof(wideBinPath), "sd:/_nds/TWiLightMenu/widescreen/%s-%X.bin", game_TID, ndsCardHeader.headerCRC16); - wideCheatFound = (access(wideBinPath, F_OK) == 0); - } else if (!wideCheatFound) { - FILE *f_nds_file = fopen(filename, "rb"); - - char game_TID[5]; - u16 headerCRC16 = 0; - fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); - fread(game_TID, 1, 4, f_nds_file); - fseek(f_nds_file, offsetof(sNDSHeaderExt, headerCRC16), SEEK_SET); - fread(&headerCRC16, sizeof(u16), 1, f_nds_file); - fclose(f_nds_file); - game_TID[4] = 0; - - snprintf(wideBinPath, sizeof(wideBinPath), "sd:/_nds/TWiLightMenu/widescreen/%s-%X.bin", game_TID, headerCRC16); - wideCheatFound = (access(wideBinPath, F_OK) == 0); - } - - if (isHomebrew[secondaryDevice]) { - FILE *f_nds_file = fopen(filename, "rb"); - - char game_TID[5]; - u8 romVersion = 0; - fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); - fread(game_TID, 1, 4, f_nds_file); - fseek(f_nds_file, offsetof(sNDSHeaderExt, romversion), SEEK_SET); - fread(&romVersion, sizeof(u8), 1, f_nds_file); - fclose(f_nds_file); - game_TID[4] = 0; - - homebrewHasWide = (game_TID[0] == 'W' || romVersion == 0x57); - return; - } - - if (wideCheatFound) { - const char* resultText1; - const char* resultText2; - mkdir("/_nds", 0777); - mkdir("/_nds/nds-bootstrap", 0777); - if (fcopy(wideBinPath, "/_nds/nds-bootstrap/wideCheatData.bin") == 0) { - return; - } else { - resultText1 = "Failed to copy widescreen"; - resultText2 = "code for the game."; - } - remove("/_nds/nds-bootstrap/wideCheatData.bin"); - int textXpos[2] = {0}; - textXpos[0] = 72; - textXpos[1] = 84; - clearText(); - printSmallCentered(false, textXpos[0], resultText1); - printSmallCentered(false, textXpos[1], resultText2); - fadeType = true; // Fade in from white - for (int i = 0; i < 60 * 3; i++) { - swiWaitForVBlank(); // Wait 3 seconds - } - fadeType = false; // Fade to white - for (int i = 0; i < 25; i++) { - swiWaitForVBlank(); - } - } -} - -char filePath[PATH_MAX]; - -//--------------------------------------------------------------------------------- -void doPause() { -//--------------------------------------------------------------------------------- - // iprintf("Press start...\n"); - // printSmall(false, x, y, "Press start..."); - while(1) { - scanKeys(); - if(keysDown() & KEY_START) - break; - swiWaitForVBlank(); - } - scanKeys(); -} - -mm_sound_effect snd_launch; -mm_sound_effect snd_select; -mm_sound_effect snd_stop; -mm_sound_effect snd_wrong; -mm_sound_effect snd_back; -mm_sound_effect snd_switch; -mm_sound_effect snd_backlight; - -void InitSound() { - mmInitDefaultMem((mm_addr)soundbank_bin); - - mmLoadEffect( SFX_LAUNCH ); - mmLoadEffect( SFX_SELECT ); - mmLoadEffect( SFX_STOP ); - mmLoadEffect( SFX_WRONG ); - mmLoadEffect( SFX_BACK ); - mmLoadEffect( SFX_SWITCH ); - mmLoadEffect( SFX_BACKLIGHT ); - - snd_launch = { - { SFX_LAUNCH } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; - snd_select = { - { SFX_SELECT } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; - snd_stop = { - { SFX_STOP } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; - snd_wrong = { - { SFX_WRONG } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; - snd_back = { - { SFX_BACK } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; - snd_switch = { - { SFX_SWITCH } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; - snd_backlight = { - { SFX_BACKLIGHT } , // id - (int)(1.0f * (1<<10)), // rate - 0, // handle - 255, // volume - 128, // panning - }; -} - -void loadGameOnFlashcard (const char* ndsPath, bool dsGame) { - bool runNds_boostCpu = false; - bool runNds_boostVram = false; - std::string filename = ndsPath; - const size_t last_slash_idx = filename.find_last_of("/"); - if (std::string::npos != last_slash_idx) { - filename.erase(0, last_slash_idx + 1); - } - - loadPerGameSettings(filename); - - if ((REG_SCFG_EXT != 0) && dsGame) { - runNds_boostCpu = perGameSettings_boostCpu == -1 ? boostCpu : perGameSettings_boostCpu; - runNds_boostVram = perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram; - } - if (dsGame) { - // Move .sav outside of "saves" folder for flashcard kernel usage - const char *typeToReplace = ".nds"; - if (extention(filename, ".dsi")) { - typeToReplace = ".dsi"; - } else if (extention(filename, ".ids")) { - typeToReplace = ".ids"; - } else if (extention(filename, ".srl")) { - typeToReplace = ".srl"; - } else if (extention(filename, ".app")) { - typeToReplace = ".app"; - } - - std::string savename = replaceAll(filename, typeToReplace, getSavExtension()); - std::string savenameFc = replaceAll(filename, typeToReplace, ".sav"); - std::string romFolderNoSlash = romfolder[true]; - RemoveTrailingSlashes(romFolderNoSlash); - std::string saveFolder = romFolderNoSlash + "/saves"; - mkdir(saveFolder.c_str(), 0777); - std::string savepath = romFolderNoSlash + "/saves/" + savename; - std::string savepathFc = romFolderNoSlash + "/" + savenameFc; - rename(savepath.c_str(), savepathFc.c_str()); - } - - std::string fcPath; - int err = 0; - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); - fcPath = replaceAll(ndsPath, "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); - err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); - fcPath = replaceAll(ndsPath, "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); - err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { - CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); - fcPath = replaceAll(ndsPath, "fat:/", dstwofat); - fcrompathini.SetString("Dir Info", "fullName", fcPath); - fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); - err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if ((memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0)) { - CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); - fcPath = replaceAll(ndsPath, "fat:/", slashchar); - fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); - fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); - err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } - - char text[32]; - snprintf(text, sizeof(text), "Start failed. Error %i", err); - ClearBrightness(); - printSmall(false, 4, 4, text); - if (err == 0) { - printSmall(false, 4, 20, "Flashcard may be unsupported."); - printSmall(false, 4, 52, "Flashcard name:"); - printSmall(false, 4, 68, io_dldi_data->friendlyName); - } - stop(); -} - -void loadROMselect() -{ - if (!isDSiMode()) { - chdir("fat:/"); - } else if (sdFound()) { - chdir("sd:/"); - } - /*if (theme == 3) - { - runNdsFile("/_nds/TWiLightMenu/akmenu.srldr", 0, NULL, true, false, false, true, true); - } - else */if (theme == 2 || theme == 6) - { - runNdsFile("/_nds/TWiLightMenu/r4menu.srldr", 0, NULL, true, false, false, true, true); - } - else - { - runNdsFile("/_nds/TWiLightMenu/dsimenu.srldr", 0, NULL, true, false, false, true, true); - } -} - -void unlaunchRomBoot(const char* rom) { - char unlaunchDevicePath[256] = {0}; - if (strncmp(rom, "cart:", 5) == 0) { - sprintf(unlaunchDevicePath, "cart:"); - } else { - sprintf(unlaunchDevicePath, "__%s", rom); - unlaunchDevicePath[0] = 's'; - unlaunchDevicePath[1] = 'd'; - unlaunchDevicePath[2] = 'm'; - unlaunchDevicePath[3] = 'c'; - } - - tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); - *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) - *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) - *(u32*)(0x02000810) = 0; // Unlaunch Flags - *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h - *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h - *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) - *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) - toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) - int i2 = 0; - for (int i = 0; i < (int)sizeof(unlaunchDevicePath); i++) { - *(u8*)(0x02000838+i2) = unlaunchDevicePath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) - i2 += 2; - } - while (*(u16*)(0x0200080E) == 0) { // Keep running, so that CRC16 isn't 0 - *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 - } - - DC_FlushAll(); // Make reboot not fail - fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Unlaunch - stop(); -} - -void unlaunchSetHiyaBoot(void) { - tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); - *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) - *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) - *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h - *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h - *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) - *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) - toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) - int i2 = 0; - for (int i = 0; i < 14; i++) { - *(u8*)(0x02000838+i2) = hiyaNdsPath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) - i2 += 2; - } - while (*(u16*)(0x0200080E) == 0) { // Keep running, so that CRC16 isn't 0 - *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 - } -} - -/** - * Reboot into an SD game when in DS mode. - */ -void ntrStartSdGame(void) { - if (consoleModel == 0) { - unlaunchRomBoot("sd:/_nds/TWiLightMenu/resetgame.srldr"); - } else { - tonccpy((u32 *)0x02000300, sr_data_srllastran, 0x020); - DC_FlushAll(); // Make reboot not fail - fifoSendValue32(FIFO_USER_02, 1); - stop(); - } -} - -void dsCardLaunch() { - *(u32*)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag - *(u16*)(0x02000304) = 0x1801; - *(u32*)(0x02000308) = 0x43415254; // "CART" - *(u32*)(0x0200030C) = 0x00000000; - *(u32*)(0x02000310) = 0x43415254; // "CART" - *(u32*)(0x02000314) = 0x00000000; - *(u32*)(0x02000318) = 0x00000013; - *(u32*)(0x0200031C) = 0x00000000; - while (*(u16*)(0x02000306) == 0) { // Keep running, so that CRC16 isn't 0 - *(u16*)(0x02000306) = swiCRC16(0xFFFF, (void*)0x02000308, 0x18); - } - - unlaunchSetHiyaBoot(); - - DC_FlushAll(); // Make reboot not fail - fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher - stop(); -} - -void directCardLaunch() { - /*if (memcmp(ndsCardHeader.gameCode, "ALXX", 4) == 0) { - u16 alxxBannerCrc = 0; - extern u32 arm9StartSig[4]; - cardRead(0x75600, &arm9StartSig, 0x10); - cardRead(0x174602, &alxxBannerCrc, sizeof(u16)); - if ((arm9StartSig[0] == 0xE58D0008 - && arm9StartSig[1] == 0xE1500005 - && arm9StartSig[2] == 0xBAFFFFC5 - && arm9StartSig[3] == 0xE59D100C) - || alxxBannerCrc != 0xBA52) - { - if (sdFound()) { - chdir("sd:/"); - } - int err = runNdsFile ("/_nds/TWiLightMenu/dstwoLaunch.srldr", 0, NULL, true, true, true, boostCpu, boostVram); - char text[32]; - snprintf(text, sizeof(text), "Start failed. Error %i", err); - ClearBrightness(); - printSmall(false, 4, 4, text); - stop(); - } - }*/ - SetWidescreen(NULL); - if (sdFound()) { - chdir("sd:/"); - } - int err = runNdsFile ("/_nds/TWiLightMenu/slot1launch.srldr", 0, NULL, true, true, false, true, true); - char text[32]; - snprintf(text, sizeof(text), "Start failed. Error %i", err); - ClearBrightness(); - printSmall(false, 4, 4, text); - stop(); -} - -void printLastPlayedText(int num) { - printSmallCentered(false, 24, iconYpos[num]+BOX_PY+BOX_PY_spacing2, "Last-played game"); - printSmallCentered(false, 24, iconYpos[num]+BOX_PY+BOX_PY_spacing3, "will appear here."); -} - -void refreshNdsCard() { - if (cardRefreshed) return; - - if (arm7SCFGLocked && showBoxArt) { - loadBoxArt("nitro:/graphics/boxart_unknown.png"); - } else if ((cardInit(true) == 0) && showBoxArt) { - char game_TID[5] = {0}; - tonccpy(&game_TID, ndsCardHeader.gameCode, 4); - - char boxArtPath[256]; - sprintf (boxArtPath, (sdFound() ? "sd:/_nds/TWiLightMenu/boxart/%s.png" : "fat:/_nds/TWiLightMenu/boxart/%s.png"), game_TID); - loadBoxArt(boxArtPath); // Load box art - } else if (showBoxArt) { - loadBoxArt("nitro:/graphics/boxart_unknown.png"); - } - - getGameInfo(1, false, "slot1"); - iconUpdate (1, false, "slot1"); - bnrRomType[1] = 0; - boxArtType[1] = 0; - - // Power off after done retrieving info - disableSlot1(); - - cardRefreshed = true; - cardEjected = false; -} - -void printNdsCartBannerText() { - if (cardEjected) { - printSmallCentered(false, 24, iconYpos[0]+BOX_PY+BOX_PY_spacing2, "There is no Game Card"); - printSmallCentered(false, 24, iconYpos[0]+BOX_PY+BOX_PY_spacing3, "inserted."); - } else if (arm7SCFGLocked) { - printSmallCentered(false, 24, iconYpos[0]+BOX_PY+BOX_PY_spacing1, "Start Game Card"); - } else { - titleUpdate(1, false, "slot1"); - } -} - -void printGbaBannerText() { - printSmallCentered(false, 24, iconYpos[3]+BOX_PY+BOX_PY_spacing1, isRegularDS ? gbamodeText : featureUnavailableText); -} - -//--------------------------------------------------------------------------------- -int main(int argc, char **argv) { -//--------------------------------------------------------------------------------- - - defaultExceptionHandler(); - - useTwlCfg = (REG_SCFG_EXT!=0 && (*(u8*)0x02000400 & 0x0F) && (*(u8*)0x02000401 == 0) && (*(u8*)0x02000402 == 0) && (*(u8*)0x02000404 == 0) && (*(u8*)0x02000448 != 0)); - - extern const DISC_INTERFACE __my_io_dsisd; - - *(u32*)(0x2FFFD0C) = 0x54494D52; // Run reboot timer - fatMountSimple("sd", &__my_io_dsisd); - fatMountSimple("fat", dldiGetInternal()); - bool fatInited = (sdFound() || flashcardFound()); - *(u32*)(0x2FFFD0C) = 0; - chdir(sdFound()&&isDSiMode() ? "sd:/" : "fat:/"); - - // Read user name - /*char *username = (char*)PersonalData->name; - - // text - for (int i = 0; i < 10; i++) { - if (username[i*2] == 0x00) - username[i*2/2] = 0; - else - username[i*2/2] = username[i*2]; - }*/ - - if (!fatInited) { - graphicsInit(); - fontInit(); - whiteScreen = true; - printSmall(false, 64, 32, "fatinitDefault failed!"); - fadeType = true; - stop(); - } - - nitroFSInit("/_nds/TWiLightMenu/mainmenu.srldr"); - - if (access(settingsinipath, F_OK) != 0 && flashcardFound()) { - settingsinipath = "fat:/_nds/TWiLightMenu/settings.ini"; // Fallback to .ini path on flashcard, if not found on SD card, or if SD access is disabled - } - - langInit(); - - std::string filename[2]; - - fifoWaitValue32(FIFO_USER_06); - if (fifoGetValue32(FIFO_USER_03) == 0) arm7SCFGLocked = true; // If TWiLight Menu++ is being run from DSiWarehax or flashcard, then arm7 SCFG is locked. - u16 arm7_SNDEXCNT = fifoGetValue32(FIFO_USER_07); - if (arm7_SNDEXCNT != 0) isRegularDS = false; // If sound frequency setting is found, then the console is not a DS Phat/Lite - isDSLite = fifoGetValue32(FIFO_USER_04); - fifoSendValue32(FIFO_USER_07, 0); - - LoadSettings(); - widescreenEffects = (consoleModel >= 2 && wideScreen && access("sd:/luma/sysmodules/TwlBg.cxi", F_OK) == 0); - - snprintf(pictochatPath, sizeof(pictochatPath), "/_nds/pictochat.nds"); - pictochatFound = (access(pictochatPath, F_OK) == 0); - - if (isDSiMode() && arm7SCFGLocked) { - if (consoleModel < 2 && !pictochatFound) { - pictochatFound = true; - pictochatReboot = true; - } - dlplayFound = true; - dlplayReboot = true; - } else { - bool nandInited = false; - char srcPath[256]; - u8 regions[3] = {0x41, 0x43, 0x4B}; - - if (!pictochatFound && consoleModel == 0) { - for (int i = 0; i < 3; i++) - { - snprintf(pictochatPath, sizeof(pictochatPath), "/title/00030005/484e45%x/content/00000000.app", regions[i]); - if (access(pictochatPath, F_OK) == 0) - { - pictochatFound = true; - break; - } - } - } - if (!pictochatFound && isDSiMode() && sdFound() && consoleModel == 0) { - if (!nandInited) { - fatMountSimple("nand", &io_dsi_nand); - nandInited = true; - } - if (access("nand:/", F_OK) == 0) { - for (int i = 0; i < 3; i++) - { - snprintf(srcPath, sizeof(srcPath), "nand:/title/00030005/484e45%x/content/00000000.app", regions[i]); - if (access(srcPath, F_OK) == 0) - { - snprintf(pictochatPath, sizeof(pictochatPath), "/_nds/pictochat.nds"); - remove(pictochatPath); - fcopy(srcPath, pictochatPath); // Copy from NAND - pictochatFound = true; - break; - } - } - } - } - - snprintf(dlplayPath, sizeof(dlplayPath), "/_nds/dlplay.nds"); - dlplayFound = (access(dlplayPath, F_OK) == 0); - if (!dlplayFound && consoleModel == 0) { - for (int i = 0; i < 3; i++) - { - snprintf(dlplayPath, sizeof(dlplayPath), "/title/00030005/484e44%x/content/00000000.app", regions[i]); - if (access(dlplayPath, F_OK) == 0) { - dlplayFound = true; - break; - } else if (regions[i] != 0x43 && regions[i] != 0x4B) { - snprintf(dlplayPath, sizeof(dlplayPath), "/title/00030005/484e4441/content/00000001.app"); - if (access(dlplayPath, F_OK) == 0) { - dlplayFound = true; - break; - } - } - } - } - if (!dlplayFound && isDSiMode() && sdFound() && consoleModel == 0) { - if (!nandInited) { - fatMountSimple("nand", &io_dsi_nand); - nandInited = true; - } - if (access("nand:/", F_OK) == 0) { - for (int i = 0; i < 3; i++) - { - snprintf(srcPath, sizeof(srcPath), "nand:/title/00030005/484e44%x/content/00000000.app", regions[i]); - if (access(srcPath, F_OK) == 0) { - snprintf(dlplayPath, sizeof(dlplayPath), "/_nds/dlplay.nds"); - remove(dlplayPath); - fcopy(srcPath, dlplayPath); // Copy from NAND - dlplayFound = true; - break; - } else if (regions[i] != 0x43 && regions[i] != 0x4B) { - snprintf(srcPath, sizeof(srcPath), "nand:/title/00030005/484e4441/content/00000001.app"); - if (access(srcPath, F_OK) == 0) { - snprintf(dlplayPath, sizeof(dlplayPath), "/_nds/dlplay.nds"); - remove(dlplayPath); - fcopy(srcPath, dlplayPath); // Copy from NAND - dlplayFound = true; - break; - } - } - } - } - } - if (!dlplayFound && consoleModel >= 2) { - dlplayFound = true; - dlplayReboot = true; - } - } - - if (isDSiMode() && sdFound() && consoleModel < 2 && launcherApp != -1) { - u8 setRegion = 0; - if (sysRegion == -1) { - // Determine SysNAND region by searching region of System Settings on SDNAND - char tmdpath[256]; - for (u8 i = 0x41; i <= 0x5A; i++) - { - snprintf(tmdpath, sizeof(tmdpath), "sd:/title/00030015/484e42%x/content/title.tmd", i); - if (access(tmdpath, F_OK) == 0) - { - setRegion = i; - break; - } - } - } else { - switch(sysRegion) { - case 0: - default: - setRegion = 0x4A; // JAP - break; - case 1: - setRegion = 0x45; // USA - break; - case 2: - setRegion = 0x50; // EUR - break; - case 3: - setRegion = 0x55; // AUS - break; - case 4: - setRegion = 0x43; // CHN - break; - case 5: - setRegion = 0x4B; // KOR - break; - } - } - - snprintf(unlaunchDevicePath, sizeof(unlaunchDevicePath), "nand:/title/00030017/484E41%x/content/0000000%i.app", setRegion, launcherApp); - } - - graphicsInit(); - fontInit(); - - iconTitleInit(); - - InitSound(); - - keysSetRepeat(25,5); - - srand(time(NULL)); - - bool menuButtonPressed = false; - - if (flashcardFound()) { - // Move .sav back to "saves" folder - std::string filename = romPath[true]; - const size_t last_slash_idx = filename.find_last_of("/"); - if (std::string::npos != last_slash_idx) { - filename.erase(0, last_slash_idx + 1); - } - - loadPerGameSettings(filename); - - const char *typeToReplace = ".nds"; - if (extention(filename, ".dsi")) { - typeToReplace = ".dsi"; - } else if (extention(filename, ".ids")) { - typeToReplace = ".ids"; - } else if (extention(filename, ".srl")) { - typeToReplace = ".srl"; - } else if (extention(filename, ".app")) { - typeToReplace = ".app"; - } - - std::string savename = replaceAll(filename, typeToReplace, getSavExtension()); - std::string savenameFc = replaceAll(filename, typeToReplace, ".sav"); - std::string romFolderNoSlash = romfolder[true]; - RemoveTrailingSlashes(romFolderNoSlash); - std::string savepath = romFolderNoSlash + "/saves/" + savename; - std::string savepathFc = romFolderNoSlash + "/" + savenameFc; - if (access(savepathFc.c_str(), F_OK) == 0) { - rename(savepathFc.c_str(), savepath.c_str()); - } - } - - if (consoleModel < 2 - && previousUsedDevice - && bothSDandFlashcard() - && launchType[previousUsedDevice] == 3 - && !dsiWareBooter - && ( - (access(dsiWarePubPath.c_str(), F_OK) == 0 && extention(dsiWarePubPath.c_str(), ".pub")) - || (access(dsiWarePrvPath.c_str(), F_OK) == 0 && extention(dsiWarePrvPath.c_str(), ".prv")) - ) - ) { - controlTopBright = false; - whiteScreen = true; - fadeType = true; // Fade in from white - printSmallCentered(false, 24, "If this takes a while, close and open"); - printSmallCentered(false, 38, "the console's lid."); - printSmallCentered(false, 86, "Now copying data..."); - printSmallCentered(false, 100, "Do not turn off the power."); - for (int i = 0; i < 30; i++) swiWaitForVBlank(); - if (access(dsiWarePubPath.c_str(), F_OK) == 0) { - fcopy("sd:/_nds/TWiLightMenu/tempDSiWare.pub", dsiWarePubPath.c_str()); - } - if (access(dsiWarePrvPath.c_str(), F_OK) == 0) { - fcopy("sd:/_nds/TWiLightMenu/tempDSiWare.prv", dsiWarePrvPath.c_str()); - } - fadeType = false; // Fade to white - for (int i = 0; i < 30; i++) swiWaitForVBlank(); - clearText(false); - whiteScreen = false; - controlTopBright = true; - } - - topBgLoad(); - bottomBgLoad(); - - bool romFound[2] = {false}; - - // SD card - if (sdFound() && romPath[0] != "" && access(romPath[0].c_str(), F_OK) == 0) { - romFound[0] = true; - - romfolder[0] = romPath[0]; - while (!romfolder[0].empty() && romfolder[0][romfolder[0].size()-1] != '/') { - romfolder[0].resize(romfolder[0].size()-1); - } - chdir(romfolder[0].c_str()); - - filename[0] = romPath[0]; - const size_t last_slash_idx = filename[0].find_last_of("/"); - if (std::string::npos != last_slash_idx) - { - filename[0].erase(0, last_slash_idx + 1); - } - - if (extention(filename[0], ".nds") || extention(filename[0], ".dsi") || extention(filename[0], ".ids") || extention(filename[0], ".app") || extention(filename[0], ".srl") || extention(filename[0], ".argv")) { - getGameInfo(0, false, filename[0].c_str()); - iconUpdate (0, false, filename[0].c_str()); - bnrRomType[0] = 0; - boxArtType[0] = 0; - } else if (extention(filename[0], ".plg") || extention(filename[0], ".rvid") || extention(filename[0], ".mp4") || extention(filename[0], ".a26") || extention(filename[0], ".pce")) { - bnrRomType[0] = 9; - boxArtType[0] = 0; - } else if (extention(filename[0], ".gba")) { - bnrRomType[0] = 1; - boxArtType[0] = 1; - } else if (extention(filename[0], ".gb") || extention(filename[0], ".sgb")) { - bnrRomType[0] = 2; - boxArtType[0] = 1; - } else if (extention(filename[0], ".gbc")) { - bnrRomType[0] = 3; - boxArtType[0] = 1; - } else if (extention(filename[0], ".nes")) { - bnrRomType[0] = 4; - boxArtType[0] = 2; - } else if (extention(filename[0], ".fds")) { - bnrRomType[0] = 4; - boxArtType[0] = 1; - } else if (extention(filename[0], ".sms")) { - bnrRomType[0] = 5; - boxArtType[0] = 2; - } else if (extention(filename[0], ".gg")) { - bnrRomType[0] = 6; - boxArtType[0] = 2; - } else if (extention(filename[0], ".gen")) { - bnrRomType[0] = 7; - boxArtType[0] = 2; - } else if (extention(filename[0], ".smc")) { - bnrRomType[0] = 8; - boxArtType[0] = 3; - } else if (extention(filename[0], ".sfc")) { - bnrRomType[0] = 8; - boxArtType[0] = 2; - } - } - - // Flashcard (Secondary device) - if (flashcardFound() && romPath[1] != "" && access(romPath[1].c_str(), F_OK) == 0) { - romFound[1] = true; - - romfolder[1] = romPath[1]; - while (!romfolder[1].empty() && romfolder[1][romfolder[1].size()-1] != '/') { - romfolder[1].resize(romfolder[1].size()-1); - } - chdir(romfolder[1].c_str()); - - filename[1] = romPath[1]; - const size_t last_slash_idx = filename[1].find_last_of("/"); - if (std::string::npos != last_slash_idx) - { - filename[1].erase(0, last_slash_idx + 1); - } - - if (extention(filename[1], ".nds") || extention(filename[1], ".dsi") || extention(filename[1], ".ids") || extention(filename[1], ".app") || extention(filename[1], ".srl") || extention(filename[1], ".argv")) { - getGameInfo(1, false, filename[1].c_str()); - iconUpdate (1, false, filename[1].c_str()); - bnrRomType[1] = 0; - boxArtType[1] = 0; - } else if (extention(filename[1], ".plg") || extention(filename[1], ".rvid") || extention(filename[1], ".mp4") || extention(filename[1], ".a26")) { - bnrRomType[1] = 9; - boxArtType[1] = 0; - } else if (extention(filename[1], ".gba")) { - bnrRomType[1] = 1; - boxArtType[1] = 1; - } else if (extention(filename[1], ".gb") || extention(filename[1], ".sgb")) { - bnrRomType[1] = 2; - boxArtType[1] = 1; - } else if (extention(filename[1], ".gbc")) { - bnrRomType[1] = 3; - boxArtType[1] = 1; - } else if (extention(filename[1], ".nes")) { - bnrRomType[1] = 4; - boxArtType[1] = 2; - } else if (extention(filename[1], ".fds")) { - bnrRomType[1] = 4; - boxArtType[1] = 1; - } else if (extention(filename[1], ".sms")) { - bnrRomType[1] = 5; - boxArtType[1] = 2; - } else if (extention(filename[1], ".gg")) { - bnrRomType[1] = 6; - boxArtType[1] = 2; - } else if (extention(filename[1], ".gen")) { - bnrRomType[1] = 7; - boxArtType[1] = 2; - } else if (extention(filename[1], ".smc")) { - bnrRomType[1] = 8; - boxArtType[1] = 3; - } else if (extention(filename[1], ".sfc")) { - bnrRomType[1] = 8; - boxArtType[1] = 2; - } - - if (showBoxArt) { - // Store box art path - std::string temp_filename = filename[secondaryDevice]; - char boxArtPath[256]; - snprintf (boxArtPath, sizeof(boxArtPath), (sdFound() ? "sd:/_nds/TWiLightMenu/boxart/%s.png" : "fat:/_nds/TWiLightMenu/boxart/%s.png"), filename[0].c_str()); - if ((access(boxArtPath, F_OK) != 0) && (bnrRomType[secondaryDevice] == 0)) { - if(extention(filename[0], ".argv")) { - vector argarray; - - FILE *argfile = fopen(filename[0].c_str(),"rb"); - char str[PATH_MAX], *pstr; - const char seps[]= "\n\r\t "; - - while( fgets(str, PATH_MAX, argfile) ) { - // Find comment and end string there - if( (pstr = strchr(str, '#')) ) - *pstr= '\0'; - - // Tokenize arguments - pstr= strtok(str, seps); - - while( pstr != NULL ) { - argarray.push_back(strdup(pstr)); - pstr= strtok(NULL, seps); - } - } - fclose(argfile); - temp_filename = argarray.at(0); - } - // Get game's TID - FILE *f_nds_file = fopen(temp_filename.c_str(), "rb"); - char game_TID[5]; - grabTID(f_nds_file, game_TID); - game_TID[4] = 0; - fclose(f_nds_file); - - sprintf (boxArtPath, (sdFound() ? "sd:/_nds/TWiLightMenu/boxart/%s.png" : "fat:/_nds/TWiLightMenu/boxart/%s.png"), game_TID); - } - loadBoxArt(boxArtPath); // Load box art - } - } - - if (isDSiMode() && !flashcardFound()) { - if (REG_SCFG_MC == 0x11) { - if (showBoxArt) loadBoxArt("nitro:/graphics/boxart_unknown.png"); - cardEjected = true; - } else { - refreshNdsCard(); - } - } - - whiteScreen = false; - fadeType = true; // Fade in from white - for (int i = 0; i < 30; i++) { - swiWaitForVBlank(); - } - topBarLoad(); - startMenu = true; // Show bottom screen graphics - fadeSpeed = false; - - while(1) { - - if (startMenu) { - int pressed = 0; - - do { - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (flashcardFound()) { - if (romFound[1]) { - titleUpdate(1, false, filename[1].c_str()); - } else { - printLastPlayedText(0); - } - } else if (isDSiMode() && !flashcardFound()) { - printNdsCartBannerText(); - } - if (!sdFound()) { - printGbaBannerText(); - } else if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - - if (isDSiMode() && !flashcardFound()) { - if (REG_SCFG_MC == 0x11) { - if (cardRefreshed && showBoxArt) { - loadBoxArt("nitro:/graphics/boxart_unknown.png"); - } - cardRefreshed = false; - cardEjected = true; - } else if (cardEjected) { - refreshNdsCard(); - } - } - - scanKeys(); - pressed = keysDownRepeat(); - touchRead(&touch); - checkSdEject(); - swiWaitForVBlank(); - } while (!pressed); - - if (pressed & KEY_UP) { - if (startMenu_cursorPosition == 2 || startMenu_cursorPosition == 3 || startMenu_cursorPosition == 5) { - startMenu_cursorPosition -= 2; - mmEffectEx(&snd_select); - } else if (startMenu_cursorPosition == 6) { - startMenu_cursorPosition -= 3; - mmEffectEx(&snd_select); - } else { - startMenu_cursorPosition--; - mmEffectEx(&snd_select); - } - } - - if (pressed & KEY_DOWN) { - if (startMenu_cursorPosition == 1 || startMenu_cursorPosition == 3) { - startMenu_cursorPosition += 2; - mmEffectEx(&snd_select); - } else if (startMenu_cursorPosition >= 0 && startMenu_cursorPosition <= 3) { - startMenu_cursorPosition++; - mmEffectEx(&snd_select); - } - } - - if (pressed & KEY_LEFT) { - if (startMenu_cursorPosition == 2 || (startMenu_cursorPosition == 5 && isDSiMode() && consoleModel < 2) - || startMenu_cursorPosition == 6) { - startMenu_cursorPosition--; - mmEffectEx(&snd_select); - } - } - - if (pressed & KEY_RIGHT) { - if (startMenu_cursorPosition == 1 || startMenu_cursorPosition == 4 || startMenu_cursorPosition == 5) { - startMenu_cursorPosition++; - mmEffectEx(&snd_select); - } - } - - if (pressed & KEY_TOUCH) { - if (touch.px >= 33 && touch.px <= 221 && touch.py >= 25 && touch.py <= 69) { - startMenu_cursorPosition = 0; - menuButtonPressed = true; - } else if (touch.px >= 33 && touch.px <= 125 && touch.py >= 73 && touch.py <= 117) { - startMenu_cursorPosition = 1; - menuButtonPressed = true; - } else if (touch.px >= 129 && touch.px <= 221 && touch.py >= 73 && touch.py <= 117) { - startMenu_cursorPosition = 2; - menuButtonPressed = true; - } else if (touch.px >= 33 && touch.px <= 221 && touch.py >= 121 && touch.py <= 165) { - startMenu_cursorPosition = 3; - menuButtonPressed = true; - } else if (touch.px >= 10 && touch.px <= 20 && touch.py >= 175 && touch.py <= 185 - && isDSiMode() && consoleModel < 2) - { - startMenu_cursorPosition = 4; - menuButtonPressed = true; - } else if (touch.px >= 117 && touch.px <= 137 && touch.py >= 170 && touch.py <= 190) { - startMenu_cursorPosition = 5; - menuButtonPressed = true; - } else if (touch.px >= 235 && touch.px <= 244 && touch.py >= 175 && touch.py <= 185) { - startMenu_cursorPosition = 6; - menuButtonPressed = true; - } - } - - if (pressed & KEY_A) { - menuButtonPressed = true; - } - - if (startMenu_cursorPosition < 0) startMenu_cursorPosition = 0; - if (startMenu_cursorPosition > 6) startMenu_cursorPosition = 6; - - if (menuButtonPressed) { - switch (startMenu_cursorPosition) { - case -1: - default: - break; - case 0: - if (flashcardFound()) { - // Launch last-run ROM (Secondary) - if (launchType[1] == 0) { - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[0] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (romFound[1]) { - titleUpdate(1, false, filename[1].c_str()); - } else { - printLastPlayedText(0); - } - if (!sdFound()) { - printGbaBannerText(); - } else if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - loadROMselect(); - } else if (launchType[1] > 0) { - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[0] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (romFound[1]) { - titleUpdate(1, false, filename[1].c_str()); - } else { - printLastPlayedText(0); - } - if (!sdFound()) { - printGbaBannerText(); - } else if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - if (romFound[1]) { - applaunch = true; - } else { - loadROMselect(); - } - } - secondaryDevice = true; - } else if (!flashcardFound() && REG_SCFG_MC != 0x11) { - // Launch Slot-1 - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[0] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - printNdsCartBannerText(); - if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - slot1Launched = true; - SaveSettings(); - - if (slot1LaunchMethod == 0 || arm7SCFGLocked) { - dsCardLaunch(); - } else if (slot1LaunchMethod == 2) { - unlaunchRomBoot("cart:"); - } else { - directCardLaunch(); - } - } else { - mmEffectEx(&snd_wrong); - } - break; - case 1: - if (pictochatFound) { - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[1] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (!sdFound()) { - printGbaBannerText(); - } else if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - - // Clear screen with white - whiteScreen = true; - controlTopBright = false; - clearText(); - - if (pictochatReboot) { - *(u32 *)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag - *(u16 *)(0x02000304) = 0x1801; - - switch (sysRegion) { - case 4: - *(u32 *)(0x02000308) = 0x484E4543; - *(u32 *)(0x0200030C) = 0x00030005; - *(u32 *)(0x02000310) = 0x484E4543; - break; - case 5: - *(u32 *)(0x02000308) = 0x484E454B; - *(u32 *)(0x0200030C) = 0x00030005; - *(u32 *)(0x02000310) = 0x484E454B; - break; - default: - *(u32 *)(0x02000308) = 0x484E4541; // "HNEA" - *(u32 *)(0x0200030C) = 0x00030005; - *(u32 *)(0x02000310) = 0x484E4541; // "HNEA" - } - - *(u32 *)(0x02000314) = 0x00030005; - *(u32 *)(0x02000318) = 0x00000017; - *(u32 *)(0x0200031C) = 0x00000000; - while (*(u16 *)(0x02000306) == 0x0000) - { // Keep running, so that CRC16 isn't 0 - *(u16 *)(0x02000306) = swiCRC16(0xFFFF, (void *)0x02000308, 0x18); - } - - if (consoleModel < 2) { - unlaunchSetHiyaBoot(); - } - - fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher - for (int i = 0; i < 15; i++) swiWaitForVBlank(); - } else { - if (sdFound()) { - chdir("sd:/"); - } - int err = runNdsFile (pictochatPath, 0, NULL, true, true, true, false, false); - char text[32]; - snprintf (text, sizeof(text), "Start failed. Error %i", err); - clearText(); - ClearBrightness(); - printSmall(false, 4, 80, text); - stop(); - } - } else { - mmEffectEx(&snd_wrong); - } - break; - case 2: - if (dlplayFound) { - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[2] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (!sdFound()) { - printGbaBannerText(); - } else if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - - // Clear screen with white - whiteScreen = true; - controlTopBright = false; - clearText(); - - if (dlplayReboot) { - *(u32 *)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag - *(u16 *)(0x02000304) = 0x1801; - - switch (sysRegion) { - case 4: - *(u32 *)(0x02000308) = 0x484E4443; - *(u32 *)(0x0200030C) = 0x00030005; - *(u32 *)(0x02000310) = 0x484E4443; - break; - case 5: - *(u32 *)(0x02000308) = 0x484E444B; - *(u32 *)(0x0200030C) = 0x00030005; - *(u32 *)(0x02000310) = 0x484E444B; - break; - default: - *(u32 *)(0x02000308) = 0x484E4441; // "HNDA" - *(u32 *)(0x0200030C) = 0x00030005; - *(u32 *)(0x02000310) = 0x484E4441; // "HNDA" - } - - *(u32 *)(0x02000314) = 0x00030005; - *(u32 *)(0x02000318) = 0x00000017; - *(u32 *)(0x0200031C) = 0x00000000; - while (*(u16 *)(0x02000306) == 0x0000) - { // Keep running, so that CRC16 isn't 0 - *(u16 *)(0x02000306) = swiCRC16(0xFFFF, (void *)0x02000308, 0x18); - } - - if (consoleModel < 2) { - unlaunchSetHiyaBoot(); - } - - fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher - for (int i = 0; i < 15; i++) swiWaitForVBlank(); - } else { - if (sdFound()) { - chdir("sd:/"); - } - int err = runNdsFile (dlplayPath, 0, NULL, true, true, true, false, false); - char text[32]; - snprintf (text, sizeof(text), "Start failed. Error %i", err); - clearText(); - ClearBrightness(); - printSmall(false, 4, 80, text); - stop(); - } - } else { - mmEffectEx(&snd_wrong); - } - break; - case 3: - if (sdFound()) { - // Launch last-run ROM (SD) - if (launchType[0] == 0) { - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[3] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - loadROMselect(); - } else if (launchType[0] > 0) { - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[3] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - if (romFound[0]) { - titleUpdate(0, false, filename[0].c_str()); - } else { - printLastPlayedText(3); - } - swiWaitForVBlank(); - } - if (romFound[0]) { - applaunch = true; - } else { - loadROMselect(); - } - } - secondaryDevice = false; - } else if (isRegularDS) { - // Switch to GBA mode - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[3] -= 6; - clearText(); - printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" - printSmallCentered(false, 112, 6, RetTime().c_str()); - printGbaBannerText(); - swiWaitForVBlank(); - } - gbaSwitch(); - } else { - mmEffectEx(&snd_wrong); - } - break; - case 4: - // Adjust backlight level - if (isDSiMode() && consoleModel < 2) { - fifoSendValue32(FIFO_USER_04, 1); - mmEffectEx(&snd_backlight); - } - break; - case 5: - // Launch settings - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[5] -= 6; - swiWaitForVBlank(); - } - - gotosettings = true; - //SaveSettings(); - if (!isDSiMode()) { - chdir("fat:/"); - } else if (sdFound()) { - chdir("sd:/"); - } - int err = runNdsFile ("/_nds/TWiLightMenu/settings.srldr", 0, NULL, true, false, false, true, true); - iprintf ("Start failed. Error %i\n", err); - break; - } - if (startMenu_cursorPosition == 6) { - // Open manual - showCursor = false; - fadeType = false; // Fade to white - mmEffectEx(&snd_launch); - for (int i = 0; i < 50; i++) { - iconYpos[6] -= 6; - swiWaitForVBlank(); - } - if (!isDSiMode()) { - chdir("fat:/"); - } else if (sdFound()) { - chdir("sd:/"); - } - int err = runNdsFile ("/_nds/TWiLightMenu/manual.srldr", 0, NULL, true, false, false, true, true); - iprintf ("Start failed. Error %i\n", err); - } - - menuButtonPressed = false; - } - - if (pressed & KEY_B) { - mmEffectEx(&snd_back); - fadeType = false; // Fade to white - for (int i = 0; i < 50; i++) swiWaitForVBlank(); - loadROMselect(); - } - - if ((pressed & KEY_X) && !isRegularDS) { - mmEffectEx(&snd_back); - fadeType = false; // Fade to white - for (int i = 0; i < 50; i++) swiWaitForVBlank(); - if (!isDSiMode() || launcherApp == -1) { - *(u32*)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag - *(u16*)(0x02000304) = 0x1801; - *(u32*)(0x02000310) = 0x4D454E55; // "MENU" - unlaunchSetHiyaBoot(); - } else { - tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); - *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) - *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) - *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h - *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h - *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) - *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) - toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) - int i2 = 0; - for (int i = 0; i < (int)sizeof(unlaunchDevicePath); i++) { - *(u8*)(0x02000838+i2) = unlaunchDevicePath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) - i2 += 2; - } - while (*(u16*)(0x0200080E) == 0) { // Keep running, so that CRC16 isn't 0 - *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 - } - } - fifoSendValue32(FIFO_USER_02, 1); // ReturntoDSiMenu - } - - } - - //////////////////////////////////// - // Launch the item - - if (applaunch) { - // Clear screen with white - whiteScreen = true; - fadeSpeed = true; - controlTopBright = false; - clearText(); - - // Delete previously used DSiWare of flashcard from SD - if (!gotosettings && consoleModel < 2 && previousUsedDevice && bothSDandFlashcard()) { - if (access("sd:/_nds/TWiLightMenu/tempDSiWare.dsi", F_OK) == 0) { - remove("sd:/_nds/TWiLightMenu/tempDSiWare.dsi"); - } - if (access("sd:/_nds/TWiLightMenu/tempDSiWare.pub", F_OK) == 0) { - remove("sd:/_nds/TWiLightMenu/tempDSiWare.pub"); - } - if (access("sd:/_nds/TWiLightMenu/tempDSiWare.prv", F_OK) == 0) { - remove("sd:/_nds/TWiLightMenu/tempDSiWare.prv"); - } - } - - // Construct a command line - getcwd (filePath, PATH_MAX); - int pathLen = strlen(filePath); - vector argarray; - - if (extention(filename[secondaryDevice], ".argv")) - { - FILE *argfile = fopen(filename[secondaryDevice].c_str(),"rb"); - char str[PATH_MAX], *pstr; - const char seps[]= "\n\r\t "; - - while( fgets(str, PATH_MAX, argfile) ) { - // Find comment and end string there - if( (pstr = strchr(str, '#')) ) - *pstr= '\0'; - - // Tokenize arguments - pstr= strtok(str, seps); - - while( pstr != NULL ) { - argarray.push_back(strdup(pstr)); - pstr= strtok(NULL, seps); - } - } - fclose(argfile); - filename[secondaryDevice] = argarray.at(0); - } else { - argarray.push_back(strdup(filename[secondaryDevice].c_str())); - } - - // Launch DSiWare .nds via Unlaunch - if ((isDSiMode() || sdFound()) && isDSiWare[secondaryDevice]) { - const char *typeToReplace = ".nds"; - if (extention(filename[secondaryDevice], ".dsi")) { - typeToReplace = ".dsi"; - } else if (extention(filename[secondaryDevice], ".ids")) { - typeToReplace = ".ids"; - } else if (extention(filename[secondaryDevice], ".srl")) { - typeToReplace = ".srl"; - } else if (extention(filename[secondaryDevice], ".app")) { - typeToReplace = ".app"; - } - - char *name = argarray.at(0); - strcpy (filePath + pathLen, name); - free(argarray.at(0)); - argarray.at(0) = filePath; - - dsiWareSrlPath = argarray[0]; - dsiWarePubPath = replaceAll(argarray[0], typeToReplace, ".pub"); - dsiWarePrvPath = replaceAll(argarray[0], typeToReplace, ".prv"); - launchType[secondaryDevice] = (consoleModel>0 ? 1 : 3); - SaveSettings(); - - sNDSHeaderExt NDSHeader; - - FILE *f_nds_file = fopen(filename[secondaryDevice].c_str(), "rb"); - - fread(&NDSHeader, 1, sizeof(NDSHeader), f_nds_file); - fclose(f_nds_file); - - whiteScreen = true; - - if ((getFileSize(dsiWarePubPath.c_str()) == 0) && (NDSHeader.pubSavSize > 0)) { - clearText(); - if (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { - // Display nothing - } else if (consoleModel >= 2) { - printSmallCentered(false, 20, "If this takes a while, press HOME,"); - printSmallCentered(false, 34, "then press B."); - } else { - printSmallCentered(false, 20, "If this takes a while, close and open"); - printSmallCentered(false, 34, "the console's lid."); - } - printSmall(false, 2, 80, "Creating public save file..."); - if (!fadeType) { - fadeType = true; // Fade in from white - for (int i = 0; i < 35; i++) swiWaitForVBlank(); - } - - static const int BUFFER_SIZE = 4096; - char buffer[BUFFER_SIZE]; - memset(buffer, 0, sizeof(buffer)); - char savHdrPath[64]; - snprintf(savHdrPath, sizeof(savHdrPath), "nitro:/DSiWareSaveHeaders/%x.savhdr", (unsigned int)NDSHeader.pubSavSize); - FILE *hdrFile = fopen(savHdrPath, "rb"); - if (hdrFile) fread(buffer, 1, 0x200, hdrFile); - fclose(hdrFile); - - FILE *pFile = fopen(dsiWarePubPath.c_str(), "wb"); - if (pFile) { - fwrite(buffer, 1, sizeof(buffer), pFile); - fseek(pFile, NDSHeader.pubSavSize - 1, SEEK_SET); - fputc('\0', pFile); - fclose(pFile); - } - printSmall(false, 2, 88, "Public save file created!"); - for (int i = 0; i < 60; i++) swiWaitForVBlank(); - } - - if ((getFileSize(dsiWarePrvPath.c_str()) == 0) && (NDSHeader.prvSavSize > 0)) { - clearText(); - if (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { - // Display nothing - } else if (consoleModel >= 2) { - printSmallCentered(false, 20, "If this takes a while, press HOME,"); - printSmallCentered(false, 34, "then press B."); - } else { - printSmallCentered(false, 20, "If this takes a while, close and open"); - printSmallCentered(false, 34, "the console's lid."); - } - printSmall(false, 2, 80, "Creating private save file..."); - if (!fadeType) { - fadeType = true; // Fade in from white - for (int i = 0; i < 35; i++) swiWaitForVBlank(); - } - - static const int BUFFER_SIZE = 4096; - char buffer[BUFFER_SIZE]; - memset(buffer, 0, sizeof(buffer)); - char savHdrPath[64]; - snprintf(savHdrPath, sizeof(savHdrPath), "nitro:/DSiWareSaveHeaders/%x.savhdr", (unsigned int)NDSHeader.prvSavSize); - FILE *hdrFile = fopen(savHdrPath, "rb"); - if (hdrFile) fread(buffer, 1, 0x200, hdrFile); - fclose(hdrFile); - - FILE *pFile = fopen(dsiWarePrvPath.c_str(), "wb"); - if (pFile) { - fwrite(buffer, 1, sizeof(buffer), pFile); - fseek(pFile, NDSHeader.prvSavSize - 1, SEEK_SET); - fputc('\0', pFile); - fclose(pFile); - } - printSmall(false, 2, 88, "Private save file created!"); - for (int i = 0; i < 60; i++) swiWaitForVBlank(); - } - - if (fadeType) { - fadeType = false; // Fade to white - for (int i = 0; i < 25; i++) swiWaitForVBlank(); - } - - if (dsiWareBooter || consoleModel > 0) { - // Use nds-bootstrap - loadPerGameSettings(filename[secondaryDevice]); - - bootstrapinipath = "sd:/_nds/nds-bootstrap.ini"; - CIniFile bootstrapini(bootstrapinipath); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", dsiWareSrlPath); - bootstrapini.SetString("NDS-BOOTSTRAP", "SAV_PATH", dsiWarePubPath); - bootstrapini.SetString("NDS-BOOTSTRAP", "AP_FIX_PATH", ""); - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", -1); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", true); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", true); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", true); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DONOR_SDK_VER", 5); - bootstrapini.SetInt("NDS-BOOTSTRAP", "GAME_SOFT_RESET", 1); - bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_REGION", 0); - bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_SIZE", 0); - bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", 1); - bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", - (forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !isRegularDS)) - ); - bootstrapini.SaveIniFile(bootstrapinipath); - - if (isDSiMode() || !secondaryDevice) { - SetWidescreen(filename[secondaryDevice].c_str()); - } - if (!isDSiMode() && !secondaryDevice) { - ntrStartSdGame(); - } - - bool useNightly = (perGameSettings_bootstrapFile == -1 ? bootstrapFile : perGameSettings_bootstrapFile); - - char ndsToBoot[256]; - sprintf(ndsToBoot, "sd:/_nds/nds-bootstrap-%s.nds", useNightly ? "nightly" : "release"); - if(access(ndsToBoot, F_OK) != 0) { - sprintf(ndsToBoot, "fat:/_nds/nds-bootstrap-%s.nds", useNightly ? "nightly" : "release"); - } - - argarray.at(0) = (char *)ndsToBoot; - int err = runNdsFile(argarray[0], argarray.size(), (const char **)&argarray[0], true, true, false, true, true); - char text[32]; - snprintf (text, sizeof(text), "Start failed. Error %i", err); - clearText(); - ClearBrightness(); - printSmall(false, 4, 80, text); - if (err == 1) { - printSmall(false, 4, 88, useNightly ? "nds-bootstrap (Nightly)" : "nds-bootstrap (Release)"); - printSmall(false, 4, 96, "not found."); - } - stop(); - } - - if (secondaryDevice) { - clearText(); - printSmallCentered(false, 20, "If this takes a while, close and open"); - printSmallCentered(false, 34, "the console's lid."); - printSmallCentered(false, 86, "Now copying data..."); - printSmallCentered(false, 100, "Do not turn off the power."); - fadeType = true; // Fade in from white - for (int i = 0; i < 35; i++) swiWaitForVBlank(); - fcopy(dsiWareSrlPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.dsi"); - if ((access(dsiWarePubPath.c_str(), F_OK) == 0) && (NDSHeader.pubSavSize > 0)) { - fcopy(dsiWarePubPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.pub"); - } - if ((access(dsiWarePrvPath.c_str(), F_OK) == 0) && (NDSHeader.prvSavSize > 0)) { - fcopy(dsiWarePrvPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.prv"); - } - fadeType = false; // Fade to white - for (int i = 0; i < 25; i++) swiWaitForVBlank(); - - if ((access(dsiWarePubPath.c_str(), F_OK) == 0 && (NDSHeader.pubSavSize > 0)) - || (access(dsiWarePrvPath.c_str(), F_OK) == 0 && (NDSHeader.prvSavSize > 0))) { - clearText(); - printSmallCentered(false, 8, "After saving, please re-start"); - printSmallCentered(false, 20, "TWiLight Menu++ to transfer your"); - printSmallCentered(false, 32, "save data back."); - fadeType = true; // Fade in from white - for (int i = 0; i < 60*3; i++) swiWaitForVBlank(); // Wait 3 seconds - fadeType = false; // Fade to white - for (int i = 0; i < 25; i++) swiWaitForVBlank(); - } - } - - char unlaunchDevicePath[256]; - if (secondaryDevice) { - snprintf(unlaunchDevicePath, sizeof(unlaunchDevicePath), "sdmc:/_nds/TWiLightMenu/tempDSiWare.dsi"); - } else { - snprintf(unlaunchDevicePath, sizeof(unlaunchDevicePath), "__%s", dsiWareSrlPath.c_str()); - unlaunchDevicePath[0] = 's'; - unlaunchDevicePath[1] = 'd'; - unlaunchDevicePath[2] = 'm'; - unlaunchDevicePath[3] = 'c'; - } - - tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); - *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) - *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) - *(u32*)(0x02000810) = 0; // Unlaunch Flags - *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h - *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h - *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) - *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) - toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) - int i2 = 0; - for (int i = 0; i < (int)sizeof(unlaunchDevicePath); i++) { - *(u8*)(0x02000838+i2) = unlaunchDevicePath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) - i2 += 2; - } - *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 - - fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher - for (int i = 0; i < 15; i++) swiWaitForVBlank(); - } - - // Launch .nds directly or via nds-bootstrap - if (extention(filename[secondaryDevice], ".nds") || extention(filename[secondaryDevice], ".dsi") - || extention(filename[secondaryDevice], ".ids") || extention(filename[secondaryDevice], ".srl") - || extention(filename[secondaryDevice], ".app")) { - const char *typeToReplace = ".nds"; - if (extention(filename[secondaryDevice], ".dsi")) { - typeToReplace = ".dsi"; - } else if (extention(filename[secondaryDevice], ".ids")) { - typeToReplace = ".ids"; - } else if (extention(filename[secondaryDevice], ".srl")) { - typeToReplace = ".srl"; - } else if (extention(filename[secondaryDevice], ".app")) { - typeToReplace = ".app"; - } - - bool dsModeSwitch = false; - bool dsModeDSiWare = false; - - char game_TID[5]; - - FILE *f_nds_file = fopen(argarray[0], "rb"); - - fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); - fread(game_TID, 1, 4, f_nds_file); - fclose(f_nds_file); - game_TID[4] = 0; - game_TID[3] = 0; - - if (strcmp(game_TID, "HND") == 0 || strcmp(game_TID, "HNE") == 0) { - dsModeSwitch = true; - dsModeDSiWare = true; - useBackend = false; // Bypass nds-bootstrap - homebrewBootstrap = true; - } else if (isHomebrew[secondaryDevice]) { - loadPerGameSettings(filename[secondaryDevice]); - if (perGameSettings_directBoot || (useBootstrap && secondaryDevice)) { - useBackend = false; // Bypass nds-bootstrap - } else { - useBackend = true; - } - if (isDSiMode() && !perGameSettings_dsiMode) { - dsModeSwitch = true; - } - homebrewBootstrap = true; - } else { - loadPerGameSettings(filename[secondaryDevice]); - useBackend = true; - homebrewBootstrap = false; - } - - char *name = argarray.at(0); - strcpy (filePath + pathLen, name); - free(argarray.at(0)); - argarray.at(0) = filePath; - if(useBackend) { - if(useBootstrap || !secondaryDevice) { - std::string path = argarray[0]; - std::string savename = replaceAll(filename[secondaryDevice], typeToReplace, getSavExtension()); - std::string ramdiskname = replaceAll(filename[secondaryDevice], typeToReplace, getImgExtension()); - std::string romFolderNoSlash = romfolder[secondaryDevice]; - RemoveTrailingSlashes(romFolderNoSlash); - mkdir (isHomebrew[secondaryDevice] ? "ramdisks" : "saves", 0777); - std::string savepath = romFolderNoSlash+"/saves/"+savename; - if (sdFound() && secondaryDevice && fcSaveOnSd) { - savepath = replaceAll(savepath, "fat:/", "sd:/"); - } - std::string ramdiskpath = romFolderNoSlash+"/ramdisks/"+ramdiskname; - - if (!isHomebrew[secondaryDevice] && (strcmp(game_TID, "NTR") != 0)) { - // Create or expand save if game isn't homebrew - int orgsavesize = getFileSize(savepath.c_str()); - int savesize = 524288; // 512KB (default size) - - for (auto i : saveMap) { - if (i.second.find(game_TID) != i.second.cend()) { - savesize = i.first; - break; - } - } - - bool saveSizeFixNeeded = false; - - // TODO: If the list gets large enough, switch to bsearch(). - for (unsigned int i = 0; i < sizeof(saveSizeFixList) / sizeof(saveSizeFixList[0]); i++) { - if (memcmp(game_TID, saveSizeFixList[i], 3) == 0) { - // Found a match. - saveSizeFixNeeded = true; - break; - } - } - - if ((orgsavesize == 0 && savesize > 0) || (orgsavesize < savesize && saveSizeFixNeeded)) { - clearText(); - ClearBrightness(); - if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { - // Display nothing - } else if (REG_SCFG_EXT != 0 && consoleModel >= 2) { - printSmallCentered(false, 20, "If this takes a while, press HOME,"); - printSmallCentered(false, 34, "then press B."); - } else { - printSmallCentered(false, 20, "If this takes a while, close and open"); - printSmallCentered(false, 34, "the console's lid."); - } - printSmallCentered(false, 88, (orgsavesize == 0) ? "Creating save file..." : "Expanding save file..."); - - if (orgsavesize > 0) { - fsizeincrease(savepath.c_str(), sdFound() ? "sd:/_nds/TWiLightMenu/temp.sav" : "fat:/_nds/TWiLightMenu/temp.sav", savesize); - } else { - FILE *pFile = fopen(savepath.c_str(), "wb"); - if (pFile) { - fseek(pFile, savesize - 1, SEEK_SET); - fputc('\0', pFile); - fclose(pFile); - } - } - clearText(); - printSmallCentered(false, 88, (orgsavesize == 0) ? "Save file created!" : "Save file expanded!"); - for (int i = 0; i < 30; i++) swiWaitForVBlank(); - } - } - - int donorSdkVer = SetDonorSDK(argarray[0]); - SetMPUSettings(argarray[0]); - SetSpeedBumpExclude(argarray[0]); - - bool useWidescreen = (perGameSettings_wideScreen == -1 ? wideScreen : perGameSettings_wideScreen); - - bootstrapinipath = ((!secondaryDevice || (isDSiMode() && sdFound())) ? "sd:/_nds/nds-bootstrap.ini" : "fat:/_nds/nds-bootstrap.ini"); - CIniFile bootstrapini( bootstrapinipath ); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", path); - bootstrapini.SetString("NDS-BOOTSTRAP", "SAV_PATH", savepath); - if (!isHomebrew[secondaryDevice]) { - bootstrapini.SetString("NDS-BOOTSTRAP", "AP_FIX_PATH", setApFix(argarray[0])); - } - bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", (useWidescreen && game_TID[0] == 'W') ? "wide" : ""); - bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", (perGameSettings_ramDiskNo >= 0 && !secondaryDevice) ? ramdiskpath : "sd:/null.img"); - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", perGameSettings_language == -2 ? gameLanguage : perGameSettings_language); - if (isDSiMode() || !secondaryDevice) { - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", perGameSettings_dsiMode == -1 ? bstrap_dsiMode : perGameSettings_dsiMode); - } - if ((REG_SCFG_EXT != 0) || !secondaryDevice) { - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", perGameSettings_boostCpu == -1 ? boostCpu : perGameSettings_boostCpu); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram); - } - bootstrapini.SetInt("NDS-BOOTSTRAP", "EXTENDED_MEMORY", perGameSettings_expandRomSpace == -1 ? bstrap_extendedMemory : perGameSettings_expandRomSpace); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DONOR_SDK_VER", donorSdkVer); - bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_REGION", mpuregion); - bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_SIZE", mpusize); - bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", ceCached); - bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", - (forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !isRegularDS)) - ); - bootstrapini.SaveIniFile( bootstrapinipath ); - - CheatCodelist codelist; - u32 gameCode,crc32; - - if ((isDSiMode() || !secondaryDevice) && !isHomebrew[secondaryDevice]) { - bool cheatsEnabled = true; - const char* cheatDataBin = "/_nds/nds-bootstrap/cheatData.bin"; - mkdir("/_nds", 0777); - mkdir("/_nds/nds-bootstrap", 0777); - if(codelist.romData(path,gameCode,crc32)) { - long cheatOffset; size_t cheatSize; - FILE* dat=fopen(sdFound() ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat","rb"); - if (dat) { - if (codelist.searchCheatData(dat, gameCode, - crc32, cheatOffset, - cheatSize)) { - codelist.parse(path); - writeCheatsToFile(codelist.getCheats(), cheatDataBin); - FILE* cheatData=fopen(cheatDataBin,"rb"); - if (cheatData) { - u32 check[2]; - fread(check, 1, 8, cheatData); - fclose(cheatData); - if (check[1] == 0xCF000000 - || getFileSize(cheatDataBin) > 0x8000) { - cheatsEnabled = false; - } - } - } else { - cheatsEnabled = false; - } - fclose(dat); - } else { - cheatsEnabled = false; - } - } else { - cheatsEnabled = false; - } - if (!cheatsEnabled) { - remove(cheatDataBin); - } - } - - launchType[secondaryDevice] = 1; - previousUsedDevice = secondaryDevice; - SaveSettings(); - - if (isDSiMode() || !secondaryDevice) { - SetWidescreen(filename[secondaryDevice].c_str()); - } - if (!isDSiMode() && !secondaryDevice) { - ntrStartSdGame(); - } - - bool useNightly = (perGameSettings_bootstrapFile == -1 ? bootstrapFile : perGameSettings_bootstrapFile); - - char ndsToBoot[256]; - sprintf(ndsToBoot, "sd:/_nds/nds-bootstrap-%s%s.nds", homebrewBootstrap ? "hb-" : "", useNightly ? "nightly" : "release"); - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - sprintf(ndsToBoot, "fat:/_nds/%s-%s%s.nds", isDSiMode() ? "nds-bootstrap" : "b4ds", homebrewBootstrap ? "hb-" : "", useNightly ? "nightly" : "release"); - } - - argarray.at(0) = (char *)ndsToBoot; - int err = runNdsFile (argarray[0], argarray.size(), (const char **)&argarray[0], (homebrewBootstrap ? false : true), true, false, true, true); - char text[32]; - snprintf (text, sizeof(text), "Start failed. Error %i", err); - clearText(); - ClearBrightness(); - printSmall(false, 4, 80, text); - if (err == 1) { - printSmall(false, 4, 88, useNightly ? "nds-bootstrap (Nightly)" : "nds-bootstrap (Release)"); - printSmall(false, 4, 96, "not found."); - } - stop(); - } else { - launchType[secondaryDevice] = 1; - previousUsedDevice = secondaryDevice; - SaveSettings(); - loadGameOnFlashcard(argarray[0], true); - } - } else { - if (isDSiMode() || !secondaryDevice) { - SetWidescreen(filename[secondaryDevice].c_str()); - } - launchType[secondaryDevice] = 2; - previousUsedDevice = secondaryDevice; - SaveSettings(); - if (!isDSiMode() && !secondaryDevice) { - ntrStartSdGame(); - } - - bool useWidescreen = (perGameSettings_wideScreen == -1 ? wideScreen : perGameSettings_wideScreen); - - if (consoleModel >= 2 && useWidescreen && homebrewHasWide) { - argarray.push_back((char*)"wide"); - } - - bool runNds_boostCpu = false; - bool runNds_boostVram = false; - if (REG_SCFG_EXT != 0 && !dsModeDSiWare) { - loadPerGameSettings(filename[secondaryDevice]); - - runNds_boostCpu = perGameSettings_boostCpu == -1 ? boostCpu : perGameSettings_boostCpu; - runNds_boostVram = perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram; - } - //iprintf ("Running %s with %d parameters\n", argarray[0], argarray.size()); - int err = runNdsFile (argarray[0], argarray.size(), (const char **)&argarray[0], true, true, dsModeSwitch, runNds_boostCpu, runNds_boostVram); - char text[32]; - snprintf (text, sizeof(text), "Start failed. Error %i", err); - clearText(); - ClearBrightness(); - printSmall(false, 4, 4, text); - stop(); - } - } else { - bool useNDSB = false; - bool dsModeSwitch = false; - bool boostCpu = true; - bool boostVram = false; - - std::string romfolderNoSlash = romfolder[secondaryDevice]; - RemoveTrailingSlashes(romfolderNoSlash); - char ROMpath[256]; - snprintf (ROMpath, sizeof(ROMpath), "%s/%s", romfolderNoSlash.c_str(), filename[secondaryDevice].c_str()); - romPath[secondaryDevice] = ROMpath; - previousUsedDevice = secondaryDevice; - homebrewBootstrap = true; - - const char *ndsToBoot = "sd:/_nds/nds-bootstrap-release.nds"; - if (extention(filename[secondaryDevice], ".plg")) { - ndsToBoot = "fat:/_nds/TWiLightMenu/bootplg.srldr"; - - // Print .plg path without "fat:" at the beginning - char ROMpathDS2[256]; - if (secondaryDevice) { - for (int i = 0; i < 252; i++) { - ROMpathDS2[i] = ROMpath[4+i]; - if (ROMpath[4+i] == '\x00') break; - } - } else { - sprintf(ROMpathDS2, "/_nds/TWiLightMenu/tempPlugin.plg"); - fcopy(ROMpath, "fat:/_nds/TWiLightMenu/tempPlugin.plg"); - } - - CIniFile dstwobootini( "fat:/_dstwo/twlm.ini" ); - dstwobootini.SetString("boot_settings", "file", ROMpathDS2); - dstwobootini.SaveIniFile( "fat:/_dstwo/twlm.ini" ); - } else if (extention(filename[secondaryDevice], ".rvid")) { - launchType[secondaryDevice] = 7; - - ndsToBoot = "sd:/_nds/TWiLightMenu/apps/RocketVideoPlayer.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/apps/RocketVideoPlayer.nds"; - boostVram = true; - } - } else if (extention(filename[secondaryDevice], ".mp4")) { - launchType[secondaryDevice] = 8; - - ndsToBoot = "sd:/_nds/TWiLightMenu/apps/MPEG4Player.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/apps/MPEG4Player.nds"; - boostVram = true; - } - } else if (extention(filename[secondaryDevice], ".gba")) { - launchType[secondaryDevice] = 1; - - if (secondaryDevice) { - ndsToBoot = gbar2DldiAccess ? "sd:/_nds/GBARunner2_arm7dldi_ds.nds" : "sd:/_nds/GBARunner2_arm9dldi_ds.nds"; - if (REG_SCFG_EXT != 0) { - ndsToBoot = consoleModel>0 ? "sd:/_nds/GBARunner2_arm7dldi_3ds.nds" : "sd:/_nds/GBARunner2_arm7dldi_dsi.nds"; - } - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = gbar2DldiAccess ? "fat:/_nds/GBARunner2_arm7dldi_ds.nds" : "fat:/_nds/GBARunner2_arm9dldi_ds.nds"; - if (REG_SCFG_EXT != 0) { - ndsToBoot = consoleModel>0 ? "fat:/_nds/GBARunner2_arm7dldi_3ds.nds" : "fat:/_nds/GBARunner2_arm7dldi_dsi.nds"; - } - } - boostVram = false; - } else { - useNDSB = true; - - const char* gbar2Path = consoleModel>0 ? "sd:/_nds/GBARunner2_arm7dldi_3ds.nds" : "sd:/_nds/GBARunner2_arm7dldi_dsi.nds"; - if (isDSiMode() && arm7SCFGLocked) { - gbar2Path = consoleModel>0 ? "sd:/_nds/GBARunner2_arm7dldi_nodsp_3ds.nds" : "sd:/_nds/GBARunner2_arm7dldi_nodsp_dsi.nds"; - } - - ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); - CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); - - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", gbar2Path); - bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", ROMpath); - bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ""); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 1); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); - - bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); - } - } else if (extention(filename[secondaryDevice], ".a26")) { - launchType[secondaryDevice] = 9; - - ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/StellaDS.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/StellaDS.nds"; - boostVram = true; - } - } else if (extention(filename[secondaryDevice], ".gb") || extention(filename[secondaryDevice], ".sgb") || extention(filename[secondaryDevice], ".gbc")) { - launchType[secondaryDevice] = 5; - - ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/gameyob.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/gameyob.nds"; - dsModeSwitch = !isDSiMode(); - boostVram = true; - } - } else if (extention(filename[secondaryDevice], ".nes") || extention(filename[secondaryDevice], ".fds")) { - launchType[secondaryDevice] = 4; - - ndsToBoot = (secondaryDevice ? "sd:/_nds/TWiLightMenu/emulators/nesds.nds" : "sd:/_nds/TWiLightMenu/emulators/nestwl.nds"); - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/nesds.nds"; - boostVram = true; - } - } else if (extention(filename[secondaryDevice], ".sms") || extention(filename[secondaryDevice], ".gg")) { - mkdir(secondaryDevice ? "fat:/data" : "sd:/data", 0777); - mkdir(secondaryDevice ? "fat:/data/s8ds" : "sd:/data/s8ds", 0777); - - if (!secondaryDevice && !arm7SCFGLocked && smsGgInRam) { - launchType[secondaryDevice] = 1; - - useNDSB = true; - - ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); - CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); - - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/S8DS07.nds"); - bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", ""); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 1); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); - - bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ROMpath); - bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); - } else { - launchType[secondaryDevice] = 6; - - ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/S8DS.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/S8DS.nds"; - boostVram = true; - } - } - } else if (extention(filename[secondaryDevice], ".gen")) { - bool usePicoDrive = ((isDSiMode() && sdFound() && arm7SCFGLocked) - || showMd==2 || (showMd==3 && getFileSize(filename[secondaryDevice].c_str()) > 0x300000)); - launchType[secondaryDevice] = (usePicoDrive ? 10 : 1); - - if (usePicoDrive || secondaryDevice) { - ndsToBoot = usePicoDrive ? "sd:/_nds/TWiLightMenu/emulators/PicoDriveTWL.nds" : "sd:/_nds/TWiLightMenu/emulators/jEnesisDS.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = usePicoDrive ? "fat:/_nds/TWiLightMenu/emulators/PicoDriveTWL.nds" : "fat:/_nds/TWiLightMenu/emulators/jEnesisDS.nds"; - boostVram = true; - } - dsModeSwitch = !usePicoDrive; - } else { - useNDSB = true; - - ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); - CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); - - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/jEnesisDS.nds"); - bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", "fat:/ROM.BIN"); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 1); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); - - bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ROMpath); - bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); - } - } else if (extention(filename[secondaryDevice], ".smc") || extention(filename[secondaryDevice], ".sfc")) { - launchType[secondaryDevice] = 1; - - if (secondaryDevice) { - ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/SNEmulDS.nds"; - if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/SNEmulDS.nds"; - boostCpu = false; - boostVram = true; - } - dsModeSwitch = true; - } else { - useNDSB = true; - - ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); - CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); - - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/SNEmulDS.nds"); - bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", "fat:/snes/ROM.SMC"); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 0); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); - - bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ROMpath); - bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); - } - } else if (extention(filename[secondaryDevice], ".pce")) { - launchType[secondaryDevice] = 1; - - if (secondaryDevice) { - ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/NitroGrafx.nds"; - if(access(ndsToBoot, F_OK) != 0) { - ndsToBoot = "/_nds/TWiLightMenu/emulators/NitroGrafx.nds"; - boostVram = true; - } - dsModeSwitch = true; - } else { - useNDSB = true; - - ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); - CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); - - bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); - bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/NitroGrafx.nds"); - bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", ROMpath); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 0); - bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); - - bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ""); - bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); - } - } - - SaveSettings(); - if (!isDSiMode() && !secondaryDevice && !extention(filename[secondaryDevice], ".plg")) { - ntrStartSdGame(); - } - argarray.push_back(ROMpath); - argarray.at(0) = (char *)ndsToBoot; - - int err = runNdsFile (argarray[0], argarray.size(), (const char **)&argarray[0], !useNDSB, true, dsModeSwitch, boostCpu, boostVram); // Pass ROM to emulator as argument - - char text[32]; - snprintf (text, sizeof(text), "Start failed. Error %i", err); - clearText(); - ClearBrightness(); - printLarge(false, 4, 80, text); - if (err == 1 && useNDSB) { - printSmall(false, 4, 88, bootstrapFile ? "nds-bootstrap (Nightly)" : "nds-bootstrap (Release)"); - printSmall(false, 4, 96, "not found."); - } - stop(); - - while(argarray.size() !=0 ) { - free(argarray.at(0)); - argarray.erase(argarray.begin()); - } - } - } - } - - return 0; -} +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "date.h" +#include "fileCopy.h" +#include "nand/nandio.h" + +#include "graphics/graphics.h" + +#include "common/tonccpy.h" +#include "common/nitrofs.h" +#include "read_card.h" +#include "flashcard.h" +#include "ndsheaderbanner.h" +#include "gbaswitch.h" +#include "nds_loader_arm9.h" +#include "perGameSettings.h" +#include "errorScreen.h" + +#include "iconTitle.h" +#include "graphics/fontHandler.h" + +#include "common/inifile.h" +#include "common/dsimenusettings.h" +#include "tool/stringtool.h" + +#include "language.h" + +#include "cheat.h" +#include "crc.h" + +#include "soundbank.h" +#include "soundbank_bin.h" + +#include "donorMap.h" +#include "mpuMap.h" +#include "speedBumpExcludeMap.h" +#include "saveMap.h" + +#include "sr_data_srllastran.h" // For rebooting into the game + +#define gbamodeText "Start GBA game." +#define featureUnavailableText "This feature is unavailable." + +bool useTwlCfg = false; + +bool whiteScreen = true; +bool fadeType = false; // false = out, true = in +bool fadeSpeed = true; // false = slow (for DSi launch effect), true = fast +bool controlTopBright = true; +bool controlBottomBright = true; +bool widescreenEffects = false; +int fps = 60; +int colorMode = 0; +int blfLevel = 0; + +bool cardEjected = false; +static bool cardRefreshed = false; + +extern void ClearBrightness(); +extern int boxArtType[2]; + +const char* settingsinipath = "sd:/_nds/TWiLightMenu/settings.ini"; +const char* bootstrapinipath = "sd:/_nds/nds-bootstrap.ini"; + +std::string romPath[2]; +std::string dsiWareSrlPath; +std::string dsiWarePubPath; +std::string dsiWarePrvPath; + +const char *charUnlaunchBg; +std::string unlaunchBg = "default.gif"; +bool removeLauncherPatches = true; + +const char *unlaunchAutoLoadID = "AutoLoadInfo"; +static char hiyaNdsPath[14] = {'s','d','m','c',':','/','h','i','y','a','.','d','s','i'}; +char unlaunchDevicePath[256]; + +static char pictochatPath[256]; +static char dlplayPath[256]; + +bool arm7SCFGLocked = false; +int consoleModel = 0; +/* 0 = Nintendo DSi (Retail) + 1 = Nintendo DSi (Dev/Panda) + 2 = Nintendo 3DS + 3 = New Nintendo 3DS */ +bool isRegularDS = true; +bool isDSLite = false; +int flashcard = 0; + +extern bool showdialogbox; + +bool extention(const std::string& filename, const char* ext) { + if(strcasecmp(filename.c_str() + filename.size() - strlen(ext), ext)) { + return false; + } else { + return true; + } +} + +/** + * Remove trailing slashes from a pathname, if present. + * @param path Pathname to modify. + */ +void RemoveTrailingSlashes(std::string& path) +{ + while (!path.empty() && path[path.size()-1] == '/') { + path.resize(path.size()-1); + } +} + +/** + * Remove trailing spaces from a cheat code line, if present. + * @param path Code line to modify. + */ +/*static void RemoveTrailingSpaces(std::string& code) +{ + while (!code.empty() && code[code.size()-1] == ' ') { + code.resize(code.size()-1); + } +}*/ + +std::string romfolder[2]; + +// These are used by flashcard functions and must retain their trailing slash. +static const std::string slashchar = "/"; +static const std::string woodfat = "fat0:/"; +static const std::string dstwofat = "fat1:/"; + +int mpuregion = 0; +int mpusize = 0; +bool ceCached = true; + +bool applaunch = false; +bool showCursor = true; +bool startMenu = false; +bool gotosettings = false; + +bool slot1Launched = false; +int launchType[2] = {0}; // 0 = Slot-1, 1 = SD/Flash card, 2 = SD/Flash card (Direct boot), 3 = DSiWare, 4 = NES, 5 = (S)GB(C), 6 = SMS/GG +int slot1LaunchMethod = 1; // 0 == Reboot, 1 == Direct, 2 == Unlaunch +bool useBootstrap = true; +bool bootstrapFile = false; +bool homebrewBootstrap = false; +bool homebrewHasWide = false; +bool show12hrClock = true; +//bool snesEmulator = true; +bool smsGgInRam = false; +bool fcSaveOnSd = false; +bool wideScreen = false; + +bool pictochatFound = false; +bool dlplayFound = false; +bool pictochatReboot = false; +bool dlplayReboot = false; +bool sdRemoveDetect = true; +bool useGbarunner = false; +bool gbar2DldiAccess = false; // false == ARM9, true == ARM7 +int theme = 0; +int subtheme = 0; +int showMd = 3; +int cursorPosition[2] = {0}; +int startMenu_cursorPosition = 0; +int pagenum[2] = {0}; +bool showDirectories = true; +int showBoxArt = 1 + isDSiMode(); +bool animateDsiIcons = false; +int launcherApp = -1; +int sysRegion = -1; + +int guiLanguage = -1; +int gameLanguage = -1; +int titleLanguage = -1; +bool boostCpu = false; // false == NTR, true == TWL +bool boostVram = false; +int bstrap_dsiMode = 0; +int bstrap_extendedMemory = 0; +bool forceSleepPatch = false; +bool dsiWareBooter = false; + +void LoadSettings(void) { + useBootstrap = isDSiMode(); + + // GUI + CIniFile settingsini( settingsinipath ); + + // UI settings. + consoleModel = settingsini.GetInt("SRLOADER", "CONSOLE_MODEL", 0); + + showMd = settingsini.GetInt("SRLOADER", "SHOW_MDGEN", showMd); + + // Customizable UI settings. + fps = settingsini.GetInt("SRLOADER", "FRAME_RATE", fps); + colorMode = settingsini.GetInt("SRLOADER", "COLOR_MODE", 0); + blfLevel = settingsini.GetInt("SRLOADER", "BLUE_LIGHT_FILTER_LEVEL", 0); + guiLanguage = settingsini.GetInt("SRLOADER", "LANGUAGE", -1); + titleLanguage = settingsini.GetInt("SRLOADER", "TITLELANGUAGE", titleLanguage); + sdRemoveDetect = settingsini.GetInt("SRLOADER", "SD_REMOVE_DETECT", 1); + useGbarunner = settingsini.GetInt("SRLOADER", "USE_GBARUNNER2", 0); + if (!isRegularDS) useGbarunner = true; + gbar2DldiAccess = settingsini.GetInt("SRLOADER", "GBAR2_DLDI_ACCESS", gbar2DldiAccess); + theme = settingsini.GetInt("SRLOADER", "THEME", 0); + subtheme = settingsini.GetInt("SRLOADER", "SUB_THEME", 0); + showDirectories = settingsini.GetInt("SRLOADER", "SHOW_DIRECTORIES", 1); + showBoxArt = settingsini.GetInt("SRLOADER", "SHOW_BOX_ART", showBoxArt); + animateDsiIcons = settingsini.GetInt("SRLOADER", "ANIMATE_DSI_ICONS", 0); + if (consoleModel < 2) { + launcherApp = settingsini.GetInt("SRLOADER", "LAUNCHER_APP", launcherApp); + } + + flashcard = settingsini.GetInt("SRLOADER", "FLASHCARD", flashcard); + + previousUsedDevice = settingsini.GetInt("SRLOADER", "PREVIOUS_USED_DEVICE", previousUsedDevice); + secondaryDevice = bothSDandFlashcard() ? settingsini.GetInt("SRLOADER", "SECONDARY_DEVICE", secondaryDevice) : flashcardFound(); + fcSaveOnSd = settingsini.GetInt("SRLOADER", "FC_SAVE_ON_SD", fcSaveOnSd); + + slot1LaunchMethod = settingsini.GetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); + useBootstrap = settingsini.GetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); + bootstrapFile = settingsini.GetInt("SRLOADER", "BOOTSTRAP_FILE", 0); + //snesEmulator = settingsini.GetInt("SRLOADER", "SNES_EMULATOR", snesEmulator); + smsGgInRam = settingsini.GetInt("SRLOADER", "SMS_GG_IN_RAM", smsGgInRam); + + show12hrClock = settingsini.GetInt("SRLOADER", "SHOW_12H_CLOCK", show12hrClock); + + unlaunchBg = settingsini.GetString("SRLOADER", "UNLAUNCH_BG", unlaunchBg); + charUnlaunchBg = unlaunchBg.c_str(); + removeLauncherPatches = settingsini.GetInt("SRLOADER", "UNLAUNCH_PATCH_REMOVE", removeLauncherPatches); + + // Default nds-bootstrap settings + gameLanguage = settingsini.GetInt("NDS-BOOTSTRAP", "LANGUAGE", -1); + boostCpu = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_CPU", 0); + boostVram = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); + bstrap_dsiMode = settingsini.GetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); + bstrap_extendedMemory = settingsini.GetInt("NDS-BOOTSTRAP", "EXTENDED_MEMORY", 0); + + forceSleepPatch = settingsini.GetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", 0); + dsiWareBooter = settingsini.GetInt("SRLOADER", "DSIWARE_BOOTER", dsiWareBooter); + + dsiWareSrlPath = settingsini.GetString("SRLOADER", "DSIWARE_SRL", dsiWareSrlPath); + dsiWarePubPath = settingsini.GetString("SRLOADER", "DSIWARE_PUB", dsiWarePubPath); + dsiWarePrvPath = settingsini.GetString("SRLOADER", "DSIWARE_PRV", dsiWarePrvPath); + launchType[0] = settingsini.GetInt("SRLOADER", "LAUNCH_TYPE", launchType[0]); + launchType[1] = settingsini.GetInt("SRLOADER", "SECONDARY_LAUNCH_TYPE", launchType[1]); + romPath[0] = settingsini.GetString("SRLOADER", "ROM_PATH", romPath[0]); + romPath[1] = settingsini.GetString("SRLOADER", "SECONDARY_ROM_PATH", romPath[1]); + + wideScreen = settingsini.GetInt("SRLOADER", "WIDESCREEN", wideScreen); +} + +void SaveSettings(void) { + // GUI + CIniFile settingsini( settingsinipath ); + + // UI settings. + if (!gotosettings) { + settingsini.SetString("SRLOADER", "DSIWARE_SRL", dsiWareSrlPath); + settingsini.SetString("SRLOADER", "DSIWARE_PUB", dsiWarePubPath); + settingsini.SetString("SRLOADER", "DSIWARE_PRV", dsiWarePrvPath); + settingsini.SetInt("SRLOADER", "SLOT1_LAUNCHED", slot1Launched); + settingsini.SetInt("SRLOADER", "LAUNCH_TYPE", launchType[0]); + settingsini.SetInt("SRLOADER", "SECONDARY_LAUNCH_TYPE", launchType[1]); + settingsini.SetInt("SRLOADER", "HOMEBREW_BOOTSTRAP", homebrewBootstrap); + settingsini.SetInt("SRLOADER", "HOMEBREW_HAS_WIDE", homebrewHasWide); + } + //settingsini.SetInt("SRLOADER", "THEME", theme); + //settingsini.SetInt("SRLOADER", "SUB_THEME", subtheme); + settingsini.SaveIniFile(settingsinipath); +} + +bool isDSPhat(void) { + return (isRegularDS && !isDSLite); +} + +bool useBackend = false; + +using namespace std; + +bool showbubble = false; +bool showSTARTborder = false; + +bool titleboxXmoveleft = false; +bool titleboxXmoveright = false; + +bool applaunchprep = false; + +int spawnedtitleboxes = 0; + +//char usernameRendered[10]; +//bool usernameRenderedDone = false; + +touchPosition touch; + +//--------------------------------------------------------------------------------- +void stop (void) { +//--------------------------------------------------------------------------------- + while (1) { + swiWaitForVBlank(); + } +} + +/** + * Set donor SDK version for a specific game. + */ +int SetDonorSDK(const char* filename) { + FILE *f_nds_file = fopen(filename, "rb"); + + char game_TID[5]; + grabTID(f_nds_file, game_TID); + fclose(f_nds_file); + game_TID[4] = 0; + game_TID[3] = 0; + + for (auto i : donorMap) { + if (i.first == 5 && game_TID[0] == 'V') + return 5; + + if (i.second.find(game_TID) != i.second.cend()) + return i.first; + } + + return 0; +} + +/** + * Set MPU settings for a specific game. + */ +void SetMPUSettings(const char* filename) { + FILE *f_nds_file = fopen(filename, "rb"); + + char game_TID[5]; + fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); + fread(game_TID, 1, 4, f_nds_file); + game_TID[4] = 0; + game_TID[3] = 0; + fclose(f_nds_file); + + scanKeys(); + int pressed = keysHeld(); + + if (pressed & KEY_B) { + mpuregion = 1; + } else if (pressed & KEY_X) { + mpuregion = 2; + } else if (pressed & KEY_Y) { + mpuregion = 3; + } else { + mpuregion = 0; + } + + if(pressed & KEY_RIGHT) { + mpusize = 3145728; + } else if(pressed & KEY_LEFT) { + mpusize = 1; + } else { + mpusize = 0; + } + + // Check for games that need an MPU size of 3 MB. + // TODO: If the list gets large enough, switch to bsearch(). + for (unsigned int i = 0; i < sizeof(mpu_3MB_list)/sizeof(mpu_3MB_list[0]); i++) { + if (!memcmp(game_TID, mpu_3MB_list[i], 3)) { + // Found a match. + mpuregion = 1; + mpusize = 3145728; + break; + } + } +} + +/** + * Move nds-bootstrap's cardEngine_arm9 to cached memory region for some games. + */ +void SetSpeedBumpExclude(const char* filename) { + if (!isDSiMode() || (perGameSettings_heapShrink >= 0 && perGameSettings_heapShrink < 2)) { + ceCached = perGameSettings_heapShrink; + return; + } + + FILE *f_nds_file = fopen(filename, "rb"); + + char game_TID[5]; + fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); + fread(game_TID, 1, 4, f_nds_file); + fclose(f_nds_file); + + // TODO: If the list gets large enough, switch to bsearch(). + for (unsigned int i = 0; i < sizeof(sbeList2)/sizeof(sbeList2[0]); i++) { + if (memcmp(game_TID, sbeList2[i], 3) == 0) { + // Found match + ceCached = false; + } + } +} + +/** + * Fix AP for some games. + */ +std::string setApFix(const char *filename) { + remove("fat:/_nds/nds-bootstrap/apFix.ips"); + + bool ipsFound = false; + char ipsPath[256]; + snprintf(ipsPath, sizeof(ipsPath), "%s:/_nds/TWiLightMenu/apfix/%s.ips", sdFound() ? "sd" : "fat", filename); + ipsFound = (access(ipsPath, F_OK) == 0); + + if (!ipsFound) { + FILE *f_nds_file = fopen(filename, "rb"); + + char game_TID[5]; + u16 headerCRC16 = 0; + fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); + fread(game_TID, 1, 4, f_nds_file); + fseek(f_nds_file, offsetof(sNDSHeaderExt, headerCRC16), SEEK_SET); + fread(&headerCRC16, sizeof(u16), 1, f_nds_file); + fclose(f_nds_file); + game_TID[4] = 0; + + snprintf(ipsPath, sizeof(ipsPath), "%s:/_nds/TWiLightMenu/apfix/%s-%X.ips", sdFound() ? "sd" : "fat", game_TID, headerCRC16); + ipsFound = (access(ipsPath, F_OK) == 0); + } + + if (ipsFound) { + if (secondaryDevice && sdFound()) { + mkdir("fat:/_nds", 0777); + mkdir("fat:/_nds/nds-bootstrap", 0777); + fcopy(ipsPath, "fat:/_nds/nds-bootstrap/apFix.ips"); + return "fat:/_nds/nds-bootstrap/apFix.ips"; + } + return ipsPath; + } + + return ""; +} + +/** + * Enable widescreen for some games. + */ +void SetWidescreen(const char *filename) { + remove("/_nds/nds-bootstrap/wideCheatData.bin"); + + bool useWidescreen = (perGameSettings_wideScreen == -1 ? wideScreen : perGameSettings_wideScreen); + + if ((isDSiMode() && arm7SCFGLocked) || consoleModel < 2 || !useWidescreen + || (access("sd:/luma/sysmodules/TwlBg.cxi", F_OK) != 0)) { + homebrewHasWide = false; + return; + } + + bool wideCheatFound = false; + char wideBinPath[256]; + if (launchType[secondaryDevice] == 1) { + snprintf(wideBinPath, sizeof(wideBinPath), "sd:/_nds/TWiLightMenu/widescreen/%s.bin", filename); + wideCheatFound = (access(wideBinPath, F_OK) == 0); + } + + if (slot1Launched) { + // Reset Slot-1 to allow reading card header + sysSetCardOwner (BUS_OWNER_ARM9); + disableSlot1(); + for(int i = 0; i < 25; i++) { swiWaitForVBlank(); } + enableSlot1(); + for(int i = 0; i < 15; i++) { swiWaitForVBlank(); } + + cardReadHeader((uint8*)&ndsCardHeader); + + char game_TID[5]; + tonccpy(game_TID, ndsCardHeader.gameCode, 4); + game_TID[4] = 0; + + snprintf(wideBinPath, sizeof(wideBinPath), "sd:/_nds/TWiLightMenu/widescreen/%s-%X.bin", game_TID, ndsCardHeader.headerCRC16); + wideCheatFound = (access(wideBinPath, F_OK) == 0); + } else if (!wideCheatFound) { + FILE *f_nds_file = fopen(filename, "rb"); + + char game_TID[5]; + u16 headerCRC16 = 0; + fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); + fread(game_TID, 1, 4, f_nds_file); + fseek(f_nds_file, offsetof(sNDSHeaderExt, headerCRC16), SEEK_SET); + fread(&headerCRC16, sizeof(u16), 1, f_nds_file); + fclose(f_nds_file); + game_TID[4] = 0; + + snprintf(wideBinPath, sizeof(wideBinPath), "sd:/_nds/TWiLightMenu/widescreen/%s-%X.bin", game_TID, headerCRC16); + wideCheatFound = (access(wideBinPath, F_OK) == 0); + } + + if (isHomebrew[secondaryDevice]) { + FILE *f_nds_file = fopen(filename, "rb"); + + char game_TID[5]; + u8 romVersion = 0; + fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); + fread(game_TID, 1, 4, f_nds_file); + fseek(f_nds_file, offsetof(sNDSHeaderExt, romversion), SEEK_SET); + fread(&romVersion, sizeof(u8), 1, f_nds_file); + fclose(f_nds_file); + game_TID[4] = 0; + + homebrewHasWide = (game_TID[0] == 'W' || romVersion == 0x57); + return; + } + + if (wideCheatFound) { + const char* resultText1; + const char* resultText2; + mkdir("/_nds", 0777); + mkdir("/_nds/nds-bootstrap", 0777); + if (fcopy(wideBinPath, "/_nds/nds-bootstrap/wideCheatData.bin") == 0) { + return; + } else { + resultText1 = "Failed to copy widescreen"; + resultText2 = "code for the game."; + } + remove("/_nds/nds-bootstrap/wideCheatData.bin"); + int textXpos[2] = {0}; + textXpos[0] = 72; + textXpos[1] = 84; + clearText(); + printSmallCentered(false, textXpos[0], resultText1); + printSmallCentered(false, textXpos[1], resultText2); + fadeType = true; // Fade in from white + for (int i = 0; i < 60 * 3; i++) { + swiWaitForVBlank(); // Wait 3 seconds + } + fadeType = false; // Fade to white + for (int i = 0; i < 25; i++) { + swiWaitForVBlank(); + } + } +} + +char filePath[PATH_MAX]; + +//--------------------------------------------------------------------------------- +void doPause() { +//--------------------------------------------------------------------------------- + // iprintf("Press start...\n"); + // printSmall(false, x, y, "Press start..."); + while(1) { + scanKeys(); + if(keysDown() & KEY_START) + break; + swiWaitForVBlank(); + } + scanKeys(); +} + +mm_sound_effect snd_launch; +mm_sound_effect snd_select; +mm_sound_effect snd_stop; +mm_sound_effect snd_wrong; +mm_sound_effect snd_back; +mm_sound_effect snd_switch; +mm_sound_effect snd_backlight; + +void InitSound() { + mmInitDefaultMem((mm_addr)soundbank_bin); + + mmLoadEffect( SFX_LAUNCH ); + mmLoadEffect( SFX_SELECT ); + mmLoadEffect( SFX_STOP ); + mmLoadEffect( SFX_WRONG ); + mmLoadEffect( SFX_BACK ); + mmLoadEffect( SFX_SWITCH ); + mmLoadEffect( SFX_BACKLIGHT ); + + snd_launch = { + { SFX_LAUNCH } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + snd_select = { + { SFX_SELECT } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + snd_stop = { + { SFX_STOP } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + snd_wrong = { + { SFX_WRONG } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + snd_back = { + { SFX_BACK } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + snd_switch = { + { SFX_SWITCH } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + snd_backlight = { + { SFX_BACKLIGHT } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; +} + +void loadGameOnFlashcard (const char* ndsPath, bool dsGame) { + bool runNds_boostCpu = false; + bool runNds_boostVram = false; + std::string filename = ndsPath; + const size_t last_slash_idx = filename.find_last_of("/"); + if (std::string::npos != last_slash_idx) { + filename.erase(0, last_slash_idx + 1); + } + + loadPerGameSettings(filename); + + if ((REG_SCFG_EXT != 0) && dsGame) { + runNds_boostCpu = perGameSettings_boostCpu == -1 ? boostCpu : perGameSettings_boostCpu; + runNds_boostVram = perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram; + } + if (dsGame) { + // Move .sav outside of "saves" folder for flashcard kernel usage + const char *typeToReplace = ".nds"; + if (extention(filename, ".dsi")) { + typeToReplace = ".dsi"; + } else if (extention(filename, ".ids")) { + typeToReplace = ".ids"; + } else if (extention(filename, ".srl")) { + typeToReplace = ".srl"; + } else if (extention(filename, ".app")) { + typeToReplace = ".app"; + } + + std::string savename = replaceAll(filename, typeToReplace, getSavExtension()); + std::string savenameFc = replaceAll(filename, typeToReplace, ".sav"); + std::string romFolderNoSlash = romfolder[true]; + RemoveTrailingSlashes(romFolderNoSlash); + std::string saveFolder = romFolderNoSlash + "/saves"; + mkdir(saveFolder.c_str(), 0777); + std::string savepath = romFolderNoSlash + "/saves/" + savename; + std::string savepathFc = romFolderNoSlash + "/" + savenameFc; + rename(savepath.c_str(), savepathFc.c_str()); + } + + std::string fcPath; + int err = 0; + + switch (flashcard) { + case 1: { + CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); + fcPath = replaceAll(ndsPath, "fat:/", slashchar); + fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); + fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); + err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 6: // Blue card can run wood 1.62 so this should work? + case 2: // And clones that can run wood (no N5) + case 3: { + CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); + fcPath = replaceAll(ndsPath, "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); + err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 7: { + CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); + fcPath = replaceAll(ndsPath, "fat:/", dstwofat); + fcrompathini.SetString("Dir Info", "fullName", fcPath); + fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); + err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 5: // ? + case 4: { + CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); + fcPath = replaceAll(ndsPath, "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); + err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + default: { + err = 1337; + return; + } + } + + + char text[32]; + snprintf(text, sizeof(text), "Start failed. Error %i", err); + ClearBrightness(); + printSmall(false, 4, 4, text); + if (err == 0) { + printSmall(false, 4, 20, "Flashcard may be unsupported."); + printSmall(false, 4, 52, "Flashcard name:"); + printSmall(false, 4, 68, io_dldi_data->friendlyName); + } + stop(); +} + +void loadROMselect() +{ + if (!isDSiMode()) { + chdir("fat:/"); + } else if (sdFound()) { + chdir("sd:/"); + } + /*if (theme == 3) + { + runNdsFile("/_nds/TWiLightMenu/akmenu.srldr", 0, NULL, true, false, false, true, true); + } + else */if (theme == 2 || theme == 6) + { + runNdsFile("/_nds/TWiLightMenu/r4menu.srldr", 0, NULL, true, false, false, true, true); + } + else + { + runNdsFile("/_nds/TWiLightMenu/dsimenu.srldr", 0, NULL, true, false, false, true, true); + } +} + +void unlaunchRomBoot(const char* rom) { + char unlaunchDevicePath[256] = {0}; + if (strncmp(rom, "cart:", 5) == 0) { + sprintf(unlaunchDevicePath, "cart:"); + } else { + sprintf(unlaunchDevicePath, "__%s", rom); + unlaunchDevicePath[0] = 's'; + unlaunchDevicePath[1] = 'd'; + unlaunchDevicePath[2] = 'm'; + unlaunchDevicePath[3] = 'c'; + } + + tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); + *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) + *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) + *(u32*)(0x02000810) = 0; // Unlaunch Flags + *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h + *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h + *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) + *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) + toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) + int i2 = 0; + for (int i = 0; i < (int)sizeof(unlaunchDevicePath); i++) { + *(u8*)(0x02000838+i2) = unlaunchDevicePath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) + i2 += 2; + } + while (*(u16*)(0x0200080E) == 0) { // Keep running, so that CRC16 isn't 0 + *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 + } + + DC_FlushAll(); // Make reboot not fail + fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Unlaunch + stop(); +} + +void unlaunchSetHiyaBoot(void) { + tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); + *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) + *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) + *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h + *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h + *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) + *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) + toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) + int i2 = 0; + for (int i = 0; i < 14; i++) { + *(u8*)(0x02000838+i2) = hiyaNdsPath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) + i2 += 2; + } + while (*(u16*)(0x0200080E) == 0) { // Keep running, so that CRC16 isn't 0 + *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 + } +} + +/** + * Reboot into an SD game when in DS mode. + */ +void ntrStartSdGame(void) { + if (consoleModel == 0) { + unlaunchRomBoot("sd:/_nds/TWiLightMenu/resetgame.srldr"); + } else { + tonccpy((u32 *)0x02000300, sr_data_srllastran, 0x020); + DC_FlushAll(); // Make reboot not fail + fifoSendValue32(FIFO_USER_02, 1); + stop(); + } +} + +void dsCardLaunch() { + *(u32*)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag + *(u16*)(0x02000304) = 0x1801; + *(u32*)(0x02000308) = 0x43415254; // "CART" + *(u32*)(0x0200030C) = 0x00000000; + *(u32*)(0x02000310) = 0x43415254; // "CART" + *(u32*)(0x02000314) = 0x00000000; + *(u32*)(0x02000318) = 0x00000013; + *(u32*)(0x0200031C) = 0x00000000; + while (*(u16*)(0x02000306) == 0) { // Keep running, so that CRC16 isn't 0 + *(u16*)(0x02000306) = swiCRC16(0xFFFF, (void*)0x02000308, 0x18); + } + + unlaunchSetHiyaBoot(); + + DC_FlushAll(); // Make reboot not fail + fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher + stop(); +} + +void directCardLaunch() { + /*if (memcmp(ndsCardHeader.gameCode, "ALXX", 4) == 0) { + u16 alxxBannerCrc = 0; + extern u32 arm9StartSig[4]; + cardRead(0x75600, &arm9StartSig, 0x10); + cardRead(0x174602, &alxxBannerCrc, sizeof(u16)); + if ((arm9StartSig[0] == 0xE58D0008 + && arm9StartSig[1] == 0xE1500005 + && arm9StartSig[2] == 0xBAFFFFC5 + && arm9StartSig[3] == 0xE59D100C) + || alxxBannerCrc != 0xBA52) + { + if (sdFound()) { + chdir("sd:/"); + } + int err = runNdsFile ("/_nds/TWiLightMenu/dstwoLaunch.srldr", 0, NULL, true, true, true, boostCpu, boostVram); + char text[32]; + snprintf(text, sizeof(text), "Start failed. Error %i", err); + ClearBrightness(); + printSmall(false, 4, 4, text); + stop(); + } + }*/ + SetWidescreen(NULL); + if (sdFound()) { + chdir("sd:/"); + } + int err = runNdsFile ("/_nds/TWiLightMenu/slot1launch.srldr", 0, NULL, true, true, false, true, true); + char text[32]; + snprintf(text, sizeof(text), "Start failed. Error %i", err); + ClearBrightness(); + printSmall(false, 4, 4, text); + stop(); +} + +void printLastPlayedText(int num) { + printSmallCentered(false, 24, iconYpos[num]+BOX_PY+BOX_PY_spacing2, "Last-played game"); + printSmallCentered(false, 24, iconYpos[num]+BOX_PY+BOX_PY_spacing3, "will appear here."); +} + +void refreshNdsCard() { + if (cardRefreshed) return; + + if (arm7SCFGLocked && showBoxArt) { + loadBoxArt("nitro:/graphics/boxart_unknown.png"); + } else if ((cardInit(true) == 0) && showBoxArt) { + char game_TID[5] = {0}; + tonccpy(&game_TID, ndsCardHeader.gameCode, 4); + + char boxArtPath[256]; + sprintf (boxArtPath, (sdFound() ? "sd:/_nds/TWiLightMenu/boxart/%s.png" : "fat:/_nds/TWiLightMenu/boxart/%s.png"), game_TID); + loadBoxArt(boxArtPath); // Load box art + } else if (showBoxArt) { + loadBoxArt("nitro:/graphics/boxart_unknown.png"); + } + + getGameInfo(1, false, "slot1"); + iconUpdate (1, false, "slot1"); + bnrRomType[1] = 0; + boxArtType[1] = 0; + + // Power off after done retrieving info + disableSlot1(); + + cardRefreshed = true; + cardEjected = false; +} + +void printNdsCartBannerText() { + if (cardEjected) { + printSmallCentered(false, 24, iconYpos[0]+BOX_PY+BOX_PY_spacing2, "There is no Game Card"); + printSmallCentered(false, 24, iconYpos[0]+BOX_PY+BOX_PY_spacing3, "inserted."); + } else if (arm7SCFGLocked) { + printSmallCentered(false, 24, iconYpos[0]+BOX_PY+BOX_PY_spacing1, "Start Game Card"); + } else { + titleUpdate(1, false, "slot1"); + } +} + +void printGbaBannerText() { + printSmallCentered(false, 24, iconYpos[3]+BOX_PY+BOX_PY_spacing1, isRegularDS ? gbamodeText : featureUnavailableText); +} + +//--------------------------------------------------------------------------------- +int main(int argc, char **argv) { +//--------------------------------------------------------------------------------- + + defaultExceptionHandler(); + + useTwlCfg = (REG_SCFG_EXT!=0 && (*(u8*)0x02000400 & 0x0F) && (*(u8*)0x02000401 == 0) && (*(u8*)0x02000402 == 0) && (*(u8*)0x02000404 == 0) && (*(u8*)0x02000448 != 0)); + + extern const DISC_INTERFACE __my_io_dsisd; + + *(u32*)(0x2FFFD0C) = 0x54494D52; // Run reboot timer + fatMountSimple("sd", &__my_io_dsisd); + fatMountSimple("fat", dldiGetInternal()); + bool fatInited = (sdFound() || flashcardFound()); + *(u32*)(0x2FFFD0C) = 0; + chdir(sdFound()&&isDSiMode() ? "sd:/" : "fat:/"); + + // Read user name + /*char *username = (char*)PersonalData->name; + + // text + for (int i = 0; i < 10; i++) { + if (username[i*2] == 0x00) + username[i*2/2] = 0; + else + username[i*2/2] = username[i*2]; + }*/ + + if (!fatInited) { + graphicsInit(); + fontInit(); + whiteScreen = true; + printSmall(false, 64, 32, "fatinitDefault failed!"); + fadeType = true; + stop(); + } + + nitroFSInit("/_nds/TWiLightMenu/mainmenu.srldr"); + + if (access(settingsinipath, F_OK) != 0 && flashcardFound()) { + settingsinipath = "fat:/_nds/TWiLightMenu/settings.ini"; // Fallback to .ini path on flashcard, if not found on SD card, or if SD access is disabled + } + + langInit(); + + std::string filename[2]; + + fifoWaitValue32(FIFO_USER_06); + if (fifoGetValue32(FIFO_USER_03) == 0) arm7SCFGLocked = true; // If TWiLight Menu++ is being run from DSiWarehax or flashcard, then arm7 SCFG is locked. + u16 arm7_SNDEXCNT = fifoGetValue32(FIFO_USER_07); + if (arm7_SNDEXCNT != 0) isRegularDS = false; // If sound frequency setting is found, then the console is not a DS Phat/Lite + isDSLite = fifoGetValue32(FIFO_USER_04); + fifoSendValue32(FIFO_USER_07, 0); + + LoadSettings(); + widescreenEffects = (consoleModel >= 2 && wideScreen && access("sd:/luma/sysmodules/TwlBg.cxi", F_OK) == 0); + + snprintf(pictochatPath, sizeof(pictochatPath), "/_nds/pictochat.nds"); + pictochatFound = (access(pictochatPath, F_OK) == 0); + + if (isDSiMode() && arm7SCFGLocked) { + if (consoleModel < 2 && !pictochatFound) { + pictochatFound = true; + pictochatReboot = true; + } + dlplayFound = true; + dlplayReboot = true; + } else { + bool nandInited = false; + char srcPath[256]; + u8 regions[3] = {0x41, 0x43, 0x4B}; + + if (!pictochatFound && consoleModel == 0) { + for (int i = 0; i < 3; i++) + { + snprintf(pictochatPath, sizeof(pictochatPath), "/title/00030005/484e45%x/content/00000000.app", regions[i]); + if (access(pictochatPath, F_OK) == 0) + { + pictochatFound = true; + break; + } + } + } + if (!pictochatFound && isDSiMode() && sdFound() && consoleModel == 0) { + if (!nandInited) { + fatMountSimple("nand", &io_dsi_nand); + nandInited = true; + } + if (access("nand:/", F_OK) == 0) { + for (int i = 0; i < 3; i++) + { + snprintf(srcPath, sizeof(srcPath), "nand:/title/00030005/484e45%x/content/00000000.app", regions[i]); + if (access(srcPath, F_OK) == 0) + { + snprintf(pictochatPath, sizeof(pictochatPath), "/_nds/pictochat.nds"); + remove(pictochatPath); + fcopy(srcPath, pictochatPath); // Copy from NAND + pictochatFound = true; + break; + } + } + } + } + + snprintf(dlplayPath, sizeof(dlplayPath), "/_nds/dlplay.nds"); + dlplayFound = (access(dlplayPath, F_OK) == 0); + if (!dlplayFound && consoleModel == 0) { + for (int i = 0; i < 3; i++) + { + snprintf(dlplayPath, sizeof(dlplayPath), "/title/00030005/484e44%x/content/00000000.app", regions[i]); + if (access(dlplayPath, F_OK) == 0) { + dlplayFound = true; + break; + } else if (regions[i] != 0x43 && regions[i] != 0x4B) { + snprintf(dlplayPath, sizeof(dlplayPath), "/title/00030005/484e4441/content/00000001.app"); + if (access(dlplayPath, F_OK) == 0) { + dlplayFound = true; + break; + } + } + } + } + if (!dlplayFound && isDSiMode() && sdFound() && consoleModel == 0) { + if (!nandInited) { + fatMountSimple("nand", &io_dsi_nand); + nandInited = true; + } + if (access("nand:/", F_OK) == 0) { + for (int i = 0; i < 3; i++) + { + snprintf(srcPath, sizeof(srcPath), "nand:/title/00030005/484e44%x/content/00000000.app", regions[i]); + if (access(srcPath, F_OK) == 0) { + snprintf(dlplayPath, sizeof(dlplayPath), "/_nds/dlplay.nds"); + remove(dlplayPath); + fcopy(srcPath, dlplayPath); // Copy from NAND + dlplayFound = true; + break; + } else if (regions[i] != 0x43 && regions[i] != 0x4B) { + snprintf(srcPath, sizeof(srcPath), "nand:/title/00030005/484e4441/content/00000001.app"); + if (access(srcPath, F_OK) == 0) { + snprintf(dlplayPath, sizeof(dlplayPath), "/_nds/dlplay.nds"); + remove(dlplayPath); + fcopy(srcPath, dlplayPath); // Copy from NAND + dlplayFound = true; + break; + } + } + } + } + } + if (!dlplayFound && consoleModel >= 2) { + dlplayFound = true; + dlplayReboot = true; + } + } + + if (isDSiMode() && sdFound() && consoleModel < 2 && launcherApp != -1) { + u8 setRegion = 0; + if (sysRegion == -1) { + // Determine SysNAND region by searching region of System Settings on SDNAND + char tmdpath[256]; + for (u8 i = 0x41; i <= 0x5A; i++) + { + snprintf(tmdpath, sizeof(tmdpath), "sd:/title/00030015/484e42%x/content/title.tmd", i); + if (access(tmdpath, F_OK) == 0) + { + setRegion = i; + break; + } + } + } else { + switch(sysRegion) { + case 0: + default: + setRegion = 0x4A; // JAP + break; + case 1: + setRegion = 0x45; // USA + break; + case 2: + setRegion = 0x50; // EUR + break; + case 3: + setRegion = 0x55; // AUS + break; + case 4: + setRegion = 0x43; // CHN + break; + case 5: + setRegion = 0x4B; // KOR + break; + } + } + + snprintf(unlaunchDevicePath, sizeof(unlaunchDevicePath), "nand:/title/00030017/484E41%x/content/0000000%i.app", setRegion, launcherApp); + } + + graphicsInit(); + fontInit(); + + iconTitleInit(); + + InitSound(); + + keysSetRepeat(25,5); + + srand(time(NULL)); + + bool menuButtonPressed = false; + + if (flashcardFound()) { + // Move .sav back to "saves" folder + std::string filename = romPath[true]; + const size_t last_slash_idx = filename.find_last_of("/"); + if (std::string::npos != last_slash_idx) { + filename.erase(0, last_slash_idx + 1); + } + + loadPerGameSettings(filename); + + const char *typeToReplace = ".nds"; + if (extention(filename, ".dsi")) { + typeToReplace = ".dsi"; + } else if (extention(filename, ".ids")) { + typeToReplace = ".ids"; + } else if (extention(filename, ".srl")) { + typeToReplace = ".srl"; + } else if (extention(filename, ".app")) { + typeToReplace = ".app"; + } + + std::string savename = replaceAll(filename, typeToReplace, getSavExtension()); + std::string savenameFc = replaceAll(filename, typeToReplace, ".sav"); + std::string romFolderNoSlash = romfolder[true]; + RemoveTrailingSlashes(romFolderNoSlash); + std::string savepath = romFolderNoSlash + "/saves/" + savename; + std::string savepathFc = romFolderNoSlash + "/" + savenameFc; + if (access(savepathFc.c_str(), F_OK) == 0) { + rename(savepathFc.c_str(), savepath.c_str()); + } + } + + if (consoleModel < 2 + && previousUsedDevice + && bothSDandFlashcard() + && launchType[previousUsedDevice] == 3 + && !dsiWareBooter + && ( + (access(dsiWarePubPath.c_str(), F_OK) == 0 && extention(dsiWarePubPath.c_str(), ".pub")) + || (access(dsiWarePrvPath.c_str(), F_OK) == 0 && extention(dsiWarePrvPath.c_str(), ".prv")) + ) + ) { + controlTopBright = false; + whiteScreen = true; + fadeType = true; // Fade in from white + printSmallCentered(false, 24, "If this takes a while, close and open"); + printSmallCentered(false, 38, "the console's lid."); + printSmallCentered(false, 86, "Now copying data..."); + printSmallCentered(false, 100, "Do not turn off the power."); + for (int i = 0; i < 30; i++) swiWaitForVBlank(); + if (access(dsiWarePubPath.c_str(), F_OK) == 0) { + fcopy("sd:/_nds/TWiLightMenu/tempDSiWare.pub", dsiWarePubPath.c_str()); + } + if (access(dsiWarePrvPath.c_str(), F_OK) == 0) { + fcopy("sd:/_nds/TWiLightMenu/tempDSiWare.prv", dsiWarePrvPath.c_str()); + } + fadeType = false; // Fade to white + for (int i = 0; i < 30; i++) swiWaitForVBlank(); + clearText(false); + whiteScreen = false; + controlTopBright = true; + } + + topBgLoad(); + bottomBgLoad(); + + bool romFound[2] = {false}; + + // SD card + if (sdFound() && romPath[0] != "" && access(romPath[0].c_str(), F_OK) == 0) { + romFound[0] = true; + + romfolder[0] = romPath[0]; + while (!romfolder[0].empty() && romfolder[0][romfolder[0].size()-1] != '/') { + romfolder[0].resize(romfolder[0].size()-1); + } + chdir(romfolder[0].c_str()); + + filename[0] = romPath[0]; + const size_t last_slash_idx = filename[0].find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + filename[0].erase(0, last_slash_idx + 1); + } + + if (extention(filename[0], ".nds") || extention(filename[0], ".dsi") || extention(filename[0], ".ids") || extention(filename[0], ".app") || extention(filename[0], ".srl") || extention(filename[0], ".argv")) { + getGameInfo(0, false, filename[0].c_str()); + iconUpdate (0, false, filename[0].c_str()); + bnrRomType[0] = 0; + boxArtType[0] = 0; + } else if (extention(filename[0], ".plg") || extention(filename[0], ".rvid") || extention(filename[0], ".mp4") || extention(filename[0], ".a26") || extention(filename[0], ".pce")) { + bnrRomType[0] = 9; + boxArtType[0] = 0; + } else if (extention(filename[0], ".gba")) { + bnrRomType[0] = 1; + boxArtType[0] = 1; + } else if (extention(filename[0], ".gb") || extention(filename[0], ".sgb")) { + bnrRomType[0] = 2; + boxArtType[0] = 1; + } else if (extention(filename[0], ".gbc")) { + bnrRomType[0] = 3; + boxArtType[0] = 1; + } else if (extention(filename[0], ".nes")) { + bnrRomType[0] = 4; + boxArtType[0] = 2; + } else if (extention(filename[0], ".fds")) { + bnrRomType[0] = 4; + boxArtType[0] = 1; + } else if (extention(filename[0], ".sms")) { + bnrRomType[0] = 5; + boxArtType[0] = 2; + } else if (extention(filename[0], ".gg")) { + bnrRomType[0] = 6; + boxArtType[0] = 2; + } else if (extention(filename[0], ".gen")) { + bnrRomType[0] = 7; + boxArtType[0] = 2; + } else if (extention(filename[0], ".smc")) { + bnrRomType[0] = 8; + boxArtType[0] = 3; + } else if (extention(filename[0], ".sfc")) { + bnrRomType[0] = 8; + boxArtType[0] = 2; + } + } + + // Flashcard (Secondary device) + if (flashcardFound() && romPath[1] != "" && access(romPath[1].c_str(), F_OK) == 0) { + romFound[1] = true; + + romfolder[1] = romPath[1]; + while (!romfolder[1].empty() && romfolder[1][romfolder[1].size()-1] != '/') { + romfolder[1].resize(romfolder[1].size()-1); + } + chdir(romfolder[1].c_str()); + + filename[1] = romPath[1]; + const size_t last_slash_idx = filename[1].find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + filename[1].erase(0, last_slash_idx + 1); + } + + if (extention(filename[1], ".nds") || extention(filename[1], ".dsi") || extention(filename[1], ".ids") || extention(filename[1], ".app") || extention(filename[1], ".srl") || extention(filename[1], ".argv")) { + getGameInfo(1, false, filename[1].c_str()); + iconUpdate (1, false, filename[1].c_str()); + bnrRomType[1] = 0; + boxArtType[1] = 0; + } else if (extention(filename[1], ".plg") || extention(filename[1], ".rvid") || extention(filename[1], ".mp4") || extention(filename[1], ".a26")) { + bnrRomType[1] = 9; + boxArtType[1] = 0; + } else if (extention(filename[1], ".gba")) { + bnrRomType[1] = 1; + boxArtType[1] = 1; + } else if (extention(filename[1], ".gb") || extention(filename[1], ".sgb")) { + bnrRomType[1] = 2; + boxArtType[1] = 1; + } else if (extention(filename[1], ".gbc")) { + bnrRomType[1] = 3; + boxArtType[1] = 1; + } else if (extention(filename[1], ".nes")) { + bnrRomType[1] = 4; + boxArtType[1] = 2; + } else if (extention(filename[1], ".fds")) { + bnrRomType[1] = 4; + boxArtType[1] = 1; + } else if (extention(filename[1], ".sms")) { + bnrRomType[1] = 5; + boxArtType[1] = 2; + } else if (extention(filename[1], ".gg")) { + bnrRomType[1] = 6; + boxArtType[1] = 2; + } else if (extention(filename[1], ".gen")) { + bnrRomType[1] = 7; + boxArtType[1] = 2; + } else if (extention(filename[1], ".smc")) { + bnrRomType[1] = 8; + boxArtType[1] = 3; + } else if (extention(filename[1], ".sfc")) { + bnrRomType[1] = 8; + boxArtType[1] = 2; + } + + if (showBoxArt) { + // Store box art path + std::string temp_filename = filename[secondaryDevice]; + char boxArtPath[256]; + snprintf (boxArtPath, sizeof(boxArtPath), (sdFound() ? "sd:/_nds/TWiLightMenu/boxart/%s.png" : "fat:/_nds/TWiLightMenu/boxart/%s.png"), filename[0].c_str()); + if ((access(boxArtPath, F_OK) != 0) && (bnrRomType[secondaryDevice] == 0)) { + if(extention(filename[0], ".argv")) { + vector argarray; + + FILE *argfile = fopen(filename[0].c_str(),"rb"); + char str[PATH_MAX], *pstr; + const char seps[]= "\n\r\t "; + + while( fgets(str, PATH_MAX, argfile) ) { + // Find comment and end string there + if( (pstr = strchr(str, '#')) ) + *pstr= '\0'; + + // Tokenize arguments + pstr= strtok(str, seps); + + while( pstr != NULL ) { + argarray.push_back(strdup(pstr)); + pstr= strtok(NULL, seps); + } + } + fclose(argfile); + temp_filename = argarray.at(0); + } + // Get game's TID + FILE *f_nds_file = fopen(temp_filename.c_str(), "rb"); + char game_TID[5]; + grabTID(f_nds_file, game_TID); + game_TID[4] = 0; + fclose(f_nds_file); + + sprintf (boxArtPath, (sdFound() ? "sd:/_nds/TWiLightMenu/boxart/%s.png" : "fat:/_nds/TWiLightMenu/boxart/%s.png"), game_TID); + } + loadBoxArt(boxArtPath); // Load box art + } + } + + if (isDSiMode() && !flashcardFound()) { + if (REG_SCFG_MC == 0x11) { + if (showBoxArt) loadBoxArt("nitro:/graphics/boxart_unknown.png"); + cardEjected = true; + } else { + refreshNdsCard(); + } + } + + whiteScreen = false; + fadeType = true; // Fade in from white + for (int i = 0; i < 30; i++) { + swiWaitForVBlank(); + } + topBarLoad(); + startMenu = true; // Show bottom screen graphics + fadeSpeed = false; + + while(1) { + + if (startMenu) { + int pressed = 0; + + do { + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (flashcardFound()) { + if (romFound[1]) { + titleUpdate(1, false, filename[1].c_str()); + } else { + printLastPlayedText(0); + } + } else if (isDSiMode() && !flashcardFound()) { + printNdsCartBannerText(); + } + if (!sdFound()) { + printGbaBannerText(); + } else if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + + if (isDSiMode() && !flashcardFound()) { + if (REG_SCFG_MC == 0x11) { + if (cardRefreshed && showBoxArt) { + loadBoxArt("nitro:/graphics/boxart_unknown.png"); + } + cardRefreshed = false; + cardEjected = true; + } else if (cardEjected) { + refreshNdsCard(); + } + } + + scanKeys(); + pressed = keysDownRepeat(); + touchRead(&touch); + checkSdEject(); + swiWaitForVBlank(); + } while (!pressed); + + if (pressed & KEY_UP) { + if (startMenu_cursorPosition == 2 || startMenu_cursorPosition == 3 || startMenu_cursorPosition == 5) { + startMenu_cursorPosition -= 2; + mmEffectEx(&snd_select); + } else if (startMenu_cursorPosition == 6) { + startMenu_cursorPosition -= 3; + mmEffectEx(&snd_select); + } else { + startMenu_cursorPosition--; + mmEffectEx(&snd_select); + } + } + + if (pressed & KEY_DOWN) { + if (startMenu_cursorPosition == 1 || startMenu_cursorPosition == 3) { + startMenu_cursorPosition += 2; + mmEffectEx(&snd_select); + } else if (startMenu_cursorPosition >= 0 && startMenu_cursorPosition <= 3) { + startMenu_cursorPosition++; + mmEffectEx(&snd_select); + } + } + + if (pressed & KEY_LEFT) { + if (startMenu_cursorPosition == 2 || (startMenu_cursorPosition == 5 && isDSiMode() && consoleModel < 2) + || startMenu_cursorPosition == 6) { + startMenu_cursorPosition--; + mmEffectEx(&snd_select); + } + } + + if (pressed & KEY_RIGHT) { + if (startMenu_cursorPosition == 1 || startMenu_cursorPosition == 4 || startMenu_cursorPosition == 5) { + startMenu_cursorPosition++; + mmEffectEx(&snd_select); + } + } + + if (pressed & KEY_TOUCH) { + if (touch.px >= 33 && touch.px <= 221 && touch.py >= 25 && touch.py <= 69) { + startMenu_cursorPosition = 0; + menuButtonPressed = true; + } else if (touch.px >= 33 && touch.px <= 125 && touch.py >= 73 && touch.py <= 117) { + startMenu_cursorPosition = 1; + menuButtonPressed = true; + } else if (touch.px >= 129 && touch.px <= 221 && touch.py >= 73 && touch.py <= 117) { + startMenu_cursorPosition = 2; + menuButtonPressed = true; + } else if (touch.px >= 33 && touch.px <= 221 && touch.py >= 121 && touch.py <= 165) { + startMenu_cursorPosition = 3; + menuButtonPressed = true; + } else if (touch.px >= 10 && touch.px <= 20 && touch.py >= 175 && touch.py <= 185 + && isDSiMode() && consoleModel < 2) + { + startMenu_cursorPosition = 4; + menuButtonPressed = true; + } else if (touch.px >= 117 && touch.px <= 137 && touch.py >= 170 && touch.py <= 190) { + startMenu_cursorPosition = 5; + menuButtonPressed = true; + } else if (touch.px >= 235 && touch.px <= 244 && touch.py >= 175 && touch.py <= 185) { + startMenu_cursorPosition = 6; + menuButtonPressed = true; + } + } + + if (pressed & KEY_A) { + menuButtonPressed = true; + } + + if (startMenu_cursorPosition < 0) startMenu_cursorPosition = 0; + if (startMenu_cursorPosition > 6) startMenu_cursorPosition = 6; + + if (menuButtonPressed) { + switch (startMenu_cursorPosition) { + case -1: + default: + break; + case 0: + if (flashcardFound()) { + // Launch last-run ROM (Secondary) + if (launchType[1] == 0) { + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[0] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (romFound[1]) { + titleUpdate(1, false, filename[1].c_str()); + } else { + printLastPlayedText(0); + } + if (!sdFound()) { + printGbaBannerText(); + } else if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + loadROMselect(); + } else if (launchType[1] > 0) { + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[0] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (romFound[1]) { + titleUpdate(1, false, filename[1].c_str()); + } else { + printLastPlayedText(0); + } + if (!sdFound()) { + printGbaBannerText(); + } else if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + if (romFound[1]) { + applaunch = true; + } else { + loadROMselect(); + } + } + secondaryDevice = true; + } else if (!flashcardFound() && REG_SCFG_MC != 0x11) { + // Launch Slot-1 + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[0] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + printNdsCartBannerText(); + if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + slot1Launched = true; + SaveSettings(); + + if (slot1LaunchMethod == 0 || arm7SCFGLocked) { + dsCardLaunch(); + } else if (slot1LaunchMethod == 2) { + unlaunchRomBoot("cart:"); + } else { + directCardLaunch(); + } + } else { + mmEffectEx(&snd_wrong); + } + break; + case 1: + if (pictochatFound) { + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[1] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (!sdFound()) { + printGbaBannerText(); + } else if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + + // Clear screen with white + whiteScreen = true; + controlTopBright = false; + clearText(); + + if (pictochatReboot) { + *(u32 *)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag + *(u16 *)(0x02000304) = 0x1801; + + switch (sysRegion) { + case 4: + *(u32 *)(0x02000308) = 0x484E4543; + *(u32 *)(0x0200030C) = 0x00030005; + *(u32 *)(0x02000310) = 0x484E4543; + break; + case 5: + *(u32 *)(0x02000308) = 0x484E454B; + *(u32 *)(0x0200030C) = 0x00030005; + *(u32 *)(0x02000310) = 0x484E454B; + break; + default: + *(u32 *)(0x02000308) = 0x484E4541; // "HNEA" + *(u32 *)(0x0200030C) = 0x00030005; + *(u32 *)(0x02000310) = 0x484E4541; // "HNEA" + } + + *(u32 *)(0x02000314) = 0x00030005; + *(u32 *)(0x02000318) = 0x00000017; + *(u32 *)(0x0200031C) = 0x00000000; + while (*(u16 *)(0x02000306) == 0x0000) + { // Keep running, so that CRC16 isn't 0 + *(u16 *)(0x02000306) = swiCRC16(0xFFFF, (void *)0x02000308, 0x18); + } + + if (consoleModel < 2) { + unlaunchSetHiyaBoot(); + } + + fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher + for (int i = 0; i < 15; i++) swiWaitForVBlank(); + } else { + if (sdFound()) { + chdir("sd:/"); + } + int err = runNdsFile (pictochatPath, 0, NULL, true, true, true, false, false); + char text[32]; + snprintf (text, sizeof(text), "Start failed. Error %i", err); + clearText(); + ClearBrightness(); + printSmall(false, 4, 80, text); + stop(); + } + } else { + mmEffectEx(&snd_wrong); + } + break; + case 2: + if (dlplayFound) { + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[2] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (!sdFound()) { + printGbaBannerText(); + } else if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + + // Clear screen with white + whiteScreen = true; + controlTopBright = false; + clearText(); + + if (dlplayReboot) { + *(u32 *)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag + *(u16 *)(0x02000304) = 0x1801; + + switch (sysRegion) { + case 4: + *(u32 *)(0x02000308) = 0x484E4443; + *(u32 *)(0x0200030C) = 0x00030005; + *(u32 *)(0x02000310) = 0x484E4443; + break; + case 5: + *(u32 *)(0x02000308) = 0x484E444B; + *(u32 *)(0x0200030C) = 0x00030005; + *(u32 *)(0x02000310) = 0x484E444B; + break; + default: + *(u32 *)(0x02000308) = 0x484E4441; // "HNDA" + *(u32 *)(0x0200030C) = 0x00030005; + *(u32 *)(0x02000310) = 0x484E4441; // "HNDA" + } + + *(u32 *)(0x02000314) = 0x00030005; + *(u32 *)(0x02000318) = 0x00000017; + *(u32 *)(0x0200031C) = 0x00000000; + while (*(u16 *)(0x02000306) == 0x0000) + { // Keep running, so that CRC16 isn't 0 + *(u16 *)(0x02000306) = swiCRC16(0xFFFF, (void *)0x02000308, 0x18); + } + + if (consoleModel < 2) { + unlaunchSetHiyaBoot(); + } + + fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher + for (int i = 0; i < 15; i++) swiWaitForVBlank(); + } else { + if (sdFound()) { + chdir("sd:/"); + } + int err = runNdsFile (dlplayPath, 0, NULL, true, true, true, false, false); + char text[32]; + snprintf (text, sizeof(text), "Start failed. Error %i", err); + clearText(); + ClearBrightness(); + printSmall(false, 4, 80, text); + stop(); + } + } else { + mmEffectEx(&snd_wrong); + } + break; + case 3: + if (sdFound()) { + // Launch last-run ROM (SD) + if (launchType[0] == 0) { + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[3] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + loadROMselect(); + } else if (launchType[0] > 0) { + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[3] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + if (romFound[0]) { + titleUpdate(0, false, filename[0].c_str()); + } else { + printLastPlayedText(3); + } + swiWaitForVBlank(); + } + if (romFound[0]) { + applaunch = true; + } else { + loadROMselect(); + } + } + secondaryDevice = false; + } else if (isRegularDS) { + // Switch to GBA mode + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[3] -= 6; + clearText(); + printSmall(false, 6, 6, "\u2428 Back"); // "(B) Back" + printSmallCentered(false, 112, 6, RetTime().c_str()); + printGbaBannerText(); + swiWaitForVBlank(); + } + gbaSwitch(); + } else { + mmEffectEx(&snd_wrong); + } + break; + case 4: + // Adjust backlight level + if (isDSiMode() && consoleModel < 2) { + fifoSendValue32(FIFO_USER_04, 1); + mmEffectEx(&snd_backlight); + } + break; + case 5: + // Launch settings + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[5] -= 6; + swiWaitForVBlank(); + } + + gotosettings = true; + //SaveSettings(); + if (!isDSiMode()) { + chdir("fat:/"); + } else if (sdFound()) { + chdir("sd:/"); + } + int err = runNdsFile ("/_nds/TWiLightMenu/settings.srldr", 0, NULL, true, false, false, true, true); + iprintf ("Start failed. Error %i\n", err); + break; + } + if (startMenu_cursorPosition == 6) { + // Open manual + showCursor = false; + fadeType = false; // Fade to white + mmEffectEx(&snd_launch); + for (int i = 0; i < 50; i++) { + iconYpos[6] -= 6; + swiWaitForVBlank(); + } + if (!isDSiMode()) { + chdir("fat:/"); + } else if (sdFound()) { + chdir("sd:/"); + } + int err = runNdsFile ("/_nds/TWiLightMenu/manual.srldr", 0, NULL, true, false, false, true, true); + iprintf ("Start failed. Error %i\n", err); + } + + menuButtonPressed = false; + } + + if (pressed & KEY_B) { + mmEffectEx(&snd_back); + fadeType = false; // Fade to white + for (int i = 0; i < 50; i++) swiWaitForVBlank(); + loadROMselect(); + } + + if ((pressed & KEY_X) && !isRegularDS) { + mmEffectEx(&snd_back); + fadeType = false; // Fade to white + for (int i = 0; i < 50; i++) swiWaitForVBlank(); + if (!isDSiMode() || launcherApp == -1) { + *(u32*)(0x02000300) = 0x434E4C54; // Set "CNLT" warmboot flag + *(u16*)(0x02000304) = 0x1801; + *(u32*)(0x02000310) = 0x4D454E55; // "MENU" + unlaunchSetHiyaBoot(); + } else { + tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); + *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) + *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) + *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h + *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h + *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) + *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) + toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) + int i2 = 0; + for (int i = 0; i < (int)sizeof(unlaunchDevicePath); i++) { + *(u8*)(0x02000838+i2) = unlaunchDevicePath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) + i2 += 2; + } + while (*(u16*)(0x0200080E) == 0) { // Keep running, so that CRC16 isn't 0 + *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 + } + } + fifoSendValue32(FIFO_USER_02, 1); // ReturntoDSiMenu + } + + } + + //////////////////////////////////// + // Launch the item + + if (applaunch) { + // Clear screen with white + whiteScreen = true; + fadeSpeed = true; + controlTopBright = false; + clearText(); + + // Delete previously used DSiWare of flashcard from SD + if (!gotosettings && consoleModel < 2 && previousUsedDevice && bothSDandFlashcard()) { + if (access("sd:/_nds/TWiLightMenu/tempDSiWare.dsi", F_OK) == 0) { + remove("sd:/_nds/TWiLightMenu/tempDSiWare.dsi"); + } + if (access("sd:/_nds/TWiLightMenu/tempDSiWare.pub", F_OK) == 0) { + remove("sd:/_nds/TWiLightMenu/tempDSiWare.pub"); + } + if (access("sd:/_nds/TWiLightMenu/tempDSiWare.prv", F_OK) == 0) { + remove("sd:/_nds/TWiLightMenu/tempDSiWare.prv"); + } + } + + // Construct a command line + getcwd (filePath, PATH_MAX); + int pathLen = strlen(filePath); + vector argarray; + + if (extention(filename[secondaryDevice], ".argv")) + { + FILE *argfile = fopen(filename[secondaryDevice].c_str(),"rb"); + char str[PATH_MAX], *pstr; + const char seps[]= "\n\r\t "; + + while( fgets(str, PATH_MAX, argfile) ) { + // Find comment and end string there + if( (pstr = strchr(str, '#')) ) + *pstr= '\0'; + + // Tokenize arguments + pstr= strtok(str, seps); + + while( pstr != NULL ) { + argarray.push_back(strdup(pstr)); + pstr= strtok(NULL, seps); + } + } + fclose(argfile); + filename[secondaryDevice] = argarray.at(0); + } else { + argarray.push_back(strdup(filename[secondaryDevice].c_str())); + } + + // Launch DSiWare .nds via Unlaunch + if ((isDSiMode() || sdFound()) && isDSiWare[secondaryDevice]) { + const char *typeToReplace = ".nds"; + if (extention(filename[secondaryDevice], ".dsi")) { + typeToReplace = ".dsi"; + } else if (extention(filename[secondaryDevice], ".ids")) { + typeToReplace = ".ids"; + } else if (extention(filename[secondaryDevice], ".srl")) { + typeToReplace = ".srl"; + } else if (extention(filename[secondaryDevice], ".app")) { + typeToReplace = ".app"; + } + + char *name = argarray.at(0); + strcpy (filePath + pathLen, name); + free(argarray.at(0)); + argarray.at(0) = filePath; + + dsiWareSrlPath = argarray[0]; + dsiWarePubPath = replaceAll(argarray[0], typeToReplace, ".pub"); + dsiWarePrvPath = replaceAll(argarray[0], typeToReplace, ".prv"); + launchType[secondaryDevice] = (consoleModel>0 ? 1 : 3); + SaveSettings(); + + sNDSHeaderExt NDSHeader; + + FILE *f_nds_file = fopen(filename[secondaryDevice].c_str(), "rb"); + + fread(&NDSHeader, 1, sizeof(NDSHeader), f_nds_file); + fclose(f_nds_file); + + whiteScreen = true; + + if ((getFileSize(dsiWarePubPath.c_str()) == 0) && (NDSHeader.pubSavSize > 0)) { + clearText(); + if (flashcard == 8) { + // Display nothing + } else if (consoleModel >= 2) { + printSmallCentered(false, 20, "If this takes a while, press HOME,"); + printSmallCentered(false, 34, "then press B."); + } else { + printSmallCentered(false, 20, "If this takes a while, close and open"); + printSmallCentered(false, 34, "the console's lid."); + } + printSmall(false, 2, 80, "Creating public save file..."); + if (!fadeType) { + fadeType = true; // Fade in from white + for (int i = 0; i < 35; i++) swiWaitForVBlank(); + } + + static const int BUFFER_SIZE = 4096; + char buffer[BUFFER_SIZE]; + memset(buffer, 0, sizeof(buffer)); + char savHdrPath[64]; + snprintf(savHdrPath, sizeof(savHdrPath), "nitro:/DSiWareSaveHeaders/%x.savhdr", (unsigned int)NDSHeader.pubSavSize); + FILE *hdrFile = fopen(savHdrPath, "rb"); + if (hdrFile) fread(buffer, 1, 0x200, hdrFile); + fclose(hdrFile); + + FILE *pFile = fopen(dsiWarePubPath.c_str(), "wb"); + if (pFile) { + fwrite(buffer, 1, sizeof(buffer), pFile); + fseek(pFile, NDSHeader.pubSavSize - 1, SEEK_SET); + fputc('\0', pFile); + fclose(pFile); + } + printSmall(false, 2, 88, "Public save file created!"); + for (int i = 0; i < 60; i++) swiWaitForVBlank(); + } + + if ((getFileSize(dsiWarePrvPath.c_str()) == 0) && (NDSHeader.prvSavSize > 0)) { + clearText(); + if (flashcard == 8) { + // Display nothing + } else if (consoleModel >= 2) { + printSmallCentered(false, 20, "If this takes a while, press HOME,"); + printSmallCentered(false, 34, "then press B."); + } else { + printSmallCentered(false, 20, "If this takes a while, close and open"); + printSmallCentered(false, 34, "the console's lid."); + } + printSmall(false, 2, 80, "Creating private save file..."); + if (!fadeType) { + fadeType = true; // Fade in from white + for (int i = 0; i < 35; i++) swiWaitForVBlank(); + } + + static const int BUFFER_SIZE = 4096; + char buffer[BUFFER_SIZE]; + memset(buffer, 0, sizeof(buffer)); + char savHdrPath[64]; + snprintf(savHdrPath, sizeof(savHdrPath), "nitro:/DSiWareSaveHeaders/%x.savhdr", (unsigned int)NDSHeader.prvSavSize); + FILE *hdrFile = fopen(savHdrPath, "rb"); + if (hdrFile) fread(buffer, 1, 0x200, hdrFile); + fclose(hdrFile); + + FILE *pFile = fopen(dsiWarePrvPath.c_str(), "wb"); + if (pFile) { + fwrite(buffer, 1, sizeof(buffer), pFile); + fseek(pFile, NDSHeader.prvSavSize - 1, SEEK_SET); + fputc('\0', pFile); + fclose(pFile); + } + printSmall(false, 2, 88, "Private save file created!"); + for (int i = 0; i < 60; i++) swiWaitForVBlank(); + } + + if (fadeType) { + fadeType = false; // Fade to white + for (int i = 0; i < 25; i++) swiWaitForVBlank(); + } + + if (dsiWareBooter || consoleModel > 0) { + // Use nds-bootstrap + loadPerGameSettings(filename[secondaryDevice]); + + bootstrapinipath = "sd:/_nds/nds-bootstrap.ini"; + CIniFile bootstrapini(bootstrapinipath); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", dsiWareSrlPath); + bootstrapini.SetString("NDS-BOOTSTRAP", "SAV_PATH", dsiWarePubPath); + bootstrapini.SetString("NDS-BOOTSTRAP", "AP_FIX_PATH", ""); + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", -1); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", true); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", true); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", true); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DONOR_SDK_VER", 5); + bootstrapini.SetInt("NDS-BOOTSTRAP", "GAME_SOFT_RESET", 1); + bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_REGION", 0); + bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_SIZE", 0); + bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", 1); + bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", + (forceSleepPatch + || ((flashcard == 1 || flashcard == 3) && !isRegularDS)) + ); + bootstrapini.SaveIniFile(bootstrapinipath); + + if (isDSiMode() || !secondaryDevice) { + SetWidescreen(filename[secondaryDevice].c_str()); + } + if (!isDSiMode() && !secondaryDevice) { + ntrStartSdGame(); + } + + bool useNightly = (perGameSettings_bootstrapFile == -1 ? bootstrapFile : perGameSettings_bootstrapFile); + + char ndsToBoot[256]; + sprintf(ndsToBoot, "sd:/_nds/nds-bootstrap-%s.nds", useNightly ? "nightly" : "release"); + if(access(ndsToBoot, F_OK) != 0) { + sprintf(ndsToBoot, "fat:/_nds/nds-bootstrap-%s.nds", useNightly ? "nightly" : "release"); + } + + argarray.at(0) = (char *)ndsToBoot; + int err = runNdsFile(argarray[0], argarray.size(), (const char **)&argarray[0], true, true, false, true, true); + char text[32]; + snprintf (text, sizeof(text), "Start failed. Error %i", err); + clearText(); + ClearBrightness(); + printSmall(false, 4, 80, text); + if (err == 1) { + printSmall(false, 4, 88, useNightly ? "nds-bootstrap (Nightly)" : "nds-bootstrap (Release)"); + printSmall(false, 4, 96, "not found."); + } + stop(); + } + + if (secondaryDevice) { + clearText(); + printSmallCentered(false, 20, "If this takes a while, close and open"); + printSmallCentered(false, 34, "the console's lid."); + printSmallCentered(false, 86, "Now copying data..."); + printSmallCentered(false, 100, "Do not turn off the power."); + fadeType = true; // Fade in from white + for (int i = 0; i < 35; i++) swiWaitForVBlank(); + fcopy(dsiWareSrlPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.dsi"); + if ((access(dsiWarePubPath.c_str(), F_OK) == 0) && (NDSHeader.pubSavSize > 0)) { + fcopy(dsiWarePubPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.pub"); + } + if ((access(dsiWarePrvPath.c_str(), F_OK) == 0) && (NDSHeader.prvSavSize > 0)) { + fcopy(dsiWarePrvPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.prv"); + } + fadeType = false; // Fade to white + for (int i = 0; i < 25; i++) swiWaitForVBlank(); + + if ((access(dsiWarePubPath.c_str(), F_OK) == 0 && (NDSHeader.pubSavSize > 0)) + || (access(dsiWarePrvPath.c_str(), F_OK) == 0 && (NDSHeader.prvSavSize > 0))) { + clearText(); + printSmallCentered(false, 8, "After saving, please re-start"); + printSmallCentered(false, 20, "TWiLight Menu++ to transfer your"); + printSmallCentered(false, 32, "save data back."); + fadeType = true; // Fade in from white + for (int i = 0; i < 60*3; i++) swiWaitForVBlank(); // Wait 3 seconds + fadeType = false; // Fade to white + for (int i = 0; i < 25; i++) swiWaitForVBlank(); + } + } + + char unlaunchDevicePath[256]; + if (secondaryDevice) { + snprintf(unlaunchDevicePath, sizeof(unlaunchDevicePath), "sdmc:/_nds/TWiLightMenu/tempDSiWare.dsi"); + } else { + snprintf(unlaunchDevicePath, sizeof(unlaunchDevicePath), "__%s", dsiWareSrlPath.c_str()); + unlaunchDevicePath[0] = 's'; + unlaunchDevicePath[1] = 'd'; + unlaunchDevicePath[2] = 'm'; + unlaunchDevicePath[3] = 'c'; + } + + tonccpy((u8*)0x02000800, unlaunchAutoLoadID, 12); + *(u16*)(0x0200080C) = 0x3F0; // Unlaunch Length for CRC16 (fixed, must be 3F0h) + *(u16*)(0x0200080E) = 0; // Unlaunch CRC16 (empty) + *(u32*)(0x02000810) = 0; // Unlaunch Flags + *(u32*)(0x02000810) |= BIT(0); // Load the title at 2000838h + *(u32*)(0x02000810) |= BIT(1); // Use colors 2000814h + *(u16*)(0x02000814) = 0x7FFF; // Unlaunch Upper screen BG color (0..7FFFh) + *(u16*)(0x02000816) = 0x7FFF; // Unlaunch Lower screen BG color (0..7FFFh) + toncset((u8*)0x02000818, 0, 0x20+0x208+0x1C0); // Unlaunch Reserved (zero) + int i2 = 0; + for (int i = 0; i < (int)sizeof(unlaunchDevicePath); i++) { + *(u8*)(0x02000838+i2) = unlaunchDevicePath[i]; // Unlaunch Device:/Path/Filename.ext (16bit Unicode,end by 0000h) + i2 += 2; + } + *(u16*)(0x0200080E) = swiCRC16(0xFFFF, (void*)0x02000810, 0x3F0); // Unlaunch CRC16 + + fifoSendValue32(FIFO_USER_02, 1); // Reboot into DSiWare title, booted via Launcher + for (int i = 0; i < 15; i++) swiWaitForVBlank(); + } + + // Launch .nds directly or via nds-bootstrap + if (extention(filename[secondaryDevice], ".nds") || extention(filename[secondaryDevice], ".dsi") + || extention(filename[secondaryDevice], ".ids") || extention(filename[secondaryDevice], ".srl") + || extention(filename[secondaryDevice], ".app")) { + const char *typeToReplace = ".nds"; + if (extention(filename[secondaryDevice], ".dsi")) { + typeToReplace = ".dsi"; + } else if (extention(filename[secondaryDevice], ".ids")) { + typeToReplace = ".ids"; + } else if (extention(filename[secondaryDevice], ".srl")) { + typeToReplace = ".srl"; + } else if (extention(filename[secondaryDevice], ".app")) { + typeToReplace = ".app"; + } + + bool dsModeSwitch = false; + bool dsModeDSiWare = false; + + char game_TID[5]; + + FILE *f_nds_file = fopen(argarray[0], "rb"); + + fseek(f_nds_file, offsetof(sNDSHeaderExt, gameCode), SEEK_SET); + fread(game_TID, 1, 4, f_nds_file); + fclose(f_nds_file); + game_TID[4] = 0; + game_TID[3] = 0; + + if (strcmp(game_TID, "HND") == 0 || strcmp(game_TID, "HNE") == 0) { + dsModeSwitch = true; + dsModeDSiWare = true; + useBackend = false; // Bypass nds-bootstrap + homebrewBootstrap = true; + } else if (isHomebrew[secondaryDevice]) { + loadPerGameSettings(filename[secondaryDevice]); + if (perGameSettings_directBoot || (useBootstrap && secondaryDevice)) { + useBackend = false; // Bypass nds-bootstrap + } else { + useBackend = true; + } + if (isDSiMode() && !perGameSettings_dsiMode) { + dsModeSwitch = true; + } + homebrewBootstrap = true; + } else { + loadPerGameSettings(filename[secondaryDevice]); + useBackend = true; + homebrewBootstrap = false; + } + + char *name = argarray.at(0); + strcpy (filePath + pathLen, name); + free(argarray.at(0)); + argarray.at(0) = filePath; + if(useBackend) { + if(useBootstrap || !secondaryDevice) { + std::string path = argarray[0]; + std::string savename = replaceAll(filename[secondaryDevice], typeToReplace, getSavExtension()); + std::string ramdiskname = replaceAll(filename[secondaryDevice], typeToReplace, getImgExtension()); + std::string romFolderNoSlash = romfolder[secondaryDevice]; + RemoveTrailingSlashes(romFolderNoSlash); + mkdir (isHomebrew[secondaryDevice] ? "ramdisks" : "saves", 0777); + std::string savepath = romFolderNoSlash+"/saves/"+savename; + if (sdFound() && secondaryDevice && fcSaveOnSd) { + savepath = replaceAll(savepath, "fat:/", "sd:/"); + } + std::string ramdiskpath = romFolderNoSlash+"/ramdisks/"+ramdiskname; + + if (!isHomebrew[secondaryDevice] && (strcmp(game_TID, "NTR") != 0)) { + // Create or expand save if game isn't homebrew + int orgsavesize = getFileSize(savepath.c_str()); + int savesize = 524288; // 512KB (default size) + + for (auto i : saveMap) { + if (i.second.find(game_TID) != i.second.cend()) { + savesize = i.first; + break; + } + } + + bool saveSizeFixNeeded = false; + + // TODO: If the list gets large enough, switch to bsearch(). + for (unsigned int i = 0; i < sizeof(saveSizeFixList) / sizeof(saveSizeFixList[0]); i++) { + if (memcmp(game_TID, saveSizeFixList[i], 3) == 0) { + // Found a match. + saveSizeFixNeeded = true; + break; + } + } + + if ((orgsavesize == 0 && savesize > 0) || (orgsavesize < savesize && saveSizeFixNeeded)) { + clearText(); + ClearBrightness(); + if (isDSiMode() && flashcard == 8) { + // Display nothing + } else if (REG_SCFG_EXT != 0 && consoleModel >= 2) { + printSmallCentered(false, 20, "If this takes a while, press HOME,"); + printSmallCentered(false, 34, "then press B."); + } else { + printSmallCentered(false, 20, "If this takes a while, close and open"); + printSmallCentered(false, 34, "the console's lid."); + } + printSmallCentered(false, 88, (orgsavesize == 0) ? "Creating save file..." : "Expanding save file..."); + + if (orgsavesize > 0) { + fsizeincrease(savepath.c_str(), sdFound() ? "sd:/_nds/TWiLightMenu/temp.sav" : "fat:/_nds/TWiLightMenu/temp.sav", savesize); + } else { + FILE *pFile = fopen(savepath.c_str(), "wb"); + if (pFile) { + fseek(pFile, savesize - 1, SEEK_SET); + fputc('\0', pFile); + fclose(pFile); + } + } + clearText(); + printSmallCentered(false, 88, (orgsavesize == 0) ? "Save file created!" : "Save file expanded!"); + for (int i = 0; i < 30; i++) swiWaitForVBlank(); + } + } + + int donorSdkVer = SetDonorSDK(argarray[0]); + SetMPUSettings(argarray[0]); + SetSpeedBumpExclude(argarray[0]); + + bool useWidescreen = (perGameSettings_wideScreen == -1 ? wideScreen : perGameSettings_wideScreen); + + bootstrapinipath = ((!secondaryDevice || (isDSiMode() && sdFound())) ? "sd:/_nds/nds-bootstrap.ini" : "fat:/_nds/nds-bootstrap.ini"); + CIniFile bootstrapini( bootstrapinipath ); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", path); + bootstrapini.SetString("NDS-BOOTSTRAP", "SAV_PATH", savepath); + if (!isHomebrew[secondaryDevice]) { + bootstrapini.SetString("NDS-BOOTSTRAP", "AP_FIX_PATH", setApFix(argarray[0])); + } + bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", (useWidescreen && game_TID[0] == 'W') ? "wide" : ""); + bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", (perGameSettings_ramDiskNo >= 0 && !secondaryDevice) ? ramdiskpath : "sd:/null.img"); + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", perGameSettings_language == -2 ? gameLanguage : perGameSettings_language); + if (isDSiMode() || !secondaryDevice) { + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", perGameSettings_dsiMode == -1 ? bstrap_dsiMode : perGameSettings_dsiMode); + } + if ((REG_SCFG_EXT != 0) || !secondaryDevice) { + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", perGameSettings_boostCpu == -1 ? boostCpu : perGameSettings_boostCpu); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram); + } + bootstrapini.SetInt("NDS-BOOTSTRAP", "EXTENDED_MEMORY", perGameSettings_expandRomSpace == -1 ? bstrap_extendedMemory : perGameSettings_expandRomSpace); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DONOR_SDK_VER", donorSdkVer); + bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_REGION", mpuregion); + bootstrapini.SetInt("NDS-BOOTSTRAP", "PATCH_MPU_SIZE", mpusize); + bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", ceCached); + bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", + (forceSleepPatch + || ((flashcard == 1 || flashcard == 3) && !isRegularDS)) + ); + bootstrapini.SaveIniFile( bootstrapinipath ); + + CheatCodelist codelist; + u32 gameCode,crc32; + + if ((isDSiMode() || !secondaryDevice) && !isHomebrew[secondaryDevice]) { + bool cheatsEnabled = true; + const char* cheatDataBin = "/_nds/nds-bootstrap/cheatData.bin"; + mkdir("/_nds", 0777); + mkdir("/_nds/nds-bootstrap", 0777); + if(codelist.romData(path,gameCode,crc32)) { + long cheatOffset; size_t cheatSize; + FILE* dat=fopen(sdFound() ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat","rb"); + if (dat) { + if (codelist.searchCheatData(dat, gameCode, + crc32, cheatOffset, + cheatSize)) { + codelist.parse(path); + writeCheatsToFile(codelist.getCheats(), cheatDataBin); + FILE* cheatData=fopen(cheatDataBin,"rb"); + if (cheatData) { + u32 check[2]; + fread(check, 1, 8, cheatData); + fclose(cheatData); + if (check[1] == 0xCF000000 + || getFileSize(cheatDataBin) > 0x8000) { + cheatsEnabled = false; + } + } + } else { + cheatsEnabled = false; + } + fclose(dat); + } else { + cheatsEnabled = false; + } + } else { + cheatsEnabled = false; + } + if (!cheatsEnabled) { + remove(cheatDataBin); + } + } + + launchType[secondaryDevice] = 1; + previousUsedDevice = secondaryDevice; + SaveSettings(); + + if (isDSiMode() || !secondaryDevice) { + SetWidescreen(filename[secondaryDevice].c_str()); + } + if (!isDSiMode() && !secondaryDevice) { + ntrStartSdGame(); + } + + bool useNightly = (perGameSettings_bootstrapFile == -1 ? bootstrapFile : perGameSettings_bootstrapFile); + + char ndsToBoot[256]; + sprintf(ndsToBoot, "sd:/_nds/nds-bootstrap-%s%s.nds", homebrewBootstrap ? "hb-" : "", useNightly ? "nightly" : "release"); + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + sprintf(ndsToBoot, "fat:/_nds/%s-%s%s.nds", isDSiMode() ? "nds-bootstrap" : "b4ds", homebrewBootstrap ? "hb-" : "", useNightly ? "nightly" : "release"); + } + + argarray.at(0) = (char *)ndsToBoot; + int err = runNdsFile (argarray[0], argarray.size(), (const char **)&argarray[0], (homebrewBootstrap ? false : true), true, false, true, true); + char text[32]; + snprintf (text, sizeof(text), "Start failed. Error %i", err); + clearText(); + ClearBrightness(); + printSmall(false, 4, 80, text); + if (err == 1) { + printSmall(false, 4, 88, useNightly ? "nds-bootstrap (Nightly)" : "nds-bootstrap (Release)"); + printSmall(false, 4, 96, "not found."); + } + stop(); + } else { + launchType[secondaryDevice] = 1; + previousUsedDevice = secondaryDevice; + SaveSettings(); + loadGameOnFlashcard(argarray[0], true); + } + } else { + if (isDSiMode() || !secondaryDevice) { + SetWidescreen(filename[secondaryDevice].c_str()); + } + launchType[secondaryDevice] = 2; + previousUsedDevice = secondaryDevice; + SaveSettings(); + if (!isDSiMode() && !secondaryDevice) { + ntrStartSdGame(); + } + + bool useWidescreen = (perGameSettings_wideScreen == -1 ? wideScreen : perGameSettings_wideScreen); + + if (consoleModel >= 2 && useWidescreen && homebrewHasWide) { + argarray.push_back((char*)"wide"); + } + + bool runNds_boostCpu = false; + bool runNds_boostVram = false; + if (REG_SCFG_EXT != 0 && !dsModeDSiWare) { + loadPerGameSettings(filename[secondaryDevice]); + + runNds_boostCpu = perGameSettings_boostCpu == -1 ? boostCpu : perGameSettings_boostCpu; + runNds_boostVram = perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram; + } + //iprintf ("Running %s with %d parameters\n", argarray[0], argarray.size()); + int err = runNdsFile (argarray[0], argarray.size(), (const char **)&argarray[0], true, true, dsModeSwitch, runNds_boostCpu, runNds_boostVram); + char text[32]; + snprintf (text, sizeof(text), "Start failed. Error %i", err); + clearText(); + ClearBrightness(); + printSmall(false, 4, 4, text); + stop(); + } + } else { + bool useNDSB = false; + bool dsModeSwitch = false; + bool boostCpu = true; + bool boostVram = false; + + std::string romfolderNoSlash = romfolder[secondaryDevice]; + RemoveTrailingSlashes(romfolderNoSlash); + char ROMpath[256]; + snprintf (ROMpath, sizeof(ROMpath), "%s/%s", romfolderNoSlash.c_str(), filename[secondaryDevice].c_str()); + romPath[secondaryDevice] = ROMpath; + previousUsedDevice = secondaryDevice; + homebrewBootstrap = true; + + const char *ndsToBoot = "sd:/_nds/nds-bootstrap-release.nds"; + if (extention(filename[secondaryDevice], ".plg")) { + ndsToBoot = "fat:/_nds/TWiLightMenu/bootplg.srldr"; + + // Print .plg path without "fat:" at the beginning + char ROMpathDS2[256]; + if (secondaryDevice) { + for (int i = 0; i < 252; i++) { + ROMpathDS2[i] = ROMpath[4+i]; + if (ROMpath[4+i] == '\x00') break; + } + } else { + sprintf(ROMpathDS2, "/_nds/TWiLightMenu/tempPlugin.plg"); + fcopy(ROMpath, "fat:/_nds/TWiLightMenu/tempPlugin.plg"); + } + + CIniFile dstwobootini( "fat:/_dstwo/twlm.ini" ); + dstwobootini.SetString("boot_settings", "file", ROMpathDS2); + dstwobootini.SaveIniFile( "fat:/_dstwo/twlm.ini" ); + } else if (extention(filename[secondaryDevice], ".rvid")) { + launchType[secondaryDevice] = 7; + + ndsToBoot = "sd:/_nds/TWiLightMenu/apps/RocketVideoPlayer.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/apps/RocketVideoPlayer.nds"; + boostVram = true; + } + } else if (extention(filename[secondaryDevice], ".mp4")) { + launchType[secondaryDevice] = 8; + + ndsToBoot = "sd:/_nds/TWiLightMenu/apps/MPEG4Player.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/apps/MPEG4Player.nds"; + boostVram = true; + } + } else if (extention(filename[secondaryDevice], ".gba")) { + launchType[secondaryDevice] = 1; + + if (secondaryDevice) { + ndsToBoot = gbar2DldiAccess ? "sd:/_nds/GBARunner2_arm7dldi_ds.nds" : "sd:/_nds/GBARunner2_arm9dldi_ds.nds"; + if (REG_SCFG_EXT != 0) { + ndsToBoot = consoleModel>0 ? "sd:/_nds/GBARunner2_arm7dldi_3ds.nds" : "sd:/_nds/GBARunner2_arm7dldi_dsi.nds"; + } + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = gbar2DldiAccess ? "fat:/_nds/GBARunner2_arm7dldi_ds.nds" : "fat:/_nds/GBARunner2_arm9dldi_ds.nds"; + if (REG_SCFG_EXT != 0) { + ndsToBoot = consoleModel>0 ? "fat:/_nds/GBARunner2_arm7dldi_3ds.nds" : "fat:/_nds/GBARunner2_arm7dldi_dsi.nds"; + } + } + boostVram = false; + } else { + useNDSB = true; + + const char* gbar2Path = consoleModel>0 ? "sd:/_nds/GBARunner2_arm7dldi_3ds.nds" : "sd:/_nds/GBARunner2_arm7dldi_dsi.nds"; + if (isDSiMode() && arm7SCFGLocked) { + gbar2Path = consoleModel>0 ? "sd:/_nds/GBARunner2_arm7dldi_nodsp_3ds.nds" : "sd:/_nds/GBARunner2_arm7dldi_nodsp_dsi.nds"; + } + + ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); + CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); + + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", gbar2Path); + bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", ROMpath); + bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ""); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 1); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); + + bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); + } + } else if (extention(filename[secondaryDevice], ".a26")) { + launchType[secondaryDevice] = 9; + + ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/StellaDS.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/StellaDS.nds"; + boostVram = true; + } + } else if (extention(filename[secondaryDevice], ".gb") || extention(filename[secondaryDevice], ".sgb") || extention(filename[secondaryDevice], ".gbc")) { + launchType[secondaryDevice] = 5; + + ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/gameyob.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/gameyob.nds"; + dsModeSwitch = !isDSiMode(); + boostVram = true; + } + } else if (extention(filename[secondaryDevice], ".nes") || extention(filename[secondaryDevice], ".fds")) { + launchType[secondaryDevice] = 4; + + ndsToBoot = (secondaryDevice ? "sd:/_nds/TWiLightMenu/emulators/nesds.nds" : "sd:/_nds/TWiLightMenu/emulators/nestwl.nds"); + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/nesds.nds"; + boostVram = true; + } + } else if (extention(filename[secondaryDevice], ".sms") || extention(filename[secondaryDevice], ".gg")) { + mkdir(secondaryDevice ? "fat:/data" : "sd:/data", 0777); + mkdir(secondaryDevice ? "fat:/data/s8ds" : "sd:/data/s8ds", 0777); + + if (!secondaryDevice && !arm7SCFGLocked && smsGgInRam) { + launchType[secondaryDevice] = 1; + + useNDSB = true; + + ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); + CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); + + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/S8DS07.nds"); + bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", ""); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 1); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); + + bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ROMpath); + bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); + } else { + launchType[secondaryDevice] = 6; + + ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/S8DS.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/S8DS.nds"; + boostVram = true; + } + } + } else if (extention(filename[secondaryDevice], ".gen")) { + bool usePicoDrive = ((isDSiMode() && sdFound() && arm7SCFGLocked) + || showMd==2 || (showMd==3 && getFileSize(filename[secondaryDevice].c_str()) > 0x300000)); + launchType[secondaryDevice] = (usePicoDrive ? 10 : 1); + + if (usePicoDrive || secondaryDevice) { + ndsToBoot = usePicoDrive ? "sd:/_nds/TWiLightMenu/emulators/PicoDriveTWL.nds" : "sd:/_nds/TWiLightMenu/emulators/jEnesisDS.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = usePicoDrive ? "fat:/_nds/TWiLightMenu/emulators/PicoDriveTWL.nds" : "fat:/_nds/TWiLightMenu/emulators/jEnesisDS.nds"; + boostVram = true; + } + dsModeSwitch = !usePicoDrive; + } else { + useNDSB = true; + + ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); + CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); + + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/jEnesisDS.nds"); + bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", "fat:/ROM.BIN"); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 1); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); + + bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ROMpath); + bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); + } + } else if (extention(filename[secondaryDevice], ".smc") || extention(filename[secondaryDevice], ".sfc")) { + launchType[secondaryDevice] = 1; + + if (secondaryDevice) { + ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/SNEmulDS.nds"; + if(!isDSiMode() || access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "fat:/_nds/TWiLightMenu/emulators/SNEmulDS.nds"; + boostCpu = false; + boostVram = true; + } + dsModeSwitch = true; + } else { + useNDSB = true; + + ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); + CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); + + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/SNEmulDS.nds"); + bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", "fat:/snes/ROM.SMC"); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 0); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); + + bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ROMpath); + bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); + } + } else if (extention(filename[secondaryDevice], ".pce")) { + launchType[secondaryDevice] = 1; + + if (secondaryDevice) { + ndsToBoot = "sd:/_nds/TWiLightMenu/emulators/NitroGrafx.nds"; + if(access(ndsToBoot, F_OK) != 0) { + ndsToBoot = "/_nds/TWiLightMenu/emulators/NitroGrafx.nds"; + boostVram = true; + } + dsModeSwitch = true; + } else { + useNDSB = true; + + ndsToBoot = (bootstrapFile ? "sd:/_nds/nds-bootstrap-hb-nightly.nds" : "sd:/_nds/nds-bootstrap-hb-release.nds"); + CIniFile bootstrapini("sd:/_nds/nds-bootstrap.ini"); + + bootstrapini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + bootstrapini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", 0); + bootstrapini.SetString("NDS-BOOTSTRAP", "NDS_PATH", "sd:/_nds/TWiLightMenu/emulators/NitroGrafx.nds"); + bootstrapini.SetString("NDS-BOOTSTRAP", "HOMEBREW_ARG", ROMpath); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", 0); + bootstrapini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", 0); + + bootstrapini.SetString("NDS-BOOTSTRAP", "RAM_DRIVE_PATH", ""); + bootstrapini.SaveIniFile("sd:/_nds/nds-bootstrap.ini"); + } + } + + SaveSettings(); + if (!isDSiMode() && !secondaryDevice && !extention(filename[secondaryDevice], ".plg")) { + ntrStartSdGame(); + } + argarray.push_back(ROMpath); + argarray.at(0) = (char *)ndsToBoot; + + int err = runNdsFile (argarray[0], argarray.size(), (const char **)&argarray[0], !useNDSB, true, dsModeSwitch, boostCpu, boostVram); // Pass ROM to emulator as argument + + char text[32]; + snprintf (text, sizeof(text), "Start failed. Error %i", err); + clearText(); + ClearBrightness(); + printLarge(false, 4, 80, text); + if (err == 1 && useNDSB) { + printSmall(false, 4, 88, bootstrapFile ? "nds-bootstrap (Nightly)" : "nds-bootstrap (Release)"); + printSmall(false, 4, 96, "not found."); + } + stop(); + + while(argarray.size() !=0 ) { + free(argarray.at(0)); + argarray.erase(argarray.begin()); + } + } + } + } + + return 0; +} diff --git a/romsel_aktheme/arm9/source/common/bootstrapconfig.cpp b/romsel_aktheme/arm9/source/common/bootstrapconfig.cpp index c4c8ecd786..698d3fc0ca 100755 --- a/romsel_aktheme/arm9/source/common/bootstrapconfig.cpp +++ b/romsel_aktheme/arm9/source/common/bootstrapconfig.cpp @@ -30,10 +30,7 @@ BootstrapConfig::BootstrapConfig(const std::string &fileName, const std::string _mpuRegion = 0; _ceCached = true; _forceSleepPatch = (ms().forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !sys().isRegularDS())); + || ((ms().flashcard == 1 || ms().flashcard == 3) && !sys().isRegularDS()); _isHomebrew = _gametid.empty() || _sdkVersion == 0; _saveSize = 0x80000; _dsiMode = 0; diff --git a/romsel_aktheme/arm9/source/common/dsimenusettings.cpp b/romsel_aktheme/arm9/source/common/dsimenusettings.cpp index 670bb40147..dc08a2738e 100644 --- a/romsel_aktheme/arm9/source/common/dsimenusettings.cpp +++ b/romsel_aktheme/arm9/source/common/dsimenusettings.cpp @@ -48,6 +48,7 @@ TWLSettings::TWLSettings() secondaryDevice = false; fcSaveOnSd = false; + flashcard = 0; slot1LaunchMethod = EReboot; useBootstrap = isDSiMode(); @@ -142,6 +143,8 @@ void TWLSettings::loadSettings() launcherApp = settingsini.GetInt("SRLOADER", "LAUNCHER_APP", launcherApp); } + flashcard = settingsini.GetInt("SRLOADER", "FLASHCARD", flashcard); + slot1LaunchMethod = settingsini.GetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); bootstrapFile = settingsini.GetInt("SRLOADER", "BOOTSTRAP_FILE", bootstrapFile); useBootstrap = settingsini.GetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); @@ -208,6 +211,7 @@ void TWLSettings::saveSettings() settingsini.SetInt("SRLOADER", "ANIMATE_DSI_ICONS", animateDsiIcons); settingsini.SetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); + settingsini.SetInt("SRLOADER", "FLASHCARD", flashcard); settingsini.SetInt("SRLOADER", "BOOTSTRAP_FILE", bootstrapFile); if (!isDSiMode()) settingsini.SetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); diff --git a/romsel_aktheme/arm9/source/common/dsimenusettings.h b/romsel_aktheme/arm9/source/common/dsimenusettings.h index 2cd08cb9a0..089a3b5e46 100644 --- a/romsel_aktheme/arm9/source/common/dsimenusettings.h +++ b/romsel_aktheme/arm9/source/common/dsimenusettings.h @@ -29,6 +29,32 @@ class TWLSettings EViewInternal = 2 }; + + /* + 0: Unknown + 1: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE + 2: R4DS (Original Non-SDHC version)/ M3 Simply + 3: R4iDSN/R4i Gold RTS/R4 Ultra + 4: Acekard 2(i)/Galaxy Eagle/M3DS Real + 5: Acekard RPG + 6: Ace 3DS+/Gateway Blue Card/R4iTT + 7: SuperCard DSTWO + 8: CycloDS iEvolution + */ + + enum TFlashCard + { + EUnknown = 0, + EDSTTClone = 1, + ER4Original = 2, + ER4iGoldClone = 3, + EAcekard2i = 4, + EAcekardRPG = 5, + EGatewayBlue = 6, + ESupercardDSTWO = 7, + ECycloDSi = 8 + }; + // Do not reorder these, just add to the end enum TLanguage { @@ -150,6 +176,7 @@ class TWLSettings bool secondaryDevice; bool fcSaveOnSd; + int flashcard; int slot1LaunchMethod; bool useBootstrap; bool bootstrapFile; diff --git a/romsel_aktheme/arm9/source/common/flashcardlaunch.cpp b/romsel_aktheme/arm9/source/common/flashcardlaunch.cpp index 5b807cdadd..66c4caec74 100644 --- a/romsel_aktheme/arm9/source/common/flashcardlaunch.cpp +++ b/romsel_aktheme/arm9/source/common/flashcardlaunch.cpp @@ -29,31 +29,37 @@ int loadGameOnFlashcard (std::string ndsPath, bool usePerGameSettings) { } std::string launchPath; - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - LoaderConfig config("fat:/Wfwd.dat", "fat:/_wfwd/lastsave.ini"); - launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_FAT0); - config.option("Save Info", "lastLoaded", launchPath); - return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - LoaderConfig config("fat:/Afwd.dat", "fat:/_afwd/lastsave.ini"); - launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_FAT0); - config.option("Save Info", "lastLoaded", launchPath); - return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { - LoaderConfig config("fat:/_dstwo/autoboot.nds", "fat:/_dstwo/autoboot.ini"); - launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_FAT1); - config.option("Dir Info", "fullName", launchPath); - return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); - } else if ((memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0)) { - LoaderConfig config("fat:/YSMenu.nds", "fat:/TTMenu/YSMenu.ini"); - launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_SLASH); - config.option("YSMENU", "AUTO_BOOT", launchPath); - return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); + + + switch (ms().flashcard) { + case 1: { + LoaderConfig config("fat:/YSMenu.nds", "fat:/TTMenu/YSMenu.ini"); + launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_SLASH); + config.option("YSMENU", "AUTO_BOOT", launchPath); + return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); + } + case 6: // Blue card can run wood 1.62 so this should work? + case 2: // And clones that can run wood (no N5) + case 3: { + LoaderConfig config("fat:/Wfwd.dat", "fat:/_wfwd/lastsave.ini"); + launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_FAT0); + config.option("Save Info", "lastLoaded", launchPath); + return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); + } + case 7: { + LoaderConfig config("fat:/_dstwo/autoboot.nds", "fat:/_dstwo/autoboot.ini"); + launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_FAT1); + config.option("Dir Info", "fullName", launchPath); + return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); + } + case 5: // ? + case 4: { + LoaderConfig config("fat:/Afwd.dat", "fat:/_afwd/lastsave.ini"); + launchPath = replaceAll(ndsPath.c_str(), FC_PREFIX_FAT, FC_PREFIX_FAT0); + config.option("Save Info", "lastLoaded", launchPath); + return config.launch(0, NULL, true, true, runNds_boostCpu, runNds_boostVram); + } } return 100; -} \ No newline at end of file +} diff --git a/romsel_aktheme/arm9/source/dsrom.cpp b/romsel_aktheme/arm9/source/dsrom.cpp index 4a46d2931d..265c026ef7 100644 --- a/romsel_aktheme/arm9/source/dsrom.cpp +++ b/romsel_aktheme/arm9/source/dsrom.cpp @@ -138,7 +138,7 @@ bool DSRomInfo::loadDSRomInfo(const std::string &filename, bool loadBanner) _hasExtendedBinaries = ETrue; _requiresDonorRom = 0; bool usingFlashcard = (!isDSiMode() && ms().secondaryDevice); - bool hasCycloDSi = (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0); + bool hasCycloDSi = ms().flashcard == 8; switch (header.arm7binarySize) { case 0x22B40: case 0x22BCC: diff --git a/romsel_aktheme/arm9/source/windows/mainlist.cpp b/romsel_aktheme/arm9/source/windows/mainlist.cpp index 6f5f3271f2..1a6a46d14b 100644 --- a/romsel_aktheme/arm9/source/windows/mainlist.cpp +++ b/romsel_aktheme/arm9/source/windows/mainlist.cpp @@ -149,7 +149,7 @@ void MainList::setupExtnames() _extnameFilter.emplace_back(std::string(".app")); _extnameFilter.emplace_back(std::string(".argv")); } - if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { + if (ms().flashcard == 7) { _extnameFilter.emplace_back(std::string(".plg")); } if (ms().showRvid) diff --git a/romsel_aktheme/arm9/source/windows/mainwnd.cpp b/romsel_aktheme/arm9/source/windows/mainwnd.cpp index 646e5f5609..64a5164ce0 100644 --- a/romsel_aktheme/arm9/source/windows/mainwnd.cpp +++ b/romsel_aktheme/arm9/source/windows/mainwnd.cpp @@ -1351,7 +1351,7 @@ void MainWnd::launchSelected() extension = fullPath.substr(lastDotPos); // DSTWO Plugin Launch - if (extension == ".plg" && ms().secondaryDevice && memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) + if (extension == ".plg" && ms().secondaryDevice && ms().flashcard == 7) { ms().launchType[ms().secondaryDevice] = TWLSettings::ESDFlashcardLaunch; ms().saveSettings(); @@ -1891,4 +1891,4 @@ Window *MainWnd::windowBelow(const Point &p) if (_startMenu->isVisible() && wbp != _startButton) wbp = _startMenu; return wbp; -} \ No newline at end of file +} diff --git a/romsel_dsimenutheme/arm9/source/cheat.cpp b/romsel_dsimenutheme/arm9/source/cheat.cpp index f68d1c26d3..d127590b3c 100644 --- a/romsel_dsimenutheme/arm9/source/cheat.cpp +++ b/romsel_dsimenutheme/arm9/source/cheat.cpp @@ -1,21 +1,21 @@ /* - cheat.cpp - Portions copyright (C) 2008 Normmatt, www.normmatt.com, Smiths (www.emuholic.com) - Portions copyright (C) 2008 bliss (bliss@hanirc.org) - Copyright (C) 2009 yellow wood goblin - - 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 3 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, see . + cheat.cpp + Portions copyright (C) 2008 Normmatt, www.normmatt.com, Smiths (www.emuholic.com) + Portions copyright (C) 2008 bliss (bliss@hanirc.org) + Copyright (C) 2009 yellow wood goblin + + 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 3 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, see . */ #include @@ -46,527 +46,555 @@ CheatCodelist::~CheatCodelist(void) {} inline u32 gamecode(const char *aGameCode) { - u32 gameCode; - tonccpy(&gameCode, aGameCode, sizeof(gameCode)); - return gameCode; + u32 gameCode; + tonccpy(&gameCode, aGameCode, sizeof(gameCode)); + return gameCode; } #define CRCPOLY 0xedb88320 static u32 crc32(const u8* p,size_t len) { - u32 crc=-1; - while(len--) - { - crc^=*p++; - for(int ii=0;ii<8;++ii) crc=(crc>>1)^((crc&1)?CRCPOLY:0); - } - return crc; + u32 crc=-1; + while(len--) + { + crc^=*p++; + for(int ii=0;ii<8;++ii) crc=(crc>>1)^((crc&1)?CRCPOLY:0); + } + return crc; } bool CheatCodelist::parse(const std::string& aFileName) { - bool res=false; - u32 romcrc32,gamecode; - if(romData(aFileName,gamecode,romcrc32)) - { - const char* usrcheatPath = (sdFound() || !ms().secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; - if (ms().secondaryDevice && !ms().useBootstrap) { - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + bool res=false; + u32 romcrc32,gamecode; + if(romData(aFileName,gamecode,romcrc32)) + { + const char* usrcheatPath = (sdFound() || !ms().secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; + if (ms().secondaryDevice && !ms().useBootstrap) { + switch (ms().flashcard) { + case 1: { + usrcheatPath = "fat:/TTMenu/usrcheat.dat"; + break; + } + case 3: + case 6: + case 2: { + usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; + break; + } + case 5: // TODO: WoodRPG? Test + case 4: { + usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + break; + } + case 7: { + usrcheatPath = "fat:/_dstwo/usrcheat.dat"; + break; + } + } + } + FILE* dat = fopen(usrcheatPath,"rb"); + if (dat) { + res=parseInternal(dat,gamecode,romcrc32); + fclose(dat); } } - FILE* dat=fopen(usrcheatPath,"rb"); - if(dat) - { - res=parseInternal(dat,gamecode,romcrc32); - fclose(dat); - } - } - return res; + return res; } bool CheatCodelist::searchCheatData(FILE* aDat,u32 gamecode,u32 crc32,long& aPos,size_t& aSize) { - aPos=0; - aSize=0; - const char* KHeader="R4 CheatCode"; - char header[12]; - fread(header,12,1,aDat); - if(strncmp(KHeader,header,12)) return false; - - sDatIndex idx,nidx; - - fseek(aDat,0,SEEK_END); - long fileSize=ftell(aDat); - - fseek(aDat,0x100,SEEK_SET); - fread(&nidx,sizeof(nidx),1,aDat); - - bool done=false; - - while(!done) - { - tonccpy(&idx,&nidx,sizeof(idx)); - fread(&nidx,sizeof(nidx),1,aDat); - if(gamecode==idx._gameCode&&crc32==idx._crc32) - { - aSize=((nidx._offset)?nidx._offset:fileSize)-idx._offset; - aPos=idx._offset; - done=true; - } - if(!nidx._offset) done=true; - } - return (aPos&&aSize); + aPos=0; + aSize=0; + const char* KHeader="R4 CheatCode"; + char header[12]; + fread(header,12,1,aDat); + if(strncmp(KHeader,header,12)) return false; + + sDatIndex idx,nidx; + + fseek(aDat,0,SEEK_END); + long fileSize=ftell(aDat); + + fseek(aDat,0x100,SEEK_SET); + fread(&nidx,sizeof(nidx),1,aDat); + + bool done=false; + + while(!done) + { + tonccpy(&idx,&nidx,sizeof(idx)); + fread(&nidx,sizeof(nidx),1,aDat); + if(gamecode==idx._gameCode&&crc32==idx._crc32) + { + aSize=((nidx._offset)?nidx._offset:fileSize)-idx._offset; + aPos=idx._offset; + done=true; + } + if(!nidx._offset) done=true; + } + return (aPos&&aSize); } bool CheatCodelist::parseInternal(FILE* aDat,u32 gamecode,u32 crc32) { - dbg_printf("%x, %x\n",gamecode,crc32); - - _data.clear(); - - long dataPos; size_t dataSize; - if(!searchCheatData(aDat,gamecode,crc32,dataPos,dataSize)) return false; - fseek(aDat,dataPos,SEEK_SET); - - dbg_printf("record found: %d\n",dataSize); - - char* buffer=(char*)malloc(dataSize); - if(!buffer) return false; - fread(buffer,dataSize,1,aDat); - char* gameTitle=buffer; - - u32* ccode=(u32*)(((u32)gameTitle+strlen(gameTitle)+4)&~3); - u32 cheatCount=*ccode; - cheatCount&=0x0fffffff; - ccode+=9; - - u32 cc=0; - while(cc>28)&1) - { - flagItem|=cParsedItem::EInFolder; - if((*ccode>>24)==0x11) flagItem|=cParsedItem::EOne; - folderCount=*ccode&0x00ffffff; - folderName=(char*)((u32)ccode+4); - folderNote=(char*)((u32)folderName+strlen(folderName)+1); - _data.push_back(cParsedItem(folderName,folderNote,cParsedItem::EFolder)); - cc++; - ccode=(u32*)(((u32)folderName+strlen(folderName)+1+strlen(folderNote)+1+3)&~3); - } - - u32 selectValue=cParsedItem::ESelected; - for(size_t ii=0;ii>28)&1) + { + flagItem|=cParsedItem::EInFolder; + if((*ccode>>24)==0x11) flagItem|=cParsedItem::EOne; + folderCount=*ccode&0x00ffffff; + folderName=(char*)((u32)ccode+4); + folderNote=(char*)((u32)folderName+strlen(folderName)+1); + _data.push_back(cParsedItem(folderName,folderNote,cParsedItem::EFolder)); + cc++; + ccode=(u32*)(((u32)folderName+strlen(folderName)+1+strlen(folderNote)+1+3)&~3); + } + + u32 selectValue=cParsedItem::ESelected; + for(size_t ii=0;ii::iterator itr=_data.begin(); - while(itr!=_data.end()) - { - std::vector row; - row.push_back(""); - row.push_back((*itr)._title); - // _List.insertRow(_List.getRowCount(),row); - _indexes.push_back(itr-_data.begin()); - u32 flags=(*itr)._flags; - ++itr; - if((flags&cParsedItem::EFolder)&&(flags&cParsedItem::EOpen)==0) - { - while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) ++itr; - } - } + _indexes.clear(); + // _List.removeAllRows(); + + std::vector::iterator itr=_data.begin(); + while(itr!=_data.end()) + { + std::vector row; + row.push_back(""); + row.push_back((*itr)._title); + // _List.insertRow(_List.getRowCount(),row); + _indexes.push_back(itr-_data.begin()); + u32 flags=(*itr)._flags; + ++itr; + if((flags&cParsedItem::EFolder)&&(flags&cParsedItem::EOpen)==0) + { + while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) ++itr; + } + } } void CheatCodelist::deselectFolder(size_t anIndex) { - std::vector::iterator itr=_data.begin()+anIndex; - while(--itr>=_data.begin()) - { - if((*itr)._flags&cParsedItem::EFolder) - { - ++itr; - break; - } - } - while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) - { - (*itr)._flags&=~cParsedItem::ESelected; - ++itr; - } + std::vector::iterator itr=_data.begin()+anIndex; + while(--itr>=_data.begin()) + { + if((*itr)._flags&cParsedItem::EFolder) + { + ++itr; + break; + } + } + while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) + { + (*itr)._flags&=~cParsedItem::ESelected; + ++itr; + } } bool CheatCodelist::romData(const std::string& aFileName,u32& aGameCode,u32& aCrc32) { - bool res=false; - FILE* rom=fopen(aFileName.c_str(),"rb"); - if(rom) - { - u8 header[512]; - if(1==fread(header,sizeof(header),1,rom)) - { - aCrc32=crc32(header,sizeof(header)); - aGameCode=gamecode((const char*)(header+12)); - res=true; - } - fclose(rom); - } - return res; + bool res=false; + FILE* rom=fopen(aFileName.c_str(),"rb"); + if(rom) + { + u8 header[512]; + if(1==fread(header,sizeof(header),1,rom)) + { + aCrc32=crc32(header,sizeof(header)); + aGameCode=gamecode((const char*)(header+12)); + res=true; + } + fclose(rom); + } + return res; } std::string CheatCodelist::getCheats() { - std::string cheats; - for(uint i=0;i< _data.size();i++) - { - if(_data[i]._flags&cParsedItem::ESelected) - { - cheats += _data[i]._cheat.substr(0, _data[i]._cheat.size()); - } - } - std::replace( cheats.begin(), cheats.end(), '\n', ' '); - return cheats; + std::string cheats; + for(uint i=0;i< _data.size();i++) + { + if(_data[i]._flags&cParsedItem::ESelected) + { + cheats += _data[i]._cheat.substr(0, _data[i]._cheat.size()); + } + } + std::replace( cheats.begin(), cheats.end(), '\n', ' '); + return cheats; } void CheatCodelist::drawCheatList(std::vector& list, uint curPos, uint screenPos) { - // Print Cheats at the top - printLarge(false, 0, 30, STR_CHEATS, Alignment::center); - - // Print bottom text - if(list[curPos]->_comment != "") { - if(list[curPos]->_flags&cParsedItem::EFolder) { - printSmall(false, 0, 160, STR_CHEATS_FOLDER_INFO, Alignment::center); - } else if(list[curPos]->_flags&cParsedItem::ESelected) { - printSmall(false, 0, 160, STR_CHEATS_SELECTED_INFO, Alignment::center); - } else { - printSmall(false, 0, 160, STR_CHEATS_DESELECTED_INFO, Alignment::center); - } - } else { - if(list[curPos]->_flags&cParsedItem::EFolder) { - printSmall(false, 0, 160, STR_CHEATS_FOLDER, Alignment::center); - } else if(list[curPos]->_flags&cParsedItem::ESelected) { - printSmall(false, 0, 160, STR_CHEATS_SELECTED, Alignment::center); - } else { - printSmall(false, 0, 160, STR_CHEATS_DESELECTED, Alignment::center); - } - } - - // Print the list - for(uint i=0;i<8 && i_flags&cParsedItem::EFolder) { - printSmall(false, 15+((screenPos+i == curPos) ? 5 : 0), 60+(i*12), ">"); - printSmall(false, 28+((screenPos+i == curPos) ? 4 : 0), 60+(i*12), list[screenPos+i]->_title); - } else { - if(list[screenPos+i]->_flags&cParsedItem::ESelected) { - printSmall(false, 13, 60+(i*12), "x"); - } - printSmall(false, 21+((screenPos+i == curPos) ? 4 : 0), 60+(i*12), "-"); - printSmall(false, 28+((screenPos+i == curPos) ? 7 : 0), 60+(i*12), list[screenPos+i]->_title); - } - } + // Print Cheats at the top + printLarge(false, 0, 30, STR_CHEATS, Alignment::center); + + // Print bottom text + if(list[curPos]->_comment != "") { + if(list[curPos]->_flags&cParsedItem::EFolder) { + printSmall(false, 0, 160, STR_CHEATS_FOLDER_INFO, Alignment::center); + } else if(list[curPos]->_flags&cParsedItem::ESelected) { + printSmall(false, 0, 160, STR_CHEATS_SELECTED_INFO, Alignment::center); + } else { + printSmall(false, 0, 160, STR_CHEATS_DESELECTED_INFO, Alignment::center); + } + } else { + if(list[curPos]->_flags&cParsedItem::EFolder) { + printSmall(false, 0, 160, STR_CHEATS_FOLDER, Alignment::center); + } else if(list[curPos]->_flags&cParsedItem::ESelected) { + printSmall(false, 0, 160, STR_CHEATS_SELECTED, Alignment::center); + } else { + printSmall(false, 0, 160, STR_CHEATS_DESELECTED, Alignment::center); + } + } + + // Print the list + for(uint i=0;i<8 && i_flags&cParsedItem::EFolder) { + printSmall(false, 15+((screenPos+i == curPos) ? 5 : 0), 60+(i*12), ">"); + printSmall(false, 28+((screenPos+i == curPos) ? 4 : 0), 60+(i*12), list[screenPos+i]->_title); + } else { + if(list[screenPos+i]->_flags&cParsedItem::ESelected) { + printSmall(false, 13, 60+(i*12), "x"); + } + printSmall(false, 21+((screenPos+i == curPos) ? 4 : 0), 60+(i*12), "-"); + printSmall(false, 28+((screenPos+i == curPos) ? 7 : 0), 60+(i*12), list[screenPos+i]->_title); + } + } } void CheatCodelist::selectCheats(std::string filename) { - int pressed = 0; - int held = 0; - - clearText(); - - dbox_showIcon = true; - - printLarge(false, 0, 30, STR_CHEATS, Alignment::center); - printSmall(false, 0, 100, STR_LOADING, Alignment::center); - - parse(filename); - - bool cheatsFound = true; - // If no cheats are found - if(_data.size() == 0) { - snd().playWrong(); - cheatsFound = false; - clearText(); - printLarge(false, 0, 30, STR_CHEATS, Alignment::center); - printSmall(false, 0, 100, STR_NO_CHEATS_FOUND, Alignment::center); - printSmall(false, 0, 160, STR_B_BACK, Alignment::center); - - while(1) { - scanKeys(); - pressed = keysDownRepeat(); - checkSdEject(); - tex().drawVolumeImageCached(); - tex().drawBatteryImageCached(); - drawCurrentTime(); - drawCurrentDate(); - drawClockColon(); - snd().updateStream(); - swiWaitForVBlank(); - if(pressed & KEY_B) { - snd().playBack(); - break; - } - } - } - - // Make list of all cheats not in folders and folders - std::vector currentList; - for(uint i=0;i<_data.size();i++) { - if(!(_data[i]._flags&cParsedItem::EInFolder)) { - currentList.push_back(&_data[i]); - } - } - - int mainListCurPos = -1, mainListScreenPos = -1, - cheatWnd_cursorPosition = 0, cheatWnd_screenPosition = 0; - - while(cheatsFound) { - // Scroll screen if needed - if(cheatWnd_cursorPosition < cheatWnd_screenPosition) { - cheatWnd_screenPosition = cheatWnd_cursorPosition; - } else if(cheatWnd_cursorPosition > cheatWnd_screenPosition + 8 - 1) { - cheatWnd_screenPosition = cheatWnd_cursorPosition - 8 + 1; - } - - clearText(); - drawCheatList(currentList, cheatWnd_cursorPosition, cheatWnd_screenPosition); - - do { - scanKeys(); - pressed = keysDown(); - held = keysDownRepeat(); - checkSdEject(); - tex().drawVolumeImageCached(); - tex().drawBatteryImageCached(); - drawCurrentTime(); - drawCurrentDate(); - drawClockColon(); - snd().updateStream(); - swiWaitForVBlank(); - } while(!pressed && !held); - - if(held & KEY_UP) { - if(cheatWnd_cursorPosition>0) { - snd().playSelect(); - cheatWnd_cursorPosition--; - } - } else if(held & KEY_DOWN) { - if(cheatWnd_cursorPosition<((int)currentList.size()-1)) { - snd().playSelect(); - cheatWnd_cursorPosition++; - } - } else if(held & KEY_LEFT) { - snd().playSelect(); - cheatWnd_cursorPosition -= (cheatWnd_cursorPosition > 8 ? 8 : cheatWnd_cursorPosition); - } else if(held & KEY_RIGHT) { - snd().playSelect(); - cheatWnd_cursorPosition += (cheatWnd_cursorPosition < (int)(currentList.size()-8) ? 8 : currentList.size()-cheatWnd_cursorPosition-1); - } else if(pressed & KEY_A) { - (ms().theme == 4) ? snd().playLaunch() : snd().playSelect(); - if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { - uint i = std::distance(&_data[0], currentList[cheatWnd_cursorPosition]) + 1; - currentList.clear(); - for(; !(_data[i]._flags & cParsedItem::EFolder) && i < _data.size(); i++) { - currentList.push_back(&_data[i]); - } - mainListCurPos = cheatWnd_cursorPosition; - mainListScreenPos = cheatWnd_screenPosition; - cheatWnd_cursorPosition = 0; - } else { - cParsedItem &cheat = *currentList[cheatWnd_cursorPosition]; - bool select = !(cheat._flags & cParsedItem::ESelected); - if(cheat._flags & cParsedItem::EOne) - deselectFolder(std::distance(&_data[0], currentList[cheatWnd_cursorPosition])); - if(select || !(cheat._flags & cParsedItem::EOne)) - cheat._flags ^= cParsedItem::ESelected; - } - } else if(pressed & KEY_B) { - snd().playBack(); - if(mainListCurPos != -1) { - currentList.clear(); - for(uint i=0;i<_data.size();i++) { - if(!(_data[i]._flags&cParsedItem::EInFolder)) { - currentList.push_back(&_data[i]); - } - } - cheatWnd_cursorPosition = mainListCurPos; - cheatWnd_screenPosition = mainListScreenPos; - mainListCurPos = -1; - } else { - break; - } - } else if(pressed & KEY_X) { - snd().playLaunch(); - clearText(); - printLarge(false, 0, 30, STR_CHEATS, Alignment::center); - printSmall(false, 0, 100, STR_SAVING, Alignment::center); - onGenerate(); - break; - } else if(pressed & KEY_Y) { - if(currentList[cheatWnd_cursorPosition]->_comment != "") { - (ms().theme == 4) ? snd().playLaunch() : snd().playSelect(); - clearText(); - printLarge(false, 0, 30, STR_CHEATS, Alignment::center); - - std::string _topText = ""; - std::string _topTextStr(currentList[cheatWnd_cursorPosition]->_comment); - std::vector words; - std::size_t pos; - - // Process comment to stay within the box - while((pos = _topTextStr.find(' ')) != std::string::npos) { - words.push_back(_topTextStr.substr(0, pos)); - _topTextStr = _topTextStr.substr(pos + 1); - } - if(_topTextStr.size()) - words.push_back(_topTextStr); - std::string temp; - for(auto word : words) { - // Split word if the word is too long for a line - int width = calcSmallFontWidth(word); - if(width > 240) { - if(temp.length()) - _topText += temp + '\n'; - for(int i = 0; i < width/240; i++) { - word.insert((float)((i + 1) * word.length()) / ((width/240) + 1), "\n"); - } - _topText += word + '\n'; - continue; - } - - width = calcSmallFontWidth(temp + " " + word); - if(width > 240) { - _topText += temp + '\n'; - temp = word; - } else { - temp += " " + word; - } - } - if(temp.size()) - _topText += temp; - - // Print comment - printSmall(false, 0, 60, _topText, Alignment::center); - - // Print 'Back' text - printSmall(false, 0, 160, STR_B_BACK, Alignment::center); - while(1) { - scanKeys(); - pressed = keysDown(); - checkSdEject(); - tex().drawVolumeImageCached(); - tex().drawBatteryImageCached(); - drawCurrentTime(); - drawCurrentDate(); - drawClockColon(); - snd().updateStream(); - swiWaitForVBlank(); - if(pressed & KEY_B) { - snd().playBack(); - break; - } - } - } - } else if(pressed & KEY_L) { - // Delect all in the actual data so it doesn't just get the folder - for(auto itr = _data.begin(); itr != _data.end(); itr++) { - (*itr)._flags &= ~cParsedItem::ESelected; - } - // Also deselect them in the current list so that it updates the display - for(auto itr = currentList.begin(); itr != currentList.end(); itr++) { - (*itr)->_flags &= ~cParsedItem::ESelected; - } - } - } + int pressed = 0; + int held = 0; + + clearText(); + + dbox_showIcon = true; + + printLarge(false, 0, 30, STR_CHEATS, Alignment::center); + printSmall(false, 0, 100, STR_LOADING, Alignment::center); + + parse(filename); + + bool cheatsFound = true; + // If no cheats are found + if(_data.size() == 0) { + snd().playWrong(); + cheatsFound = false; + clearText(); + printLarge(false, 0, 30, STR_CHEATS, Alignment::center); + printSmall(false, 0, 100, STR_NO_CHEATS_FOUND, Alignment::center); + printSmall(false, 0, 160, STR_B_BACK, Alignment::center); + + while(1) { + scanKeys(); + pressed = keysDownRepeat(); + checkSdEject(); + tex().drawVolumeImageCached(); + tex().drawBatteryImageCached(); + drawCurrentTime(); + drawCurrentDate(); + drawClockColon(); + snd().updateStream(); + swiWaitForVBlank(); + if(pressed & KEY_B) { + snd().playBack(); + break; + } + } + } + + // Make list of all cheats not in folders and folders + std::vector currentList; + for(uint i=0;i<_data.size();i++) { + if(!(_data[i]._flags&cParsedItem::EInFolder)) { + currentList.push_back(&_data[i]); + } + } + + int mainListCurPos = -1, mainListScreenPos = -1, + cheatWnd_cursorPosition = 0, cheatWnd_screenPosition = 0; + + while(cheatsFound) { + // Scroll screen if needed + if(cheatWnd_cursorPosition < cheatWnd_screenPosition) { + cheatWnd_screenPosition = cheatWnd_cursorPosition; + } else if(cheatWnd_cursorPosition > cheatWnd_screenPosition + 8 - 1) { + cheatWnd_screenPosition = cheatWnd_cursorPosition - 8 + 1; + } + + clearText(); + drawCheatList(currentList, cheatWnd_cursorPosition, cheatWnd_screenPosition); + + do { + scanKeys(); + pressed = keysDown(); + held = keysDownRepeat(); + checkSdEject(); + tex().drawVolumeImageCached(); + tex().drawBatteryImageCached(); + drawCurrentTime(); + drawCurrentDate(); + drawClockColon(); + snd().updateStream(); + swiWaitForVBlank(); + } while(!pressed && !held); + + if(held & KEY_UP) { + if(cheatWnd_cursorPosition>0) { + snd().playSelect(); + cheatWnd_cursorPosition--; + } + } else if(held & KEY_DOWN) { + if(cheatWnd_cursorPosition<((int)currentList.size()-1)) { + snd().playSelect(); + cheatWnd_cursorPosition++; + } + } else if(held & KEY_LEFT) { + snd().playSelect(); + cheatWnd_cursorPosition -= (cheatWnd_cursorPosition > 8 ? 8 : cheatWnd_cursorPosition); + } else if(held & KEY_RIGHT) { + snd().playSelect(); + cheatWnd_cursorPosition += (cheatWnd_cursorPosition < (int)(currentList.size()-8) ? 8 : currentList.size()-cheatWnd_cursorPosition-1); + } else if(pressed & KEY_A) { + (ms().theme == 4) ? snd().playLaunch() : snd().playSelect(); + if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { + uint i = std::distance(&_data[0], currentList[cheatWnd_cursorPosition]) + 1; + currentList.clear(); + for(; !(_data[i]._flags & cParsedItem::EFolder) && i < _data.size(); i++) { + currentList.push_back(&_data[i]); + } + mainListCurPos = cheatWnd_cursorPosition; + mainListScreenPos = cheatWnd_screenPosition; + cheatWnd_cursorPosition = 0; + } else { + cParsedItem &cheat = *currentList[cheatWnd_cursorPosition]; + bool select = !(cheat._flags & cParsedItem::ESelected); + if(cheat._flags & cParsedItem::EOne) + deselectFolder(std::distance(&_data[0], currentList[cheatWnd_cursorPosition])); + if(select || !(cheat._flags & cParsedItem::EOne)) + cheat._flags ^= cParsedItem::ESelected; + } + } else if(pressed & KEY_B) { + snd().playBack(); + if(mainListCurPos != -1) { + currentList.clear(); + for(uint i=0;i<_data.size();i++) { + if(!(_data[i]._flags&cParsedItem::EInFolder)) { + currentList.push_back(&_data[i]); + } + } + cheatWnd_cursorPosition = mainListCurPos; + cheatWnd_screenPosition = mainListScreenPos; + mainListCurPos = -1; + } else { + break; + } + } else if(pressed & KEY_X) { + snd().playLaunch(); + clearText(); + printLarge(false, 0, 30, STR_CHEATS, Alignment::center); + printSmall(false, 0, 100, STR_SAVING, Alignment::center); + onGenerate(); + break; + } else if(pressed & KEY_Y) { + if(currentList[cheatWnd_cursorPosition]->_comment != "") { + (ms().theme == 4) ? snd().playLaunch() : snd().playSelect(); + clearText(); + printLarge(false, 0, 30, STR_CHEATS, Alignment::center); + + std::string _topText = ""; + std::string _topTextStr(currentList[cheatWnd_cursorPosition]->_comment); + std::vector words; + std::size_t pos; + + // Process comment to stay within the box + while((pos = _topTextStr.find(' ')) != std::string::npos) { + words.push_back(_topTextStr.substr(0, pos)); + _topTextStr = _topTextStr.substr(pos + 1); + } + if(_topTextStr.size()) + words.push_back(_topTextStr); + std::string temp; + for(auto word : words) { + // Split word if the word is too long for a line + int width = calcSmallFontWidth(word); + if(width > 240) { + if(temp.length()) + _topText += temp + '\n'; + for(int i = 0; i < width/240; i++) { + word.insert((float)((i + 1) * word.length()) / ((width/240) + 1), "\n"); + } + _topText += word + '\n'; + continue; + } + + width = calcSmallFontWidth(temp + " " + word); + if(width > 240) { + _topText += temp + '\n'; + temp = word; + } else { + temp += " " + word; + } + } + if(temp.size()) + _topText += temp; + + // Print comment + printSmall(false, 0, 60, _topText, Alignment::center); + + // Print 'Back' text + printSmall(false, 0, 160, STR_B_BACK, Alignment::center); + while(1) { + scanKeys(); + pressed = keysDown(); + checkSdEject(); + tex().drawVolumeImageCached(); + tex().drawBatteryImageCached(); + drawCurrentTime(); + drawCurrentDate(); + drawClockColon(); + snd().updateStream(); + swiWaitForVBlank(); + if(pressed & KEY_B) { + snd().playBack(); + break; + } + } + } + } else if(pressed & KEY_L) { + // Delect all in the actual data so it doesn't just get the folder + for(auto itr = _data.begin(); itr != _data.end(); itr++) { + (*itr)._flags &= ~cParsedItem::ESelected; + } + // Also deselect them in the current list so that it updates the display + for(auto itr = currentList.begin(); itr != currentList.end(); itr++) { + (*itr)->_flags &= ~cParsedItem::ESelected; + } + } + } } static void updateDB(u8 value,u32 offset,FILE* db) { - u8 oldvalue; - if(!db) return; - if(!offset) return; - if(fseek(db,offset,SEEK_SET)) return; - if(fread(&oldvalue,sizeof(oldvalue),1,db)!=1) return; - if(oldvalue!=value) - { - if(fseek(db,offset,SEEK_SET)) return; - fwrite(&value,sizeof(value),1,db); - } + u8 oldvalue; + if(!db) return; + if(!offset) return; + if(fseek(db,offset,SEEK_SET)) return; + if(fread(&oldvalue,sizeof(oldvalue),1,db)!=1) return; + if(oldvalue!=value) + { + if(fseek(db,offset,SEEK_SET)) return; + fwrite(&value,sizeof(value),1,db); + } } void CheatCodelist::onGenerate(void) { - const char* usrcheatPath = (sdFound() || !ms().secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; + const char* usrcheatPath = (sdFound() || !ms().secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; if (ms().secondaryDevice && !ms().useBootstrap) { - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + switch (ms().flashcard) { + case 1: { + usrcheatPath = "fat:/TTMenu/usrcheat.dat"; + break; + } + case 3: + case 6: + case 2: { + usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; + break; + } + case 5: // TODO: WoodRPG? Test + case 4: { + usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + break; + } + case 7: { + usrcheatPath = "fat:/_dstwo/usrcheat.dat"; + break; + } } } - FILE* db=fopen(usrcheatPath,"r+b"); - if(db) - { - std::vector::iterator itr=_data.begin(); - while(itr!=_data.end()) - { - updateDB(((*itr)._flags&cParsedItem::ESelected)?1:0,(*itr)._offset,db); - ++itr; - } - fclose(db); - } + + FILE* db=fopen(usrcheatPath,"r+b"); + if(db) + { + std::vector::iterator itr=_data.begin(); + while(itr!=_data.end()) + { + updateDB(((*itr)._flags&cParsedItem::ESelected)?1:0,(*itr)._offset,db); + ++itr; + } + fclose(db); + } } void writeCheatsToFile(std::string data, const char* path) { - std::fstream fs; - fs.open(path, std::ios::binary | std::fstream::out); - std::stringstream str; - u32 value; - while(1) { - str.clear(); - str << data.substr(0, data.find(" ")); - str >> std::hex >> value; - fs.write(reinterpret_cast(&value),sizeof(value)); - data = data.substr(data.find(" ")+1); - if((int)data.find(" ") == -1) break; - } - fs.write("\0\0\0\xCF", 4); - fs.close(); + std::fstream fs; + fs.open(path, std::ios::binary | std::fstream::out); + std::stringstream str; + u32 value; + while(1) { + str.clear(); + str << data.substr(0, data.find(" ")); + str >> std::hex >> value; + fs.write(reinterpret_cast(&value),sizeof(value)); + data = data.substr(data.find(" ")+1); + if((int)data.find(" ") == -1) break; + } + fs.write("\0\0\0\xCF", 4); + fs.close(); } diff --git a/romsel_dsimenutheme/arm9/source/common/dsimenusettings.cpp b/romsel_dsimenutheme/arm9/source/common/dsimenusettings.cpp index b576c9876f..52b4583ea5 100644 --- a/romsel_dsimenutheme/arm9/source/common/dsimenusettings.cpp +++ b/romsel_dsimenutheme/arm9/source/common/dsimenusettings.cpp @@ -64,7 +64,7 @@ TWLSettings::TWLSettings() updateRecentlyPlayedList = true; sortMethod = 0; - flashcard = EDSTTClone; + flashcard = 0; slot1LaunchMethod = EDirect; @@ -128,6 +128,8 @@ void TWLSettings::loadSettings() startMenu_cursorPosition = settingsini.GetInt("SRLOADER", "STARTMENU_CURSOR_POSITION", startMenu_cursorPosition); consoleModel = settingsini.GetInt("SRLOADER", "CONSOLE_MODEL", consoleModel); + flashcard = settingsini.GetInt("SRLOADER", "FLASHCARD", flashcard); + showNds = settingsini.GetInt("SRLOADER", "SHOW_NDS", showNds); showRvid = settingsini.GetInt("SRLOADER", "SHOW_RVID", showRvid); showA26 = settingsini.GetInt("SRLOADER", "SHOW_A26", showA26); @@ -233,6 +235,7 @@ void TWLSettings::saveSettings() if (bothSDandFlashcard()) { settingsini.SetInt("SRLOADER", "SECONDARY_DEVICE", secondaryDevice); } + settingsini.SetInt("SRLOADER", "FLASHCARD", flashcard); if (!gotosettings) { settingsini.SetInt("SRLOADER", "PREVIOUS_USED_DEVICE", previousUsedDevice); diff --git a/romsel_dsimenutheme/arm9/source/common/dsimenusettings.h b/romsel_dsimenutheme/arm9/source/common/dsimenusettings.h index 8b76e7e0ef..a34aa34e24 100644 --- a/romsel_dsimenutheme/arm9/source/common/dsimenusettings.h +++ b/romsel_dsimenutheme/arm9/source/common/dsimenusettings.h @@ -33,24 +33,28 @@ class TWLSettings }; /* - 0: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE - 1: R4DS (Original Non-SDHC version)/ M3 Simply - 2: R4iDSN/R4i Gold RTS/R4 Ultra - 3: Acekard 2(i)/Galaxy Eagle/M3DS Real - 4: Acekard RPG - 5: Ace 3DS+/Gateway Blue Card/R4iTT - 6: SuperCard DSTWO + 0: Unknown + 1: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE + 2: R4DS (Original Non-SDHC version)/ M3 Simply + 3: R4iDSN/R4i Gold RTS/R4 Ultra + 4: Acekard 2(i)/Galaxy Eagle/M3DS Real + 5: Acekard RPG + 6: Ace 3DS+/Gateway Blue Card/R4iTT + 7: SuperCard DSTWO + 8: CycloDS iEvolution */ enum TFlashCard { - EDSTTClone = 0, - ER4Original = 1, - ER4iGoldClone = 2, - EAcekard2i = 3, - EAcekardRPG = 4, - EGatewayBlue = 5, - ESupercardDSTWO = 6 + EUnknown = 0, + EDSTTClone = 1, + ER4Original = 2, + ER4iGoldClone = 3, + EAcekard2i = 4, + EAcekardRPG = 5, + EGatewayBlue = 6, + ESupercardDSTWO = 7, + ECycloDSi = 8 }; // Do not reorder these, just add to the end diff --git a/romsel_dsimenutheme/arm9/source/fileBrowse.cpp b/romsel_dsimenutheme/arm9/source/fileBrowse.cpp index b0ee9821f7..c771e93f41 100644 --- a/romsel_dsimenutheme/arm9/source/fileBrowse.cpp +++ b/romsel_dsimenutheme/arm9/source/fileBrowse.cpp @@ -430,7 +430,7 @@ void displayNowLoading(void) { fadeType = true; // Fade in from white snd().updateStream(); std::string *msg; - if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { + if (isDSiMode() && ms().flashcard == 8) { msg = &STR_TAKEWHILE_TURNOFF; } else if (REG_SCFG_EXT != 0 && ms().consoleModel >= 2) { msg = &STR_TAKEWHILE_PRESSHOME; @@ -1268,7 +1268,7 @@ bool selectMenu(void) { int selCursorPosition = 0; int assignedOp[5] = {-1}; int selIconYpos = 96; - if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) != 0) { + if (isDSiMode() && ms().flashcard != 8) { for (int i = 0; i < 4; i++) { selIconYpos -= 14; } @@ -1321,7 +1321,7 @@ bool selectMenu(void) { } else { printSmall(false, 64, textYpos, STR_SWITCH_TO_SLOT_1); } - } else if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) != 0) { + } else if (isDSiMode() && ms().flashcard != 8) { printSmall(false, 64, textYpos, (REG_SCFG_MC == 0x11) ? STR_NO_SLOT_1 : STR_LAUNCH_SLOT_1); } } else if (assignedOp[i] == 3) { diff --git a/romsel_dsimenutheme/arm9/source/graphics/graphics.cpp b/romsel_dsimenutheme/arm9/source/graphics/graphics.cpp index 44a6d389c8..97c0011792 100644 --- a/romsel_dsimenutheme/arm9/source/graphics/graphics.cpp +++ b/romsel_dsimenutheme/arm9/source/graphics/graphics.cpp @@ -1256,15 +1256,10 @@ void vBlankHandler() { drawIcon(24, ((ms().theme == 4 || ms().theme == 5) ? 0 : dbox_Ypos) + 24, CURPOS); } if (dbox_selectMenu) { + bool noCycloDSi = isDSiMode() && ms().flashcard != 8; int selIconYpos = 96; - if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) != 0) { - for (int i = 0; i < 4; i++) { - selIconYpos -= 14; - } - } else { - for (int i = 0; i < 3; i++) { - selIconYpos -= 14; - } + for (int i = 0; i < (noCycloDSi ? 4 : 3); i++) { + selIconYpos -= 14; } if (!sys().isRegularDS()) { glSprite(32, (ms().theme == 4 ? 0 : dbox_Ypos) + selIconYpos, GL_FLIP_NONE, @@ -1274,16 +1269,10 @@ void vBlankHandler() { glSprite(32, (ms().theme == 4 ? 0 : dbox_Ypos) + selIconYpos, GL_FLIP_NONE, &tex().cornerButtonImage()[0]); // Settings selIconYpos += 28; - if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) != 0) { - if (ms().secondaryDevice) { - glSprite(32, (ms().theme == 4 ? 0 : dbox_Ypos) + selIconYpos, GL_FLIP_NONE, - &tex().smallCartImage()[2]); // SD card - } else { - glSprite( - 32, (ms().theme == 4 ? 0 : dbox_Ypos) + selIconYpos, GL_FLIP_NONE, - &tex().smallCartImage()[(REG_SCFG_MC == 0x11) ? 1 - : 0]); // Slot-1 card - } + if (noCycloDSi) { + glSprite( + 32, (ms().theme == 4 ? 0 : dbox_Ypos) + selIconYpos, GL_FLIP_NONE, + &tex().smallCartImage()[ms().secondaryDevice ? 2 : (REG_SCFG_MC == 0x11)]); selIconYpos += 28; } if (!ms().useGbarunner && sys().isRegularDS()) { diff --git a/romsel_dsimenutheme/arm9/source/iconTitle.cpp b/romsel_dsimenutheme/arm9/source/iconTitle.cpp index 5ecc749248..bdd4d35e06 100644 --- a/romsel_dsimenutheme/arm9/source/iconTitle.cpp +++ b/romsel_dsimenutheme/arm9/source/iconTitle.cpp @@ -371,7 +371,7 @@ void getGameInfo(bool isDir, const char *name, int num) { } bool usingFlashcard = (!isDSiMode() && ms().secondaryDevice); - bool hasCycloDSi = (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0); + bool hasCycloDSi = ms().flashcard == 8; if (num < 40) { tonccpy(gameTid[num], ndsHeader.gameCode, 4); diff --git a/romsel_dsimenutheme/arm9/source/main.cpp b/romsel_dsimenutheme/arm9/source/main.cpp index 46eb42ab3e..34dff5bdd7 100644 --- a/romsel_dsimenutheme/arm9/source/main.cpp +++ b/romsel_dsimenutheme/arm9/source/main.cpp @@ -379,34 +379,46 @@ void loadGameOnFlashcard (const char *ndsPath, bool dsGame) { int err = 0; snd().stopStream(); - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); - fcPath = replaceAll(ndsPath, "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); - err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); - fcPath = replaceAll(ndsPath, "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); - err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { - CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); - fcPath = replaceAll(ndsPath, "fat:/", dstwofat); - fcrompathini.SetString("Dir Info", "fullName", fcPath); - fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); - err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if ((memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0)) { - CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); - fcPath = replaceAll(ndsPath, "fat:/", slashchar); - fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); - fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); - err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + switch (ms().flashcard) { + case 1: { + CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); + fcPath = replaceAll(ndsPath, "fat:/", slashchar); + fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); + fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); + err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 6: // Blue card can run wood 1.62 so this should work? + case 2: // And clones that can run wood (no N5) + case 3: { + CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); + fcPath = replaceAll(ndsPath, "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); + err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 7: { + CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); + fcPath = replaceAll(ndsPath, "fat:/", dstwofat); + fcrompathini.SetString("Dir Info", "fullName", fcPath); + fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); + err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 5: // ? + case 4: { + CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); + fcPath = replaceAll(ndsPath, "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); + err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + default: { + err = 1337; + break; + } } char text[64]; @@ -681,7 +693,7 @@ int main(int argc, char **argv) { extensionList.emplace_back(".app"); extensionList.emplace_back(".argv"); } - if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { + if (ms().flashcard == 7) { extensionList.emplace_back(".plg"); } if (ms().showRvid) { @@ -908,7 +920,7 @@ int main(int argc, char **argv) { if ((getFileSize(ms().dsiWarePubPath.c_str()) == 0) && (NDSHeader.pubSavSize > 0)) { if (ms().theme == 5) displayGameIcons = false; clearText(); - if (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { + if (ms().flashcard == 8) { // Display nothing } else if (ms().consoleModel >= 2) { printSmall(false, 0, 20, STR_TAKEWHILE_PRESSHOME, Alignment::center); @@ -954,7 +966,7 @@ int main(int argc, char **argv) { if ((getFileSize(ms().dsiWarePrvPath.c_str()) == 0) && (NDSHeader.prvSavSize > 0)) { if (ms().theme == 5) displayGameIcons = false; clearText(); - if (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { + if (ms().flashcard == 8) { // Display nothing } else if (ms().consoleModel >= 2) { printSmall(false, 0, 20, STR_TAKEWHILE_PRESSHOME, Alignment::center); @@ -1024,11 +1036,8 @@ int main(int argc, char **argv) { bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", 1); bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", (ms().forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !sys().isRegularDS())) - ); + || ((ms().flashcard == 1 || ms().flashcard == 3) && !sys().isRegularDS()) + )); bootstrapini.SaveIniFile(bootstrapinipath); @@ -1269,7 +1278,7 @@ int main(int argc, char **argv) { if ((orgsavesize == 0 && savesize > 0) || (orgsavesize < savesize && saveSizeFixNeeded)) { if (ms().theme == 5) displayGameIcons = false; - if (isDSiMode() && memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0) { + if (isDSiMode() && ms().flashcard == 8) { // Display nothing } else if (REG_SCFG_EXT != 0 && ms().consoleModel >= 2) { printSmall(false, 0, 20, STR_TAKEWHILE_PRESSHOME, Alignment::center); @@ -1341,10 +1350,7 @@ int main(int argc, char **argv) { bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", ceCached); bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", (ms().forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !sys().isRegularDS()) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !sys().isRegularDS())) + || ((ms().flashcard == 1 || ms().flashcard == 3) && !sys().isRegularDS())) ); if (!isDSiMode() && ms().secondaryDevice && sdFound()) { CIniFile bootstrapiniSD("sd:/_nds/nds-bootstrap.ini"); diff --git a/romsel_dsimenutheme/arm9/source/perGameSettings.cpp b/romsel_dsimenutheme/arm9/source/perGameSettings.cpp index f8ca707740..3ae30faca9 100644 --- a/romsel_dsimenutheme/arm9/source/perGameSettings.cpp +++ b/romsel_dsimenutheme/arm9/source/perGameSettings.cpp @@ -189,7 +189,7 @@ bool showSetDonorRom(u32 arm7size, u32 SDKVersion) { if (requiresDonorRom[CURPOS]) return false; bool usingFlashcard = (!isDSiMode() && ms().secondaryDevice); - bool hasCycloDSi = (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0); + bool hasCycloDSi = ms().flashcard == 8; if (((usingFlashcard || hasCycloDSi) && SDKVersion > 0x2000000 && SDKVersion < 0x2008000 // Early SDK2 && (arm7size==0x25F70 @@ -324,11 +324,9 @@ void perGameSettings (std::string filename) { }*/ bool showCheats = ((isDSiMode() && ms().useBootstrap) + // TODO: Enable /*|| (ms().secondaryDevice && !ms().useBootstrap - && ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0)))*/ + && ms().flashcard != 0))*/ || !ms().secondaryDevice); firstPerGameOpShown = 0; diff --git a/romsel_r4theme/arm9/source/cheat.cpp b/romsel_r4theme/arm9/source/cheat.cpp index 046fe56f25..d002857947 100644 --- a/romsel_r4theme/arm9/source/cheat.cpp +++ b/romsel_r4theme/arm9/source/cheat.cpp @@ -1,21 +1,21 @@ /* - cheat.cpp - Portions copyright (C) 2008 Normmatt, www.normmatt.com, Smiths (www.emuholic.com) - Portions copyright (C) 2008 bliss (bliss@hanirc.org) - Copyright (C) 2009 yellow wood goblin - - 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 3 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, see . + cheat.cpp + Portions copyright (C) 2008 Normmatt, www.normmatt.com, Smiths (www.emuholic.com) + Portions copyright (C) 2008 bliss (bliss@hanirc.org) + Copyright (C) 2009 yellow wood goblin + + 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 3 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, see . */ #include @@ -37,525 +37,554 @@ extern int dialogboxHeight; extern bool useBootstrap; +extern int flashcard; CheatCodelist::~CheatCodelist(void) {} inline u32 gamecode(const char *aGameCode) { - u32 gameCode; - memcpy(&gameCode, aGameCode, sizeof(gameCode)); - return gameCode; + u32 gameCode; + memcpy(&gameCode, aGameCode, sizeof(gameCode)); + return gameCode; } #define CRCPOLY 0xedb88320 static u32 crc32(const u8* p,size_t len) { - u32 crc=-1; - while(len--) - { - crc^=*p++; - for(int ii=0;ii<8;++ii) crc=(crc>>1)^((crc&1)?CRCPOLY:0); - } - return crc; + u32 crc=-1; + while(len--) + { + crc^=*p++; + for(int ii=0;ii<8;++ii) crc=(crc>>1)^((crc&1)?CRCPOLY:0); + } + return crc; } bool CheatCodelist::parse(const std::string& aFileName) { - bool res=false; - u32 romcrc32,gamecode; - if(romData(aFileName,gamecode,romcrc32)) - { - const char* usrcheatPath = (sdFound() || !secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; + bool res=false; + u32 romcrc32,gamecode; + if(romData(aFileName,gamecode,romcrc32)) + { + const char* usrcheatPath = (sdFound() || !secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; if (secondaryDevice && !useBootstrap) { - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + switch (flashcard) { + case 1: { + usrcheatPath = "fat:/TTMenu/usrcheat.dat"; + break; + } + case 3: + case 6: + case 2: { + usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; + break; + } + case 5: // TODO: WoodRPG? Test + case 4: { + usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + break; + } + case 7: { + usrcheatPath = "fat:/_dstwo/usrcheat.dat"; + break; + } + } + } + FILE* dat=fopen(usrcheatPath,"rb"); + if(dat) + { + res=parseInternal(dat,gamecode,romcrc32); + fclose(dat); } } - FILE* dat=fopen(usrcheatPath,"rb"); - if(dat) - { - res=parseInternal(dat,gamecode,romcrc32); - fclose(dat); - } - } - return res; + return res; } bool CheatCodelist::searchCheatData(FILE* aDat,u32 gamecode,u32 crc32,long& aPos,size_t& aSize) { - aPos=0; - aSize=0; - const char* KHeader="R4 CheatCode"; - char header[12]; - fread(header,12,1,aDat); - if(strncmp(KHeader,header,12)) return false; - - sDatIndex idx,nidx; - - fseek(aDat,0,SEEK_END); - long fileSize=ftell(aDat); - - fseek(aDat,0x100,SEEK_SET); - fread(&nidx,sizeof(nidx),1,aDat); - - bool done=false; - - while(!done) - { - tonccpy(&idx,&nidx,sizeof(idx)); - fread(&nidx,sizeof(nidx),1,aDat); - if(gamecode==idx._gameCode&&crc32==idx._crc32) - { - aSize=((nidx._offset)?nidx._offset:fileSize)-idx._offset; - aPos=idx._offset; - done=true; - } - if(!nidx._offset) done=true; - } - return (aPos&&aSize); + aPos=0; + aSize=0; + const char* KHeader="R4 CheatCode"; + char header[12]; + fread(header,12,1,aDat); + if(strncmp(KHeader,header,12)) return false; + + sDatIndex idx,nidx; + + fseek(aDat,0,SEEK_END); + long fileSize=ftell(aDat); + + fseek(aDat,0x100,SEEK_SET); + fread(&nidx,sizeof(nidx),1,aDat); + + bool done=false; + + while(!done) + { + tonccpy(&idx,&nidx,sizeof(idx)); + fread(&nidx,sizeof(nidx),1,aDat); + if(gamecode==idx._gameCode&&crc32==idx._crc32) + { + aSize=((nidx._offset)?nidx._offset:fileSize)-idx._offset; + aPos=idx._offset; + done=true; + } + if(!nidx._offset) done=true; + } + return (aPos&&aSize); } bool CheatCodelist::parseInternal(FILE* aDat,u32 gamecode,u32 crc32) { - dbg_printf("%x, %x\n",gamecode,crc32); - - _data.clear(); - - long dataPos; size_t dataSize; - if(!searchCheatData(aDat,gamecode,crc32,dataPos,dataSize)) return false; - fseek(aDat,dataPos,SEEK_SET); - - dbg_printf("record found: %d\n",dataSize); - - char* buffer=(char*)malloc(dataSize); - if(!buffer) return false; - fread(buffer,dataSize,1,aDat); - char* gameTitle=buffer; - - u32* ccode=(u32*)(((u32)gameTitle+strlen(gameTitle)+4)&~3); - u32 cheatCount=*ccode; - cheatCount&=0x0fffffff; - ccode+=9; - - u32 cc=0; - while(cc>28)&1) - { - flagItem|=cParsedItem::EInFolder; - if((*ccode>>24)==0x11) flagItem|=cParsedItem::EOne; - folderCount=*ccode&0x00ffffff; - folderName=(char*)((u32)ccode+4); - folderNote=(char*)((u32)folderName+strlen(folderName)+1); - _data.push_back(cParsedItem(folderName,folderNote,cParsedItem::EFolder)); - cc++; - ccode=(u32*)(((u32)folderName+strlen(folderName)+1+strlen(folderNote)+1+3)&~3); - } - - u32 selectValue=cParsedItem::ESelected; - for(size_t ii=0;ii>28)&1) + { + flagItem|=cParsedItem::EInFolder; + if((*ccode>>24)==0x11) flagItem|=cParsedItem::EOne; + folderCount=*ccode&0x00ffffff; + folderName=(char*)((u32)ccode+4); + folderNote=(char*)((u32)folderName+strlen(folderName)+1); + _data.push_back(cParsedItem(folderName,folderNote,cParsedItem::EFolder)); + cc++; + ccode=(u32*)(((u32)folderName+strlen(folderName)+1+strlen(folderNote)+1+3)&~3); + } + + u32 selectValue=cParsedItem::ESelected; + for(size_t ii=0;ii::iterator itr=_data.begin(); - while(itr!=_data.end()) - { - std::vector row; - row.push_back(""); - row.push_back((*itr)._title); - // _List.insertRow(_List.getRowCount(),row); - _indexes.push_back(itr-_data.begin()); - u32 flags=(*itr)._flags; - ++itr; - if((flags&cParsedItem::EFolder)&&(flags&cParsedItem::EOpen)==0) - { - while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) ++itr; - } - } + _indexes.clear(); + // _List.removeAllRows(); + + std::vector::iterator itr=_data.begin(); + while(itr!=_data.end()) + { + std::vector row; + row.push_back(""); + row.push_back((*itr)._title); + // _List.insertRow(_List.getRowCount(),row); + _indexes.push_back(itr-_data.begin()); + u32 flags=(*itr)._flags; + ++itr; + if((flags&cParsedItem::EFolder)&&(flags&cParsedItem::EOpen)==0) + { + while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) ++itr; + } + } } void CheatCodelist::deselectFolder(size_t anIndex) { - std::vector::iterator itr=_data.begin()+anIndex; - while(--itr>=_data.begin()) - { - if((*itr)._flags&cParsedItem::EFolder) - { - ++itr; - break; - } - } - while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) - { - (*itr)._flags&=~cParsedItem::ESelected; - ++itr; - } + std::vector::iterator itr=_data.begin()+anIndex; + while(--itr>=_data.begin()) + { + if((*itr)._flags&cParsedItem::EFolder) + { + ++itr; + break; + } + } + while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) + { + (*itr)._flags&=~cParsedItem::ESelected; + ++itr; + } } bool CheatCodelist::romData(const std::string& aFileName,u32& aGameCode,u32& aCrc32) { - bool res=false; - FILE* rom=fopen(aFileName.c_str(),"rb"); - if(rom) - { - u8 header[512]; - if(1==fread(header,sizeof(header),1,rom)) - { - aCrc32=crc32(header,sizeof(header)); - aGameCode=gamecode((const char*)(header+12)); - res=true; - } - fclose(rom); - } - return res; + bool res=false; + FILE* rom=fopen(aFileName.c_str(),"rb"); + if(rom) + { + u8 header[512]; + if(1==fread(header,sizeof(header),1,rom)) + { + aCrc32=crc32(header,sizeof(header)); + aGameCode=gamecode((const char*)(header+12)); + res=true; + } + fclose(rom); + } + return res; } std::string CheatCodelist::getCheats() { - std::string cheats; - for(uint i=0;i< _data.size();i++) - { - if(_data[i]._flags&cParsedItem::ESelected) - { - cheats += _data[i]._cheat.substr(0, _data[i]._cheat.size()); - } - } - std::replace( cheats.begin(), cheats.end(), '\n', ' '); - return cheats; + std::string cheats; + for(uint i=0;i< _data.size();i++) + { + if(_data[i]._flags&cParsedItem::ESelected) + { + cheats += _data[i]._cheat.substr(0, _data[i]._cheat.size()); + } + } + std::replace( cheats.begin(), cheats.end(), '\n', ' '); + return cheats; } void CheatCodelist::drawCheatList(std::vector& list, uint curPos, uint screenPos) { - for(uint i=0;(int)i<(dialogboxHeight+2) && i_flags&cParsedItem::EFolder) { - if(screenPos+i == curPos) { - printSmall(false, 27, 90+(i*10), ">"); - printSmall(false, 35, 90+(i*10), list[screenPos+i]->_title.c_str()); - } else { - printSmall(false, 22, 90+(i*10), ">"); - printSmall(false, 30, 90+(i*10), list[screenPos+i]->_title.c_str()); - } - } else { - if(list[screenPos+i]->_flags&cParsedItem::ESelected) { - printSmall(false, 16, 89+(i*10), "x"); - } - if(screenPos+i == curPos) { - printSmall(false, 25, 90+(i*10), "-"); - printSmall(false, 32, 90+(i*10), list[screenPos+i]->_title.c_str()); - } else { - printSmall(false, 21, 90+(i*10), "-"); - printSmall(false, 28, 90+(i*10), list[screenPos+i]->_title.c_str()); - } - } - } + for(uint i=0;(int)i<(dialogboxHeight+2) && i_flags&cParsedItem::EFolder) { + if(screenPos+i == curPos) { + printSmall(false, 27, 90+(i*10), ">"); + printSmall(false, 35, 90+(i*10), list[screenPos+i]->_title.c_str()); + } else { + printSmall(false, 22, 90+(i*10), ">"); + printSmall(false, 30, 90+(i*10), list[screenPos+i]->_title.c_str()); + } + } else { + if(list[screenPos+i]->_flags&cParsedItem::ESelected) { + printSmall(false, 16, 89+(i*10), "x"); + } + if(screenPos+i == curPos) { + printSmall(false, 25, 90+(i*10), "-"); + printSmall(false, 32, 90+(i*10), list[screenPos+i]->_title.c_str()); + } else { + printSmall(false, 21, 90+(i*10), "-"); + printSmall(false, 28, 90+(i*10), list[screenPos+i]->_title.c_str()); + } + } + } } void CheatCodelist::selectCheats(std::string filename) { - int pressed = 0; - int held = 0; - - clearText(); - - int oldDialogboxHeight = dialogboxHeight; - dialogboxHeight = 5; - - titleUpdate(isDirectory, filename.c_str()); - printLargeCentered(false, 74, "Cheats"); - printSmallCentered(false, 100, "Loading..."); - - parse(filename); - - bool cheatsFound = true; - // If no cheats are found - if(_data.size() == 0) { - cheatsFound = false; - clearText(); - titleUpdate(isDirectory, filename.c_str()); - printLargeCentered(false, 74, "Cheats"); - printSmallCentered(false, 100, "No cheats found"); - printSmallCentered(false, 160, "B: Back"); - - while(1) { - snd().updateStream(); - scanKeys(); - pressed = keysDownRepeat(); - checkSdEject(); - swiWaitForVBlank(); - if(pressed & KEY_B) { - break; - } - } - } - - // Make list of all cheats not in folders and folders - std::vector currentList; - for(uint i=0;i<_data.size();i++) { - if(!(_data[i]._flags&cParsedItem::EInFolder)) { - currentList.push_back(&_data[i]); - } - } - - int mainListCurPos = -1, mainListScreenPos = -1, - cheatWnd_cursorPosition = 0, cheatWnd_screenPosition = 0; - - while(cheatsFound) { - clearText(); - titleUpdate(isDirectory, filename.c_str()); - printLargeCentered(false, 74, "Cheats"); - - // Print bottom text - if(currentList[cheatWnd_cursorPosition]->_comment != "") { - if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { - printSmallCentered(false, 167, "A: Open Y: Info X: Save B: Cancel"); - } else if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::ESelected) { - printSmallCentered(false, 167, "A: Deselect Y: Info X: Save B: Cancel"); - } else { - printSmallCentered(false, 167, "A: Select Y: Info X: Save B: Cancel"); - } - } else { - if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { - printSmallCentered(false, 167, "A: Open X: Save B: Cancel"); - } else if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::ESelected) { - printSmallCentered(false, 167, "A: Deselect X: Save B: Cancel"); - } else { - printSmallCentered(false, 167, "A: Select X: Save B: Cancel"); - } - } - - // Scroll screen if needed - if(cheatWnd_cursorPosition < cheatWnd_screenPosition) { - cheatWnd_screenPosition = cheatWnd_cursorPosition; - } else if(cheatWnd_cursorPosition > cheatWnd_screenPosition + (dialogboxHeight+2) - 1) { - cheatWnd_screenPosition = cheatWnd_cursorPosition - (dialogboxHeight+2) + 1; - } - - drawCheatList(currentList, cheatWnd_cursorPosition, cheatWnd_screenPosition); - - do { - snd().updateStream(); - scanKeys(); - pressed = keysDown(); - held = keysDownRepeat(); - checkSdEject(); - swiWaitForVBlank(); - } while(!pressed && !held); - - if(held & KEY_UP) { - if(cheatWnd_cursorPosition>0) { - cheatWnd_cursorPosition--; - } - } else if(held & KEY_DOWN) { - if(cheatWnd_cursorPosition<((int)currentList.size()-1)) { - cheatWnd_cursorPosition++; - } - } else if(held & KEY_LEFT) { - cheatWnd_cursorPosition -= (cheatWnd_cursorPosition > (dialogboxHeight+2) ? (dialogboxHeight+2) : cheatWnd_cursorPosition); - } else if(held & KEY_RIGHT) { - cheatWnd_cursorPosition += (cheatWnd_cursorPosition < (int)(currentList.size()-(dialogboxHeight+2)) ? (dialogboxHeight+2) : currentList.size()-cheatWnd_cursorPosition-1); - } else if(pressed & KEY_A) { - if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { - uint i = std::distance(&_data[0], currentList[cheatWnd_cursorPosition]) + 1; - currentList.clear(); - for(; !(_data[i]._flags & cParsedItem::EFolder) && i < _data.size(); i++) { - currentList.push_back(&_data[i]); - } - mainListCurPos = cheatWnd_cursorPosition; - mainListScreenPos = cheatWnd_screenPosition; - cheatWnd_cursorPosition = 0; - } else { - cParsedItem &cheat = *currentList[cheatWnd_cursorPosition]; - bool select = !(cheat._flags & cParsedItem::ESelected); - if(cheat._flags & cParsedItem::EOne) - deselectFolder(std::distance(&_data[0], currentList[cheatWnd_cursorPosition])); - if(select || !(cheat._flags & cParsedItem::EOne)) - cheat._flags ^= cParsedItem::ESelected; - } - } else if(pressed & KEY_B) { - if(mainListCurPos != -1) { - currentList.clear(); - for(uint i=0;i<_data.size();i++) { - if(!(_data[i]._flags&cParsedItem::EInFolder)) { - currentList.push_back(&_data[i]); - } - } - cheatWnd_cursorPosition = mainListCurPos; - cheatWnd_screenPosition = mainListScreenPos; - mainListCurPos = -1; - } else { - break; - } - } else if(pressed & KEY_X) { - clearText(); - titleUpdate(isDirectory, filename.c_str()); - printLargeCentered(false, 74, "Cheats"); - printSmallCentered(false, 100, "Saving..."); - onGenerate(); - break; - } - if(pressed & KEY_Y) { - if(currentList[cheatWnd_cursorPosition]->_comment != "") { - clearText(); - titleUpdate(isDirectory, filename.c_str()); - printLargeCentered(false, 74, "Cheats"); - - std::vector _topText; - std::string _topTextStr(currentList[cheatWnd_cursorPosition]->_comment); - std::vector words; - std::size_t pos; - - // Process comment to stay within the box - while((pos = _topTextStr.find(' ')) != std::string::npos) { - words.push_back(_topTextStr.substr(0, pos)); - _topTextStr = _topTextStr.substr(pos + 1); - } - if(_topTextStr.size()) - words.push_back(_topTextStr); - std::string temp; - for(auto word : words) { - // Split word if the word is too long for a line - int width = calcLargeFontWidth(word.c_str()); - if(width > 220) { - if(temp.length()) - _topText.push_back(temp); - for(int i = 0; i < width/240; i++) { - word.insert((float)((i + 1) * word.length()) / ((width/240) + 1), "\n"); - } - _topText.push_back(word); - continue; - } - - width = calcSmallFontWidth((temp + " " + word).c_str()); - if(width > 240) { - _topText.push_back(temp); - temp = word; - } else { - temp += " " + word; - } - } - if(temp.size()) - _topText.push_back(temp); - - // Print comment - for (int i = 0; i < (int)_topText.size(); i++) { - printSmallCentered(false, 90 + (i*10), _topText[i].c_str()); - } - - // Print 'Back' text - printSmallCentered(false, 167, "B: Back"); - while(1) { - snd().updateStream(); - scanKeys(); - pressed = keysDown(); - checkSdEject(); - swiWaitForVBlank(); - if(pressed & KEY_B) { - break; - } - } - } - } - if(pressed & KEY_L) { - // Delect all in the actual data so it doesn't just get the folder - for(auto itr = _data.begin(); itr != _data.end(); itr++) { - (*itr)._flags &= ~cParsedItem::ESelected; - } - // Also deselect them in the current list so that it updates the display - for(auto itr = currentList.begin(); itr != currentList.end(); itr++) { - (*itr)->_flags &= ~cParsedItem::ESelected; - } - } - } - dialogboxHeight = oldDialogboxHeight; + int pressed = 0; + int held = 0; + + clearText(); + + int oldDialogboxHeight = dialogboxHeight; + dialogboxHeight = 5; + + titleUpdate(isDirectory, filename.c_str()); + printLargeCentered(false, 74, "Cheats"); + printSmallCentered(false, 100, "Loading..."); + + parse(filename); + + bool cheatsFound = true; + // If no cheats are found + if(_data.size() == 0) { + cheatsFound = false; + clearText(); + titleUpdate(isDirectory, filename.c_str()); + printLargeCentered(false, 74, "Cheats"); + printSmallCentered(false, 100, "No cheats found"); + printSmallCentered(false, 160, "B: Back"); + + while(1) { + snd().updateStream(); + scanKeys(); + pressed = keysDownRepeat(); + checkSdEject(); + swiWaitForVBlank(); + if(pressed & KEY_B) { + break; + } + } + } + + // Make list of all cheats not in folders and folders + std::vector currentList; + for(uint i=0;i<_data.size();i++) { + if(!(_data[i]._flags&cParsedItem::EInFolder)) { + currentList.push_back(&_data[i]); + } + } + + int mainListCurPos = -1, mainListScreenPos = -1, + cheatWnd_cursorPosition = 0, cheatWnd_screenPosition = 0; + + while(cheatsFound) { + clearText(); + titleUpdate(isDirectory, filename.c_str()); + printLargeCentered(false, 74, "Cheats"); + + // Print bottom text + if(currentList[cheatWnd_cursorPosition]->_comment != "") { + if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { + printSmallCentered(false, 167, "A: Open Y: Info X: Save B: Cancel"); + } else if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::ESelected) { + printSmallCentered(false, 167, "A: Deselect Y: Info X: Save B: Cancel"); + } else { + printSmallCentered(false, 167, "A: Select Y: Info X: Save B: Cancel"); + } + } else { + if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { + printSmallCentered(false, 167, "A: Open X: Save B: Cancel"); + } else if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::ESelected) { + printSmallCentered(false, 167, "A: Deselect X: Save B: Cancel"); + } else { + printSmallCentered(false, 167, "A: Select X: Save B: Cancel"); + } + } + + // Scroll screen if needed + if(cheatWnd_cursorPosition < cheatWnd_screenPosition) { + cheatWnd_screenPosition = cheatWnd_cursorPosition; + } else if(cheatWnd_cursorPosition > cheatWnd_screenPosition + (dialogboxHeight+2) - 1) { + cheatWnd_screenPosition = cheatWnd_cursorPosition - (dialogboxHeight+2) + 1; + } + + drawCheatList(currentList, cheatWnd_cursorPosition, cheatWnd_screenPosition); + + do { + snd().updateStream(); + scanKeys(); + pressed = keysDown(); + held = keysDownRepeat(); + checkSdEject(); + swiWaitForVBlank(); + } while(!pressed && !held); + + if(held & KEY_UP) { + if(cheatWnd_cursorPosition>0) { + cheatWnd_cursorPosition--; + } + } else if(held & KEY_DOWN) { + if(cheatWnd_cursorPosition<((int)currentList.size()-1)) { + cheatWnd_cursorPosition++; + } + } else if(held & KEY_LEFT) { + cheatWnd_cursorPosition -= (cheatWnd_cursorPosition > (dialogboxHeight+2) ? (dialogboxHeight+2) : cheatWnd_cursorPosition); + } else if(held & KEY_RIGHT) { + cheatWnd_cursorPosition += (cheatWnd_cursorPosition < (int)(currentList.size()-(dialogboxHeight+2)) ? (dialogboxHeight+2) : currentList.size()-cheatWnd_cursorPosition-1); + } else if(pressed & KEY_A) { + if(currentList[cheatWnd_cursorPosition]->_flags&cParsedItem::EFolder) { + uint i = std::distance(&_data[0], currentList[cheatWnd_cursorPosition]) + 1; + currentList.clear(); + for(; !(_data[i]._flags & cParsedItem::EFolder) && i < _data.size(); i++) { + currentList.push_back(&_data[i]); + } + mainListCurPos = cheatWnd_cursorPosition; + mainListScreenPos = cheatWnd_screenPosition; + cheatWnd_cursorPosition = 0; + } else { + cParsedItem &cheat = *currentList[cheatWnd_cursorPosition]; + bool select = !(cheat._flags & cParsedItem::ESelected); + if(cheat._flags & cParsedItem::EOne) + deselectFolder(std::distance(&_data[0], currentList[cheatWnd_cursorPosition])); + if(select || !(cheat._flags & cParsedItem::EOne)) + cheat._flags ^= cParsedItem::ESelected; + } + } else if(pressed & KEY_B) { + if(mainListCurPos != -1) { + currentList.clear(); + for(uint i=0;i<_data.size();i++) { + if(!(_data[i]._flags&cParsedItem::EInFolder)) { + currentList.push_back(&_data[i]); + } + } + cheatWnd_cursorPosition = mainListCurPos; + cheatWnd_screenPosition = mainListScreenPos; + mainListCurPos = -1; + } else { + break; + } + } else if(pressed & KEY_X) { + clearText(); + titleUpdate(isDirectory, filename.c_str()); + printLargeCentered(false, 74, "Cheats"); + printSmallCentered(false, 100, "Saving..."); + onGenerate(); + break; + } + if(pressed & KEY_Y) { + if(currentList[cheatWnd_cursorPosition]->_comment != "") { + clearText(); + titleUpdate(isDirectory, filename.c_str()); + printLargeCentered(false, 74, "Cheats"); + + std::vector _topText; + std::string _topTextStr(currentList[cheatWnd_cursorPosition]->_comment); + std::vector words; + std::size_t pos; + + // Process comment to stay within the box + while((pos = _topTextStr.find(' ')) != std::string::npos) { + words.push_back(_topTextStr.substr(0, pos)); + _topTextStr = _topTextStr.substr(pos + 1); + } + if(_topTextStr.size()) + words.push_back(_topTextStr); + std::string temp; + for(auto word : words) { + // Split word if the word is too long for a line + int width = calcLargeFontWidth(word.c_str()); + if(width > 220) { + if(temp.length()) + _topText.push_back(temp); + for(int i = 0; i < width/240; i++) { + word.insert((float)((i + 1) * word.length()) / ((width/240) + 1), "\n"); + } + _topText.push_back(word); + continue; + } + + width = calcSmallFontWidth((temp + " " + word).c_str()); + if(width > 240) { + _topText.push_back(temp); + temp = word; + } else { + temp += " " + word; + } + } + if(temp.size()) + _topText.push_back(temp); + + // Print comment + for (int i = 0; i < (int)_topText.size(); i++) { + printSmallCentered(false, 90 + (i*10), _topText[i].c_str()); + } + + // Print 'Back' text + printSmallCentered(false, 167, "B: Back"); + while(1) { + snd().updateStream(); + scanKeys(); + pressed = keysDown(); + checkSdEject(); + swiWaitForVBlank(); + if(pressed & KEY_B) { + break; + } + } + } + } + if(pressed & KEY_L) { + // Delect all in the actual data so it doesn't just get the folder + for(auto itr = _data.begin(); itr != _data.end(); itr++) { + (*itr)._flags &= ~cParsedItem::ESelected; + } + // Also deselect them in the current list so that it updates the display + for(auto itr = currentList.begin(); itr != currentList.end(); itr++) { + (*itr)->_flags &= ~cParsedItem::ESelected; + } + } + } + dialogboxHeight = oldDialogboxHeight; } static void updateDB(u8 value,u32 offset,FILE* db) { - u8 oldvalue; - if(!db) return; - if(!offset) return; - if(fseek(db,offset,SEEK_SET)) return; - if(fread(&oldvalue,sizeof(oldvalue),1,db)!=1) return; - if(oldvalue!=value) - { - if(fseek(db,offset,SEEK_SET)) return; - fwrite(&value,sizeof(value),1,db); - } + u8 oldvalue; + if(!db) return; + if(!offset) return; + if(fseek(db,offset,SEEK_SET)) return; + if(fread(&oldvalue,sizeof(oldvalue),1,db)!=1) return; + if(oldvalue!=value) + { + if(fseek(db,offset,SEEK_SET)) return; + fwrite(&value,sizeof(value),1,db); + } } void CheatCodelist::onGenerate(void) { - const char* usrcheatPath = (sdFound() || !secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; + const char* usrcheatPath = (sdFound() || !secondaryDevice) ? "sd:/_nds/TWiLightMenu/extras/usrcheat.dat" : "fat:/_nds/TWiLightMenu/extras/usrcheat.dat"; if (secondaryDevice && !useBootstrap) { - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + switch (flashcard) { + case 1: { + usrcheatPath = "fat:/TTMenu/usrcheat.dat"; + break; + } + case 3: + case 6: + case 2: { + usrcheatPath = "fat:/_wfwd/cheats/usrcheat.dat"; + break; + } + case 5: // TODO: WoodRPG? Test + case 4: { + usrcheatPath = "fat:/_afwd/cheats/usrcheat.dat"; + break; + } + case 7: { + usrcheatPath = "fat:/_dstwo/usrcheat.dat"; + break; + } + } + } + FILE* db=fopen(usrcheatPath,"r+b"); + if(db) + { + std::vector::iterator itr=_data.begin(); + while(itr!=_data.end()) + { + updateDB(((*itr)._flags&cParsedItem::ESelected)?1:0,(*itr)._offset,db); + ++itr; } + fclose(db); } - FILE* db=fopen(usrcheatPath,"r+b"); - if(db) - { - std::vector::iterator itr=_data.begin(); - while(itr!=_data.end()) - { - updateDB(((*itr)._flags&cParsedItem::ESelected)?1:0,(*itr)._offset,db); - ++itr; - } - fclose(db); - } } void writeCheatsToFile(std::string data, const char* path) { - std::fstream fs; - fs.open(path, std::ios::binary | std::fstream::out); - std::stringstream str; - u32 value; - while(1) { - str.clear(); - str << data.substr(0, data.find(" ")); - str >> std::hex >> value; - fs.write(reinterpret_cast(&value),sizeof(value)); - data = data.substr(data.find(" ")+1); - if((int)data.find(" ") == -1) break; - } - fs.write("\0\0\0\xCF", 4); - fs.close(); + std::fstream fs; + fs.open(path, std::ios::binary | std::fstream::out); + std::stringstream str; + u32 value; + while(1) { + str.clear(); + str << data.substr(0, data.find(" ")); + str >> std::hex >> value; + fs.write(reinterpret_cast(&value),sizeof(value)); + data = data.substr(data.find(" ")+1); + if((int)data.find(" ") == -1) break; + } + fs.write("\0\0\0\xCF", 4); + fs.close(); } diff --git a/romsel_r4theme/arm9/source/iconTitle.cpp b/romsel_r4theme/arm9/source/iconTitle.cpp index f4ea194f67..9f50b03163 100644 --- a/romsel_r4theme/arm9/source/iconTitle.cpp +++ b/romsel_r4theme/arm9/source/iconTitle.cpp @@ -57,6 +57,8 @@ extern int consoleModel; extern bool dsiWareBooter; extern bool secondaryDevice; +extern int flashcard; + extern int theme; extern int colorMode; extern bool useGbarunner; @@ -723,7 +725,7 @@ void getGameInfo(bool isDir, const char* name) } bool usingFlashcard = (!isDSiMode() && secondaryDevice); - bool hasCycloDSi = (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0); + bool hasCycloDSi = flashcard == 8; romVersion = ndsHeader.romversion; switch (ndsHeader.arm7binarySize) { case 0x22B40: diff --git a/romsel_r4theme/arm9/source/main.cpp b/romsel_r4theme/arm9/source/main.cpp index 158c8cc8c9..258c50fd74 100644 --- a/romsel_r4theme/arm9/source/main.cpp +++ b/romsel_r4theme/arm9/source/main.cpp @@ -82,6 +82,7 @@ int consoleModel = 0; 2 = Nintendo 3DS 3 = New Nintendo 3DS */ bool isRegularDS = true; +int flashcard = 0; extern bool showdialogbox; extern int dialogboxHeight; @@ -186,6 +187,8 @@ void LoadSettings(void) { cursorPosition[1] = settingsini.GetInt("SRLOADER", "SECONDARY_CURSOR_POSITION", 0); //startMenu_cursorPosition = settingsini.GetInt("SRLOADER", "STARTMENU_CURSOR_POSITION", 1); consoleModel = settingsini.GetInt("SRLOADER", "CONSOLE_MODEL", 0); + + flashcard = settingsini.GetInt("SRLOADER", "FLASHCARD", flashcard); showNds = settingsini.GetInt("SRLOADER", "SHOW_NDS", true); showRvid = settingsini.GetInt("SRLOADER", "SHOW_RVID", true); @@ -691,34 +694,47 @@ void loadGameOnFlashcard (const char* ndsPath, bool dsGame) { std::string fcPath; int err = 0; - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); - fcPath = replaceAll(ndsPath, "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); - err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); - fcPath = replaceAll(ndsPath, "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); - err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { - CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); - fcPath = replaceAll(ndsPath, "fat:/", dstwofat); - fcrompathini.SetString("Dir Info", "fullName", fcPath); - fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); - err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if ((memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0)) { - CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); - fcPath = replaceAll(ndsPath, "fat:/", slashchar); - fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); - fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); - err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + + switch (flashcard) { + case 1: { + CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); + fcPath = replaceAll(ndsPath, "fat:/", slashchar); + fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); + fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); + err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 6: // Blue card can run wood 1.62 so this should work? + case 2: // And clones that can run wood (no N5) + case 3: { + CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); + fcPath = replaceAll(ndsPath, "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); + err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 7: { + CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); + fcPath = replaceAll(ndsPath, "fat:/", dstwofat); + fcrompathini.SetString("Dir Info", "fullName", fcPath); + fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); + err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 5: // ? + case 4: { + CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); + fcPath = replaceAll(ndsPath, "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); + err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + default: { + err = 1337; + break; + } } char text[32]; @@ -952,7 +968,7 @@ int main(int argc, char **argv) { extensionList.push_back(".app"); extensionList.push_back(".argv"); } - if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { + if (flashcard == 7) { extensionList.push_back(".plg"); } if (showRvid) { @@ -1473,10 +1489,7 @@ int main(int argc, char **argv) { bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", 1); bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", (forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !isRegularDS)) + || ((flashcard == 1 || flashcard == 3) && !isRegularDS)) ); bootstrapini.SaveIniFile(bootstrapinipath); @@ -1733,10 +1746,7 @@ int main(int argc, char **argv) { bootstrapini.SetInt("NDS-BOOTSTRAP", "CARDENGINE_CACHED", ceCached); bootstrapini.SetInt("NDS-BOOTSTRAP", "FORCE_SLEEP_PATCH", (forceSleepPatch - || (memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0 && !isRegularDS) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0 && !isRegularDS)) + || ((flashcard == 1 || flashcard == 3) && !isRegularDS)) ); if (!isDSiMode() && secondaryDevice && sdFound()) { CIniFile bootstrapiniSD("sd:/_nds/nds-bootstrap.ini"); diff --git a/romsel_r4theme/arm9/source/perGameSettings.cpp b/romsel_r4theme/arm9/source/perGameSettings.cpp index 11fcf2e03d..75371862ca 100644 --- a/romsel_r4theme/arm9/source/perGameSettings.cpp +++ b/romsel_r4theme/arm9/source/perGameSettings.cpp @@ -40,6 +40,8 @@ extern const char *bootstrapinipath; extern bool isRegularDS; extern int consoleModel; +extern int flashcard; + extern int bstrap_dsiMode; extern bool useBootstrap; extern int theme; @@ -174,7 +176,7 @@ bool checkIfDSiMode (std::string filename) { bool showSetDonorRom(u32 arm7size, u32 SDKVersion) { if (requiresDonorRom) return false; - bool hasCycloDSi = (memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 18) == 0); + bool hasCycloDSi = flashcard == 8; if (((!isDSiMode() || hasCycloDSi) && SDKVersion > 0x2000000 && SDKVersion < 0x2008000 // Early SDK2 && (arm7size==0x25F70 @@ -295,11 +297,9 @@ void perGameSettings (std::string filename) { }*/ bool showCheats = ((isDSiMode() && useBootstrap) + // TODO: Enable /*|| (secondaryDevice && !useBootstrap - && ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0)))*/ + && flashcard != 0))*/ || !secondaryDevice); firstPerGameOpShown = 0; diff --git a/rungame/arm9/source/main.cpp b/rungame/arm9/source/main.cpp index 248ca7a9cd..b0613500e1 100644 --- a/rungame/arm9/source/main.cpp +++ b/rungame/arm9/source/main.cpp @@ -112,6 +112,7 @@ TWL_CODE void LoadSettings(void) { fcSaveOnSd = settingsini.GetInt("SRLOADER", "FC_SAVE_ON_SD", fcSaveOnSd); useBootstrap = settingsini.GetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); bootstrapFile = settingsini.GetInt("SRLOADER", "BOOTSTRAP_FILE", 0); + flashcard = settingsini.GetInt("SRLOADER", "FLASHCARD", 0); unlaunchBg = settingsini.GetString("SRLOADER", "UNLAUNCH_BG", unlaunchBg); charUnlaunchBg = unlaunchBg.c_str(); @@ -327,33 +328,38 @@ TWL_CODE int lastRunROM() { bool runNds_boostVram = perGameSettings_boostVram == -1 ? boostVram : perGameSettings_boostVram; std::string path; - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); - path = ReplaceAll(romPath[1], "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", path); - fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); - return runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); - path = ReplaceAll(romPath[1], "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", path); - fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); - return runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { - CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); - path = ReplaceAll(romPath[1], "fat:/", dstwofat); - fcrompathini.SetString("Dir Info", "fullName", path); - fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); - return runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if ((memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0)) { - CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); - path = ReplaceAll(romPath[1], "fat:/", slashchar); - fcrompathini.SetString("YSMENU", "AUTO_BOOT", path); - fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); - return runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + switch (flashcard) { + case 1: { + CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); + path = ReplaceAll(romPath[1], "fat:/", slashchar); + fcrompathini.SetString("YSMENU", "AUTO_BOOT", path); + fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); + return runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + } + case 6: // Blue card can run wood 1.62 so this should work? + case 2: // And clones that can run wood (no N5) + case 3: { + CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); + path = ReplaceAll(romPath[1], "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", path); + fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); + return runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + } + case 7: { + CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); + path = ReplaceAll(romPath[1], "fat:/", dstwofat); + fcrompathini.SetString("Dir Info", "fullName", path); + fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); + return runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + } + case 5: // ? + case 4: { + CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); + path = ReplaceAll(romPath[1], "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", path); + fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); + return runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + } } } case 2: { diff --git a/settings/arm9/source/common/dsimenusettings.cpp b/settings/arm9/source/common/dsimenusettings.cpp index 8ecf0f059a..003489a1a3 100644 --- a/settings/arm9/source/common/dsimenusettings.cpp +++ b/settings/arm9/source/common/dsimenusettings.cpp @@ -56,7 +56,7 @@ TWLSettings::TWLSettings() secondaryDevice = false; fcSaveOnSd = false; - flashcard = EDSTTClone; + flashcard = 0; slot1LaunchMethod = EDirect; diff --git a/settings/arm9/source/common/dsimenusettings.h b/settings/arm9/source/common/dsimenusettings.h index d0b85bdf37..0bc9f9a190 100644 --- a/settings/arm9/source/common/dsimenusettings.h +++ b/settings/arm9/source/common/dsimenusettings.h @@ -30,24 +30,28 @@ class TWLSettings }; /* - 0: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE - 1: R4DS (Original Non-SDHC version)/ M3 Simply - 2: R4iDSN/R4i Gold RTS/R4 Ultra - 3: Acekard 2(i)/Galaxy Eagle/M3DS Real - 4: Acekard RPG - 5: Ace 3DS+/Gateway Blue Card/R4iTT - 6: SuperCard DSTWO + 0: Unknown + 1: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE + 2: R4DS (Original Non-SDHC version)/ M3 Simply + 3: R4iDSN/R4i Gold RTS/R4 Ultra + 4: Acekard 2(i)/Galaxy Eagle/M3DS Real + 5: Acekard RPG + 6: Ace 3DS+/Gateway Blue Card/R4iTT + 7: SuperCard DSTWO + 8: CycloDS iEvolution */ enum TFlashCard { - EDSTTClone = 0, - ER4Original = 1, - ER4iGoldClone = 2, - EAcekard2i = 3, - EAcekardRPG = 4, - EGatewayBlue = 5, - ESupercardDSTWO = 6 + EUnknown = 0, + EDSTTClone = 1, + ER4Original = 2, + ER4iGoldClone = 3, + EAcekard2i = 4, + EAcekardRPG = 5, + EGatewayBlue = 6, + ESupercardDSTWO = 7, + ECycloDSi = 8 }; // Do not reorder these, just add to the end diff --git a/settings/arm9/source/common/flashcard.cpp b/settings/arm9/source/common/flashcard.cpp index 50e23d2700..b701f91c3f 100644 --- a/settings/arm9/source/common/flashcard.cpp +++ b/settings/arm9/source/common/flashcard.cpp @@ -91,6 +91,9 @@ TWL_CODE void twl_flashcardInit(void) { io_dldi_data = dldiLoadFromFile("nitro:/dldi/CycloIEvo.dldi"); fatMountSimple("fat", &io_dldi_data->ioInterface); } */ + else { + disableSlot1(); + } } } diff --git a/settings/arm9/source/settingsgui.h b/settings/arm9/source/settingsgui.h index d1ad5e7bf4..3ded0ce4c0 100644 --- a/settings/arm9/source/settingsgui.h +++ b/settings/arm9/source/settingsgui.h @@ -235,4 +235,4 @@ class SettingsGUI typedef singleton settingsGui_s; inline SettingsGUI &gui() { return settingsGui_s::instance(); } -#endif \ No newline at end of file +#endif diff --git a/title/arm9/source/common/dsimenusettings.cpp b/title/arm9/source/common/dsimenusettings.cpp index c444731773..f8cde861b9 100644 --- a/title/arm9/source/common/dsimenusettings.cpp +++ b/title/arm9/source/common/dsimenusettings.cpp @@ -12,65 +12,65 @@ bool removeLauncherPatches = true; TWLSettings::TWLSettings() { - romfolder = ""; - pagenum = 0; - cursorPosition = 0; - startMenu_cursorPosition = 0; - consoleModel = -1; - - guiLanguage = ELangDefault; - colorMode = 0; - blfLevel = 0; - dsiWareExploit = 0; - wifiLed = -1; - useGbarunner = false; - showMainMenu = false; - theme = 0; - subtheme = 0; + romfolder = ""; + pagenum = 0; + cursorPosition = 0; + startMenu_cursorPosition = 0; + consoleModel = -1; + + guiLanguage = ELangDefault; + colorMode = 0; + blfLevel = 0; + dsiWareExploit = 0; + wifiLed = -1; + useGbarunner = false; + showMainMenu = false; + theme = 0; + subtheme = 0; showMd = 3; - showDirectories = true; - showBoxArt = 1 + isDSiMode(); - animateDsiIcons = true; - sysRegion = -1; - launcherApp = -1; - secondaryAccess = false; - previousUsedDevice = false; - secondaryDevice = false; + showDirectories = true; + showBoxArt = 1 + isDSiMode(); + animateDsiIcons = true; + sysRegion = -1; + launcherApp = -1; + secondaryAccess = false; + previousUsedDevice = false; + secondaryDevice = false; fcSaveOnSd = false; - flashcard = EDSTTClone; + flashcard = 0; - slot1LaunchMethod = EDirect; + slot1LaunchMethod = EDirect; - useBootstrap = true; - bootstrapFile = EReleaseBootstrap; + useBootstrap = true; + bootstrapFile = EReleaseBootstrap; - gameLanguage = ELangDefault; - boostCpu = false; - boostVram = false; - bstrap_dsiMode = false; - slot1SCFGUnlock = false; + gameLanguage = ELangDefault; + boostCpu = false; + boostVram = false; + bstrap_dsiMode = false; + slot1SCFGUnlock = false; - show12hrClock = true; + show12hrClock = true; - ak_viewMode = EViewInternal; - ak_scrollSpeed = EScrollFast; - ak_theme = "zelda"; - ak_zoomIcons = true; + ak_viewMode = EViewInternal; + ak_scrollSpeed = EScrollFast; + ak_theme = "zelda"; + ak_zoomIcons = true; slot1Launched = false; - launchType[0] = ENoLaunch; - launchType[1] = ENoLaunch; - homebrewBootstrap = EReleaseBootstrap; - homebrewHasWide = false; + launchType[0] = ENoLaunch; + launchType[1] = ENoLaunch; + homebrewBootstrap = EReleaseBootstrap; + homebrewHasWide = false; - r4_theme = "unused"; - unlaunchBg = "default.gif"; + r4_theme = "unused"; + unlaunchBg = "default.gif"; dsiSplash = isDSiMode(); - showlogo = true; - autorun = false; + showlogo = true; + autorun = false; autostartSlot1 = false; wideScreen = false; @@ -78,144 +78,147 @@ TWLSettings::TWLSettings() void TWLSettings::loadSettings() { - CIniFile settingsini(settingsinipath); + CIniFile settingsini(settingsinipath); - // UI settings. - romfolder = settingsini.GetString("SRLOADER", "ROM_FOLDER", romfolder); + // UI settings. + romfolder = settingsini.GetString("SRLOADER", "ROM_FOLDER", romfolder); - pagenum = settingsini.GetInt("SRLOADER", "PAGE_NUMBER", pagenum); - cursorPosition = settingsini.GetInt("SRLOADER", "CURSOR_POSITION", cursorPosition); - startMenu_cursorPosition = settingsini.GetInt("SRLOADER", "STARTMENU_CURSOR_POSITION", startMenu_cursorPosition); - consoleModel = settingsini.GetInt("SRLOADER", "CONSOLE_MODEL", consoleModel); + pagenum = settingsini.GetInt("SRLOADER", "PAGE_NUMBER", pagenum); + cursorPosition = settingsini.GetInt("SRLOADER", "CURSOR_POSITION", cursorPosition); + startMenu_cursorPosition = settingsini.GetInt("SRLOADER", "STARTMENU_CURSOR_POSITION", startMenu_cursorPosition); + consoleModel = settingsini.GetInt("SRLOADER", "CONSOLE_MODEL", consoleModel); + + flashcard = settingsini.GetInt("SRLOADER", "FLASHCARD", flashcard); showMd = settingsini.GetInt("SRLOADER", "SHOW_MDGEN", showMd); - // Customizable UI settings. + // Customizable UI settings. colorMode = settingsini.GetInt("SRLOADER", "COLOR_MODE", colorMode); blfLevel = settingsini.GetInt("SRLOADER", "BLUE_LIGHT_FILTER_LEVEL", blfLevel); dsiWareExploit = settingsini.GetInt("SRLOADER", "DSIWARE_EXPLOIT", dsiWareExploit); wifiLed = settingsini.GetInt("SRLOADER", "WIFI_LED", wifiLed); - guiLanguage = settingsini.GetInt("SRLOADER", "LANGUAGE", guiLanguage); - useGbarunner = settingsini.GetInt("SRLOADER", "USE_GBARUNNER2", useGbarunner); - if (!sys().isRegularDS()) { - useGbarunner = true; - } + guiLanguage = settingsini.GetInt("SRLOADER", "LANGUAGE", guiLanguage); + useGbarunner = settingsini.GetInt("SRLOADER", "USE_GBARUNNER2", useGbarunner); + if (!sys().isRegularDS()) { + useGbarunner = true; + } - dsiSplash = settingsini.GetInt("SRLOADER", "DSI_SPLASH", dsiSplash); - showlogo = settingsini.GetInt("SRLOADER", "SHOWLOGO", showlogo); + dsiSplash = settingsini.GetInt("SRLOADER", "DSI_SPLASH", dsiSplash); + showlogo = settingsini.GetInt("SRLOADER", "SHOWLOGO", showlogo); secondaryAccess = settingsini.GetInt("SRLOADER", "SECONDARY_ACCESS", secondaryAccess); previousUsedDevice = settingsini.GetInt("SRLOADER", "PREVIOUS_USED_DEVICE", previousUsedDevice); - secondaryDevice = settingsini.GetInt("SRLOADER", "SECONDARY_DEVICE", secondaryDevice); + secondaryDevice = settingsini.GetInt("SRLOADER", "SECONDARY_DEVICE", secondaryDevice); fcSaveOnSd = settingsini.GetInt("SRLOADER", "FC_SAVE_ON_SD", fcSaveOnSd); - romPath[0] = settingsini.GetString("SRLOADER", "ROM_PATH", romPath[0]); - romPath[1] = settingsini.GetString("SRLOADER", "SECONDARY_ROM_PATH", romPath[1]); - showMainMenu = settingsini.GetInt("SRLOADER", "SHOW_MAIN_MENU", showMainMenu); - theme = settingsini.GetInt("SRLOADER", "THEME", theme); - subtheme = settingsini.GetInt("SRLOADER", "SUB_THEME", subtheme); - showDirectories = settingsini.GetInt("SRLOADER", "SHOW_DIRECTORIES", showDirectories); - showBoxArt = settingsini.GetInt("SRLOADER", "SHOW_BOX_ART", showBoxArt); - animateDsiIcons = settingsini.GetInt("SRLOADER", "ANIMATE_DSI_ICONS", animateDsiIcons); + romPath[0] = settingsini.GetString("SRLOADER", "ROM_PATH", romPath[0]); + romPath[1] = settingsini.GetString("SRLOADER", "SECONDARY_ROM_PATH", romPath[1]); + showMainMenu = settingsini.GetInt("SRLOADER", "SHOW_MAIN_MENU", showMainMenu); + theme = settingsini.GetInt("SRLOADER", "THEME", theme); + subtheme = settingsini.GetInt("SRLOADER", "SUB_THEME", subtheme); + showDirectories = settingsini.GetInt("SRLOADER", "SHOW_DIRECTORIES", showDirectories); + showBoxArt = settingsini.GetInt("SRLOADER", "SHOW_BOX_ART", showBoxArt); + animateDsiIcons = settingsini.GetInt("SRLOADER", "ANIMATE_DSI_ICONS", animateDsiIcons); if (consoleModel < 2) { sysRegion = settingsini.GetInt("SRLOADER", "SYS_REGION", sysRegion); launcherApp = settingsini.GetInt("SRLOADER", "LAUNCHER_APP", launcherApp); } - slot1LaunchMethod = settingsini.GetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); - bootstrapFile = settingsini.GetInt("SRLOADER", "BOOTSTRAP_FILE", bootstrapFile); - useBootstrap = settingsini.GetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); + slot1LaunchMethod = settingsini.GetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); + bootstrapFile = settingsini.GetInt("SRLOADER", "BOOTSTRAP_FILE", bootstrapFile); + useBootstrap = settingsini.GetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); - // Default nds-bootstrap settings - gameLanguage = settingsini.GetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - boostCpu = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_CPU", boostCpu); - boostVram = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_VRAM", boostVram); - bstrap_dsiMode = settingsini.GetInt("NDS-BOOTSTRAP", "DSI_MODE", bstrap_dsiMode); + // Default nds-bootstrap settings + gameLanguage = settingsini.GetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + boostCpu = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_CPU", boostCpu); + boostVram = settingsini.GetInt("NDS-BOOTSTRAP", "BOOST_VRAM", boostVram); + bstrap_dsiMode = settingsini.GetInt("NDS-BOOTSTRAP", "DSI_MODE", bstrap_dsiMode); - ak_viewMode = settingsini.GetInt("SRLOADER", "AK_VIEWMODE", ak_viewMode); - ak_scrollSpeed = settingsini.GetInt("SRLOADER", "AK_SCROLLSPEED", ak_scrollSpeed); - ak_theme = settingsini.GetString("SRLOADER", "AK_THEME", ak_theme); - ak_zoomIcons = settingsini.GetInt("SRLOADER", "AK_ZOOM_ICONS", ak_zoomIcons); + ak_viewMode = settingsini.GetInt("SRLOADER", "AK_VIEWMODE", ak_viewMode); + ak_scrollSpeed = settingsini.GetInt("SRLOADER", "AK_SCROLLSPEED", ak_scrollSpeed); + ak_theme = settingsini.GetString("SRLOADER", "AK_THEME", ak_theme); + ak_zoomIcons = settingsini.GetInt("SRLOADER", "AK_ZOOM_ICONS", ak_zoomIcons); - dsiWareSrlPath = settingsini.GetString("SRLOADER", "DSIWARE_SRL", dsiWareSrlPath); - dsiWarePubPath = settingsini.GetString("SRLOADER", "DSIWARE_PUB", dsiWarePubPath); - dsiWarePrvPath = settingsini.GetString("SRLOADER", "DSIWARE_PRV", dsiWarePrvPath); + dsiWareSrlPath = settingsini.GetString("SRLOADER", "DSIWARE_SRL", dsiWareSrlPath); + dsiWarePubPath = settingsini.GetString("SRLOADER", "DSIWARE_PUB", dsiWarePubPath); + dsiWarePrvPath = settingsini.GetString("SRLOADER", "DSIWARE_PRV", dsiWarePrvPath); slot1Launched = settingsini.GetInt("SRLOADER", "SLOT1_LAUNCHED", slot1Launched); - launchType[0] = settingsini.GetInt("SRLOADER", "LAUNCH_TYPE", launchType[0]); - launchType[1] = settingsini.GetInt("SRLOADER", "SECONDARY_LAUNCH_TYPE", launchType[1]); - homebrewArg[0] = settingsini.GetString("SRLOADER", "HOMEBREW_ARG", homebrewArg[0]); - homebrewArg[1] = settingsini.GetString("SRLOADER", "SECONDARY_HOMEBREW_ARG", homebrewArg[0]); - homebrewBootstrap = settingsini.GetInt("SRLOADER", "HOMEBREW_BOOTSTRAP", homebrewBootstrap); - homebrewHasWide = settingsini.GetInt("SRLOADER", "HOMEBREW_HAS_WIDE", homebrewHasWide); - - unlaunchBg = settingsini.GetString("SRLOADER", "UNLAUNCH_BG", unlaunchBg); + launchType[0] = settingsini.GetInt("SRLOADER", "LAUNCH_TYPE", launchType[0]); + launchType[1] = settingsini.GetInt("SRLOADER", "SECONDARY_LAUNCH_TYPE", launchType[1]); + homebrewArg[0] = settingsini.GetString("SRLOADER", "HOMEBREW_ARG", homebrewArg[0]); + homebrewArg[1] = settingsini.GetString("SRLOADER", "SECONDARY_HOMEBREW_ARG", homebrewArg[0]); + homebrewBootstrap = settingsini.GetInt("SRLOADER", "HOMEBREW_BOOTSTRAP", homebrewBootstrap); + homebrewHasWide = settingsini.GetInt("SRLOADER", "HOMEBREW_HAS_WIDE", homebrewHasWide); + + unlaunchBg = settingsini.GetString("SRLOADER", "UNLAUNCH_BG", unlaunchBg); charUnlaunchBg = unlaunchBg.c_str(); removeLauncherPatches = settingsini.GetInt("SRLOADER", "UNLAUNCH_PATCH_REMOVE", removeLauncherPatches); - show12hrClock = settingsini.GetInt("SRLOADER", "SHOW_12H_CLOCK", show12hrClock); + show12hrClock = settingsini.GetInt("SRLOADER", "SHOW_12H_CLOCK", show12hrClock); - autorun = settingsini.GetInt("SRLOADER", "AUTORUNGAME", autorun); - autostartSlot1 = settingsini.GetInt("SRLOADER", "AUTORUNSLOT1", autostartSlot1); + autorun = settingsini.GetInt("SRLOADER", "AUTORUNGAME", autorun); + autostartSlot1 = settingsini.GetInt("SRLOADER", "AUTORUNSLOT1", autostartSlot1); - wideScreen = settingsini.GetInt("SRLOADER", "WIDESCREEN", wideScreen); + wideScreen = settingsini.GetInt("SRLOADER", "WIDESCREEN", wideScreen); } void TWLSettings::saveSettings() { - CIniFile settingsini(settingsinipath); + CIniFile settingsini(settingsinipath); - settingsini.SetString("SRLOADER", "ROM_FOLDER", romfolder); + settingsini.SetString("SRLOADER", "ROM_FOLDER", romfolder); - settingsini.SetInt("SRLOADER", "PAGE_NUMBER", pagenum); - settingsini.SetInt("SRLOADER", "CURSOR_POSITION", cursorPosition); - settingsini.SetInt("SRLOADER", "STARTMENU_CURSOR_POSITION", startMenu_cursorPosition); - settingsini.SetInt("SRLOADER", "CONSOLE_MODEL", consoleModel); - settingsini.SetInt("SRLOADER", "AUTORUNGAME", autorun); + settingsini.SetInt("SRLOADER", "PAGE_NUMBER", pagenum); + settingsini.SetInt("SRLOADER", "CURSOR_POSITION", cursorPosition); + settingsini.SetInt("SRLOADER", "STARTMENU_CURSOR_POSITION", startMenu_cursorPosition); + settingsini.SetInt("SRLOADER", "CONSOLE_MODEL", consoleModel); + settingsini.SetInt("SRLOADER", "FLASHCARD", flashcard); + settingsini.SetInt("SRLOADER", "AUTORUNGAME", autorun); settingsini.SetInt("SRLOADER", "WIFI_LED", wifiLed); - // Customizable UI settings. - settingsini.SetInt("SRLOADER", "LANGUAGE", guiLanguage); - settingsini.SetInt("SRLOADER", "USE_GBARUNNER2", useGbarunner); - - settingsini.SetInt("SRLOADER", "SHOWLOGO", showlogo); - - settingsini.SetInt("SRLOADER", "SECONDARY_ACCESS", secondaryAccess); - settingsini.SetInt("SRLOADER", "SHOW_MAIN_MENU", showMainMenu); - settingsini.SetInt("SRLOADER", "THEME", theme); - settingsini.SetInt("SRLOADER", "SUB_THEME", subtheme); - settingsini.SetInt("SRLOADER", "SHOW_DIRECTORIES", showDirectories); - settingsini.SetInt("SRLOADER", "SHOW_BOX_ART", showBoxArt); - settingsini.SetInt("SRLOADER", "ANIMATE_DSI_ICONS", animateDsiIcons); + // Customizable UI settings. + settingsini.SetInt("SRLOADER", "LANGUAGE", guiLanguage); + settingsini.SetInt("SRLOADER", "USE_GBARUNNER2", useGbarunner); + + settingsini.SetInt("SRLOADER", "SHOWLOGO", showlogo); + + settingsini.SetInt("SRLOADER", "SECONDARY_ACCESS", secondaryAccess); + settingsini.SetInt("SRLOADER", "SHOW_MAIN_MENU", showMainMenu); + settingsini.SetInt("SRLOADER", "THEME", theme); + settingsini.SetInt("SRLOADER", "SUB_THEME", subtheme); + settingsini.SetInt("SRLOADER", "SHOW_DIRECTORIES", showDirectories); + settingsini.SetInt("SRLOADER", "SHOW_BOX_ART", showBoxArt); + settingsini.SetInt("SRLOADER", "ANIMATE_DSI_ICONS", animateDsiIcons); if (consoleModel < 2) { settingsini.SetInt("SRLOADER", "SYS_REGION", sysRegion); settingsini.SetInt("SRLOADER", "LAUNCHER_APP", launcherApp); } - settingsini.SetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); - settingsini.SetInt("SRLOADER", "BOOTSTRAP_FILE", bootstrapFile); - settingsini.SetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); + settingsini.SetInt("SRLOADER", "SLOT1_LAUNCHMETHOD", slot1LaunchMethod); + settingsini.SetInt("SRLOADER", "BOOTSTRAP_FILE", bootstrapFile); + settingsini.SetInt("SRLOADER", "USE_BOOTSTRAP", useBootstrap); - // Default nds-bootstrap settings - settingsini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); - settingsini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", boostCpu); - settingsini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", boostVram); - settingsini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", bstrap_dsiMode); + // Default nds-bootstrap settings + settingsini.SetInt("NDS-BOOTSTRAP", "LANGUAGE", gameLanguage); + settingsini.SetInt("NDS-BOOTSTRAP", "BOOST_CPU", boostCpu); + settingsini.SetInt("NDS-BOOTSTRAP", "BOOST_VRAM", boostVram); + settingsini.SetInt("NDS-BOOTSTRAP", "DSI_MODE", bstrap_dsiMode); - settingsini.SetInt("SRLOADER", "AK_VIEWMODE", ak_viewMode); - settingsini.SetInt("SRLOADER", "AK_SCROLLSPEED", ak_scrollSpeed); - settingsini.SetString("SRLOADER", "AK_THEME", ak_theme); - settingsini.SetInt("SRLOADER", "AK_ZOOM_ICONS", ak_zoomIcons); + settingsini.SetInt("SRLOADER", "AK_VIEWMODE", ak_viewMode); + settingsini.SetInt("SRLOADER", "AK_SCROLLSPEED", ak_scrollSpeed); + settingsini.SetString("SRLOADER", "AK_THEME", ak_theme); + settingsini.SetInt("SRLOADER", "AK_ZOOM_ICONS", ak_zoomIcons); - settingsini.SetInt("SRLOADER", "SHOW_12H_CLOCK", show12hrClock); + settingsini.SetInt("SRLOADER", "SHOW_12H_CLOCK", show12hrClock); - settingsini.SaveIniFile(settingsinipath); + settingsini.SaveIniFile(settingsinipath); } TWLSettings::TLanguage TWLSettings::getGuiLanguage() { - if (guiLanguage == ELangDefault) - { + if (guiLanguage == ELangDefault) + { extern bool useTwlCfg; - return (TLanguage)(useTwlCfg ? *(u8*)0x02000406 : PersonalData->language); - } - return (TLanguage)guiLanguage; -} \ No newline at end of file + return (TLanguage)(useTwlCfg ? *(u8*)0x02000406 : PersonalData->language); + } + return (TLanguage)guiLanguage; +} diff --git a/title/arm9/source/common/dsimenusettings.h b/title/arm9/source/common/dsimenusettings.h index dfd9495714..8923a2dd0f 100644 --- a/title/arm9/source/common/dsimenusettings.h +++ b/title/arm9/source/common/dsimenusettings.h @@ -29,24 +29,29 @@ class TWLSettings EViewInternal = 2 }; - /*0: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE - 1: R4DS (Original Non-SDHC version)/ M3 Simply - 2: R4iDSN/R4i Gold RTS/R4 Ultra - 3: Acekard 2(i)/Galaxy Eagle/M3DS Real - 4: Acekard RPG - 5: Ace 3DS+/Gateway Blue Card/R4iTT - 6: SuperCard DSTWO + /* + 0: Unknown + 1: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE + 2: R4DS (Original Non-SDHC version)/ M3 Simply + 3: R4iDSN/R4i Gold RTS/R4 Ultra + 4: Acekard 2(i)/Galaxy Eagle/M3DS Real + 5: Acekard RPG + 6: Ace 3DS+/Gateway Blue Card/R4iTT + 7: SuperCard DSTWO + 8: CycloDS iEvolution */ enum TFlashCard { - EDSTTClone = 0, - ER4Original = 1, - ER4iGoldClone = 2, - EAcekard2i = 3, - EAcekardRPG = 4, - EGatewayBlue = 5, - ESupercardDSTWO = 6 + EUnknown = 0, + EDSTTClone = 1, + ER4Original = 2, + ER4iGoldClone = 3, + EAcekard2i = 4, + EAcekardRPG = 5, + EGatewayBlue = 6, + ESupercardDSTWO = 7, + ECycloDSi = 8 }; // Do not reorder these, just add to the end diff --git a/title/arm9/source/common/flashcard.cpp b/title/arm9/source/common/flashcard.cpp index 50e23d2700..41f8385468 100644 --- a/title/arm9/source/common/flashcard.cpp +++ b/title/arm9/source/common/flashcard.cpp @@ -7,8 +7,11 @@ #include "common/bootstrappaths.h" #include "common/inifile.h" #include "common/systemdetails.h" +#include "common/dsimenusettings.h" #include "read_card.h" +using FC = TWLSettings::TFlashCard; + bool sdFound(void) { return (access("sd:/", F_OK) == 0); } @@ -83,6 +86,7 @@ TWL_CODE void twl_flashcardInit(void) { fatMountSimple("fat", &io_dldi_data->ioInterface); } else if (!memcmp(ndsCardHeader.gameCode, "ACEK", 4) || !memcmp(ndsCardHeader.gameCode, "YCEP", 4) || !memcmp(ndsCardHeader.gameCode, "AHZH", 4) || !memcmp(ndsCardHeader.gameCode, "CHPJ", 4) || !memcmp(ndsCardHeader.gameCode, "ADLP", 4)) { io_dldi_data = dldiLoadFromFile("nitro:/dldi/ak2_sd.dldi"); + //io_dldi_data = dldiLoadFromFile("nitro:/dldi/r4idsn_sd.dldi"); fatMountSimple("fat", &io_dldi_data->ioInterface); } /*else if (!memcmp(ndsCardHeader.gameCode, "ALXX", 4)) { io_dldi_data = dldiLoadFromFile("nitro:/dldi/dstwo.dldi"); @@ -91,6 +95,9 @@ TWL_CODE void twl_flashcardInit(void) { io_dldi_data = dldiLoadFromFile("nitro:/dldi/CycloIEvo.dldi"); fatMountSimple("fat", &io_dldi_data->ioInterface); } */ + else { + disableSlot1(); + } } } @@ -99,3 +106,24 @@ void flashcardInit(void) { twl_flashcardInit(); } } + +int detectFlashcard() { + if (!memcmp(io_dldi_data->friendlyName, "TTCARD", 6) + || !memcmp(io_dldi_data->friendlyName, "DSTT", 4) + || !memcmp(io_dldi_data->friendlyName, "DEMON", 5)) + return FC::EDSTTClone; + if (!memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 0x1A) + || !memcmp(io_dldi_data->friendlyName, "R4TF", 4)) + return FC::ER4Original; + if (!memcmp(io_dldi_data->friendlyName, "R4iDSN", 6)) + return FC::ER4iGoldClone; + if (!memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB)) + return FC::EAcekard2i; + if (!memcmp(io_dldi_data->friendlyName, "Acekard RPG", 0xB)) + return FC::EAcekardRPG; + if (!memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD)) + return FC::ESupercardDSTWO; + if (!memcmp(io_dldi_data->friendlyName, "CycloDS iEvolution", 0x12)) + return FC::ECycloDSi; + return FC::EUnknown; +} diff --git a/title/arm9/source/common/flashcard.h b/title/arm9/source/common/flashcard.h index 4b364b710e..30be6c9946 100644 --- a/title/arm9/source/common/flashcard.h +++ b/title/arm9/source/common/flashcard.h @@ -8,5 +8,6 @@ bool sdFound(void); bool flashcardFound(void); bool bothSDandFlashcard(void); void flashcardInit(void); +int detectFlashcard(void); #endif //DSIMENUPP_FLASHCARD_H diff --git a/title/arm9/source/main.cpp b/title/arm9/source/main.cpp index c38797f6f0..65f79aa311 100644 --- a/title/arm9/source/main.cpp +++ b/title/arm9/source/main.cpp @@ -34,16 +34,7 @@ extern bool controlBottomBright; //bool soundfreqsettingChanged = false; bool hiyaAutobootFound = false; -//static int flashcard; -/* Flashcard value - 0: DSTT/R4i Gold/R4i-SDHC/R4 SDHC Dual-Core/R4 SDHC Upgrade/SC DSONE - 1: R4DS (Original Non-SDHC version)/ M3 Simply - 2: R4iDSN/R4i Gold RTS/R4 Ultra - 3: Acekard 2(i)/Galaxy Eagle/M3DS Real - 4: Acekard RPG - 5: Ace 3DS+/Gateway Blue Card/R4iTT - 6: SuperCard DSTWO -*/ +int flashcard = 0; const char *hiyacfwinipath = "sd:/hiya/settings.ini"; const char *settingsinipath = DSIMENUPP_INI; @@ -93,8 +84,8 @@ void stop(void) char filePath[PATH_MAX]; -/*//--------------------------------------------------------------------------------- -void doPause(void) +//--------------------------------------------------------------------------------- +/*void doPause(void) { //--------------------------------------------------------------------------------- printf("Press start...\n"); @@ -428,34 +419,47 @@ void lastRunROM() rename(savepath.c_str(), savepathFc.c_str()); std::string fcPath; - if ((memcmp(io_dldi_data->friendlyName, "R4(DS) - Revolution for DS", 26) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4TF", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "R4iDSN", 6) == 0)) { - CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); - fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); - err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "Acekard AK2", 0xB) == 0) { - CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); - fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", woodfat); - fcrompathini.SetString("Save Info", "lastLoaded", fcPath); - fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); - err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if (memcmp(io_dldi_data->friendlyName, "DSTWO(Slot-1)", 0xD) == 0) { - CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); - fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", dstwofat); - fcrompathini.SetString("Dir Info", "fullName", fcPath); - fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); - err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); - } else if ((memcmp(io_dldi_data->friendlyName, "TTCARD", 6) == 0) - || (memcmp(io_dldi_data->friendlyName, "DSTT", 4) == 0) - || (memcmp(io_dldi_data->friendlyName, "DEMON", 5) == 0)) { - CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); - fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", slashchar); - fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); - fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); - err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + + switch (ms().flashcard) { + case 1: { + CIniFile fcrompathini("fat:/TTMenu/YSMenu.ini"); + fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", slashchar); + fcrompathini.SetString("YSMENU", "AUTO_BOOT", fcPath); + fcrompathini.SaveIniFile("fat:/TTMenu/YSMenu.ini"); + err = runNdsFile("fat:/YSMenu.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 6: // Blue card can run wood 1.62 so this should work? + case 2: // And clones that can run wood (no N5) + case 3: { + CIniFile fcrompathini("fat:/_wfwd/lastsave.ini"); + fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_wfwd/lastsave.ini"); + err = runNdsFile("fat:/Wfwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 7: { + CIniFile fcrompathini("fat:/_dstwo/autoboot.ini"); + fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", dstwofat); + fcrompathini.SetString("Dir Info", "fullName", fcPath); + fcrompathini.SaveIniFile("fat:/_dstwo/autoboot.ini"); + err = runNdsFile("fat:/_dstwo/autoboot.nds", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + case 5: // ? + case 4: { + CIniFile fcrompathini("fat:/_afwd/lastsave.ini"); + fcPath = replaceAll(ms().romPath[ms().secondaryDevice], "fat:/", woodfat); + fcrompathini.SetString("Save Info", "lastLoaded", fcPath); + fcrompathini.SaveIniFile("fat:/_afwd/lastsave.ini"); + err = runNdsFile("fat:/Afwd.dat", 0, NULL, true, true, true, runNds_boostCpu, runNds_boostVram); + break; + } + default: { + err = 1337; + break; + } } } } @@ -708,6 +712,7 @@ int main(int argc, char **argv) ms().loadSettings(); bs().loadSettings(); + if (isDSiMode() && ms().consoleModel < 2) { if (ms().wifiLed == -1) { if (*(u8*)(0x023FFD01) == 0x13) { @@ -845,6 +850,17 @@ int main(int argc, char **argv) scanKeys(); + // If in DSi mode with SCFG access attempt to cut slot1 power to save battery + if (isDSiMode() && !sys().arm7SCFGLocked() && !ms().autostartSlot1) { + disableSlot1(); + } else { + const int flashcard = detectFlashcard(); + ms().flashcard = flashcard; + ms().flashcard = flashcard; + ms().saveSettings(); + ms().saveSettings(); + } + if (softResetParamsFound || (ms().autorun && !(keysHeld() & KEY_B)) || (!ms().autorun && (keysHeld() & KEY_B))) @@ -853,10 +869,6 @@ int main(int argc, char **argv) lastRunROM(); } - // If in DSi mode with SCFG access attempt to cut slot1 power to save battery - if (isDSiMode() && !sys().arm7SCFGLocked() && !ms().autostartSlot1) { - disableSlot1(); - } if (!softResetParamsFound && ms().autostartSlot1 && isDSiMode() && REG_SCFG_MC != 0x11 && !flashcardFound() && !(keysHeld() & KEY_SELECT)) { if (ms().slot1LaunchMethod==0 || sys().arm7SCFGLocked()) {