From 1cd0489dfe17c571130b0aa49369129bcfa94100 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 3 Aug 2023 11:29:14 +0300 Subject: [PATCH] placeholder for making Memory and Timer classes portable --- src/Core/Memory.cpp | 217 ++++++++++++++++++++++---------------------- src/Lib/Timer.cpp | 39 ++++++-- 2 files changed, 137 insertions(+), 119 deletions(-) diff --git a/src/Core/Memory.cpp b/src/Core/Memory.cpp index 0855df7f..2386dc7e 100644 --- a/src/Core/Memory.cpp +++ b/src/Core/Memory.cpp @@ -1,127 +1,122 @@ -#include "../Core/PS4/Loader/Elf.h" #include "Memory.h" +#include "../Core/PS4/Loader/Elf.h" + #ifdef _WIN64 - #include +#include #else - #include +#include #endif #if !defined(_WIN64) -enum PosixPageProtection -{ - PAGE_NOACCESS = 0, - PAGE_READONLY = PROT_READ, - PAGE_READWRITE = PROT_READ | PROT_WRITE, - PAGE_EXECUTE = PROT_EXEC, - PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ, +enum PosixPageProtection { + PAGE_NOACCESS = 0, + PAGE_READONLY = PROT_READ, + PAGE_READWRITE = PROT_READ | PROT_WRITE, + PAGE_EXECUTE = PROT_EXEC, + PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ, PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE }; #endif #include "../Util/Log.h" -namespace Memory -{ - namespace VirtualMemory { - static u32 convertMemoryMode(MemoryMode mode) - { - switch (mode) - { - case MemoryMode::Read: return PAGE_READONLY; - case MemoryMode::Write: - case MemoryMode::ReadWrite: return PAGE_READWRITE; +namespace Memory { +namespace VirtualMemory { +static u32 convertMemoryMode(MemoryMode mode) { + switch (mode) { + case MemoryMode::Read: return PAGE_READONLY; + case MemoryMode::Write: + case MemoryMode::ReadWrite: return PAGE_READWRITE; - case MemoryMode::Execute: return PAGE_EXECUTE; - case MemoryMode::ExecuteRead: return PAGE_EXECUTE_READ; - case MemoryMode::ExecuteWrite: - case MemoryMode::ExecuteReadWrite: return PAGE_EXECUTE_READWRITE; + case MemoryMode::Execute: return PAGE_EXECUTE; + case MemoryMode::ExecuteRead: return PAGE_EXECUTE_READ; + case MemoryMode::ExecuteWrite: + case MemoryMode::ExecuteReadWrite: return PAGE_EXECUTE_READWRITE; - case MemoryMode::NoAccess: return PAGE_NOACCESS; - default: - return PAGE_NOACCESS; - } - } - static MemoryMode convertMemoryMode(u32 mode) { - switch (mode) { - case PAGE_NOACCESS: return MemoryMode::NoAccess; - case PAGE_READONLY: return MemoryMode::Read; - case PAGE_READWRITE: return MemoryMode::ReadWrite; - case PAGE_EXECUTE: return MemoryMode::Execute; - case PAGE_EXECUTE_READ: return MemoryMode::ExecuteRead; - case PAGE_EXECUTE_READWRITE: return MemoryMode::ExecuteReadWrite; - default: return MemoryMode::NoAccess; - } - } - - u64 memory_alloc(u64 address, u64 size, MemoryMode mode) - { - #ifdef _WIN64 - auto ptr = reinterpret_cast(VirtualAlloc(reinterpret_cast(static_cast(address)), - size, - static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), - convertMemoryMode(mode))); - - if (ptr == 0) - { - auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "VirtualAlloc() failed: 0x{:X}\n", err); - } - #else - auto ptr = reinterpret_cast(mmap(reinterpret_cast(static_cast(address)), - size, - PROT_EXEC | PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, - -1, - 0)); - - if (ptr == reinterpret_castMAP_FAILED) - { - LOG_ERROR_IF(true, "mmap() failed: {}\n", std::strerror(errno)); - } - #endif - return ptr; - } - bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode) { - DWORD old_protect = 0; - if (VirtualProtect(reinterpret_cast(static_cast(address)), size, convertMemoryMode(mode), &old_protect) == 0) { - auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "VirtualProtect() failed: 0x{:X}\n", err); - return false; - } - if (old_mode != nullptr) { - *old_mode = convertMemoryMode(old_protect); - } - return true; - } - - bool memory_flush(u64 address, u64 size) { - if (::FlushInstructionCache(GetCurrentProcess(), reinterpret_cast(static_cast(address)), size) == 0) { - auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "FlushInstructionCache() failed: 0x{:X}\n", err); - return false; - } - return true; - } - bool memory_patch(u64 vaddr, u64 value) { - MemoryMode old_mode{}; - memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode); - - auto* ptr = reinterpret_cast(vaddr); - - bool ret = (*ptr != value); - - *ptr = value; - - memory_protect(vaddr, 8, old_mode, nullptr); - - //if mode is executable flush it so insure that cpu finds it - if ((old_mode == MemoryMode::Execute || old_mode == MemoryMode::ExecuteRead || old_mode == MemoryMode::ExecuteWrite || - old_mode == MemoryMode::ExecuteReadWrite)) { - memory_flush(vaddr, 8); - } - - return ret; - } - } + case MemoryMode::NoAccess: return PAGE_NOACCESS; + default: return PAGE_NOACCESS; + } } +static MemoryMode convertMemoryMode(u32 mode) { + switch (mode) { + case PAGE_NOACCESS: return MemoryMode::NoAccess; + case PAGE_READONLY: return MemoryMode::Read; + case PAGE_READWRITE: return MemoryMode::ReadWrite; + case PAGE_EXECUTE: return MemoryMode::Execute; + case PAGE_EXECUTE_READ: return MemoryMode::ExecuteRead; + case PAGE_EXECUTE_READWRITE: return MemoryMode::ExecuteReadWrite; + default: return MemoryMode::NoAccess; + } +} + +u64 memory_alloc(u64 address, u64 size, MemoryMode mode) { +#ifdef _WIN64 + auto ptr = reinterpret_cast(VirtualAlloc(reinterpret_cast(static_cast(address)), size, + static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), convertMemoryMode(mode))); + + if (ptr == 0) { + auto err = static_cast(GetLastError()); + LOG_ERROR_IF(true, "VirtualAlloc() failed: 0x{:X}\n", err); + } +#else + auto ptr = reinterpret_cast( + mmap(reinterpret_cast(static_cast(address)), size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); + + if (ptr == reinterpret_cast MAP_FAILED) { + LOG_ERROR_IF(true, "mmap() failed: {}\n", std::strerror(errno)); + } +#endif + return ptr; +} +bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode) { +#ifdef _WIN64 + DWORD old_protect = 0; + if (VirtualProtect(reinterpret_cast(static_cast(address)), size, convertMemoryMode(mode), &old_protect) == 0) { + auto err = static_cast(GetLastError()); + LOG_ERROR_IF(true, "VirtualProtect() failed: 0x{:X}\n", err); + return false; + } + if (old_mode != nullptr) { + *old_mode = convertMemoryMode(old_protect); + } + return true; +#else +#error Unimplement memory_protect function +#endif +} + +bool memory_flush(u64 address, u64 size) { +#ifdef _WIN64 + if (::FlushInstructionCache(GetCurrentProcess(), reinterpret_cast(static_cast(address)), size) == 0) { + auto err = static_cast(GetLastError()); + LOG_ERROR_IF(true, "FlushInstructionCache() failed: 0x{:X}\n", err); + return false; + } + return true; +#else // linux probably doesn't have something similar + return true; +#endif +} +bool memory_patch(u64 vaddr, u64 value) { + MemoryMode old_mode{}; + memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode); + + auto* ptr = reinterpret_cast(vaddr); + + bool ret = (*ptr != value); + + *ptr = value; + + memory_protect(vaddr, 8, old_mode, nullptr); + + // if mode is executable flush it so insure that cpu finds it + if ((old_mode == MemoryMode::Execute || old_mode == MemoryMode::ExecuteRead || old_mode == MemoryMode::ExecuteWrite || + old_mode == MemoryMode::ExecuteReadWrite)) { + memory_flush(vaddr, 8); + } + + return ret; +} +} // namespace VirtualMemory +} // namespace Memory diff --git a/src/Lib/Timer.cpp b/src/Lib/Timer.cpp index 66cb9fa3..b4509107 100644 --- a/src/Lib/Timer.cpp +++ b/src/Lib/Timer.cpp @@ -1,33 +1,50 @@ #include "Timer.h" + +#ifdef _WIN64 #include +#endif Lib::Timer::Timer() { +#ifdef _WIN64 LARGE_INTEGER f; QueryPerformanceFrequency(&f); m_Frequency = f.QuadPart; +#else +#error Unimplemented +#endif } void Lib::Timer::Start() { +#ifdef _WIN64 LARGE_INTEGER c; QueryPerformanceCounter(&c); m_StartTime = c.QuadPart; +#else +#error Unimplemented +#endif m_is_timer_paused = false; } void Lib::Timer::Pause() { +#ifdef _WIN64 LARGE_INTEGER c; QueryPerformanceCounter(&c); m_PauseTime = c.QuadPart; +#else +#error Unimplemented +#endif m_is_timer_paused = true; } void Lib::Timer::Resume() { u64 current_time = 0; - +#ifdef _WIN64 LARGE_INTEGER c; QueryPerformanceCounter(&c); current_time = c.QuadPart; - +#else +#error Unimplemented +#endif m_StartTime += current_time - m_PauseTime; m_is_timer_paused = false; } @@ -40,11 +57,13 @@ double Lib::Timer::GetTimeMsec() const { } u64 current_time = 0; - +#ifdef _WIN64 LARGE_INTEGER c; QueryPerformanceCounter(&c); current_time = c.QuadPart; - +#else +#error Unimplemented +#endif return 1000.0 * (static_cast(current_time - m_StartTime)) / static_cast(m_Frequency); } @@ -54,11 +73,13 @@ double Lib::Timer::GetTimeSec() const { } u64 current_time = 0; - +#ifdef _WIN64 LARGE_INTEGER c; QueryPerformanceCounter(&c); current_time = c.QuadPart; - +#else +#error Unimplemented +#endif return (static_cast(current_time - m_StartTime)) / static_cast(m_Frequency); } @@ -68,11 +89,13 @@ u64 Lib::Timer::GetTicks() const { } u64 current_time = 0; - +#ifdef _WIN64 LARGE_INTEGER c; QueryPerformanceCounter(&c); current_time = c.QuadPart; - +#else +#error Unimplemented +#endif return (current_time - m_StartTime); }