mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 23:06:43 +08:00 
			
		
		
		
	Merge pull request #2279 from lioncash/cheat-global
file_sys/cheat_engine: Remove use of global system accessors
This commit is contained in:
		
						commit
						819dd93257
					
				| @ -460,8 +460,8 @@ Tegra::DebugContext* System::GetGPUDebugContext() const { | |||||||
| void System::RegisterCheatList(const std::vector<FileSys::CheatList>& list, | void System::RegisterCheatList(const std::vector<FileSys::CheatList>& list, | ||||||
|                                const std::string& build_id, VAddr code_region_start, |                                const std::string& build_id, VAddr code_region_start, | ||||||
|                                VAddr code_region_end) { |                                VAddr code_region_end) { | ||||||
|     impl->cheat_engine = |     impl->cheat_engine = std::make_unique<FileSys::CheatEngine>(*this, list, build_id, | ||||||
|         std::make_unique<FileSys::CheatEngine>(list, build_id, code_region_start, code_region_end); |                                                                 code_region_start, code_region_end); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) { | void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) { | ||||||
|  | |||||||
| @ -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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,14 +7,18 @@ | |||||||
| #include <map> | #include <map> | ||||||
| #include <set> | #include <set> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <queue> |  | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| namespace Core::Timing { | namespace Core { | ||||||
| struct EventType; | class System; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | namespace Core::Timing { | ||||||
|  | class CoreTiming; | ||||||
|  | struct EventType; | ||||||
|  | } // namespace Core::Timing
 | ||||||
|  | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| enum class CodeType : u32 { | enum class CodeType : u32 { | ||||||
| @ -133,7 +137,7 @@ public: | |||||||
|     void Execute(); |     void Execute(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     CheatList(ProgramSegment master, ProgramSegment standard); |     CheatList(const Core::System& system_, ProgramSegment master, ProgramSegment standard); | ||||||
| 
 | 
 | ||||||
|     void ProcessBlockPairs(const Block& block); |     void ProcessBlockPairs(const Block& block); | ||||||
|     void ExecuteSingleCheat(const Cheat& cheat); |     void ExecuteSingleCheat(const Cheat& cheat); | ||||||
| @ -183,6 +187,8 @@ private: | |||||||
|     std::map<u64, u64> block_pairs; |     std::map<u64, u64> block_pairs; | ||||||
| 
 | 
 | ||||||
|     std::set<u64> encountered_loops; |     std::set<u64> encountered_loops; | ||||||
|  | 
 | ||||||
|  |     const Core::System* system; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Intermediary class that parses a text file or other disk format for storing cheats into a
 | // Intermediary class that parses a text file or other disk format for storing cheats into a
 | ||||||
| @ -191,10 +197,10 @@ class CheatParser { | |||||||
| public: | public: | ||||||
|     virtual ~CheatParser(); |     virtual ~CheatParser(); | ||||||
| 
 | 
 | ||||||
|     virtual CheatList Parse(const std::vector<u8>& data) const = 0; |     virtual CheatList Parse(const Core::System& system, const std::vector<u8>& data) const = 0; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     CheatList MakeCheatList(CheatList::ProgramSegment master, |     CheatList MakeCheatList(const Core::System& system_, CheatList::ProgramSegment master, | ||||||
|                             CheatList::ProgramSegment standard) const; |                             CheatList::ProgramSegment standard) const; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -203,7 +209,7 @@ class TextCheatParser final : public CheatParser { | |||||||
| public: | public: | ||||||
|     ~TextCheatParser() override; |     ~TextCheatParser() override; | ||||||
| 
 | 
 | ||||||
|     CheatList Parse(const std::vector<u8>& data) const override; |     CheatList Parse(const Core::System& system, const std::vector<u8>& data) const override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     std::array<u8, 16> ParseSingleLineCheat(const std::string& line) const; |     std::array<u8, 16> ParseSingleLineCheat(const std::string& line) const; | ||||||
| @ -212,16 +218,17 @@ private: | |||||||
| // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming
 | // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming
 | ||||||
| class CheatEngine final { | class CheatEngine final { | ||||||
| public: | public: | ||||||
|     CheatEngine(std::vector<CheatList> cheats, const std::string& build_id, VAddr code_region_start, |     CheatEngine(Core::System& system_, std::vector<CheatList> cheats_, const std::string& build_id, | ||||||
|                 VAddr code_region_end); |                 VAddr code_region_start, VAddr code_region_end); | ||||||
|     ~CheatEngine(); |     ~CheatEngine(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void FrameCallback(u64 userdata, int cycles_late); |     void FrameCallback(u64 userdata, s64 cycles_late); | ||||||
| 
 |  | ||||||
|     Core::Timing::EventType* event; |  | ||||||
| 
 | 
 | ||||||
|     std::vector<CheatList> cheats; |     std::vector<CheatList> cheats; | ||||||
|  | 
 | ||||||
|  |     Core::Timing::EventType* event; | ||||||
|  |     Core::Timing::CoreTiming& core_timing; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FileSys
 | ||||||
|  | |||||||
| @ -233,7 +233,7 @@ bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const { | |||||||
|     return !CollectPatches(patch_dirs, build_id).empty(); |     return !CollectPatches(patch_dirs, build_id).empty(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static std::optional<CheatList> ReadCheatFileFromFolder(u64 title_id, | static std::optional<CheatList> ReadCheatFileFromFolder(const Core::System& system, u64 title_id, | ||||||
|                                                         const std::array<u8, 0x20>& build_id_, |                                                         const std::array<u8, 0x20>& build_id_, | ||||||
|                                                         const VirtualDir& base_path, bool upper) { |                                                         const VirtualDir& base_path, bool upper) { | ||||||
|     const auto build_id_raw = Common::HexArrayToString(build_id_, upper); |     const auto build_id_raw = Common::HexArrayToString(build_id_, upper); | ||||||
| @ -254,28 +254,28 @@ static std::optional<CheatList> ReadCheatFileFromFolder(u64 title_id, | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     TextCheatParser parser; |     TextCheatParser parser; | ||||||
|     return parser.Parse(data); |     return parser.Parse(system, data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<CheatList> PatchManager::CreateCheatList(const std::array<u8, 32>& build_id_) const { | std::vector<CheatList> PatchManager::CreateCheatList(const Core::System& system, | ||||||
|     std::vector<CheatList> out; |                                                      const std::array<u8, 32>& build_id_) const { | ||||||
| 
 |  | ||||||
|     const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); |     const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); | ||||||
|     auto patch_dirs = load_dir->GetSubdirectories(); |     auto patch_dirs = load_dir->GetSubdirectories(); | ||||||
|     std::sort(patch_dirs.begin(), patch_dirs.end(), |     std::sort(patch_dirs.begin(), patch_dirs.end(), | ||||||
|               [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); |               [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); | ||||||
| 
 | 
 | ||||||
|  |     std::vector<CheatList> out; | ||||||
|     out.reserve(patch_dirs.size()); |     out.reserve(patch_dirs.size()); | ||||||
|     for (const auto& subdir : patch_dirs) { |     for (const auto& subdir : patch_dirs) { | ||||||
|         auto cheats_dir = subdir->GetSubdirectory("cheats"); |         auto cheats_dir = subdir->GetSubdirectory("cheats"); | ||||||
|         if (cheats_dir != nullptr) { |         if (cheats_dir != nullptr) { | ||||||
|             auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, true); |             auto res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, true); | ||||||
|             if (res.has_value()) { |             if (res.has_value()) { | ||||||
|                 out.push_back(std::move(*res)); |                 out.push_back(std::move(*res)); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, false); |             res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, false); | ||||||
|             if (res.has_value()) |             if (res.has_value()) | ||||||
|                 out.push_back(std::move(*res)); |                 out.push_back(std::move(*res)); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -12,6 +12,10 @@ | |||||||
| #include "core/file_sys/nca_metadata.h" | #include "core/file_sys/nca_metadata.h" | ||||||
| #include "core/file_sys/vfs.h" | #include "core/file_sys/vfs.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| class NCA; | class NCA; | ||||||
| @ -47,7 +51,8 @@ public: | |||||||
|     bool HasNSOPatch(const std::array<u8, 0x20>& build_id) const; |     bool HasNSOPatch(const std::array<u8, 0x20>& build_id) const; | ||||||
| 
 | 
 | ||||||
|     // Creates a CheatList object with all
 |     // Creates a CheatList object with all
 | ||||||
|     std::vector<CheatList> CreateCheatList(const std::array<u8, 0x20>& build_id) const; |     std::vector<CheatList> CreateCheatList(const Core::System& system, | ||||||
|  |                                            const std::array<u8, 0x20>& build_id) const; | ||||||
| 
 | 
 | ||||||
|     // Currently tracked RomFS patches:
 |     // Currently tracked RomFS patches:
 | ||||||
|     // - Game Updates
 |     // - Game Updates
 | ||||||
|  | |||||||
| @ -169,11 +169,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | |||||||
| 
 | 
 | ||||||
|     // Apply cheats if they exist and the program has a valid title ID
 |     // Apply cheats if they exist and the program has a valid title ID
 | ||||||
|     if (pm) { |     if (pm) { | ||||||
|         const auto cheats = pm->CreateCheatList(nso_header.build_id); |         auto& system = Core::System::GetInstance(); | ||||||
|  |         const auto cheats = pm->CreateCheatList(system, nso_header.build_id); | ||||||
|         if (!cheats.empty()) { |         if (!cheats.empty()) { | ||||||
|             Core::System::GetInstance().RegisterCheatList( |             system.RegisterCheatList(cheats, Common::HexArrayToString(nso_header.build_id), | ||||||
|                 cheats, Common::HexArrayToString(nso_header.build_id), load_base, |                                      load_base, load_base + program_image.size()); | ||||||
|                 load_base + program_image.size()); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user