Cheats: Support parsing built-in database

This commit is contained in:
Connor McLaughlin
2020-11-29 16:42:49 +10:00
parent d1399fe6a3
commit eaafd0a00c
6 changed files with 165 additions and 13 deletions

View File

@ -1,6 +1,7 @@
#include "cheats.h"
#include "bus.h"
#include "common/assert.h"
#include "common/byte_stream.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/string.h"
@ -505,6 +506,123 @@ bool CheatList::SaveToPCSXRFile(const char* filename)
return (std::ferror(fp.get()) == 0);
}
bool CheatList::LoadFromPackage(const std::string& game_code)
{
std::unique_ptr<ByteStream> stream =
g_host_interface->OpenPackageFile("database/chtdb.txt", BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED);
if (!stream)
return false;
std::string db_string = FileSystem::ReadStreamToString(stream.get());
stream.reset();
if (db_string.empty())
return false;
std::istringstream iss(db_string);
std::string line;
while (std::getline(iss, line))
{
char* start = line.data();
while (*start != '\0' && std::isspace(*start))
start++;
// skip empty lines
if (*start == '\0' || *start == ';')
continue;
char* end = start + std::strlen(start) - 1;
while (end > start && std::isspace(*end))
{
*end = '\0';
end--;
}
if (start == end)
continue;
if (start[0] != ':' || std::strcmp(&start[1], game_code.c_str()) != 0)
continue;
// game code match
CheatCode current_code;
while (std::getline(iss, line))
{
start = line.data();
while (*start != '\0' && std::isspace(*start))
start++;
// skip empty lines
if (*start == '\0' || *start == ';')
continue;
end = start + std::strlen(start) - 1;
while (end > start && std::isspace(*end))
{
*end = '\0';
end--;
}
if (start == end)
continue;
if (start[0] == ':')
break;
if (start[0] == '#')
{
start++;
if (current_code.Valid())
{
m_codes.push_back(std::move(current_code));
current_code = CheatCode();
}
// new code
char* slash = std::strrchr(start, '\\');
if (slash)
{
*slash = '\0';
current_code.group = start;
start = slash + 1;
}
if (current_code.group.empty())
current_code.group = "Ungrouped";
current_code.description = start;
continue;
}
while (!IsHexCharacter(*start) && start != end)
start++;
if (start == end)
continue;
char* end_ptr;
CheatCode::Instruction inst;
inst.first = static_cast<u32>(std::strtoul(start, &end_ptr, 16));
inst.second = 0;
if (end_ptr)
{
while (!IsHexCharacter(*end_ptr) && end_ptr != end)
end_ptr++;
if (end_ptr != end)
inst.second = static_cast<u32>(std::strtoul(end_ptr, nullptr, 16));
}
current_code.instructions.push_back(inst);
}
if (current_code.Valid())
m_codes.push_back(std::move(current_code));
Log_InfoPrintf("Loaded %zu codes from package for %s", m_codes.size(), game_code.c_str());
return !m_codes.empty();
}
Log_WarningPrintf("No codes found in package for %s", game_code.c_str());
return false;
}
u32 CheatList::GetEnabledCodeCount() const
{
u32 count = 0;

View File

@ -129,6 +129,8 @@ public:
bool SaveToPCSXRFile(const char* filename);
bool LoadFromPackage(const std::string& game_code);
void Apply();
void ApplyCode(u32 index);

View File

@ -263,7 +263,15 @@ CheatList* CheatManagerDialog::getCheatList() const
CheatList* list = System::GetCheatList();
if (!list)
{
QtHostInterface::GetInstance()->LoadCheatListFromGameTitle();
list = System::GetCheatList();
}
if (!list)
{
QtHostInterface::GetInstance()->LoadCheatListFromDatabase();
list = System::GetCheatList();
}
if (!list)
{
QtHostInterface::GetInstance()->executeOnEmulationThread(

View File

@ -2436,6 +2436,20 @@ bool CommonHostInterface::LoadCheatListFromGameTitle()
return LoadCheatList(filename.c_str());
}
bool CommonHostInterface::LoadCheatListFromDatabase()
{
if (System::GetRunningCode().empty())
return false;
std::unique_ptr<CheatList> cl = std::make_unique<CheatList>();
if (!cl->LoadFromPackage(System::GetRunningCode()))
return false;
AddFormattedOSDMessage(10.0f, TranslateString("OSDMessage", "Loaded %u cheats from database."), cl->GetCodeCount());
System::SetCheatList(std::move(cl));
return true;
}
bool CommonHostInterface::SaveCheatList()
{
if (!System::IsValid() || !System::HasCheatList())

View File

@ -160,6 +160,9 @@ public:
/// Loads the cheat list for the current game title from the user directory.
bool LoadCheatListFromGameTitle();
/// Loads the cheat list for the current game code from the built-in code database.
bool LoadCheatListFromDatabase();
/// Saves the current cheat list to the game title's file.
bool SaveCheatList();