diff --git a/src/core/core.cpp b/src/core/core.cpp index ce53ef758..32c5b112d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -450,8 +450,10 @@ Tegra::DebugContext* System::GetGPUDebugContext() const { } void System::RegisterCheatList(const std::vector& list, - const std::string& build_id) { - impl->cheat_engine = std::make_unique(list, build_id); + const std::string& build_id, VAddr code_region_start, + VAddr code_region_end) { + impl->cheat_engine = + std::make_unique(list, build_id, code_region_start, code_region_end); } void System::SetFilesystem(std::shared_ptr vfs) { diff --git a/src/core/core.h b/src/core/core.h index bfb75631e..a6cfda405 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -254,8 +254,8 @@ public: std::shared_ptr GetFilesystem() const; - void RegisterCheatList(const std::vector& list, - const std::string& build_id); + void RegisterCheatList(const std::vector& list, const std::string& build_id, + VAddr code_region_start, VAddr code_region_end); void SetProfileSelector(std::unique_ptr applet); diff --git a/src/core/file_sys/cheat_engine.cpp b/src/core/file_sys/cheat_engine.cpp index e4383d8c1..09ca9d705 100644 --- a/src/core/file_sys/cheat_engine.cpp +++ b/src/core/file_sys/cheat_engine.cpp @@ -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 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::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(cheat.comparison_op.Value()) < 6); - const auto* function = comparison_functions[static_cast(cheat.comparison_op.Value())]; + auto* function = comparison_functions[static_cast(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 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 arithmetic_overflow_checks{ [](u64 a, u64 b) { return a > (std::numeric_limits::max() - b); }, // a + b [](u64 a, u64 b) { return a > (std::numeric_limits::max() + b); }, // a - b [](u64 a, u64 b) { return a > (std::numeric_limits::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(cheat.arithmetic_op.Value()) < 5); - const auto* function = arithmetic_functions[static_cast(cheat.arithmetic_op.Value())]; - const auto* overflow_function = + auto* function = arithmetic_functions[static_cast(cheat.arithmetic_op.Value())]; + auto* overflow_function = arithmetic_overflow_checks[static_cast(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 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& 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 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(value)); @@ -457,31 +460,34 @@ void MemoryWriteImpl(u8 width, VAddr addr, u64 value) { } } -CheatEngine::CheatEngine(std::vector cheats, const std::string& build_id) +CheatEngine::CheatEngine(std::vector 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 diff --git a/src/core/file_sys/cheat_engine.h b/src/core/file_sys/cheat_engine.h index d7a8654b7..7ed69a2c8 100644 --- a/src/core/file_sys/cheat_engine.h +++ b/src/core/file_sys/cheat_engine.h @@ -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>; // (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 cheats, const std::string& build_id); + CheatEngine(std::vector 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 cheats; }; diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 161a83660..10ad94aa6 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -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; } diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 728318f4b..d83a63e07 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -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; diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index e39cd6b51..498602de5 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -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" diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index ef9a577e3..07aa7a1cd 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -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; } diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 2721d85b1..5f6a6c0cf 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -97,7 +97,6 @@ static constexpr u32 PageAlignSize(u32 size) { std::optional AppLoader_NSO::LoadModule(Kernel::Process& process, const FileSys::VfsFile& file, VAddr load_base, bool should_pass_arguments, - bool should_register_data_region, std::optional pm) { if (file.GetSize() < sizeof(NsoHeader)) return {}; @@ -156,10 +155,6 @@ std::optional AppLoader_NSO::LoadModule(Kernel::Process& process, const u32 image_size{PageAlignSize(static_cast(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 pi_header(program_image.size() + 0x100); @@ -176,7 +171,8 @@ std::optional 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); diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 858e346c6..135b6ea5a 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h @@ -43,7 +43,6 @@ public: static std::optional LoadModule(Kernel::Process& process, const FileSys::VfsFile& file, VAddr load_base, bool should_pass_arguments, - bool should_register_data_segment, std::optional pm = {}); ResultStatus Load(Kernel::Process& process) override;