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,