From 323990d40286159c37e2f9003e5a7f99b67b4aea Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Wed, 21 Nov 2018 15:04:31 -0500
Subject: [PATCH] Memory: move Read/Write8/16/32/64 and ReadCString into class

---
 src/core/arm/dynarmic/arm_dynarmic.cpp        | 20 ++++---
 .../arm/dyncom/arm_dyncom_interpreter.cpp     |  2 +-
 src/core/arm/skyeye_common/armstate.cpp       | 16 +++---
 src/core/cheats/gateway_cheat.cpp             | 55 +++++++++++--------
 src/core/hle/kernel/address_arbiter.cpp       | 14 ++---
 src/core/hle/kernel/address_arbiter.h         |  2 +
 src/core/hle/kernel/svc.cpp                   | 16 +++---
 src/core/hle/service/ldr_ro/cro_helper.cpp    | 34 ++++++------
 src/core/hle/service/ldr_ro/cro_helper.h      |  6 +-
 src/core/memory.cpp                           | 22 ++++----
 src/core/memory.h                             | 31 +++++++----
 11 files changed, 119 insertions(+), 99 deletions(-)

diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 9ba4d0368..2c60dbac9 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -72,33 +72,34 @@ private:
 class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks {
 public:
     explicit DynarmicUserCallbacks(ARM_Dynarmic& parent)
-        : parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system) {}
+        : parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system),
+          memory(parent.system.Memory()) {}
     ~DynarmicUserCallbacks() = default;
 
     std::uint8_t MemoryRead8(VAddr vaddr) override {
-        return Memory::Read8(vaddr);
+        return memory.Read8(vaddr);
     }
     std::uint16_t MemoryRead16(VAddr vaddr) override {
-        return Memory::Read16(vaddr);
+        return memory.Read16(vaddr);
     }
     std::uint32_t MemoryRead32(VAddr vaddr) override {
-        return Memory::Read32(vaddr);
+        return memory.Read32(vaddr);
     }
     std::uint64_t MemoryRead64(VAddr vaddr) override {
-        return Memory::Read64(vaddr);
+        return memory.Read64(vaddr);
     }
 
     void MemoryWrite8(VAddr vaddr, std::uint8_t value) override {
-        Memory::Write8(vaddr, value);
+        memory.Write8(vaddr, value);
     }
     void MemoryWrite16(VAddr vaddr, std::uint16_t value) override {
-        Memory::Write16(vaddr, value);
+        memory.Write16(vaddr, value);
     }
     void MemoryWrite32(VAddr vaddr, std::uint32_t value) override {
-        Memory::Write32(vaddr, value);
+        memory.Write32(vaddr, value);
     }
     void MemoryWrite64(VAddr vaddr, std::uint64_t value) override {
-        Memory::Write64(vaddr, value);
+        memory.Write64(vaddr, value);
     }
 
     void InterpreterFallback(VAddr pc, std::size_t num_instructions) override {
@@ -159,6 +160,7 @@ public:
     ARM_Dynarmic& parent;
     Core::Timing& timing;
     Kernel::SVCContext svc_context;
+    Memory::MemorySystem& memory;
 };
 
 ARM_Dynarmic::ARM_Dynarmic(Core::System& system, PrivilegeMode initial_mode)
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 4854eb23e..adb126b95 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -811,7 +811,7 @@ MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
 static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
                                                     ARM_INST_PTR& inst_base) {
     u32 inst_size = 4;
-    u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
+    u32 inst = Core::System::GetInstance().Memory().Read32(phys_addr & 0xFFFFFFFC);
 
     // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
     // instruction
diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp
index a6920c89b..9c29783fc 100644
--- a/src/core/arm/skyeye_common/armstate.cpp
+++ b/src/core/arm/skyeye_common/armstate.cpp
@@ -191,13 +191,13 @@ static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {
 u8 ARMul_State::ReadMemory8(u32 address) const {
     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 
-    return Memory::Read8(address);
+    return Core::System::GetInstance().Memory().Read8(address);
 }
 
 u16 ARMul_State::ReadMemory16(u32 address) const {
     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 
-    u16 data = Memory::Read16(address);
+    u16 data = Core::System::GetInstance().Memory().Read16(address);
 
     if (InBigEndianMode())
         data = Common::swap16(data);
@@ -208,7 +208,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const {
 u32 ARMul_State::ReadMemory32(u32 address) const {
     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 
-    u32 data = Memory::Read32(address);
+    u32 data = Core::System::GetInstance().Memory().Read32(address);
 
     if (InBigEndianMode())
         data = Common::swap32(data);
@@ -219,7 +219,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const {
 u64 ARMul_State::ReadMemory64(u32 address) const {
     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 
-    u64 data = Memory::Read64(address);
+    u64 data = Core::System::GetInstance().Memory().Read64(address);
 
     if (InBigEndianMode())
         data = Common::swap64(data);
@@ -230,7 +230,7 @@ u64 ARMul_State::ReadMemory64(u32 address) const {
 void ARMul_State::WriteMemory8(u32 address, u8 data) {
     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
 
-    Memory::Write8(address, data);
+    Core::System::GetInstance().Memory().Write8(address, data);
 }
 
 void ARMul_State::WriteMemory16(u32 address, u16 data) {
@@ -239,7 +239,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data) {
     if (InBigEndianMode())
         data = Common::swap16(data);
 
-    Memory::Write16(address, data);
+    Core::System::GetInstance().Memory().Write16(address, data);
 }
 
 void ARMul_State::WriteMemory32(u32 address, u32 data) {
@@ -248,7 +248,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data) {
     if (InBigEndianMode())
         data = Common::swap32(data);
 
-    Memory::Write32(address, data);
+    Core::System::GetInstance().Memory().Write32(address, data);
 }
 
 void ARMul_State::WriteMemory64(u32 address, u64 data) {
@@ -257,7 +257,7 @@ void ARMul_State::WriteMemory64(u32 address, u64 data) {
     if (InBigEndianMode())
         data = Common::swap64(data);
 
-    Memory::Write64(address, data);
+    Core::System::GetInstance().Memory().Write64(address, data);
 }
 
 // Reads from the CP15 registers. Used with implementation of the MRC instruction.
diff --git a/src/core/cheats/gateway_cheat.cpp b/src/core/cheats/gateway_cheat.cpp
index 06fb41485..af7e0f8cf 100644
--- a/src/core/cheats/gateway_cheat.cpp
+++ b/src/core/cheats/gateway_cheat.cpp
@@ -49,9 +49,10 @@ static inline std::enable_if_t<std::is_integral_v<T>> CompOp(const GatewayCheat:
     }
 }
 
-static inline void LoadOffsetOp(const GatewayCheat::CheatLine& line, State& state) {
+static inline void LoadOffsetOp(Memory::MemorySystem& memory, const GatewayCheat::CheatLine& line,
+                                State& state) {
     u32 addr = line.address + state.offset;
-    state.offset = Memory::Read32(addr);
+    state.offset = memory.Read32(addr);
 }
 
 static inline void LoopOp(const GatewayCheat::CheatLine& line, State& state) {
@@ -154,7 +155,7 @@ static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Co
             state.current_line_nr++;
         }
         first = !first;
-        Memory::Write32(addr, tmp);
+        system.Memory().Write32(addr, tmp);
         addr += 4;
         num_bytes -= 4;
     }
@@ -162,7 +163,7 @@ static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Co
         u32 tmp = (first ? cheat_lines[state.current_line_nr].first
                          : cheat_lines[state.current_line_nr].value) >>
                   bit_offset;
-        Memory::Write8(addr, tmp);
+        system.Memory().Write8(addr, tmp);
         addr += 1;
         num_bytes -= 1;
         bit_offset += 8;
@@ -205,6 +206,14 @@ GatewayCheat::~GatewayCheat() = default;
 void GatewayCheat::Execute(Core::System& system) {
     State state;
 
+    Memory::MemorySystem& memory = system.Memory();
+    auto Read8 = [&memory](VAddr addr) { return memory.Read8(addr); };
+    auto Read16 = [&memory](VAddr addr) { return memory.Read16(addr); };
+    auto Read32 = [&memory](VAddr addr) { return memory.Read32(addr); };
+    auto Write8 = [&memory](VAddr addr, u8 value) { memory.Write8(addr, value); };
+    auto Write16 = [&memory](VAddr addr, u16 value) { memory.Write16(addr, value); };
+    auto Write32 = [&memory](VAddr addr, u32 value) { memory.Write32(addr, value); };
+
     for (state.current_line_nr = 0; state.current_line_nr < cheat_lines.size();
          state.current_line_nr++) {
         auto line = cheat_lines[state.current_line_nr];
@@ -247,63 +256,61 @@ void GatewayCheat::Execute(Core::System& system) {
             break;
         case CheatType::Write32:
             // 0XXXXXXX YYYYYYYY - word[XXXXXXX+offset] = YYYYYYYY
-            WriteOp<u32>(line, state, &Memory::Write32, system);
+            WriteOp<u32>(line, state, Write32, system);
             break;
         case CheatType::Write16:
             // 1XXXXXXX 0000YYYY - half[XXXXXXX+offset] = YYYY
-            WriteOp<u16>(line, state, &Memory::Write16, system);
+            WriteOp<u16>(line, state, Write16, system);
             break;
         case CheatType::Write8:
             // 2XXXXXXX 000000YY - byte[XXXXXXX+offset] = YY
-            WriteOp<u8>(line, state, &Memory::Write8, system);
+            WriteOp<u8>(line, state, Write8, system);
             break;
         case CheatType::GreaterThan32:
             // 3XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY > word[XXXXXXX]   ;unsigned
-            CompOp<u32>(line, state, &Memory::Read32,
-                        [&line](u32 val) -> bool { return line.value > val; });
+            CompOp<u32>(line, state, Read32, [&line](u32 val) -> bool { return line.value > val; });
             break;
         case CheatType::LessThan32:
             // 4XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY < word[XXXXXXX]   ;unsigned
-            CompOp<u32>(line, state, &Memory::Read32,
-                        [&line](u32 val) -> bool { return line.value < val; });
+            CompOp<u32>(line, state, Read32, [&line](u32 val) -> bool { return line.value < val; });
             break;
         case CheatType::EqualTo32:
             // 5XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY == word[XXXXXXX]   ;unsigned
-            CompOp<u32>(line, state, &Memory::Read32,
+            CompOp<u32>(line, state, Read32,
                         [&line](u32 val) -> bool { return line.value == val; });
             break;
         case CheatType::NotEqualTo32:
             // 6XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY != word[XXXXXXX]   ;unsigned
-            CompOp<u32>(line, state, &Memory::Read32,
+            CompOp<u32>(line, state, Read32,
                         [&line](u32 val) -> bool { return line.value != val; });
             break;
         case CheatType::GreaterThan16WithMask:
             // 7XXXXXXX ZZZZYYYY - Execute next block IF YYYY > ((not ZZZZ) AND half[XXXXXXX])
-            CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool {
+            CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
                 return static_cast<u16>(line.value) > (static_cast<u16>(~line.value >> 16) & val);
             });
             break;
         case CheatType::LessThan16WithMask:
             // 8XXXXXXX ZZZZYYYY - Execute next block IF YYYY < ((not ZZZZ) AND half[XXXXXXX])
-            CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool {
+            CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
                 return static_cast<u16>(line.value) < (static_cast<u16>(~line.value >> 16) & val);
             });
             break;
         case CheatType::EqualTo16WithMask:
             // 9XXXXXXX ZZZZYYYY - Execute next block IF YYYY = ((not ZZZZ) AND half[XXXXXXX])
-            CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool {
+            CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
                 return static_cast<u16>(line.value) == (static_cast<u16>(~line.value >> 16) & val);
             });
             break;
         case CheatType::NotEqualTo16WithMask:
             // AXXXXXXX ZZZZYYYY - Execute next block IF YYYY <> ((not ZZZZ) AND half[XXXXXXX])
-            CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool {
+            CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
                 return static_cast<u16>(line.value) != (static_cast<u16>(~line.value >> 16) & val);
             });
             break;
         case CheatType::LoadOffset:
             // BXXXXXXX 00000000 - offset = word[XXXXXXX+offset]
-            LoadOffsetOp(line, state);
+            LoadOffsetOp(system.Memory(), line, state);
             break;
         case CheatType::Loop: {
             // C0000000 YYYYYYYY - LOOP next block YYYYYYYY times
@@ -343,32 +350,32 @@ void GatewayCheat::Execute(Core::System& system) {
         }
         case CheatType::IncrementiveWrite32: {
             // D6000000 XXXXXXXX – (32bit) [XXXXXXXX+offset] = reg ; offset += 4
-            IncrementiveWriteOp<u32>(line, state, &Memory::Write32, system);
+            IncrementiveWriteOp<u32>(line, state, Write32, system);
             break;
         }
         case CheatType::IncrementiveWrite16: {
             // D7000000 XXXXXXXX – (16bit) [XXXXXXXX+offset] = reg & 0xffff ; offset += 2
-            IncrementiveWriteOp<u16>(line, state, &Memory::Write16, system);
+            IncrementiveWriteOp<u16>(line, state, Write16, system);
             break;
         }
         case CheatType::IncrementiveWrite8: {
             // D8000000 XXXXXXXX – (16bit) [XXXXXXXX+offset] = reg & 0xff ; offset++
-            IncrementiveWriteOp<u8>(line, state, &Memory::Write8, system);
+            IncrementiveWriteOp<u8>(line, state, Write8, system);
             break;
         }
         case CheatType::Load32: {
             // D9000000 XXXXXXXX – reg = [XXXXXXXX+offset]
-            LoadOp<u32>(line, state, &Memory::Read32);
+            LoadOp<u32>(line, state, Read32);
             break;
         }
         case CheatType::Load16: {
             // DA000000 XXXXXXXX – reg = [XXXXXXXX+offset] & 0xFFFF
-            LoadOp<u16>(line, state, &Memory::Read16);
+            LoadOp<u16>(line, state, Read16);
             break;
         }
         case CheatType::Load8: {
             // DB000000 XXXXXXXX – reg = [XXXXXXXX+offset] & 0xFF
-            LoadOp<u8>(line, state, &Memory::Read8);
+            LoadOp<u8>(line, state, Read8);
             break;
         }
         case CheatType::AddOffset: {
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index d391da208..cc5404570 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -65,7 +65,7 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
     return thread;
 }
 
-AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel) {}
+AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
 AddressArbiter::~AddressArbiter() {}
 
 SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
@@ -103,31 +103,31 @@ ResultCode AddressArbiter::ArbitrateAddress(SharedPtr<Thread> thread, Arbitratio
 
     // Wait current thread (acquire the arbiter)...
     case ArbitrationType::WaitIfLessThan:
-        if ((s32)Memory::Read32(address) < value) {
+        if ((s32)kernel.memory.Read32(address) < value) {
             WaitThread(std::move(thread), address);
         }
         break;
     case ArbitrationType::WaitIfLessThanWithTimeout:
-        if ((s32)Memory::Read32(address) < value) {
+        if ((s32)kernel.memory.Read32(address) < value) {
             thread->wakeup_callback = timeout_callback;
             thread->WakeAfterDelay(nanoseconds);
             WaitThread(std::move(thread), address);
         }
         break;
     case ArbitrationType::DecrementAndWaitIfLessThan: {
-        s32 memory_value = Memory::Read32(address);
+        s32 memory_value = kernel.memory.Read32(address);
         if (memory_value < value) {
             // Only change the memory value if the thread should wait
-            Memory::Write32(address, (s32)memory_value - 1);
+            kernel.memory.Write32(address, (s32)memory_value - 1);
             WaitThread(std::move(thread), address);
         }
         break;
     }
     case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
-        s32 memory_value = Memory::Read32(address);
+        s32 memory_value = kernel.memory.Read32(address);
         if (memory_value < value) {
             // Only change the memory value if the thread should wait
-            Memory::Write32(address, (s32)memory_value - 1);
+            kernel.memory.Write32(address, (s32)memory_value - 1);
             thread->wakeup_callback = timeout_callback;
             thread->WakeAfterDelay(nanoseconds);
             WaitThread(std::move(thread), address);
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index cdfa64ec2..ac01749f7 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -52,6 +52,8 @@ private:
     explicit AddressArbiter(KernelSystem& kernel);
     ~AddressArbiter() override;
 
+    KernelSystem& kernel;
+
     /// Puts the thread to wait on the specified arbitration address under this address arbiter.
     void WaitThread(SharedPtr<Thread> thread, VAddr wait_address);
 
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 660361720..1e414c397 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -352,7 +352,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
 
     static constexpr std::size_t PortNameMaxLength = 11;
     // Read 1 char beyond the max allowed port name to detect names that are too long.
-    std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1);
+    std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
     if (port_name.size() > PortNameMaxLength)
         return ERR_PORT_NAME_TOO_LONG;
 
@@ -467,7 +467,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
     std::vector<ObjectPtr> objects(handle_count);
 
     for (int i = 0; i < handle_count; ++i) {
-        Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
+        Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
         auto object = kernel.GetCurrentProcess()->handle_table.Get<WaitObject>(handle);
         if (object == nullptr)
             return ERR_INVALID_HANDLE;
@@ -636,7 +636,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
     SharedPtr<Process> current_process = kernel.GetCurrentProcess();
 
     for (int i = 0; i < handle_count; ++i) {
-        Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
+        Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
         auto object = current_process->handle_table.Get<WaitObject>(handle);
         if (object == nullptr)
             return ERR_INVALID_HANDLE;
@@ -646,7 +646,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
     // We are also sending a command reply.
     // Do not send a reply if the command id in the command buffer is 0xFFFF.
     Thread* thread = kernel.GetThreadManager().GetCurrentThread();
-    u32 cmd_buff_header = Memory::Read32(thread->GetCommandBufferAddress());
+    u32 cmd_buff_header = memory.Read32(thread->GetCommandBufferAddress());
     IPC::Header header{cmd_buff_header};
     if (reply_target != 0 && header.command_id != 0xFFFF) {
         auto session = current_process->handle_table.Get<ServerSession>(reply_target);
@@ -832,9 +832,9 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi
         return ERR_INVALID_HANDLE;
 
     for (unsigned int i = 0; i < name_count; ++i) {
-        u32 name = Memory::Read32(names + i * sizeof(u32));
+        u32 name = memory.Read32(names + i * sizeof(u32));
         s64 value = resource_limit->GetCurrentResourceValue(name);
-        Memory::Write64(values + i * sizeof(u64), value);
+        memory.Write64(values + i * sizeof(u64), value);
     }
 
     return RESULT_SUCCESS;
@@ -852,9 +852,9 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_
         return ERR_INVALID_HANDLE;
 
     for (unsigned int i = 0; i < name_count; ++i) {
-        u32 name = Memory::Read32(names + i * sizeof(u32));
+        u32 name = memory.Read32(names + i * sizeof(u32));
         s64 value = resource_limit->GetMaxResourceValue(name);
-        Memory::Write64(values + i * sizeof(u64), value);
+        memory.Write64(values + i * sizeof(u64), value);
     }
 
     return RESULT_SUCCESS;
diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp
index 19308d08d..3d4a97d9f 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.cpp
+++ b/src/core/hle/service/ldr_ro/cro_helper.cpp
@@ -71,11 +71,11 @@ ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType reloc
         break;
     case RelocationType::AbsoluteAddress:
     case RelocationType::AbsoluteAddress2:
-        Memory::Write32(target_address, symbol_address + addend);
+        memory.Write32(target_address, symbol_address + addend);
         Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
         break;
     case RelocationType::RelativeAddress:
-        Memory::Write32(target_address, symbol_address + addend - target_future_address);
+        memory.Write32(target_address, symbol_address + addend - target_future_address);
         Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
         break;
     case RelocationType::ThumbBranch:
@@ -98,7 +98,7 @@ ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType reloc
     case RelocationType::AbsoluteAddress:
     case RelocationType::AbsoluteAddress2:
     case RelocationType::RelativeAddress:
-        Memory::Write32(target_address, 0);
+        memory.Write32(target_address, 0);
         Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
         break;
     case RelocationType::ThumbBranch:
@@ -188,7 +188,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
     ExportNamedSymbolEntry symbol_entry;
     GetEntry(found_id, symbol_entry);
 
-    if (Memory::ReadCString(symbol_entry.name_offset, export_strings_size) != name)
+    if (memory.ReadCString(symbol_entry.name_offset, export_strings_size) != name)
         return 0;
 
     return SegmentTagToAddress(symbol_entry.symbol_position);
@@ -761,7 +761,7 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
             ResultCode result = ForEachAutoLinkCRO(
                 process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
                     std::string symbol_name =
-                        Memory::ReadCString(entry.name_offset, import_strings_size);
+                        memory.ReadCString(entry.name_offset, import_strings_size);
                     u32 symbol_address = source.FindExportNamedSymbol(symbol_name);
 
                     if (symbol_address != 0) {
@@ -858,7 +858,7 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
     for (u32 i = 0; i < import_module_num; ++i) {
         ImportModuleEntry entry;
         GetEntry(i, entry);
-        std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size);
+        std::string want_cro_name = memory.ReadCString(entry.name_offset, import_strings_size);
 
         ResultCode result = ForEachAutoLinkCRO(
             process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
@@ -921,7 +921,7 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
 
         if (!relocation_entry.is_batch_resolved) {
             std::string symbol_name =
-                Memory::ReadCString(entry.name_offset, target_import_strings_size);
+                memory.ReadCString(entry.name_offset, target_import_strings_size);
             u32 symbol_address = FindExportNamedSymbol(symbol_name);
             if (symbol_address != 0) {
                 LOG_TRACE(Service_LDR, "    exports symbol \"{}\"", symbol_name);
@@ -952,7 +952,7 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
 
         if (relocation_entry.is_batch_resolved) {
             std::string symbol_name =
-                Memory::ReadCString(entry.name_offset, target_import_strings_size);
+                memory.ReadCString(entry.name_offset, target_import_strings_size);
             u32 symbol_address = FindExportNamedSymbol(symbol_name);
             if (symbol_address != 0) {
                 LOG_TRACE(Service_LDR, "    unexports symbol \"{}\"", symbol_name);
@@ -976,7 +976,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
         ImportModuleEntry entry;
         target.GetEntry(i, entry);
 
-        if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
+        if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name)
             continue;
 
         LOG_INFO(Service_LDR, "CRO \"{}\" exports {} indexed symbols to \"{}\"", module_name,
@@ -1025,7 +1025,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
         ImportModuleEntry entry;
         target.GetEntry(i, entry);
 
-        if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
+        if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name)
             continue;
 
         LOG_DEBUG(Service_LDR, "CRO \"{}\" unexports indexed symbols to \"{}\"", module_name,
@@ -1069,7 +1069,7 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
         Memory::ReadBlock(process, relocation_addr, &relocation_entry,
                           sizeof(ExternalRelocationEntry));
 
-        if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
+        if (memory.ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
             ResultCode result = ForEachAutoLinkCRO(
                 process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
                     u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_");
@@ -1108,9 +1108,9 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
  * @param size the size of the string (table), including the terminating 0
  * @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code.
  */
-static ResultCode VerifyStringTableLength(VAddr address, u32 size) {
+static ResultCode VerifyStringTableLength(Memory::MemorySystem& memory, VAddr address, u32 size) {
     if (size != 0) {
-        if (Memory::Read8(address + size - 1) != 0)
+        if (memory.Read8(address + size - 1) != 0)
             return CROFormatError(0x0B);
     }
     return RESULT_SUCCESS;
@@ -1126,7 +1126,7 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
         return result;
     }
 
-    result = VerifyStringTableLength(GetField(ModuleNameOffset), GetField(ModuleNameSize));
+    result = VerifyStringTableLength(memory, GetField(ModuleNameOffset), GetField(ModuleNameSize));
     if (result.IsError()) {
         LOG_ERROR(Service_LDR, "Error verifying module name {:08X}", result.raw);
         return result;
@@ -1155,7 +1155,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
         return result;
     }
 
-    result = VerifyStringTableLength(GetField(ExportStringsOffset), GetField(ExportStringsSize));
+    result =
+        VerifyStringTableLength(memory, GetField(ExportStringsOffset), GetField(ExportStringsSize));
     if (result.IsError()) {
         LOG_ERROR(Service_LDR, "Error verifying export strings {:08X}", result.raw);
         return result;
@@ -1191,7 +1192,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
         return result;
     }
 
-    result = VerifyStringTableLength(GetField(ImportStringsOffset), GetField(ImportStringsSize));
+    result =
+        VerifyStringTableLength(memory, GetField(ImportStringsOffset), GetField(ImportStringsSize));
     if (result.IsError()) {
         LOG_ERROR(Service_LDR, "Error verifying import strings {:08X}", result.raw);
         return result;
diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h
index d3a6e3d9a..e868a66c8 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.h
+++ b/src/core/hle/service/ldr_ro/cro_helper.h
@@ -44,7 +44,7 @@ public:
         : module_address(cro_address), process(process), memory(memory) {}
 
     std::string ModuleName() const {
-        return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize));
+        return memory.ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize));
     }
 
     u32 GetFileSize() const {
@@ -408,11 +408,11 @@ private:
     }
 
     u32 GetField(HeaderField field) const {
-        return Memory::Read32(Field(field));
+        return memory.Read32(Field(field));
     }
 
     void SetField(HeaderField field, u32 value) {
-        Memory::Write32(Field(field), value);
+        memory.Write32(Field(field), value);
     }
 
     /**
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 8c260c1f7..cf545ec8e 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -114,7 +114,7 @@ template <typename T>
 T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
 
 template <typename T>
-T Read(const VAddr vaddr) {
+T MemorySystem::Read(const VAddr vaddr) {
     const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
     if (page_pointer) {
         // NOTE: Avoid adding any extra logic to this fast-path block
@@ -152,7 +152,7 @@ template <typename T>
 void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
 
 template <typename T>
-void Write(const VAddr vaddr, const T data) {
+void MemorySystem::Write(const VAddr vaddr, const T data) {
     u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
     if (page_pointer) {
         // NOTE: Avoid adding any extra logic to this fast-path block
@@ -224,7 +224,7 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) {
     return nullptr;
 }
 
-std::string ReadCString(VAddr vaddr, std::size_t max_length) {
+std::string MemorySystem::ReadCString(VAddr vaddr, std::size_t max_length) {
     std::string string;
     string.reserve(max_length);
     for (std::size_t i = 0; i < max_length; ++i) {
@@ -417,19 +417,19 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
     CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR);
 }
 
-u8 Read8(const VAddr addr) {
+u8 MemorySystem::Read8(const VAddr addr) {
     return Read<u8>(addr);
 }
 
-u16 Read16(const VAddr addr) {
+u16 MemorySystem::Read16(const VAddr addr) {
     return Read<u16_le>(addr);
 }
 
-u32 Read32(const VAddr addr) {
+u32 MemorySystem::Read32(const VAddr addr) {
     return Read<u32_le>(addr);
 }
 
-u64 Read64(const VAddr addr) {
+u64 MemorySystem::Read64(const VAddr addr) {
     return Read<u64_le>(addr);
 }
 
@@ -483,19 +483,19 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
     }
 }
 
-void Write8(const VAddr addr, const u8 data) {
+void MemorySystem::Write8(const VAddr addr, const u8 data) {
     Write<u8>(addr, data);
 }
 
-void Write16(const VAddr addr, const u16 data) {
+void MemorySystem::Write16(const VAddr addr, const u16 data) {
     Write<u16_le>(addr, data);
 }
 
-void Write32(const VAddr addr, const u32 data) {
+void MemorySystem::Write32(const VAddr addr, const u32 data) {
     Write<u32_le>(addr, data);
 }
 
-void Write64(const VAddr addr, const u64 data) {
+void MemorySystem::Write64(const VAddr addr, const u64 data) {
     Write<u64_le>(addr, data);
 }
 
diff --git a/src/core/memory.h b/src/core/memory.h
index ffafc4c1c..f99067705 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -180,16 +180,6 @@ enum : VAddr {
 
 extern std::array<u8, Memory::FCRAM_N3DS_SIZE> fcram;
 
-u8 Read8(VAddr addr);
-u16 Read16(VAddr addr);
-u32 Read32(VAddr addr);
-u64 Read64(VAddr addr);
-
-void Write8(VAddr addr, u8 data);
-void Write16(VAddr addr, u16 data);
-void Write32(VAddr addr, u32 data);
-void Write64(VAddr addr, u64 data);
-
 void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size);
 void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
                 std::size_t size);
@@ -198,8 +188,6 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
 void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process,
                VAddr src_addr, VAddr dest_addr, std::size_t size);
 
-std::string ReadCString(VAddr vaddr, std::size_t max_length);
-
 /**
  * Mark each page touching the region as cached.
  */
@@ -241,6 +229,18 @@ public:
     void SetCurrentPageTable(PageTable* page_table);
     PageTable* GetCurrentPageTable();
 
+    u8 Read8(VAddr addr);
+    u16 Read16(VAddr addr);
+    u32 Read32(VAddr addr);
+    u64 Read64(VAddr addr);
+
+    void Write8(VAddr addr, u8 data);
+    void Write16(VAddr addr, u16 data);
+    void Write32(VAddr addr, u32 data);
+    void Write64(VAddr addr, u64 data);
+
+    std::string ReadCString(VAddr vaddr, std::size_t max_length);
+
     /// Determines if the given VAddr is valid for the specified process.
     bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
 
@@ -255,6 +255,13 @@ public:
 
     /// Gets offset in FCRAM from a pointer inside FCRAM range
     u32 GetFCRAMOffset(u8* pointer);
+
+private:
+    template <typename T>
+    T Read(const VAddr vaddr);
+
+    template <typename T>
+    void Write(const VAddr vaddr, const T data);
 };
 
 } // namespace Memory