Config: Make SpeedHack a scoped enum

And get rid of the redundant "SpeedHack" suffix on all values.
This commit is contained in:
Stenzek 2023-07-07 20:24:15 +10:00 committed by Connor McLaughlin
parent b53e9856b8
commit 48cfe9ca73
6 changed files with 233 additions and 220 deletions

File diff suppressed because it is too large Load Diff

View File

@ -170,15 +170,12 @@ enum GamefixId
// TODO - config - not a fan of the excessive use of enums and macros to make them work
// a proper object would likely make more sense (if possible).
enum SpeedhackId
enum class SpeedHack
{
SpeedhackId_FIRST = 0,
Speedhack_mvuFlag = SpeedhackId_FIRST,
Speedhack_InstantVU1,
Speedhack_MTVU,
SpeedhackId_COUNT
MVUFlag,
InstantVU1,
MTVU,
MaxCount,
};
enum class VsyncMode
@ -374,7 +371,6 @@ typename std::underlying_type<Enumeration>::type enum_cast(Enumeration E)
}
ImplementEnumOperators(GamefixId);
ImplementEnumOperators(SpeedhackId);
//------------ DEFAULT sseMXCSR VALUES ---------------
#define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop"
@ -1068,6 +1064,10 @@ struct Pcsx2Config
// ------------------------------------------------------------------------
struct SpeedhackOptions
{
static constexpr s8 MIN_EE_CYCLE_RATE = -3;
static constexpr s8 MAX_EE_CYCLE_RATE = 3;
static constexpr u8 MAX_EE_CYCLE_SKIP = 3;
BITFIELD32()
bool
fastCDVD : 1, // enables fast CDVD access
@ -1085,17 +1085,13 @@ struct Pcsx2Config
void LoadSave(SettingsWrapper& conf);
SpeedhackOptions& DisableAll();
void Set(SpeedhackId id, bool enabled = true);
void Set(SpeedHack id, int value);
bool operator==(const SpeedhackOptions& right) const
{
return OpEqu(bitset) && OpEqu(EECycleRate) && OpEqu(EECycleSkip);
}
bool operator==(const SpeedhackOptions& right) const;
bool operator!=(const SpeedhackOptions& right) const;
bool operator!=(const SpeedhackOptions& right) const
{
return !this->operator==(right);
}
static const char* GetSpeedHackName(SpeedHack id);
static std::optional<SpeedHack> ParseSpeedHackName(const std::string_view& name);
};
struct DebugOptions

View File

