GameList: Seperate disc region and console region
This commit is contained in:
parent
e8a5259e68
commit
e0a339ca96
|
@ -127,7 +127,7 @@ std::string GameList::GetGameCodeForImage(CDImage* cdi)
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ConsoleRegion> GameList::GetRegionForCode(std::string_view code)
|
DiscRegion GameList::GetRegionForCode(std::string_view code)
|
||||||
{
|
{
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
for (size_t pos = 0; pos < code.length(); pos++)
|
for (size_t pos = 0; pos < code.length(); pos++)
|
||||||
|
@ -140,21 +140,21 @@ std::optional<ConsoleRegion> GameList::GetRegionForCode(std::string_view code)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefix == "sces" || prefix == "sced" || prefix == "sles" || prefix == "sled")
|
if (prefix == "sces" || prefix == "sced" || prefix == "sles" || prefix == "sled")
|
||||||
return ConsoleRegion::PAL;
|
return DiscRegion::PAL;
|
||||||
else if (prefix == "scps" || prefix == "slps" || prefix == "slpm")
|
else if (prefix == "scps" || prefix == "slps" || prefix == "slpm")
|
||||||
return ConsoleRegion::NTSC_J;
|
return DiscRegion::NTSC_J;
|
||||||
else if (prefix == "scus" || prefix == "slus" || prefix == "papx")
|
else if (prefix == "scus" || prefix == "slus" || prefix == "papx")
|
||||||
return ConsoleRegion::NTSC_U;
|
return DiscRegion::NTSC_U;
|
||||||
else
|
else
|
||||||
return std::nullopt;
|
return DiscRegion::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ConsoleRegion> GameList::GetRegionFromSystemArea(CDImage* cdi)
|
DiscRegion GameList::GetRegionFromSystemArea(CDImage* cdi)
|
||||||
{
|
{
|
||||||
// The license code is on sector 4 of the disc.
|
// The license code is on sector 4 of the disc.
|
||||||
u8 sector[CDImage::DATA_SECTOR_SIZE];
|
u8 sector[CDImage::DATA_SECTOR_SIZE];
|
||||||
if (!cdi->Seek(1, 4) || cdi->Read(CDImage::ReadMode::DataOnly, 1, sector) != 1)
|
if (!cdi->Seek(1, 4) || cdi->Read(CDImage::ReadMode::DataOnly, 1, sector) != 1)
|
||||||
return std::nullopt;
|
return DiscRegion::Other;
|
||||||
|
|
||||||
static constexpr char ntsc_u_string[] = " Licensed by Sony Computer Entertainment Amer ica ";
|
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 ntsc_j_string[] = " Licensed by Sony Computer Entertainment Inc.";
|
||||||
|
@ -162,29 +162,29 @@ std::optional<ConsoleRegion> GameList::GetRegionFromSystemArea(CDImage* cdi)
|
||||||
|
|
||||||
// subtract one for the terminating null
|
// subtract one for the terminating null
|
||||||
if (std::equal(ntsc_u_string, ntsc_u_string + countof(ntsc_u_string) - 1, sector))
|
if (std::equal(ntsc_u_string, ntsc_u_string + countof(ntsc_u_string) - 1, sector))
|
||||||
return ConsoleRegion::NTSC_U;
|
return DiscRegion::NTSC_U;
|
||||||
else if (std::equal(ntsc_j_string, ntsc_j_string + countof(ntsc_j_string) - 1, sector))
|
else if (std::equal(ntsc_j_string, ntsc_j_string + countof(ntsc_j_string) - 1, sector))
|
||||||
return ConsoleRegion::NTSC_J;
|
return DiscRegion::NTSC_J;
|
||||||
else if (std::equal(pal_string, pal_string + countof(pal_string) - 1, sector))
|
else if (std::equal(pal_string, pal_string + countof(pal_string) - 1, sector))
|
||||||
return ConsoleRegion::PAL;
|
return DiscRegion::PAL;
|
||||||
|
else
|
||||||
return std::nullopt;
|
return DiscRegion::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ConsoleRegion> GameList::GetRegionForImage(CDImage* cdi)
|
DiscRegion GameList::GetRegionForImage(CDImage* cdi)
|
||||||
{
|
{
|
||||||
std::optional<ConsoleRegion> system_area_region = GetRegionFromSystemArea(cdi);
|
DiscRegion system_area_region = GetRegionFromSystemArea(cdi);
|
||||||
if (system_area_region)
|
if (system_area_region != DiscRegion::Other)
|
||||||
return 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 DiscRegion::Other;
|
||||||
|
|
||||||
return GetRegionForCode(code);
|
return GetRegionForCode(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ConsoleRegion> GameList::GetRegionForPath(const char* image_path)
|
std::optional<DiscRegion> GameList::GetRegionForPath(const char* image_path)
|
||||||
{
|
{
|
||||||
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path);
|
std::unique_ptr<CDImage> cdi = CDImage::Open(image_path);
|
||||||
if (!cdi)
|
if (!cdi)
|
||||||
|
@ -263,7 +263,7 @@ bool GameList::GetExeListEntry(const char* path, GameListEntry* entry)
|
||||||
|
|
||||||
// no way to detect region...
|
// no way to detect region...
|
||||||
entry->path = path;
|
entry->path = path;
|
||||||
entry->region = ConsoleRegion::NTSC_U;
|
entry->region = DiscRegion::Other;
|
||||||
entry->total_size = ZeroExtend64(file_size);
|
entry->total_size = ZeroExtend64(file_size);
|
||||||
entry->last_modified_time = ffd.ModificationTime.AsUnixTimestamp();
|
entry->last_modified_time = ffd.ModificationTime.AsUnixTimestamp();
|
||||||
entry->type = GameListEntryType::PSExe;
|
entry->type = GameListEntryType::PSExe;
|
||||||
|
@ -280,10 +280,14 @@ bool GameList::GetGameListEntry(const std::string& path, GameListEntry* entry)
|
||||||
if (!cdi)
|
if (!cdi)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
std::string code = GetGameCodeForImage(cdi.get());
|
||||||
|
DiscRegion region = GetRegionFromSystemArea(cdi.get());
|
||||||
|
if (region == DiscRegion::Other)
|
||||||
|
region = GetRegionForCode(code);
|
||||||
|
|
||||||
entry->path = path;
|
entry->path = path;
|
||||||
entry->code = GetGameCodeForImage(cdi.get());
|
entry->code = std::move(code);
|
||||||
entry->region =
|
entry->region = 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 = GameListEntryType::Disc;
|
entry->type = GameListEntryType::Disc;
|
||||||
cdi.reset();
|
cdi.reset();
|
||||||
|
@ -299,7 +303,9 @@ bool GameList::GetGameListEntry(const std::string& path, GameListEntry* entry)
|
||||||
if (database_entry)
|
if (database_entry)
|
||||||
{
|
{
|
||||||
entry->title = database_entry->title;
|
entry->title = database_entry->title;
|
||||||
entry->region = database_entry->region;
|
|
||||||
|
if (entry->region != database_entry->region)
|
||||||
|
Log_WarningPrintf("Region mismatch between disc and database for '%s'", entry->code.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -418,7 +424,7 @@ bool GameList::LoadEntriesFromCache(ByteStream* stream)
|
||||||
|
|
||||||
if (!ReadString(stream, &path) || !ReadString(stream, &code) || !ReadString(stream, &title) ||
|
if (!ReadString(stream, &path) || !ReadString(stream, &code) || !ReadString(stream, &title) ||
|
||||||
!ReadU64(stream, &total_size) || !ReadU64(stream, &last_modified_time) || !ReadU8(stream, ®ion) ||
|
!ReadU64(stream, &total_size) || !ReadU64(stream, &last_modified_time) || !ReadU8(stream, ®ion) ||
|
||||||
region >= static_cast<u8>(ConsoleRegion::Count) || !ReadU8(stream, &type) ||
|
region >= static_cast<u8>(DiscRegion::Count) || !ReadU8(stream, &type) ||
|
||||||
type > static_cast<u8>(GameListEntryType::PSExe))
|
type > static_cast<u8>(GameListEntryType::PSExe))
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Game list cache entry is corrupted");
|
Log_WarningPrintf("Game list cache entry is corrupted");
|
||||||
|
@ -431,7 +437,7 @@ bool GameList::LoadEntriesFromCache(ByteStream* stream)
|
||||||
ge.title = std::move(title);
|
ge.title = std::move(title);
|
||||||
ge.total_size = total_size;
|
ge.total_size = total_size;
|
||||||
ge.last_modified_time = last_modified_time;
|
ge.last_modified_time = last_modified_time;
|
||||||
ge.region = static_cast<ConsoleRegion>(region);
|
ge.region = static_cast<DiscRegion>(region);
|
||||||
ge.type = static_cast<GameListEntryType>(type);
|
ge.type = static_cast<GameListEntryType>(type);
|
||||||
|
|
||||||
auto iter = m_cache_map.find(ge.path);
|
auto iter = m_cache_map.find(ge.path);
|
||||||
|
@ -620,7 +626,7 @@ public:
|
||||||
{
|
{
|
||||||
GameListDatabaseEntry gde;
|
GameListDatabaseEntry gde;
|
||||||
gde.code = std::move(code);
|
gde.code = std::move(code);
|
||||||
gde.region = GameList::GetRegionForCode(gde.code).value_or(ConsoleRegion::NTSC_U);
|
gde.region = GameList::GetRegionForCode(gde.code);
|
||||||
gde.title = name;
|
gde.title = name;
|
||||||
m_database.emplace(gde.code, std::move(gde));
|
m_database.emplace(gde.code, std::move(gde));
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct GameListDatabaseEntry
|
||||||
{
|
{
|
||||||
std::string code;
|
std::string code;
|
||||||
std::string title;
|
std::string title;
|
||||||
ConsoleRegion region;
|
DiscRegion region;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GameListEntry
|
struct GameListEntry
|
||||||
|
@ -32,7 +32,7 @@ struct GameListEntry
|
||||||
std::string title;
|
std::string title;
|
||||||
u64 total_size;
|
u64 total_size;
|
||||||
u64 last_modified_time;
|
u64 last_modified_time;
|
||||||
ConsoleRegion region;
|
DiscRegion region;
|
||||||
GameListEntryType type;
|
GameListEntryType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,10 +51,10 @@ 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 DiscRegion GetRegionForCode(std::string_view code);
|
||||||
static std::optional<ConsoleRegion> GetRegionFromSystemArea(CDImage* cdi);
|
static DiscRegion GetRegionFromSystemArea(CDImage* cdi);
|
||||||
static std::optional<ConsoleRegion> GetRegionForImage(CDImage* cdi);
|
static DiscRegion GetRegionForImage(CDImage* cdi);
|
||||||
static std::optional<ConsoleRegion> GetRegionForPath(const char* image_path);
|
static std::optional<DiscRegion> GetRegionForPath(const char* image_path);
|
||||||
static std::string_view GetTitleForPath(const char* path);
|
static std::string_view GetTitleForPath(const char* path);
|
||||||
|
|
||||||
const EntryList& GetEntries() const { return m_entries; }
|
const EntryList& GetEntries() const { return m_entries; }
|
||||||
|
@ -79,7 +79,7 @@ private:
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
|
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
|
||||||
GAME_LIST_CACHE_VERSION = 2
|
GAME_LIST_CACHE_VERSION = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
using DatabaseMap = std::unordered_map<std::string, GameListDatabaseEntry>;
|
using DatabaseMap = std::unordered_map<std::string, GameListDatabaseEntry>;
|
||||||
|
|
|
@ -155,6 +155,34 @@ const char* Settings::GetConsoleRegionDisplayName(ConsoleRegion region)
|
||||||
return s_console_region_display_names[static_cast<int>(region)];
|
return s_console_region_display_names[static_cast<int>(region)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::array<const char*, 4> s_disc_region_names = {{"NTSC-J", "NTSC-U", "PAL", "Other"}};
|
||||||
|
static std::array<const char*, 4> s_disc_region_display_names = {
|
||||||
|
{"NTSC-J (Japan)", "NTSC-U (US)", "PAL (Europe, Australia)", "Other"}};
|
||||||
|
|
||||||
|
std::optional<DiscRegion> Settings::ParseDiscRegionName(const char* str)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
for (const char* name : s_console_region_names)
|
||||||
|
{
|
||||||
|
if (StringUtil::Strcasecmp(name, str) == 0)
|
||||||
|
return static_cast<DiscRegion>(index);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Settings::GetDiscRegionName(DiscRegion region)
|
||||||
|
{
|
||||||
|
return s_disc_region_names[static_cast<int>(region)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Settings::GetDiscRegionDisplayName(DiscRegion region)
|
||||||
|
{
|
||||||
|
return s_disc_region_display_names[static_cast<int>(region)];
|
||||||
|
}
|
||||||
|
|
||||||
static std::array<const char*, 3> s_cpu_execution_mode_names = {{"Interpreter", "CachedInterpreter", "Recompiler"}};
|
static std::array<const char*, 3> s_cpu_execution_mode_names = {{"Interpreter", "CachedInterpreter", "Recompiler"}};
|
||||||
static std::array<const char*, 3> s_cpu_execution_mode_display_names = {
|
static std::array<const char*, 3> s_cpu_execution_mode_display_names = {
|
||||||
{"Intepreter (Slowest)", "Cached Interpreter (Faster)", "Recompiler (Fastest)"}};
|
{"Intepreter (Slowest)", "Cached Interpreter (Faster)", "Recompiler (Fastest)"}};
|
||||||
|
|
|
@ -91,6 +91,10 @@ struct Settings
|
||||||
static const char* GetConsoleRegionName(ConsoleRegion region);
|
static const char* GetConsoleRegionName(ConsoleRegion region);
|
||||||
static const char* GetConsoleRegionDisplayName(ConsoleRegion region);
|
static const char* GetConsoleRegionDisplayName(ConsoleRegion region);
|
||||||
|
|
||||||
|
static std::optional<DiscRegion> ParseDiscRegionName(const char* str);
|
||||||
|
static const char* GetDiscRegionName(DiscRegion region);
|
||||||
|
static const char* GetDiscRegionDisplayName(DiscRegion region);
|
||||||
|
|
||||||
static std::optional<CPUExecutionMode> ParseCPUExecutionMode(const char* str);
|
static std::optional<CPUExecutionMode> ParseCPUExecutionMode(const char* str);
|
||||||
static const char* GetCPUExecutionModeName(CPUExecutionMode mode);
|
static const char* GetCPUExecutionModeName(CPUExecutionMode mode);
|
||||||
static const char* GetCPUExecutionModeDisplayName(CPUExecutionMode mode);
|
static const char* GetCPUExecutionModeDisplayName(CPUExecutionMode mode);
|
||||||
|
|
|
@ -59,6 +59,23 @@ System::~System()
|
||||||
DestroyComponents();
|
DestroyComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConsoleRegion System::GetConsoleRegionForDiscRegion(DiscRegion region)
|
||||||
|
{
|
||||||
|
switch (region)
|
||||||
|
{
|
||||||
|
case DiscRegion::NTSC_J:
|
||||||
|
return ConsoleRegion::NTSC_J;
|
||||||
|
|
||||||
|
case DiscRegion::NTSC_U:
|
||||||
|
case DiscRegion::Other:
|
||||||
|
default:
|
||||||
|
return ConsoleRegion::NTSC_U;
|
||||||
|
|
||||||
|
case DiscRegion::PAL:
|
||||||
|
return ConsoleRegion::PAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<System> System::Create(HostInterface* host_interface)
|
std::unique_ptr<System> System::Create(HostInterface* host_interface)
|
||||||
{
|
{
|
||||||
std::unique_ptr<System> system(new System(host_interface));
|
std::unique_ptr<System> system(new System(host_interface));
|
||||||
|
@ -136,18 +153,19 @@ bool System::Boot(const SystemBootParameters& params)
|
||||||
|
|
||||||
if (m_region == ConsoleRegion::Auto)
|
if (m_region == ConsoleRegion::Auto)
|
||||||
{
|
{
|
||||||
std::optional<ConsoleRegion> detected_region = GameList::GetRegionForImage(media.get());
|
const DiscRegion disc_region = GameList::GetRegionForImage(media.get());
|
||||||
if (detected_region)
|
if (disc_region != DiscRegion::Other)
|
||||||
{
|
{
|
||||||
m_region = detected_region.value();
|
m_region = GetConsoleRegionForDiscRegion(disc_region);
|
||||||
Log_InfoPrintf("Auto-detected %s region for '%s'", Settings::GetConsoleRegionName(m_region),
|
Log_InfoPrintf("Auto-detected console %s region for '%s' (region %s)",
|
||||||
params.filename.c_str());
|
Settings::GetConsoleRegionName(m_region), params.filename.c_str(),
|
||||||
|
Settings::GetDiscRegionName(disc_region));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_region = ConsoleRegion::NTSC_U;
|
m_region = ConsoleRegion::NTSC_U;
|
||||||
Log_WarningPrintf("Could not determine region for CD. Defaulting to %s.",
|
Log_WarningPrintf("Could not determine console region for disc region %s. Defaulting to %s.",
|
||||||
Settings::GetConsoleRegionName(m_region));
|
Settings::GetDiscRegionName(disc_region), Settings::GetConsoleRegionName(m_region));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,9 @@ public:
|
||||||
|
|
||||||
~System();
|
~System();
|
||||||
|
|
||||||
|
/// Returns the preferred console type for a disc.
|
||||||
|
static ConsoleRegion GetConsoleRegionForDiscRegion(DiscRegion region);
|
||||||
|
|
||||||
/// Creates a new System.
|
/// Creates a new System.
|
||||||
static std::unique_ptr<System> Create(HostInterface* host_interface);
|
static std::unique_ptr<System> Create(HostInterface* host_interface);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,15 @@ enum class ConsoleRegion
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DiscRegion : u8
|
||||||
|
{
|
||||||
|
NTSC_J, // SCEI
|
||||||
|
NTSC_U, // SCEA
|
||||||
|
PAL, // SCEE
|
||||||
|
Other,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
enum class CPUExecutionMode : u8
|
enum class CPUExecutionMode : u8
|
||||||
{
|
{
|
||||||
Interpreter,
|
Interpreter,
|
||||||
|
@ -78,7 +87,6 @@ enum : u32
|
||||||
NUM_CONTROLLER_AND_CARD_PORTS = 2
|
NUM_CONTROLLER_AND_CARD_PORTS = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
CPU_CODE_CACHE_PAGE_SIZE = 1024,
|
CPU_CODE_CACHE_PAGE_SIZE = 1024,
|
||||||
|
|
|
@ -147,11 +147,11 @@ public:
|
||||||
{
|
{
|
||||||
switch (ge.region)
|
switch (ge.region)
|
||||||
{
|
{
|
||||||
case ConsoleRegion::NTSC_J:
|
case DiscRegion::NTSC_J:
|
||||||
return m_region_jp_pixmap;
|
return m_region_jp_pixmap;
|
||||||
case ConsoleRegion::NTSC_U:
|
case DiscRegion::NTSC_U:
|
||||||
return m_region_us_pixmap;
|
return m_region_us_pixmap;
|
||||||
case ConsoleRegion::PAL:
|
case DiscRegion::PAL:
|
||||||
default:
|
default:
|
||||||
return m_region_eu_pixmap;
|
return m_region_eu_pixmap;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue