summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/file_sys/cheat_engine.cpp43
-rw-r--r--src/core/file_sys/cheat_engine.h29
-rw-r--r--src/core/file_sys/patch_manager.cpp14
-rw-r--r--src/core/file_sys/patch_manager.h7
-rw-r--r--src/core/loader/nso.cpp8
6 files changed, 57 insertions, 48 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index a88e332be..4fe77c25b 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -460,8 +460,8 @@ Tegra::DebugContext* System::GetGPUDebugContext() const {
460void System::RegisterCheatList(const std::vector<FileSys::CheatList>& list, 460void System::RegisterCheatList(const std::vector<FileSys::CheatList>& list,
461 const std::string& build_id, VAddr code_region_start, 461 const std::string& build_id, VAddr code_region_start,
462 VAddr code_region_end) { 462 VAddr code_region_end) {
463 impl->cheat_engine = 463 impl->cheat_engine = std::make_unique<FileSys::CheatEngine>(*this, list, build_id,
464 std::make_unique<FileSys::CheatEngine>(list, build_id, code_region_start, code_region_end); 464 code_region_start, code_region_end);
465} 465}
466 466
467void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) { 467void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
diff --git a/src/core/file_sys/cheat_engine.cpp b/src/core/file_sys/cheat_engine.cpp
index 09ca9d705..247fbc864 100644
--- a/src/core/file_sys/cheat_engine.cpp
+++ b/src/core/file_sys/cheat_engine.cpp
@@ -11,14 +11,13 @@
11#include "core/core_timing_util.h" 11#include "core/core_timing_util.h"
12#include "core/file_sys/cheat_engine.h" 12#include "core/file_sys/cheat_engine.h"
13#include "core/hle/kernel/process.h" 13#include "core/hle/kernel/process.h"
14#include "core/hle/service/hid/controllers/controller_base.h"
15#include "core/hle/service/hid/controllers/npad.h" 14#include "core/hle/service/hid/controllers/npad.h"
16#include "core/hle/service/hid/hid.h" 15#include "core/hle/service/hid/hid.h"
17#include "core/hle/service/sm/sm.h" 16#include "core/hle/service/sm/sm.h"
18 17
19namespace FileSys { 18namespace FileSys {
20 19
21constexpr u64 CHEAT_ENGINE_TICKS = Core::Timing::BASE_CLOCK_RATE / 60; 20constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 60);
22constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; 21constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
23 22
24u64 Cheat::Address() const { 23u64 Cheat::Address() const {
@@ -77,8 +76,8 @@ void CheatList::Execute() {
77 } 76 }
78} 77}
79 78
80CheatList::CheatList(ProgramSegment master, ProgramSegment standard) 79CheatList::CheatList(const Core::System& system_, ProgramSegment master, ProgramSegment standard)
81 : master_list(master), standard_list(standard) {} 80 : master_list{std::move(master)}, standard_list{std::move(standard)}, system{&system_} {}
82 81
83bool CheatList::EvaluateConditional(const Cheat& cheat) const { 82bool CheatList::EvaluateConditional(const Cheat& cheat) const {
84 using ComparisonFunction = bool (*)(u64, u64); 83 using ComparisonFunction = bool (*)(u64, u64);
@@ -89,10 +88,8 @@ bool CheatList::EvaluateConditional(const Cheat& cheat) const {
89 }; 88 };
90 89
91 if (cheat.type == CodeType::ConditionalInput) { 90 if (cheat.type == CodeType::ConditionalInput) {
92 const auto applet_resource = Core::System::GetInstance() 91 const auto applet_resource =
93 .ServiceManager() 92 system->ServiceManager().GetService<Service::HID::Hid>("hid")->GetAppletResource();
94 .GetService<Service::HID::Hid>("hid")
95 ->GetAppletResource();
96 if (applet_resource == nullptr) { 93 if (applet_resource == nullptr) {
97 LOG_WARNING( 94 LOG_WARNING(
98 Common_Filesystem, 95 Common_Filesystem,
@@ -188,8 +185,9 @@ void CheatList::Loop(const Cheat& cheat) {
188 ASSERT(iter != block_pairs.end()); 185 ASSERT(iter != block_pairs.end());
189 ASSERT(iter->first < iter->second); 186 ASSERT(iter->first < iter->second);
190 187
191 for (int i = cheat.Value(4, 4); i >= 0; --i) { 188 const s32 initial_value = static_cast<s32>(cheat.Value(4, sizeof(s32)));
192 register_3 = i; 189 for (s32 i = initial_value; i >= 0; --i) {
190 register_3 = static_cast<u64>(i);
193 for (std::size_t c = iter->first + 1; c < iter->second; ++c) { 191 for (std::size_t c = iter->first + 1; c < iter->second; ++c) {
194 current_index = c; 192 current_index = c;
195 ExecuteSingleCheat( 193 ExecuteSingleCheat(
@@ -320,14 +318,14 @@ void CheatList::ExecuteBlock(const Block& block) {
320 318
321CheatParser::~CheatParser() = default; 319CheatParser::~CheatParser() = default;
322 320
323CheatList CheatParser::MakeCheatList(CheatList::ProgramSegment master, 321CheatList CheatParser::MakeCheatList(const Core::System& system, CheatList::ProgramSegment master,
324 CheatList::ProgramSegment standard) const { 322 CheatList::ProgramSegment standard) const {
325 return {master, standard}; 323 return {system, std::move(master), std::move(standard)};
326} 324}
327 325
328TextCheatParser::~TextCheatParser() = default; 326TextCheatParser::~TextCheatParser() = default;
329 327
330CheatList TextCheatParser::Parse(const std::vector<u8>& data) const { 328CheatList TextCheatParser::Parse(const Core::System& system, const std::vector<u8>& data) const {
331 std::stringstream ss; 329 std::stringstream ss;
332 ss.write(reinterpret_cast<const char*>(data.data()), data.size()); 330 ss.write(reinterpret_cast<const char*>(data.data()), data.size());
333 331
@@ -375,7 +373,7 @@ CheatList TextCheatParser::Parse(const std::vector<u8>& data) const {
375 } 373 }
376 } 374 }
377 375
378 return MakeCheatList(master_list, standard_list); 376 return MakeCheatList(system, master_list, standard_list);
379} 377}
380 378
381std::array<u8, 16> TextCheatParser::ParseSingleLineCheat(const std::string& line) const { 379std::array<u8, 16> TextCheatParser::ParseSingleLineCheat(const std::string& line) const {
@@ -460,16 +458,16 @@ void MemoryWriteImpl(u32 width, VAddr addr, u64 value) {
460 } 458 }
461} 459}
462 460
463CheatEngine::CheatEngine(std::vector<CheatList> cheats, const std::string& build_id, 461CheatEngine::CheatEngine(Core::System& system, std::vector<CheatList> cheats_,
464 VAddr code_region_start, VAddr code_region_end) 462 const std::string& build_id, VAddr code_region_start,
465 : cheats(std::move(cheats)) { 463 VAddr code_region_end)
466 auto& core_timing{Core::System::GetInstance().CoreTiming()}; 464 : cheats{std::move(cheats_)}, core_timing{system.CoreTiming()} {
467 event = core_timing.RegisterEvent( 465 event = core_timing.RegisterEvent(
468 "CheatEngine::FrameCallback::" + build_id, 466 "CheatEngine::FrameCallback::" + build_id,
469 [this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); }); 467 [this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
470 core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event); 468 core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);
471 469
472 const auto& vm_manager = Core::System::GetInstance().CurrentProcess()->VMManager(); 470 const auto& vm_manager = system.CurrentProcess()->VMManager();
473 for (auto& list : this->cheats) { 471 for (auto& list : this->cheats) {
474 list.SetMemoryParameters(code_region_start, vm_manager.GetHeapRegionBaseAddress(), 472 list.SetMemoryParameters(code_region_start, vm_manager.GetHeapRegionBaseAddress(),
475 code_region_end, vm_manager.GetHeapRegionEndAddress(), 473 code_region_end, vm_manager.GetHeapRegionEndAddress(),
@@ -478,15 +476,14 @@ CheatEngine::CheatEngine(std::vector<CheatList> cheats, const std::string& build
478} 476}
479 477
480CheatEngine::~CheatEngine() { 478CheatEngine::~CheatEngine() {
481 auto& core_timing{Core::System::GetInstance().CoreTiming()};
482 core_timing.UnscheduleEvent(event, 0); 479 core_timing.UnscheduleEvent(event, 0);
483} 480}
484 481
485void CheatEngine::FrameCallback(u64 userdata, int cycles_late) { 482void CheatEngine::FrameCallback(u64 userdata, s64 cycles_late) {
486 for (auto& list : cheats) 483 for (auto& list : cheats) {
487 list.Execute(); 484 list.Execute();
485 }
488 486
489 auto& core_timing{Core::System::GetInstance().CoreTiming()};
490 core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - cycles_late, event); 487 core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - cycles_late, event);
491} 488}
492 489
diff --git a/src/core/file_sys/cheat_engine.h b/src/core/file_sys/cheat_engine.h
index 7ed69a2c8..ac22a82cb 100644
--- a/src/core/file_sys/cheat_engine.h
+++ b/src/core/file_sys/cheat_engine.h
@@ -7,13 +7,17 @@
7#include <map> 7#include <map>
8#include <set> 8#include <set>
9#include <vector> 9#include <vector>
10#include <queue>
11#include "common/bit_field.h" 10#include "common/bit_field.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13 12
13namespace Core {
14class System;
15}
16
14namespace Core::Timing { 17namespace Core::Timing {
18class CoreTiming;
15struct EventType; 19struct EventType;
16} 20} // namespace Core::Timing
17 21
18namespace FileSys { 22namespace FileSys {
19 23
@@ -133,7 +137,7 @@ public:
133 void Execute(); 137 void Execute();
134 138
135private: 139private:
136 CheatList(ProgramSegment master, ProgramSegment standard); 140 CheatList(const Core::System& system_, ProgramSegment master, ProgramSegment standard);
137 141
138 void ProcessBlockPairs(const Block& block); 142 void ProcessBlockPairs(const Block& block);
139 void ExecuteSingleCheat(const Cheat& cheat); 143 void ExecuteSingleCheat(const Cheat& cheat);
@@ -183,6 +187,8 @@ private:
183 std::map<u64, u64> block_pairs; 187 std::map<u64, u64> block_pairs;
184 188
185 std::set<u64> encountered_loops; 189 std::set<u64> encountered_loops;
190
191 const Core::System* system;
186}; 192};
187 193
188// Intermediary class that parses a text file or other disk format for storing cheats into a 194// Intermediary class that parses a text file or other disk format for storing cheats into a
@@ -191,10 +197,10 @@ class CheatParser {
191public: 197public:
192 virtual ~CheatParser(); 198 virtual ~CheatParser();
193 199
194 virtual CheatList Parse(const std::vector<u8>& data) const = 0; 200 virtual CheatList Parse(const Core::System& system, const std::vector<u8>& data) const = 0;
195 201
196protected: 202protected:
197 CheatList MakeCheatList(CheatList::ProgramSegment master, 203 CheatList MakeCheatList(const Core::System& system_, CheatList::ProgramSegment master,
198 CheatList::ProgramSegment standard) const; 204 CheatList::ProgramSegment standard) const;
199}; 205};
200 206
@@ -203,7 +209,7 @@ class TextCheatParser final : public CheatParser {
203public: 209public:
204 ~TextCheatParser() override; 210 ~TextCheatParser() override;
205 211
206 CheatList Parse(const std::vector<u8>& data) const override; 212 CheatList Parse(const Core::System& system, const std::vector<u8>& data) const override;
207 213
208private: 214private:
209 std::array<u8, 16> ParseSingleLineCheat(const std::string& line) const; 215 std::array<u8, 16> ParseSingleLineCheat(const std::string& line) const;
@@ -212,16 +218,17 @@ private:
212// Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming 218// Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming
213class CheatEngine final { 219class CheatEngine final {
214public: 220public:
215 CheatEngine(std::vector<CheatList> cheats, const std::string& build_id, VAddr code_region_start, 221 CheatEngine(Core::System& system_, std::vector<CheatList> cheats_, const std::string& build_id,
216 VAddr code_region_end); 222 VAddr code_region_start, VAddr code_region_end);
217 ~CheatEngine(); 223 ~CheatEngine();
218 224
219private: 225private:
220 void FrameCallback(u64 userdata, int cycles_late); 226 void FrameCallback(u64 userdata, s64 cycles_late);
221
222 Core::Timing::EventType* event;
223 227
224 std::vector<CheatList> cheats; 228 std::vector<CheatList> cheats;
229
230 Core::Timing::EventType* event;
231 Core::Timing::CoreTiming& core_timing;
225}; 232};
226 233
227} // namespace FileSys 234} // namespace FileSys
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 2b09e5d35..58884b4a0 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -233,7 +233,7 @@ bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const {
233 return !CollectPatches(patch_dirs, build_id).empty(); 233 return !CollectPatches(patch_dirs, build_id).empty();
234} 234}
235 235
236static std::optional<CheatList> ReadCheatFileFromFolder(u64 title_id, 236static std::optional<CheatList> ReadCheatFileFromFolder(const Core::System& system, u64 title_id,
237 const std::array<u8, 0x20>& build_id_, 237 const std::array<u8, 0x20>& build_id_,
238 const VirtualDir& base_path, bool upper) { 238 const VirtualDir& base_path, bool upper) {
239 const auto build_id_raw = Common::HexArrayToString(build_id_, upper); 239 const auto build_id_raw = Common::HexArrayToString(build_id_, upper);
@@ -254,28 +254,28 @@ static std::optional<CheatList> ReadCheatFileFromFolder(u64 title_id,
254 } 254 }
255 255
256 TextCheatParser parser; 256 TextCheatParser parser;
257 return parser.Parse(data); 257 return parser.Parse(system, data);
258} 258}
259 259
260std::vector<CheatList> PatchManager::CreateCheatList(const std::array<u8, 32>& build_id_) const { 260std::vector<CheatList> PatchManager::CreateCheatList(const Core::System& system,
261 std::vector<CheatList> out; 261 const std::array<u8, 32>& build_id_) const {
262
263 const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); 262 const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
264 auto patch_dirs = load_dir->GetSubdirectories(); 263 auto patch_dirs = load_dir->GetSubdirectories();
265 std::sort(patch_dirs.begin(), patch_dirs.end(), 264 std::sort(patch_dirs.begin(), patch_dirs.end(),
266 [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); 265 [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
267 266
267 std::vector<CheatList> out;
268 out.reserve(patch_dirs.size()); 268 out.reserve(patch_dirs.size());
269 for (const auto& subdir : patch_dirs) { 269 for (const auto& subdir : patch_dirs) {
270 auto cheats_dir = subdir->GetSubdirectory("cheats"); 270 auto cheats_dir = subdir->GetSubdirectory("cheats");
271 if (cheats_dir != nullptr) { 271 if (cheats_dir != nullptr) {
272 auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, true); 272 auto res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, true);
273 if (res.has_value()) { 273 if (res.has_value()) {
274 out.push_back(std::move(*res)); 274 out.push_back(std::move(*res));
275 continue; 275 continue;
276 } 276 }
277 277
278 res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, false); 278 res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, false);
279 if (res.has_value()) 279 if (res.has_value())
280 out.push_back(std::move(*res)); 280 out.push_back(std::move(*res));
281 } 281 }
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h
index 3e3ac6aca..de2672c76 100644
--- a/src/core/file_sys/patch_manager.h
+++ b/src/core/file_sys/patch_manager.h
@@ -12,6 +12,10 @@
12#include "core/file_sys/nca_metadata.h" 12#include "core/file_sys/nca_metadata.h"
13#include "core/file_sys/vfs.h" 13#include "core/file_sys/vfs.h"
14 14
15namespace Core {
16class System;
17}
18
15namespace FileSys { 19namespace FileSys {
16 20
17class NCA; 21class NCA;
@@ -47,7 +51,8 @@ public:
47 bool HasNSOPatch(const std::array<u8, 0x20>& build_id) const; 51 bool HasNSOPatch(const std::array<u8, 0x20>& build_id) const;
48 52
49 // Creates a CheatList object with all 53 // Creates a CheatList object with all
50 std::vector<CheatList> CreateCheatList(const std::array<u8, 0x20>& build_id) const; 54 std::vector<CheatList> CreateCheatList(const Core::System& system,
55 const std::array<u8, 0x20>& build_id) const;
51 56
52 // Currently tracked RomFS patches: 57 // Currently tracked RomFS patches:
53 // - Game Updates 58 // - Game Updates
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 0eb9fd7f7..7494f8a28 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -169,11 +169,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
169 169
170 // Apply cheats if they exist and the program has a valid title ID 170 // Apply cheats if they exist and the program has a valid title ID
171 if (pm) { 171 if (pm) {
172 const auto cheats = pm->CreateCheatList(nso_header.build_id); 172 auto& system = Core::System::GetInstance();
173 const auto cheats = pm->CreateCheatList(system, nso_header.build_id);
173 if (!cheats.empty()) { 174 if (!cheats.empty()) {
174 Core::System::GetInstance().RegisterCheatList( 175 system.RegisterCheatList(cheats, Common::HexArrayToString(nso_header.build_id),
175 cheats, Common::HexArrayToString(nso_header.build_id), load_base, 176 load_base, load_base + program_image.size());
176 load_base + program_image.size());
177 } 177 }
178 } 178 }
179 179