mirror of
https://github.com/PabloMK7/citra.git
synced 2025-09-10 21:00:06 +00:00
cheats: Use global cheat engine (#7291)
* cheats: Use global cheat engine * cheats: Prevent wasted double-load of cheat file. * android: Fix for cheat engine updates. --------- Co-authored-by: GPUCode <geoster3d@gmail.com>
This commit is contained in:
parent
5a7f615da1
commit
7dd9174d31
14 changed files with 120 additions and 125 deletions
|
@ -10,7 +10,6 @@
|
|||
#include "core/cheats/gateway_cheat.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
|
||||
namespace Cheats {
|
||||
|
||||
|
@ -18,11 +17,11 @@ namespace Cheats {
|
|||
// we use the same value
|
||||
constexpr u64 run_interval_ticks = 50'000'000;
|
||||
|
||||
CheatEngine::CheatEngine(u64 title_id_, Core::System& system_)
|
||||
: system(system_), title_id{title_id_} {
|
||||
LoadCheatFile();
|
||||
CheatEngine::CheatEngine(Core::System& system_) : system{system_} {}
|
||||
|
||||
CheatEngine::~CheatEngine() {
|
||||
if (system.IsPoweredOn()) {
|
||||
Connect();
|
||||
system.CoreTiming().UnscheduleEvent(event, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,24 +32,18 @@ void CheatEngine::Connect() {
|
|||
system.CoreTiming().ScheduleEvent(run_interval_ticks, event);
|
||||
}
|
||||
|
||||
CheatEngine::~CheatEngine() {
|
||||
if (system.IsPoweredOn()) {
|
||||
system.CoreTiming().UnscheduleEvent(event, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<CheatBase>> CheatEngine::GetCheats() const {
|
||||
std::shared_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
std::span<const std::shared_ptr<CheatBase>> CheatEngine::GetCheats() const {
|
||||
std::shared_lock lock{cheats_list_mutex};
|
||||
return cheats_list;
|
||||
}
|
||||
|
||||
void CheatEngine::AddCheat(const std::shared_ptr<CheatBase>& cheat) {
|
||||
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
cheats_list.push_back(cheat);
|
||||
void CheatEngine::AddCheat(std::shared_ptr<CheatBase>&& cheat) {
|
||||
std::unique_lock lock{cheats_list_mutex};
|
||||
cheats_list.push_back(std::move(cheat));
|
||||
}
|
||||
|
||||
void CheatEngine::RemoveCheat(std::size_t index) {
|
||||
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
std::unique_lock lock{cheats_list_mutex};
|
||||
if (index < 0 || index >= cheats_list.size()) {
|
||||
LOG_ERROR(Core_Cheats, "Invalid index {}", index);
|
||||
return;
|
||||
|
@ -58,16 +51,16 @@ void CheatEngine::RemoveCheat(std::size_t index) {
|
|||
cheats_list.erase(cheats_list.begin() + index);
|
||||
}
|
||||
|
||||
void CheatEngine::UpdateCheat(std::size_t index, const std::shared_ptr<CheatBase>& new_cheat) {
|
||||
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
void CheatEngine::UpdateCheat(std::size_t index, std::shared_ptr<CheatBase>&& new_cheat) {
|
||||
std::unique_lock lock{cheats_list_mutex};
|
||||
if (index < 0 || index >= cheats_list.size()) {
|
||||
LOG_ERROR(Core_Cheats, "Invalid index {}", index);
|
||||
return;
|
||||
}
|
||||
cheats_list[index] = new_cheat;
|
||||
cheats_list[index] = std::move(new_cheat);
|
||||
}
|
||||
|
||||
void CheatEngine::SaveCheatFile() const {
|
||||
void CheatEngine::SaveCheatFile(u64 title_id) const {
|
||||
const std::string cheat_dir = FileUtil::GetUserPath(FileUtil::UserPath::CheatsDir);
|
||||
const std::string filepath = fmt::format("{}{:016X}.txt", cheat_dir, title_id);
|
||||
|
||||
|
@ -82,7 +75,14 @@ void CheatEngine::SaveCheatFile() const {
|
|||
}
|
||||
}
|
||||
|
||||
void CheatEngine::LoadCheatFile() {
|
||||
void CheatEngine::LoadCheatFile(u64 title_id) {
|
||||
{
|
||||
std::unique_lock lock{cheats_list_mutex};
|
||||
if (loaded_title_id.has_value() && loaded_title_id == title_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string cheat_dir = FileUtil::GetUserPath(FileUtil::UserPath::CheatsDir);
|
||||
const std::string filepath = fmt::format("{}{:016X}.txt", cheat_dir, title_id);
|
||||
|
||||
|
@ -90,20 +90,22 @@ void CheatEngine::LoadCheatFile() {
|
|||
FileUtil::CreateDir(cheat_dir);
|
||||
}
|
||||
|
||||
if (!FileUtil::Exists(filepath))
|
||||
if (!FileUtil::Exists(filepath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto gateway_cheats = GatewayCheat::LoadFile(filepath);
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
std::move(gateway_cheats.begin(), gateway_cheats.end(), std::back_inserter(cheats_list));
|
||||
std::unique_lock lock{cheats_list_mutex};
|
||||
loaded_title_id = title_id;
|
||||
cheats_list = std::move(gateway_cheats);
|
||||
}
|
||||
}
|
||||
|
||||
void CheatEngine::RunCallback([[maybe_unused]] std::uintptr_t user_data, s64 cycles_late) {
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
for (auto& cheat : cheats_list) {
|
||||
std::shared_lock lock{cheats_list_mutex};
|
||||
for (const auto& cheat : cheats_list) {
|
||||
if (cheat->IsEnabled()) {
|
||||
cheat->Execute(system);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
|
@ -24,22 +26,39 @@ class CheatBase;
|
|||
|
||||
class CheatEngine {
|
||||
public:
|
||||
explicit CheatEngine(u64 title_id_, Core::System& system);
|
||||
explicit CheatEngine(Core::System& system);
|
||||
~CheatEngine();
|
||||
|
||||
/// Registers the cheat execution callback.
|
||||
void Connect();
|
||||
std::vector<std::shared_ptr<CheatBase>> GetCheats() const;
|
||||
void AddCheat(const std::shared_ptr<CheatBase>& cheat);
|
||||
|
||||
/// Returns a span of the currently active cheats.
|
||||
std::span<const std::shared_ptr<CheatBase>> GetCheats() const;
|
||||
|
||||
/// Adds a cheat to the cheat engine.
|
||||
void AddCheat(std::shared_ptr<CheatBase>&& cheat);
|
||||
|
||||
/// Removes a cheat at the specified index in the cheats list.
|
||||
void RemoveCheat(std::size_t index);
|
||||
void UpdateCheat(std::size_t index, const std::shared_ptr<CheatBase>& new_cheat);
|
||||
void SaveCheatFile() const;
|
||||
|
||||
/// Updates a cheat at the specified index in the cheats list.
|
||||
void UpdateCheat(std::size_t index, std::shared_ptr<CheatBase>&& new_cheat);
|
||||
|
||||
/// Loads the cheat file from disk for the specified title id.
|
||||
void LoadCheatFile(u64 title_id);
|
||||
|
||||
/// Saves currently active cheats to file for the specified title id.
|
||||
void SaveCheatFile(u64 title_id) const;
|
||||
|
||||
private:
|
||||
void LoadCheatFile();
|
||||
/// The cheat execution callback.
|
||||
void RunCallback(std::uintptr_t user_data, s64 cycles_late);
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
Core::TimingEventType* event;
|
||||
std::optional<u64> loaded_title_id;
|
||||
std::vector<std::shared_ptr<CheatBase>> cheats_list;
|
||||
mutable std::shared_mutex cheats_list_mutex;
|
||||
Core::TimingEventType* event;
|
||||
Core::System& system;
|
||||
u64 title_id;
|
||||
};
|
||||
} // namespace Cheats
|
||||
|
|
|
@ -472,8 +472,8 @@ std::string GatewayCheat::ToString() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string& filepath) {
|
||||
std::vector<std::unique_ptr<CheatBase>> cheats;
|
||||
std::vector<std::shared_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string& filepath) {
|
||||
std::vector<std::shared_ptr<CheatBase>> cheats;
|
||||
|
||||
boost::iostreams::stream<boost::iostreams::file_descriptor_source> file;
|
||||
FileUtil::OpenFStream<std::ios_base::in>(file, filepath);
|
||||
|
@ -493,7 +493,7 @@ std::vector<std::unique_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string
|
|||
line = Common::StripSpaces(line); // remove spaces at front and end
|
||||
if (line.length() >= 2 && line.front() == '[') {
|
||||
if (!cheat_lines.empty()) {
|
||||
cheats.push_back(std::make_unique<GatewayCheat>(name, cheat_lines, comments));
|
||||
cheats.push_back(std::make_shared<GatewayCheat>(name, cheat_lines, comments));
|
||||
cheats.back()->SetEnabled(enabled);
|
||||
enabled = false;
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ std::vector<std::unique_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string
|
|||
}
|
||||
}
|
||||
if (!cheat_lines.empty()) {
|
||||
cheats.push_back(std::make_unique<GatewayCheat>(name, cheat_lines, comments));
|
||||
cheats.push_back(std::make_shared<GatewayCheat>(name, cheat_lines, comments));
|
||||
cheats.back()->SetEnabled(enabled);
|
||||
}
|
||||
return cheats;
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
/// (there might be multiple lines of those hex numbers)
|
||||
/// Comment lines start with a '*'
|
||||
/// This function will pares the file for such structures
|
||||
static std::vector<std::unique_ptr<CheatBase>> LoadFile(const std::string& filepath);
|
||||
static std::vector<std::shared_ptr<CheatBase>> LoadFile(const std::string& filepath);
|
||||
|
||||
private:
|
||||
std::atomic<bool> enabled = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue