diff --git a/src/core/bios.cpp b/src/core/bios.cpp index 7fceb571f..5ba8b3222 100644 --- a/src/core/bios.cpp +++ b/src/core/bios.cpp @@ -252,4 +252,20 @@ bool IsValidPSExeHeader(const PSEXEHeader& header, u32 file_size) return true; } +DiscRegion GetPSExeDiscRegion(const PSEXEHeader& header) +{ + static constexpr char ntsc_u_id[] = "Sony Computer Entertainment Inc. for North America area"; + static constexpr char ntsc_j_id[] = "Sony Computer Entertainment Inc. for Japan area"; + static constexpr char pal_id[] = "Sony Computer Entertainment Inc. for Europe area"; + + if (std::memcmp(header.marker, ntsc_u_id, sizeof(ntsc_u_id) - 1) == 0) + return DiscRegion::NTSC_U; + else if (std::memcmp(header.marker, ntsc_j_id, sizeof(ntsc_j_id) - 1) == 0) + return DiscRegion::NTSC_J; + else if (std::memcmp(header.marker, pal_id, sizeof(pal_id) - 1) == 0) + return DiscRegion::PAL; + else + return DiscRegion::Other; +} + } // namespace BIOS diff --git a/src/core/bios.h b/src/core/bios.h index f0c569f32..0068f0905 100644 --- a/src/core/bios.h +++ b/src/core/bios.h @@ -69,4 +69,5 @@ bool PatchBIOSFastBoot(u8* image, u32 image_size, const Hash& hash); bool PatchBIOSForEXE(u8* image, u32 image_size, u32 r_pc, u32 r_gp, u32 r_sp, u32 r_fp); bool IsValidPSExeHeader(const PSEXEHeader& header, u32 file_size); +DiscRegion GetPSExeDiscRegion(const PSEXEHeader& header); } // namespace BIOS \ No newline at end of file diff --git a/src/core/psf_loader.cpp b/src/core/psf_loader.cpp index efff009f2..33a01f54f 100644 --- a/src/core/psf_loader.cpp +++ b/src/core/psf_loader.cpp @@ -1,4 +1,5 @@ #include "psf_loader.h" +#include "bios.h" #include "common/assert.h" #include "common/file_system.h" #include "common/log.h" @@ -159,6 +160,16 @@ bool File::Load(const char* path) } } + // Region detection. + m_region = BIOS::GetPSExeDiscRegion(*reinterpret_cast(m_program_data.data())); + + // _refresh tag takes precedence. + const int refresh_tag = GetTagInt("_region", 0); + if (refresh_tag == 60) + m_region = DiscRegion::NTSC_U; + else if (refresh_tag == 50) + m_region = DiscRegion::PAL; + return true; } diff --git a/src/core/psf_loader.h b/src/core/psf_loader.h index 1c242c800..9e6c55fcf 100644 --- a/src/core/psf_loader.h +++ b/src/core/psf_loader.h @@ -27,6 +27,7 @@ public: ALWAYS_INLINE const ProgramData& GetProgramData() const { return m_program_data; } ALWAYS_INLINE const TagMap& GetTagMap() const { return m_tags; } + ALWAYS_INLINE DiscRegion GetRegion() const { return m_region; } std::optional GetTagString(const char* tag_name) const; std::optional GetTagInt(const char* tag_name) const; @@ -46,6 +47,7 @@ private: ProgramData m_program_data; TagMap m_tags; + DiscRegion m_region = DiscRegion::Other; }; bool Load(const char* path);