GameDB: Merge traits/compatibility into single file

This commit is contained in:
Stenzek 2023-08-19 22:00:20 +10:00
parent e501012a68
commit cee5decec4
14 changed files with 8038 additions and 8316 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -69,8 +69,6 @@ add_library(core
imgui_overlays.h
interrupt_controller.cpp
interrupt_controller.h
libcrypt_serials.cpp
libcrypt_serials.h
mdec.cpp
mdec.h
memory_card.cpp
@ -125,7 +123,7 @@ set(RECOMPILER_SRCS
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_link_libraries(core PUBLIC Threads::Threads common util zlib)
target_link_libraries(core PRIVATE stb xxhash imgui rapidjson tinyxml2)
target_link_libraries(core PRIVATE stb xxhash imgui rapidjson)
if(WIN32)
target_sources(core PRIVATE

View File

@ -9,7 +9,7 @@
<PreprocessorDefinitions Condition="('$(Platform)'=='x64' Or '$(Platform)'=='ARM' Or '$(Platform)'=='ARM64')">WITH_RECOMPILER=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="('$(Platform)'=='x64' Or '$(Platform)'=='ARM64')">WITH_MMAP_FASTMEM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\rcheevos\include;$(SolutionDir)dep\rapidjson\include;$(SolutionDir)dep\discord-rpc\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\rcheevos\include;$(SolutionDir)dep\rapidjson\include;$(SolutionDir)dep\discord-rpc\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Platform)'!='ARM64'">%(AdditionalIncludeDirectories);$(SolutionDir)dep\rainterface</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Platform)'=='x64'">%(AdditionalIncludeDirectories);$(SolutionDir)dep\xbyak\xbyak</AdditionalIncludeDirectories>

View File

@ -60,7 +60,6 @@
<ClCompile Include="host_settings.cpp" />
<ClCompile Include="imgui_overlays.cpp" />
<ClCompile Include="interrupt_controller.cpp" />
<ClCompile Include="libcrypt_serials.cpp" />
<ClCompile Include="mdec.cpp" />
<ClCompile Include="memory_card.cpp" />
<ClCompile Include="memory_card_image.cpp" />
@ -139,7 +138,6 @@
<ClInclude Include="imgui_overlays.h" />
<ClInclude Include="input_types.h" />
<ClInclude Include="interrupt_controller.h" />
<ClInclude Include="libcrypt_serials.h" />
<ClInclude Include="mdec.h" />
<ClInclude Include="memory_card.h" />
<ClInclude Include="memory_card_image.h" />
@ -180,9 +178,6 @@
<ProjectReference Include="..\..\dep\stb\stb.vcxproj">
<Project>{ed601289-ac1a-46b8-a8ed-17db9eb73423}</Project>
</ProjectReference>
<ProjectReference Include="..\..\dep\tinyxml2\tinyxml2.vcxproj">
<Project>{933118a9-68c5-47b4-b151-b03c93961623}</Project>
</ProjectReference>
<ProjectReference Include="..\..\dep\vixl\vixl.vcxproj" Condition="'$(Platform)'=='ARM64'">
<Project>{8906836e-f06e-46e8-b11a-74e5e8c7b8fb}</Project>
</ProjectReference>

View File

@ -51,7 +51,6 @@
<ClCompile Include="cpu_recompiler_code_generator_aarch32.cpp" />
<ClCompile Include="gpu_backend.cpp" />
<ClCompile Include="gpu_sw_backend.cpp" />
<ClCompile Include="libcrypt_serials.cpp" />
<ClCompile Include="texture_replacements.cpp" />
<ClCompile Include="multitap.cpp" />
<ClCompile Include="gpu_hw_d3d12.cpp" />
@ -117,7 +116,6 @@
<ClInclude Include="gpu_types.h" />
<ClInclude Include="gpu_backend.h" />
<ClInclude Include="gpu_sw_backend.h" />
<ClInclude Include="libcrypt_serials.h" />
<ClInclude Include="texture_replacements.h" />
<ClInclude Include="shader_cache_version.h" />
<ClInclude Include="multitap.h" />

View File

@ -13,7 +13,6 @@
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "system.h"
#include "tinyxml2.h"
#include "util/cd_image.h"
#include <iomanip>
#include <memory>
@ -24,14 +23,13 @@ Log_SetChannel(GameDatabase);
#ifdef _WIN32
#include "common/windows_headers.h"
#endif
#include "SimpleIni.h"
namespace GameDatabase {
enum : u32
{
GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48,
GAME_DATABASE_CACHE_VERSION = 2,
GAME_DATABASE_CACHE_VERSION = 3,
};
static Entry* GetMutableEntry(const std::string_view& serial);
@ -42,31 +40,29 @@ static bool SaveToCache();
static bool LoadGameDBJson();
static bool ParseJsonEntry(Entry* entry, const rapidjson::Value& value);
static bool ParseJsonCodes(u32 index, const rapidjson::Value& value);
static bool LoadGameSettingsIni();
static bool ParseGameSettingsIniEntry(const CSimpleIniA& ini, const char* section);
static bool LoadGameCompatibilityXml();
static bool LoadTrackHashes();
std::array<std::pair<const char*, const char*>, static_cast<u32>(GameDatabase::Trait::Count)> s_trait_names = {{
{"ForceInterpreter", TRANSLATABLE("GameSettingsTrait", "Force Interpreter")},
{"ForceSoftwareRenderer", TRANSLATABLE("GameSettingsTrait", "Force Software Renderer")},
{"ForceSoftwareRendererForReadbacks", TRANSLATABLE("GameSettingsTrait", "Force Software Renderer For Readbacks")},
{"ForceInterlacing", TRANSLATABLE("GameSettingsTrait", "Force Interlacing")},
{"DisableTrueColor", TRANSLATABLE("GameSettingsTrait", "Disable True Color")},
{"DisableUpscaling", TRANSLATABLE("GameSettingsTrait", "Disable Upscaling")},
{"DisableScaledDithering", TRANSLATABLE("GameSettingsTrait", "Disable Scaled Dithering")},
{"DisableForceNTSCTimings", TRANSLATABLE("GameSettingsTrait", "Disallow Forcing NTSC Timings")},
{"DisableWidescreen", TRANSLATABLE("GameSettingsTrait", "Disable Widescreen")},
{"DisablePGXP", TRANSLATABLE("GameSettingsTrait", "Disable PGXP")},
{"DisablePGXPCulling", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Culling")},
{"DisablePGXPTextureCorrection", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Perspective Correct Textures")},
{"DisablePGXPColorCorrection", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Perspective Correct Colors")},
{"DisablePGXPDepthBuffer", TRANSLATABLE("GameSettingsTrait", "Disable PGXP Depth Buffer")},
{"ForcePGXPVertexCache", TRANSLATABLE("GameSettingsTrait", "Force PGXP Vertex Cache")},
{"ForcePGXPCPUMode", TRANSLATABLE("GameSettingsTrait", "Force PGXP CPU Mode")},
{"ForceRecompilerMemoryExceptions", TRANSLATABLE("GameSettingsTrait", "Force Recompiler Memory Exceptions")},
{"ForceRecompilerICache", TRANSLATABLE("GameSettingsTrait", "Force Recompiler ICache")},
{"ForceRecompilerLUTFastmem", TRANSLATABLE("GameSettingsTrait", "Force Recompiler LUT Fastmem")},
std::array<const char*, static_cast<u32>(GameDatabase::Trait::Count)> s_trait_names = {{
"ForceInterpreter",
"ForceSoftwareRenderer",
"ForceSoftwareRendererForReadbacks",
"ForceInterlacing",
"DisableTrueColor",
"DisableUpscaling",
"DisableScaledDithering",
"DisableForceNTSCTimings",
"DisableWidescreen",
"DisablePGXP",
"DisablePGXPCulling",
"DisablePGXPTextureCorrection",
"DisablePGXPColorCorrection",
"DisablePGXPDepthBuffer",
"ForcePGXPVertexCache",
"ForcePGXPCPUMode",
"ForceRecompilerMemoryExceptions",
"ForceRecompilerICache",
"ForceRecompilerLUTFastmem",
"IsLibCryptProtected",
}};
static bool s_loaded = false;
@ -93,8 +89,6 @@ void GameDatabase::EnsureLoaded()
s_code_lookup = {};
LoadGameDBJson();
LoadGameSettingsIni();
LoadGameCompatibilityXml();
SaveToCache();
}
@ -180,13 +174,7 @@ GameDatabase::Entry* GameDatabase::GetMutableEntry(const std::string_view& seria
const char* GameDatabase::GetTraitName(Trait trait)
{
DebugAssert(trait < Trait::Count);
return s_trait_names[static_cast<u32>(trait)].first;
}
const char* GameDatabase::GetTraitDisplayName(Trait trait)
{
DebugAssert(trait < Trait::Count);
return s_trait_names[static_cast<u32>(trait)].second;
return s_trait_names[static_cast<u32>(trait)];
}
const char* GameDatabase::GetCompatibilityRatingName(CompatibilityRating rating)
@ -263,9 +251,10 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
{
if (display_osd_messages && settings.gpu_renderer != GPURenderer::Software)
{
Host::AddKeyedOSDMessage("gamedb_force_software_rb",
Host::TranslateStdString("OSDMessage", "Using software renderer for readbacks based on game settings."),
osd_duration);
Host::AddKeyedOSDMessage(
"gamedb_force_software_rb",
Host::TranslateStdString("OSDMessage", "Using software renderer for readbacks based on game settings."),
osd_duration);
}
settings.gpu_use_software_renderer_for_readbacks = true;
@ -716,6 +705,18 @@ static bool GetStringFromObject(const rapidjson::Value& object, const char* key,
return true;
}
static bool GetBoolFromObject(const rapidjson::Value& object, const char* key, bool* dest)
{
*dest = false;
auto member = object.FindMember(key);
if (member == object.MemberEnd() || !member->value.IsBool())
return false;
*dest = member->value.GetBool();
return true;
}
template<typename T>
static bool GetUIntFromObject(const rapidjson::Value& object, const char* key, T* dest)
{
@ -746,9 +747,38 @@ static bool GetArrayOfStringsFromObject(const rapidjson::Value& object, const ch
return true;
}
template<typename T>
static std::optional<T> GetOptionalIntFromObject(const rapidjson::Value& object, const char* key)
{
auto member = object.FindMember(key);
if (member == object.MemberEnd() || !member->value.IsInt())
return std::nullopt;
return static_cast<T>(member->value.GetInt());
}
template<typename T>
static std::optional<T> GetOptionalUIntFromObject(const rapidjson::Value& object, const char* key)
{
auto member = object.FindMember(key);
if (member == object.MemberEnd() || !member->value.IsUint())
return std::nullopt;
return static_cast<T>(member->value.GetUint());
}
static std::optional<float> GetOptionalFloatFromObject(const rapidjson::Value& object, const char* key)
{
auto member = object.FindMember(key);
if (member == object.MemberEnd() || !member->value.IsFloat())
return std::nullopt;
return member->value.GetFloat();
}
bool GameDatabase::LoadGameDBJson()
{
std::optional<std::string> gamedb_data(Host::ReadResourceFileToString("database/gamedb.json"));
std::optional<std::string> gamedb_data(Host::ReadResourceFileToString("gamedb.json"));
if (!gamedb_data.has_value())
{
Log_ErrorPrintf("Failed to read game database");
@ -837,7 +867,7 @@ bool GameDatabase::ParseJsonEntry(Entry* entry, const rapidjson::Value& value)
}
entry->supported_controllers = ~0u;
auto controllers = value.FindMember("controllers");
const auto controllers = value.FindMember("controllers");
if (controllers != value.MemberEnd())
{
if (controllers->value.IsArray())
@ -873,6 +903,57 @@ bool GameDatabase::ParseJsonEntry(Entry* entry, const rapidjson::Value& value)
}
}
const auto compatibility = value.FindMember("compatibility");
if (compatibility != value.MemberEnd())
{
if (compatibility->value.IsObject())
{
u32 rating;
if (GetUIntFromObject(compatibility->value, "rating", &rating) &&
rating < static_cast<u32>(CompatibilityRating::Count))
{
entry->compatibility = static_cast<CompatibilityRating>(rating);
}
}
else
{
Log_WarningPrintf("compatibility is not an object");
}
}
if (entry->serial == "SCES-02105")
__debugbreak();
const auto traits = value.FindMember("traits");
if (traits != value.MemberEnd())
{
if (traits->value.IsObject())
{
const auto& traitsobj = traits->value;
for (u32 trait = 0; trait < static_cast<u32>(Trait::Count); trait++)
{
bool bvalue;
if (GetBoolFromObject(traitsobj, s_trait_names[trait], &bvalue) && bvalue)
entry->traits[trait] = bvalue;
}
entry->display_active_start_offset = GetOptionalIntFromObject<s16>(traitsobj, "DisplayActiveStartOffset");
entry->display_active_end_offset = GetOptionalIntFromObject<s16>(traitsobj, "DisplayActiveEndOffset");
entry->display_line_start_offset = GetOptionalIntFromObject<s8>(traitsobj, "DisplayLineStartOffset");
entry->display_line_end_offset = GetOptionalIntFromObject<s8>(traitsobj, "DisplayLineEndOffset");
entry->dma_max_slice_ticks = GetOptionalUIntFromObject<u32>(traitsobj, "DMAMaxSliceTicks");
entry->dma_halt_ticks = GetOptionalUIntFromObject<u32>(traitsobj, "DMAHaltTicks");
entry->gpu_fifo_size = GetOptionalUIntFromObject<u32>(traitsobj, "GPUFIFOSize");
entry->gpu_max_run_ahead = GetOptionalUIntFromObject<u32>(traitsobj, "GPUMaxRunAhead");
entry->gpu_pgxp_tolerance = GetOptionalFloatFromObject(traitsobj, "GPUPGXPTolerance");
entry->gpu_pgxp_depth_threshold = GetOptionalFloatFromObject(traitsobj, "GPUPGXPDepthThreshold");
}
else
{
Log_WarningPrintf("traits is not an object");
}
}
return true;
}
@ -915,151 +996,6 @@ bool GameDatabase::ParseJsonCodes(u32 index, const rapidjson::Value& value)
return (added > 0);
}
bool GameDatabase::LoadGameSettingsIni()
{
std::optional<std::string> gamedb_data(Host::ReadResourceFileToString("database/gamesettings.ini"));
if (!gamedb_data.has_value())
{
Log_ErrorPrintf("Failed to read gamesettings database");
return false;
}
CSimpleIniA ini;
SI_Error err = ini.LoadData(gamedb_data->data(), gamedb_data->size());
if (err != SI_OK)
{
Log_ErrorPrintf("Failed to parse game settings ini: %d", static_cast<int>(err));
return false;
}
std::list<CSimpleIniA::Entry> sections;
ini.GetAllSections(sections);
for (const CSimpleIniA::Entry& section_entry : sections)
ParseGameSettingsIniEntry(ini, section_entry.pItem);
Log_InfoPrintf("Loaded %zu gamesettings entries", sections.size());
return true;
}
bool GameDatabase::ParseGameSettingsIniEntry(const CSimpleIniA& ini, const char* section)
{
Entry* entry = GetMutableEntry(section);
if (!entry)
{
Log_ErrorPrintf("Unknown game serial '%s' in gamesettings", section);
return false;
}
for (u32 trait = 0; trait < static_cast<u32>(Trait::Count); trait++)
{
if (ini.GetBoolValue(section, s_trait_names[trait].first, false))
entry->traits[trait] = true;
}
long lvalue = ini.GetLongValue(section, "DisplayActiveStartOffset", 0);
if (lvalue != 0)
entry->display_active_start_offset = static_cast<s16>(lvalue);
lvalue = ini.GetLongValue(section, "DisplayActiveEndOffset", 0);
if (lvalue != 0)
entry->display_active_end_offset = static_cast<s16>(lvalue);
lvalue = ini.GetLongValue(section, "DisplayLineStartOffset", 0);
if (lvalue != 0)
entry->display_line_start_offset = static_cast<s8>(lvalue);
lvalue = ini.GetLongValue(section, "DisplayLineEndOffset", 0);
if (lvalue != 0)
entry->display_line_end_offset = static_cast<s8>(lvalue);
lvalue = ini.GetLongValue(section, "DMAMaxSliceTicks", 0);
if (lvalue > 0)
entry->dma_max_slice_ticks = static_cast<u32>(lvalue);
lvalue = ini.GetLongValue(section, "DMAHaltTicks", 0);
if (lvalue > 0)
entry->dma_halt_ticks = static_cast<u32>(lvalue);
lvalue = ini.GetLongValue(section, "GPUFIFOSize", 0);
if (lvalue > 0)
entry->gpu_fifo_size = static_cast<u32>(lvalue);
lvalue = ini.GetLongValue(section, "GPUMaxRunAhead", 0);
if (lvalue > 0)
entry->gpu_max_run_ahead = static_cast<u32>(lvalue);
float fvalue = static_cast<float>(ini.GetDoubleValue(section, "GPUPGXPTolerance", -1.0f));
if (fvalue >= 0.0f)
entry->gpu_pgxp_tolerance = fvalue;
fvalue = static_cast<float>(ini.GetDoubleValue(section, "GPUPGXPDepthThreshold", -1.0f));
if (fvalue > 0.0f)
entry->gpu_pgxp_depth_threshold = fvalue;
return true;
}
class CompatibilityListVisitor final : public tinyxml2::XMLVisitor
{
public:
ALWAYS_INLINE u32 GetCount() const { return m_count; }
bool VisitEnter(const tinyxml2::XMLElement& element, const tinyxml2::XMLAttribute* firstAttribute) override
{
// recurse into gamelist
if (StringUtil::Strcasecmp(element.Name(), "compatibility-list") == 0)
return true;
if (StringUtil::Strcasecmp(element.Name(), "entry") != 0)
return false;
const char* attr = element.Attribute("code");
std::string code(attr ? attr : "");
const u32 compatibility = static_cast<u32>(element.IntAttribute("compatibility"));
if (code.empty() || compatibility >= static_cast<u32>(GameDatabase::CompatibilityRating::Count))
{
Log_ErrorPrintf("Missing child node at line %d", element.GetLineNum());
return false;
}
GameDatabase::Entry* entry = GameDatabase::GetMutableEntry(code);
if (!entry)
{
Log_ErrorPrintf("Unknown serial in compatibility list: '%s'", code.c_str());
return false;
}
entry->compatibility = static_cast<GameDatabase::CompatibilityRating>(compatibility);
m_count++;
return false;
}
private:
u32 m_count = 0;
};
bool GameDatabase::LoadGameCompatibilityXml()
{
std::optional<std::string> xml(Host::ReadResourceFileToString("database/compatibility.xml"));
if (!xml.has_value())
{
Log_ErrorPrintf("Failed to load compatibility.xml from package");
return false;
}
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.Parse(xml->c_str(), xml->size());
if (error != tinyxml2::XML_SUCCESS)
{
Log_ErrorPrintf("Failed to parse compatibility list: %s", tinyxml2::XMLDocument::ErrorIDToName(error));
return false;
}
const tinyxml2::XMLElement* datafile_elem = doc.FirstChildElement("compatibility-list");
if (!datafile_elem)
{
Log_ErrorPrintf("Failed to get compatibility-list element");
return false;
}
CompatibilityListVisitor visitor;
datafile_elem->Accept(&visitor);
Log_InfoPrintf("Loaded %u entries from compatibility list", visitor.GetCount());
return true;
}
void GameDatabase::EnsureTrackHashesMapLoaded()
{
if (s_track_hashes_loaded)
@ -1071,7 +1007,7 @@ void GameDatabase::EnsureTrackHashesMapLoaded()
bool GameDatabase::LoadTrackHashes()
{
std::optional<std::string> gamedb_data(Host::ReadResourceFileToString("database/gamedb.json"));
std::optional<std::string> gamedb_data(Host::ReadResourceFileToString("gamedb.json"));
if (!gamedb_data.has_value())
{
Log_ErrorPrintf("Failed to read game database");

View File

@ -15,7 +15,7 @@ class CDImage;
struct Settings;
namespace GameDatabase {
enum class CompatibilityRating : u32
enum class CompatibilityRating : u8
{
Unknown = 0,
DoesntBoot = 1,
@ -47,6 +47,7 @@ enum class Trait : u32
ForceRecompilerMemoryExceptions,
ForceRecompilerICache,
ForceRecompilerLUTFastmem,
IsLibCryptProtected,
Count
};
@ -94,7 +95,6 @@ std::string GetSerialForDisc(CDImage* image);
std::string GetSerialForPath(const char* path);
const char* GetTraitName(Trait trait);
const char* GetTraitDisplayName(Trait trait);
const char* GetCompatibilityRatingName(CompatibilityRating rating);
const char* GetCompatibilityRatingDisplayName(CompatibilityRating rating);

View File

@ -22,8 +22,6 @@
#include "common/progress_callback.h"
#include "common/string_util.h"
#include "tinyxml2.h"
#include <algorithm>
#include <array>
#include <cctype>

View File

@ -1,279 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "libcrypt_serials.h"
namespace LibcryptGameList {
static const char* LIBCRYPT_GAME_SERIALS[] = {
"SLES-01226", // Actua Ice Hockey 2 (Europe)
"SLES-01226", // Actua Ice Hockey 2 (Europe)
"SLES-02563", // Anstoss - Premier Manager (Germany)
"SCES-01564", // Ape Escape (Europe)
"SCES-01564", // Ape Escape (Europe)
"SCES-02028", // Ape Escape (France)
"SCES-02029", // Ape Escape (Germany)
"SCES-02030", // Ape Escape (Italy)
"SCES-02031", // Ape Escape - La Invasion de los Monos (Spain)
"SLES-03324", // Asterix - Mega Madness (Europe) (En,Fr,De,Es,It,Nl)
"SCES-02366", // Barbie - Aventure Equestre (France)
"SCES-02365", // Barbie - Race & Ride (Europe)
"SCES-02367", // Barbie - Race & Ride (Germany)
"SCES-02368", // Barbie - Race & Ride (Italy)
"SCES-02369", // Barbie - Race & Ride (Spain)
"SCES-02488", // Barbie - Sports Extreme (France)
"SCES-02489", // Barbie - Super Sport (Germany)
"SCES-02487", // Barbie - Super Sports (Europe)
"SCES-02490", // Barbie - Super Sports (Italy)
"SCES-02491", // Barbie - Super Sports (Spain)
"SLES-02977", // BDFL Manager 2001 (Germany)
"SLES-03605", // BDFL Manager 2002 (Germany)
"SLES-02293", // Canal+ Premier Manager (Europe) (Fr,Es,It)
"SLES-02766", // Cochons de Guerre, Les (France)
"SCES-02834", // Crash Bash (Europe) (En,Fr,De,Es,It)
"SCES-02834", // Crash Bash (Europe) (En,Fr,De,Es,It)
"SCES-02105", // CTR - Crash Team Racing (Europe) (En,Fr,De,Es,It,Nl)
"SCES-02105", // CTR - Crash Team Racing (Europe) (En,Fr,De,Es,It,Nl)
"SCES-02105", // CTR - Crash Team Racing (Europe) (En,Fr,De,Es,It,Nl) (EDC)
"SLES-02207", // Dino Crisis (Europe)
"SLES-02208", // Dino Crisis (France)
"SLES-02209", // Dino Crisis (Germany)
"SLES-02210", // Dino Crisis (Italy)
"SLES-02211", // Dino Crisis (Spain)
"SCES-02004", // Disney Fais Ton Histoire! Mulan (France)
"SCES-02006", // Disney Libro Animato Creativo - Mulan (Italy)
"SCES-01516", // Disney Tarzan (France)
"SCES-01518", // Disney Tarzan (Italy)
"SCES-01519", // Disney Tarzan (Spain)
"SLES-03189", // Disney's 102 Dalmatians - Puppies to the Rescue (Europe) (Rev 1)
"SLES-03191", // Disney's 102 Dalmatians - Puppies to the Rescue (Europe) (Fr,De,Es,It,Nl)
"SLES-03190", // Disney's 102 Dalmatians - Puppies to the Rescue (Scandinavia) (Sv,No,Da)
"SCES-02007", // Disney's Aventura Interactiva - Mulan (Spain)
"SCES-01695", // Disney's Mulan - Story Studio (Europe)
"SCES-01431", // Disney's Tarzan (Europe)
"SCES-02185", // Disney's Tarzan (Netherlands)
"SCES-02264", // Disney's Verhalenstudio - Mulan (Netherlands)
"SCES-02184", // Disneyn Tarzan (Finland)
"SCES-02005", // Disneys Interaktive Abenteuer - Mulan (Germany)
"SCES-02181", // Disneys Tarzan (Denmark)
"SCES-01517", // Disneys Tarzan (Germany)
"SCES-02182", // Disneys Tarzan (Sweden)
"SLES-02538", // EA Sports Superbike 2000 (Europe) (En,Fr,De,Es,It,Sv)
"SLES-01715", // Eagle One - Harrier Attack (Europe) (En,Fr,De,Es,It)
"SLES-01715", // Eagle One - Harrier Attack (Europe) (En,Fr,De,Es,It)
"SCES-01704", // Esto Es Futbol (Spain)
"SLES-03061", // F.A. Premier League Football Manager 2001, The (Europe)
"SLES-02722", // F1 2000 (Europe) (En,Fr,De,Nl)
"SLES-02723", // F1 2000 (Europe) (En,Es,Sv,Da,Fi)
"SLES-02724", // F1 2000 (Italy)
"SLES-12965", // Final Fantasy IX (Europe) (Disc 2)
"SLES-02965", // Final Fantasy IX (Europe) (Disc 1)
"SLES-22965", // Final Fantasy IX (Europe) (Disc 3)
"SLES-32965", // Final Fantasy IX (Europe) (Disc 4)
"SLES-02966", // Final Fantasy IX (France) (Disc 1)
"SLES-12966", // Final Fantasy IX (France) (Disc 2)
"SLES-22966", // Final Fantasy IX (France) (Disc 3)
"SLES-32966", // Final Fantasy IX (France) (Disc 4)
"SLES-02967", // Final Fantasy IX (Germany) (Disc 1)
"SLES-12967", // Final Fantasy IX (Germany) (Disc 2)
"SLES-22967", // Final Fantasy IX (Germany) (Disc 3)
"SLES-32967", // Final Fantasy IX (Germany) (Disc 4)
"SLES-02968", // Final Fantasy IX (Italy) (Disc 1)
"SLES-12968", // Final Fantasy IX (Italy) (Disc 2)
"SLES-22968", // Final Fantasy IX (Italy) (Disc 3)
"SLES-32968", // Final Fantasy IX (Italy) (Disc 4)
"SLES-02969", // Final Fantasy IX (Spain) (Disc 1)
"SLES-12969", // Final Fantasy IX (Spain) (Disc 2)
"SLES-22969", // Final Fantasy IX (Spain) (Disc 3)
"SLES-32969", // Final Fantasy IX (Spain) (Disc 4)
"SCES-02080", // Final Fantasy VIII (Europe, Australia) (Disc 1)
"SLES-02080", // Final Fantasy VIII (Europe, Australia) (Disc 1)
"SCES-22080", // Final Fantasy VIII (Europe, Australia) (Disc 3)
"SLES-22080", // Final Fantasy VIII (Europe, Australia) (Disc 3)
"SCES-32080", // Final Fantasy VIII (Europe, Australia) (Disc 4)
"SLES-32080", // Final Fantasy VIII (Europe, Australia) (Disc 4)
"SCES-12080", // Final Fantasy VIII (Europe, Australia) (Disc 2)
"SLES-12080", // Final Fantasy VIII (Europe, Australia) (Disc 2)
"SLES-02081", // Final Fantasy VIII (France) (Disc 1)
"SLES-12081", // Final Fantasy VIII (France) (Disc 2)
"SLES-22081", // Final Fantasy VIII (France) (Disc 3)
"SLES-32081", // Final Fantasy VIII (France) (Disc 4)
"SLES-02082", // Final Fantasy VIII (Germany) (Disc 1)
"SLES-12082", // Final Fantasy VIII (Germany) (Disc 2)
"SLES-22082", // Final Fantasy VIII (Germany) (Disc 3)
"SLES-32082", // Final Fantasy VIII (Germany) (Disc 4)
"SLES-02083", // Final Fantasy VIII (Italy) (Disc 1)
"SLES-12083", // Final Fantasy VIII (Italy) (Disc 2)
"SLES-22083", // Final Fantasy VIII (Italy) (Disc 3)
"SLES-32083", // Final Fantasy VIII (Italy) (Disc 4)
"SLES-02084", // Final Fantasy VIII (Spain) (Disc 1)
"SLES-12084", // Final Fantasy VIII (Spain) (Disc 2)
"SLES-22084", // Final Fantasy VIII (Spain) (Disc 3)
"SLES-32084", // Final Fantasy VIII (Spain) (Disc 4)
"SLES-02978", // Football Manager Campionato 2001 (Italy)
"SLES-03606", // Football Manager Campionato 2002 (Italy)
"SCED-01979", // Formula One '99 (Europe) (En,Fr,De,It) (Beta)
"SCES-02222", // Formula One 99 (Europe) (En,Es,Fi)
"SCES-01979", // Formula One 99 (Europe) (En,Fr,De,It)
"SLES-02767", // Frontschweine (Germany)
"SCES-01702", // Fussball Live (Germany)
"SLES-03062", // Fussball Manager 2001 (Germany)
"SLES-02328", // Galerians (Europe) (Disc 1)
"SLES-12328", // Galerians (Europe) (Disc 2)
"SLES-22328", // Galerians (Europe) (Disc 3)
"SLES-02329", // Galerians (France) (Disc 1)
"SLES-12329", // Galerians (France) (Disc 2)
"SLES-22329", // Galerians (France) (Disc 3)
"SLES-02330", // Galerians (Germany) (Disc 1)
"SLES-12330", // Galerians (Germany) (Disc 2)
"SLES-22330", // Galerians (Germany) (Disc 3)
"SLES-01241", // Gekido - Urban Fighters (Europe) (En,Fr,De,Es,It)
"SLES-01241", // Gekido - Urban Fighters (Europe) (En,Fr,De,Es,It)
"SLES-01041", // Hogs of War (Europe)
"SLES-01041", // Hogs of War (Europe)
"SLES-02769", // Hogs of War - Nati per Soffritto (Italy)
"SLES-03489", // Italian Job, The (Europe)
"SLES-03489", // Italian Job, The (Europe)
"SLES-03626", // Italian Job, The (Europe) (Fr,De,Es)
"SLES-03648", // Italian Job, The (Italy)
"SCES-01444", // Jackie Chan Stuntmaster (Europe)
"SLES-01362", // Le Mans 24 Hours (Europe) (En,Fr,De,Es,It,Pt)
"SLES-01362", // Le Mans 24 Hours (Europe) (En,Fr,De,Es,It,Pt)
"SLES-01301", // Legacy of Kain - Soul Reaver (Europe)
"SLES-01301", // Legacy of Kain - Soul Reaver (Europe)
"SLES-02024", // Legacy of Kain - Soul Reaver (France)
"SLES-02025", // Legacy of Kain - Soul Reaver (Germany)
"SLES-02027", // Legacy of Kain - Soul Reaver (Italy)
"SLES-02026", // Legacy of Kain - Soul Reaver (Spain)
"SLES-02975", // LMA Manager 2001 (Europe)
"SLES-03603", // LMA Manager 2002 (Europe)
"SLES-03530", // Lucky Luke - Western Fever (Europe) (En,Fr,De,Es,It,Nl)
"SLES-02402", // Manager de Liga (Spain) (Beta)
"SLES-02979", // Manager de Liga 2001 (Spain)
"SLES-03607", // Manager de Liga 2002 (Spain)
"SLES-02768", // Marranos en Guerra (Spain)
"SCES-00311", // MediEvil (Europe)
"SCES-01492", // MediEvil (France)
"SCES-01493", // MediEvil (Germany)
"SCES-01494", // MediEvil (Italy)
"SCES-01494", // MediEvil (Italy)
"SCES-01495", // MediEvil (Spain)
"SCES-02545", // MediEvil 2 (Europe) (Es,It,Pt)
"SCES-02545", // MediEvil 2 (Europe) (Es,It,Pt)
"SCES-02544", // MediEvil 2 (Europe) (En,Fr,De)
"SCES-02544", // MediEvil 2 (Europe) (En,Fr,De)
"SCES-02546", // MediEvil 2 (Russia)
"SLES-03519", // Men in Black - The Series - Crashdown (Europe)
"SLES-03519", // Men in Black - The Series - Crashdown (Europe)
"SLES-03520", // Men in Black - The Series - Crashdown (France)
"SLES-03520", // Men in Black - The Series - Crashdown (France)
"SLES-03521", // Men in Black - The Series - Crashdown (Germany)
"SLES-03522", // Men in Black - The Series - Crashdown (Italy)
"SLES-03522", // Men in Black - The Series - Crashdown (Italy)
"SLES-03523", // Men in Black - The Series - Crashdown (Spain)
"SLES-02395", // Michelin Rally Masters - Race of Champions (Europe) (Fr,Es,It)
"SLES-01545", // Michelin Rally Masters - Race of Champions (Europe) (En,De,Sv)
"SLES-02839", // Mike Tyson Boxing (Europe) (En,Fr,De,Es,It)
"SLES-01906", // Mission - Impossible (Europe) (En,Fr,De,Es,It)
"SLES-02830", // MoHo (Europe) (En,Fr,De,Es,It)
"SCES-01701", // Monde des Bleus, Le - Le Jeu Officiel de l'Equipe de France (France)
"SLES-02086", // N-Gen Racing (Europe) (En,Fr,De,Es,It)
"SLES-02086", // N-Gen Racing (Europe) (En,Fr,De,Es,It)
"SLES-02700", // Need for Speed - Porsche 2000 (Europe) (Fr,Es,It)
"SLES-02689", // Need for Speed - Porsche 2000 (Europe) (En,De,Sv)
"SLES-02689", // Need for Speed - Porsche 2000 (Europe) (En,De,Sv)
"SLES-02558", // Parasite Eve II (Europe) (Disc 1)
"SLES-12558", // Parasite Eve II (Europe) (Disc 2)
"SLES-12559", // Parasite Eve II (France) (Disc 2)
"SLES-02559", // Parasite Eve II (France) (Disc 1)
"SLES-02560", // Parasite Eve II (Germany) (Disc 1)
"SLES-12560", // Parasite Eve II (Germany) (Disc 2)
"SLES-02562", // Parasite Eve II (Italy) (Disc 1)
"SLES-12562", // Parasite Eve II (Italy) (Disc 2)
"SLES-02561", // Parasite Eve II (Spain) (Disc 1)
"SLES-12561", // Parasite Eve II (Spain) (Disc 2)
"SLES-02061", // PGA European Tour Golf (Europe) (En,De)
"SLES-02396", // PGA European Tour Golf (Europe) (Fr,Es,It)
"SLES-02396", // PGA European Tour Golf (Europe) (Fr,Es,It) (Alt)
"SLES-02292", // Premier Manager 2000 (Europe)
"SLES-00017", // Prince Naseem Boxing (Europe) (En,Fr,De,Es,It)
"SLES-01943", // Radikal Bikers (Europe) (En,Fr,De,Es,It)
"SLES-01943", // Radikal Bikers (Europe) (En,Fr,De,Es,It)
"SLES-02824", // RC Revenge (Europe) (En,Fr,De,Es)
"SLES-02529", // Resident Evil 3 - Nemesis (Europe)
"SLES-02530", // Resident Evil 3 - Nemesis (France)
"SLES-02531", // Resident Evil 3 - Nemesis (Germany)
"SLES-02533", // Resident Evil 3 - Nemesis (Italy)
"SLES-02698", // Resident Evil 3 - Nemesis (Ireland)
"SLES-02532", // Resident Evil 3 - Nemesis (Spain)
"SLES-02976", // Roger Lemerre - La Selection des Champions (France)
"SLES-03604", // Roger Lemerre - La Selection des Champions 2002 (France)
"SLES-02681", // Ronaldo V-Football (Europe) (De,Es,It,Pt)
"SLES-00995", // Ronaldo V-Football (Europe) (En,Fr,Nl,Sv)
"SLES-02112", // SaGa Frontier 2 (Europe)
"SLES-02113", // SaGa Frontier 2 (France)
"SLES-02118", // SaGa Frontier 2 (Germany)
"SLES-02763", // SnoCross Championship Racing (Europe) (En,Fr,De,Es,It)
"SCES-02290", // Space Debris (Europe)
"SCES-02430", // Space Debris (France)
"SCES-02431", // Space Debris (Germany)
"SCES-02432", // Space Debris (Italy)
"SCES-02433", // Space Debris (Spain)
"SCES-01763", // Speed Freaks (Europe)
"SCES-02104", // Spyro 2 - Gateway to Glimmer (Europe) (En,Fr,De,Es,It)
"SCES-02835", // Spyro - Year of the Dragon (Europe) (En,Fr,De,Es,It) (Rev 1)
"SCES-02835", // Spyro - Year of the Dragon (Europe) (En,Fr,De,Es,It)
"SLES-02862", // Sydney 2000 (Australia)
"SLES-02857", // Sydney 2000 (Europe)
"SLES-02858", // Sydney 2000 (France)
"SLES-02859", // Sydney 2000 (Germany)
"SLES-02860", // Sydney 2000 (Italy)
"SLES-02861", // Sydney 2000 (Spain)
"SLES-03245", // TechnoMage - De Terugkeer der Eeuwigheid (Netherlands)
"SLES-02831", // TechnoMage - Die Rueckkehr der Ewigkeit (Germany)
"SLES-03244", // Technomage - El Retorno de la Eternidad (Spain)
"SLES-03242", // TechnoMage - En Quete de L'Eternite (France)
"SLES-03241", // TechnoMage - Return of Eternity (Europe)
"SLES-03243", // TechnoMage - Ritorno all'Eternita (Italy)
"SLES-02688", // Theme Park World (Europe) (En,Fr,De,Es,It,Nl,Sv)
"SLES-02688", // Theme Park World (Europe) (En,Fr,De,Es,It,Nl,Sv)
"SCES-01882", // This Is Football (Europe) (Fr,Nl)
"SCES-01700", // This Is Football (Europe)
"SCES-01703", // This Is Football (Italy)
"SLES-02572", // TOCA World Touring Cars (Europe) (En,Fr,De)
"SLES-02572", // TOCA World Touring Cars (Europe) (En,Fr,De)
"SLES-02573", // TOCA World Touring Cars (Europe) (Es,It)
"SLES-02704", // UEFA Euro 2000 (Europe)
"SLES-02705", // UEFA Euro 2000 (France)
"SLES-02706", // UEFA Euro 2000 (Germany)
"SLES-02707", // UEFA Euro 2000 (Italy)
"SLES-02708", // UEFA Euro 2000 (Spain)
"SLES-01733", // UEFA Striker (Europe) (En,Fr,De,Es,It,Nl)
"SLES-02071", // Urban Chaos (Europe) (En,Es,It)
"SLES-02071", // Urban Chaos (Europe) (En,Es,It)
"SLES-02354", // Urban Chaos (France)
"SLES-02355", // Urban Chaos (Germany)
"SLES-02355", // Urban Chaos (Germany)
"SLES-01907", // V-Rally - Championship Edition 2 (Europe) (En,Fr,De)
"SLES-01907", // V-Rally - Championship Edition 2 (Europe) (En,Fr,De)
"SLES-01907", // V-Rally - Championship Edition 2 (Europe) (En,Fr,De)
"SLES-02754", // Vagrant Story (Europe)
"SLES-02755", // Vagrant Story (France)
"SLES-02756", // Vagrant Story (Germany)
"SLES-02733", // Walt Disney World Quest - Magical Racing Tour (Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da)
"SLES-02733", // Walt Disney World Quest - Magical Racing Tour (Europe) (En,Fr,De,Es,It,Nl,Sv,No,Da)
"SCES-01909", // Wip3out (Europe) (En,Fr,De,Es,It)
};
bool IsLibcryptGameCode(const std::string_view& serial)
{
for (const char* compare_serial : LIBCRYPT_GAME_SERIALS)
{
if (serial == compare_serial)
return true;
}
return false;
}
} // namespace LibcryptGameList

View File

@ -1,9 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include <string_view>
namespace LibcryptGameList {
bool IsLibcryptGameCode(const std::string_view& serial);
}

View File

@ -25,11 +25,9 @@
#include "gpu.h"
#include "gte.h"
#include "host.h"
#include "util/host_display.h"
#include "host_interface_progress_callback.h"
#include "host_settings.h"
#include "interrupt_controller.h"
#include "libcrypt_serials.h"
#include "mdec.h"
#include "memory_card.h"
#include "multitap.h"
@ -44,6 +42,7 @@
#include "timers.h"
#include "util/audio_stream.h"
#include "util/cd_image.h"
#include "util/host_display.h"
#include "util/ini_settings_interface.h"
#include "util/iso_reader.h"
#include "util/state_wrapper.h"
@ -148,8 +147,8 @@ static BIOS::Hash s_bios_hash = {};
static std::string s_running_game_path;
static std::string s_running_game_serial;
static std::string s_running_game_title;
static const GameDatabase::Entry* s_running_game_entry = nullptr;
static System::GameHash s_running_game_hash;
static bool s_running_unknown_game;
static bool s_was_fast_booted;
static float s_throttle_frequency = 60.0f;
@ -333,7 +332,7 @@ System::GameHash System::GetGameHash()
bool System::IsRunningUnknownGame()
{
return s_running_unknown_game;
return !s_running_game_entry;
}
bool System::WasFastBooted()
@ -1561,8 +1560,8 @@ void System::ClearRunningGame()
s_running_game_serial.clear();
s_running_game_path.clear();
s_running_game_title.clear();
s_running_game_entry = nullptr;
s_running_game_hash = 0;
s_running_unknown_game = false;
Host::OnGameChanged(s_running_game_path, s_running_game_serial, s_running_game_title);
@ -3126,8 +3125,8 @@ void System::UpdateRunningGame(const char* path, CDImage* image, bool booting)
s_running_game_path.clear();
s_running_game_serial.clear();
s_running_game_title.clear();
s_running_game_entry = nullptr;
s_running_game_hash = 0;
s_running_unknown_game = true;
if (path && std::strlen(path) > 0)
{
@ -3143,12 +3142,11 @@ void System::UpdateRunningGame(const char* path, CDImage* image, bool booting)
std::string id;
GetGameDetailsFromImage(image, &id, &s_running_game_hash);
const GameDatabase::Entry* entry = GameDatabase::GetEntryForId(id);
if (entry)
s_running_game_entry = GameDatabase::GetEntryForId(id);
if (s_running_game_entry)
{
s_running_game_serial = entry->serial;
s_running_game_title = entry->title;
s_running_unknown_game = false;
s_running_game_serial = s_running_game_entry->serial;
s_running_game_title = s_running_game_entry->title;
}
else
{
@ -3186,7 +3184,7 @@ void System::UpdateRunningGame(const char* path, CDImage* image, bool booting)
bool System::CheckForSBIFile(CDImage* image)
{
if (s_running_game_serial.empty() || !LibcryptGameList::IsLibcryptGameCode(s_running_game_serial) || !image ||
if (!s_running_game_entry || !s_running_game_entry->HasTrait(GameDatabase::Trait::IsLibCryptProtected) || !image ||
image->HasNonStandardSubchannel())
{
return true;

View File

@ -26,7 +26,7 @@ class QUrl;
enum class ConsoleRegion;
enum class DiscRegion : u8;
namespace GameDatabase {
enum class CompatibilityRating : u32;
enum class CompatibilityRating : u8;
}
namespace GameList {
enum class EntryType;