diff --git a/arm7/source/main.cpp b/arm7/source/main.cpp index ce924a3d..181d6fc6 100644 --- a/arm7/source/main.cpp +++ b/arm7/source/main.cpp @@ -43,10 +43,6 @@ static u32 getSystem(void) { return dsGen; } -static void prepairResetTT() { - memcpy(__NDSHeader->arm7destination, *(void* volatile*)0x02FFFE00, __NDSHeader->arm7binarySize); -} - typedef void (*pico_loader_7_func_t)(void); volatile bool reset_pico = false; @@ -63,7 +59,7 @@ static void resetDSPico() { ((pico_loader_7_func_t)header7->entryPoint)(); } -static void prepairReset() { +static void prepareReset() { // enable sound if (2 == getSystem()) writePowerManagement(PM_CONTROL_REG, @@ -148,10 +144,8 @@ static void menuValue32Handler(u32 value, void* data) { swiChangeSoundBias(0, 0x400); swiSwitchToGBAModeFixed(); } break; - case MENU_MSG_ARM7_REBOOT_TT: - prepairResetTT(); case MENU_MSG_ARM7_REBOOT: - prepairReset(); + prepareReset(); swiSoftReset(); break; case MENU_MSG_ARM7_REBOOT_PICOLOADER: diff --git a/arm7/source/picoLoader7.h b/arm7/source/picoLoader7.h index 375975f6..ee2f6e45 100644 --- a/arm7/source/picoLoader7.h +++ b/arm7/source/picoLoader7.h @@ -1,7 +1,7 @@ #pragma once /// @brief The Pico Loader API version supported by this header file. -#define PICO_LOADER_API_VERSION 1 +#define PICO_LOADER_API_VERSION 3 /// @brief Enum to specify the drive to boot from. typedef enum @@ -35,6 +35,54 @@ typedef struct char arguments[256]; } pload_params_t; +/// @brief Struct representing the API version 2 part of the header of picoLoader7.bin. +typedef struct +{ + /// @brief The path of the rom to return to when exiting an application. + /// When this path is not set, no bootstub will be patched into homebrew applications. + char launcherPath[256]; +} pload_header7_v2_t; + +/// @brief Struct representing a single Action Replay cheat opcode. +typedef struct +{ + /// @brief The first part of the opcode. + u32 a; + + /// @brief The second part of the opcode. + u32 b; +} pload_cheat_opcode_t; + +/// @brief Struct representing a single Action Replay cheat. +typedef struct +{ + /// @brief Length of \see opcodes in bytes. + u32 length; + + /// @brief The cheat opcodes. + pload_cheat_opcode_t opcodes[1]; +} pload_cheat_t; + +/// @brief Struct representing one or more cheats. Cheats are adjacent starting from the firstCheat field. +typedef struct +{ + /// @brief Length of this stucture (length field + numberOfCheats field + all cheats). + u32 length; + + /// @brief The number of cheats. + u32 numberOfCheats; + + /// @brief The first cheat. + pload_cheat_t firstCheat; +} pload_cheats_t; + +/// @brief Struct representing the API version 3 part of the header of picoLoader7.bin. +typedef struct +{ + /// @brief Pointer to the cheats, or \c nullptr when there are no cheats. + const pload_cheats_t* cheats; +} pload_header7_v3_t; + /// @brief Struct representing the header of picoLoader7.bin. typedef struct { @@ -52,4 +100,10 @@ typedef struct /// @brief The load params, see \see pload_params_t. pload_params_t loadParams; + + /// @brief The API version 2 part of the header. Only access this when \see apiVersion >= 2. + pload_header7_v2_t v2; + + /// @brief The API version 3 part of the header. Only access this when \see apiVersion >= 3. + pload_header7_v3_t v3; } pload_header7_t; diff --git a/arm9/source/cheat.cpp b/arm9/source/cheat.cpp new file mode 100644 index 00000000..3e7009ef --- /dev/null +++ b/arm9/source/cheat.cpp @@ -0,0 +1,190 @@ +/* + cheatwnd.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 + + SPDX-License-Identifier: GPL-3.0-or-later +*/ + +#include +#include +#include +#include + +#include + +#include "cheat.h" +#include "dbgtool.h" +#include "gamecode.h" +#include "systemfilenames.h" + +#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; +} + +bool cCheat::parse(const std::string& aFileName) { + bool res = false; + _fileName = aFileName; + u32 romcrc32, gamecode; + if (romData(_fileName, gamecode, romcrc32)) { + FILE* dat = fopen((SFN_CHEATS).c_str(), "rb"); + if (dat) { + res = parseInternal(dat, gamecode, romcrc32); + fclose(dat); + } + } + return res; +} + +bool cCheat::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 cCheat::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; + + sCheatDatIndex 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) { + memcpy(&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 cCheat::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 < cheatCount) { + u32 folderCount = 1; + char* folderName = NULL; + char* folderNote = NULL; + u32 flagItem = 0; + if ((*ccode >> 28) & 1) { + flagItem |= cCheatDatItem::EInFolder; + if ((*ccode >> 24) == 0x11) flagItem |= cCheatDatItem::EOne; + folderCount = *ccode & 0x00ffffff; + folderName = (char*)((u32)ccode + 4); + folderNote = (char*)((u32)folderName + strlen(folderName) + 1); + _data.push_back(cCheatDatItem(folderName, folderNote, cCheatDatItem::EFolder)); + cc++; + ccode = (u32*)(((u32)folderName + strlen(folderName) + 1 + strlen(folderNote) + 1 + 3) & + ~3); + } + + u32 selectValue = cCheatDatItem::ESelected; + for (size_t ii = 0; ii < folderCount; ++ii) { + char* cheatName = (char*)((u32)ccode + 4); + char* cheatNote = (char*)((u32)cheatName + strlen(cheatName) + 1); + u32* cheatData = (u32*)(((u32)cheatNote + strlen(cheatNote) + 1 + 3) & ~3); + u32 cheatDataLen = *cheatData++; + + if (cheatDataLen) { + _data.push_back(cCheatDatItem(cheatName, cheatNote, + flagItem | ((*ccode & 0xff000000) ? selectValue : 0), + dataPos + (((char*)ccode + 3) - buffer))); + if ((*ccode & 0xff000000) && (flagItem & cCheatDatItem::EOne)) selectValue = 0; + _data.back()._cheat.resize(cheatDataLen); + memcpy(_data.back()._cheat.data(), cheatData, cheatDataLen * 4); + } + cc++; + ccode = (u32*)((u32)ccode + (((*ccode & 0x00ffffff) + 1) * 4)); + } + } + free(buffer); + // generateList(); + return true; +} + +void cCheat::deselectFolder(size_t anIndex) { + std::vector::iterator itr = _data.begin() + anIndex; + while (--itr >= _data.begin()) { + if ((*itr)._flags & cCheatDatItem::EFolder) { + ++itr; + break; + } + } + while (((*itr)._flags & cCheatDatItem::EInFolder) && itr != _data.end()) { + (*itr)._flags &= ~cCheatDatItem::ESelected; + ++itr; + } +} + +std::vector cCheat::getEnabledCheats() { + std::vector cheats; + for (uint i = 0; i < _data.size(); i++) { + if (_data[i]._flags & cCheatDatItem::ESelected) { + cheats.push_back(_data[i]); + } + } + return cheats; +} + +void cCheat::writeCheatsToFile(const char* path) { + FILE* file = fopen(path, "wb"); + if (file) { + std::vector cheats(getEnabledCheats()); + for (uint i = 0; i < cheats.size(); i++) { + fwrite(cheats[i]._cheat.data(), 4, cheats[i]._cheat.size(), file); + } + fwrite("\0\0\0\xCF", 4, 1, file); + fclose(file); + } +} diff --git a/arm9/source/cheat.h b/arm9/source/cheat.h new file mode 100644 index 00000000..aea07d5b --- /dev/null +++ b/arm9/source/cheat.h @@ -0,0 +1,48 @@ +/* + cheatwnd.h + Copyright (C) 2009 yellow wood goblin + + SPDX-License-Identifier: GPL-3.0-or-later +*/ + +#pragma once + +#include +#include + +#include + +struct sCheatDatIndex { + u32 _gameCode; + u32 _crc32; + u64 _offset; +}; + +class cCheatDatItem { + public: + std::string _title; + std::string _comment; + std::vector _cheat; + u32 _flags; + u32 _offset; + cCheatDatItem(const std::string& title, const std::string& comment, u32 flags, u32 offset = 0) + : _title(title), _comment(comment), _flags(flags), _offset(offset) {}; + enum { EFolder = 1, EInFolder = 2, EOne = 4, ESelected = 8, EOpen = 16 }; +}; + +class cCheat { + public: + bool parse(const std::string& aFileName); + static bool searchCheatData(FILE* aDat, u32 gamecode, u32 crc32, long& aPos, size_t& aSize); + static bool romData(const std::string& aFileName, u32& aGameCode, u32& aCrc32); + std::vector getEnabledCheats(); + void writeCheatsToFile(const char* path); + + protected: + bool parseInternal(FILE* aDat, u32 gamecode, u32 crc32); + void deselectFolder(size_t anIndex); + + protected: + std::vector _data; + std::string _fileName; +}; diff --git a/arm9/source/cheatwnd.cpp b/arm9/source/cheatwnd.cpp index b5ce965b..4058849b 100644 --- a/arm9/source/cheatwnd.cpp +++ b/arm9/source/cheatwnd.cpp @@ -7,9 +7,14 @@ SPDX-License-Identifier: GPL-3.0-or-later */ -#include "cheatwnd.h" -#include +#include #include +#include + +#include + +#include "cheat.h" +#include "cheatwnd.h" #include "gamecode.h" #include "language.h" #include "msgbox.h" @@ -18,16 +23,6 @@ using namespace akui; -#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; -} - cCheatWnd::cCheatWnd(s32 x, s32 y, u32 w, u32 h, cWindow* parent, const std::string& text) : cForm(x, y, w, h, parent, text), _buttonDeselect(0, 0, 46, 18, this, "\x05 Deselect"), @@ -135,7 +130,7 @@ bool cCheatWnd::processKeyMessage(const cKeyMessage& msg) { case cKeyMessage::UI_KEY_LEFT: { size_t ii = _List.selectedRowId(); while (--ii > 0) { - if (_data[_indexes[ii]]._flags & cParsedItem::EFolder) break; + if (_data[_indexes[ii]]._flags & cCheatDatItem::EFolder) break; } _List.selectRow(ii); } @@ -144,7 +139,7 @@ bool cCheatWnd::processKeyMessage(const cKeyMessage& msg) { case cKeyMessage::UI_KEY_RIGHT: { size_t ii = _List.selectedRowId(), top = _List.getRowCount(); while (++ii < top) { - if (_data[_indexes[ii]]._flags & cParsedItem::EFolder) break; + if (_data[_indexes[ii]]._flags & cCheatDatItem::EFolder) break; } _List.selectRow(ii); } @@ -190,23 +185,23 @@ void cCheatWnd::onItemClicked(u32 index) { void cCheatWnd::onSelect(void) { size_t index = _indexes[_List.selectedRowId()]; - if (_data[index]._flags & cParsedItem::EFolder) { - _data[index]._flags ^= cParsedItem::EOpen; + if (_data[index]._flags & cCheatDatItem::EFolder) { + _data[index]._flags ^= cCheatDatItem::EOpen; u32 first = _List.firstVisibleRowId(), row = _List.selectedRowId(); generateList(); _List.setFirstVisibleIdAndSelectRow(first, row); } else { - bool deselect = (_data[index]._flags & (cParsedItem::EOne | cParsedItem::ESelected)) == - (cParsedItem::EOne | cParsedItem::ESelected); - if (_data[index]._flags & cParsedItem::EOne) deselectFolder(index); - if (!deselect) _data[index]._flags ^= cParsedItem::ESelected; + bool deselect = (_data[index]._flags & (cCheatDatItem::EOne | cCheatDatItem::ESelected)) == + (cCheatDatItem::EOne | cCheatDatItem::ESelected); + if (_data[index]._flags & cCheatDatItem::EOne) deselectFolder(index); + if (!deselect) _data[index]._flags ^= cCheatDatItem::ESelected; } } void cCheatWnd::onDeselectAll(void) { - std::vector::iterator itr = _data.begin(); + std::vector::iterator itr = _data.begin(); while (itr != _data.end()) { - (*itr)._flags &= ~cParsedItem::ESelected; + (*itr)._flags &= ~cCheatDatItem::ESelected; ++itr; } } @@ -238,9 +233,9 @@ static void updateDB(u8 value, u32 offset, FILE* db) { void cCheatWnd::onGenerate(void) { FILE* db = fopen((SFN_CHEATS).c_str(), "r+b"); if (db) { - std::vector::iterator itr = _data.begin(); + std::vector::iterator itr = _data.begin(); while (itr != _data.end()) { - updateDB(((*itr)._flags & cParsedItem::ESelected) ? 1 : 0, (*itr)._offset, db); + updateDB(((*itr)._flags & cCheatDatItem::ESelected) ? 1 : 0, (*itr)._offset, db); ++itr; } fclose(db); @@ -259,23 +254,23 @@ void cCheatWnd::onDraw(const cListView::cOwnerDraw& od) { size_t index = _indexes[od._row]; u32 flags = _data[index]._flags; if (od._col == EIconColumn) { - if (flags & cParsedItem::EFolder) { + if (flags & cCheatDatItem::EFolder) { u16 size = od._size.y - EFolderTop * 2; s16 x1 = od._position.x + ((od._size.x - size) >> 1) - 1, x2 = x1 + (size >> 1), y1 = od._position.y + EFolderTop, y2 = y1 + (size >> 1); gdi().frameRect(x1, y1, size, size, od._engine); gdi().drawLine(x1, y2, x1 + size, y2, od._engine); - if (!(flags & cParsedItem::EOpen)) gdi().drawLine(x2, y1, x2, y1 + size, od._engine); - } else if (!(flags & cParsedItem::EInFolder)) { - if (flags & cParsedItem::ESelected) drawMark(od, od._size.x); + if (!(flags & cCheatDatItem::EOpen)) gdi().drawLine(x2, y1, x2, y1 + size, od._engine); + } else if (!(flags & cCheatDatItem::EInFolder)) { + if (flags & cCheatDatItem::ESelected) drawMark(od, od._size.x); } } else if (od._col == ETextColumn) { - if (flags & cParsedItem::EInFolder) { - if (flags & cParsedItem::ESelected) drawMark(od, EFolderWidth); + if (flags & cCheatDatItem::EInFolder) { + if (flags & cCheatDatItem::ESelected) drawMark(od, EFolderWidth); } s16 x = od._position.x; u16 w = od._size.x; - if (flags & cParsedItem::EInFolder) { + if (flags & cCheatDatItem::EInFolder) { x += EFolderWidth; w -= EFolderWidth; } @@ -284,134 +279,17 @@ void cCheatWnd::onDraw(const cListView::cOwnerDraw& od) { } bool cCheatWnd::parse(const std::string& aFileName) { - bool res = false; - _fileName = aFileName; - u32 romcrc32, gamecode; - if (romData(_fileName, gamecode, romcrc32)) { - FILE* dat = fopen((SFN_CHEATS).c_str(), "rb"); - if (dat) { - res = parseInternal(dat, gamecode, romcrc32); - fclose(dat); - } - } - return res; -} + bool res = cCheat::parse(aFileName); + if (res) generateList(); -bool cCheatWnd::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 cCheatWnd::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) { - memcpy(&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 cCheatWnd::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 < cheatCount) { - u32 folderCount = 1; - char* folderName = NULL; - char* folderNote = NULL; - u32 flagItem = 0; - if ((*ccode >> 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 < folderCount; ++ii) { - char* cheatName = (char*)((u32)ccode + 4); - char* cheatNote = (char*)((u32)cheatName + strlen(cheatName) + 1); - u32* cheatData = (u32*)(((u32)cheatNote + strlen(cheatNote) + 1 + 3) & ~3); - u32 cheatDataLen = *cheatData++; - - if (cheatDataLen) { - _data.push_back(cParsedItem(cheatName, cheatNote, - flagItem | ((*ccode & 0xff000000) ? selectValue : 0), - dataPos + (((char*)ccode + 3) - buffer))); - if ((*ccode & 0xff000000) && (flagItem & cParsedItem::EOne)) selectValue = 0; - _data.back()._cheat.resize(cheatDataLen); - memcpy(_data.back()._cheat.data(), cheatData, cheatDataLen * 4); - } - cc++; - ccode = (u32*)((u32)ccode + (((*ccode & 0x00ffffff) + 1) * 4)); - } - } - free(buffer); - generateList(); - return true; -} - void cCheatWnd::generateList(void) { _indexes.clear(); _List.removeAllRows(); - std::vector::iterator itr = _data.begin(); + std::vector::iterator itr = _data.begin(); while (itr != _data.end()) { std::vector row; row.push_back(""); @@ -420,42 +298,8 @@ void cCheatWnd::generateList(void) { _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 cCheatWnd::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 cCheatWnd::getCheats() { - std::vector cheats; - for (uint i = 0; i < _data.size(); i++) { - if (_data[i]._flags & cParsedItem::ESelected) { - cheats.insert(cheats.end(), _data[i]._cheat.begin(), _data[i]._cheat.end()); + if ((flags & cCheatDatItem::EFolder) && (flags & cCheatDatItem::EOpen) == 0) { + while (((*itr)._flags & cCheatDatItem::EInFolder) && itr != _data.end()) ++itr; } } - return cheats; -} - -void cCheatWnd::writeCheatsToFile(const char* path) { - FILE* file = fopen(path, "wb"); - if (file) { - std::vector cheats(getCheats()); - fwrite(cheats.data(), 4, cheats.size(), file); - fwrite("\0\0\0\xCF", 4, 1, file); - fclose(file); - } } diff --git a/arm9/source/cheatwnd.h b/arm9/source/cheatwnd.h index e685a1ba..79ad7aa4 100644 --- a/arm9/source/cheatwnd.h +++ b/arm9/source/cheatwnd.h @@ -10,21 +10,18 @@ #include #include +#include "cheat.h" #include "button.h" #include "form.h" #include "formdesc.h" #include "listview.h" #include "statictext.h" -class cCheatWnd : public akui::cForm { +class cCheatWnd : public akui::cForm, public cCheat { public: cCheatWnd(s32 x, s32 y, u32 w, u32 h, cWindow* parent, const std::string& text); ~cCheatWnd(); bool parse(const std::string& aFileName); - static bool searchCheatData(FILE* aDat, u32 gamecode, u32 crc32, long& aPos, size_t& aSize); - static bool romData(const std::string& aFileName, u32& aGameCode, u32& aCrc32); - std::vector getCheats(); - void writeCheatsToFile(const char* path); protected: void draw(); @@ -49,27 +46,7 @@ class cCheatWnd : public akui::cForm { akui::cFormDesc _renderDesc; akui::cListView _List; - protected: - bool parseInternal(FILE* aDat, u32 gamecode, u32 crc32); - void deselectFolder(size_t anIndex); - private: - struct sDatIndex { - u32 _gameCode; - u32 _crc32; - u64 _offset; - }; - class cParsedItem { - public: - std::string _title; - std::string _comment; - std::vector _cheat; - u32 _flags; - u32 _offset; - cParsedItem(const std::string& title, const std::string& comment, u32 flags, u32 offset = 0) - : _title(title), _comment(comment), _flags(flags), _offset(offset){}; - enum { EFolder = 1, EInFolder = 2, EOne = 4, ESelected = 8, EOpen = 16 }; - }; enum { EIconColumn = 0, ETextColumn = 1, @@ -81,7 +58,5 @@ class cCheatWnd : public akui::cForm { }; private: - std::vector _data; std::vector _indexes; - std::string _fileName; }; diff --git a/arm9/source/globalsettings.cpp b/arm9/source/globalsettings.cpp index 91dbc089..400f886a 100644 --- a/arm9/source/globalsettings.cpp +++ b/arm9/source/globalsettings.cpp @@ -51,11 +51,6 @@ cGlobalSettings::cGlobalSettings() { hbStrap = 0; pico = 0; icon = 1; -#ifndef __KERNEL_LAUNCHER_SUPPORT__ - romLauncher = EKernelLauncher; -#else - romLauncher = ENdsBootstrapLauncher; -#endif } void cGlobalSettings::loadSettings() { diff --git a/arm9/source/launcher/AcekardLauncher.cpp b/arm9/source/launcher/AcekardLauncher.cpp deleted file mode 100644 index 2707e6d3..00000000 --- a/arm9/source/launcher/AcekardLauncher.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - AcekardLauncher.cpp - Copyright (C) 2007 Acekard, www.acekard.com - Copyright (C) 2007-2009 somebody - Copyright (C) 2009 yellow wood goblin - Copyright (C) 2024 lifehackerhansol - - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#include -#include -#include - -#include - -#include "../../../share/fifotool.h" -#include "../ui/progresswnd.h" -#include "AcekardLauncher.h" -#include "dbgtool.h" - -// 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars -#define MAX_FILENAME_LENGTH 768 - -static void resetAndLoop() { - DC_FlushAll(); - DC_InvalidateAll(); - - fifoSendValue32(FIFO_USER_01, MENU_MSG_ARM7_REBOOT); - *((vu32*)0x02FFFE04) = 0; - - // Interrupt - REG_IME = 0; - REG_IE = 0; - REG_IF = ~0; - - // wait for arm7 - while (*((vu32*)0x02FFFE04) == 0) - ; - swiSoftReset(); -} - -bool AcekardLauncher::launchRom(std::string romPath, std::string savePath, u32 flags, - u32 cheatOffset, u32 cheatSize, bool hb) { - tNDSHeader header; - - dbg_printf("load %s\n", romPath.c_str()); - - if (access("fat:/__rpg/akloader.nds", F_OK) != 0) { - printLoaderNotFound("fat:/__rpg/akloader.nds"); - return false; - } - - // akloaders are very old and expect the old-style libfat mount points - romPath.replace(0, 3, "fat0"); - savePath.replace(0, 3, "fat0"); - -#ifdef __AKLOADER_AK2__ - // Create TTMENU.SYS if it don't exist - if (access("fat:/__rpg/system.sys", F_OK) != 0) { - progressWnd().setTipText("Generating SYSTEM.SYS..."); - progressWnd().show(); - progressWnd().setPercent(0); - FILE* TTSYSFile = fopen("fat:/__rpg/system.sys", "wb"); - fseek(TTSYSFile, 0, SEEK_SET); - // memdump. Actually just expanding the file seems to crash, but this works totally fine... - fwrite((void*)0x02400000, 1, 0x400000, TTSYSFile); - fflush(TTSYSFile); - fclose(TTSYSFile); - progressWnd().setPercent(100); - progressWnd().hide(); - } -#endif - - FILE* loader = fopen("fat:/__rpg/akloader.nds", "rb"); - if (loader == NULL) return false; - - fseek(loader, 0, SEEK_SET); - fread(&header, sizeof(header), 1, loader); - - // copy loader's arm7 code - fseek(loader, header.arm7romOffset, SEEK_SET); - fread(header.arm7destination, 4, header.arm7binarySize >> 2, loader); - __NDSHeader->arm7executeAddress = header.arm7executeAddress; - - // copy loader's arm9 code - fseek(loader, header.arm9romOffset, SEEK_SET); - fread(header.arm9destination, 4, header.arm9binarySize >> 2, loader); - __NDSHeader->arm9executeAddress = header.arm9executeAddress; - fclose(loader); - - *(u32*)0x23fd900 = flags; - *(u32*)0x23fd904 = cheatOffset; - *(u32*)0x23fd908 = cheatSize; - memset((void*)0x23fda00, 0, MAX_FILENAME_LENGTH * 2); - strcpy((char*)0x23fda00, romPath.c_str()); - strcpy((char*)(0x23fda00 + MAX_FILENAME_LENGTH), savePath.c_str()); - - dbg_printf("load done\n"); - - resetAndLoop(); - return true; -} diff --git a/arm9/source/launcher/AcekardLauncher.h b/arm9/source/launcher/AcekardLauncher.h deleted file mode 100644 index 1648d475..00000000 --- a/arm9/source/launcher/AcekardLauncher.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright (C) 2024 lifehackerhansol - - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#pragma once - -#include -#include - -#include "ILauncher.h" - -class AcekardLauncher : public ILauncher { - public: - bool launchRom(std::string romPath, std::string savePath, u32 flags, u32 cheatOffset, - u32 cheatSize, bool hb) override; -}; diff --git a/arm9/source/launcher/DSpico/picoLoader7.h b/arm9/source/launcher/DSpico/picoLoader7.h index 375975f6..ee2f6e45 100644 --- a/arm9/source/launcher/DSpico/picoLoader7.h +++ b/arm9/source/launcher/DSpico/picoLoader7.h @@ -1,7 +1,7 @@ #pragma once /// @brief The Pico Loader API version supported by this header file. -#define PICO_LOADER_API_VERSION 1 +#define PICO_LOADER_API_VERSION 3 /// @brief Enum to specify the drive to boot from. typedef enum @@ -35,6 +35,54 @@ typedef struct char arguments[256]; } pload_params_t; +/// @brief Struct representing the API version 2 part of the header of picoLoader7.bin. +typedef struct +{ + /// @brief The path of the rom to return to when exiting an application. + /// When this path is not set, no bootstub will be patched into homebrew applications. + char launcherPath[256]; +} pload_header7_v2_t; + +/// @brief Struct representing a single Action Replay cheat opcode. +typedef struct +{ + /// @brief The first part of the opcode. + u32 a; + + /// @brief The second part of the opcode. + u32 b; +} pload_cheat_opcode_t; + +/// @brief Struct representing a single Action Replay cheat. +typedef struct +{ + /// @brief Length of \see opcodes in bytes. + u32 length; + + /// @brief The cheat opcodes. + pload_cheat_opcode_t opcodes[1]; +} pload_cheat_t; + +/// @brief Struct representing one or more cheats. Cheats are adjacent starting from the firstCheat field. +typedef struct +{ + /// @brief Length of this stucture (length field + numberOfCheats field + all cheats). + u32 length; + + /// @brief The number of cheats. + u32 numberOfCheats; + + /// @brief The first cheat. + pload_cheat_t firstCheat; +} pload_cheats_t; + +/// @brief Struct representing the API version 3 part of the header of picoLoader7.bin. +typedef struct +{ + /// @brief Pointer to the cheats, or \c nullptr when there are no cheats. + const pload_cheats_t* cheats; +} pload_header7_v3_t; + /// @brief Struct representing the header of picoLoader7.bin. typedef struct { @@ -52,4 +100,10 @@ typedef struct /// @brief The load params, see \see pload_params_t. pload_params_t loadParams; + + /// @brief The API version 2 part of the header. Only access this when \see apiVersion >= 2. + pload_header7_v2_t v2; + + /// @brief The API version 3 part of the header. Only access this when \see apiVersion >= 3. + pload_header7_v3_t v3; } pload_header7_t; diff --git a/arm9/source/launcher/DSpicoLauncher.cpp b/arm9/source/launcher/DSpicoLauncher.cpp index 85ae50ec..9464a36c 100644 --- a/arm9/source/launcher/DSpicoLauncher.cpp +++ b/arm9/source/launcher/DSpicoLauncher.cpp @@ -33,11 +33,66 @@ constexpr std::align_val_t cache_align { 32 }; typedef void (*pico_loader_9_func_t)(void); +bool DSpicoLauncher::prepareCheats(void) { + u32* cheatTablePtr; + std::vector cheatEntries; + // a pload_cheats_t table always has two u32s as the header + u32 cheatTableSize = 8; + cCheat cheat; + + if (!cheat.parse(mRomPath)) goto cheat_failed; + + cheatEntries = cheat.getEnabledCheats(); + if (cheatEntries.empty()) goto cheat_failed; + + // calculate size of pload_cheats_t to allocate + for (u32 i = 0; i < cheatEntries.size(); i++) { + // Each pload_cheats_t table has a pload_cheat_t entry for each cheat entry + // which has a u32 for length + cheatTableSize += 4; + // then the data, multiplied by 4 since each opcode is a u32 + cheatTableSize += ((cheatEntries[i]._cheat.size()) << 2); + } + + // construct the cheat table + mCheats = (pload_cheats_t*)memalign(4, cheatTableSize); + mCheats->length = cheatTableSize; + mCheats->numberOfCheats = cheatEntries.size(); + cheatTablePtr = (u32*)mCheats; + + // load cheat codes to table + // skip the first two u32, which is the cheat table's header + cheatTablePtr += 2; + + for (u32 i = 0; i < cheatEntries.size(); i++) { + // pload_cheat_t->length + *cheatTablePtr = cheatEntries[i]._cheat.size() << 2; + + cheatTablePtr++; + // pload_cheat_opcode_t, arbitrary size + // TODO bounds check + for (u32 j = 0; j < cheatEntries[i]._cheat.size(); j++) { + *cheatTablePtr = cheatEntries[i]._cheat[j]; + cheatTablePtr++; + } + } + + return true; + + cheat_failed: + return false; +} + + bool DSpicoLauncher::launchRom(std::string romPath, std::string savePath, u32 flags, u32 cheatOffset, u32 cheatSize, bool hb) { const char picoLoader7Path[] = "fat:/_pico/picoLoader7.bin"; const char picoLoader9Path[] = "fat:/_pico/picoLoader9.bin"; + mRomPath = romPath; + mSavePath = savePath; + mFlags = flags; + progressWnd().setTipText("Initializing pico-loader..."); progressWnd().show(); progressWnd().setPercent(0); @@ -71,8 +126,14 @@ bool DSpicoLauncher::launchRom(std::string romPath, std::string savePath, u32 fl } pload_params_t sLoadParams{}; - strcpy(sLoadParams.romPath, romPath.c_str()); - strcpy(sLoadParams.savePath, savePath.c_str()); + strcpy(sLoadParams.romPath, mRomPath.c_str()); + strcpy(sLoadParams.savePath, mSavePath.c_str()); + + if(mFlags & PATCH_CHEATS){ + prepareCheats(); + } + progressWnd().setPercent(20); + fseek(loader9, 0, SEEK_END); auto picoLoader9Size = ftell(loader9); @@ -114,14 +175,18 @@ bool DSpicoLauncher::launchRom(std::string romPath, std::string savePath, u32 fl TIMER_DATA(i) = 0; } + ((pload_header7_t*)0x06840000)->bootDrive = PLOAD_BOOT_DRIVE_DLDI; + ((pload_header7_t*)0x06840000)->dldiDriver = (void*)io_dldi_data; + tonccpy(&((pload_header7_t*)0x06840000)->loadParams, &sLoadParams, sizeof(pload_params_t)); + if(mFlags & PATCH_CHEATS){ + ((pload_header7_t*)0x06840000)->v3.cheats = mCheats; + } + DC_FlushAll(); DC_InvalidateAll(); IC_InvalidateAll(); sysSetBusOwners(false, false); - ((pload_header7_t*)0x06840000)->bootDrive = PLOAD_BOOT_DRIVE_DLDI; - ((pload_header7_t*)0x06840000)->dldiDriver = (void*)io_dldi_data; - tonccpy(&((pload_header7_t*)0x06840000)->loadParams, &sLoadParams, sizeof(pload_params_t)); vramSetBankC(VRAM_C_ARM7_0x06000000); vramSetBankD(VRAM_D_ARM7_0x06020000); fifoSendValue32(FIFO_USER_01, MENU_MSG_ARM7_REBOOT_PICOLOADER); @@ -129,4 +194,4 @@ bool DSpicoLauncher::launchRom(std::string romPath, std::string savePath, u32 fl ((pico_loader_9_func_t)0x06800000)(); return false; -} \ No newline at end of file +} diff --git a/arm9/source/launcher/DSpicoLauncher.h b/arm9/source/launcher/DSpicoLauncher.h index c09baeb4..01e6931f 100644 --- a/arm9/source/launcher/DSpicoLauncher.h +++ b/arm9/source/launcher/DSpicoLauncher.h @@ -8,6 +8,7 @@ #include +#include "DSpico/picoLoader7.h" #include "../dsrom.h" #include "ILauncher.h" @@ -18,10 +19,8 @@ class DSpicoLauncher : public ILauncher { private: bool prepareCheats(void); - bool prepareIni(bool hb); - bool hotkeyCheck; std::string mRomPath; std::string mSavePath; u32 mFlags; - DSRomInfo _romInfo; -}; \ No newline at end of file + pload_cheats_t* mCheats; +}; diff --git a/arm9/source/launcher/NdsBootstrapLauncher.cpp b/arm9/source/launcher/NdsBootstrapLauncher.cpp index 32b1374b..6e4370e3 100644 --- a/arm9/source/launcher/NdsBootstrapLauncher.cpp +++ b/arm9/source/launcher/NdsBootstrapLauncher.cpp @@ -15,7 +15,7 @@ #include -#include "../cheatwnd.h" +#include "cheat.h" #include "../dsrom.h" #include "../flags.h" #include "../inifile.h" @@ -68,17 +68,16 @@ void slot2RamAccess(){ bool NdsBootstrapLauncher::prepareCheats() { u32 gameCode, crc32; - if (cCheatWnd::romData(mRomPath, gameCode, crc32)) { + if (cCheat::romData(mRomPath, gameCode, crc32)) { FILE* cheatDb = fopen((SFN_CHEATS).c_str(), "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 (cCheat::searchCheatData(cheatDb, gameCode, crc32, cheatOffset, cheatSize)) { + cCheat cheat; + cheat.parse(mRomPath); + cheat.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); diff --git a/arm9/source/launcher/TopToyLauncher.cpp b/arm9/source/launcher/TopToyLauncher.cpp deleted file mode 100644 index dde9c37d..00000000 --- a/arm9/source/launcher/TopToyLauncher.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - Copyright (C) 2024 lifehackerhansol - - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#include -#include -#include -#include -#include -#include - -#include - -#include "../cheatwnd.h" -#include "../dsrom.h" -#include "../flags.h" -#include "../mainlist.h" -#include "../systemfilenames.h" -#include "../ui/progresswnd.h" -#include "ILauncher.h" -#include "TopToyLauncher.h" -#include "libfat_ext/fat_ext.h" - -#ifdef __TTLAUNCHER_DSTT__ -#include "ttio/scdssdhc.h" -extern u32 SCDS_isSDHC; -#endif - -static void resetAndLoop() { - DC_FlushAll(); - DC_InvalidateAll(); - - fifoSendValue32(FIFO_USER_01, MENU_MSG_ARM7_REBOOT_TT); - *((vu32*)0x02FFFE04) = 0; - - // Interrupt - REG_IME = 0; - REG_IE = 0; - REG_IF = ~0; - - // wait for arm7 - while (*((vu32*)0x02FFFE04) == 0) - ; - swiSoftReset(); -} - -typedef struct { - char TTARMagic[4]; // usually "TTAR" - char gameCode[4]; // gameCode of title as seen in usrcheat.dat - u32 crc32; // crc32 of title header as seen in usrcheat.dat - u32 unk1; // TODO: what does this mean? - u32 cheatOffset; // relative from 0x1100 of file - u32 cheatSize; // size in bytes - u8 reserved[235]; -} PACKED TTARHeader; - -bool TopToyLauncher::prepareCheats() { - u32 gameCode, crc32; - - if (cCheatWnd::romData(mRomPath, gameCode, crc32)) { - FILE* cheatDb = fopen((SFN_CHEATS).c_str(), "rb"); - if (!cheatDb) goto cheat_failed; - long cheatOffset; - size_t cheatSize; - if (cCheatWnd::searchCheatData(cheatDb, gameCode, crc32, cheatOffset, cheatSize)) { - // Read cheat codes - cCheatWnd chtwnd((256) / 2, (192) / 2, 100, 100, NULL, mRomPath); - chtwnd.parse(mRomPath); - std::vector cheats(chtwnd.getCheats()); - - // YSMENU.ARP file creation - ALIGN(4) TTARHeader arHeader = {}; - arHeader.TTARMagic[0] = 'T'; - arHeader.TTARMagic[1] = 'T'; - arHeader.TTARMagic[2] = 'A'; - arHeader.TTARMagic[3] = 'R'; - memcpy(&arHeader.gameCode, &gameCode, 4); - arHeader.crc32 = crc32; - // We will write the cheat codes directly to 0x1100. - arHeader.cheatOffset = 0; - arHeader.cheatSize = cheats.size() << 2; - FILE* cheatFile = fopen("/YSMENU.ARP", "wb"); - fseek(cheatFile, 0, SEEK_SET); - // memdump. Actually just expanding the file seems to crash, but this works totally - // fine... - fwrite((void*)0x02400000, 4, 0x1100 >> 2, cheatFile); - fflush(cheatFile); - fseek(cheatFile, 0, SEEK_SET); - fwrite(&arHeader, 1, sizeof(TTARHeader), cheatFile); - fseek(cheatFile, 0x1100, SEEK_SET); - fwrite(cheats.data(), 4, cheats.size(), cheatFile); - fflush(cheatFile); - fclose(cheatFile); - } else { - fclose(cheatDb); - goto cheat_failed; - } - fclose(cheatDb); - } - - return true; - -cheat_failed: - // Remove cheat bin if exists - if (access("/YSMENU.ARP", F_OK) == 0) { - remove("/YSMENU.ARP"); - } - - return false; -} - -// TODO: what are the unknowns? -typedef struct { - char TTSYSMagic[4]; - u32 unk1; - u32 unk2; // always set to 1? - u32 softReset; - u32 useCheats; - u32 DMA; - u8 reserved[232]; -} PACKED TTSYSHeader; - -// TTMENU.SYS file creation. Sets up parameters for ttpatch.dat -bool TopToyLauncher::prepareTTSYS(void) { - char fname[0x1004] = {}; - TTSYSHeader* ttsys_header = (TTSYSHeader*)malloc(sizeof(TTSYSHeader)); - ttsys_header->TTSYSMagic[0] = 't'; - ttsys_header->TTSYSMagic[1] = 't'; - ttsys_header->TTSYSMagic[2] = 'd'; - ttsys_header->TTSYSMagic[3] = 's'; - ttsys_header->unk1 = 0; - ttsys_header->unk2 = 1; - ttsys_header->softReset = mFlags & PATCH_SOFT_RESET ? 1 : 0; - ttsys_header->useCheats = mFlags & PATCH_CHEATS ? 1 : 0; - ttsys_header->DMA = mFlags & PATCH_DMA ? 1 : 0; - - FILE* TTSYSFile = fopen("fat:/TTMENU.SYS", "rb+"); - fseek(TTSYSFile, 0, SEEK_SET); - fwrite(ttsys_header, sizeof(TTSYSHeader), 1, TTSYSFile); - free(ttsys_header); - fatGetAliasPath("fat:/", mRomPath.c_str(), fname); - fseek(TTSYSFile, 0x100, SEEK_SET); - fwrite(fname + 4, 1, 0x1000, TTSYSFile); - fatGetAliasPath("fat:/", mSavePath.c_str(), fname); - fseek(TTSYSFile, 0x1100, SEEK_SET); - fwrite(fname + 4, 1, 0x1000, TTSYSFile); - if (mFlags & PATCH_CHEATS) { - fseek(TTSYSFile, 0x2100, SEEK_SET); - fwrite("/YSMENU.ARP", 1, 0x12, TTSYSFile); - } - fflush(TTSYSFile); - fclose(TTSYSFile); - - return true; -} - -bool TopToyLauncher::launchRom(std::string romPath, std::string savePath, u32 flags, - u32 cheatOffset, u32 cheatSize, bool hb) { - std::string loaderPath = -#ifdef __TTLAUNCHER_M3__ - "fat:/TTMenu/m3patch.dat" -#else // __TTLAUNCHER_M3__ - "fat:/TTMenu/ttpatch.dat" -#endif // __TTLAUNCHER_M3__ - ; - - if (access(loaderPath.c_str(), F_OK) != 0) { - printLoaderNotFound(loaderPath); - return false; - } - - mRomPath = romPath; - mSavePath = savePath; - mFlags = flags; - - // Create TTMENU.SYS if it don't exist - if (access("fat:/TTMENU.SYS", F_OK) != 0) { - progressWnd().setTipText("Generating TTMENU.SYS..."); - progressWnd().show(); - progressWnd().setPercent(0); - FILE* TTSYSFile = fopen("fat:/TTMENU.SYS", "wb"); - fseek(TTSYSFile, 0, SEEK_SET); - // memdump. Actually just expanding the file seems to crash, but this works totally fine... - fwrite((void*)0x02400000, 1, 0x400000, TTSYSFile); - fflush(TTSYSFile); - fclose(TTSYSFile); - progressWnd().setPercent(100); - progressWnd().hide(); - } - - // Prepare cheat codes if enabled - if (flags & PATCH_CHEATS) { - if (!prepareCheats()) return false; - } - - // Setup TTMenu system parameters - if (!prepareTTSYS()) return false; - - FILE* loader = fopen(loaderPath.c_str(), "rb"); - tNDSHeader* header = (tNDSHeader*)malloc(sizeof(tNDSHeader)); - u8* loader_arm7 = NULL; - fseek(loader, 0, SEEK_SET); - fread(header, 1, sizeof(tNDSHeader), loader); - fseek(loader, header->arm9romOffset, SEEK_SET); - fread((void*)header->arm9destination, 1, header->arm9binarySize, loader); - fseek(loader, header->arm7romOffset, SEEK_SET); - loader_arm7 = (u8*)memalign(32, header->arm7binarySize); - fread(loader_arm7, 1, header->arm7binarySize, loader); - fclose(loader); - memcpy((void*)__NDSHeader, header, sizeof(tNDSHeader)); - free(header); - *(u32*)0x02FFFE00 = (u32)loader_arm7; - - // patch a loop in ARM9 - // not sure why it's there. Some sort of obfuscation mechanism? - if (*((vu32*)0x023200EC) == 0xEAFFFFFE) // b #0; bad - *((vu32*)0x023200EC) = 0xE3A00000; // mov r0, #0 - - // ttpatch checks this for some reason - *((vu32*)0x02FFFC20) = 0x5555AAAA; - -#ifdef __TTLAUNCHER_DSTT__ - // set SD/SDHC flag - // Needs a SDIO reinitialization to retrieve HCS bit - if (!SCDS_SDInitialize()) return false; - - *((vu32*)0x02FFFC24) = SCDS_isSDHC ? ~0 : 0; -#endif - - // this int seems to be a flag to reinitialize the SD card in ttpatch - // if this is *not* -1, ttpatch sends an SDIO CMD12 (STOP_TRANSMISSION) - // other frontends set this to -1 by default, so let's do it too - *((vu32*)0x02FFFC28) = ~0; - - resetAndLoop(); - - free(loader_arm7); - - return false; -} diff --git a/arm9/source/launcher/TopToyLauncher.h b/arm9/source/launcher/TopToyLauncher.h deleted file mode 100644 index 760d0376..00000000 --- a/arm9/source/launcher/TopToyLauncher.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) 2024 lifehackerhansol - - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#pragma once - -#include -#include - -#include "ILauncher.h" - -class TopToyLauncher : public ILauncher { - public: - bool launchRom(std::string romPath, std::string savePath, u32 flags, u32 cheatOffset, - u32 cheatSize, bool hb) override; - - private: - bool prepareCheats(void); - bool prepareTTSYS(void); - std::string mRomPath; - std::string mSavePath; - u32 mFlags; -}; diff --git a/arm9/source/launcher/ttio/libtwl_card.c b/arm9/source/launcher/ttio/libtwl_card.c deleted file mode 100644 index 2945aa3a..00000000 --- a/arm9/source/launcher/ttio/libtwl_card.c +++ /dev/null @@ -1,82 +0,0 @@ -// clang-format off - -/* - This file is a part of libtwl (card.c) - - Copyright (C) 2023 Gericom - - SPDX-License-Identifier: Zlib -*/ - -#include -#include "libtwl_card.h" - -void card_romCpuRead(u32* dst, u32 words) -{ - u32* target = dst + words; - do - { - // Read data if available - if (card_romIsDataReady()) - { - u32 data = card_romGetData(); - if (dst < target) - *dst++ = data; - } - } while (card_romIsBusy()); -} - -void card_romCpuReadUnaligned(u8* dst, u32 words) -{ - u8* target = dst + (words << 2); - do - { - // Read data if available - if (card_romIsDataReady()) - { - u32 data = card_romGetData(); - if (dst < target) - { - *dst++ = data & 0xFF; - *dst++ = (data >> 8) & 0xFF; - *dst++ = (data >> 16) & 0xFF; - *dst++ = (data >> 24) & 0xFF; - } - } - } while (card_romIsBusy()); -} - -void card_romCpuWrite(const u32* src, u32 words) -{ - u32 data = 0; - const u32* target = src + words; - do - { - // Write data if ready - if (card_romIsDataReady()) - { - if (src < target) - data = *src++; - card_romSetData(data); - } - } while (card_romIsBusy()); -} - -void card_romCpuWriteUnaligned(const u8* src, u32 words) -{ - u32 data = 0; - const u8* target = src + (words << 2); - do - { - // Write data if ready - if (card_romIsDataReady()) - { - if (src < target) - { - data = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - src += 4; - } - card_romSetData(data); - } - } while (card_romIsBusy()); -} diff --git a/arm9/source/launcher/ttio/libtwl_card.h b/arm9/source/launcher/ttio/libtwl_card.h deleted file mode 100644 index cf9ca699..00000000 --- a/arm9/source/launcher/ttio/libtwl_card.h +++ /dev/null @@ -1,134 +0,0 @@ -// clang-format off - -/* - This file is a part of libtwl (card.h) - - Copyright (C) 2023 Gericom - - SPDX-License-Identifier: Zlib -*/ - -#pragma once - -#define REG_MCCNT0 (*(vu16*)0x040001A0) -#define REG_MCD0 (*(vu16*)0x040001A2) -#define REG_MCCNT1 (*(vu32*)0x040001A4) -#define REG_MCCMD0 (*(vu32*)0x040001A8) -#define REG_MCCMD1 (*(vu32*)0x040001AC) -#define REG_MCSCR0 (*(vu32*)0x040001B0) -#define REG_MCSCR1 (*(vu32*)0x040001B4) -#define REG_MCSCR2 (*(vu32*)0x040001B8) -#define REG_MCD1 (*(vu32*)0x04100010) - -// REG_MCCNT0 - -#define MCCNT0_SPI_RATE_4_19_MHZ 0 -#define MCCNT0_SPI_RATE_2_09_MHZ 1 -#define MCCNT0_SPI_RATE_1_05_MHZ 2 -#define MCCNT0_SPI_RATE_524_KHZ 3 - -#define MCCNT0_SPI_HOLD_CS (1 << 6) -#define MCCNT0_SPI_BUSY (1 << 7) - -#define MCCNT0_MODE_MASK (1 << 13) -#define MCCNT0_MODE_ROM (0 << 13) -#define MCCNT0_MODE_SPI (1 << 13) - -#define MCCNT0_ROM_XFER_IRQ (1 << 14) -#define MCCNT0_ENABLE (1 << 15) - -// REG_MCCNT1 - -#define MCCNT1_LATENCY1_SHIFT 0 -#define MCCNT1_LATENCY1_MASK 0x1FFF -#define MCCNT1_LATENCY1(x) (x) - -#define MCCNT1_READ_DATA_DESCRAMBLE (1 << 13) -#define MCCNT1_CLOCK_SCRAMBLER (1 << 14) -#define MCCNT1_APPLY_SCRAMBLE_SEED (1 << 15) - -#define MCCNT1_LATENCY2_SHIFT 16 -#define MCCNT1_LATENCY2_MASK 0x3F0000 -#define MCCNT1_LATENCY2(x) (((x) << MCCNT1_LATENCY2_SHIFT) & MCCNT1_LATENCY2_MASK) - -#define MCCNT1_CMD_SCRAMBLE (1 << 22) - -#define MCCNT1_DATA_READY (1 << 23) - -#define MCCNT1_LEN_0 (0 << 24) -#define MCCNT1_LEN_512 (1 << 24) -#define MCCNT1_LEN_1024 (2 << 24) -#define MCCNT1_LEN_2048 (3 << 24) -#define MCCNT1_LEN_4096 (4 << 24) -#define MCCNT1_LEN_8192 (5 << 24) -#define MCCNT1_LEN_16384 (6 << 24) -#define MCCNT1_LEN_4 (7 << 24) - -#define MCCNT1_CLK_6_7_MHZ (0 << 27) -#define MCCNT1_CLK_4_2_MHZ (1 << 27) - -#define MCCNT1_LATENCY_CLK (1 << 28) - -#define MCCNT1_RESET_ON (0 << 29) -#define MCCNT1_RESET_OFF (1 << 29) - -#define MCCNT1_DIR_READ (0 << 30) -#define MCCNT1_DIR_WRITE (1 << 30) - -#define MCCNT1_ENABLE (1 << 31) - -#ifdef __cplusplus -extern "C" -{ -#endif - - static inline void card_romSetCmd(u64 cmd) - { - *(vu64*)®_MCCMD0 = __builtin_bswap64(cmd); - } - - static inline bool card_romIsDataReady(void) - { - return REG_MCCNT1 & MCCNT1_DATA_READY; - } - - static inline void card_romWaitDataReady(void) - { - while(!card_romIsDataReady()); - } - - static inline u32 card_romGetData(void) - { - return REG_MCD1; - } - - static inline void card_romSetData(u32 data) - { - REG_MCD1 = data; - } - - static inline bool card_romIsBusy(void) - { - return REG_MCCNT1 & MCCNT1_ENABLE; - } - - static inline void card_romWaitBusy(void) - { - while(card_romIsBusy()); - } - - static inline void card_romStartXfer(u32 settings, bool irq) - { - REG_MCCNT0 = (REG_MCCNT0 & ~(MCCNT0_MODE_MASK | MCCNT0_ROM_XFER_IRQ)) | MCCNT0_MODE_ROM | (irq ? MCCNT0_ROM_XFER_IRQ : 0) | MCCNT0_ENABLE; - REG_MCCNT1 = MCCNT1_ENABLE | settings; - } - - void card_romCpuRead(u32* dst, u32 len); - void card_romCpuReadUnaligned(u8* dst, u32 words); - - void card_romCpuWrite(const u32* src, u32 words); - void card_romCpuWriteUnaligned(const u8* src, u32 words); - -#ifdef __cplusplus -} -#endif diff --git a/arm9/source/launcher/ttio/scdssdhc.c b/arm9/source/launcher/ttio/scdssdhc.c deleted file mode 100644 index a3e451e2..00000000 --- a/arm9/source/launcher/ttio/scdssdhc.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - SuperCard DSONE - Card IO routines - - Copyright (C) 2023 lifehackerhansol - - SPDX-License-Identifier: Zlib -*/ - -#include -#include "scdssdhc.h" -#include "libtwl_card.h" - -u32 SCDS_isSDHC = 0; - -static u32 SCDS_SDHostSetMode(u8 sdio, u32 parameter, u8 response_type, u32 latency) -{ - u64 command = ((u64)SCDS_CMD_SD_HOST_PARAM << 56) | ((u64)parameter << 24) | ((u64)sdio << 16) | ((u64)response_type << 8); - card_romSetCmd(command); - card_romStartXfer(SCDS_CTRL_READ_4B | MCCNT1_LATENCY1(latency), false); - card_romWaitDataReady(); - return card_romGetData(); -} - -static u32 SCDS_IsSDHostBusy(void) -{ - REG_SCDS_MCCMD[0] = SCDS_CMD_SD_HOST_BUSY; - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - return card_romGetData(); -} - -static u32 SCDS_SDHostGetResponse(void) -{ - REG_SCDS_MCCMD[0] = SCDS_CMD_SD_HOST_RESPONSE; - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - return __builtin_bswap32(card_romGetData()); -} - -static void SCDS_SDSendR0Command(u8 sdio, u32 parameter, u32 latency) -{ - SCDS_SDHostSetMode(sdio, parameter, SCDS_SD_HOST_NORESPONSE, latency); - while(SCDS_IsSDHostBusy()); -} - -static u32 SCDS_SDSendR1Command(u8 sdio, u32 parameter, u32 latency) -{ - SCDS_SDHostSetMode(sdio, parameter, SCDS_SD_HOST_READ_4B, latency); - while(SCDS_IsSDHostBusy()); - return SCDS_SDHostGetResponse(); -} - -// TODO: save the response to a buffer (also figure out in which order they're sent) -static void SCDS_SDSendR2Command(u8 sdio, u32 parameter, u32 latency) -{ - SCDS_SDHostSetMode(sdio, parameter, SCDS_SD_HOST_READ_4B_MULTI, latency); - while(SCDS_IsSDHostBusy()); - - // TODO: parse this response - SCDS_SDHostGetResponse(); - - for(int i=0; i < 4; i++) - { - SCDS_SDHostSetMode(sdio, parameter, SCDS_SD_HOST_NEXT_4B, latency); - while(SCDS_IsSDHostBusy()); - // TODO: parse this response - SCDS_SDHostGetResponse(); - } - SCDS_SDHostSetMode(sdio, parameter, SCDS_SD_HOST_SEND_STOP_CLK, 0); - while(SCDS_IsSDHostBusy()); -} - -void waitByLoop(u32 count); - -static void SCDS_SDHostSetRegister(u8 bits) -{ - u64 command = ((u64)SCDS_CMD_SD_HOST_SET_REGISTER << 56) | ((u64)(0x30 | bits) << 48); - card_romSetCmd(command); - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - card_romGetData(); - waitByLoop(0x300); -} - -static u32 SCDS_IsSDFIFOBusy(void) { - REG_SCDS_MCCMD[0] = SCDS_CMD_FIFO_BUSY; - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - return card_romGetData(); -} - -// Reads max 512 bytes -static void SCDS_SDFIFOReadData(void *buffer, u32 length) -{ - REG_SCDS_MCCMD[0] = SCDS_CMD_FIFO_READ_DATA; - card_romStartXfer(SCDS_CTRL_READ_512B, false); - if ((u32)buffer & 3) - card_romCpuReadUnaligned((u8 *)buffer, length); - else - card_romCpuRead(buffer, length); -} - -// Writes max 512 bytes -static void SCDS_SDFIFOWriteData(const void *buffer, u32 length) -{ - REG_SCDS_MCCMD[0] = SCDS_CMD_FIFO_WRITE_DATA; - card_romStartXfer(SCDS_CTRL_WRITE_512B, false); - if ((u32)buffer & 3) - card_romCpuWriteUnaligned((u8 *)buffer, length); - else - card_romCpuWrite(buffer, length); -} - -bool SCDS_SDInitialize(void) -{ - u32 isSD20 = 0; - u32 response = 0; - - SCDS_isSDHC = 0; - - // TODO: What is this command doing? - card_romSetCmd(0x6600000000000000ull); - card_romStartXfer(0xA7586000, false); - card_romWaitDataReady(); - card_romGetData(); - - // Reset SD host - SCDS_SDHostSetRegister(0); - - // Init - SCDS_SDHostSetRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_400KHZ_CLK | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); - SCDS_SDHostSetMode(0, 0, SCDS_SD_HOST_SEND_CLK, SCDS_CTRL_SD_LOW_CLK_LATENCY); - waitByLoop(0x1000); - - // CMD0 - SCDS_SDSendR0Command(0, 0, SCDS_CTRL_SD_LOW_CLK_LATENCY); - SCDS_SDHostSetMode(0, 0, SCDS_SD_HOST_SEND_STOP_CLK, SCDS_CTRL_SD_LOW_CLK_LATENCY); - - // CMD8 - SCDS_SDHostSetMode(8, 0x1AA, SCDS_SD_HOST_READ_4B, SCDS_CTRL_SD_LOW_CLK_LATENCY); - - u32 retryCount = 9999; - while(1) - { - if(!SCDS_IsSDHostBusy()) - { - response = SCDS_SDHostGetResponse(); - break; - } - if (--retryCount == 0) - { - SCDS_SDHostSetRegister(0); - SCDS_SDHostSetRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_400KHZ_CLK | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); - response = 0; - break; - } - } - - if(response == 0x1AA) - isSD20 = 1; - - do - { - // CMD55 - SCDS_SDHostSetMode(55, 0, SCDS_SD_HOST_READ_4B, SCDS_CTRL_SD_LOW_CLK_LATENCY); - retryCount = 9999; - while(SCDS_IsSDHostBusy()) - { - if (--retryCount == 0) - { - SCDS_SDHostSetRegister(0); - SCDS_SDHostSetRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_400KHZ_CLK | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); - return false; - } - } - SCDS_SDHostGetResponse(); - - // ACMD41 - u32 parameter = 0x00FC0000; - if(isSD20) - parameter |= BIT(30); - response = SCDS_SDSendR1Command(41, parameter, SCDS_CTRL_SD_LOW_CLK_LATENCY); - } while(!(response & BIT(31))); - - SCDS_isSDHC = response & BIT(30) ? 1 : 0; - - // CMD2 - SCDS_SDSendR2Command(2, 0, SCDS_CTRL_SD_LOW_CLK_LATENCY); - - // CMD3 - response = SCDS_SDSendR1Command(3, 0, SCDS_CTRL_SD_LOW_CLK_LATENCY); - u32 sdio_rca = response & 0xFFFF0000; - - // CMD7 - SCDS_SDSendR1Command(7, sdio_rca, SCDS_CTRL_SD_LOW_CLK_LATENCY); - - // ACMD6 - SCDS_SDSendR1Command(55, sdio_rca, SCDS_CTRL_SD_LOW_CLK_LATENCY); - SCDS_SDSendR1Command(6, 2, SCDS_CTRL_SD_LOW_CLK_LATENCY); - - // CMD16 - SCDS_SDSendR1Command(16, 512, SCDS_CTRL_SD_LOW_CLK_LATENCY); - - SCDS_SDHostSetRegister(0); - SCDS_SDHostSetRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_CLEAN_ROM_MODE); - if(SCDS_isSDHC) - SCDS_SDHostSetRegister(SCDS_SD_HOST_REG_RESET | SCDS_SD_HOST_REG_CLEAN_ROM_MODE | SCDS_SD_HOST_REG_SDHC); - - return true; -} - -void SCDS_SDReadSingleSector(u32 sector, void *buffer) -{ - u64 command = ((u64)SCDS_CMD_SD_READ_SINGLE_BLOCK << 56) | ((u64)(SCDS_isSDHC ? sector : sector << 9) << 24); - card_romSetCmd(command); - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - card_romGetData(); - - // wait until data ready - while(SCDS_IsSDFIFOBusy()); - - // retrieve data - SCDS_SDFIFOReadData(buffer, 128); -} - -void SCDS_SDReadMultiSector(u32 sector, void *buffer, u32 num_sectors) -{ - u64 command = ((u64)SCDS_CMD_SD_READ_MULTI_BLOCK << 56) | ((u64)(SCDS_isSDHC ? sector : sector << 9) << 24); - card_romSetCmd(command); - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - card_romGetData(); - - while(1) - { - // wait until data ready - while(SCDS_IsSDFIFOBusy()); - - // retrieve data - SCDS_SDFIFOReadData(buffer, 128); - buffer = (u8 *)buffer + 0x200; - num_sectors--; - if(num_sectors == 0) - break; - SCDS_SDHostSetMode(0, 0, SCDS_SD_HOST_NEXT_DATABLOCK, 0); - }; - - // end read - SCDS_SDSendR1Command(12, 0, 0); -} - -void SCDS_SDWriteSingleSector(u32 sector, const void *buffer) -{ - // instruct cart where to write - SCDS_SDSendR1Command(24, SCDS_isSDHC ? sector : sector << 9, 0); - - // write - SCDS_SDFIFOWriteData(buffer, 128); - while(SCDS_IsSDHostBusy()); - - // end write - REG_SCDS_MCCMD[0] = SCDS_CMD_SD_WRITE_END; - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - card_romGetData(); - while(SCDS_IsSDHostBusy()); -} - -void SCDS_SDWriteMultiSector(u32 sector, const void *buffer, u32 num_sectors) -{ - // instruct cart where to write - SCDS_SDSendR1Command(25, SCDS_isSDHC ? sector : sector << 9, 0); - - while (num_sectors--) { - // end write - // well, it's supposed to be end write. But doing it first is a no-op, and it's also - // a little simpler to write this way - REG_SCDS_MCCMD[0] = SCDS_CMD_SD_WRITE_END; - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - card_romGetData(); - while(SCDS_IsSDHostBusy()); - // write - SCDS_SDFIFOWriteData(buffer, 128); - while(SCDS_IsSDHostBusy()); - buffer = (u8 *)buffer + 0x200; - } - - // *really* end write - SCDS_SDSendR1Command(12, 0, 0); - REG_SCDS_MCCMD[0] = SCDS_CMD_SD_WRITE_END; - card_romStartXfer(SCDS_CTRL_READ_4B, false); - card_romWaitDataReady(); - card_romGetData(); - while(SCDS_IsSDHostBusy()); -} diff --git a/arm9/source/launcher/ttio/scdssdhc.h b/arm9/source/launcher/ttio/scdssdhc.h deleted file mode 100644 index 41ed5f16..00000000 --- a/arm9/source/launcher/ttio/scdssdhc.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - SuperCard DSONE - Card IO routines - - Copyright (C) 2006 SuperCard - Copyright (C) 2023 lifehackerhansol - - SPDX-License-Identifier: Zlib -*/ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "libtwl_card.h" - -#ifndef NULL - #define NULL 0 -#endif - -// libtwl workaround -// Certain DSTT clones need bytewise access to MCCMD -#define REG_SCDS_MCCMD ((vu8*)®_MCCMD0) - -// SCDS defines -// SCDS ROMCTRL flags -#define SCDS_CTRL_BASE (MCCNT1_ENABLE | MCCNT1_RESET_OFF | MCCNT1_LATENCY2(24) | MCCNT1_LATENCY1(0)) -#define SCDS_CTRL_READ_4B (SCDS_CTRL_BASE | MCCNT1_LEN_4) -#define SCDS_CTRL_READ_512B (SCDS_CTRL_BASE | MCCNT1_LEN_512) -#define SCDS_CTRL_WRITE_4B (SCDS_CTRL_BASE | MCCNT1_DIR_WRITE | MCCNT1_LEN_4) -#define SCDS_CTRL_WRITE_512B (SCDS_CTRL_BASE | MCCNT1_DIR_WRITE | MCCNT1_LEN_512) - -#define SCDS_CTRL_SD_LOW_CLK_LATENCY 0x1000 - -// SCDS CARD_COMMANDs - -/* - SRAM commands - - Command structure: - AA BB BB BB BB 00 00 00 - AA = command - BBBBBBBB = address -*/ -#define SCDS_CMD_SRAM_READ_DATA (0x70) -#define SCDS_CMD_SRAM_WRITE_DATA (0x71) - -// FIFO commands -#define SCDS_CMD_FIFO_BUSY (0x80) -#define SCDS_CMD_FIFO_READ_DATA (0x81) -#define SCDS_CMD_FIFO_WRITE_DATA (0x82) - -/* - SD host modes - Used with 0x51 command, see below -*/ -enum SCDS_SD_HOST_MODES { - SCDS_SD_HOST_NORESPONSE = 0, - SCDS_SD_HOST_READ_4B = 1, - SCDS_SD_HOST_READ_4B_MULTI = 2, // use mode 3 to continue this read - SCDS_SD_HOST_NEXT_4B = 3, - SCDS_SD_HOST_SEND_CLK = 4, - SCDS_SD_HOST_SEND_STOP_CLK = 5, - SCDS_SD_HOST_READ_DATABLOCK = 6, - SCDS_SD_HOST_NEXT_DATABLOCK = 7, - SCDS_SD_HOST_CMD17_READ_DATA = 8, // Send SDIO CMD17 & read data - SCDS_SD_HOST_CMD18_READ_DATA = 9, // Send SDIO CMD18 & read data until stop - SCDS_SD_HOST_COMMIT_FIFO_DATA = 0xA, // commit data in FIFO to SD card - SCDS_SD_HOST_CMD24_WRITE_DATA = 0xB, // Send SDIO CMD24 & send data in SRAM buffer - SCDS_SD_HOST_WAIT_BUSY = 0xC // wait until data transfer ends -}; - -/* - SD host related commands - - Note: - While this is where the SDIO happens, it isn't always SDIO - Thus, it can sometimes be 0 - - Command structure: - 51 AA AA AA AA BB CC 00 - AAAAAAAA = SDIO parameter - BB = SDIO command - CC = SD host mode, see SCDS_SD_HOST_MODES enum -*/ -#define SCDS_CMD_SD_HOST_PARAM (0x51) - -// SD host misc commands -// return 0 == idle -// return non-0 == not idle -#define SCDS_CMD_SD_HOST_BUSY (0x50) - -// Gets response of SD_HOST commands, if the sent mode is 1 or 2 -#define SCDS_CMD_SD_HOST_RESPONSE (0x52) -// Stops SD host data transfer -#define SCDS_CMD_SD_WRITE_END (0x56) - -// Sends CMD17 -#define SCDS_CMD_SD_READ_SINGLE_BLOCK (0x53) -// Sends CMD18 -#define SCDS_CMD_SD_READ_MULTI_BLOCK (0x54) - -/* - SD host control registers - The 0x5F sets raw registers related to the SD host, which is a single u8. - Bits: - 0: Reset - 1: Set 400k low clk - 2: Use 0xB7 as alternative of 0x5B for ROM reads - 3: Set SDHC mode - 4-5: 1 - 6-7: 0 -*/ -#define SCDS_SD_HOST_REG_RESET BIT(0) -#define SCDS_SD_HOST_REG_400KHZ_CLK BIT(1) -#define SCDS_SD_HOST_REG_CLEAN_ROM_MODE BIT(2) -#define SCDS_SD_HOST_REG_SDHC BIT(3) - -// Command to write to host register -#define SCDS_CMD_SD_HOST_SET_REGISTER (0x5F) - -// user API -bool SCDS_SDInitialize(void); -void SCDS_SDReadSingleSector(u32 sector, void *buffer); -void SCDS_SDReadMultiSector(u32 sector, void *buffer, u32 num_sectors); -void SCDS_SDWriteSingleSector(u32 sector, const void *buffer); -void SCDS_SDWriteMultiSector(u32 sector, const void *buffer, u32 num_sectors); - -#ifdef __cplusplus -} -#endif diff --git a/arm9/source/launcher/ttio/waitByLoop.s b/arm9/source/launcher/ttio/waitByLoop.s deleted file mode 100644 index e457b97c..00000000 --- a/arm9/source/launcher/ttio/waitByLoop.s +++ /dev/null @@ -1,18 +0,0 @@ -@ -@ Copyright (C) 2024 lifehackerhansol -@ -@ SPDX-License-Identifier: zlib -@ - -#include - - .syntax unified - .arm - -@ void waitByLoop(u32 count) -@ because we can't use swi 0x3 in DLDI - -BEGIN_ASM_FUNC waitByLoop - subs r0, r0, #1 - bgt waitByLoop - bx lr diff --git a/arm9/source/mainwnd.cpp b/arm9/source/mainwnd.cpp index 2de48010..3210b77e 100644 --- a/arm9/source/mainwnd.cpp +++ b/arm9/source/mainwnd.cpp @@ -588,13 +588,6 @@ void cMainWnd::setParam(void) { settingWnd.addSettingItem(LANG("nds bootstrap", "loader"), _values, gs().pico); } -#ifdef __KERNEL_LAUNCHER_SUPPORT__ - _values.clear(); - _values.push_back("Kernel"); - _values.push_back("nds-bootstrap"); - settingWnd.addSettingItem(LANG("loader", "text"), _values, gs().romLauncher); -#endif - // page 5: other settingWnd.addSettingTab(LANG("gba settings", "title")); _values.clear(); diff --git a/arm9/source/rominfownd.cpp b/arm9/source/rominfownd.cpp index 2d59c834..eb562b25 100644 --- a/arm9/source/rominfownd.cpp +++ b/arm9/source/rominfownd.cpp @@ -259,7 +259,6 @@ void cRomInfoWnd::setRomInfo(const DSRomInfo& romInfo) { addCode(); _buttonSaveType.show(); if (gs().cheatDB) _buttonCheats.show(); - if (gs().pico) _buttonCheats.hide(); } else if (_romInfo.isGbaRom()) { _buttonFlash.show(); _buttonSaveType.setText("\x03 " + LANG("exp window", "flash to nor")); diff --git a/arm9/source/romlauncher.cpp b/arm9/source/romlauncher.cpp index 9372dbd4..8122f60f 100644 --- a/arm9/source/romlauncher.cpp +++ b/arm9/source/romlauncher.cpp @@ -7,16 +7,14 @@ #include #include "romlauncher.h" -#include "cheatwnd.h" +#include "cheat.h" #include "exptools.h" #include "flags.h" #include "language.h" -#include "launcher/AcekardLauncher.h" #include "launcher/HomebrewLauncher.h" #include "launcher/ILauncher.h" #include "launcher/NdsBootstrapLauncher.h" -#include "launcher/TopToyLauncher.h" #include "launcher/DSpicoLauncher.h" static SAVE_TYPE PrefillGame(u32 aGameCode) { @@ -231,10 +229,11 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool if (aRomInfo.saveInfo().isDownloadPlay()) flags |= PATCH_DOWNLOAD_PLAY; if (aRomInfo.saveInfo().isCheat()) { u32 gameCode, crc32; - if (cCheatWnd::romData(aFullPath, gameCode, crc32)) { + + if (cCheat::romData(aFullPath, gameCode, crc32)) { FILE* dat = fopen((SFN_CHEATS).c_str(), "rb"); if (dat) { - if (cCheatWnd::searchCheatData(dat, gameCode, crc32, cheatOffset, cheatSize)) { + if (cCheat::searchCheatData(dat, gameCode, crc32, cheatOffset, cheatSize)) { flags |= PATCH_CHEATS; } fclose(dat); diff --git a/arm9/source/saves/ROMList.cpp b/arm9/source/saves/ROMList.cpp index e000947c..f266aca2 100644 --- a/arm9/source/saves/ROMList.cpp +++ b/arm9/source/saves/ROMList.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2024 melonDS team + Copyright 2016-2026 melonDS team This file is part of melonDS. @@ -20,6 +20,12 @@ #include "ROMList.h" +/* AKMENU CHANGES START - don't namespace ROMList */ +/* +namespace melonDS +{ +*/ +/* AKMENU CHANGES END - don't namespace ROMList */ const ROMListEntry ROMList[] = { {0x41464141, 0x00800000, 0x00000004}, @@ -898,7 +904,7 @@ const ROMListEntry ROMList[] = {0x45455742, 0x04000000, 0x00000001}, {0x45455743, 0x01000000, 0x00000002}, {0x45455842, 0x04000000, 0x00000001}, - {0x45455943, 0x08000000, 0x00000002}, + {0x45455943, 0x08000000, 0x00000003}, {0x45455A41, 0x04000000, 0x00000006}, {0x45455A42, 0x00800000, 0x00000001}, {0x45463242, 0x00800000, 0x00000001}, @@ -6803,3 +6809,9 @@ const ROMListEntry ROMList[] = }; const size_t ROMListEntryCount = sizeof(ROMList) / sizeof(ROMListEntry); + +/* AKMENU CHANGES START - don't namespace ROMList */ +/* +} +*/ +/* AKMENU CHANGES END - don't namespace ROMList */ diff --git a/arm9/source/saves/ROMList.h b/arm9/source/saves/ROMList.h index 372c01bd..f5ad2a88 100644 --- a/arm9/source/saves/ROMList.h +++ b/arm9/source/saves/ROMList.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2024 melonDS team + Copyright 2016-2026 melonDS team This file is part of melonDS. @@ -25,6 +25,12 @@ #include +/* AKMENU CHANGES START - don't namespace ROMList */ +/* +namespace melonDS +{ +*/ +/* AKMENU CHANGES END - don't namespace ROMList */ struct ROMListEntry { u32 GameCode; @@ -38,4 +44,9 @@ extern const ROMListEntry ROMList[]; /// The number of elements in \c ROMList. extern const size_t ROMListEntryCount; -#endif // ROMLIST_H +/* AKMENU CHANGES START - don't namespace ROMList */ +/* +} +*/ +/* AKMENU CHANGES END - don't namespace ROMList */ +#endif // ROMLIST_H diff --git a/arm9/source/version.h b/arm9/source/version.h index 00504972..f985ad63 100644 --- a/arm9/source/version.h +++ b/arm9/source/version.h @@ -10,18 +10,6 @@ #define AKMENU_VERSION_MAIN "2" #define AKMENU_VERSION_SUB "0.5" -#ifndef __KERNEL_LAUNCHER_SUPPORT__ #define AKMENU_LOADER_NAME "nds-bootstrap" #define AKMENU_PICO_NAME "Pico-Loader" #define AKMENU_LOADER_VERSION "" -#else // __KERNEL_LAUNCHER_SUPPORT__ - -// Loader versions - may not be accurate -#if defined(__AKLOADER_AK2__) -#define AKMENU_LOADER_NAME "BL2CK" -#define AKMENU_LOADER_VERSION "1.31.0" -#else // fallback for acekard -#define AKMENU_LOADER_NAME "wood" -#define AKMENU_LOADER_VERSION "1.62" -#endif // __AKLOADER_AK2__ -#endif // __KERNEL_LAUNCHER_SUPPORT__ diff --git a/share/fifotool.h b/share/fifotool.h index ff7a034d..0201643a 100644 --- a/share/fifotool.h +++ b/share/fifotool.h @@ -18,7 +18,6 @@ #define MENU_MSG_BRIGHTNESS_SET2 10 #define MENU_MSG_BRIGHTNESS_SET3 11 #define MENU_MSG_SHUTDOWN 12 -#define MENU_MSG_ARM7_REBOOT_TT 13 -#define MENU_MSG_ARM7_REBOOT_PICOLOADER 14 -#define MENU_MSG_IS_SD_INSERTED 15 -#define MENU_MSG_IS_3DS 16 \ No newline at end of file +#define MENU_MSG_ARM7_REBOOT_PICOLOADER 13 +#define MENU_MSG_IS_SD_INSERTED 14 +#define MENU_MSG_IS_3DS 15