From cd0664eb77e14a801fe1f15be50c3a90b98ee5ef Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Thu, 24 Apr 2014 22:16:54 -0400
Subject: [PATCH 01/20] - refactored how service functions are called

- added option to create/delete service handles
---
 src/core/hle/service/apt.cpp   |  6 ++---
 src/core/hle/service/apt.h     |  4 ----
 src/core/hle/service/hid.cpp   |  2 +-
 src/core/hle/service/service.h | 40 +++++++++++++++++++++++++++-------
 src/core/hle/service/srv.cpp   |  6 ++---
 5 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp
index 4f8d7248dd..4a1e8c992a 100644
--- a/src/core/hle/service/apt.cpp
+++ b/src/core/hle/service/apt.cpp
@@ -13,16 +13,16 @@
 
 namespace APT_U {
 
-void Initialize() {
+void Initialize(Service::Interface* self) {
     NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize");
 }
 
-void GetLockHandle() {
+void GetLockHandle(Service::Interface* self) {
     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
     cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle
 }
 
-const HLE::FunctionDef FunctionTable[] = {
+const Interface::FunctionInfo FunctionTable[] = {
     {0x00010040, GetLockHandle, "GetLockHandle"},
     {0x00020080, Initialize,    "Initialize"},
     {0x00030040, NULL,          "Enable"},
diff --git a/src/core/hle/service/apt.h b/src/core/hle/service/apt.h
index e74baac0c0..4c7dd07e7b 100644
--- a/src/core/hle/service/apt.h
+++ b/src/core/hle/service/apt.h
@@ -32,10 +32,6 @@ public:
     std::string GetPortName() const {
         return "APT:U";
     }
-
-private:
-
-    DISALLOW_COPY_AND_ASSIGN(Interface);
 };
 
 } // namespace
diff --git a/src/core/hle/service/hid.cpp b/src/core/hle/service/hid.cpp
index 2d823dd16c..5542e5bf2f 100644
--- a/src/core/hle/service/hid.cpp
+++ b/src/core/hle/service/hid.cpp
@@ -12,7 +12,7 @@
 
 namespace HID_User {
 
-const HLE::FunctionDef FunctionTable[] = {
+const Interface::FunctionInfo FunctionTable[] = {
     {0x000A0000, NULL, "GetIPCHandles"},
     {0x00110000, NULL, "EnableAccelerometer"},
     {0x00130000, NULL, "EnableGyroscopeLow"},
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 9cbf8b6fa9..9de17beab1 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -25,7 +25,7 @@ static const int kCommandHeaderOffset   = 0x80; ///< Offset into command buffer
 class Manager;
 
 /// Interface to a CTROS service
-class Interface {
+class Interface : NonCopyable {
     friend class Manager;
 public:
 
@@ -35,6 +35,14 @@ public:
     virtual ~Interface() {
     }
 
+    typedef void (*Function)(Interface*);
+
+    struct FunctionInfo {
+        u32         id;
+        Function    func;
+        std::string name;
+    };
+
     /**
      * Gets the UID for the serice
      * @return UID of service in native format
@@ -51,6 +59,23 @@ public:
         return "[UNKNOWN SERVICE PORT]";
     }
 
+    /// Allocates a new handle for the service
+    Syscall::Handle NewHandle() {
+        Syscall::Handle handle = (m_handles.size() << 16) | m_uid;
+        m_handles.push_back(handle);
+        return handle;
+    }
+
+    /// Frees a handle from the service
+    void DeleteHandle(Syscall::Handle handle) {
+        for(auto iter = m_handles.begin(); iter != m_handles.end(); ++iter) {
+            if(*iter == handle) {
+                m_handles.erase(iter);
+                break;
+            }
+        }
+    }
+
     /**
      * Called when svcSendSyncRequest is called, loads command buffer and executes comand
      * @return Return result of svcSendSyncRequest passed back to user app
@@ -70,16 +95,17 @@ public:
             return -1;
         } 
 
-        itr->second.func();
+        itr->second.func(this);
 
         return 0; // TODO: Implement return from actual function
     }
 
 protected:
+
     /**
      * Registers the functions in the service
      */
-    void Register(const HLE::FunctionDef* functions, int len) {
+    void Register(const FunctionInfo* functions, int len) {
         for (int i = 0; i < len; i++) {
             m_functions[functions[i].id] = functions[i];
         }
@@ -87,9 +113,9 @@ protected:
 
 private:
     u32 m_uid;
-    std::map<u32, HLE::FunctionDef> m_functions;
-
-    DISALLOW_COPY_AND_ASSIGN(Interface);
+    
+    std::vector<Syscall::Handle>    m_handles;
+    std::map<u32, FunctionInfo> m_functions;
 };
 
 /// Simple class to manage accessing services from ports and UID handles
@@ -126,8 +152,6 @@ private:
 
     std::vector<Interface*>     m_services;
     std::map<std::string, u32>  m_port_map;
-
-    DISALLOW_COPY_AND_ASSIGN(Manager);
 };
 
 /// Initialize ServiceManager
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 579ea4a344..9437868c56 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -12,11 +12,11 @@
 
 namespace SRV {
 
-void Initialize() {
+void Initialize(Service::Interface* self) {
     NOTICE_LOG(OSHLE, "SRV::Sync - Initialize");
 }
 
-void GetServiceHandle() {
+void GetServiceHandle(Service::Interface* self) {
     Syscall::Result res = 0;
     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
 
@@ -37,7 +37,7 @@ void GetServiceHandle() {
     //return res;
 }
 
-const HLE::FunctionDef FunctionTable[] = {
+const Interface::FunctionInfo FunctionTable[] = {
     {0x00010002, Initialize,        "Initialize"},
     {0x00020000, NULL,              "GetProcSemaphore"},
     {0x00030100, NULL,              "RegisterService"},

From 66e1f8ab330aca275db686290d9ece5100821c6c Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Thu, 24 Apr 2014 22:20:13 -0400
Subject: [PATCH 02/20] added GSP::RegisterInterruptRelayQueue function

---
 src/core/hle/service/gsp.cpp | 71 ++++++++++++++++++++----------------
 1 file changed, 40 insertions(+), 31 deletions(-)

diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp
index 7c80ab8b59..df23ac542b 100644
--- a/src/core/hle/service/gsp.cpp
+++ b/src/core/hle/service/gsp.cpp
@@ -13,37 +13,46 @@
 
 namespace GSP_GPU {
 
-const HLE::FunctionDef FunctionTable[] = {
-    {0x00010082, NULL, "WriteHWRegs"},
-    {0x00020084, NULL, "WriteHWRegsWithMask"},
-    {0x00030082, NULL, "WriteHWRegRepeat"},
-    {0x00040080, NULL, "ReadHWRegs"},
-    {0x00050200, NULL, "SetBufferSwap"},
-    {0x00060082, NULL, "SetCommandList"},
-    {0x000700C2, NULL, "RequestDma"},
-    {0x00080082, NULL, "FlushDataCache"},
-    {0x00090082, NULL, "InvalidateDataCache"},
-    {0x000A0044, NULL, "RegisterInterruptEvents"},
-    {0x000B0040, NULL, "SetLcdForceBlack"},
-    {0x000C0000, NULL, "TriggerCmdReqQueue"},
-    {0x000D0140, NULL, "SetDisplayTransfer"},
-    {0x000E0180, NULL, "SetTextureCopy"},
-    {0x000F0200, NULL, "SetMemoryFill"},
-    {0x00100040, NULL, "SetAxiConfigQoSMode"},
-    {0x00110040, NULL, "SetPerfLogMode"},
-    {0x00120000, NULL, "GetPerfLog"},
-    {0x00130042, NULL, "RegisterInterruptRelayQueue"},
-    {0x00140000, NULL, "UnregisterInterruptRelayQueue"},
-    {0x00150002, NULL, "TryAcquireRight"},
-    {0x00160042, NULL, "AcquireRight"},
-    {0x00170000, NULL, "ReleaseRight"},
-    {0x00180000, NULL, "ImportDisplayCaptureInfo"},
-    {0x00190000, NULL, "SaveVramSysArea"},
-    {0x001A0000, NULL, "RestoreVramSysArea"},
-    {0x001B0000, NULL, "ResetGpuCore"},
-    {0x001C0040, NULL, "SetLedForceOff"},
-    {0x001D0040, NULL, "SetTestCommand"},
-    {0x001E0080, NULL, "SetInternalPriorities"},
+void RegisterInterruptRelayQueue(Service::Interface* self) {
+    u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
+    u32 flags = cmd_buff[1];
+    u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling
+    cmd_buff[4] = self->NewHandle();
+
+    return;
+}
+
+const Interface::FunctionInfo FunctionTable[] = {
+    {0x00010082, NULL,                          "WriteHWRegs"},
+    {0x00020084, NULL,                          "WriteHWRegsWithMask"},
+    {0x00030082, NULL,                          "WriteHWRegRepeat"},
+    {0x00040080, NULL,                          "ReadHWRegs"},
+    {0x00050200, NULL,                          "SetBufferSwap"},
+    {0x00060082, NULL,                          "SetCommandList"},
+    {0x000700C2, NULL,                          "RequestDma"},
+    {0x00080082, NULL,                          "FlushDataCache"},
+    {0x00090082, NULL,                          "InvalidateDataCache"},
+    {0x000A0044, NULL,                          "RegisterInterruptEvents"},
+    {0x000B0040, NULL,                          "SetLcdForceBlack"},
+    {0x000C0000, NULL,                          "TriggerCmdReqQueue"},
+    {0x000D0140, NULL,                          "SetDisplayTransfer"},
+    {0x000E0180, NULL,                          "SetTextureCopy"},
+    {0x000F0200, NULL,                          "SetMemoryFill"},
+    {0x00100040, NULL,                          "SetAxiConfigQoSMode"},
+    {0x00110040, NULL,                          "SetPerfLogMode"},
+    {0x00120000, NULL,                          "GetPerfLog"},
+    {0x00130042, RegisterInterruptRelayQueue,   "RegisterInterruptRelayQueue"},
+    {0x00140000, NULL,                          "UnregisterInterruptRelayQueue"},
+    {0x00150002, NULL,                          "TryAcquireRight"},
+    {0x00160042, NULL,                          "AcquireRight"},
+    {0x00170000, NULL,                          "ReleaseRight"},
+    {0x00180000, NULL,                          "ImportDisplayCaptureInfo"},
+    {0x00190000, NULL,                          "SaveVramSysArea"},
+    {0x001A0000, NULL,                          "RestoreVramSysArea"},
+    {0x001B0000, NULL,                          "ResetGpuCore"},
+    {0x001C0040, NULL,                          "SetLedForceOff"},
+    {0x001D0040, NULL,                          "SetTestCommand"},
+    {0x001E0080, NULL,                          "SetInternalPriorities"},
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////

From b7cd4c9e90be42476a2e242571d36cbbca2fbd4c Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Thu, 24 Apr 2014 22:32:26 -0400
Subject: [PATCH 03/20] added functions to map Heap and Shared memory space

---
 src/core/mem_map.cpp       |  4 +--
 src/core/mem_map.h         | 27 ++++++++++++++++---
 src/core/mem_map_funcs.cpp | 54 +++++++++++++++++++++++++++++++++++---
 3 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index 180829239c..f0090206e0 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -16,15 +16,15 @@ u8*    g_base                   = NULL;         ///< The base pointer to the aut
 
 MemArena g_arena;                               ///< The MemArena class
 
-u8* g_heap_gsp                  = NULL;         ///< GSP heap (main memory)
 u8* g_heap                      = NULL;         ///< Application heap (main memory)
+u8* g_heap_gsp                  = NULL;         ///< GSP heap (main memory)
 u8* g_vram                      = NULL;         ///< Video memory (VRAM) pointer
 
 u8* g_physical_bootrom          = NULL;         ///< Bootrom physical memory
 u8* g_uncached_bootrom          = NULL;
 
 u8* g_physical_fcram            = NULL;         ///< Main physical memory (FCRAM)
-u8* g_physical_heap_gsp         = NULL;
+u8* g_physical_heap_gsp         = NULL;         ///< GSP heap physical memory
 u8* g_physical_vram             = NULL;         ///< Video physical memory (VRAM)
 u8* g_physical_scratchpad       = NULL;         ///< Scratchpad memory used for main thread stack
 
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index ab1eb2606a..5346d04ee0 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -22,6 +22,8 @@ enum {
     HEAP_GSP_SIZE           = 0x02000000,   ///< GSP heap size... TODO: Define correctly?
     HEAP_SIZE               = FCRAM_SIZE,   ///< Application heap size
 
+    SHARED_MEMORY_VADDR     = 0x10000000,   ///< Shared memory
+
     HEAP_PADDR              = HEAP_GSP_SIZE,
     HEAP_PADDR_END          = (HEAP_PADDR + HEAP_SIZE),
     HEAP_VADDR              = 0x08000000,
@@ -49,10 +51,11 @@ enum {
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
-/// Represents a block of heap memory mapped by ControlMemory
-struct HeapBlock {
-    HeapBlock() : base_address(0), address(0), size(0), operation(0), permissions(0) {
+/// 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;
@@ -98,10 +101,26 @@ void Write32(const u32 addr, const u32 data);
 
 u8* GetPointer(const u32 Address);
 
+/**
+ * Maps a block of memory in shared memory
+ * @param handle Handle to map memory block for
+ * @param addr Address to map memory block to
+ * @param permissions Memory map permissions
+ */
+u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) ;
+
+/**
+ * Maps a block of memory on the heap
+ * @param size Size of block in bytes
+ * @param operation Memory map operation type
+ * @param flags Memory allocation flags
+ */
+u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions);
+
 /**
  * Maps a block of memory on the GSP heap
  * @param size Size of block in bytes
- * @param operation Control memory operation
+ * @param operation Memory map operation type
  * @param permissions Control memory permissions
  */
 u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions);
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index af4cfacbdf..eff0cf4b8c 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -12,7 +12,9 @@
 
 namespace Memory {
 
-std::map<u32, HeapBlock> g_heap_gsp_map;
+std::map<u32, MemoryBlock> g_heap_map;
+std::map<u32, MemoryBlock> g_heap_gsp_map;
+std::map<u32, MemoryBlock> g_shared_map;
 
 /// Convert a physical address to virtual address
 u32 _AddressPhysicalToVirtual(const u32 addr) {
@@ -120,13 +122,59 @@ u8 *GetPointer(const u32 addr) {
     }
 }
 
+/**
+ * Maps a block of memory in shared memory
+ * @param handle Handle to map memory block for
+ * @param addr Address to map memory block to
+ * @param permissions Memory map permissions
+ */
+u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) {
+    MemoryBlock block;
+    
+    block.handle        = handle;
+    block.base_address  = addr;
+    block.permissions   = permissions;
+    
+    if (g_shared_map.size() > 0) {
+        const MemoryBlock last_block = g_shared_map.rbegin()->second;
+        block.address = last_block.address + last_block.size;
+    }
+    g_shared_map[block.GetVirtualAddress()] = block;
+
+    return block.GetVirtualAddress();
+}
+
+/**
+ * Maps a block of memory on the heap
+ * @param size Size of block in bytes
+ * @param operation Memory map operation type
+ * @param flags Memory allocation flags
+ */
+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 (g_heap_map.size() > 0) {
+        const MemoryBlock last_block = g_heap_map.rbegin()->second;
+        block.address = last_block.address + last_block.size;
+    }
+    g_heap_map[block.GetVirtualAddress()] = block;
+
+    return block.GetVirtualAddress();
+}
+
 /**
  * Maps a block of memory on the GSP heap
  * @param size Size of block in bytes
+ * @param operation Memory map operation type
  * @param flags Memory allocation flags
  */
 u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
-    HeapBlock block;
+    MemoryBlock block;
     
     block.base_address  = HEAP_GSP_VADDR;
     block.size          = size;
@@ -134,7 +182,7 @@ u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
     block.permissions   = permissions;
     
     if (g_heap_gsp_map.size() > 0) {
-        const HeapBlock last_block = g_heap_gsp_map.rbegin()->second;
+        const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second;
         block.address = last_block.address + last_block.size;
     }
     g_heap_gsp_map[block.GetVirtualAddress()] = block;

From 890c7261d2d6d6a760512ebe93c565ee87220983 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Thu, 24 Apr 2014 23:56:06 -0400
Subject: [PATCH 04/20] - added preliminary support for svc_MapMemoryBlock

- added shared memory region
- moarrrr cleanups to memory_map
---
 src/core/hle/syscall.cpp   | 38 ++++++++++++++++++++++++++++++++++----
 src/core/mem_map.cpp       | 10 ++++++----
 src/core/mem_map.h         |  9 +++++++++
 src/core/mem_map_funcs.cpp | 27 +++++++++++++++++++++------
 4 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp
index e5533a7412..de1c118621 100644
--- a/src/core/hle/syscall.cpp
+++ b/src/core/hle/syscall.cpp
@@ -15,14 +15,29 @@
 
 namespace Syscall {
 
+enum ControlMemoryOperation {
+    MEMORY_OPERATION_HEAP       = 0x00000003,
+    MEMORY_OPERATION_GSP_HEAP   = 0x00010003,
+};
+
+enum MapMemoryPermission {
+    MEMORY_PERMISSION_UNMAP     = 0x00000000,
+    MEMORY_PERMISSION_NORMAL    = 0x00000001,
+};
+
 /// Map application or GSP heap memory
 Result ControlMemory(void* outaddr, u32 addr0, u32 addr1, u32 size, u32 operation, u32 permissions) {
     u32 virtual_address = 0x00000000;
 
     switch (operation) {
 
-    // Map GSP heap memory?
-    case 0x00010003:
+    // Map normal heap memory
+    case MEMORY_OPERATION_HEAP:
+        virtual_address = Memory::MapBlock_Heap(size, operation, permissions);
+        break;
+
+    // Map GSP heap memory
+    case MEMORY_OPERATION_GSP_HEAP:
         virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions);
         break;
 
@@ -31,7 +46,22 @@ Result ControlMemory(void* outaddr, u32 addr0, u32 addr1, u32 size, u32 operatio
         ERROR_LOG(OSHLE, "Unknown ControlMemory operation %08X", operation);
     }
 
-    Core::g_app_core->SetReg(1,  Memory::MapBlock_HeapGSP(size, operation, permissions));
+    Core::g_app_core->SetReg(1, virtual_address);
+    return 0;
+}
+
+/// Maps a memory block to specified address
+Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) {
+    int x = 0;
+    switch (mypermissions) {
+    case MEMORY_PERMISSION_NORMAL:
+    case MEMORY_PERMISSION_NORMAL + 1:
+    case MEMORY_PERMISSION_NORMAL + 2:
+        Memory::MapBlock_Shared(memblock, addr, mypermissions);
+        break;
+    default:
+        ERROR_LOG(OSHLE, "Unknown MapMemoryBlock permissions %08X", mypermissions);
+    }
     return 0;
 }
 
@@ -93,7 +123,7 @@ const HLE::FunctionDef Syscall_Table[] = {
     {0x1C,  NULL,                               "CancelTimer"},
     {0x1D,  NULL,                               "ClearTimer"},
     {0x1E,  NULL,                               "CreateMemoryBlock"},
-    {0x1F,  NULL,                               "MapMemoryBlock"},
+    {0x1F,  WrapI_UUUU<MapMemoryBlock>,         "MapMemoryBlock"},
     {0x20,  NULL,                               "UnmapMemoryBlock"},
     {0x21,  NULL,                               "CreateAddressArbiter"},
     {0x22,  NULL,                               "ArbitrateAddress"},
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index f0090206e0..96245e320d 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -19,6 +19,7 @@ MemArena g_arena;                               ///< The MemArena class
 u8* g_heap                      = NULL;         ///< Application heap (main memory)
 u8* g_heap_gsp                  = NULL;         ///< GSP heap (main memory)
 u8* g_vram                      = NULL;         ///< Video memory (VRAM) pointer
+u8* g_shared_mem                = NULL;         ///< Shared memory
 
 u8* g_physical_bootrom          = NULL;         ///< Bootrom physical memory
 u8* g_uncached_bootrom          = NULL;
@@ -26,13 +27,14 @@ u8* g_uncached_bootrom          = NULL;
 u8* g_physical_fcram            = NULL;         ///< Main physical memory (FCRAM)
 u8* g_physical_heap_gsp         = NULL;         ///< GSP heap physical memory
 u8* g_physical_vram             = NULL;         ///< Video physical memory (VRAM)
-u8* g_physical_scratchpad       = NULL;         ///< Scratchpad memory used for main thread stack
+u8* g_physical_shared_mem       = NULL;         ///< Physical shared memory
 
 // We don't declare the IO region in here since its handled by other means.
 static MemoryView g_views[] = {
-    {&g_vram,       &g_physical_vram,       VRAM_VADDR,     VRAM_SIZE,      0},
-    {&g_heap_gsp,   &g_physical_heap_gsp,   HEAP_GSP_VADDR, HEAP_GSP_SIZE,  0},
-    {&g_heap,       &g_physical_fcram,      HEAP_VADDR,     HEAP_SIZE,      MV_IS_PRIMARY_RAM},
+    {&g_vram,       &g_physical_vram,       VRAM_VADDR,             VRAM_SIZE,          0},
+    {&g_heap,       &g_physical_fcram,      HEAP_VADDR,             HEAP_SIZE,          MV_IS_PRIMARY_RAM},
+    {&g_shared_mem, &g_physical_shared_mem, SHARED_MEMORY_VADDR,    SHARED_MEMORY_SIZE, 0},
+    {&g_heap_gsp,   &g_physical_heap_gsp,   HEAP_GSP_VADDR,         HEAP_GSP_SIZE,      0},
 };
 
 /*static MemoryView views[] =
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 5346d04ee0..ab96e210fe 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -21,8 +21,11 @@ enum {
     SCRATCHPAD_SIZE         = 0x00004000,   ///< Typical stack size - TODO: Read from exheader
     HEAP_GSP_SIZE           = 0x02000000,   ///< GSP heap size... TODO: Define correctly?
     HEAP_SIZE               = FCRAM_SIZE,   ///< Application heap size
+    SHARED_MEMORY_SIZE      = 0x04000000,   ///< Shared memory size
+    HARDWARE_IO_SIZE        = 0x01000000,
 
     SHARED_MEMORY_VADDR     = 0x10000000,   ///< Shared memory
+    SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE),
 
     HEAP_PADDR              = HEAP_GSP_SIZE,
     HEAP_PADDR_END          = (HEAP_PADDR + HEAP_SIZE),
@@ -38,12 +41,17 @@ enum {
     SCRATCHPAD_MASK         = (SCRATCHPAD_SIZE - 1),            ///< Scratchpad memory mask
     HEAP_GSP_MASK           = (HEAP_GSP_SIZE - 1),
     HEAP_MASK               = (HEAP_SIZE - 1),
+    SHARED_MEMORY_MASK      = (SHARED_MEMORY_SIZE - 1),
 
     FCRAM_PADDR             = 0x20000000,                       ///< FCRAM physical address
     FCRAM_PADDR_END         = (FCRAM_PADDR + FCRAM_SIZE),       ///< FCRAM end of physical space
     FCRAM_VADDR             = 0x08000000,                       ///< FCRAM virtual address
     FCRAM_VADDR_END         = (FCRAM_VADDR + FCRAM_SIZE),       ///< FCRAM end of virtual space
 
+    HARDWARE_IO_VADDR       = 0x1EC00000,
+    HARDWARE_IO_VADDR_END   = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE),
+    
+
     VRAM_VADDR              = 0x1F000000,
     SCRATCHPAD_VADDR_END    = 0x10000000,
     SCRATCHPAD_VADDR        = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space
@@ -84,6 +92,7 @@ extern u8 *g_base;
 extern u8* g_heap_gsp;      ///< GSP heap (main memory)
 extern u8* g_heap;          ///< Application heap (main memory)
 extern u8* g_vram;          ///< Video memory (VRAM)
+extern u8* g_shared_mem;    ///< Shared memory
 
 void Init();
 void Shutdown();
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index eff0cf4b8c..b2c39c57c1 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -43,17 +43,22 @@ inline void _Read(T &var, const u32 addr) {
 
     // Hardware I/O register reads
     // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
-    } else if ((vaddr & 0xFF000000) == 0x10000000 || (vaddr & 0xFF000000) == 0x1E000000) {
+    } else if ((vaddr >= HARDWARE_IO_VADDR) && (vaddr < HARDWARE_IO_VADDR_END)) {
         HW::Read<T>(var, vaddr);
 
     // FCRAM - GSP heap
-    } else if ((vaddr > HEAP_GSP_VADDR)  && (vaddr < HEAP_GSP_VADDR_END)) {
+    } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
         var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]);
 
     // FCRAM - application heap
-    } else if ((vaddr > HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
+    } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
         var = *((const T*)&g_heap[vaddr & HEAP_MASK]);
 
+    // Shared memory
+    } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
+        NOTICE_LOG(OSHLE, "wtf read");
+        var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
+
     /*else if ((vaddr & 0x3F800000) == 0x04000000) {
         var = *((const T*)&m_pVRAM[vaddr & VRAM_MASK]);*/
 
@@ -74,17 +79,22 @@ inline void _Write(u32 addr, const T data) {
 
     // Hardware I/O register writes
     // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
-    } else if ((vaddr & 0xFF000000) == 0x10000000 || (vaddr & 0xFF000000) == 0x1E000000) {
+    } else if ((vaddr >= HARDWARE_IO_VADDR) && (vaddr < HARDWARE_IO_VADDR_END)) {
         HW::Write<T>(vaddr, data);
 
     // FCRAM - GSP heap
-    } else if ((vaddr > HEAP_GSP_VADDR)  && (vaddr < HEAP_GSP_VADDR_END)) {
+    } else if ((vaddr >= HEAP_GSP_VADDR)  && (vaddr < HEAP_GSP_VADDR_END)) {
         *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data;
 
     // FCRAM - application heap
-    } else if ((vaddr > HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
+    } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
         *(T*)&g_heap[vaddr & HEAP_MASK] = data;
 
+    // Shared memory
+    } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
+        NOTICE_LOG(OSHLE, "wtf read");
+        *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
+
     } else if ((vaddr & 0xFF000000) == 0x14000000) {
         _assert_msg_(MEMMAP, false, "umimplemented write to GSP heap");
     } else if ((vaddr & 0xFFF00000) == 0x1EC00000) {
@@ -116,6 +126,11 @@ u8 *GetPointer(const u32 addr) {
     } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) {
         return g_heap + (vaddr & HEAP_MASK);
 
+    // Shared memory
+    } else if ((vaddr > SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
+        NOTICE_LOG(OSHLE, "wtf read");
+        return g_shared_mem + (vaddr & SHARED_MEMORY_MASK);
+
     } else {
         ERROR_LOG(MEMMAP, "Unknown GetPointer @ 0x%08x", vaddr);
         return 0;

From e08f24214110d713a07c2cfb0e5202520a9eccd6 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Fri, 25 Apr 2014 15:26:27 -0400
Subject: [PATCH 05/20] fixed bug where svc_ControlMemory was not properly
 getting passed in parameters

---
 src/core/hle/syscall.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp
index de1c118621..df6412743a 100644
--- a/src/core/hle/syscall.cpp
+++ b/src/core/hle/syscall.cpp
@@ -26,7 +26,7 @@ enum MapMemoryPermission {
 };
 
 /// Map application or GSP heap memory
-Result ControlMemory(void* outaddr, u32 addr0, u32 addr1, u32 size, u32 operation, u32 permissions) {
+Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
     u32 virtual_address = 0x00000000;
 
     switch (operation) {
@@ -93,7 +93,7 @@ Result WaitSynchronization1(Handle handle, s64 nanoseconds) {
 
 const HLE::FunctionDef Syscall_Table[] = {
     {0x00,  NULL,                               "Unknown"},
-    {0x01,  WrapI_VUUUUU<ControlMemory>,        "ControlMemory"},
+    {0x01,  WrapI_UUUUU<ControlMemory>,         "ControlMemory"},
     {0x02,  NULL,                               "QueryMemory"},
     {0x03,  NULL,                               "ExitProcess"},
     {0x04,  NULL,                               "GetProcessAffinityMask"},

From 2672e7d88361528c9b2748114f6874d3474cb4da Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Fri, 25 Apr 2014 15:27:47 -0400
Subject: [PATCH 06/20] removed some cruft

---
 src/core/mem_map_funcs.cpp | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index b2c39c57c1..832957cb15 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -56,14 +56,10 @@ inline void _Read(T &var, const u32 addr) {
 
     // Shared memory
     } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
-        NOTICE_LOG(OSHLE, "wtf read");
         var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
 
-    /*else if ((vaddr & 0x3F800000) == 0x04000000) {
-        var = *((const T*)&m_pVRAM[vaddr & VRAM_MASK]);*/
-
     } else {
-        //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
+        _assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
     }
 }
 
@@ -92,7 +88,6 @@ inline void _Write(u32 addr, const T data) {
 
     // Shared memory
     } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
-        NOTICE_LOG(OSHLE, "wtf read");
         *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
 
     } else if ((vaddr & 0xFF000000) == 0x14000000) {
@@ -128,7 +123,6 @@ u8 *GetPointer(const u32 addr) {
 
     // Shared memory
     } else if ((vaddr > SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
-        NOTICE_LOG(OSHLE, "wtf read");
         return g_shared_mem + (vaddr & SHARED_MEMORY_MASK);
 
     } else {

From 6151e26958fa243b6322a9a544446dda5020204b Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Fri, 25 Apr 2014 15:57:32 -0400
Subject: [PATCH 07/20] added disassembly to unimplemented instruction

---
 src/core/arm/interpreter/armsupp.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 101b9807ae..48e55c63a7 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -17,9 +17,11 @@
 
 #include "armdefs.h"
 #include "armemu.h"
+
 //#include "ansidecl.h"
 #include "skyeye_defs.h"
 #include "core/hle/hle.h"
+#include "core/arm/disassembler/arm_disasm.h"
 
 unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
                                         unsigned cpnum);
@@ -846,7 +848,10 @@ ARMul_CDP (ARMul_State * state, ARMword instr)
 void
 ARMul_UndefInstr (ARMul_State * state, ARMword instr)
 {
-	ERROR_LOG(ARM11, "Undefined instruction!! Instr: 0x%x", instr);
+	char buff[512];
+	ARM_Disasm disasm = ARM_Disasm();
+	disasm.disasm(state->pc, instr, buff);
+	ERROR_LOG(ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", buff, instr);
 	ARMul_Abort (state, ARMul_UndefinedInstrV);
 }
 

From cb0663de5147f10533ecdbf6f58865f7cbe0241c Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Fri, 25 Apr 2014 17:15:19 -0400
Subject: [PATCH 08/20] moved HLE::MRC to its own module, added support for
 catching data synchronization barrier command

---
 src/core/CMakeLists.txt              |  1 +
 src/core/arm/interpreter/armemu.cpp  |  3 ++-
 src/core/arm/interpreter/armsupp.cpp |  5 +++--
 src/core/core.vcxproj                |  2 ++
 src/core/core.vcxproj.filters        |  6 ++++++
 src/core/hle/hle.cpp                 |  8 -------
 src/core/hle/hle.h                   |  2 --
 src/core/hle/mrc.cpp                 | 32 ++++++++++++++++++++++++++++
 src/core/hle/mrc.h                   | 20 +++++++++++++++++
 9 files changed, 66 insertions(+), 13 deletions(-)
 create mode 100644 src/core/hle/mrc.cpp
 create mode 100644 src/core/hle/mrc.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3ba3afa700..314f6e64c9 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -18,6 +18,7 @@ set(SRCS    core.cpp
             file_sys/directory_file_system.cpp
             file_sys/meta_file_system.cpp
             hle/hle.cpp
+            hle/mrc.cpp
             hle/syscall.cpp
             hle/service/apt.cpp
             hle/service/gsp.cpp
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 6074ff4807..c137c61fe2 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -4467,7 +4467,7 @@ ARMul_Emulate26 (ARMul_State * state)
                     }
                 /* Drop through.  */
 
-            case 0xe0:
+            //case 0xe0:
             case 0xe4:
             case 0xe6:
             case 0xe8:
@@ -4502,6 +4502,7 @@ ARMul_Emulate26 (ARMul_State * state)
 
 
                 /* Co-Processor Register Transfers (MRC) and Data Ops.  */
+            case 0xe0:
             case 0xe1:
             case 0xe3:
             case 0xe5:
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 48e55c63a7..b2bbedc18c 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -20,7 +20,7 @@
 
 //#include "ansidecl.h"
 #include "skyeye_defs.h"
-#include "core/hle/hle.h"
+#include "core/hle/mrc.h"
 #include "core/arm/disassembler/arm_disasm.h"
 
 unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
@@ -738,7 +738,8 @@ ARMword
 ARMul_MRC (ARMul_State * state, ARMword instr)
 {
 	unsigned cpab;
-	ARMword result = HLE::CallGetThreadCommandBuffer();
+
+	ARMword result = HLE::CallMRC((HLE::ARM11_MRC_OPERATION)BITS(20, 27));
 
 	////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
 	//if (!CP_ACCESS_ALLOWED (state, CPNum)) {
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index b6fc604c68..be84489694 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -153,6 +153,7 @@
     <ClCompile Include="file_sys\directory_file_system.cpp" />
     <ClCompile Include="file_sys\meta_file_system.cpp" />
     <ClCompile Include="hle\hle.cpp" />
+    <ClCompile Include="hle\mrc.cpp" />
     <ClCompile Include="hle\service\apt.cpp" />
     <ClCompile Include="hle\service\gsp.cpp" />
     <ClCompile Include="hle\service\hid.cpp" />
@@ -192,6 +193,7 @@
     <ClInclude Include="file_sys\meta_file_system.h" />
     <ClInclude Include="hle\function_wrappers.h" />
     <ClInclude Include="hle\hle.h" />
+    <ClInclude Include="hle\mrc.h" />
     <ClInclude Include="hle\service\apt.h" />
     <ClInclude Include="hle\service\gsp.h" />
     <ClInclude Include="hle\service\hid.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index ff7877feb6..b5473bc41e 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -105,6 +105,9 @@
     <ClCompile Include="hw\lcd.cpp">
       <Filter>hw</Filter>
     </ClCompile>
+    <ClCompile Include="hle\mrc.cpp">
+      <Filter>hle</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -205,6 +208,9 @@
     <ClInclude Include="hw\lcd.h">
       <Filter>hw</Filter>
     </ClInclude>
+    <ClInclude Include="hle\mrc.h">
+      <Filter>hle</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Text Include="CMakeLists.txt" />
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 5672a659f1..aae9a39438 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -80,14 +80,6 @@ void CallSyscall(u32 opcode) {
     }
 }
 
-/// Returns the coprocessor (in this case, syscore) command buffer pointer
-Addr CallGetThreadCommandBuffer() {
-    // Called on insruction: mrc p15, 0, r0, c13, c0, 3
-    // Returns an address in OSHLE memory for the CPU to read/write to
-    RETURN(CMD_BUFFER_ADDR);
-    return CMD_BUFFER_ADDR;
-}
-
 void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) {
     ModuleDef module = {name, num_functions, func_table};
     g_module_db.push_back(module);
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index 628a1da892..907e2d741c 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -57,8 +57,6 @@ void RegisterModule(std::string name, int num_functions, const FunctionDef *func
 
 void CallSyscall(u32 opcode);
 
-Addr CallGetThreadCommandBuffer();
-
 void Init();
 
 void Shutdown();
diff --git a/src/core/hle/mrc.cpp b/src/core/hle/mrc.cpp
new file mode 100644
index 0000000000..04d6cb5a56
--- /dev/null
+++ b/src/core/hle/mrc.cpp
@@ -0,0 +1,32 @@
+#include "mrc.h"
+#include "hle.h"
+
+namespace HLE {
+
+/// Returns the coprocessor (in this case, syscore) command buffer pointer
+Addr CallGetThreadCommandBuffer() {
+    // Called on insruction: mrc p15, 0, r0, c13, c0, 3
+    // Returns an address in OSHLE memory for the CPU to read/write to
+    RETURN(CMD_BUFFER_ADDR);
+    return CMD_BUFFER_ADDR;
+}
+
+/// Call an MRC operation in HLE
+u32 CallMRC(ARM11_MRC_OPERATION operation) {
+    switch (operation) {
+
+    case DATA_SYNCHRONIZATION_BARRIER:
+        ERROR_LOG(OSHLE, "Unimplemented MRC operation DATA_SYNCHRONIZATION_BARRIER");
+        break;
+
+    case CALL_GET_THREAD_COMMAND_BUFFER:
+        return CallGetThreadCommandBuffer();
+
+    default:
+        ERROR_LOG(OSHLE, "Unimplemented MRC operation 0x%02X", operation);
+        break;
+    }
+    return -1;
+}
+
+} // namespace
diff --git a/src/core/hle/mrc.h b/src/core/hle/mrc.h
new file mode 100644
index 0000000000..d6b9f162ff
--- /dev/null
+++ b/src/core/hle/mrc.h
@@ -0,0 +1,20 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.  
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace HLE {
+
+/// MRC operations (ARM register from coprocessor), decoded as instr[20:27]
+enum ARM11_MRC_OPERATION {
+    DATA_SYNCHRONIZATION_BARRIER    = 0xE0,
+    CALL_GET_THREAD_COMMAND_BUFFER  = 0xE1,
+};
+
+/// Call an MRC operation in HLE
+u32 CallMRC(ARM11_MRC_OPERATION operation);
+
+} // namespace

From 86a515e5acd7e5fa3abd3a012ce4771d3b920754 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sat, 26 Apr 2014 01:27:25 -0400
Subject: [PATCH 09/20] added vram to memory_map

---
 src/core/mem_map.h         |  3 ++-
 src/core/mem_map_funcs.cpp | 20 +++++++++++++-------
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index ab96e210fe..087e8d3bc9 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -50,9 +50,10 @@ enum {
 
     HARDWARE_IO_VADDR       = 0x1EC00000,
     HARDWARE_IO_VADDR_END   = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE),
-    
 
     VRAM_VADDR              = 0x1F000000,
+    VRAM_VADDR_END          = (VRAM_VADDR + VRAM_SIZE),
+
     SCRATCHPAD_VADDR_END    = 0x10000000,
     SCRATCHPAD_VADDR        = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space
 };
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 832957cb15..875821adb6 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -58,8 +58,12 @@ inline void _Read(T &var, const u32 addr) {
     } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
         var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
 
+    // VRAM
+    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
+        var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
+
     } else {
-        _assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
+        //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
     }
 }
 
@@ -90,12 +94,10 @@ inline void _Write(u32 addr, const T data) {
     } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
         *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
 
-    } else if ((vaddr & 0xFF000000) == 0x14000000) {
-        _assert_msg_(MEMMAP, false, "umimplemented write to GSP heap");
-    } else if ((vaddr & 0xFFF00000) == 0x1EC00000) {
-        _assert_msg_(MEMMAP, false, "umimplemented write to IO registers");
-    } else if ((vaddr & 0xFF000000) == 0x1F000000) {
-        _assert_msg_(MEMMAP, false, "umimplemented write to VRAM");
+    // VRAM
+    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
+        *(T*)&g_vram[vaddr & VRAM_MASK] = data;
+
     } else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
         _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
     } else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
@@ -125,6 +127,10 @@ u8 *GetPointer(const u32 addr) {
     } else if ((vaddr > SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
         return g_shared_mem + (vaddr & SHARED_MEMORY_MASK);
 
+    // VRAM
+    } else if ((vaddr > VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
+        return g_vram + (vaddr & VRAM_MASK);
+
     } else {
         ERROR_LOG(MEMMAP, "Unknown GetPointer @ 0x%08x", vaddr);
         return 0;

From 25d595d86912b079ab4d013cc2c0bd078a7276b3 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sat, 26 Apr 2014 01:32:05 -0400
Subject: [PATCH 10/20] added (fake) physical addresses for where to put
 framebuffer in VRAM

---
 src/core/hw/lcd.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h
index 386ed6004a..b047e7ceae 100644
--- a/src/core/hw/lcd.h
+++ b/src/core/hw/lcd.h
@@ -16,6 +16,7 @@ enum {
     TOP_WIDTH           = 400,
     BOTTOM_WIDTH        = 320,
 
+    // Physical addresses in FCRAM used by ARM9 applications - these are correct for real hardware 
     FRAMEBUFFER_SEL     = 0x20184E59,
     TOP_LEFT_FRAME1     = 0x20184E60,
     TOP_LEFT_FRAME2     = 0x201CB370,
@@ -23,6 +24,15 @@ enum {
     TOP_RIGHT_FRAME2    = 0x202C8670,
     SUB_FRAME1          = 0x202118E0,
     SUB_FRAME2          = 0x20249CF0,
+
+    // Physical addresses in VRAM - I'm not sure how these are actually allocated (so not real)
+    VRAM_FRAMEBUFFER_SEL    = 0x18184E59,
+    VRAM_TOP_LEFT_FRAME1    = 0x18184E60,
+    VRAM_TOP_LEFT_FRAME2    = 0x181CB370,
+    VRAM_TOP_RIGHT_FRAME1   = 0x18282160,
+    VRAM_TOP_RIGHT_FRAME2   = 0x182C8670,
+    VRAM_SUB_FRAME1         = 0x182118E0,
+    VRAM_SUB_FRAME2         = 0x18249CF0,
 };
 
 template <typename T>

From a272803dcb5fdd6b0b5181cbdeff9ad68c9db934 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sat, 26 Apr 2014 01:47:52 -0400
Subject: [PATCH 11/20] added preliminary DataSynchronizationBarrier support
 with simple DMA copy

---
 src/core/hle/mrc.cpp | 46 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/core/hle/mrc.cpp b/src/core/hle/mrc.cpp
index 04d6cb5a56..5223be7c92 100644
--- a/src/core/hle/mrc.cpp
+++ b/src/core/hle/mrc.cpp
@@ -1,10 +1,43 @@
-#include "mrc.h"
-#include "hle.h"
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.  
+
+#include "core/hle/mrc.h"
+#include "core/hle/hle.h"
+#include "core/mem_map.h"
+#include "core/core.h"
 
 namespace HLE {
 
+enum {
+    CMD_GX_REQUEST_DMA  = 0x00000000,
+};
+
+/// Data synchronization barrier
+u32 DataSynchronizationBarrier(u32* command_buffer) {
+    u32 command = command_buffer[0];
+
+    switch (command) {
+
+    case CMD_GX_REQUEST_DMA:
+        {
+            u32* src = (u32*)Memory::GetPointer(command_buffer[1]);
+            u32* dst = (u32*)Memory::GetPointer(command_buffer[2]);
+            u32 size = command_buffer[3];
+            memcpy(dst, src, size);
+        }
+        break;
+
+    default:
+        ERROR_LOG(OSHLE, "MRC::DataSynchronizationBarrier unknown command 0x%08X", command);
+        return -1;
+    }
+
+    return 0;
+}
+
 /// Returns the coprocessor (in this case, syscore) command buffer pointer
-Addr CallGetThreadCommandBuffer() {
+Addr GetThreadCommandBuffer() {
     // Called on insruction: mrc p15, 0, r0, c13, c0, 3
     // Returns an address in OSHLE memory for the CPU to read/write to
     RETURN(CMD_BUFFER_ADDR);
@@ -16,14 +49,13 @@ u32 CallMRC(ARM11_MRC_OPERATION operation) {
     switch (operation) {
 
     case DATA_SYNCHRONIZATION_BARRIER:
-        ERROR_LOG(OSHLE, "Unimplemented MRC operation DATA_SYNCHRONIZATION_BARRIER");
-        break;
+        return DataSynchronizationBarrier((u32*)Memory::GetPointer(PARAM(0)));
 
     case CALL_GET_THREAD_COMMAND_BUFFER:
-        return CallGetThreadCommandBuffer();
+        return GetThreadCommandBuffer();
 
     default:
-        ERROR_LOG(OSHLE, "Unimplemented MRC operation 0x%02X", operation);
+        ERROR_LOG(OSHLE, "unimplemented MRC operation 0x%02X", operation);
         break;
     }
     return -1;

From 9e047e32d4973cb01f96116027e80639aa9f4280 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sat, 26 Apr 2014 01:48:24 -0400
Subject: [PATCH 12/20] added  simple GSP GPU ReadHWRegs function to support
 returning the framebuffer address

---
 src/core/hle/service/gsp.cpp | 38 +++++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp
index df23ac542b..24e9f18dc0 100644
--- a/src/core/hle/service/gsp.cpp
+++ b/src/core/hle/service/gsp.cpp
@@ -5,14 +5,50 @@
 
 #include "common/log.h"
 
+#include "core/mem_map.h"
 #include "core/hle/hle.h"
 #include "core/hle/service/gsp.h"
 
+#include "core/hw/lcd.h"
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Namespace GSP_GPU
 
 namespace GSP_GPU {
 
+enum {
+    REG_FRAMEBUFFER_1   = 0x00400468,
+    REG_FRAMEBUFFER_2   = 0x00400494,
+};
+
+/// Read a GSP GPU hardware register
+void ReadHWRegs(Service::Interface* self) {
+    static const u32 framebuffer_1[] = {LCD::VRAM_TOP_LEFT_FRAME1, LCD::VRAM_TOP_RIGHT_FRAME1};
+    static const u32 framebuffer_2[] = {LCD::VRAM_TOP_LEFT_FRAME2, LCD::VRAM_TOP_RIGHT_FRAME2};
+
+    u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
+    u32 reg_addr = cmd_buff[1];
+    u32 size = cmd_buff[2];
+    u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]);
+    
+    switch (reg_addr) {
+
+    // Top framebuffer 1 addresses
+    case REG_FRAMEBUFFER_1:
+        memcpy(dst, framebuffer_1, size);
+        break;
+
+    // Top framebuffer 2 addresses
+    case REG_FRAMEBUFFER_2:
+        memcpy(dst, framebuffer_1, size);
+        break;
+
+    default:
+        ERROR_LOG(OSHLE, "GSP_GPU::ReadHWRegs unknown register read at address %08X", reg_addr);
+    }
+
+}
+
 void RegisterInterruptRelayQueue(Service::Interface* self) {
     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
     u32 flags = cmd_buff[1];
@@ -26,7 +62,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00010082, NULL,                          "WriteHWRegs"},
     {0x00020084, NULL,                          "WriteHWRegsWithMask"},
     {0x00030082, NULL,                          "WriteHWRegRepeat"},
-    {0x00040080, NULL,                          "ReadHWRegs"},
+    {0x00040080, ReadHWRegs,                    "ReadHWRegs"},
     {0x00050200, NULL,                          "SetBufferSwap"},
     {0x00060082, NULL,                          "SetCommandList"},
     {0x000700C2, NULL,                          "RequestDma"},

From f78794961e2bdcb0314516a3c2409afbfcd6d470 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sat, 26 Apr 2014 14:21:40 -0400
Subject: [PATCH 13/20] - changed HW IO map to use virtual addresses

- added hooks to catch LCD IO read/writes
---
 src/core/hw/hw.cpp         | 76 +++++++++++++++++++-------------------
 src/core/hw/lcd.cpp        | 14 +++++++
 src/core/mem_map.h         |  4 +-
 src/core/mem_map_funcs.cpp | 12 +++++-
 4 files changed, 64 insertions(+), 42 deletions(-)

diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index 16bd701254..85669ae7f7 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -12,49 +12,42 @@
 namespace HW {
 
 enum {
-    ADDRESS_CONFIG      = 0x10000000,
-    ADDRESS_IRQ         = 0x10001000,
-    ADDRESS_NDMA        = 0x10002000,
-    ADDRESS_TIMER       = 0x10003000,
-    ADDRESS_CTRCARD     = 0x10004000,
-    ADDRESS_CTRCARD_2   = 0x10005000,
-    ADDRESS_SDMC_NAND   = 0x10006000,
-    ADDRESS_SDMC_NAND_2 = 0x10007000,   // Apparently not used on retail
-    ADDRESS_PXI         = 0x10008000,
-    ADDRESS_AES         = 0x10009000,
-    ADDRESS_SHA         = 0x1000A000,
-    ADDRESS_RSA         = 0x1000B000,
-    ADDRESS_XDMA        = 0x1000C000,
-    ADDRESS_SPICARD     = 0x1000D800,
-    ADDRESS_CONFIG_2    = 0x10010000,
-    ADDRESS_HASH        = 0x10101000,
-    ADDRESS_CSND        = 0x10103000,
-    ADDRESS_DSP         = 0x10140000,
-    ADDRESS_PDN         = 0x10141000,
-    ADDRESS_CODEC       = 0x10141000,
-    ADDRESS_SPI         = 0x10142000,
-    ADDRESS_SPI_2       = 0x10143000,
-    ADDRESS_I2C         = 0x10144000,
-    ADDRESS_CODEC_2     = 0x10145000,
-    ADDRESS_HID         = 0x10146000,
-    ADDRESS_PAD         = 0x10146000,
-    ADDRESS_PTM         = 0x10146000,
-    ADDRESS_I2C_2       = 0x10148000,
-    ADDRESS_SPI_3       = 0x10160000,
-    ADDRESS_I2C_3       = 0x10161000,
-    ADDRESS_MIC         = 0x10162000,
-    ADDRESS_PXI_2       = 0x10163000,
-    ADDRESS_NTRCARD     = 0x10164000,
-    ADDRESS_DSP_2       = 0x10203000,
-    ADDRESS_HASH_2      = 0x10301000,
+    VADDR_HASH      = 0x1EC01000,
+    VADDR_CSND      = 0x1EC03000,
+    VADDR_DSP       = 0x1EC40000,
+    VADDR_PDN       = 0x1EC41000,
+    VADDR_CODEC     = 0x1EC41000,
+    VADDR_SPI       = 0x1EC42000,
+    VADDR_SPI_2     = 0x1EC43000,   // Only used under TWL_FIRM?
+    VADDR_I2C       = 0x1EC44000,
+    VADDR_CODEC_2   = 0x1EC45000,
+    VADDR_HID       = 0x1EC46000,
+    VADDR_PAD       = 0x1EC46000,
+    VADDR_PTM       = 0x1EC46000,
+    VADDR_GPIO      = 0x1EC47000,
+    VADDR_I2C_2     = 0x1EC48000,
+    VADDR_SPI_3     = 0x1EC60000,
+    VADDR_I2C_3     = 0x1EC61000,
+    VADDR_MIC       = 0x1EC62000,
+    VADDR_PXI       = 0x1EC63000,   // 0xFFFD2000
+    //VADDR_NTRCARD
+    VADDR_CDMA      = 0xFFFDA000,   // CoreLink DMA-330? Info
+    VADDR_DSP_2     = 0x1ED03000,
+    VADDR_HASH_2    = 0x1EE01000,
+    VADDR_LCD       = 0x1EF00000,
 };
 
 template <typename T>
 inline void Read(T &var, const u32 addr) {
     switch (addr & 0xFFFFF000) {
     
-    case ADDRESS_NDMA:
-        NDMA::Read(var, addr);
+    // TODO(bunnei): What is the virtual address of NDMA?
+    // case VADDR_NDMA:
+    //     NDMA::Read(var, addr);
+    //     break;
+
+    case VADDR_LCD:
+        LCD::Read(var, addr);
         break;
 
     default:
@@ -66,8 +59,13 @@ template <typename T>
 inline void Write(u32 addr, const T data) {
     switch (addr & 0xFFFFF000) {
     
-    case ADDRESS_NDMA:
-        NDMA::Write(addr, data);
+    // TODO(bunnei): What is the virtual address of NDMA?
+    // case VADDR_NDMA 
+    //     NDMA::Write(addr, data);
+    //     break;
+
+    case VADDR_LCD:
+        LCD::Write(addr, data);
         break;
 
     default:
diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp
index 3013673f84..822cd16473 100644
--- a/src/core/hw/lcd.cpp
+++ b/src/core/hw/lcd.cpp
@@ -18,12 +18,26 @@ u64 g_last_ticks = 0; ///< Last CPU ticks
 
 template <typename T>
 inline void Read(T &var, const u32 addr) {
+    ERROR_LOG(LCD, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr);
 }
 
 template <typename T>
 inline void Write(u32 addr, const T data) {
+    ERROR_LOG(LCD, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
 }
 
+// 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);
+
+template void Write<u64>(u32 addr, const u64 data);
+template void Write<u32>(u32 addr, const u32 data);
+template void Write<u16>(u32 addr, const u16 data);
+template void Write<u8>(u32 addr, const u8 data);
+
 /// Update hardware
 void Update() {
     u64 current_ticks = Core::g_app_core->GetTicks();
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 087e8d3bc9..1a49cc98dc 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -48,7 +48,9 @@ enum {
     FCRAM_VADDR             = 0x08000000,                       ///< FCRAM virtual address
     FCRAM_VADDR_END         = (FCRAM_VADDR + FCRAM_SIZE),       ///< FCRAM end of virtual space
 
-    HARDWARE_IO_VADDR       = 0x1EC00000,
+    HARDWARE_IO_PADDR       = 0x10000000,                       ///< IO physical address start
+    HARDWARE_IO_VADDR       = 0x1EC00000,                       ///< IO virtual address start
+    HARDWARE_IO_PADDR_END   = (HARDWARE_IO_PADDR + HARDWARE_IO_SIZE),
     HARDWARE_IO_VADDR_END   = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE),
 
     VRAM_VADDR              = 0x1F000000,
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 875821adb6..d0bec31c6f 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -21,8 +21,16 @@ u32 _AddressPhysicalToVirtual(const u32 addr) {
     // Our memory interface read/write functions assume virtual addresses. Put any physical address 
     // to virtual address translations here. This is obviously quite hacky... But we're not doing 
     // any MMU emulation yet or anything
-    if ((addr >= FCRAM_PADDR) && (addr < (FCRAM_PADDR_END))) {
+    if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) {
         return (addr & FCRAM_MASK) | FCRAM_VADDR;
+
+    // Hardware IO
+    // TODO(bunnei): FixMe
+    // This isn't going to work... The physical address of HARDWARE_IO conflicts with the virtual 
+    // address of shared memory.
+    //} else if ((addr >= HARDWARE_IO_PADDR) && (addr < HARDWARE_IO_PADDR_END)) {
+    //    return (addr + 0x0EB00000);
+
     }
     return addr;
 }
@@ -132,7 +140,7 @@ u8 *GetPointer(const u32 addr) {
         return g_vram + (vaddr & VRAM_MASK);
 
     } else {
-        ERROR_LOG(MEMMAP, "Unknown GetPointer @ 0x%08x", vaddr);
+        ERROR_LOG(MEMMAP, "unknown GetPointer @ 0x%08x", vaddr);
         return 0;
     }
 }

From f0525a1eb4bc133f43c6dd10166965467a34dd45 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 12:39:57 -0400
Subject: [PATCH 14/20] added code to LCD modules keep track of framebuffer
 location in FCRAM or VRAM

---
 src/core/hw/lcd.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++-
 src/core/hw/lcd.h   | 77 +++++++++++++++++++++++++++++++-------
 2 files changed, 153 insertions(+), 15 deletions(-)

diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp
index 822cd16473..6468053f27 100644
--- a/src/core/hw/lcd.cpp
+++ b/src/core/hw/lcd.cpp
@@ -6,19 +6,107 @@
 #include "common/log.h"
 
 #include "core/core.h"
+#include "core/mem_map.h"
 #include "core/hw/lcd.h"
 
 #include "video_core/video_core.h"
 
 namespace LCD {
 
+Registers g_regs;
+
 static const u32 kFrameTicks = 268123480 / 60;  ///< 268MHz / 60 frames per second
 
 u64 g_last_ticks = 0; ///< Last CPU ticks
 
+/**
+ * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM
+ * @param 
+ */
+void SetFramebufferLocation(const FramebufferLocation mode) {
+    switch (mode) {
+    case FRAMEBUFFER_LOCATION_FCRAM:
+        g_regs.framebuffer_top_left_1   = PADDR_TOP_LEFT_FRAME1;
+        g_regs.framebuffer_top_left_2   = PADDR_TOP_LEFT_FRAME2;
+        g_regs.framebuffer_top_right_1  = PADDR_TOP_RIGHT_FRAME1;
+        g_regs.framebuffer_top_right_2  = PADDR_TOP_RIGHT_FRAME2;
+        g_regs.framebuffer_sub_left_1   = PADDR_SUB_FRAME1;
+        //g_regs.framebuffer_sub_left_2  = unknown;
+        g_regs.framebuffer_sub_right_1  = PADDR_SUB_FRAME2;
+        //g_regs.framebufferr_sub_right_2 = unknown;
+        break;
+
+    case FRAMEBUFFER_LOCATION_VRAM:
+        g_regs.framebuffer_top_left_1   = PADDR_VRAM_TOP_LEFT_FRAME1;
+        g_regs.framebuffer_top_left_2   = PADDR_VRAM_TOP_LEFT_FRAME2;
+        g_regs.framebuffer_top_right_1  = PADDR_VRAM_TOP_RIGHT_FRAME1;
+        g_regs.framebuffer_top_right_2  = PADDR_VRAM_TOP_RIGHT_FRAME2;
+        g_regs.framebuffer_sub_left_1   = PADDR_VRAM_SUB_FRAME1;
+        //g_regs.framebuffer_sub_left_2  = unknown;
+        g_regs.framebuffer_sub_right_1  = PADDR_VRAM_SUB_FRAME2;
+        //g_regs.framebufferr_sub_right_2 = unknown;
+        break;
+    }
+}
+
+/**
+ * Gets the location of the framebuffers
+ * @return Location of framebuffers as FramebufferLocation enum
+ */
+const FramebufferLocation GetFramebufferLocation() {
+    if ((g_regs.framebuffer_top_right_1 & ~Memory::VRAM_MASK) == Memory::VRAM_PADDR) {
+        return FRAMEBUFFER_LOCATION_VRAM;
+    } else if ((g_regs.framebuffer_top_right_1 & ~Memory::FCRAM_MASK) == Memory::FCRAM_PADDR) {
+        return FRAMEBUFFER_LOCATION_FCRAM;
+    } else {
+        ERROR_LOG(LCD, "unknown framebuffer location!");
+    }
+    return FRAMEBUFFER_LOCATION_UNKNOWN;
+}
+
+/**
+ * Gets a read-only pointer to a framebuffer in memory
+ * @param address Physical address of framebuffer
+ * @return Returns const pointer to raw framebuffer
+ */
+const u8* GetFramebufferPointer(const u32 address) {
+    switch (GetFramebufferLocation()) {
+    case FRAMEBUFFER_LOCATION_FCRAM:
+        return (const u8*)Memory::GetPointer(Memory::VirtualAddressFromPhysical_FCRAM(address));
+    case FRAMEBUFFER_LOCATION_VRAM:
+        return (const u8*)Memory::GetPointer(Memory::VirtualAddressFromPhysical_VRAM(address));
+    default:
+        ERROR_LOG(LCD, "unknown framebuffer location");
+    }
+    return NULL;
+}
+
 template <typename T>
 inline void Read(T &var, const u32 addr) {
-    ERROR_LOG(LCD, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr);
+    switch (addr) {
+    case REG_FRAMEBUFFER_TOP_LEFT_1:
+        var = g_regs.framebuffer_top_left_1;
+        break;
+    case REG_FRAMEBUFFER_TOP_LEFT_2:
+        var = g_regs.framebuffer_top_left_2;
+        break;
+    case REG_FRAMEBUFFER_TOP_RIGHT_1:
+        var = g_regs.framebuffer_top_right_1;
+        break;
+    case REG_FRAMEBUFFER_TOP_RIGHT_2:
+        var = g_regs.framebuffer_top_right_2;
+        break;
+    case REG_FRAMEBUFFER_SUB_LEFT_1:
+        var = g_regs.framebuffer_sub_left_1;
+        break;
+    case REG_FRAMEBUFFER_SUB_RIGHT_1:
+        var = g_regs.framebuffer_sub_right_1;
+        break;
+    default:
+        ERROR_LOG(LCD, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr);
+        break;
+    }
+    
 }
 
 template <typename T>
@@ -51,6 +139,7 @@ void Update() {
 /// Initialize hardware
 void Init() {
     g_last_ticks = Core::g_app_core->GetTicks();
+    SetFramebufferLocation(FRAMEBUFFER_LOCATION_FCRAM);
     NOTICE_LOG(LCD, "initialized OK");
 }
 
diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h
index b047e7ceae..2dd3b4adc3 100644
--- a/src/core/hw/lcd.h
+++ b/src/core/hw/lcd.h
@@ -8,6 +8,19 @@
 
 namespace LCD {
 
+struct Registers {
+    u32 framebuffer_top_left_1;
+    u32 framebuffer_top_left_2;
+    u32 framebuffer_top_right_1;
+    u32 framebuffer_top_right_2;
+    u32 framebuffer_sub_left_1;
+    u32 framebuffer_sub_left_2;
+    u32 framebuffer_sub_right_1;
+    u32 framebuffer_sub_right_2;
+};
+
+extern Registers g_regs;
+
 enum {
     TOP_ASPECT_X        = 0x5,
     TOP_ASPECT_Y        = 0x3,
@@ -17,24 +30,60 @@ enum {
     BOTTOM_WIDTH        = 320,
 
     // Physical addresses in FCRAM used by ARM9 applications - these are correct for real hardware 
-    FRAMEBUFFER_SEL     = 0x20184E59,
-    TOP_LEFT_FRAME1     = 0x20184E60,
-    TOP_LEFT_FRAME2     = 0x201CB370,
-    TOP_RIGHT_FRAME1    = 0x20282160,
-    TOP_RIGHT_FRAME2    = 0x202C8670,
-    SUB_FRAME1          = 0x202118E0,
-    SUB_FRAME2          = 0x20249CF0,
+    PADDR_FRAMEBUFFER_SEL       = 0x20184E59,
+    PADDR_TOP_LEFT_FRAME1       = 0x20184E60,
+    PADDR_TOP_LEFT_FRAME2       = 0x201CB370,
+    PADDR_TOP_RIGHT_FRAME1      = 0x20282160,
+    PADDR_TOP_RIGHT_FRAME2      = 0x202C8670,
+    PADDR_SUB_FRAME1            = 0x202118E0,
+    PADDR_SUB_FRAME2            = 0x20249CF0,
 
     // Physical addresses in VRAM - I'm not sure how these are actually allocated (so not real)
-    VRAM_FRAMEBUFFER_SEL    = 0x18184E59,
-    VRAM_TOP_LEFT_FRAME1    = 0x18184E60,
-    VRAM_TOP_LEFT_FRAME2    = 0x181CB370,
-    VRAM_TOP_RIGHT_FRAME1   = 0x18282160,
-    VRAM_TOP_RIGHT_FRAME2   = 0x182C8670,
-    VRAM_SUB_FRAME1         = 0x182118E0,
-    VRAM_SUB_FRAME2         = 0x18249CF0,
+    PADDR_VRAM_FRAMEBUFFER_SEL  = 0x18184E59,
+    PADDR_VRAM_TOP_LEFT_FRAME1  = 0x18184E60,
+    PADDR_VRAM_TOP_LEFT_FRAME2  = 0x181CB370,
+    PADDR_VRAM_TOP_RIGHT_FRAME1 = 0x18282160,
+    PADDR_VRAM_TOP_RIGHT_FRAME2 = 0x182C8670,
+    PADDR_VRAM_SUB_FRAME1       = 0x182118E0,
+    PADDR_VRAM_SUB_FRAME2       = 0x18249CF0,
 };
 
+enum {
+    REG_FRAMEBUFFER_TOP_LEFT_1  = 0x1EF00468,   // Main LCD, first framebuffer for 3D left
+    REG_FRAMEBUFFER_TOP_LEFT_2  = 0x1EF0046C,   // Main LCD, second framebuffer for 3D left
+    REG_FRAMEBUFFER_TOP_RIGHT_1 = 0x1EF00494,   // Main LCD, first framebuffer for 3D right
+    REG_FRAMEBUFFER_TOP_RIGHT_2 = 0x1EF00498,   // Main LCD, second framebuffer for 3D right
+    REG_FRAMEBUFFER_SUB_LEFT_1  = 0x1EF00568,   // Sub LCD, first framebuffer
+    REG_FRAMEBUFFER_SUB_LEFT_2  = 0x1EF0056C,   // Sub LCD, second framebuffer
+    REG_FRAMEBUFFER_SUB_RIGHT_1 = 0x1EF00594,   // Sub LCD, unused first framebuffer
+    REG_FRAMEBUFFER_SUB_RIGHT_2 = 0x1EF00598,   // Sub LCD, unused second framebuffer
+};
+
+/// Framebuffer location
+enum FramebufferLocation {
+    FRAMEBUFFER_LOCATION_UNKNOWN,   ///< Framebuffer location is unknown
+    FRAMEBUFFER_LOCATION_FCRAM,  ///< Framebuffer is in the GSP heap
+    FRAMEBUFFER_LOCATION_VRAM,      ///< Framebuffer is in VRAM
+};
+
+/**
+ * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM
+ * @param 
+ */
+void SetFramebufferLocation(const FramebufferLocation mode);
+
+/**
+ * Gets a read-only pointer to a framebuffer in memory
+ * @param address Physical address of framebuffer
+ * @return Returns const pointer to raw framebuffer
+ */
+const u8* GetFramebufferPointer(const u32 address);
+
+/**
+ * Gets the location of the framebuffers
+ */
+const FramebufferLocation GetFramebufferLocation();
+
 template <typename T>
 inline void Read(T &var, const u32 addr);
 

From b2a6ad52f4a059b66e2a0ea12813ce968fa04277 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 12:40:31 -0400
Subject: [PATCH 15/20] added helper functions to mem_map to convert physical
 addresses to virtual addresses

---
 src/core/mem_map.h         | 14 ++++++++++++++
 src/core/mem_map_funcs.cpp |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 1a49cc98dc..c744e377e9 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -53,7 +53,9 @@ enum {
     HARDWARE_IO_PADDR_END   = (HARDWARE_IO_PADDR + HARDWARE_IO_SIZE),
     HARDWARE_IO_VADDR_END   = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE),
 
+    VRAM_PADDR              = 0x18000000,
     VRAM_VADDR              = 0x1F000000,
+    VRAM_PADDR_END          = (VRAM_PADDR + VRAM_SIZE),
     VRAM_VADDR_END          = (VRAM_VADDR + VRAM_SIZE),
 
     SCRATCHPAD_VADDR_END    = 0x10000000,
@@ -141,4 +143,16 @@ inline const char* GetCharPointer(const u32 address) {
     return (const char *)GetPointer(address);
 }
 
+inline const u32 VirtualAddressFromPhysical_FCRAM(const u32 address) {
+    return ((address & FCRAM_MASK) | FCRAM_VADDR);
+}
+
+inline const u32 VirtualAddressFromPhysical_IO(const u32 address) {
+    return (address + 0x0EB00000);
+}
+
+inline const u32 VirtualAddressFromPhysical_VRAM(const u32 address) {
+    return (address + 0x07000000);
+}
+
 } // namespace
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index d0bec31c6f..c8daf0df5f 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -22,7 +22,7 @@ u32 _AddressPhysicalToVirtual(const u32 addr) {
     // to virtual address translations here. This is obviously quite hacky... But we're not doing 
     // any MMU emulation yet or anything
     if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) {
-        return (addr & FCRAM_MASK) | FCRAM_VADDR;
+        return VirtualAddressFromPhysical_FCRAM(addr);
 
     // Hardware IO
     // TODO(bunnei): FixMe

From a6c925112a4e97feb21a8ae577f2993d0617cb1f Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 12:41:25 -0400
Subject: [PATCH 16/20] hackish but working way to set the framebuffer location
 to VRAM (used in ARM11 demos tested thus far, e.g. yeti3DS)

---
 src/core/hle/service/gsp.cpp | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp
index 24e9f18dc0..88c1f1a0fb 100644
--- a/src/core/hle/service/gsp.cpp
+++ b/src/core/hle/service/gsp.cpp
@@ -23,8 +23,8 @@ enum {
 
 /// Read a GSP GPU hardware register
 void ReadHWRegs(Service::Interface* self) {
-    static const u32 framebuffer_1[] = {LCD::VRAM_TOP_LEFT_FRAME1, LCD::VRAM_TOP_RIGHT_FRAME1};
-    static const u32 framebuffer_2[] = {LCD::VRAM_TOP_LEFT_FRAME2, LCD::VRAM_TOP_RIGHT_FRAME2};
+    static const u32 framebuffer_1[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME1, LCD::PADDR_VRAM_TOP_RIGHT_FRAME1};
+    static const u32 framebuffer_2[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME2, LCD::PADDR_VRAM_TOP_RIGHT_FRAME2};
 
     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
     u32 reg_addr = cmd_buff[1];
@@ -33,14 +33,20 @@ void ReadHWRegs(Service::Interface* self) {
     
     switch (reg_addr) {
 
+    // NOTE: Calling SetFramebufferLocation here is a hack... Not sure the correct way yet to set 
+    // whether the framebuffers should be in VRAM or GSP heap, but from what I understand, if the 
+    // user application is reading from either of these registers, then its going to be in VRAM.
+
     // Top framebuffer 1 addresses
     case REG_FRAMEBUFFER_1:
+        LCD::SetFramebufferLocation(LCD::FRAMEBUFFER_LOCATION_VRAM);
         memcpy(dst, framebuffer_1, size);
         break;
 
     // Top framebuffer 2 addresses
     case REG_FRAMEBUFFER_2:
-        memcpy(dst, framebuffer_1, size);
+        LCD::SetFramebufferLocation(LCD::FRAMEBUFFER_LOCATION_VRAM);
+        memcpy(dst, framebuffer_2, size);
         break;
 
     default:

From 1142ccba035afbe75ab707a81633c6cc26515848 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 12:42:01 -0400
Subject: [PATCH 17/20] fixed renderer to use correct framebuffer location

---
 src/video_core/renderer_opengl/renderer_opengl.cpp | 11 +++++------
 src/video_core/renderer_opengl/renderer_opengl.h   |  4 ++--
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index cf7b029ab8..b63a73d186 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -53,12 +53,11 @@ void RendererOpenGL::SwapBuffers() {
 
 /**
  * Helper function to flip framebuffer from left-to-right to top-to-bottom
- * @param addr Address of framebuffer in RAM
+ * @param in Pointer to input raw framebuffer in V/RAM
  * @param out Pointer to output buffer with flipped framebuffer
  * @todo Early on hack... I'd like to find a more efficient way of doing this /bunnei
  */
-void RendererOpenGL::FlipFramebuffer(u32 addr, u8* out) {
-    u8* in = Memory::GetPointer(addr);
+void RendererOpenGL::FlipFramebuffer(const u8* in, u8* out) {
     for (int y = 0; y < VideoCore::kScreenTopHeight; y++) {
         for (int x = 0; x < VideoCore::kScreenTopWidth; x++) {
             int in_coord = (VideoCore::kScreenTopHeight * 3 * x) + (VideoCore::kScreenTopHeight * 3)
@@ -77,10 +76,10 @@ void RendererOpenGL::FlipFramebuffer(u32 addr, u8* out) {
  * @param src_rect Source rectangle in XFB to copy
  * @param dst_rect Destination rectangle in output framebuffer to copy to
  */
-void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) {  
+void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) {
 
-    FlipFramebuffer(LCD::TOP_RIGHT_FRAME1,  m_xfb_top_flipped);
-    FlipFramebuffer(LCD::SUB_FRAME1,        m_xfb_bottom_flipped);
+    FlipFramebuffer(LCD::GetFramebufferPointer(LCD::g_regs.framebuffer_top_left_1), m_xfb_top_flipped);
+    FlipFramebuffer(LCD::GetFramebufferPointer(LCD::g_regs.framebuffer_sub_left_1), m_xfb_bottom_flipped);
 
     // Blit the top framebuffer
     // ------------------------
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 00aa17649f..676a0ea028 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -55,11 +55,11 @@ private:
 
     /**
      * Helper function to flip framebuffer from left-to-right to top-to-bottom
-     * @param addr Address of framebuffer in RAM
+     * @param in Pointer to input raw framebuffer in V/RAM
      * @param out Pointer to output buffer with flipped framebuffer
      * @todo Early on hack... I'd like to find a more efficient way of doing this /bunnei
      */
-    void RendererOpenGL::FlipFramebuffer(u32 addr, u8* out);
+    void RendererOpenGL::FlipFramebuffer(const u8* in, u8* out);
 
 
     EmuWindow*  m_render_window;                    ///< Handle to render window

From f76a60be05ea1b12fda9ad9852719b50dee9649e Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 18:22:30 -0400
Subject: [PATCH 18/20] removed commented out line - this was for an
 unimplemented MRC call, no longer need to leave this here

---
 src/core/arm/interpreter/armemu.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index c137c61fe2..a35c5c8dc3 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -4467,7 +4467,6 @@ ARMul_Emulate26 (ARMul_State * state)
                     }
                 /* Drop through.  */
 
-            //case 0xe0:
             case 0xe4:
             case 0xe6:
             case 0xe8:

From 451a14f98c4d881208c786a6a5aa621e2647aed5 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 18:24:54 -0400
Subject: [PATCH 19/20] fixed weird spacing

---
 src/core/hle/service/service.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 9de17beab1..b79dc9458b 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -115,7 +115,7 @@ private:
     u32 m_uid;
     
     std::vector<Syscall::Handle>    m_handles;
-    std::map<u32, FunctionInfo> m_functions;
+    std::map<u32, FunctionInfo>     m_functions;
 };
 
 /// Simple class to manage accessing services from ports and UID handles

From a48c6b947d5314ab804f375cca22af159cc3b77b Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sun, 27 Apr 2014 18:29:51 -0400
Subject: [PATCH 20/20] removed DISALLOW_COPY_AND_ASSIGN in favor of
 NonCopyable class

---
 src/common/common.h                              | 5 -----
 src/core/arm/arm_interface.h                     | 3 +--
 src/core/arm/interpreter/arm_interpreter.h       | 1 -
 src/core/hle/service/gsp.h                       | 3 ---
 src/core/hle/service/hid.h                       | 3 ---
 src/core/hle/service/srv.h                       | 3 ---
 src/video_core/renderer_base.h                   | 4 +---
 src/video_core/renderer_opengl/renderer_opengl.h | 1 -
 8 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/src/common/common.h b/src/common/common.h
index a281b21cc8..4187578552 100644
--- a/src/common/common.h
+++ b/src/common/common.h
@@ -159,9 +159,4 @@ enum EMUSTATE_CHANGE
     EMUSTATE_CHANGE_STOP
 };
 
-// This should be used in the private: declarations for a class
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-    TypeName(const TypeName&);               \
-    void operator=(const TypeName&)
-
 #endif // _COMMON_H_
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index eee4726db0..4dfe0570b5 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -8,7 +8,7 @@
 #include "common/common_types.h"
 
 /// Generic ARM11 CPU interface
-class ARM_Interface {
+class ARM_Interface : NonCopyable {
 public:
     ARM_Interface() {
         m_num_instructions = 0;
@@ -75,5 +75,4 @@ private:
 
     u64 m_num_instructions;                     ///< Number of instructions executed
 
-    DISALLOW_COPY_AND_ASSIGN(ARM_Interface);
 };
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index f3c86f8dd0..625c0c652c 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -63,5 +63,4 @@ private:
 
     ARMul_State* m_state;
 
-    DISALLOW_COPY_AND_ASSIGN(ARM_Interpreter);
 };
diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h
index 3b18460821..5ba09ab705 100644
--- a/src/core/hle/service/gsp.h
+++ b/src/core/hle/service/gsp.h
@@ -27,9 +27,6 @@ public:
         return "gsp::Gpu";
     }
 
-private:
-
-    DISALLOW_COPY_AND_ASSIGN(Interface);
 };
 
 } // namespace
diff --git a/src/core/hle/service/hid.h b/src/core/hle/service/hid.h
index 746c1b1fc5..b17fcfa865 100644
--- a/src/core/hle/service/hid.h
+++ b/src/core/hle/service/hid.h
@@ -29,9 +29,6 @@ public:
         return "hid:USER";
     }
 
-private:
-
-    DISALLOW_COPY_AND_ASSIGN(Interface);
 };
 
 } // namespace
diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h
index d9ac8fc888..760c976b48 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.h
@@ -32,9 +32,6 @@ public:
      */
     Syscall::Result Sync();
 
-private:
-     
-    DISALLOW_COPY_AND_ASSIGN(Interface);
 };
 
 } // namespace
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index bc65bf0ce0..2650620b4b 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -6,7 +6,7 @@
 
 #include "common/common.h"
 
-class RendererBase {
+class RendererBase : NonCopyable {
 public:
 
     /// Used to reference a framebuffer
@@ -52,6 +52,4 @@ protected:
     f32 m_current_fps;              ///< Current framerate, should be set by the renderer
     int m_current_frame;            ///< Current frame, should be set by the renderer
 
-private:
-    DISALLOW_COPY_AND_ASSIGN(RendererBase);
 };
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 676a0ea028..4c0b6e59d2 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -87,5 +87,4 @@ private:
     u8 m_xfb_top_flipped[VideoCore::kScreenTopWidth * VideoCore::kScreenTopWidth * 4]; 
     u8 m_xfb_bottom_flipped[VideoCore::kScreenTopWidth * VideoCore::kScreenTopWidth * 4];   
 
-    DISALLOW_COPY_AND_ASSIGN(RendererOpenGL);
 };
\ No newline at end of file