|
|
@ -11,14 +11,13 @@
|
|
|
|
#include "core/core_timing_util.h"
|
|
|
|
#include "core/core_timing_util.h"
|
|
|
|
#include "core/file_sys/cheat_engine.h"
|
|
|
|
#include "core/file_sys/cheat_engine.h"
|
|
|
|
#include "core/hle/kernel/process.h"
|
|
|
|
#include "core/hle/kernel/process.h"
|
|
|
|
#include "core/hle/service/hid/controllers/controller_base.h"
|
|
|
|
|
|
|
|
#include "core/hle/service/hid/controllers/npad.h"
|
|
|
|
#include "core/hle/service/hid/controllers/npad.h"
|
|
|
|
#include "core/hle/service/hid/hid.h"
|
|
|
|
#include "core/hle/service/hid/hid.h"
|
|
|
|
#include "core/hle/service/sm/sm.h"
|
|
|
|
#include "core/hle/service/sm/sm.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace FileSys {
|
|
|
|
namespace FileSys {
|
|
|
|
|
|
|
|
|
|
|
|
constexpr u64 CHEAT_ENGINE_TICKS = Core::Timing::BASE_CLOCK_RATE / 60;
|
|
|
|
constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 60);
|
|
|
|
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
|
|
|
|
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
|
|
|
|
|
|
|
|
|
|
|
|
u64 Cheat::Address() const {
|
|
|
|
u64 Cheat::Address() const {
|
|
|
@ -77,8 +76,8 @@ void CheatList::Execute() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CheatList::CheatList(ProgramSegment master, ProgramSegment standard)
|
|
|
|
CheatList::CheatList(const Core::System& system_, ProgramSegment master, ProgramSegment standard)
|
|
|
|
: master_list(master), standard_list(standard) {}
|
|
|
|
: master_list{std::move(master)}, standard_list{std::move(standard)}, system{&system_} {}
|
|
|
|
|
|
|
|
|
|
|
|
bool CheatList::EvaluateConditional(const Cheat& cheat) const {
|
|
|
|
bool CheatList::EvaluateConditional(const Cheat& cheat) const {
|
|
|
|
using ComparisonFunction = bool (*)(u64, u64);
|
|
|
|
using ComparisonFunction = bool (*)(u64, u64);
|
|
|
@ -89,10 +88,8 @@ bool CheatList::EvaluateConditional(const Cheat& cheat) const {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (cheat.type == CodeType::ConditionalInput) {
|
|
|
|
if (cheat.type == CodeType::ConditionalInput) {
|
|
|
|
const auto applet_resource = Core::System::GetInstance()
|
|
|
|
const auto applet_resource =
|
|
|
|
.ServiceManager()
|
|
|
|
system->ServiceManager().GetService<Service::HID::Hid>("hid")->GetAppletResource();
|
|
|
|
.GetService<Service::HID::Hid>("hid")
|
|
|
|
|
|
|
|
->GetAppletResource();
|
|
|
|
|
|
|
|
if (applet_resource == nullptr) {
|
|
|
|
if (applet_resource == nullptr) {
|
|
|
|
LOG_WARNING(
|
|
|
|
LOG_WARNING(
|
|
|
|
Common_Filesystem,
|
|
|
|
Common_Filesystem,
|
|
|
@ -188,8 +185,9 @@ void CheatList::Loop(const Cheat& cheat) {
|
|
|
|
ASSERT(iter != block_pairs.end());
|
|
|
|
ASSERT(iter != block_pairs.end());
|
|
|
|
ASSERT(iter->first < iter->second);
|
|
|
|
ASSERT(iter->first < iter->second);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = cheat.Value(4, 4); i >= 0; --i) {
|
|
|
|
const s32 initial_value = static_cast<s32>(cheat.Value(4, sizeof(s32)));
|
|
|
|
register_3 = i;
|
|
|
|
for (s32 i = initial_value; i >= 0; --i) {
|
|
|
|
|
|
|
|
register_3 = static_cast<u64>(i);
|
|
|
|
for (std::size_t c = iter->first + 1; c < iter->second; ++c) {
|
|
|
|
for (std::size_t c = iter->first + 1; c < iter->second; ++c) {
|
|
|
|
current_index = c;
|
|
|
|
current_index = c;
|
|
|
|
ExecuteSingleCheat(
|
|
|
|
ExecuteSingleCheat(
|
|
|
@ -320,14 +318,14 @@ void CheatList::ExecuteBlock(const Block& block) {
|
|
|
|
|
|
|
|
|
|
|
|
CheatParser::~CheatParser() = default;
|
|
|
|
CheatParser::~CheatParser() = default;
|
|
|
|
|
|
|
|
|
|
|
|
CheatList CheatParser::MakeCheatList(CheatList::ProgramSegment master,
|
|
|
|
CheatList CheatParser::MakeCheatList(const Core::System& system, CheatList::ProgramSegment master,
|
|
|
|
CheatList::ProgramSegment standard) const {
|
|
|
|
CheatList::ProgramSegment standard) const {
|
|
|
|
return {master, standard};
|
|
|
|
return {system, std::move(master), std::move(standard)};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TextCheatParser::~TextCheatParser() = default;
|
|
|
|
TextCheatParser::~TextCheatParser() = default;
|
|
|
|
|
|
|
|
|
|
|
|
CheatList TextCheatParser::Parse(const std::vector<u8>& data) const {
|
|
|
|
CheatList TextCheatParser::Parse(const Core::System& system, const std::vector<u8>& data) const {
|
|
|
|
std::stringstream ss;
|
|
|
|
std::stringstream ss;
|
|
|
|
ss.write(reinterpret_cast<const char*>(data.data()), data.size());
|
|
|
|
ss.write(reinterpret_cast<const char*>(data.data()), data.size());
|
|
|
|
|
|
|
|
|
|
|
@ -375,7 +373,7 @@ CheatList TextCheatParser::Parse(const std::vector<u8>& data) const {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return MakeCheatList(master_list, standard_list);
|
|
|
|
return MakeCheatList(system, master_list, standard_list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::array<u8, 16> TextCheatParser::ParseSingleLineCheat(const std::string& line) const {
|
|
|
|
std::array<u8, 16> TextCheatParser::ParseSingleLineCheat(const std::string& line) const {
|
|
|
@ -460,16 +458,16 @@ void MemoryWriteImpl(u32 width, VAddr addr, u64 value) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CheatEngine::CheatEngine(std::vector<CheatList> cheats, const std::string& build_id,
|
|
|
|
CheatEngine::CheatEngine(Core::System& system, std::vector<CheatList> cheats_,
|
|
|
|
VAddr code_region_start, VAddr code_region_end)
|
|
|
|
const std::string& build_id, VAddr code_region_start,
|
|
|
|
: cheats(std::move(cheats)) {
|
|
|
|
VAddr code_region_end)
|
|
|
|
auto& core_timing{Core::System::GetInstance().CoreTiming()};
|
|
|
|
: cheats{std::move(cheats_)}, core_timing{system.CoreTiming()} {
|
|
|
|
event = core_timing.RegisterEvent(
|
|
|
|
event = core_timing.RegisterEvent(
|
|
|
|
"CheatEngine::FrameCallback::" + build_id,
|
|
|
|
"CheatEngine::FrameCallback::" + build_id,
|
|
|
|
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
|
|
|
|
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
|
|
|
|
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);
|
|
|
|
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);
|
|
|
|
|
|
|
|
|
|
|
|
const auto& vm_manager = Core::System::GetInstance().CurrentProcess()->VMManager();
|
|
|
|
const auto& vm_manager = system.CurrentProcess()->VMManager();
|
|
|
|
for (auto& list : this->cheats) {
|
|
|
|
for (auto& list : this->cheats) {
|
|
|
|
list.SetMemoryParameters(code_region_start, vm_manager.GetHeapRegionBaseAddress(),
|
|
|
|
list.SetMemoryParameters(code_region_start, vm_manager.GetHeapRegionBaseAddress(),
|
|
|
|
code_region_end, vm_manager.GetHeapRegionEndAddress(),
|
|
|
|
code_region_end, vm_manager.GetHeapRegionEndAddress(),
|
|
|
@ -478,15 +476,14 @@ CheatEngine::CheatEngine(std::vector<CheatList> cheats, const std::string& build
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CheatEngine::~CheatEngine() {
|
|
|
|
CheatEngine::~CheatEngine() {
|
|
|
|
auto& core_timing{Core::System::GetInstance().CoreTiming()};
|
|
|
|
|
|
|
|
core_timing.UnscheduleEvent(event, 0);
|
|
|
|
core_timing.UnscheduleEvent(event, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CheatEngine::FrameCallback(u64 userdata, int cycles_late) {
|
|
|
|
void CheatEngine::FrameCallback(u64 userdata, s64 cycles_late) {
|
|
|
|
for (auto& list : cheats)
|
|
|
|
for (auto& list : cheats) {
|
|
|
|
list.Execute();
|
|
|
|
list.Execute();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto& core_timing{Core::System::GetInstance().CoreTiming()};
|
|
|
|
|
|
|
|
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - cycles_late, event);
|
|
|
|
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - cycles_late, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|