diff --git a/Utilities/cheat_info.cpp b/Utilities/cheat_info.cpp new file mode 100644 index 0000000000..cea2ef9062 --- /dev/null +++ b/Utilities/cheat_info.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#include "cheat_info.h" +#include "Config.h" +#include "StrUtil.h" + +LOG_CHANNEL(log_cheat, "Cheat"); + +bool cheat_info::from_str(const std::string& cheat_line) +{ + auto cheat_vec = fmt::split(cheat_line, {"@@@"}, false); + + s64 val64 = 0; + if (cheat_vec.size() != 5 || !cfg::try_to_int64(&val64, cheat_vec[2], 0, cheat_type_max - 1)) + { + log_cheat.fatal("Failed to parse cheat line"); + return false; + } + + game = cheat_vec[0]; + description = cheat_vec[1]; + type = cheat_type{::narrow(val64)}; + offset = std::stoul(cheat_vec[3]); + red_script = cheat_vec[4]; + + return true; +} + +std::string cheat_info::to_str() const +{ + std::string cheat_str = game + "@@@" + description + "@@@" + std::to_string(static_cast(type)) + "@@@" + std::to_string(offset) + "@@@" + red_script + "@@@"; + return cheat_str; +} diff --git a/Utilities/cheat_info.h b/Utilities/cheat_info.h new file mode 100644 index 0000000000..c6b747ac79 --- /dev/null +++ b/Utilities/cheat_info.h @@ -0,0 +1,30 @@ +#pragma once + +#include "stdafx.h" + +enum class cheat_type : u8 +{ + unsigned_8_cheat, + unsigned_16_cheat, + unsigned_32_cheat, + unsigned_64_cheat, + signed_8_cheat, + signed_16_cheat, + signed_32_cheat, + signed_64_cheat, + max +}; + +constexpr u8 cheat_type_max = static_cast(cheat_type::max); + +struct cheat_info +{ + std::string game; + std::string description; + cheat_type type = cheat_type::max; + u32 offset{}; + std::string red_script; + + bool from_str(const std::string& cheat_line); + std::string to_str() const; +}; diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index add72b7d67..c022b509a7 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -35,6 +35,7 @@ target_sources(rpcs3_emu PRIVATE ../util/yaml.cpp ../util/cereal.cpp ../../Utilities/bin_patch.cpp + ../../Utilities/cheat_info.cpp ../../Utilities/cond.cpp ../../Utilities/Config.cpp ../../Utilities/dynamic_library.cpp diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 385a720b98..b810d8f13e 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -69,6 +69,7 @@ + true true @@ -446,6 +447,7 @@ + true true diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 5ac69c570a..5a4eabec1a 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -950,6 +950,9 @@ Emu\Audio\Pulse + + Utilities + @@ -1822,6 +1825,9 @@ Emu\Audio\Pulse + + Utilities + diff --git a/rpcs3/rpcs3qt/cheat_manager.cpp b/rpcs3/rpcs3qt/cheat_manager.cpp index ecd59cc754..ff3dc6f78c 100644 --- a/rpcs3/rpcs3qt/cheat_manager.cpp +++ b/rpcs3/rpcs3qt/cheat_manager.cpp @@ -47,31 +47,6 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } -namespace YAML -{ - template <> - struct convert - { - static bool decode(const Node& node, cheat_info& rhs) - { - if (node.size() != 3) - { - return false; - } - - rhs.description = node[0].as(); - u64 type64 = 0; - if (!cfg::try_to_enum_value(&type64, &fmt_class_string::format, node[1].Scalar())) - return false; - if (type64 >= cheat_type_max) - return false; - rhs.type = cheat_type{::narrow(type64)}; - rhs.red_script = node[2].as(); - return true; - } - }; -} // namespace YAML - YAML::Emitter& operator<<(YAML::Emitter& out, const cheat_info& rhs) { std::string type_formatted; @@ -82,32 +57,6 @@ YAML::Emitter& operator<<(YAML::Emitter& out, const cheat_info& rhs) return out; } -bool cheat_info::from_str(const std::string& cheat_line) -{ - auto cheat_vec = fmt::split(cheat_line, {"@@@"}, false); - - s64 val64 = 0; - if (cheat_vec.size() != 5 || !cfg::try_to_int64(&val64, cheat_vec[2], 0, cheat_type_max - 1)) - { - log_cheat.fatal("Failed to parse cheat line"); - return false; - } - - game = cheat_vec[0]; - description = cheat_vec[1]; - type = cheat_type{::narrow(val64)}; - offset = std::stoul(cheat_vec[3]); - red_script = cheat_vec[4]; - - return true; -} - -std::string cheat_info::to_str() const -{ - std::string cheat_str = game + "@@@" + description + "@@@" + std::to_string(static_cast(type)) + "@@@" + std::to_string(offset) + "@@@" + red_script + "@@@"; - return cheat_str; -} - cheat_engine::cheat_engine() { const std::string path = patch_engine::get_patches_path() + m_cheats_filename; @@ -125,10 +74,25 @@ cheat_engine::cheat_engine() for (const auto& yml_cheat : yml_cheats) { const std::string& game_name = yml_cheat.first.Scalar(); + for (const auto& yml_offset : yml_cheat.second) { - const u32 offset = yml_offset.first.as(); - cheat_info cheat = yml_offset.second.as(); + std::string error; + + const u32 offset = get_yaml_node_value(yml_offset.first, error); + if (!error.empty()) + { + log_cheat.error("Error parsing %s: node key %s is not a u32 offset", path, yml_offset.first.Scalar()); + return; + } + + cheat_info cheat = get_yaml_node_value(yml_offset.second, error); + if (!error.empty()) + { + log_cheat.error("Error parsing %s: node %s is not a cheat_info node", path, yml_offset.first.Scalar()); + return; + } + cheat.game = game_name; cheat.offset = offset; cheats[game_name][offset] = std::move(cheat); @@ -659,7 +623,8 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent) connect(tbl_cheats, &QTableWidget::cellChanged, [this](int row, int column) { - if (!tbl_cheats->item(row, column)) + QTableWidgetItem* item = tbl_cheats->item(row, column); + if (!item) { return; } @@ -679,8 +644,8 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent) switch (column) { - case cheat_table_columns::description: cheat->description = tbl_cheats->item(row, cheat_table_columns::description)->text().toStdString(); break; - case cheat_table_columns::script: cheat->red_script = tbl_cheats->item(row, cheat_table_columns::script)->text().toStdString(); break; + case cheat_table_columns::description: cheat->description = item->text().toStdString(); break; + case cheat_table_columns::script: cheat->red_script = item->text().toStdString(); break; default: break; } @@ -1029,7 +994,7 @@ void cheat_manager_dialog::update_cheat_list() { size_t num_rows = 0; for (const auto& name : g_cheat.cheats) - num_rows += g_cheat.cheats[name.first].size(); + num_rows += name.second.size(); tbl_cheats->setRowCount(::narrow(num_rows)); @@ -1038,7 +1003,7 @@ void cheat_manager_dialog::update_cheat_list() const QSignalBlocker blocker(tbl_cheats); for (const auto& game : g_cheat.cheats) { - for (const auto& offset : g_cheat.cheats[game.first]) + for (const auto& offset : game.second) { QTableWidgetItem* item_game = new QTableWidgetItem(QString::fromStdString(offset.second.game)); item_game->setFlags(item_game->flags() & ~Qt::ItemIsEditable); diff --git a/rpcs3/rpcs3qt/cheat_manager.h b/rpcs3/rpcs3qt/cheat_manager.h index ef5432021e..7b1b26cc78 100644 --- a/rpcs3/rpcs3qt/cheat_manager.h +++ b/rpcs3/rpcs3qt/cheat_manager.h @@ -8,32 +8,7 @@ #include #include -enum class cheat_type : u8 -{ - unsigned_8_cheat, - unsigned_16_cheat, - unsigned_32_cheat, - unsigned_64_cheat, - signed_8_cheat, - signed_16_cheat, - signed_32_cheat, - signed_64_cheat, - max -}; - -constexpr u8 cheat_type_max = static_cast(cheat_type::max); - -struct cheat_info -{ - std::string game; - std::string description; - cheat_type type = cheat_type::max; - u32 offset{}; - std::string red_script; - - bool from_str(const std::string& cheat_line); - std::string to_str() const; -}; +#include "Utilities/cheat_info.h" class cheat_engine { diff --git a/rpcs3/util/yaml.cpp b/rpcs3/util/yaml.cpp index dcafcdf650..1f0716c02a 100644 --- a/rpcs3/util/yaml.cpp +++ b/rpcs3/util/yaml.cpp @@ -1,5 +1,32 @@ #include "util/yaml.hpp" #include "Utilities/types.h" +#include "Utilities/cheat_info.h" +#include "Utilities/Config.h" + +namespace YAML +{ + template <> + struct convert + { + static bool decode(const Node& node, cheat_info& rhs) + { + if (node.size() != 3) + { + return false; + } + + rhs.description = node[0].Scalar(); + u64 type64 = 0; + if (!cfg::try_to_enum_value(&type64, &fmt_class_string::format, node[1].Scalar())) + return false; + if (type64 >= cheat_type_max) + return false; + rhs.type = cheat_type{::narrow(type64)}; + rhs.red_script = node[2].Scalar(); + return true; + } + }; +} // namespace YAML std::pair yaml_load(const std::string& from) { @@ -32,5 +59,7 @@ T get_yaml_node_value(YAML::Node node, std::string& error_message) return {}; } +template u32 get_yaml_node_value(YAML::Node, std::string&); template u64 get_yaml_node_value(YAML::Node, std::string&); template f64 get_yaml_node_value(YAML::Node, std::string&); +template cheat_info get_yaml_node_value(YAML::Node, std::string&);