Browse Source

Merge pull request #762 from yuriks/memmap

Memory: Use a table based lookup scheme to read from memory regions
Yuri Kunde Schlesner 11 năm trước cách đây
mục cha
commit
bb68933894
38 tập tin đã thay đổi với 572 bổ sung589 xóa
  1. 1 1
      src/citra_qt/debugger/callstack.cpp
  2. 1 1
      src/citra_qt/debugger/disassembler.cpp
  3. 2 0
      src/citra_qt/debugger/graphics_framebuffer.cpp
  4. 0 2
      src/citra_qt/debugger/ramview.cpp
  5. 3 1
      src/core/CMakeLists.txt
  6. 1 1
      src/core/arm/dyncom/arm_dyncom_interpreter.cpp
  7. 0 1
      src/core/arm/interpreter/arminit.cpp
  8. 1 1
      src/core/arm/skyeye_common/armmmu.h
  9. 0 1
      src/core/core.cpp
  10. 1 1
      src/core/file_sys/archive_backend.cpp
  11. 2 47
      src/core/hle/config_mem.cpp
  12. 35 3
      src/core/hle/config_mem.h
  13. 3 3
      src/core/hle/function_wrappers.h
  14. 1 1
      src/core/hle/kernel/address_arbiter.cpp
  15. 1 1
      src/core/hle/kernel/process.cpp
  16. 1 1
      src/core/hle/kernel/session.h
  17. 1 1
      src/core/hle/kernel/shared_memory.cpp
  18. 1 1
      src/core/hle/kernel/thread.cpp
  19. 0 1
      src/core/hle/kernel/thread.h
  20. 1 0
      src/core/hle/service/gsp_gpu.cpp
  21. 3 54
      src/core/hle/shared_page.cpp
  22. 33 5
      src/core/hle/shared_page.h
  23. 1 1
      src/core/hle/svc.cpp
  24. 1 1
      src/core/hw/gpu.cpp
  25. 1 1
      src/core/loader/3dsx.cpp
  26. 1 1
      src/core/loader/elf.cpp
  27. 0 1
      src/core/loader/loader.cpp
  28. 1 1
      src/core/loader/ncch.cpp
  29. 112 10
      src/core/mem_map.cpp
  30. 0 157
      src/core/mem_map.h
  31. 0 283
      src/core/mem_map_funcs.cpp
  32. 202 0
      src/core/memory.cpp
  33. 129 0
      src/core/memory.h
  34. 29 0
      src/core/memory_setup.h
  35. 0 2
      src/video_core/pica.h
  36. 2 0
      src/video_core/rasterizer.cpp
  37. 1 1
      src/video_core/renderer_opengl/renderer_opengl.cpp
  38. 0 2
      src/video_core/vertex_shader.cpp

+ 1 - 1
src/citra_qt/debugger/callstack.cpp

@@ -8,7 +8,7 @@
 
 #include "core/core.h"
 #include "core/arm/arm_interface.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "common/symbols.h"
 #include "core/arm/disassembler/arm_disasm.h"
 

+ 1 - 1
src/citra_qt/debugger/disassembler.cpp

@@ -7,7 +7,7 @@
 #include "../bootmanager.h"
 #include "../hotkeys.h"
 
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 #include "core/core.h"
 #include "common/break_points.h"

+ 2 - 0
src/citra_qt/debugger/graphics_framebuffer.cpp

@@ -10,6 +10,8 @@
 #include <QSpinBox>
 
 #include "core/hw/gpu.h"
+#include "core/memory.h"
+
 #include "video_core/color.h"
 #include "video_core/pica.h"
 #include "video_core/utils.h"

+ 0 - 2
src/citra_qt/debugger/ramview.cpp

@@ -4,8 +4,6 @@
 
 #include "ramview.h"
 
