Skip to content

Commit 3df9135

Browse files
committed
Add banner.sav/.bnr support
1 parent 7b4e83c commit 3df9135

File tree

25 files changed

+535
-27
lines changed

25 files changed

+535
-27
lines changed

quickmenu/arm9/source/iconTitle.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "common/tonccpy.h"
3030
#include "common/twlmenusettings.h"
3131
#include "common/systemdetails.h"
32+
#include "common/stringtool.h"
3233
#include "graphics/graphics.h"
3334
#include "graphics/fontHandler.h"
3435
#include "common/lodepng.h"
@@ -681,9 +682,62 @@ void getGameInfo(int num, bool isDir, const char* name, bool fromArgv)
681682
memcpy(ndsBanner.palette, paletteCopy, sizeof(paletteCopy));
682683
return;
683684
}
685+
686+
if (ndsHeader.dsi_flags & BIT(2)) {
687+
{
688+
std::string filename = name;
689+
690+
extern int getSaveNo (std::string filename);
691+
getSaveNo(filename);
692+
693+
extern void RemoveTrailingSlashes(std::string &path);
694+
std::string romFolderNoSlash = ms().romfolder[ms().secondaryDevice];
695+
RemoveTrailingSlashes(romFolderNoSlash);
696+
697+
std::string typeToReplace = filename.substr(filename.rfind('.'));
698+
699+
std::string bnrPath = romFolderNoSlash + "/saves/" + filename;
700+
if (ms().saveLocation == TWLSettings::ETWLMFolder) {
701+
std::string twlmSavesFolder = sys().isRunFromSD() ? "sd:/_nds/TWiLightMenu/saves" : "fat:/_nds/TWiLightMenu/saves";
702+
bnrPath = twlmSavesFolder + "/" + filename;
703+
} else if (ms().saveLocation == TWLSettings::EGamesFolder) {
704+
bnrPath = romFolderNoSlash + "/" + filename;
705+
}
706+
extern std::string getBnrExtension(void);
707+
bnrPath = replaceAll(bnrPath, typeToReplace, getBnrExtension());
708+
709+
logPrint("Banner save path: %s\n", bnrPath.c_str());
710+
fp = fopen(bnrPath.c_str(), "rb");
711+
}
712+
713+
if (fp) {
714+
logPrint("Banner save found!\n");
715+
716+
u16 ver = 0;
717+
fread(&ver, sizeof(u16), 1, fp);
718+
if (ver == NDS_BANNER_VER_DSi) {
719+
logPrint("Banner save is valid.\n");
720+
721+
fseek(fp, 8, SEEK_SET);
722+
fread(ndsBanner.crc+3, sizeof(u16), 1, fp);
723+
724+
fseek(fp, 0x20, SEEK_SET);
725+
fread(ndsBanner.dsi_icon, 1, 0x1180, fp);
726+
727+
tonccpy(ndsBanner.icon, ndsBanner.dsi_icon, 512);
728+
tonccpy(ndsBanner.palette, ndsBanner.dsi_palette, 16*sizeof(u16));
729+
} else {
730+
logPrint("Banner save is invalid.\n");
731+
}
732+
fclose(fp);
733+
} else {
734+
logPrint("Banner save not found!\n");
735+
}
736+
}
737+
684738
// banner sequence
685739
if (ms().animateDsiIcons && ndsBanner.version == NDS_BANNER_VER_DSi) {
686-
u16 crc16 = swiCRC16(0xFFFF, ndsBanner.dsi_icon, 0x1180);
740+
const u16 crc16 = swiCRC16(0xFFFF, ndsBanner.dsi_icon, 0x1180);
687741
if (ndsBanner.crc[3] == crc16) { // Check if CRC16 is valid
688742
grabBannerSequence(num);
689743
bnriconisDSi[num] = true;

quickmenu/arm9/source/language.inl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ STRING(CREATING_PUBLIC_SAVE, "Creating public save file...")
1212
STRING(PUBLIC_SAVE_CREATED, "Public save file created!")
1313
STRING(CREATING_PRIVATE_SAVE, "Creating private save file...")
1414
STRING(PRIVATE_SAVE_CREATED, "Private save file created!")
15+
STRING(CREATING_BANNER_SAVE, "Creating banner save file...")
16+
STRING(BANNER_SAVE_CREATED, "Banner save file created!")
1517
STRING(CREATING_SAVE, "Creating save file...")
1618
STRING(SAVE_CREATED, "Save file created!")
1719
STRING(EXPANDING_SAVE, "Expanding save file...")

quickmenu/arm9/source/main.cpp

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,8 @@ int dsClassicMenu(void) {
14301430

14311431
if (ms().previousUsedDevice && bothSDandFlashcard() && ms().launchType[ms().previousUsedDevice] == 3
14321432
&& ((access(ms().dsiWarePubPath.c_str(), F_OK) == 0 && access("sd:/_nds/TWiLightMenu/tempDSiWare.pub", F_OK) == 0)
1433-
|| (access(ms().dsiWarePrvPath.c_str(), F_OK) == 0 && access("sd:/_nds/TWiLightMenu/tempDSiWare.prv", F_OK) == 0))) {
1433+
|| (access(ms().dsiWarePrvPath.c_str(), F_OK) == 0 && access("sd:/_nds/TWiLightMenu/tempDSiWare.prv", F_OK) == 0)
1434+
|| (access(ms().dsiWareBnrPath.c_str(), F_OK) == 0 && access("sd:/_nds/TWiLightMenu/tempDSiWare.bnr", F_OK) == 0))) {
14341435
controlTopBright = false;
14351436
whiteScreen = true;
14361437
fadeType = true; // Fade in from white
@@ -1445,6 +1446,10 @@ int dsClassicMenu(void) {
14451446
fcopy("sd:/_nds/TWiLightMenu/tempDSiWare.prv", ms().dsiWarePrvPath.c_str());
14461447
rename("sd:/_nds/TWiLightMenu/tempDSiWare.prv", "sd:/_nds/TWiLightMenu/tempDSiWare.prv.bak");
14471448
}
1449+
if (access(ms().dsiWareBnrPath.c_str(), F_OK) == 0) {
1450+
fcopy("sd:/_nds/TWiLightMenu/tempDSiWare.bnr", ms().dsiWareBnrPath.c_str());
1451+
rename("sd:/_nds/TWiLightMenu/tempDSiWare.bnr", "sd:/_nds/TWiLightMenu/tempDSiWare.bnr.bak");
1452+
}
14481453
fadeType = false; // Fade to white
14491454
for (int i = 0; i < 30; i++) swiWaitForVBlank();
14501455
clearText(false);
@@ -2218,6 +2223,9 @@ int dsClassicMenu(void) {
22182223
if (access("sd:/_nds/TWiLightMenu/tempDSiWare.prv.bak", F_OK) == 0) {
22192224
remove("sd:/_nds/TWiLightMenu/tempDSiWare.prv.bak");
22202225
}
2226+
if (access("sd:/_nds/TWiLightMenu/tempDSiWare.bnr.bak", F_OK) == 0) {
2227+
remove("sd:/_nds/TWiLightMenu/tempDSiWare.bnr.bak");
2228+
}
22212229
if (access("sd:/_nds/nds-bootstrap/patchOffsetCache/tempDSiWare.bin", F_OK) == 0) {
22222230
remove("sd:/_nds/nds-bootstrap/patchOffsetCache/tempDSiWare.bin");
22232231
}
@@ -2264,6 +2272,8 @@ int dsClassicMenu(void) {
22642272
if (isDSiWare[ms().secondaryDevice]) {
22652273
remove(sys().isRunFromSD() ? "sd:/_nds/nds-bootstrap/esrb.bin" : "fat:/_nds/nds-bootstrap/esrb.bin");
22662274

2275+
loadPerGameSettings(filename[ms().secondaryDevice]);
2276+
22672277
std::string typeToReplace = filename[ms().secondaryDevice].substr(filename[ms().secondaryDevice].rfind('.'));
22682278

22692279
char *name = argarray.at(0);
@@ -2286,6 +2296,7 @@ int dsClassicMenu(void) {
22862296
mkdir("saves", 0777);
22872297
}
22882298
ms().dsiWarePrvPath = ms().dsiWarePubPath;
2299+
ms().dsiWareBnrPath = ms().dsiWarePubPath;
22892300
const bool savFormat = (ms().secondaryDevice && (!isDSiMode() || !sys().scfgSdmmcEnabled() || bs().b4dsMode));
22902301
if (savFormat) {
22912302
ms().dsiWarePubPath = replaceAll(ms().dsiWarePubPath, typeToReplace, getSavExtension());
@@ -2294,6 +2305,7 @@ int dsClassicMenu(void) {
22942305
ms().dsiWarePubPath = replaceAll(ms().dsiWarePubPath, typeToReplace, getPubExtension());
22952306
ms().dsiWarePrvPath = replaceAll(ms().dsiWarePrvPath, typeToReplace, getPrvExtension());
22962307
}
2308+
ms().dsiWareBnrPath = replaceAll(ms().dsiWareBnrPath, typeToReplace, getBnrExtension());
22972309
ms().homebrewBootstrap = isHomebrew[ms().secondaryDevice];
22982310
ms().launchType[ms().secondaryDevice] = TWLSettings::EDSiWareLaunch;
22992311
ms().saveSettings();
@@ -2385,6 +2397,32 @@ int dsClassicMenu(void) {
23852397
}
23862398
}
23872399

2400+
if ((NDSHeader.dsi_flags & BIT(2)) && getFileSize(ms().dsiWareBnrPath.c_str()) == 0) {
2401+
while (!fadeType && !screenFadedOut()) {
2402+
swiWaitForVBlank();
2403+
}
2404+
s2RamAccessAlt(true);
2405+
whiteScreen = true;
2406+
fadeSpeed = true;
2407+
controlTopBright = false;
2408+
clearText();
2409+
printSmall(false, 0, 88, STR_CREATING_BANNER_SAVE, Alignment::center);
2410+
fadeType = true; // Fade in from white
2411+
updateText(false);
2412+
2413+
FILE *pFile = fopen(ms().dsiWareBnrPath.c_str(), "wb");
2414+
if (pFile) {
2415+
fseek(pFile, 0x4000 - 1, SEEK_SET);
2416+
fputc('\0', pFile);
2417+
fclose(pFile);
2418+
}
2419+
2420+
clearText();
2421+
printSmall(false, 0, 88, STR_BANNER_SAVE_CREATED, Alignment::center);
2422+
updateText(false);
2423+
for (int i = 0; i < 60; i++) swiWaitForVBlank();
2424+
}
2425+
23882426
fadeType = false; // Fade to white
23892427

23902428
if (ms().secondaryDevice && !bs().b4dsMode && (ms().dsiWareToSD || (!(perGameSettings_dsiwareBooter == -1 ? ms().dsiWareBooter : perGameSettings_dsiwareBooter) && ms().consoleModel == 0)) && sdFound()) {
@@ -2407,10 +2445,14 @@ int dsClassicMenu(void) {
24072445
if ((access(ms().dsiWarePrvPath.c_str(), F_OK) == 0) && (NDSHeader.prvSavSize > 0)) {
24082446
fcopy(ms().dsiWarePrvPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.prv");
24092447
}
2448+
if ((NDSHeader.dsi_flags & BIT(2)) && access(ms().dsiWareBnrPath.c_str(), F_OK) == 0) {
2449+
fcopy(ms().dsiWareBnrPath.c_str(), "sd:/_nds/TWiLightMenu/tempDSiWare.bnr");
2450+
}
24102451
fadeType = false; // Fade to white
24112452

24122453
if ((access(ms().dsiWarePubPath.c_str(), F_OK) == 0 && (NDSHeader.pubSavSize > 0))
2413-
|| (access(ms().dsiWarePrvPath.c_str(), F_OK) == 0 && (NDSHeader.prvSavSize > 0))) {
2454+
|| (access(ms().dsiWarePrvPath.c_str(), F_OK) == 0 && (NDSHeader.prvSavSize > 0))
2455+
|| ((NDSHeader.dsi_flags & BIT(2)) && access(ms().dsiWareBnrPath.c_str(), F_OK) == 0)) {
24142456
for (int i = 0; i < 25; i++) swiWaitForVBlank();
24152457
clearText();
24162458
printSmall(false, 0, 8, STR_RESTART_AFTER_SAVE, Alignment::center);
@@ -2463,19 +2505,20 @@ int dsClassicMenu(void) {
24632505

24642506
if (((perGameSettings_dsiwareBooter == -1 ? ms().dsiWareBooter : perGameSettings_dsiwareBooter) || (ms().secondaryDevice && bs().b4dsMode) || sys().arm7SCFGLocked() || ms().consoleModel > 0) && !ms().homebrewBootstrap) {
24652507
// Use nds-bootstrap
2466-
loadPerGameSettings(filename[ms().secondaryDevice]);
2467-
24682508
char sfnSrl[62];
24692509
char sfnPub[62];
24702510
char sfnPrv[62];
2511+
char sfnBnr[62];
24712512
if (ms().secondaryDevice && !bs().b4dsMode && ms().dsiWareToSD && sdFound()) {
24722513
fatGetAliasPath("sd:/", "sd:/_nds/TWiLightMenu/tempDSiWare.dsi", sfnSrl);
24732514
fatGetAliasPath("sd:/", "sd:/_nds/TWiLightMenu/tempDSiWare.pub", sfnPub);
24742515
fatGetAliasPath("sd:/", "sd:/_nds/TWiLightMenu/tempDSiWare.prv", sfnPrv);
2516+
fatGetAliasPath("sd:/", "sd:/_nds/TWiLightMenu/tempDSiWare.bnr", sfnBnr);
24752517
} else {
24762518
fatGetAliasPath(ms().secondaryDevice ? "fat:/" : "sd:/", ms().dsiWareSrlPath.c_str(), sfnSrl);
24772519
fatGetAliasPath(ms().secondaryDevice ? "fat:/" : "sd:/", ms().dsiWarePubPath.c_str(), sfnPub);
24782520
fatGetAliasPath(ms().secondaryDevice ? "fat:/" : "sd:/", ms().dsiWarePrvPath.c_str(), sfnPrv);
2521+
fatGetAliasPath(ms().secondaryDevice ? "fat:/" : "sd:/", ms().dsiWareBnrPath.c_str(), sfnBnr);
24792522
}
24802523

24812524
const char *bootstrapinipath = sdFound() ? BOOTSTRAP_INI : BOOTSTRAP_INI_FC;
@@ -2484,6 +2527,7 @@ int dsClassicMenu(void) {
24842527
bootstrapini.SetString("NDS-BOOTSTRAP", "APP_PATH", sfnSrl);
24852528
bootstrapini.SetString("NDS-BOOTSTRAP", "SAV_PATH", sfnPub);
24862529
bootstrapini.SetString("NDS-BOOTSTRAP", "PRV_PATH", sfnPrv);
2530+
bootstrapini.SetString("NDS-BOOTSTRAP", "BNR_PATH", sfnBnr);
24872531
bootstrapini.SetString("NDS-BOOTSTRAP", "MANUAL_PATH", getGameManual(filename[ms().secondaryDevice].c_str()));
24882532
bootstrapini.SetString("NDS-BOOTSTRAP", "QUIT_PATH", mainSrldrPath(sys().isRunFromSD() && (!ms().secondaryDevice || !bs().b4dsMode)));
24892533
bootstrapini.SetString("NDS-BOOTSTRAP", "GUI_LANGUAGE", ms().getGuiLanguageString());

quickmenu/arm9/source/perGameSettings.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ void loadPerGameSettings (std::string filename) {
7878
perGameSettings_remappedKeys[11] = pergameini.GetInt("GAMESETTINGS", "REMAPPED_KEY_Y", 11);
7979
}
8080

81+
int getSaveNo (std::string filename) {
82+
snprintf(pergamefilepath, sizeof(pergamefilepath), "%s/_nds/TWiLightMenu/gamesettings/%s.ini", (ms().secondaryDevice ? "fat:" : "sd:"), filename.c_str());
83+
CIniFile pergameini( pergamefilepath );
84+
perGameSettings_saveNo = pergameini.GetInt("GAMESETTINGS", "SAVE_NUMBER", 0);
85+
return perGameSettings_saveNo;
86+
}
87+
8188
std::string getSavExtension(void) {
8289
if (ms().saveLocation == TWLSettings::EGamesFolder || perGameSettings_saveNo == 0) {
8390
return ".sav";
@@ -102,6 +109,14 @@ std::string getPrvExtension(void) {
102109
}
103110
}
104111

112+
std::string getBnrExtension(void) {
113+
if (ms().saveLocation == TWLSettings::EGamesFolder || perGameSettings_saveNo == 0) {
114+
return ".bnr";
115+
} else {
116+
return ".bn" + std::to_string(perGameSettings_saveNo);
117+
}
118+
}
119+
105120
std::string getImgExtension(void) {
106121
if (perGameSettings_ramDiskNo == 0) {
107122
return ".img";

quickmenu/arm9/source/perGameSettings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ extern int perGameSettings_saveRelocation;
2525
extern int perGameSettings_remappedKeys[12];
2626

2727
void loadPerGameSettings(std::string filename);
28+
int getSaveNo (std::string filename);
2829
std::string getSavExtension(void);
2930
std::string getPubExtension(void);
3031
std::string getPrvExtension(void);
32+
std::string getBnrExtension(void);
3133
std::string getImgExtension(void);
3234

3335

quickmenu/nitrofiles/languages/en/language.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ CREATING_PUBLIC_SAVE = Creating public save file...
1212
PUBLIC_SAVE_CREATED = Public save file created!
1313
CREATING_PRIVATE_SAVE = Creating private save file...
1414
PRIVATE_SAVE_CREATED = Private save file created!
15+
CREATING_BANNER_SAVE = Creating banner save file...
16+
BANNER_SAVE_CREATED = Banner save file created!
1517
CREATING_SAVE = Creating save file...
1618
SAVE_CREATED = Save file created!
1719
EXPANDING_SAVE = Expanding save file...

romsel_aktheme/arm9/source/iconTitle.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@
2727
#include <ctype.h>
2828
#include <sys/stat.h>
2929
#include <gl2d.h>
30+
#include "common/twlmenusettings.h"
3031
#include "common/bootstrapsettings.h"
3132
#include "common/systemdetails.h"
33+
#include "common/stringtool.h"
3234
#include "common/tonccpy.h"
33-
#include "common/twlmenusettings.h"
3435
#include "fileBrowse.h"
3536
#include "graphics/fontHandler.h"
3637
#include "common/lodepng.h"
@@ -1370,6 +1371,58 @@ void getGameInfo(int num, int fileOffset, bool isDir, const char* name, bool fro
13701371
return;
13711372
}
13721373

1374+
if (ndsHeader.dsi_flags & BIT(2)) {
1375+
{
1376+
std::string filename = name;
1377+
1378+
extern int getSaveNo (std::string filename);
1379+
getSaveNo(filename);
1380+
1381+
extern void RemoveTrailingSlashes(std::string &path);
1382+
std::string romFolderNoSlash = ms().romfolder[ms().secondaryDevice];
1383+
RemoveTrailingSlashes(romFolderNoSlash);
1384+
1385+
std::string typeToReplace = filename.substr(filename.rfind('.'));
1386+
1387+
std::string bnrPath = romFolderNoSlash + "/saves/" + filename;
1388+
if (ms().saveLocation == TWLSettings::ETWLMFolder) {
1389+
std::string twlmSavesFolder = sys().isRunFromSD() ? "sd:/_nds/TWiLightMenu/saves" : "fat:/_nds/TWiLightMenu/saves";
1390+
bnrPath = twlmSavesFolder + "/" + filename;
1391+
} else if (ms().saveLocation == TWLSettings::EGamesFolder) {
1392+
bnrPath = romFolderNoSlash + "/" + filename;
1393+
}
1394+
extern std::string getBnrExtension(void);
1395+
bnrPath = replaceAll(bnrPath, typeToReplace, getBnrExtension());
1396+
1397+
logPrint("Banner save path: %s\n", bnrPath.c_str());
1398+
fp = fopen(bnrPath.c_str(), "rb");
1399+
}
1400+
1401+
if (fp) {
1402+
logPrint("Banner save found!\n");
1403+
1404+
u16 ver = 0;
1405+
fread(&ver, sizeof(u16), 1, fp);
1406+
if (ver == NDS_BANNER_VER_DSi) {
1407+
logPrint("Banner save is valid.\n");
1408+
1409+
fseek(fp, 8, SEEK_SET);
1410+
fread(ndsBanner.crc+3, sizeof(u16), 1, fp);
1411+
1412+
fseek(fp, 0x20, SEEK_SET);
1413+
fread(ndsBanner.dsi_icon, 1, 0x1180, fp);
1414+
1415+
tonccpy(ndsBanner.icon, ndsBanner.dsi_icon, 512);
1416+
tonccpy(ndsBanner.palette, ndsBanner.dsi_palette, 16*sizeof(u16));
1417+
} else {
1418+
logPrint("Banner save is invalid.\n");
1419+
}
1420+
fclose(fp);
1421+
} else {
1422+
logPrint("Banner save not found!\n");
1423+
}
1424+
}
1425+
13731426
// banner sequence
13741427
if (ms().animateDsiIcons && ndsBanner.version == NDS_BANNER_VER_DSi) {
13751428
u16 crc16 = swiCRC16(0xFFFF, ndsBanner.dsi_icon, 0x1180);

0 commit comments

Comments
 (0)