mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-18 08:55:46 -04:00
Add nds-bootstrap interface
- Rework savemngr to use melonDS ROM list for save type - Use nds-bootstrap in place of akloader for retail game launching
This commit is contained in:
parent
1a88151eee
commit
1a76345468
@ -16,7 +16,7 @@ include $(DEVKITARM)/ds_rules
|
|||||||
# all directories are relative to this makefile
|
# all directories are relative to this makefile
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
BUILD := build
|
BUILD := build
|
||||||
SOURCES := source source/ui source/font source/launcher
|
SOURCES := source source/ui source/font source/launcher source/saves
|
||||||
INCLUDES := include ../share $(SOURCES)
|
INCLUDES := include ../share $(SOURCES)
|
||||||
DATA := data
|
DATA := data
|
||||||
GRAPHICS :=
|
GRAPHICS :=
|
||||||
|
110
arm9/source/launcher/NdsBootstrapLauncher.cpp
Normal file
110
arm9/source/launcher/NdsBootstrapLauncher.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2024 lifehackerhansol
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <nds/ndstypes.h>
|
||||||
|
|
||||||
|
#include "../cheatwnd.h"
|
||||||
|
#include "../dsrom.h"
|
||||||
|
#include "../flags.h"
|
||||||
|
#include "../inifile.h"
|
||||||
|
#include "ILauncher.h"
|
||||||
|
#include "NdsBootstrapLauncher.h"
|
||||||
|
#include "nds_loader_arm9.h"
|
||||||
|
|
||||||
|
bool NdsBootstrapLauncher::prepareCheats() {
|
||||||
|
u32 gameCode, crc32;
|
||||||
|
|
||||||
|
if (cCheatWnd::romData(mRomPath, gameCode, crc32)) {
|
||||||
|
FILE* cheatDb = fopen("/__rpg/cheats/usrcheat.dat", "rb");
|
||||||
|
if (!cheatDb) goto cheat_failed;
|
||||||
|
long cheatOffset;
|
||||||
|
size_t cheatSize;
|
||||||
|
if (cCheatWnd::searchCheatData(cheatDb, gameCode, crc32, cheatOffset, cheatSize)) {
|
||||||
|
cCheatWnd chtwnd((256) / 2, (192) / 2, 100, 100, NULL, mRomPath);
|
||||||
|
|
||||||
|
chtwnd.parse(mRomPath);
|
||||||
|
chtwnd.writeCheatsToFile("/_nds/nds-bootstrap/cheatData.bin");
|
||||||
|
FILE* cheatData = fopen("/_nds/nds-bootstrap/cheatData.bin", "rb");
|
||||||
|
if (cheatData) {
|
||||||
|
u32 check[2];
|
||||||
|
fread(check, 1, 8, cheatData);
|
||||||
|
fclose(cheatData);
|
||||||
|
// TODO: Delete file, if above 0x8000 bytes
|
||||||
|
if (check[1] == 0xCF000000) goto cheat_failed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fclose(cheatDb);
|
||||||
|
goto cheat_failed;
|
||||||
|
}
|
||||||
|
fclose(cheatDb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
cheat_failed:
|
||||||
|
// Remove cheat bin if exists
|
||||||
|
if (access("/_nds/nds-bootstrap/cheatData.bin", F_OK) == 0) {
|
||||||
|
remove("/_nds/nds-bootstrap/cheatData.bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NdsBootstrapLauncher::prepareIni() {
|
||||||
|
CIniFile ini;
|
||||||
|
ini.SetString("NDS-BOOTSTRAP", "NDS_PATH", mRomPath);
|
||||||
|
ini.SetString("NDS-BOOTSTRAP", "SAV_PATH", mSavePath);
|
||||||
|
|
||||||
|
ini.SaveIniFile("/_nds/nds-bootstrap.ini");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NdsBootstrapLauncher::launchRom(std::string romPath, std::string savePath, u32 flags,
|
||||||
|
u32 cheatOffset, u32 cheatSize) {
|
||||||
|
std::string ndsBootstrapPath = "/_nds/nds-bootstrap-release.nds";
|
||||||
|
std::vector<const char*> argv;
|
||||||
|
|
||||||
|
mRomPath = romPath;
|
||||||
|
mSavePath = savePath;
|
||||||
|
mFlags = flags;
|
||||||
|
|
||||||
|
// mRomPath *should* have the drive name set
|
||||||
|
// If it doesn't for some reason, default to `fat:/`, because most people are probably using
|
||||||
|
// this on flashcart
|
||||||
|
if (mRomPath.find("sd:/", 0) == std::string::npos)
|
||||||
|
ndsBootstrapPath = "fat:" + ndsBootstrapPath;
|
||||||
|
else
|
||||||
|
ndsBootstrapPath = "sd:" + ndsBootstrapPath;
|
||||||
|
|
||||||
|
// Create the nds-bootstrap directory if it doesn't exist
|
||||||
|
if (access("/_nds/nds-bootstrap/", F_OK) != 0) {
|
||||||
|
mkdir("/_nds/nds-bootstrap/", 0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup argv to launch nds-bootstrap
|
||||||
|
argv.push_back(ndsBootstrapPath.c_str());
|
||||||
|
|
||||||
|
// Prepare cheat codes if enabled
|
||||||
|
if (flags & PATCH_CHEATS) {
|
||||||
|
if (!prepareCheats()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup nds-bootstrap INI parameters
|
||||||
|
if (!prepareIni()) return false;
|
||||||
|
|
||||||
|
// Launch
|
||||||
|
eRunNdsRetCode rc = runNdsFile(argv[0], argv.size(), &argv[0]);
|
||||||
|
if (rc == RUN_NDS_OK) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
25
arm9/source/launcher/NdsBootstrapLauncher.h
Normal file
25
arm9/source/launcher/NdsBootstrapLauncher.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2024 lifehackerhansol
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nds/ndstypes.h>
|
||||||
|
|
||||||
|
#include "../dsrom.h"
|
||||||
|
#include "ILauncher.h"
|
||||||
|
|
||||||
|
class NdsBootstrapLauncher : public ILauncher {
|
||||||
|
public:
|
||||||
|
bool launchRom(std::string romPath, std::string savePath, u32 flags, u32 cheatOffset,
|
||||||
|
u32 cheatSize) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool prepareCheats(void);
|
||||||
|
bool prepareIni(void);
|
||||||
|
std::string mRomPath;
|
||||||
|
std::string mSavePath;
|
||||||
|
u32 mFlags;
|
||||||
|
};
|
@ -36,6 +36,7 @@
|
|||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
|
|
||||||
#include "launcher/HomebrewLauncher.h"
|
#include "launcher/HomebrewLauncher.h"
|
||||||
|
#include "launcher/NdsBootstrapLauncher.h"
|
||||||
|
|
||||||
using namespace akui;
|
using namespace akui;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "launcher/HomebrewLauncher.h"
|
#include "launcher/HomebrewLauncher.h"
|
||||||
#include "launcher/ILauncher.h"
|
#include "launcher/ILauncher.h"
|
||||||
|
#include "launcher/NdsBootstrapLauncher.h"
|
||||||
|
|
||||||
static SAVE_TYPE PrefillGame(u32 aGameCode) {
|
static SAVE_TYPE PrefillGame(u32 aGameCode) {
|
||||||
if (0x45444759 == aGameCode) // YGDE: 2209 - Diary Girl (USA)
|
if (0x45444759 == aGameCode) // YGDE: 2209 - Diary Girl (USA)
|
||||||
@ -135,7 +136,6 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool
|
|||||||
size_t cheatSize = 0;
|
size_t cheatSize = 0;
|
||||||
std::string saveName;
|
std::string saveName;
|
||||||
ILauncher* launcher = nullptr;
|
ILauncher* launcher = nullptr;
|
||||||
#if 0
|
|
||||||
if (!aRomInfo.isHomebrew()) {
|
if (!aRomInfo.isHomebrew()) {
|
||||||
u32 gameCode;
|
u32 gameCode;
|
||||||
memcpy(&gameCode, aRomInfo.saveInfo().gameCode, sizeof(gameCode)); // because alignment
|
memcpy(&gameCode, aRomInfo.saveInfo().gameCode, sizeof(gameCode)); // because alignment
|
||||||
@ -167,6 +167,8 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveName = cSaveManager::generateSaveName(aFullPath, aRomInfo.saveInfo().getSlot());
|
saveName = cSaveManager::generateSaveName(aFullPath, aRomInfo.saveInfo().getSlot());
|
||||||
|
|
||||||
|
// restore save data only for offical programs
|
||||||
if (isBigSave) {
|
if (isBigSave) {
|
||||||
isBigSave = cSaveManager::initializeSaveFile(aFullPath, aRomInfo.saveInfo().getSlot(),
|
isBigSave = cSaveManager::initializeSaveFile(aFullPath, aRomInfo.saveInfo().getSlot(),
|
||||||
bigSaveSize);
|
bigSaveSize);
|
||||||
@ -174,7 +176,6 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool
|
|||||||
flags |= PATCH_SD_SAVE | (bigSaveMask << PATCH_SAVE_SHIFT);
|
flags |= PATCH_SD_SAVE | (bigSaveMask << PATCH_SAVE_SHIFT);
|
||||||
saveManager().saveLastInfo(aFullPath);
|
saveManager().saveLastInfo(aFullPath);
|
||||||
} else {
|
} else {
|
||||||
// restore save data only for offical programs
|
|
||||||
SAVE_TYPE st = (SAVE_TYPE)aRomInfo.saveInfo().saveType;
|
SAVE_TYPE st = (SAVE_TYPE)aRomInfo.saveInfo().saveType;
|
||||||
if (ST_UNKNOWN == st) st = ST_AUTO;
|
if (ST_UNKNOWN == st) st = ST_AUTO;
|
||||||
SAVE_TYPE st_new = PrefillGame(gameCode);
|
SAVE_TYPE st_new = PrefillGame(gameCode);
|
||||||
@ -232,12 +233,9 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool
|
|||||||
|
|
||||||
launcher = new NdsBootstrapLauncher();
|
launcher = new NdsBootstrapLauncher();
|
||||||
} else {
|
} else {
|
||||||
#endif
|
if (!aMenu) saveManager().saveLastInfo(aFullPath);
|
||||||
if (!aMenu) saveManager().saveLastInfo(aFullPath);
|
launcher = new HomebrewLauncher();
|
||||||
launcher = new HomebrewLauncher();
|
|
||||||
#if 0
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
launcher->launchRom(aFullPath, saveName, flags, cheatOffset, cheatSize);
|
launcher->launchRom(aFullPath, saveName, flags, cheatOffset, cheatSize);
|
||||||
return ELaunchRomOk;
|
return ELaunchRomOk;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "systemfilenames.h"
|
#include "systemfilenames.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
||||||
|
#include "saves/ROMList.h"
|
||||||
|
|
||||||
using namespace akui;
|
using namespace akui;
|
||||||
|
|
||||||
cSaveManager::cSaveManager() {}
|
cSaveManager::cSaveManager() {}
|
||||||
@ -221,6 +223,9 @@ SAVE_TYPE cSaveManager::getSaveTypeByFile(const std::string& romFilename) {
|
|||||||
return ST_UNKNOWN;
|
return ST_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAVE_TYPE MelonDSROMListToSaveType[] = {ST_NOSAVE, ST_4K, ST_64K, ST_512K, ST_1M, ST_2M,
|
||||||
|
ST_4M, ST_8M, ST_16M, ST_32M, ST_64M};
|
||||||
|
|
||||||
void cSaveManager::updateSaveInfoByInfo(SAVE_INFO_EX& gameInfo) {
|
void cSaveManager::updateSaveInfoByInfo(SAVE_INFO_EX& gameInfo) {
|
||||||
size_t saveCount = _customSaveList.size();
|
size_t saveCount = _customSaveList.size();
|
||||||
for (size_t i = 0; i < saveCount; ++i) {
|
for (size_t i = 0; i < saveCount; ++i) {
|
||||||
@ -231,13 +236,17 @@ void cSaveManager::updateSaveInfoByInfo(SAVE_INFO_EX& gameInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gameInfo.defaults();
|
gameInfo.defaults();
|
||||||
saveCount = _saveList.size();
|
u32 gameCode;
|
||||||
for (size_t ii = 0; ii < saveCount; ii++) {
|
memcpy(&gameCode, gameInfo.gameCode, sizeof(gameCode)); // because alignment
|
||||||
if (0 == memcmp(&gameInfo, &_saveList[ii], SAVE_INFO_EX_COMPARE_SIZE)) {
|
|
||||||
u8 saveType = _saveList[ii].saveType;
|
for (size_t i = 0; i < ROMListEntryCount; i++) {
|
||||||
if (saveType > ST_UNKNOWN && saveType <= ST_8M)
|
const ROMListEntry* entry = &ROMList[i];
|
||||||
gameInfo.saveType = _saveList[ii].saveType;
|
if (gameCode == entry->GameCode) {
|
||||||
return;
|
if (entry->SaveMemType == 0xFFFFFFFF)
|
||||||
|
gameInfo.saveType = ST_AUTO;
|
||||||
|
else
|
||||||
|
gameInfo.saveType = MelonDSROMListToSaveType[entry->SaveMemType];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
6805
arm9/source/saves/ROMList.cpp
Normal file
6805
arm9/source/saves/ROMList.cpp
Normal file
File diff suppressed because it is too large
Load Diff
41
arm9/source/saves/ROMList.h
Normal file
41
arm9/source/saves/ROMList.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS 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.
|
||||||
|
|
||||||
|
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
|
#ifndef ROMLIST_H
|
||||||
|
#define ROMLIST_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <nds/ndstypes.h>
|
||||||
|
|
||||||
|
struct ROMListEntry
|
||||||
|
{
|
||||||
|
u32 GameCode;
|
||||||
|
u32 ROMSize;
|
||||||
|
u32 SaveMemType;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern const ROMListEntry ROMList[];
|
||||||
|
|
||||||
|
/// The number of elements in \c ROMList.
|
||||||
|
extern const size_t ROMListEntryCount;
|
||||||
|
|
||||||
|
#endif // ROMLIST_H
|
@ -2,6 +2,8 @@ This program is originally based on the akmenu project by the Acekard team, who
|
|||||||
|
|
||||||
This program is further developed by yellow wood goblin, who released the source under the GPL-3.0-or-later license. See GPL3.txt for more info.
|
This program is further developed by yellow wood goblin, who released the source under the GPL-3.0-or-later license. See GPL3.txt for more info.
|
||||||
|
|
||||||
|
This provided source integrates ROM list code from the melonDS project, which is licensed under the GPL-3.0-or-later license. See GPL3.txt for more info.
|
||||||
|
|
||||||
This provided source integrates devkitPro's bootloader, which is licensed under the GPL-2.0-or-later license. See GPL2.txt for more info.
|
This provided source integrates devkitPro's bootloader, which is licensed under the GPL-2.0-or-later license. See GPL2.txt for more info.
|
||||||
|
|
||||||
This provided source is collectively licensed under the GPL-3.0-or-later license.
|
This provided source is collectively licensed under the GPL-3.0-or-later license.
|
||||||
|
Loading…
Reference in New Issue
Block a user