From 19cce5960b204aef26477542cb399ec9df4ca8ca Mon Sep 17 00:00:00 2001 From: TY <47445484+R-YaTian@users.noreply.github.com> Date: Tue, 23 Dec 2025 22:08:55 +0800 Subject: [PATCH] Properly set the supported language, user language, and region based on the ROM's region (#38) --- arm7/source/loader/ConsoleRegion.h | 12 ++++ arm7/source/loader/NdsLoader.cpp | 112 +++++++++++++++++++++++++++-- arm7/source/loader/NdsLoader.h | 5 ++ arm7/source/loader/UserLanguage.h | 14 ++++ 4 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 arm7/source/loader/ConsoleRegion.h create mode 100644 arm7/source/loader/UserLanguage.h diff --git a/arm7/source/loader/ConsoleRegion.h b/arm7/source/loader/ConsoleRegion.h new file mode 100644 index 0000000..2adf528 --- /dev/null +++ b/arm7/source/loader/ConsoleRegion.h @@ -0,0 +1,12 @@ +#pragma once + +/// @brief Enum for DSi console region. +enum class ConsoleRegion +{ + Japan, + America, + Europe, + Australia, + China, + Korea +}; diff --git a/arm7/source/loader/NdsLoader.cpp b/arm7/source/loader/NdsLoader.cpp index 1aa21a7..61a2489 100644 --- a/arm7/source/loader/NdsLoader.cpp +++ b/arm7/source/loader/NdsLoader.cpp @@ -865,6 +865,10 @@ void NdsLoader::StartRom(BootMode bootMode) void NdsLoader::SetupTwlConfig() { + ConsoleRegion romRegion = GetRomRegion(_romHeader.gameCode); + // Set language based on rom region, TODO: allow user to override this via some config or so + UserLanguage userLang = GetLanguageByRomRegion(romRegion); + twl_config_t* twlConfig = (twl_config_t*)0x02000400; *(twl_config_t**)0x02FFFDFC = twlConfig; *(vu8*)0x02FFFDFA = 0x80; @@ -872,7 +876,7 @@ void NdsLoader::SetupTwlConfig() memset(twlConfig, 0, sizeof(twl_config_t)); twlConfig->configFlags = 0x0100000F; twlConfig->country = 0x4E; - twlConfig->language = TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x64]; + twlConfig->language = static_cast(userLang); twlConfig->rtcYear = TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x66]; twlConfig->rtcOffset = *(s64*)&TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x68]; twlConfig->eulaAgreeVersion[0] = 1; @@ -880,7 +884,7 @@ void NdsLoader::SetupTwlConfig() twlConfig->alarmMinute = TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x53]; twlConfig->alarmEnable = TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x56]; twlConfig->systemMenuUsedTitleSlots = 9; - twlConfig->systemMenuUsedTitleSlots = 30; + twlConfig->systemMenuFreeTitleSlots = 30; twlConfig->field24 = 3; memcpy(&twlConfig->touchCalibrationX1Adc, &TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x58], 0xC); twlConfig->field3C = 0x0201209C; @@ -906,9 +910,10 @@ void NdsLoader::SetupTwlConfig() } *(vu16*)0x020005E2 = swi_getCrc16(0xFFFF, (void*)0x020005E4, 0xC); - *(vu32*)0x02FFFD68 = 0x3E; // supported languages + // Set bitmask for supported languages + *(vu32*)0x02FFFD68 = GetSupportedLanguagesByRegion(romRegion); *(vu32*)0x02FFFD6C = 0; - *(vu8*)0x02FFFD70 = 2; // region, 2 = europe + *(vu8*)0x02FFFD70 = static_cast(romRegion); // region } void NdsLoader::SetDeviceListEntry(dsi_devicelist_entry_t& deviceListEntry, @@ -1011,3 +1016,102 @@ bool NdsLoader::TryDecryptSecureArea() LOG_DEBUG("Decrypted secure area\n"); return true; } + +ConsoleRegion NdsLoader::GetRomRegion(u32 gameCode) +{ + u8 gameRegionCode = (gameCode >> 24) & 0xFF; + if (gameRegionCode != 'A' && gameRegionCode != 'O') + { + // Determine region by TID + if (gameRegionCode == 'J') + { + return ConsoleRegion::Japan; + } + else if (gameRegionCode == 'E' || gameRegionCode == 'T') + { + return ConsoleRegion::America; + } + else if (gameRegionCode == 'P' || gameRegionCode == 'V') + { + return ConsoleRegion::Europe; + } + else if (gameRegionCode == 'U') + { + return ConsoleRegion::Australia; + } + else if (gameRegionCode == 'C') + { + return ConsoleRegion::China; + } + else if (gameRegionCode== 'K') + { + return ConsoleRegion::Korea; + } + } + + return ConsoleRegion::Europe; // Default to EUR +} + +UserLanguage NdsLoader::GetLanguageByRomRegion(ConsoleRegion romRegion) +{ + UserLanguage userLang = static_cast(TWL_SHARED_MEMORY->ntrSharedMem.firmwareUserData[0x64] & 0x07); + + if (romRegion == ConsoleRegion::Japan) + { + return UserLanguage::Japanese; + } + else if (romRegion == ConsoleRegion::America && + (userLang != UserLanguage::English || + userLang != UserLanguage::French || + userLang != UserLanguage::Spanish)) + { + return UserLanguage::English; + } + else if (romRegion == ConsoleRegion::Europe && userLang < UserLanguage::English && userLang > UserLanguage::Spanish) + { + return UserLanguage::English; + } + else if (romRegion == ConsoleRegion::China) + { + return UserLanguage::Chinese; + } + else if (romRegion == ConsoleRegion::Korea) + { + return UserLanguage::Korean; + } + + return userLang; +} + +u32 NdsLoader::GetSupportedLanguagesByRegion(ConsoleRegion region) +{ + switch (region) + { + case ConsoleRegion::Japan: + { + return 0x01; + } + case ConsoleRegion::America: + { + return 0x26; + } + case ConsoleRegion::Europe: + { + return 0x3E; + } + case ConsoleRegion::Australia: + { + return 0x02; + } + case ConsoleRegion::China: + { + return 0x40; + } + case ConsoleRegion::Korea: + { + return 0x80; + } + } + + return 0x3E; +} diff --git a/arm7/source/loader/NdsLoader.h b/arm7/source/loader/NdsLoader.h index 7c284e2..416faa4 100644 --- a/arm7/source/loader/NdsLoader.h +++ b/arm7/source/loader/NdsLoader.h @@ -3,6 +3,8 @@ #include "ndsHeader.h" #include "DsiWareSaveArranger.h" #include "BootMode.h" +#include "ConsoleRegion.h" +#include "UserLanguage.h" struct dsi_devicelist_entry_t; @@ -72,4 +74,7 @@ private: void InsertArgv(); bool TrySetupDsiWareSave(); bool TryDecryptSecureArea(); + ConsoleRegion GetRomRegion(u32 gameCode); + UserLanguage GetLanguageByRomRegion(ConsoleRegion romRegion); + u32 GetSupportedLanguagesByRegion(ConsoleRegion region); }; diff --git a/arm7/source/loader/UserLanguage.h b/arm7/source/loader/UserLanguage.h new file mode 100644 index 0000000..fa0ec26 --- /dev/null +++ b/arm7/source/loader/UserLanguage.h @@ -0,0 +1,14 @@ +#pragma once + +/// @brief Enum for DSi user language. +enum class UserLanguage +{ + Japanese, + English, + French, + German, + Italian, + Spanish, + Chinese, + Korean +};