From 664a0247fa610b03975ee1b2e761cffefb3feb87 Mon Sep 17 00:00:00 2001 From: Mena Date: Sun, 13 Sep 2026 12:35:06 -0400 Subject: [PATCH 1/2] Read banner and save info from NDZ front matter --- arm9/source/dsrom.cpp | 32 ++++++++++++++++++++++++++++++++ arm9/source/dsrom.h | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/arm9/source/dsrom.cpp b/arm9/source/dsrom.cpp index b8f29ac7..941516be 100644 --- a/arm9/source/dsrom.cpp +++ b/arm9/source/dsrom.cpp @@ -20,6 +20,10 @@ #include "unknown_nds_banner_bin.h" namespace { +constexpr long ndzBannerOffset = 0x10; +constexpr long ndzGameCodeOffset = 0x2410; +constexpr long ndzHeaderCrcOffset = 0x2418; + const u16* iconBackground() { static u16 background[32 * 32]; static int cachedSource = -1; @@ -49,6 +53,7 @@ DSRomInfo& DSRomInfo::operator=(const DSRomInfo& src) { _isDSiWare = src._isDSiWare; _isModernHomebrew = src._isModernHomebrew; _isGbaRom = src._isGbaRom; + _isNdz = src._isNdz; _fileName = src._fileName; _romVersion = src._romVersion; _extIcon = src._extIcon; @@ -60,6 +65,7 @@ bool DSRomInfo::loadDSRomInfo(const std::string& filename, bool loadBanner) { _isHomebrew = EFalse; _isDSiWare = EFalse; _isModernHomebrew = EFalse; + _isNdz = false; FILE* f = fopen(filename.c_str(), "rb"); if (NULL == f) // 锟斤拷锟侥硷拷失锟斤拷 { @@ -76,6 +82,27 @@ bool DSRomInfo::loadDSRomInfo(const std::string& filename, bool loadBanner) { return false; } + if (0 == memcmp(&header, "NDZ1", 4)) { + _isNdz = true; + _isDSRom = ETrue; + fseek(f, ndzGameCodeOffset, SEEK_SET); + fread(_saveInfo.gameCode, 1, sizeof(_saveInfo.gameCode), f); + fseek(f, ndzHeaderCrcOffset, SEEK_SET); + fread(&_saveInfo.gameCRC, 1, sizeof(_saveInfo.gameCRC), f); + saveManager().updateSaveInfoByInfo(_saveInfo); + + tNDSBanner banner; + fseek(f, ndzBannerOffset, SEEK_SET); + if (sizeof(tNDSBanner) == fread(&banner, 1, sizeof(banner), f) && + swiCRC16(0xffff, banner.icon, 0x840 - 32) == banner.crc) { + memcpy(&_banner, &banner, sizeof(_banner)); + } else { + loadBannerIcon(_banner, "nds_banner.bin", nds_banner_bin); + } + fclose(f); + return true; + } + if (header.unitCode == 0x03) { _isDSiWare = ETrue; } @@ -357,6 +384,11 @@ bool DSRomInfo::isGbaRom(void) { return (_isGbaRom == ETrue) ? true : false; } +bool DSRomInfo::isNdz(void) { + load(); + return _isNdz; +} + void DSRomInfo::setExtIcon(const std::string& aValue) { _extIcon = fileIcons().Icon(aValue); }; diff --git a/arm9/source/dsrom.h b/arm9/source/dsrom.h index 3c9e3fd2..01f3c169 100644 --- a/arm9/source/dsrom.h +++ b/arm9/source/dsrom.h @@ -26,6 +26,7 @@ class DSRomInfo { TBool _isHomebrew; TBool _isModernHomebrew; TBool _isGbaRom; + bool _isNdz; std::string _fileName; s32 _extIcon; u8 _romVersion; @@ -37,7 +38,7 @@ class DSRomInfo { public: DSRomInfo() - : _isDSRom(EFalse), _isDSiWare(EFalse), _isHomebrew(EFalse), _isModernHomebrew(EFalse), _isGbaRom(EFalse), _extIcon(-1), _romVersion(0) { + : _isDSRom(EFalse), _isDSiWare(EFalse), _isHomebrew(EFalse), _isModernHomebrew(EFalse), _isGbaRom(EFalse), _isNdz(false), _extIcon(-1), _romVersion(0) { // memcpy(&_banner,unknown_banner_bin,unknown_banner_bin_size); memset(&_banner, 0, sizeof(_banner)); memset(&_saveInfo, 0, sizeof(_saveInfo)); @@ -56,6 +57,7 @@ class DSRomInfo { bool isHomebrew(void); bool isModernHomebrew(void); bool isGbaRom(void); + bool isNdz(void); DSRomInfo& operator=(const DSRomInfo& src); void MayBeDSRom(const std::string& filename) { _isDSRom = EMayBe; From fafe42f1a2395881b75403462c5b20bb8462e69b Mon Sep 17 00:00:00 2001 From: Mena Date: Sun, 13 Sep 2026 12:35:06 -0400 Subject: [PATCH 2/2] Launch NDZ roms with Pico-Loader --- arm9/source/romlauncher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arm9/source/romlauncher.cpp b/arm9/source/romlauncher.cpp index 1bc8dc7f..eea9e3f3 100644 --- a/arm9/source/romlauncher.cpp +++ b/arm9/source/romlauncher.cpp @@ -250,7 +250,7 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool u8 loader = aRomInfo.saveInfo().getLoader(); // loader = 0: pico, 1: nds-bootstrap, 2: global - if(((gs().pico && loader == 2) || loader == 0) && aFullPath[0] != 's'){ //roms can only be launched from the sd with nds-bootstrap + if(aRomInfo.isNdz() || (((gs().pico && loader == 2) || loader == 0) && aFullPath[0] != 's')){ //roms can only be launched from the sd with nds-bootstrap launcher = new DSpicoLauncher(); } else {