-#include "core/mem_map.h"
-
 
 GRamView::GRamView(QWidget* parent) : QHexEdit(parent)
 {

+ 3 - 1
src/core/CMakeLists.txt

@@ -99,7 +99,7 @@ set(SRCS
             loader/loader.cpp
             loader/ncch.cpp
             mem_map.cpp
-            mem_map_funcs.cpp
+            memory.cpp
             settings.cpp
             system.cpp
             )
@@ -211,6 +211,8 @@ set(HEADERS
             loader/loader.h
             loader/ncch.h
             mem_map.h
+            memory.h
+            memory_setup.h
             settings.h
             system.h
             )

+ 1 - 1
src/core/arm/dyncom/arm_dyncom_interpreter.cpp

@@ -10,7 +10,7 @@
 #include "common/logging/log.h"
 #include "common/profiler.h"
 
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/hle/svc.h"
 #include "core/arm/disassembler/arm_disasm.h"
 #include "core/arm/dyncom/arm_dyncom_interpreter.h"

+ 0 - 1
src/core/arm/interpreter/arminit.cpp

@@ -16,7 +16,6 @@
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
 #include <cstring>
-#include "core/mem_map.h"
 #include "core/arm/skyeye_common/armdefs.h"
 #include "core/arm/skyeye_common/armemu.h"
 #include "core/arm/skyeye_common/vfp/vfp.h"

+ 1 - 1
src/core/arm/skyeye_common/armmmu.h

@@ -22,7 +22,7 @@
 
 #include "common/swap.h"
 
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/arm/skyeye_common/armdefs.h"
 
 // Register numbers in the MMU

+ 0 - 1
src/core/core.cpp

@@ -8,7 +8,6 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 
-#include "core/mem_map.h"
 #include "core/settings.h"
 #include "core/arm/arm_interface.h"
 #include "core/arm/disassembler/arm_disasm.h"

+ 1 - 1
src/core/file_sys/archive_backend.cpp

@@ -8,7 +8,7 @@
 #include "common/string_util.h"
 
 #include "core/file_sys/archive_backend.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 
 namespace FileSys {

+ 2 - 47
src/core/hle/config_mem.cpp

@@ -9,59 +9,14 @@
 #include "common/common_funcs.h"
 
 #include "core/core.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/hle/config_mem.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace ConfigMem {
 
-struct ConfigMemDef {
-    u8  kernel_unk;                      // 0
-    u8  kernel_version_rev;              // 1
-    u8  kernel_version_min;              // 2
-    u8  kernel_version_maj;              // 3
-    u32 update_flag;                     // 4
-    u64 ns_tid;                          // 8
-    u32 sys_core_ver;                    // 10
-    u8  unit_info;                       // 14
-    u8  boot_firm;                       // 15
-    u8  prev_firm;                       // 16
-    INSERT_PADDING_BYTES(0x1);           // 17
-    u32 ctr_sdk_ver;                     // 18
-    INSERT_PADDING_BYTES(0x30 - 0x1C);   // 1C
-    u32 app_mem_type;                    // 30
-    INSERT_PADDING_BYTES(0x40 - 0x34);   // 34
-    u32 app_mem_alloc;                   // 40
-    u32 sys_mem_alloc;                   // 44
-    u32 base_mem_alloc;                  // 48
-    INSERT_PADDING_BYTES(0x60 - 0x4C);   // 4C
-    u8  firm_unk;                        // 60
-    u8  firm_version_rev;                // 61
-    u8  firm_version_min;                // 62
-    u8  firm_version_maj;                // 63
-    u32 firm_sys_core_ver;               // 64
-    u32 firm_ctr_sdk_ver;                // 68
-    INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
-};
-
-static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong");
-
-static ConfigMemDef config_mem;
-
-template <typename T>
-inline void Read(T &var, const u32 addr) {
-    u32 offset = addr - Memory::CONFIG_MEMORY_VADDR;
-    ASSERT(offset < Memory::CONFIG_MEMORY_SIZE);
-    var = *(reinterpret_cast<T*>(((uintptr_t)&config_mem) + offset));
-}
-
-// Explicitly instantiate template functions because we aren't defining this in the header:
-
-template void Read<u64>(u64 &var, const u32 addr);
-template void Read<u32>(u32 &var, const u32 addr);
-template void Read<u16>(u16 &var, const u32 addr);
-template void Read<u8>(u8 &var, const u32 addr);
+ConfigMemDef config_mem;
 
 void Init() {
     std::memset(&config_mem, 0, sizeof(config_mem));

+ 35 - 3
src/core/hle/config_mem.h

@@ -9,17 +9,49 @@
 // bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm
 // putting this as a subset of HLE for now.
 
+#include "common/common_funcs.h"
 #include "common/common_types.h"
+#include "common/swap.h"
+
+#include "core/memory.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace ConfigMem {
 
-template <typename T>
-void Read(T &var, const u32 addr);
+struct ConfigMemDef {
+    u8     kernel_unk;                   // 0
+    u8     kernel_version_rev;           // 1
+    u8     kernel_version_min;           // 2
+    u8     kernel_version_maj;           // 3
+    u32_le update_flag;                  // 4
+    u64_le ns_tid;                       // 8
+    u32_le sys_core_ver;                 // 10
+    u8     unit_info;                    // 14
+    u8     boot_firm;                    // 15
+    u8     prev_firm;                    // 16
+    INSERT_PADDING_BYTES(0x1);           // 17
+    u32_le ctr_sdk_ver;                  // 18
+    INSERT_PADDING_BYTES(0x30 - 0x1C);   // 1C
+    u32_le app_mem_type;                 // 30
+    INSERT_PADDING_BYTES(0x40 - 0x34);   // 34
+    u32_le app_mem_alloc;                // 40
+    u32_le sys_mem_alloc;                // 44
+    u32_le base_mem_alloc;               // 48
+    INSERT_PADDING_BYTES(0x60 - 0x4C);   // 4C
+    u8     firm_unk;                     // 60
+    u8     firm_version_rev;             // 61
+    u8     firm_version_min;             // 62
+    u8     firm_version_maj;             // 63
+    u32_le firm_sys_core_ver;            // 64
+    u32_le firm_ctr_sdk_ver;             // 68
+    INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
+};
+static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong");
+
+extern ConfigMemDef config_mem;
 
 void Init();
-
 void Shutdown();
 
 } // namespace

+ 3 - 3
src/core/hle/function_wrappers.h

@@ -7,7 +7,7 @@
 #include "common/common_types.h"
 
 #include "core/arm/arm_interface.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/hle/hle.h"
 
 namespace HLE {
@@ -109,7 +109,7 @@ template<ResultCode func(s64*, u32, void*, s32)> void Wrap(){
 
 template<ResultCode func(u32*, const char*)> void Wrap() {
     u32 param_1 = 0;
-    u32 retval = func(&param_1, Memory::GetCharPointer(PARAM(1))).raw;
+    u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
     Core::g_app_core->SetReg(1, param_1);
     FuncReturn(retval);
 }
@@ -163,7 +163,7 @@ template<void func(s64)> void Wrap() {
 }
 
 template<void func(const char*)> void Wrap() {
-    func(Memory::GetCharPointer(PARAM(0)));
+    func((char*)Memory::GetPointer(PARAM(0)));
 }
 
 #undef PARAM

+ 1 - 1
src/core/hle/kernel/address_arbiter.cpp

@@ -5,7 +5,7 @@
 #include "common/common_types.h"
 #include "common/logging/log.h"
 
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 #include "core/hle/hle.h"
 #include "core/hle/kernel/address_arbiter.h"

+ 1 - 1
src/core/hle/kernel/process.cpp

@@ -8,7 +8,7 @@
 
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/thread.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 namespace Kernel {
 

+ 1 - 1
src/core/hle/kernel/session.h

@@ -6,7 +6,7 @@
 
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/thread.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 namespace Kernel {
 

+ 1 - 1
src/core/hle/kernel/shared_memory.cpp

@@ -6,7 +6,7 @@
 
 #include "common/logging/log.h"
 
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/hle/kernel/shared_memory.h"
 
 namespace Kernel {

+ 1 - 1
src/core/hle/kernel/thread.cpp

@@ -21,7 +21,7 @@
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/result.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 namespace Kernel {
 

+ 0 - 1
src/core/hle/kernel/thread.h

@@ -12,7 +12,6 @@
 #include "common/common_types.h"
 
 #include "core/core.h"
-#include "core/mem_map.h"
 
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/result.h"

+ 1 - 0
src/core/hle/service/gsp_gpu.cpp

@@ -5,6 +5,7 @@
 #include "common/bit_field.h"
 
 #include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/hle/kernel/event.h"
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/result.h"

+ 3 - 54
src/core/hle/shared_page.cpp

@@ -8,7 +8,7 @@
 #include "common/common_funcs.h"
 
 #include "core/core.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/hle/config_mem.h"
 #include "core/hle/shared_page.h"
 
@@ -16,63 +16,12 @@
 
 namespace SharedPage {
 
-// see http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes
+SharedPageDef shared_page;
 
-#pragma pack(1)
-struct DateTime {
-    u64     date_time;      // 0x0
-    u64     update_tick;    // 0x8
-    INSERT_PADDING_BYTES(0x20 - 0x10); // 0x10
-};
-
-struct SharedPageDef {
-    // most of these names are taken from the 3dbrew page linked above.
-    u32    date_time_selector;  // 0x0
-    u8     running_hw;          // 0x4
-    u8     mcu_hw_info;         // 0x5: don't know what the acronyms mean
-    INSERT_PADDING_BYTES(0x20 - 0x6); // 0x6
-    DateTime date_time_0;       // 0x20
-    DateTime date_time_1;       // 0x40
-    u8      wifi_macaddr[6];    // 0x60
-    u8      wifi_unknown1;      // 0x66: 3dbrew says these are "Likely wifi hardware related"
-    u8      wifi_unknown2;      // 0x67
-    INSERT_PADDING_BYTES(0x80 - 0x68); // 0x68
-    float   sliderstate_3d;     // 0x80
-    u8      ledstate_3d;        // 0x84
-    INSERT_PADDING_BYTES(0xA0 - 0x85); // 0x85
-    u64     menu_title_id;      // 0xA0
-    u64     active_menu_title_id; // 0xA8
-    INSERT_PADDING_BYTES(0x1000 - 0xB0); // 0xB0
-};
-#pragma pack()
-
-static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
-static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong");
-
-static SharedPageDef shared_page;
-
-template <typename T>
-inline void Read(T &var, const u32 addr) {
-    u32 offset = addr - Memory::SHARED_PAGE_VADDR;
-    var = *(reinterpret_cast<T*>(((uintptr_t)&shared_page) + offset));
-}
-
-// Explicitly instantiate template functions because we aren't defining this in the header:
-template void Read<u64>(u64 &var, const u32 addr);
-template void Read<u32>(u32 &var, const u32 addr);
-template void Read<u16>(u16 &var, const u32 addr);
-template void Read<u8>(u8 &var, const u32 addr);
-
-void Set3DSlider(float amount) {
+void Init() {
     std::memset(&shared_page, 0, sizeof(shared_page));
 
-    shared_page.sliderstate_3d = amount;
-    shared_page.ledstate_3d = (amount == 0.0f); // off when non-zero
-}
-
-void Init() {
     shared_page.running_hw = 0x1; // product
-    Set3DSlider(0.0f);
 }
 
 void Shutdown() {

+ 33 - 5
src/core/hle/shared_page.h

@@ -11,18 +11,46 @@
  */
 
 #include "common/common_types.h"
+#include "common/swap.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace SharedPage {
 
-template <typename T>
-void Read(T &var, const u32 addr);
-
-void Set3DSlider(float amount);
+// See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes
+
+struct DateTime {
+    u64_le date_time;                  // 0
+    u64_le update_tick;                // 8
+    INSERT_PADDING_BYTES(0x20 - 0x10); // 10
+};
+static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
+
+struct SharedPageDef {
+    // Most of these names are taken from the 3dbrew page linked above.
+    u32_le   date_time_selector;         // 0
+    u8       running_hw;                 // 4
+    /// "Microcontroller hardware info"
+    u8       mcu_hw_info;                // 5
+    INSERT_PADDING_BYTES(0x20 - 0x6);    // 6
+    DateTime date_time_0;                // 20
+    DateTime date_time_1;                // 40
+    u8       wifi_macaddr[6];            // 60
+    u8       wifi_unknown1;              // 66
+    u8       wifi_unknown2;              // 67
+    INSERT_PADDING_BYTES(0x80 - 0x68);   // 68
+    float_le sliderstate_3d;             // 80
+    u8       ledstate_3d;                // 84
+    INSERT_PADDING_BYTES(0xA0 - 0x85);   // 85
+    u64_le   menu_title_id;              // A0
+    u64_le   active_menu_title_id;       // A8
+    INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
+};
+static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong");
+
+extern SharedPageDef shared_page;
 
 void Init();
-
 void Shutdown();
 
 } // namespace

+ 1 - 1
src/core/hle/svc.cpp

@@ -315,7 +315,7 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
     s32 name_count) {
     LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%p, name_count=%d",
         resource_limit, names, name_count);
-    Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
+    values[0] = 0; // Normmatt: Set used memory to 0 for now
     return RESULT_SUCCESS;
 }
 

+ 1 - 1
src/core/hw/gpu.cpp

@@ -8,7 +8,7 @@
 
 #include "core/settings.h"
 #include "core/core.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/core_timing.h"
 
 #include "core/hle/hle.h"

+ 1 - 1
src/core/loader/3dsx.cpp

@@ -12,7 +12,7 @@
 #include "core/hle/service/fs/archive.h"
 #include "core/loader/elf.h"
 #include "core/loader/ncch.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 #include "3dsx.h"
 

+ 1 - 1
src/core/loader/elf.cpp

@@ -12,7 +12,7 @@
 
 #include "core/hle/kernel/kernel.h"
 #include "core/loader/elf.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // ELF Header Constants

+ 0 - 1
src/core/loader/loader.cpp

@@ -13,7 +13,6 @@
 #include "core/loader/3dsx.h"
 #include "core/loader/elf.h"
 #include "core/loader/ncch.h"
-#include "core/mem_map.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 

+ 1 - 1
src/core/loader/ncch.cpp

@@ -12,7 +12,7 @@
 
 #include "core/hle/kernel/kernel.h"
 #include "core/loader/ncch.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Loader namespace

+ 112 - 10
src/core/mem_map.cpp

@@ -2,10 +2,16 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <map>
+
 #include "common/common_types.h"
 #include "common/logging/log.h"
 
+#include "core/hle/config_mem.h"
+#include "core/hle/shared_page.h"
 #include "core/mem_map.h"
+#include "core/memory.h"
+#include "core/memory_setup.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -23,33 +29,129 @@ namespace {
 
 struct MemoryArea {
     u8** ptr;
-    size_t size;
+    u32 base;
+    u32 size;
 };
 
 // We don't declare the IO regions in here since its handled by other means.
 static MemoryArea memory_areas[] = {
-    {&g_exefs_code,  PROCESS_IMAGE_MAX_SIZE},
-    {&g_heap,        HEAP_SIZE             },
-    {&g_shared_mem,  SHARED_MEMORY_SIZE    },
-    {&g_heap_linear, LINEAR_HEAP_SIZE      },
-    {&g_vram,        VRAM_SIZE             },
-    {&g_dsp_mem,     DSP_RAM_SIZE          },
-    {&g_tls_mem,     TLS_AREA_SIZE         },
+    {&g_exefs_code,  PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE},
+    {&g_heap,        HEAP_VADDR,          HEAP_SIZE             },
+    {&g_shared_mem,  SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE    },
+    {&g_heap_linear, LINEAR_HEAP_VADDR,   LINEAR_HEAP_SIZE      },
+    {&g_vram,        VRAM_VADDR,          VRAM_SIZE             },
+    {&g_dsp_mem,     DSP_RAM_VADDR,       DSP_RAM_SIZE          },
+    {&g_tls_mem,     TLS_AREA_VADDR,      TLS_AREA_SIZE         },
+};
+
+/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock
+struct MemoryBlock {
+    MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) {
+    }
+    u32 handle;
+    u32 base_address;
+    u32 address;
+    u32 size;
+    u32 operation;
+    u32 permissions;
+
+    const u32 GetVirtualAddress() const{
+        return base_address + address;
+    }
 };
 
+static std::map<u32, MemoryBlock> heap_map;
+static std::map<u32, MemoryBlock> heap_linear_map;
+
+}
+
+u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
+    MemoryBlock block;
+
+    block.base_address  = HEAP_VADDR;
+    block.size          = size;
+    block.operation     = operation;
+    block.permissions   = permissions;
+
+    if (heap_map.size() > 0) {
+        const MemoryBlock last_block = heap_map.rbegin()->second;
+        block.address = last_block.address + last_block.size;
+    }
+    heap_map[block.GetVirtualAddress()] = block;
+
+    return block.GetVirtualAddress();
+}
+
+u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) {
+    MemoryBlock block;
+
+    block.base_address  = LINEAR_HEAP_VADDR;
+    block.size          = size;
+    block.operation     = operation;
+    block.permissions   = permissions;
+
+    if (heap_linear_map.size() > 0) {
+        const MemoryBlock last_block = heap_linear_map.rbegin()->second;
+        block.address = last_block.address + last_block.size;
+    }
+    heap_linear_map[block.GetVirtualAddress()] = block;
+
+    return block.GetVirtualAddress();
+}
+
+PAddr VirtualToPhysicalAddress(const VAddr addr) {
+    if (addr == 0) {
+        return 0;
+    } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
+        return addr - VRAM_VADDR + VRAM_PADDR;
+    } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
+        return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR;
+    } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) {
+        return addr - DSP_RAM_VADDR + DSP_RAM_PADDR;
+    } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) {
+        return addr - IO_AREA_VADDR + IO_AREA_PADDR;
+    }
+
+    LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr);
+    // To help with debugging, set bit on address so that it's obviously invalid.
+    return addr | 0x80000000;
+}
+
+VAddr PhysicalToVirtualAddress(const PAddr addr) {
+    if (addr == 0) {
+        return 0;
+    } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
+        return addr - VRAM_PADDR + VRAM_VADDR;
+    } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
+        return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR;
+    } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
+        return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
+    } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
+        return addr - IO_AREA_PADDR + IO_AREA_VADDR;
+    }
+
+    LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr);
+    // To help with debugging, set bit on address so that it's obviously invalid.
+    return addr | 0x80000000;
 }
 
 void Init() {
+    InitMemoryMap();
+
     for (MemoryArea& area : memory_areas) {
         *area.ptr = new u8[area.size];
+        MapMemoryRegion(area.base, area.size, *area.ptr);
     }
-    MemBlock_Init();
+    MapMemoryRegion(CONFIG_MEMORY_VADDR, CONFIG_MEMORY_SIZE, (u8*)&ConfigMem::config_mem);
+    MapMemoryRegion(SHARED_PAGE_VADDR, SHARED_PAGE_SIZE, (u8*)&SharedPage::shared_page);
 
     LOG_DEBUG(HW_Memory, "initialized OK, RAM at %p", g_heap);
 }
 
 void Shutdown() {
-    MemBlock_Shutdown();
+    heap_map.clear();
+    heap_linear_map.clear();
+
     for (MemoryArea& area : memory_areas) {
         delete[] *area.ptr;
         *area.ptr = nullptr;

+ 0 - 157
src/core/mem_map.h

@@ -8,121 +8,6 @@
 
 namespace Memory {
 
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-const u32 PAGE_SIZE = 0x1000;
-
-/// Physical memory regions as seen from the ARM11
-enum : PAddr {
-    /// IO register area
-    IO_AREA_PADDR     = 0x10100000,
-    IO_AREA_SIZE      = 0x01000000, ///< IO area size (16MB)
-    IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE,
-
-    /// MPCore internal memory region
-    MPCORE_RAM_PADDR     = 0x17E00000,
-    MPCORE_RAM_SIZE      = 0x00002000, ///< MPCore internal memory size (8KB)
-    MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE,
-
-    /// Video memory
-    VRAM_PADDR     = 0x18000000,
-    VRAM_SIZE      = 0x00600000, ///< VRAM size (6MB)
-    VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
-
-    /// DSP memory
-    DSP_RAM_PADDR     = 0x1FF00000,
-    DSP_RAM_SIZE      = 0x00080000, ///< DSP memory size (512KB)
-    DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE,
-
-    /// AXI WRAM
-    AXI_WRAM_PADDR     = 0x1FF80000,
-    AXI_WRAM_SIZE      = 0x00080000, ///< AXI WRAM size (512KB)
-    AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE,
-
-    /// Main FCRAM
-    FCRAM_PADDR     = 0x20000000,
-    FCRAM_SIZE      = 0x08000000, ///< FCRAM size (128MB)
-    FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE,
-};
-
-/// Virtual user-space memory regions
-enum : VAddr {
-    /// Where the application text, data and bss reside.
-    PROCESS_IMAGE_VADDR     = 0x00100000,
-    PROCESS_IMAGE_MAX_SIZE  = 0x03F00000,
-    PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
-
-    /// Area where IPC buffers are mapped onto.
-    IPC_MAPPING_VADDR     = 0x04000000,
-    IPC_MAPPING_SIZE      = 0x04000000,
-    IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
-
-    /// Application heap (includes stack).
-    HEAP_VADDR     = 0x08000000,
-    HEAP_SIZE      = 0x08000000,
-    HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
-
-    /// Area where shared memory buffers are mapped onto.
-    SHARED_MEMORY_VADDR     = 0x10000000,
-    SHARED_MEMORY_SIZE      = 0x04000000,
-    SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
-
-    /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory.
-    LINEAR_HEAP_VADDR     = 0x14000000,
-    LINEAR_HEAP_SIZE      = 0x08000000,
-    LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
-
-    /// Maps 1:1 to the IO register area.
-    IO_AREA_VADDR     = 0x1EC00000,
-    IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,
-
-    /// Maps 1:1 to VRAM.
-    VRAM_VADDR     = 0x1F000000,
-    VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE,
-
-    /// Maps 1:1 to DSP memory.
-    DSP_RAM_VADDR     = 0x1FF00000,
-    DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE,
-
-    /// Read-only page containing kernel and system configuration values.
-    CONFIG_MEMORY_VADDR     = 0x1FF80000,
-    CONFIG_MEMORY_SIZE      = 0x00001000,
-    CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
-
-    /// Usually read-only page containing mostly values read from hardware.
-    SHARED_PAGE_VADDR     = 0x1FF81000,
-    SHARED_PAGE_SIZE      = 0x00001000,
-    SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
-
-    // TODO(yuriks): The size of this area is dynamic, the kernel grows
-    // it as more and more threads are created. For now we'll just use a 
-    // hardcoded value.
-    /// Area where TLS (Thread-Local Storage) buffers are allocated.
-    TLS_AREA_VADDR     = 0x1FF82000,
-    TLS_AREA_SIZE      = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads
-    TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock
-struct MemoryBlock {
-    MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) {
-    }
-    u32 handle;
-    u32 base_address;
-    u32 address;
-    u32 size;
-    u32 operation;
-    u32 permissions;
-
-    const u32 GetVirtualAddress() const{
-        return base_address + address;
-    }
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
 extern u8* g_exefs_code;  ///< ExeFS:/.code is loaded here
 extern u8* g_heap;        ///< Application heap (main memory)
 extern u8* g_shared_mem;  ///< Shared memory
@@ -134,29 +19,6 @@ extern u8* g_tls_mem;     ///< TLS memory
 void Init();
 void Shutdown();
 
-template <typename T>
-inline void Read(T &var, VAddr addr);
-
-template <typename T>
-inline void Write(VAddr addr, T data);
-
-u8 Read8(VAddr addr);
-u16 Read16(VAddr addr);
-u32 Read32(VAddr addr);
-u64 Read64(VAddr addr);
-
-u32 Read8_ZX(VAddr addr);
-u32 Read16_ZX(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 WriteBlock(VAddr addr, const u8* data, size_t size);
-
-u8* GetPointer(VAddr virtual_address);
-
 /**
  * Maps a block of memory on the heap
  * @param size Size of block in bytes
@@ -173,16 +35,6 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions);
  */
 u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions);
 
-/// Initialize mapped memory blocks
-void MemBlock_Init();
-
-/// Shutdown mapped memory blocks
-void MemBlock_Shutdown();
-
-inline const char* GetCharPointer(const VAddr address) {
-    return (const char *)GetPointer(address);
-}
-
 /**
  * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical
  * address. This should be used by services to translate addresses for use by the hardware.
@@ -194,13 +46,4 @@ PAddr VirtualToPhysicalAddress(VAddr addr);
  */
 VAddr PhysicalToVirtualAddress(PAddr addr);
 
-/**
- * Gets a pointer to the memory region beginning at the specified physical address.
- *
- * @note This is currently implemented using PhysicalToVirtualAddress().
- */
-inline u8* GetPhysicalPointer(PAddr address) {
-    return GetPointer(PhysicalToVirtualAddress(address));
-}
-
 } // namespace

+ 0 - 283
src/core/mem_map_funcs.cpp

@@ -1,283 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <map>
-
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "common/swap.h"
-
-#include "core/mem_map.h"
-#include "core/hw/hw.h"
-#include "hle/config_mem.h"
-#include "hle/shared_page.h"
-
-namespace Memory {
-
-static std::map<u32, MemoryBlock> heap_map;
-static std::map<u32, MemoryBlock> heap_linear_map;
-
-PAddr VirtualToPhysicalAddress(const VAddr addr) {
-    if (addr == 0) {
-        return 0;
-    } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
-        return addr - VRAM_VADDR + VRAM_PADDR;
-    } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
-        return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR;
-    } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) {
-        return addr - DSP_RAM_VADDR + DSP_RAM_PADDR;
-    } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) {
-        return addr - IO_AREA_VADDR + IO_AREA_PADDR;
-    }
-
-    LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr);
-    // To help with debugging, set bit on address so that it's obviously invalid.
-    return addr | 0x80000000;
-}
-
-VAddr PhysicalToVirtualAddress(const PAddr addr) {
-    if (addr == 0) {
-        return 0;
-    } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
-        return addr - VRAM_PADDR + VRAM_VADDR;
-    } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
-        return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR;
-    } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
-        return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
-    } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
-        return addr - IO_AREA_PADDR + IO_AREA_VADDR;
-    }
-
-    LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr);
-    // To help with debugging, set bit on address so that it's obviously invalid.
-    return addr | 0x80000000;
-}
-
-template <typename T>
-inline void Read(T &var, const VAddr vaddr) {
-    // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
-    // TODO: Make sure this represents the mirrors in a correct way.
-    // Could just do a base-relative read, too.... TODO
-
-    // Kernel memory command buffer
-    if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) {
-        var = *((const T*)&g_tls_mem[vaddr - TLS_AREA_VADDR]);
-
-    // ExeFS:/.code is loaded here
-    } else if ((vaddr >= PROCESS_IMAGE_VADDR)  && (vaddr < PROCESS_IMAGE_VADDR_END)) {
-        var = *((const T*)&g_exefs_code[vaddr - PROCESS_IMAGE_VADDR]);
-
-    // FCRAM - linear heap
-    } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) {
-        var = *((const T*)&g_heap_linear[vaddr - LINEAR_HEAP_VADDR]);
-
-    // FCRAM - application heap
-    } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
-        var = *((const T*)&g_heap[vaddr - HEAP_VADDR]);
-
-    // Shared memory
-    } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
-        var = *((const T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR]);
-
-    // Config memory
-    } else if ((vaddr >= CONFIG_MEMORY_VADDR)  && (vaddr < CONFIG_MEMORY_VADDR_END)) {
-        ConfigMem::Read<T>(var, vaddr);
-
-    // Shared page
-    } else if ((vaddr >= SHARED_PAGE_VADDR)  && (vaddr < SHARED_PAGE_VADDR_END)) {
-        SharedPage::Read<T>(var, vaddr);
-
-    // DSP memory
-    } else if ((vaddr >= DSP_RAM_VADDR)  && (vaddr < DSP_RAM_VADDR_END)) {
-        var = *((const T*)&g_dsp_mem[vaddr - DSP_RAM_VADDR]);
-
-    // VRAM
-    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
-        var = *((const T*)&g_vram[vaddr - VRAM_VADDR]);
-
-    } else {
-        LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr);
-    }
-}
-
-template <typename T>
-inline void Write(const VAddr vaddr, const T data) {
-
-    // Kernel memory command buffer
-    if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) {
-        *(T*)&g_tls_mem[vaddr - TLS_AREA_VADDR] = data;
-
-    // ExeFS:/.code is loaded here
-    } else if ((vaddr >= PROCESS_IMAGE_VADDR)  && (vaddr < PROCESS_IMAGE_VADDR_END)) {
-        *(T*)&g_exefs_code[vaddr - PROCESS_IMAGE_VADDR] = data;
-
-    // FCRAM - linear heap
-    } else if ((vaddr >= LINEAR_HEAP_VADDR)  && (vaddr < LINEAR_HEAP_VADDR_END)) {
-        *(T*)&g_heap_linear[vaddr - LINEAR_HEAP_VADDR] = data;
-
-    // FCRAM - application heap
-    } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
-        *(T*)&g_heap[vaddr - HEAP_VADDR] = data;
-
-    // Shared memory
-    } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
-        *(T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR] = data;
-
-    // VRAM
-    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
-        *(T*)&g_vram[vaddr - VRAM_VADDR] = data;
-
-    // DSP memory
-    } else if ((vaddr >= DSP_RAM_VADDR)  && (vaddr < DSP_RAM_VADDR_END)) {
-        *(T*)&g_dsp_mem[vaddr - DSP_RAM_VADDR] = data;
-
-    //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
-    //    ASSERT_MSG(MEMMAP, false, "umimplemented write to Configuration Memory");
-    //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
-    //    ASSERT_MSG(MEMMAP, false, "umimplemented write to shared page");
-
-    // Error out...
-    } else {
-        LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr);
-    }
-}
-
-u8 *GetPointer(const VAddr vaddr) {
-    // Kernel memory command buffer
-    if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) {
-        return g_tls_mem + (vaddr - TLS_AREA_VADDR);
-
-    // ExeFS:/.code is loaded here
-    } else if ((vaddr >= PROCESS_IMAGE_VADDR)  && (vaddr < PROCESS_IMAGE_VADDR_END)) {
-        return g_exefs_code + (vaddr - PROCESS_IMAGE_VADDR);
-
-    // FCRAM - linear heap
-    } else if ((vaddr >= LINEAR_HEAP_VADDR)  && (vaddr < LINEAR_HEAP_VADDR_END)) {
-        return g_heap_linear + (vaddr - LINEAR_HEAP_VADDR);
-
-    // FCRAM - application heap
-    } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
-        return g_heap + (vaddr - HEAP_VADDR);
-
-    // Shared memory
-    } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
-        return g_shared_mem + (vaddr - SHARED_MEMORY_VADDR);
-
-    // VRAM
-    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
-        return g_vram + (vaddr - VRAM_VADDR);
-
-    } else {
-        LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr);
-        return 0;
-    }
-}
-
-u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
-    MemoryBlock block;
-
-    block.base_address  = HEAP_VADDR;
-    block.size          = size;
-    block.operation     = operation;
-    block.permissions   = permissions;
-
-    if (heap_map.size() > 0) {
-        const MemoryBlock last_block = heap_map.rbegin()->second;
-        block.address = last_block.address + last_block.size;
-    }
-    heap_map[block.GetVirtualAddress()] = block;
-
-    return block.GetVirtualAddress();
-}
-
-u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) {
-    MemoryBlock block;
-
-    block.base_address  = LINEAR_HEAP_VADDR;
-    block.size          = size;
-    block.operation     = operation;
-    block.permissions   = permissions;
-
-    if (heap_linear_map.size() > 0) {
-        const MemoryBlock last_block = heap_linear_map.rbegin()->second;
-        block.address = last_block.address + last_block.size;
-    }
-    heap_linear_map[block.GetVirtualAddress()] = block;
-
-    return block.GetVirtualAddress();
-}
-
-void MemBlock_Init() {
-}
-
-void MemBlock_Shutdown() {
-    heap_map.clear();
-    heap_linear_map.clear();
-}
-
-u8 Read8(const VAddr addr) {
-    u8 data = 0;
-    Read<u8>(data, addr);
-    return data;
-}
-
-u16 Read16(const VAddr addr) {
-    u16_le data = 0;
-    Read<u16_le>(data, addr);
-    return (u16)data;
-}
-
-u32 Read32(const VAddr addr) {
-    u32_le data = 0;
-    Read<u32_le>(data, addr);
-    return (u32)data;
-}
-
-u64 Read64(const VAddr addr) {
-    u64_le data = 0;
-    Read<u64_le>(data, addr);
-    return (u64)data;
-}
-
-u32 Read8_ZX(const VAddr addr) {
-    return (u32)Read8(addr);
-}
-
-u32 Read16_ZX(const VAddr addr) {
-    return (u32)Read16(addr);
-}
-
-void Write8(const VAddr addr, const u8 data) {
-    Write<u8>(addr, data);
-}
-
-void Write16(const VAddr addr, const u16 data) {
-    Write<u16_le>(addr, data);
-}
-
-void Write32(const VAddr addr, const u32 data) {
-    Write<u32_le>(addr, data);
-}
-
-void Write64(const VAddr addr, const u64 data) {
-    Write<u64_le>(addr, data);
-}
-
-void WriteBlock(const VAddr addr, const u8* data, const size_t size) {
-    u32 offset = 0;
-    while (offset < (size & ~3)) {
-        Write32(addr + offset, *(u32*)&data[offset]);
-        offset += 4;
-    }
-
-    if (size & 2) {
-        Write16(addr + offset, *(u16*)&data[offset]);
-        offset += 2;
-    }
-
-    if (size & 1)
-        Write8(addr + offset, data[offset]);
-}
-
-} // namespace

