mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	vm_manager: Remove cheat-specific ranges from VMManager
This commit is contained in:
		
							parent
							
								
									7053546687
								
							
						
					
					
						commit
						52ac6419da
					
				| @ -450,8 +450,10 @@ Tegra::DebugContext* System::GetGPUDebugContext() const { | ||||
| } | ||||
| 
 | ||||
| void System::RegisterCheatList(const std::vector<FileSys::CheatList>& list, | ||||
|                                const std::string& build_id) { | ||||
|     impl->cheat_engine = std::make_unique<FileSys::CheatEngine>(list, build_id); | ||||
|                                const std::string& build_id, VAddr code_region_start, | ||||
|                                VAddr code_region_end) { | ||||
|     impl->cheat_engine = | ||||
|         std::make_unique<FileSys::CheatEngine>(list, build_id, code_region_start, code_region_end); | ||||
| } | ||||
| 
 | ||||
| void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) { | ||||
|  | ||||
| @ -254,8 +254,8 @@ public: | ||||
| 
 | ||||
|     std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const; | ||||
| 
 | ||||
|     void RegisterCheatList(const std::vector<FileSys::CheatList>& list, | ||||
|                            const std::string& build_id); | ||||
|     void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id, | ||||
|                            VAddr code_region_start, VAddr code_region_end); | ||||
| 
 | ||||
|     void SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet); | ||||
| 
 | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
| 
 | ||||
