From 5fd421860a9608957fcb1bc597b16462b5e8ac25 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 13 Dec 2019 16:51:36 +1000 Subject: [PATCH] GameList: Support detecting region from system area of CDROM More accurate than basing it off the code, and better support for homebrew discs. --- src/core/game_list.cpp | 29 ++++++++++++++++++++++++++++- src/core/game_list.h | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/core/game_list.cpp b/src/core/game_list.cpp index 0171adcab..c93fdec89 100644 --- a/src/core/game_list.cpp +++ b/src/core/game_list.cpp @@ -150,8 +150,34 @@ std::optional GameList::GetRegionForCode(std::string_view code) return std::nullopt; } +std::optional GameList::GetRegionFromSystemArea(CDImage* cdi) +{ + // The license code is on sector 4 of the disc. + u8 sector[CDImage::DATA_SECTOR_SIZE]; + if (!cdi->Seek(1, 4) || cdi->Read(CDImage::ReadMode::DataOnly, 1, sector) != 1) + return std::nullopt; + + static constexpr char ntsc_u_string[] = " Licensed by Sony Computer Entertainment Amer ica "; + static constexpr char ntsc_j_string[] = " Licensed by Sony Computer Entertainment Inc."; + static constexpr char pal_string[] = " Licensed by Sony Computer Entertainment Euro pe"; + + // subtract one for the terminating null + if (std::equal(ntsc_u_string, ntsc_u_string + countof(ntsc_u_string) - 1, sector)) + return ConsoleRegion::NTSC_U; + else if (std::equal(ntsc_j_string, ntsc_j_string + countof(ntsc_j_string) - 1, sector)) + return ConsoleRegion::NTSC_J; + else if (std::equal(pal_string, pal_string + countof(pal_string) - 1, sector)) + return ConsoleRegion::PAL; + + return std::nullopt; +} + std::optional GameList::GetRegionForImage(CDImage* cdi) { + std::optional system_area_region = GetRegionFromSystemArea(cdi); + if (system_area_region) + return system_area_region; + std::string code = GetGameCodeForImage(cdi); if (code.empty()) return std::nullopt; @@ -240,6 +266,8 @@ bool GameList::GetGameListEntry(const char* path, GameListEntry* entry) entry->path = path; entry->code = GetGameCodeForImage(cdi.get()); + entry->region = + GetRegionFromSystemArea(cdi.get()).value_or(GetRegionForCode(entry->code).value_or(ConsoleRegion::NTSC_U)); entry->total_size = static_cast(CDImage::RAW_SECTOR_SIZE) * static_cast(cdi->GetLBACount()); entry->type = EntryType::Disc; cdi.reset(); @@ -254,7 +282,6 @@ bool GameList::GetGameListEntry(const char* path, GameListEntry* entry) { Log_WarningPrintf("'%s' not found in database", entry->code.c_str()); entry->title = entry->code; - entry->region = GetRegionForCode(entry->code).value_or(ConsoleRegion::NTSC_U); } return true; diff --git a/src/core/game_list.h b/src/core/game_list.h index 8b07c9d11..6f797cb8b 100644 --- a/src/core/game_list.h +++ b/src/core/game_list.h @@ -46,6 +46,7 @@ public: static std::string GetGameCodeForImage(CDImage* cdi); static std::string GetGameCodeForPath(const char* image_path); static std::optional GetRegionForCode(std::string_view code); + static std::optional GetRegionFromSystemArea(CDImage* cdi); static std::optional GetRegionForImage(CDImage* cdi); static std::optional GetRegionForPath(const char* image_path);