+ 202 - 0
src/core/memory.cpp

@@ -0,0 +1,202 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "common/swap.h"
+
+#include "core/hle/config_mem.h"
+#include "core/hle/shared_page.h"
+#include "core/hw/hw.h"
+#include "core/mem_map.h"
+#include "core/memory.h"
+
+namespace Memory {
+
+const u32 PAGE_MASK = PAGE_SIZE - 1;
+const int PAGE_BITS = 12;
+
+enum class PageType {
+    /// Page is unmapped and should cause an access error.
+    Unmapped,
+    /// Page is mapped to regular memory. This is the only type you can get pointers to.
+    Memory,
+    /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
+    Special,
+};
+
+/**
+ * A (reasonably) fast way of allowing switchable and remmapable process address spaces. It loosely
+ * mimics the way a real CPU page table works, but instead is optimized for minimal decoding and
+ * fetching requirements when acessing. In the usual case of an access to regular memory, it only
+ * requires an indexed fetch and a check for NULL.
+ */
+struct PageTable {
+    static const size_t NUM_ENTRIES = 1 << (32 - PAGE_BITS);
+
+    /**
+     * Array of memory pointers backing each page. An entry can only be non-null if the
+     * corresponding entry in the `attributes` array is of type `Memory`.
+     */
+    std::array<u8*, NUM_ENTRIES> pointers;
+
+    /**
+     * Array of fine grained page attributes. If it is set to any value other than `Memory`, then
+     * the corresponding entry in `pointer` MUST be set to null.
+     */
+    std::array<PageType, NUM_ENTRIES> attributes;
+};
+
+/// Singular page table used for the singleton process
+static PageTable main_page_table;
+/// Currently active page table
+static PageTable* current_page_table = &main_page_table;
+
+static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
+    LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE);
+
+    u32 end = base + size;
+
+    while (base != end) {
+        ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base);
+
+        if (current_page_table->attributes[base] != PageType::Unmapped) {
+            LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE);
+        }
+        current_page_table->attributes[base] = type;
+        current_page_table->pointers[base] = memory;
+
+        base += 1;
+        memory += PAGE_SIZE;
+    }
+}
+
+void InitMemoryMap() {
+    main_page_table.pointers.fill(nullptr);
+    main_page_table.attributes.fill(PageType::Unmapped);
+}
+
+void MapMemoryRegion(VAddr base, u32 size, u8* target) {
+    ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size);
+    ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base);
+    MapPages(base / PAGE_SIZE, size / PAGE_SIZE, target, PageType::Memory);
+}
+
+void MapIoRegion(VAddr base, u32 size) {
+    ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size);
+    ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base);
+    MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special);
+}
+
+template <typename T>
+T Read(const VAddr vaddr) {
+    const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+    if (page_pointer) {
+        return *reinterpret_cast<const T*>(page_pointer + (vaddr & PAGE_MASK));
+    }
+
+    PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
+    switch (type) {
+    case PageType::Unmapped:
+        LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr);
+        return 0;
+    case PageType::Memory:
+        ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
+    case PageType::Special:
+        LOG_ERROR(HW_Memory, "I/O reads aren't implemented yet @ %08X", vaddr);
+        return 0;
+    default:
+        UNREACHABLE();
+    }
+}
+
+template <typename T>
+void Write(const VAddr vaddr, const T data) {
+    u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+    if (page_pointer) {
+        *reinterpret_cast<T*>(page_pointer + (vaddr & PAGE_MASK)) = data;
+        return;
+    }
+
+    PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
+    switch (type) {
+    case PageType::Unmapped:
+        LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr);
+        return;
+    case PageType::Memory:
+        ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
+    case PageType::Special:
+        LOG_ERROR(HW_Memory, "I/O writes aren't implemented yet @ %08X", vaddr);
+        return;
+    default:
+        UNREACHABLE();
+    }
+}
+
+u8* GetPointer(const VAddr vaddr) {
+    u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+    if (page_pointer) {
+        return page_pointer + (vaddr & PAGE_MASK);
+    }
+
+    LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr);
+    return nullptr;
+}
+
+u8* GetPhysicalPointer(PAddr address) {
+    return GetPointer(PhysicalToVirtualAddress(address));
+}
+
+u8 Read8(const VAddr addr) {
+    return Read<u8>(addr);
+}
+
+u16 Read16(const VAddr addr) {
+    return Read<u16_le>(addr);
+}
+
+u32 Read32(const VAddr addr) {
+    return Read<u32_le>(addr);
+}
+
+u64 Read64(const VAddr addr) {
+    return Read<u64_le>(addr);
+}
+
+void Write8(const VAddr addr, const u8 data) {
+    Write<u8>(addr, data);
+}
+
+void Write16(const VAddr addr, const u16 data) {
+    Write<u16_le>(addr, data);
+}
+
+void Write32(const VAddr addr, const u32 data) {
+    Write<u32_le>(addr, data);
+}
+
+void Write64(const VAddr addr, const u64 data) {
+    Write<u64_le>(addr, data);
+}
+
+void WriteBlock(const VAddr addr, const u8* data, const size_t size) {
+    u32 offset = 0;
+    while (offset < (size & ~3)) {
+        Write32(addr + offset, *(u32*)&data[offset]);
+        offset += 4;
+    }
+
+    if (size & 2) {
+        Write16(addr + offset, *(u16*)&data[offset]);
+        offset += 2;
+    }
+
+    if (size & 1)
+        Write8(addr + offset, data[offset]);
+}
+
+} // namespace

