GameList: Support detecting region from system area of CDROM

More accurate than basing it off the code, and better support for
homebrew discs.
This commit is contained in:
Connor McLaughlin 2019-12-13 16:51:36 +10:00
parent f77721b84d
commit 5fd421860a
2 changed files with 29 additions and 1 deletions

View file

@ -150,8 +150,34 @@ std::optional<ConsoleRegion> GameList::GetRegionForCode(std::string_view code)
return std::nullopt; return std::nullopt;
} }
std::optional<ConsoleRegion> 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<ConsoleRegion> GameList::GetRegionForImage(CDImage* cdi) std::optional<ConsoleRegion> GameList::GetRegionForImage(CDImage* cdi)
{ {
std::optional<ConsoleRegion> system_area_region = GetRegionFromSystemArea(cdi);
if (system_area_region)
return system_area_region;
std::string code = GetGameCodeForImage(cdi); std::string code = GetGameCodeForImage(cdi);
if (code.empty()) if (code.empty())
return std::nullopt; return std::nullopt;
@ -240,6 +266,8 @@ bool GameList::GetGameListEntry(const char* path, GameListEntry* entry)
entry->path = path; entry->path = path;
entry->code = GetGameCodeForImage(cdi.get()); 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<u64>(CDImage::RAW_SECTOR_SIZE) * static_cast<u64>(cdi->GetLBACount()); entry->total_size = static_cast<u64>(CDImage::RAW_SECTOR_SIZE) * static_cast<u64>(cdi->GetLBACount());
entry->type = EntryType::Disc; entry->type = EntryType::Disc;
cdi.reset(); 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()); Log_WarningPrintf("'%s' not found in database", entry->code.c_str());
entry->title = entry->code; entry->title = entry->code;
entry->region = GetRegionForCode(entry->code).value_or(ConsoleRegion::NTSC_U);
} }
return true; return true;

View file

@ -46,6 +46,7 @@ public:
static std::string GetGameCodeForImage(CDImage* cdi); static std::string GetGameCodeForImage(CDImage* cdi);
static std::string GetGameCodeForPath(const char* image_path); static std::string GetGameCodeForPath(const char* image_path);
static std::optional<ConsoleRegion> GetRegionForCode(std::string_view code); static std::optional<ConsoleRegion> GetRegionForCode(std::string_view code);
static std::optional<ConsoleRegion> GetRegionFromSystemArea(CDImage* cdi);
static std::optional<ConsoleRegion> GetRegionForImage(CDImage* cdi); static std::optional<ConsoleRegion> GetRegionForImage(CDImage* cdi);
static std::optional<ConsoleRegion> GetRegionForPath(const char* image_path); static std::optional<ConsoleRegion> GetRegionForPath(const char* image_path);