summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-05-14 13:52:40 -0700
committerGravatar GitHub2017-05-14 13:52:40 -0700
commit180587bb8bd18feeb81028007556276ef4ecaafd (patch)
tree5939bfa2c92ced9b30ade0b725ace7b7dce3d040 /src
parentMerge pull request #2695 from JayFoxRox/gs-regs (diff)
parentKernel: Map special regions according to ExHeader (diff)
downloadyuzu-180587bb8bd18feeb81028007556276ef4ecaafd.tar.gz
yuzu-180587bb8bd18feeb81028007556276ef4ecaafd.tar.xz
yuzu-180587bb8bd18feeb81028007556276ef4ecaafd.zip
Merge pull request #2687 from yuriks/address-mappings
Kernel: Map special regions according to ExHeader
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/audio_core.cpp19
-rw-r--r--src/audio_core/audio_core.h13
-rw-r--r--src/audio_core/hle/dsp.cpp14
-rw-r--r--src/audio_core/hle/dsp.h21
-rw-r--r--src/core/core.cpp5
-rw-r--r--src/core/hle/kernel/memory.cpp112
-rw-r--r--src/core/hle/kernel/memory.h10
-rw-r--r--src/core/hle/kernel/process.cpp23
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/memory.cpp8
-rw-r--r--src/core/memory.h10
11 files changed, 157 insertions, 80 deletions
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
index 84f9c03a7..9c2e6ed88 100644
--- a/src/audio_core/audio_core.cpp
+++ b/src/audio_core/audio_core.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
5#include <memory> 6#include <memory>
6#include <string> 7#include <string>
7#include "audio_core/audio_core.h" 8#include "audio_core/audio_core.h"
@@ -10,8 +11,8 @@
10#include "audio_core/null_sink.h" 11#include "audio_core/null_sink.h"
11#include "audio_core/sink.h" 12#include "audio_core/sink.h"
12#include "audio_core/sink_details.h" 13#include "audio_core/sink_details.h"
14#include "common/common_types.h"
13#include "core/core_timing.h" 15#include "core/core_timing.h"
14#include "core/hle/kernel/vm_manager.h"
15#include "core/hle/service/dsp_dsp.h" 16#include "core/hle/service/dsp_dsp.h"
16 17
17namespace AudioCore { 18namespace AudioCore {
@@ -39,20 +40,8 @@ void Init() {
39 CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event); 40 CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event);
40} 41}
41 42
42void AddAddressSpace(Kernel::VMManager& address_space) { 43std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() {
43 auto r0_vma = address_space 44 return DSP::HLE::g_dsp_memory.raw_memory;
44 .MapBackingMemory(DSP::HLE::region0_base,
45 reinterpret_cast<u8*>(&DSP::HLE::g_regions[0]),
46 sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO)
47 .MoveFrom();
48 address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite);
49
50 auto r1_vma = address_space
51 .MapBackingMemory(DSP::HLE::region1_base,
52 reinterpret_cast<u8*>(&DSP::HLE::g_regions[1]),
53 sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO)
54 .MoveFrom();
55 address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite);
56} 45}
57 46
58void SelectSink(std::string sink_id) { 47void SelectSink(std::string sink_id) {
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
index 0edf6dd15..ab323ce1f 100644
--- a/src/audio_core/audio_core.h
+++ b/src/audio_core/audio_core.h
@@ -4,11 +4,10 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <string> 8#include <string>
8 9#include "common/common_types.h"
9namespace Kernel { 10#include "core/memory.h"
10class VMManager;
11}
12 11
13namespace AudioCore { 12namespace AudioCore {
14 13
@@ -17,8 +16,8 @@ constexpr int native_sample_rate = 32728; ///< 32kHz
17/// Initialise Audio Core 16/// Initialise Audio Core
18void Init(); 17void Init();
19 18
20/// Add DSP address spaces to a Process. 19/// Returns a reference to the array backing DSP memory
21void AddAddressSpace(Kernel::VMManager& vm_manager); 20std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory();
22 21
23/// Select the sink to use based on sink id. 22/// Select the sink to use based on sink id.
24void SelectSink(std::string sink_id); 23void SelectSink(std::string sink_id);
@@ -29,4 +28,4 @@ void EnableStretching(bool enable);
29/// Shutdown Audio Core 28/// Shutdown Audio Core
30void Shutdown(); 29void Shutdown();
31 30
32} // namespace 31} // namespace AudioCore
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
index 31421fdc6..260b182ed 100644
--- a/src/audio_core/hle/dsp.cpp
+++ b/src/audio_core/hle/dsp.cpp
@@ -16,31 +16,33 @@ namespace HLE {
16 16
17// Region management 17// Region management
18 18
19std::array<SharedMemory, 2> g_regions; 19DspMemory g_dsp_memory;
20 20
21static size_t CurrentRegionIndex() { 21static size_t CurrentRegionIndex() {
22 // The region with the higher frame counter is chosen unless there is wraparound. 22 // The region with the higher frame counter is chosen unless there is wraparound.
23 // This function only returns a 0 or 1. 23 // This function only returns a 0 or 1.
24 u16 frame_counter_0 = g_dsp_memory.region_0.frame_counter;
25 u16 frame_counter_1 = g_dsp_memory.region_1.frame_counter;
24 26
25 if (g_regions[0].frame_counter == 0xFFFFu && g_regions[1].frame_counter != 0xFFFEu) { 27 if (frame_counter_0 == 0xFFFFu && frame_counter_1 != 0xFFFEu) {
26 // Wraparound has occurred. 28 // Wraparound has occurred.
27 return 1; 29 return 1;
28 } 30 }
29 31
30 if (g_regions[1].frame_counter == 0xFFFFu && g_regions[0].frame_counter != 0xFFFEu) { 32 if (frame_counter_1 == 0xFFFFu && frame_counter_0 != 0xFFFEu) {
31 // Wraparound has occurred. 33 // Wraparound has occurred.
32 return 0; 34 return 0;
33 } 35 }
34 36
35 return (g_regions[0].frame_counter > g_regions[1].frame_counter) ? 0 : 1; 37 return (frame_counter_0 > frame_counter_1) ? 0 : 1;
36} 38}
37 39
38static SharedMemory& ReadRegion() { 40static SharedMemory& ReadRegion() {
39 return g_regions[CurrentRegionIndex()]; 41 return CurrentRegionIndex() == 0 ? g_dsp_memory.region_0 : g_dsp_memory.region_1;
40} 42}
41 43
42static SharedMemory& WriteRegion() { 44static SharedMemory& WriteRegion() {
43 return g_regions[1 - CurrentRegionIndex()]; 45 return CurrentRegionIndex() != 0 ? g_dsp_memory.region_0 : g_dsp_memory.region_1;
44} 46}
45 47
46// Audio processing and mixing 48// Audio processing and mixing
diff --git a/src/audio_core/hle/dsp.h b/src/audio_core/hle/dsp.h
index 0a0f60ac1..94ce48863 100644
--- a/src/audio_core/hle/dsp.h
+++ b/src/audio_core/hle/dsp.h
@@ -31,8 +31,8 @@ namespace HLE {
31// double-buffer. The frame counter is located as the very last u16 of each region and is 31// double-buffer. The frame counter is located as the very last u16 of each region and is
32// incremented each audio tick. 32// incremented each audio tick.
33 33
34constexpr VAddr region0_base = 0x1FF50000; 34constexpr u32 region0_offset = 0x50000;
35constexpr VAddr region1_base = 0x1FF70000; 35constexpr u32 region1_offset = 0x70000;
36 36
37/** 37/**
38 * The DSP is native 16-bit. The DSP also appears to be big-endian. When reading 32-bit numbers from 38 * The DSP is native 16-bit. The DSP also appears to be big-endian. When reading 32-bit numbers from
@@ -512,7 +512,22 @@ struct SharedMemory {
512}; 512};
513ASSERT_DSP_STRUCT(SharedMemory, 0x8000); 513ASSERT_DSP_STRUCT(SharedMemory, 0x8000);
514 514
515extern std::array<SharedMemory, 2> g_regions; 515union DspMemory {
516 std::array<u8, 0x80000> raw_memory;
517 struct {
518 u8 unused_0[0x50000];
519 SharedMemory region_0;
520 u8 unused_1[0x18000];
521 SharedMemory region_1;
522 u8 unused_2[0x8000];
523 };
524};
525static_assert(offsetof(DspMemory, region_0) == region0_offset,
526 "DSP region 0 is at the wrong offset");
527static_assert(offsetof(DspMemory, region_1) == region1_offset,
528 "DSP region 1 is at the wrong offset");
529
530extern DspMemory g_dsp_memory;
516 531
517// Structures must have an offset that is a multiple of two. 532// Structures must have an offset that is a multiple of two.
518static_assert(offsetof(SharedMemory, frame_counter) % 2 == 0, 533static_assert(offsetof(SharedMemory, frame_counter) % 2 == 0,
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 140ff6451..881f1e93c 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -13,11 +13,11 @@
13#include "core/core_timing.h" 13#include "core/core_timing.h"
14#include "core/gdbstub/gdbstub.h" 14#include "core/gdbstub/gdbstub.h"
15#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/memory.h"
17#include "core/hle/kernel/thread.h" 16#include "core/hle/kernel/thread.h"
18#include "core/hle/service/service.h" 17#include "core/hle/service/service.h"
19#include "core/hw/hw.h" 18#include "core/hw/hw.h"
20#include "core/loader/loader.h" 19#include "core/loader/loader.h"
20#include "core/memory_setup.h"
21#include "core/settings.h" 21#include "core/settings.h"
22#include "video_core/video_core.h" 22#include "video_core/video_core.h"
23 23
@@ -123,7 +123,8 @@ void System::Reschedule() {
123} 123}
124 124
125System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { 125System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
126 Memory::Init(); 126 Memory::InitMemoryMap();
127 LOG_DEBUG(HW_Memory, "initialized OK");
127 128
128 if (Settings::values.use_cpu_jit) { 129 if (Settings::values.use_cpu_jit) {
129 cpu_core = std::make_unique<ARM_Dynarmic>(USER32MODE); 130 cpu_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 33c165197..8250a90b5 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -2,11 +2,13 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cinttypes>
5#include <map> 6#include <map>
6#include <memory> 7#include <memory>
7#include <utility> 8#include <utility>
8#include <vector> 9#include <vector>
9#include "audio_core/audio_core.h" 10#include "audio_core/audio_core.h"
11#include "common/assert.h"
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "common/logging/log.h" 13#include "common/logging/log.h"
12#include "core/hle/config_mem.h" 14#include "core/hle/config_mem.h"
@@ -92,52 +94,96 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
92 UNREACHABLE(); 94 UNREACHABLE();
93 } 95 }
94} 96}
95}
96
97namespace Memory {
98 97
99namespace { 98std::array<u8, Memory::VRAM_SIZE> vram;
99std::array<u8, Memory::N3DS_EXTRA_RAM_SIZE> n3ds_extra_ram;
100
101void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {
102 using namespace Memory;
103
104 struct MemoryArea {
105 VAddr vaddr_base;
106 PAddr paddr_base;
107 u32 size;
108 };
109
110 // The order of entries in this array is important. The VRAM and IO VAddr ranges overlap, and
111 // VRAM must be tried first.
112 static constexpr MemoryArea memory_areas[] = {
113 {VRAM_VADDR, VRAM_PADDR, VRAM_SIZE},
114 {IO_AREA_VADDR, IO_AREA_PADDR, IO_AREA_SIZE},
115 {DSP_RAM_VADDR, DSP_RAM_PADDR, DSP_RAM_SIZE},
116 {N3DS_EXTRA_RAM_VADDR, N3DS_EXTRA_RAM_PADDR, N3DS_EXTRA_RAM_SIZE - 0x20000},
117 };
118
119 VAddr mapping_limit = mapping.address + mapping.size;
120 if (mapping_limit < mapping.address) {
121 LOG_CRITICAL(Loader, "Mapping size overflowed: address=0x%08" PRIX32 " size=0x%" PRIX32,
122 mapping.address, mapping.size);
123 return;
124 }
100 125
101struct MemoryArea { 126 auto area =
102 u32 base; 127 std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) {
103 u32 size; 128 return mapping.address >= area.vaddr_base &&
104 const char* name; 129 mapping_limit <= area.vaddr_base + area.size;
105}; 130 });
131 if (area == std::end(memory_areas)) {
132 LOG_ERROR(Loader, "Unhandled special mapping: address=0x%08" PRIX32 " size=0x%" PRIX32
133 " read_only=%d unk_flag=%d",
134 mapping.address, mapping.size, mapping.read_only, mapping.unk_flag);
135 return;
136 }
106 137
107// We don't declare the IO regions in here since its handled by other means. 138 u32 offset_into_region = mapping.address - area->vaddr_base;
108static MemoryArea memory_areas[] = { 139 if (area->paddr_base == IO_AREA_PADDR) {
109 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) 140 LOG_ERROR(Loader, "MMIO mappings are not supported yet. phys_addr=0x%08" PRIX32,
110}; 141 area->paddr_base + offset_into_region);
111} 142 return;
143 }
112 144
113void Init() { 145 // TODO(yuriks): Use GetPhysicalPointer when that becomes independent of the virtual
114 InitMemoryMap(); 146 // mappings.
115 LOG_DEBUG(HW_Memory, "initialized OK"); 147 u8* target_pointer = nullptr;
116} 148 switch (area->paddr_base) {
149 case VRAM_PADDR:
150 target_pointer = vram.data();
151 break;
152 case DSP_RAM_PADDR:
153 target_pointer = AudioCore::GetDspMemory().data();
154 break;
155 case N3DS_EXTRA_RAM_PADDR:
156 target_pointer = n3ds_extra_ram.data();
157 break;
158 default:
159 UNREACHABLE();
160 }
117 161
118void InitLegacyAddressSpace(Kernel::VMManager& address_space) { 162 // TODO(yuriks): This flag seems to have some other effect, but it's unknown what
119 using namespace Kernel; 163 MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO;
120 164
121 for (MemoryArea& area : memory_areas) { 165 auto vma = address_space
122 auto block = std::make_shared<std::vector<u8>>(area.size); 166 .MapBackingMemory(mapping.address, target_pointer + offset_into_region,
123 address_space 167 mapping.size, memory_state)
124 .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private) 168 .MoveFrom();
125 .Unwrap(); 169 address_space.Reprotect(vma,
126 } 170 mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite);
171}
127 172
173void MapSharedPages(VMManager& address_space) {
128 auto cfg_mem_vma = address_space 174 auto cfg_mem_vma = address_space
129 .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem, 175 .MapBackingMemory(Memory::CONFIG_MEMORY_VADDR,
130 CONFIG_MEMORY_SIZE, MemoryState::Shared) 176 reinterpret_cast<u8*>(&ConfigMem::config_mem),
177 Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared)
131 .MoveFrom(); 178 .MoveFrom();
132 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 179 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
133 180
134 auto shared_page_vma = address_space 181 auto shared_page_vma = address_space
135 .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page, 182 .MapBackingMemory(Memory::SHARED_PAGE_VADDR,
136 SHARED_PAGE_SIZE, MemoryState::Shared) 183 reinterpret_cast<u8*>(&SharedPage::shared_page),
184 Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
137 .MoveFrom(); 185 .MoveFrom();
138 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 186 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
139
140 AudioCore::AddAddressSpace(address_space);
141} 187}
142 188
143} // namespace 189} // namespace Kernel
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
index 4e1856a41..08c1a9989 100644
--- a/src/core/hle/kernel/memory.h
+++ b/src/core/hle/kernel/memory.h
@@ -23,11 +23,7 @@ struct MemoryRegionInfo {
23void MemoryInit(u32 mem_type); 23void MemoryInit(u32 mem_type);
24void MemoryShutdown(); 24void MemoryShutdown();
25MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); 25MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
26}
27 26
28namespace Memory { 27void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
29 28void MapSharedPages(VMManager& address_space);
30void Init(); 29} // namespace Kernel
31void InitLegacyAddressSpace(Kernel::VMManager& address_space);
32
33} // namespace
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index ba80fe7f8..32cb25fb7 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -35,7 +35,6 @@ SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) {
35 process->codeset = std::move(code_set); 35 process->codeset = std::move(code_set);
36 process->flags.raw = 0; 36 process->flags.raw = 0;
37 process->flags.memory_region.Assign(MemoryRegion::APPLICATION); 37 process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
38 Memory::InitLegacyAddressSpace(process->vm_manager);
39 38
40 return process; 39 return process;
41} 40}
@@ -78,8 +77,15 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
78 77
79 AddressMapping mapping; 78 AddressMapping mapping;
80 mapping.address = descriptor << 12; 79 mapping.address = descriptor << 12;
81 mapping.size = (end_desc << 12) - mapping.address; 80 VAddr end_address = end_desc << 12;
82 mapping.writable = (descriptor & (1 << 20)) != 0; 81
82 if (mapping.address < end_address) {
83 mapping.size = end_address - mapping.address;
84 } else {
85 mapping.size = 0;
86 }
87
88 mapping.read_only = (descriptor & (1 << 20)) != 0;
83 mapping.unk_flag = (end_desc & (1 << 20)) != 0; 89 mapping.unk_flag = (end_desc & (1 << 20)) != 0;
84 90
85 address_mappings.push_back(mapping); 91 address_mappings.push_back(mapping);
@@ -88,8 +94,10 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
88 AddressMapping mapping; 94 AddressMapping mapping;
89 mapping.address = descriptor << 12; 95 mapping.address = descriptor << 12;
90 mapping.size = Memory::PAGE_SIZE; 96 mapping.size = Memory::PAGE_SIZE;
91 mapping.writable = true; // TODO: Not sure if correct 97 mapping.read_only = false;
92 mapping.unk_flag = false; 98 mapping.unk_flag = false;
99
100 address_mappings.push_back(mapping);
93 } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF 101 } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
94 // Kernel version 102 // Kernel version
95 kernel_version = descriptor & 0xFFFF; 103 kernel_version = descriptor & 0xFFFF;
@@ -131,6 +139,12 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
131 misc_memory_used += stack_size; 139 misc_memory_used += stack_size;
132 memory_region->used += stack_size; 140 memory_region->used += stack_size;
133 141
142 // Map special address mappings
143 MapSharedPages(vm_manager);
144 for (const auto& mapping : address_mappings) {
145 HandleSpecialMapping(vm_manager, mapping);
146 }
147
134 vm_manager.LogLayout(Log::Level::Debug); 148 vm_manager.LogLayout(Log::Level::Debug);
135 Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); 149 Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority);
136} 150}
@@ -138,6 +152,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
138VAddr Process::GetLinearHeapAreaAddress() const { 152VAddr Process::GetLinearHeapAreaAddress() const {
139 return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR; 153 return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR;
140} 154}
155
141VAddr Process::GetLinearHeapBase() const { 156VAddr Process::GetLinearHeapBase() const {
142 return GetLinearHeapAreaAddress() + memory_region->base; 157 return GetLinearHeapAreaAddress() + memory_region->base;
143} 158}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index b566950b0..b52211d2a 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -20,7 +20,7 @@ struct AddressMapping {
20 // Address and size must be page-aligned 20 // Address and size must be page-aligned
21 VAddr address; 21 VAddr address;
22 u32 size; 22 u32 size;
23 bool writable; 23 bool read_only;
24 bool unk_flag; 24 bool unk_flag;
25}; 25};
26 26
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 65e4bba85..b8438e490 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -672,12 +672,14 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) {
672 return addr - VRAM_VADDR + VRAM_PADDR; 672 return addr - VRAM_VADDR + VRAM_PADDR;
673 } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { 673 } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
674 return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; 674 return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR;
675 } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) {
676 return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR;
675 } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { 677 } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) {
676 return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; 678 return addr - DSP_RAM_VADDR + DSP_RAM_PADDR;
677 } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { 679 } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) {
678 return addr - IO_AREA_VADDR + IO_AREA_PADDR; 680 return addr - IO_AREA_VADDR + IO_AREA_PADDR;
679 } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { 681 } else if (addr >= N3DS_EXTRA_RAM_VADDR && addr < N3DS_EXTRA_RAM_VADDR_END) {
680 return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR; 682 return addr - N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_PADDR;
681 } 683 }
682 684
683 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); 685 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr);
@@ -696,6 +698,8 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) {
696 return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; 698 return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
697 } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { 699 } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
698 return addr - IO_AREA_PADDR + IO_AREA_VADDR; 700 return addr - IO_AREA_PADDR + IO_AREA_VADDR;
701 } else if (addr >= N3DS_EXTRA_RAM_PADDR && addr < N3DS_EXTRA_RAM_PADDR_END) {
702 return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR;
699 } 703 }
700 704
701 LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr); 705 LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr);
diff --git a/src/core/memory.h b/src/core/memory.h
index 903b58a22..802aa465e 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -37,6 +37,12 @@ enum : PAddr {
37 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) 37 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
38 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, 38 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
39 39
40 /// New 3DS additional memory. Supposedly faster than regular FCRAM. Part of it can be used by
41 /// applications and system modules if mapped via the ExHeader.
42 N3DS_EXTRA_RAM_PADDR = 0x1F000000,
43 N3DS_EXTRA_RAM_SIZE = 0x00400000, ///< New 3DS additional memory size (4MB)
44 N3DS_EXTRA_RAM_PADDR_END = N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_SIZE,
45
40 /// DSP memory 46 /// DSP memory
41 DSP_RAM_PADDR = 0x1FF00000, 47 DSP_RAM_PADDR = 0x1FF00000,
42 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) 48 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
@@ -81,6 +87,10 @@ enum : VAddr {
81 LINEAR_HEAP_SIZE = 0x08000000, 87 LINEAR_HEAP_SIZE = 0x08000000,
82 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, 88 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
83 89
90 /// Maps 1:1 to New 3DS additional memory
91 N3DS_EXTRA_RAM_VADDR = 0x1E800000,
92 N3DS_EXTRA_RAM_VADDR_END = N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_SIZE,
93
84 /// Maps 1:1 to the IO register area. 94 /// Maps 1:1 to the IO register area.
85 IO_AREA_VADDR = 0x1EC00000, 95 IO_AREA_VADDR = 0x1EC00000,
86 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, 96 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,