From 65a5ad65911a3e3081651a73410944123d9c168c Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Tue, 7 Feb 2023 22:08:31 +0000 Subject: [PATCH] cxbxkrnl: avoid region patching loaded titles While it sounds ideal from a UX standpoint, region patching does break a number of titles that would otherwise work. Instead, show a warning that it may not be compatible with instructions on how to configure region settings in eeprom. Allow the user to attempt to run the title anyway, if the game does not do it's own region checking, it will most likely just work regardless. --- src/common/xbe/Xbe.cpp | 20 ++++++++++++-------- src/common/xbe/Xbe.h | 2 +- src/core/kernel/init/CxbxKrnl.cpp | 23 +++++++++++++++++++++++ src/core/kernel/init/KrnlPatches.hpp | 11 ++--------- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/common/xbe/Xbe.cpp b/src/common/xbe/Xbe.cpp index 62641103c..36b93ab5c 100644 --- a/src/common/xbe/Xbe.cpp +++ b/src/common/xbe/Xbe.cpp @@ -732,25 +732,29 @@ void Xbe::PurgeBadChar(std::string& s, const std::string& illegalChars) } } -const char *Xbe::GameRegionToString() +const char *Xbe::GameRegionToString(uint32_t dwRegionFlags) { + if (!dwRegionFlags) { + dwRegionFlags = m_Certificate.dwGameRegion; + } + const char *Region_text[] = { - "Unknown", "NTSC", "JAP", "NTSC+JAP", - "PAL", "PAL+NTSC", "PAL+JAP", "Region Free", - "DEBUG", "NTSC (DEBUG)", "JAP (DEBUG)", "NTSC+JAP (DEBUG)", - "PAL (DEBUG)", "PAL+NTSC (DEBUG)", "PAL+JAP (DEBUG)", "Region Free (DEBUG)" + "Unknown", "NTSC", "JAPAN", "NTSC+JAPAN", + "PAL", "PAL+NTSC", "PAL+JAPAN", "Region Free", + "DEBUG", "NTSC (DEBUG)", "JAPAN (DEBUG)", "NTSC+JAPAN (DEBUG)", + "PAL (DEBUG)", "PAL+NTSC (DEBUG)", "PAL+JAPAN (DEBUG)", "Region Free (DEBUG)" }; const uint32_t all_regions = XBEIMAGE_GAME_REGION_NA | XBEIMAGE_GAME_REGION_JAPAN | XBEIMAGE_GAME_REGION_RESTOFWORLD | XBEIMAGE_GAME_REGION_MANUFACTURING; - if(m_Certificate.dwGameRegion & ~all_regions) { + if(dwRegionFlags & ~all_regions) { return "REGION ERROR"; } - uint8_t index = (m_Certificate.dwGameRegion & XBEIMAGE_GAME_REGION_MANUFACTURING) ? 0x8 : 0; - index |= (m_Certificate.dwGameRegion & 0x7); + uint8_t index = (dwRegionFlags & XBEIMAGE_GAME_REGION_MANUFACTURING) ? 0x8 : 0; + index |= (dwRegionFlags & 0x7); return Region_text[index]; } diff --git a/src/common/xbe/Xbe.h b/src/common/xbe/Xbe.h index 8f960ccc5..1291a98a8 100644 --- a/src/common/xbe/Xbe.h +++ b/src/common/xbe/Xbe.h @@ -81,7 +81,7 @@ class Xbe : public Error void PurgeBadChar(std::string& s, const std::string& illegalChars = "\\/:?\"<>|"); // Convert game region field to string - const char *GameRegionToString(); + const char *GameRegionToString(uint32_t dwRegionFlags = 0); XbeType GetXbeType(); diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index 4f325ed7b..94f7db80b 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -1409,6 +1409,29 @@ static void CxbxrKrnlInitHacks() // See: https://multimedia.cx/eggs/xbox-sphinx-protocol/ ApplyMediaPatches(); + // Verify that the emulator region matches the game region, if not, show a warning + // that it may not work. + if (!(g_pCertificate->dwGameRegion & EEPROM->EncryptedSettings.GameRegion)) + { + auto expected = CxbxKrnl_Xbe->GameRegionToString(); + auto actual = CxbxKrnl_Xbe->GameRegionToString(EEPROM->EncryptedSettings.GameRegion); + + std::stringstream ss; + ss << "The loaded title is designed for region: " << expected << "\n"; + ss << "However Cxbx-Reloaded is configured as: " << actual << "\n\n"; + ss << "This means that you may encounter emulation issues\n\n"; + ss << "You can fix this by changing your emulated Xbox region in EEPROM Settings\n\n"; + ss << "Please do not submit bug reports that result from incorrect region flags\n\n"; + ss << "Would you like to attempt emulation anyway?"; + + PopupReturn ret = PopupWarningEx(nullptr, PopupButtons::YesNo, PopupReturn::No, ss.str().c_str()); + if (ret != PopupReturn::Yes) + { + CxbxrShutDown(); + } + } + + // Chihiro games require more patches // The chihiro BIOS does this to bypass XAPI cache init if (g_bIsChihiro) { diff --git a/src/core/kernel/init/KrnlPatches.hpp b/src/core/kernel/init/KrnlPatches.hpp index 3789f659d..bbd18740b 100644 --- a/src/core/kernel/init/KrnlPatches.hpp +++ b/src/core/kernel/init/KrnlPatches.hpp @@ -57,15 +57,8 @@ static void ApplyMediaPatches() | XBEIMAGE_MEDIA_TYPE_DVD_5_RO | XBEIMAGE_MEDIA_TYPE_DVD_9_RO | XBEIMAGE_MEDIA_TYPE_DVD_5_RW - | XBEIMAGE_MEDIA_TYPE_DVD_9_RW - ; - // Patch the XBE Header to allow running on all regions - g_pCertificate->dwGameRegion = 0 - | XBEIMAGE_GAME_REGION_MANUFACTURING - | XBEIMAGE_GAME_REGION_NA - | XBEIMAGE_GAME_REGION_JAPAN - | XBEIMAGE_GAME_REGION_RESTOFWORLD - ; + | XBEIMAGE_MEDIA_TYPE_DVD_9_RW; + // Patch the XBE Security Flag // This field is only present if the Xbe Size is >= than our Certificate Structure // This works as our structure is large enough to fit the newer certificate size,