@ -303,17 +303,17 @@
"speedHacks": {
"type": "object",
"properties": {
"mvuFlagSpeedHack": {
"mvuFlag": {
"type": "integer",
"minimum": 0,
"maximum": 1
},
"InstantVU1SpeedHack": {
"instantVU1": {
"type": "integer",
"minimum": 0,
"maximum": 1
},
"MTVUSpeedHack": {
"mtvu": {
"type": "integer",
"minimum": 0,
"maximum": 1

View File

@ -200,33 +200,25 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml:
}
}
// Validate speed hacks, invalid ones will be dropped!
if (node.has_child("speedHacks") && node["speedHacks"].has_children())
{
for (const auto& n : node["speedHacks"].children())
{
bool speedHackValidated = false;
auto speedHack = std::string(n.key().str, n.key().len);
const std::string_view id_view = std::string_view(n.key().str, n.key().len);
const std::string_view value_view = std::string_view(n.val().str, n.val().len);
const std::optional<SpeedHack> id = Pcsx2Config::SpeedhackOptions::ParseSpeedHackName(id_view);
const std::optional<int> value = StringUtil::FromChars<int>(value_view);
// Same deal with SpeedHacks
if (StringUtil::EndsWith(speedHack, "SpeedHack"))
if (id.has_value() && value.has_value() &&
std::none_of(gameEntry.speedHacks.begin(), gameEntry.speedHacks.end(),
[&id](const auto& it) { return it.first == id.value(); }))
{
speedHack.erase(speedHack.size() - 9);
for (SpeedhackId id = SpeedhackId_FIRST; id < pxEnumEnd; ++id)
{
if (speedHack.compare(EnumToString(id)) == 0 &&
std::none_of(gameEntry.speedHacks.begin(), gameEntry.speedHacks.end(), [id](const auto& it) { return it.first == id; }))
{
gameEntry.speedHacks.emplace_back(id, std::atoi(n.val().str));
speedHackValidated = true;
break;
}
}
gameEntry.speedHacks.emplace_back(id.value(), value.value());
}
if (!speedHackValidated)
else
{
Console.Error(fmt::format("[GameDB] Invalid speedhack: '{}', specified for serial: '{}'. Dropping!", speedHack.c_str(), serial));
Console.Error(fmt::format("[GameDB] Invalid speedhack: '{}={}', specified for serial: '{}'. Dropping!",
id_view, value_view, serial));
}
}
}
@ -507,16 +499,17 @@ void GameDatabaseSchema::GameEntry::applyGameFixes(Pcsx2Config& config, bool app
// TODO - config - this could be simplified with maps instead of bitfields and enums
for (const auto& it : speedHacks)
{
const bool mode = it.second != 0;
if (!applyAuto)
{
Console.Warning("[GameDB] Skipping setting Speedhack '%s' to [mode=%d]", EnumToString(it.first), mode);
Console.Warning("[GameDB] Skipping setting Speedhack '%s' to [mode=%d]",
Pcsx2Config::SpeedhackOptions::GetSpeedHackName(it.first), it.second);
continue;
}
// Legacy note - speedhacks are setup in the GameDB as integer values, but
// are effectively booleans like the gamefixes
config.Speedhacks.Set(it.first, mode);
Console.WriteLn("(GameDB) Setting Speedhack '%s' to [mode=%d]", EnumToString(it.first), mode);
config.Speedhacks.Set(it.first, it.second);
Console.WriteLn("(GameDB) Setting Speedhack '%s' to [mode=%d]",
Pcsx2Config::SpeedhackOptions::GetSpeedHackName(it.first), it.second);
}
// TODO - config - this could be simplified with maps instead of bitfields and enums

View File

@ -24,7 +24,6 @@
#include <vector>
enum GamefixId;
enum SpeedhackId;
namespace GameDatabaseSchema
{
@ -113,7 +112,7 @@ namespace GameDatabaseSchema
ClampMode vu0ClampMode = ClampMode::Undefined;
ClampMode vu1ClampMode = ClampMode::Undefined;
std::vector<GamefixId> gameFixes;
std::vector<std::pair<SpeedhackId, int>> speedHacks;
std::vector<std::pair<SpeedHack, int>> speedHacks;
std::vector<std::pair<GSHWFixId, s32>> gsHWFixes;
std::vector<std::string> memcardFilters;
std::unordered_map<u32, std::string> patches;

View File

@ -177,36 +177,58 @@ void TraceLogFilters::LoadSave(SettingsWrapper& wrap)
SettingsWrapEntry(IOP.bitset);
}
const char* const tbl_SpeedhackNames[] =
{
static constexpr const char* s_speed_hack_names[] = {
"mvuFlag",
"InstantVU1",
"MTVU"
"instantVU1",
"mtvu",
};
const char* EnumToString(SpeedhackId id)
const char* Pcsx2Config::SpeedhackOptions::GetSpeedHackName(SpeedHack id)
{
return tbl_SpeedhackNames[id];
pxAssert(static_cast<u32>(id) < std::size(s_speed_hack_names));
return s_speed_hack_names[static_cast<u32>(id)];
}
void Pcsx2Config::SpeedhackOptions::Set(SpeedhackId id, bool enabled)
std::optional<SpeedHack> Pcsx2Config::SpeedhackOptions::ParseSpeedHackName(const std::string_view& name)
{
pxAssert(EnumIsValid(id));
for (u32 i = 0; i < std::size(s_speed_hack_names); i++)
{
if (name == s_speed_hack_names[i])
return static_cast<SpeedHack>(i);
}
return std::nullopt;
}
void Pcsx2Config::SpeedhackOptions::Set(SpeedHack id, int value)
{
pxAssert(static_cast<u32>(id) < std::size(s_speed_hack_names));
switch (id)
{
case Speedhack_mvuFlag:
vuFlagHack = enabled;
case SpeedHack::MVUFlag:
vuFlagHack = (value != 0);
break;
case Speedhack_InstantVU1:
vu1Instant = enabled;
case SpeedHack::InstantVU1:
vu1Instant = (value != 0);
break;
case Speedhack_MTVU:
vuThread = enabled;
case SpeedHack::MTVU:
vuThread = (value != 0);
break;
jNO_DEFAULT;
jNO_DEFAULT
}
}
bool Pcsx2Config::SpeedhackOptions::operator==(const SpeedhackOptions& right) const
{
return OpEqu(bitset) && OpEqu(EECycleRate) && OpEqu(EECycleSkip);
}
bool Pcsx2Config::SpeedhackOptions::operator!=(const SpeedhackOptions& right) const
{
return !operator==(right);
}
Pcsx2Config::SpeedhackOptions::SpeedhackOptions()
{
DisableAll();
@ -239,6 +261,9 @@ void Pcsx2Config::SpeedhackOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBool(vuFlagHack);
SettingsWrapBitBool(vuThread);
SettingsWrapBitBool(vu1Instant);
EECycleRate = std::clamp(EECycleRate, MIN_EE_CYCLE_RATE, MAX_EE_CYCLE_RATE);
EECycleSkip = std::min(EECycleSkip, MAX_EE_CYCLE_SKIP);
}
void Pcsx2Config::ProfilerOptions::LoadSave(SettingsWrapper& wrap)