| namespace FileSys { | ||||
| 
 | ||||
| constexpr u64 CHEAT_ENGINE_TICKS = CoreTiming::BASE_CLOCK_RATE / 60; | ||||
| constexpr u64 CHEAT_ENGINE_TICKS = Core::Timing::BASE_CLOCK_RATE / 60; | ||||
| constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; | ||||
| 
 | ||||
| u64 Cheat::Address() const { | ||||
| @ -82,7 +82,7 @@ CheatList::CheatList(ProgramSegment master, ProgramSegment standard) | ||||
| 
 | ||||
| bool CheatList::EvaluateConditional(const Cheat& cheat) const { | ||||
|     using ComparisonFunction = bool (*)(u64, u64); | ||||
|     constexpr ComparisonFunction comparison_functions[] = { | ||||
|     constexpr std::array<ComparisonFunction, 6> comparison_functions{ | ||||
|         [](u64 a, u64 b) { return a > b; },  [](u64 a, u64 b) { return a >= b; }, | ||||
|         [](u64 a, u64 b) { return a < b; },  [](u64 a, u64 b) { return a <= b; }, | ||||
|         [](u64 a, u64 b) { return a == b; }, [](u64 a, u64 b) { return a != b; }, | ||||
| @ -103,7 +103,7 @@ bool CheatList::EvaluateConditional(const Cheat& cheat) const { | ||||
|         const auto press_state = | ||||
|             applet_resource | ||||
|                 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad) | ||||
|                 .GetPressState(); | ||||
|                 .GetAndResetPressState(); | ||||
|         return ((press_state & cheat.KeypadValue()) & KEYPAD_BITMASK) != 0; | ||||
|     } | ||||
| 
 | ||||
| @ -112,7 +112,7 @@ bool CheatList::EvaluateConditional(const Cheat& cheat) const { | ||||
|     const auto offset = | ||||
|         cheat.memory_type == MemoryType::MainNSO ? main_region_begin : heap_region_begin; | ||||
|     ASSERT(static_cast<u8>(cheat.comparison_op.Value()) < 6); | ||||
|     const auto* function = comparison_functions[static_cast<u8>(cheat.comparison_op.Value())]; | ||||
|     auto* function = comparison_functions[static_cast<u8>(cheat.comparison_op.Value())]; | ||||
|     const auto addr = cheat.Address() + offset; | ||||
| 
 | ||||
|     return function(reader(cheat.width, SanitizeAddress(addr)), cheat.ValueWidth(8)); | ||||
| @ -157,7 +157,7 @@ void CheatList::ProcessBlockPairs(const Block& block) { | ||||
| void CheatList::WriteImmediate(const Cheat& cheat) { | ||||
|     const auto offset = | ||||
|         cheat.memory_type == MemoryType::MainNSO ? main_region_begin : heap_region_begin; | ||||
|     auto& register_3 = scratch.at(cheat.register_3); | ||||
|     const auto& register_3 = scratch.at(cheat.register_3); | ||||
| 
 | ||||
|     const auto addr = cheat.Address() + offset + register_3; | ||||
|     LOG_DEBUG(Common_Filesystem, "writing value={:016X} to addr={:016X}", addr, | ||||
| @ -166,11 +166,13 @@ void CheatList::WriteImmediate(const Cheat& cheat) { | ||||
| } | ||||
| 
 | ||||
| void CheatList::BeginConditional(const Cheat& cheat) { | ||||
|     if (!EvaluateConditional(cheat)) { | ||||
|         const auto iter = block_pairs.find(current_index); | ||||
|         ASSERT(iter != block_pairs.end()); | ||||
|         current_index = iter->second - 1; | ||||
|     if (EvaluateConditional(cheat)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const auto iter = block_pairs.find(current_index); | ||||
|     ASSERT(iter != block_pairs.end()); | ||||
|     current_index = iter->second - 1; | ||||
| } | ||||
| 
 | ||||
| void CheatList::EndConditional(const Cheat& cheat) { | ||||
| @ -218,7 +220,7 @@ void CheatList::LoadIndexed(const Cheat& cheat) { | ||||
| } | ||||
| 
 | ||||
| void CheatList::StoreIndexed(const Cheat& cheat) { | ||||
|     auto& register_3 = scratch.at(cheat.register_3); | ||||
|     const auto& register_3 = scratch.at(cheat.register_3); | ||||
| 
 | ||||
|     const auto addr = | ||||
|         register_3 + (cheat.add_additional_register.Value() ? scratch.at(cheat.register_6) : 0); | ||||
| @ -229,14 +231,14 @@ void CheatList::StoreIndexed(const Cheat& cheat) { | ||||
| 
 | ||||
| void CheatList::RegisterArithmetic(const Cheat& cheat) { | ||||
|     using ArithmeticFunction = u64 (*)(u64, u64); | ||||
|     constexpr ArithmeticFunction arithmetic_functions[] = { | ||||
|     constexpr std::array<ArithmeticFunction, 5> arithmetic_functions{ | ||||
|         [](u64 a, u64 b) { return a + b; },  [](u64 a, u64 b) { return a - b; }, | ||||
|         [](u64 a, u64 b) { return a * b; },  [](u64 a, u64 b) { return a << b; }, | ||||
|         [](u64 a, u64 b) { return a >> b; }, | ||||
|     }; | ||||
| 
 | ||||
|     using ArithmeticOverflowCheck = bool (*)(u64, u64); | ||||
|     constexpr ArithmeticOverflowCheck arithmetic_overflow_checks[] = { | ||||
|     constexpr std::array<ArithmeticOverflowCheck, 5> arithmetic_overflow_checks{ | ||||
|         [](u64 a, u64 b) { return a > (std::numeric_limits<u64>::max() - b); },       // a + b
 | ||||
|         [](u64 a, u64 b) { return a > (std::numeric_limits<u64>::max() + b); },       // a - b
 | ||||
|         [](u64 a, u64 b) { return a > (std::numeric_limits<u64>::max() / b); },       // a * b
 | ||||
| @ -250,8 +252,8 @@ void CheatList::RegisterArithmetic(const Cheat& cheat) { | ||||
|     auto& register_3 = scratch.at(cheat.register_3); | ||||
| 
 | ||||
|     ASSERT(static_cast<u8>(cheat.arithmetic_op.Value()) < 5); | ||||
|     const auto* function = arithmetic_functions[static_cast<u8>(cheat.arithmetic_op.Value())]; | ||||
|     const auto* overflow_function = | ||||
|     auto* function = arithmetic_functions[static_cast<u8>(cheat.arithmetic_op.Value())]; | ||||
|     auto* overflow_function = | ||||
|         arithmetic_overflow_checks[static_cast<u8>(cheat.arithmetic_op.Value())]; | ||||
|     LOG_DEBUG(Common_Filesystem, "performing arithmetic with register={:01X}, value={:016X}", | ||||
|               cheat.register_3, cheat.ValueWidth(4)); | ||||
| @ -267,11 +269,12 @@ void CheatList::RegisterArithmetic(const Cheat& cheat) { | ||||
| } | ||||
| 
 | ||||
| void CheatList::BeginConditionalInput(const Cheat& cheat) { | ||||
|     if (!EvaluateConditional(cheat)) { | ||||
|         const auto iter = block_pairs.find(current_index); | ||||
|         ASSERT(iter != block_pairs.end()); | ||||
|         current_index = iter->second - 1; | ||||
|     } | ||||
|     if (EvaluateConditional(cheat)) | ||||
|         return; | ||||
| 
 | ||||
|     const auto iter = block_pairs.find(current_index); | ||||
|     ASSERT(iter != block_pairs.end()); | ||||
|     current_index = iter->second - 1; | ||||
| } | ||||
| 
 | ||||
| VAddr CheatList::SanitizeAddress(VAddr in) const { | ||||
| @ -290,7 +293,7 @@ VAddr CheatList::SanitizeAddress(VAddr in) const { | ||||
| 
 | ||||
| void CheatList::ExecuteSingleCheat(const Cheat& cheat) { | ||||
|     using CheatOperationFunction = void (CheatList::*)(const Cheat&); | ||||
|     constexpr CheatOperationFunction cheat_operation_functions[] = { | ||||
|     constexpr std::array<CheatOperationFunction, 9> cheat_operation_functions{ | ||||
|         &CheatList::WriteImmediate,        &CheatList::BeginConditional, | ||||
|         &CheatList::EndConditional,        &CheatList::Loop, | ||||
|         &CheatList::LoadImmediate,         &CheatList::LoadIndexed, | ||||
| @ -346,7 +349,7 @@ CheatList TextCheatParser::Parse(const std::vector<u8>& data) const { | ||||
|         if (!line.empty() && (line[0] == '[' || line[0] == '{')) { | ||||
|             const auto master = line[0] == '{'; | ||||
|             const auto begin = master ? line.find('{') : line.find('['); | ||||
|             const auto end = master ? line.find_last_of('}') : line.find_last_of(']'); | ||||
|             const auto end = master ? line.rfind('}') : line.rfind(']'); | ||||
| 
 | ||||
|             ASSERT(begin != std::string::npos && end != std::string::npos); | ||||
| 
 | ||||
| @ -422,7 +425,7 @@ std::array<u8, 16> TextCheatParser::ParseSingleLineCheat(const std::string& line | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| u64 MemoryReadImpl(u8 width, VAddr addr) { | ||||
| u64 MemoryReadImpl(u32 width, VAddr addr) { | ||||
|     switch (width) { | ||||
|     case 1: | ||||
|         return Memory::Read8(addr); | ||||
| @ -438,7 +441,7 @@ u64 MemoryReadImpl(u8 width, VAddr addr) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void MemoryWriteImpl(u8 width, VAddr addr, u64 value) { | ||||
| void MemoryWriteImpl(u32 width, VAddr addr, u64 value) { | ||||
|     switch (width) { | ||||
|     case 1: | ||||
|         Memory::Write8(addr, static_cast<u8>(value)); | ||||
| @ -457,31 +460,34 @@ void MemoryWriteImpl(u8 width, VAddr addr, u64 value) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CheatEngine::CheatEngine(std::vector<CheatList> cheats, const std::string& build_id) | ||||
| CheatEngine::CheatEngine(std::vector<CheatList> cheats, const std::string& build_id, | ||||
|                          VAddr code_region_start, VAddr code_region_end) | ||||
|     : cheats(std::move(cheats)) { | ||||
|     event = CoreTiming::RegisterEvent( | ||||
|     auto& core_timing{Core::System::GetInstance().CoreTiming()}; | ||||
|     event = core_timing.RegisterEvent( | ||||
|         "CheatEngine::FrameCallback::" + build_id, | ||||
|         [this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); }); | ||||
|     CoreTiming::ScheduleEvent(CHEAT_ENGINE_TICKS, event); | ||||
|     core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event); | ||||
| 
 | ||||
|     const auto& vm_manager = Core::System::GetInstance().CurrentProcess()->VMManager(); | ||||
|     for (auto& list : this->cheats) { | ||||
|         list.SetMemoryParameters( | ||||
|             vm_manager.GetMainCodeRegionBaseAddress(), vm_manager.GetHeapRegionBaseAddress(), | ||||
|             vm_manager.GetMainCodeRegionEndAddress(), vm_manager.GetHeapRegionEndAddress(), | ||||
|             &MemoryWriteImpl, &MemoryReadImpl); | ||||
|         list.SetMemoryParameters(code_region_start, vm_manager.GetHeapRegionBaseAddress(), | ||||
|                                  code_region_end, vm_manager.GetHeapRegionEndAddress(), | ||||
|                                  &MemoryWriteImpl, &MemoryReadImpl); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CheatEngine::~CheatEngine() { | ||||
|     CoreTiming::UnscheduleEvent(event, 0); | ||||
|     auto& core_timing{Core::System::GetInstance().CoreTiming()}; | ||||
|     core_timing.UnscheduleEvent(event, 0); | ||||
| } | ||||
| 
 | ||||
| void CheatEngine::FrameCallback(u64 userdata, int cycles_late) { | ||||
|     for (auto& list : cheats) | ||||
|         list.Execute(); | ||||
| 
 | ||||
|     CoreTiming::ScheduleEvent(CHEAT_ENGINE_TICKS - cycles_late, event); | ||||
|     auto& core_timing{Core::System::GetInstance().CoreTiming()}; | ||||
|     core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - cycles_late, event); | ||||
| } | ||||
| 
 | ||||
| } // namespace FileSys
 | ||||
|  | ||||
| @ -11,7 +11,7 @@ | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace CoreTiming { | ||||
| namespace Core::Timing { | ||||
| struct EventType; | ||||
| } | ||||
| 
 | ||||
| @ -123,9 +123,9 @@ public: | ||||
|     using ProgramSegment = std::vector<std::pair<std::string, Block>>; | ||||
| 
 | ||||
|     // (width in bytes, address, value)
 | ||||
|     using MemoryWriter = void (*)(u8, VAddr, u64); | ||||
|     using MemoryWriter = void (*)(u32, VAddr, u64); | ||||
|     // (width in bytes, address) -> value
 | ||||
|     using MemoryReader = u64 (*)(u8, VAddr); | ||||
|     using MemoryReader = u64 (*)(u32, VAddr); | ||||
| 
 | ||||
|     void SetMemoryParameters(VAddr main_begin, VAddr heap_begin, VAddr main_end, VAddr heap_end, | ||||
|                              MemoryWriter writer, MemoryReader reader); | ||||
| @ -212,13 +212,14 @@ private: | ||||
| // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming
 | ||||
| class CheatEngine final { | ||||
| public: | ||||
|     CheatEngine(std::vector<CheatList> cheats, const std::string& build_id); | ||||
|     CheatEngine(std::vector<CheatList> cheats, const std::string& build_id, VAddr code_region_start, | ||||
|                 VAddr code_region_end); | ||||
|     ~CheatEngine(); | ||||
| 
 | ||||
| private: | ||||
|     void FrameCallback(u64 userdata, int cycles_late); | ||||
| 
 | ||||
|     CoreTiming::EventType* event; | ||||
|     Core::Timing::EventType* event; | ||||
| 
 | ||||
|     std::vector<CheatList> cheats; | ||||
| }; | ||||
|  | ||||
| @ -786,23 +786,6 @@ u64 VMManager::GetNewMapRegionSize() const { | ||||
|     return new_map_region_end - new_map_region_base; | ||||
| } | ||||
| 
 | ||||
| void VMManager::SetMainCodeRegion(VAddr begin, VAddr end) { | ||||
|     main_code_region_base = begin; | ||||
|     main_code_region_end = end; | ||||
| } | ||||
| 
 | ||||
| VAddr VMManager::GetMainCodeRegionBaseAddress() const { | ||||
|     return main_code_region_base; | ||||
| } | ||||
| 
 | ||||
| VAddr VMManager::GetMainCodeRegionEndAddress() const { | ||||
|     return main_code_region_end; | ||||
| } | ||||
| 
 | ||||
| u64 VMManager::GetMainCodeRegionSize() const { | ||||
|     return main_code_region_end - main_code_region_base; | ||||
| } | ||||
| 
 | ||||
| VAddr VMManager::GetTLSIORegionBaseAddress() const { | ||||
|     return tls_io_region_base; | ||||
| } | ||||
|  | ||||
| @ -480,14 +480,6 @@ public: | ||||
|     /// Gets the total size of the new map region in bytes.
 | ||||
|     u64 GetNewMapRegionSize() const; | ||||
| 
 | ||||
|     void SetMainCodeRegion(VAddr begin, VAddr end); | ||||
| 
 | ||||
|     VAddr GetMainCodeRegionBaseAddress() const; | ||||
| 
 | ||||
|     VAddr GetMainCodeRegionEndAddress() const; | ||||
| 
 | ||||
|     u64 GetMainCodeRegionSize() const; | ||||
| 
 | ||||
|     /// Gets the base address of the TLS IO region.
 | ||||
|     VAddr GetTLSIORegionBaseAddress() const; | ||||
| 
 | ||||
|  | ||||
| @ -3,6 +3,8 @@ | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "core/hle/service/hid/controllers/controller_base.h" | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| #include "controllers/controller_base.h" | ||||
|  | ||||
| @ -147,10 +147,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | ||||
| 
 | ||||
|         const VAddr load_addr = next_load_addr; | ||||
|         const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; | ||||
|         const bool should_register_data_segment = std::strcmp(module, "main") == 0; | ||||
|         const auto tentative_next_load_addr = | ||||
|             AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, | ||||
|                                       should_register_data_segment, pm); | ||||
|             AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm); | ||||
|         if (!tentative_next_load_addr) { | ||||
|             return ResultStatus::ErrorLoadingNSO; | ||||
|         } | ||||
|  | ||||
| @ -97,7 +97,6 @@ static constexpr u32 PageAlignSize(u32 size) { | ||||
| std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | ||||
|                                                const FileSys::VfsFile& file, VAddr load_base, | ||||
|                                                bool should_pass_arguments, | ||||
|                                                bool should_register_data_region, | ||||
|                                                std::optional<FileSys::PatchManager> pm) { | ||||
|     if (file.GetSize() < sizeof(NsoHeader)) | ||||
|         return {}; | ||||
| @ -156,10 +155,6 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | ||||
|     const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)}; | ||||
|     program_image.resize(image_size); | ||||
| 
 | ||||
|     if (should_register_data_region) { | ||||
|         process.VMManager().SetMainCodeRegion(load_base, load_base + program_image.size()); | ||||
|     } | ||||
| 
 | ||||
|     // Apply patches if necessary
 | ||||
|     if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) { | ||||
|         std::vector<u8> pi_header(program_image.size() + 0x100); | ||||
| @ -176,7 +171,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | ||||
|         const auto cheats = pm->CreateCheatList(nso_header.build_id); | ||||
|         if (!cheats.empty()) { | ||||
|             Core::System::GetInstance().RegisterCheatList( | ||||
|                 cheats, Common::HexArrayToString(nso_header.build_id)); | ||||
|                 cheats, Common::HexArrayToString(nso_header.build_id), load_base, | ||||
|                 load_base + program_image.size()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -197,7 +193,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { | ||||
| 
 | ||||
|     // Load module
 | ||||
|     const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | ||||
|     if (!LoadModule(process, *file, base_address, true, true)) { | ||||
|     if (!LoadModule(process, *file, base_address, true)) { | ||||
|         return ResultStatus::ErrorLoadingNSO; | ||||
|     } | ||||
|     LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); | ||||
|  | ||||
| @ -43,7 +43,6 @@ public: | ||||
| 
 | ||||
|     static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file, | ||||
|                                            VAddr load_base, bool should_pass_arguments, | ||||
|                                            bool should_register_data_segment, | ||||
|                                            std::optional<FileSys::PatchManager> pm = {}); | ||||
| 
 | ||||
|     ResultStatus Load(Kernel::Process& process) override; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Zach Hilman
						Zach Hilman