+ 129 - 0
src/core/memory.h

@@ -0,0 +1,129 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Memory {
+
+/**
+ * Page size used by the ARM architecture. This is the smallest granularity with which memory can
+ * be mapped.
+ */
+const u32 PAGE_SIZE = 0x1000;
+
+/// Physical memory regions as seen from the ARM11
+enum : PAddr {
+    /// IO register area
+    IO_AREA_PADDR     = 0x10100000,
+    IO_AREA_SIZE      = 0x01000000, ///< IO area size (16MB)
+    IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE,
+
+    /// MPCore internal memory region
+    MPCORE_RAM_PADDR     = 0x17E00000,
+    MPCORE_RAM_SIZE      = 0x00002000, ///< MPCore internal memory size (8KB)
+    MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE,
+
+    /// Video memory
+    VRAM_PADDR     = 0x18000000,
+    VRAM_SIZE      = 0x00600000, ///< VRAM size (6MB)
+    VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
+
+    /// DSP memory
+    DSP_RAM_PADDR     = 0x1FF00000,
+    DSP_RAM_SIZE      = 0x00080000, ///< DSP memory size (512KB)
+    DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE,
+
+    /// AXI WRAM
+    AXI_WRAM_PADDR     = 0x1FF80000,
+    AXI_WRAM_SIZE      = 0x00080000, ///< AXI WRAM size (512KB)
+    AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE,
+
+    /// Main FCRAM
+    FCRAM_PADDR     = 0x20000000,
+    FCRAM_SIZE      = 0x08000000, ///< FCRAM size (128MB)
+    FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE,
+};
+
+/// Virtual user-space memory regions
+enum : VAddr {
+    /// Where the application text, data and bss reside.
+    PROCESS_IMAGE_VADDR     = 0x00100000,
+    PROCESS_IMAGE_MAX_SIZE  = 0x03F00000,
+    PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
+
+    /// Area where IPC buffers are mapped onto.
+    IPC_MAPPING_VADDR     = 0x04000000,
+    IPC_MAPPING_SIZE      = 0x04000000,
+    IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
+
+    /// Application heap (includes stack).
+    HEAP_VADDR     = 0x08000000,
+    HEAP_SIZE      = 0x08000000,
+    HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
+
+    /// Area where shared memory buffers are mapped onto.
+    SHARED_MEMORY_VADDR     = 0x10000000,
+    SHARED_MEMORY_SIZE      = 0x04000000,
+    SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
+
+    /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory.
+    LINEAR_HEAP_VADDR     = 0x14000000,
+    LINEAR_HEAP_SIZE      = 0x08000000,
+    LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
+
+    /// Maps 1:1 to the IO register area.
+    IO_AREA_VADDR     = 0x1EC00000,
+    IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,
+
+    /// Maps 1:1 to VRAM.
+    VRAM_VADDR     = 0x1F000000,
+    VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE,
+
+    /// Maps 1:1 to DSP memory.
+    DSP_RAM_VADDR     = 0x1FF00000,
+    DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE,
+
+    /// Read-only page containing kernel and system configuration values.
+    CONFIG_MEMORY_VADDR     = 0x1FF80000,
+    CONFIG_MEMORY_SIZE      = 0x00001000,
+    CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
+
+    /// Usually read-only page containing mostly values read from hardware.
+    SHARED_PAGE_VADDR     = 0x1FF81000,
+    SHARED_PAGE_SIZE      = 0x00001000,
+    SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
+
+    // TODO(yuriks): The size of this area is dynamic, the kernel grows
+    // it as more and more threads are created. For now we'll just use a 
+    // hardcoded value.
+    /// Area where TLS (Thread-Local Storage) buffers are allocated.
+    TLS_AREA_VADDR     = 0x1FF82000,
+    TLS_AREA_SIZE      = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads
+    TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
+};
+
+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 WriteBlock(VAddr addr, const u8* data, size_t size);
+
+u8* GetPointer(VAddr virtual_address);
+
+/**
+ * Gets a pointer to the memory region beginning at the specified physical address.
+ *
+ * @note This is currently implemented using PhysicalToVirtualAddress().
+ */
+u8* GetPhysicalPointer(PAddr address);
+
+}

+ 29 - 0
src/core/memory_setup.h

@@ -0,0 +1,29 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Memory {
+
+void InitMemoryMap();
+
+/**
+ * Maps an allocated buffer onto a region of the emulated process address space.
+ *
+ * @param base The address to start mapping at. Must be page-aligned.
+ * @param size The amount of bytes to map. Must be page-aligned.
+ * @param target Buffer with the memory backing the mapping. Must be of length at least `size`.
+ */
+void MapMemoryRegion(VAddr base, u32 size, u8* target);
+
+/**
+ * Maps a region of the emulated process address space as a IO region.
+ * @note Currently this can only be used to mark a region as being IO, since actual memory-mapped
+ *       IO isn't yet supported.
+ */
+void MapIoRegion(VAddr base, u32 size);
+
+}

+ 0 - 2
src/video_core/pica.h

@@ -16,8 +16,6 @@
 #include "common/common_types.h"
 #include "common/logging/log.h"
 
-#include "core/mem_map.h"
-
 namespace Pica {
 
 // Returns index corresponding to the Regs member labeled by field_name

+ 2 - 0
src/video_core/rasterizer.cpp

@@ -9,6 +9,8 @@
 #include "common/profiler.h"
 
 #include "core/hw/gpu.h"
+#include "core/memory.h"
+
 #include "debug_utils/debug_utils.h"
 #include "math.h"
 #include "color.h"

+ 1 - 1
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -5,7 +5,7 @@
 #include "core/hw/gpu.h"
 #include "core/hw/hw.h"
 #include "core/hw/lcd.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
 #include "core/settings.h"
 
 #include "common/emu_window.h"

+ 0 - 2
src/video_core/vertex_shader.cpp

@@ -8,8 +8,6 @@
 
 #include <common/file_util.h>
 
-#include <core/mem_map.h>
-
 #include <nihstro/shader_bytecode.h>
 
 #include "common/profiler.h"