diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index a94643111..a3b8b0d9c 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -188,10 +188,10 @@ ResultVal Process::HeapAllocate(VAddr target, u32 size, VMAPermission per u32 interval_size = interval.upper() - interval.lower(); LOG_DEBUG(Kernel, "Allocated FCRAM region lower={:08X}, upper={:08X}", interval.lower(), interval.upper()); - std::fill(kernel.memory.fcram.begin() + interval.lower(), - kernel.memory.fcram.begin() + interval.upper(), 0); + std::fill(kernel.memory.GetFCRAMPointer(interval.lower()), + kernel.memory.GetFCRAMPointer(interval.upper()), 0); auto vma = vm_manager.MapBackingMemory(interval_target, - kernel.memory.fcram.data() + interval.lower(), + kernel.memory.GetFCRAMPointer(interval.lower()), interval_size, memory_state); ASSERT(vma.Succeeded()); vm_manager.Reprotect(vma.Unwrap(), perms); @@ -263,7 +263,7 @@ ResultVal Process::LinearAllocate(VAddr target, u32 size, VMAPermission p } } - u8* backing_memory = kernel.memory.fcram.data() + physical_offset; + u8* backing_memory = kernel.memory.GetFCRAMPointer(physical_offset); std::fill(backing_memory, backing_memory + size, 0); auto vma = vm_manager.MapBackingMemory(target, backing_memory, size, MemoryState::Continuous); diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 99fe2a436..91f82c45e 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -43,8 +43,8 @@ ResultVal> KernelSystem::CreateSharedMemory( ASSERT_MSG(offset, "Not enough space in region to allocate shared memory!"); - std::fill(memory.fcram.data() + *offset, memory.fcram.data() + *offset + size, 0); - shared_memory->backing_blocks = {{memory.fcram.data() + *offset, size}}; + std::fill(memory.GetFCRAMPointer(*offset), memory.GetFCRAMPointer(*offset + size), 0); + shared_memory->backing_blocks = {{memory.GetFCRAMPointer(*offset), size}}; shared_memory->holding_memory += MemoryRegionInfo::Interval(*offset, *offset + size); shared_memory->linear_heap_phys_offset = *offset; @@ -86,8 +86,8 @@ SharedPtr KernelSystem::CreateSharedMemoryForApplet( shared_memory->other_permissions = other_permissions; for (const auto& interval : backing_blocks) { shared_memory->backing_blocks.push_back( - {memory.fcram.data() + interval.lower(), interval.upper() - interval.lower()}); - std::fill(memory.fcram.data() + interval.lower(), memory.fcram.data() + interval.upper(), + {memory.GetFCRAMPointer(interval.lower()), interval.upper() - interval.lower()}); + std::fill(memory.GetFCRAMPointer(interval.lower()), memory.GetFCRAMPointer(interval.upper()), 0); } shared_memory->base_address = Memory::HEAP_VADDR + offset; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 203fa86f4..4f4c9b174 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -355,7 +355,7 @@ ResultVal> KernelSystem::CreateThread(std::string name, VAddr // Map the page to the current process' address space. vm_manager.MapBackingMemory(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, - memory.fcram.data() + *offset, Memory::PAGE_SIZE, + memory.GetFCRAMPointer(*offset), Memory::PAGE_SIZE, MemoryState::Locked); } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 5b4e990ca..d94bd0381 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -21,15 +21,34 @@ namespace Memory { +class MemorySystem::Impl { +public: + Impl() { + std::fill(fcram.get(), fcram.get() + Memory::FCRAM_N3DS_SIZE, 0); + std::fill(vram.get(), vram.get() + Memory::VRAM_SIZE, 0); + std::fill(n3ds_extra_ram.get(), n3ds_extra_ram.get() + Memory::N3DS_EXTRA_RAM_SIZE, 0); + } + + // Visual Studio would try to allocate these on compile time if they are std::array, which would exceed the memory limit. + std::unique_ptr fcram = std::make_unique(Memory::FCRAM_N3DS_SIZE); + std::unique_ptr vram = std::make_unique(Memory::VRAM_SIZE); + std::unique_ptr n3ds_extra_ram = std::make_unique(Memory::N3DS_EXTRA_RAM_SIZE); + + PageTable* current_page_table = nullptr; +}; + +MemorySystem::MemorySystem() : impl(std::make_unique()) {} +MemorySystem::~MemorySystem() = default; + void MemorySystem::SetCurrentPageTable(PageTable* page_table) { - current_page_table = page_table; + impl->current_page_table = page_table; if (Core::System::GetInstance().IsPoweredOn()) { Core::CPU().PageTableChanged(); } } PageTable* MemorySystem::GetCurrentPageTable() const { - return current_page_table; + return impl->current_page_table; } static void MapPages(PageTable& page_table, u32 base, u32 size, u8* memory, PageType type) { @@ -74,13 +93,13 @@ void UnmapRegion(PageTable& page_table, VAddr base, u32 size) { u8* MemorySystem::GetPointerForRasterizerCache(VAddr addr) { if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { - return fcram.data() + (addr - LINEAR_HEAP_VADDR); + return impl->fcram.get() + (addr - LINEAR_HEAP_VADDR); } if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { - return fcram.data() + (addr - NEW_LINEAR_HEAP_VADDR); + return impl->fcram.get() + (addr - NEW_LINEAR_HEAP_VADDR); } if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { - return vram.data() + (addr - VRAM_VADDR); + return impl->vram.get() + (addr - VRAM_VADDR); } UNREACHABLE(); } @@ -103,7 +122,7 @@ T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); template T MemorySystem::Read(const VAddr vaddr) { - const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + const u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { // NOTE: Avoid adding any extra logic to this fast-path block T value; @@ -114,7 +133,7 @@ T MemorySystem::Read(const VAddr vaddr) { // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state std::lock_guard lock(HLE::g_hle_lock); - PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); @@ -130,7 +149,7 @@ T MemorySystem::Read(const VAddr vaddr) { return value; } case PageType::Special: - return ReadMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr); + return ReadMMIO(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr); default: UNREACHABLE(); } @@ -141,7 +160,7 @@ void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); template void MemorySystem::Write(const VAddr vaddr, const T data) { - u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { // NOTE: Avoid adding any extra logic to this fast-path block std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); @@ -151,7 +170,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) { // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state std::lock_guard lock(HLE::g_hle_lock); - PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X}", sizeof(data) * 8, (u32)data, @@ -166,7 +185,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) { break; } case PageType::Special: - WriteMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr, data); + WriteMMIO(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data); break; default: UNREACHABLE(); @@ -199,12 +218,12 @@ bool MemorySystem::IsValidPhysicalAddress(const PAddr paddr) { } u8* MemorySystem::GetPointer(const VAddr vaddr) { - u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { return page_pointer + (vaddr & PAGE_MASK); } - if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { + if (impl->current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { return GetPointerForRasterizerCache(vaddr); } @@ -256,16 +275,16 @@ u8* MemorySystem::GetPhysicalPointer(PAddr address) { u8* target_pointer = nullptr; switch (area->paddr_base) { case VRAM_PADDR: - target_pointer = vram.data() + offset_into_region; + target_pointer = impl->vram.get() + offset_into_region; break; case DSP_RAM_PADDR: target_pointer = Core::DSP().GetDspMemory().data() + offset_into_region; break; case FCRAM_PADDR: - target_pointer = fcram.data() + offset_into_region; + target_pointer = impl->fcram.get() + offset_into_region; break; case N3DS_EXTRA_RAM_PADDR: - target_pointer = n3ds_extra_ram.data() + offset_into_region; + target_pointer = impl->n3ds_extra_ram.get() + offset_into_region; break; default: UNREACHABLE(); @@ -303,7 +322,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) { - PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; + PageType& page_type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; if (cached) { // Switch page type to cached if now cached @@ -314,7 +333,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached break; case PageType::Memory: page_type = PageType::RasterizerCachedMemory; - current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; + impl->current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; break; default: UNREACHABLE(); @@ -328,7 +347,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached break; case PageType::RasterizerCachedMemory: { page_type = PageType::Memory; - current_page_table->pointers[vaddr >> PAGE_BITS] = + impl->current_page_table->pointers[vaddr >> PAGE_BITS] = GetPointerForRasterizerCache(vaddr & ~PAGE_MASK); break; } @@ -730,8 +749,13 @@ void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) } u32 MemorySystem::GetFCRAMOffset(u8* pointer) { - ASSERT(pointer >= fcram.data() && pointer < fcram.data() + fcram.size()); - return pointer - fcram.data(); + ASSERT(pointer >= impl->fcram.get() && pointer <= impl->fcram.get() + Memory::FCRAM_N3DS_SIZE); + return pointer - impl->fcram.get(); +} + +u8* MemorySystem::GetFCRAMPointer(u32 offset) { + ASSERT(offset <= Memory::FCRAM_N3DS_SIZE); + return impl->fcram.get() + offset; } } // namespace Memory diff --git a/src/core/memory.h b/src/core/memory.h index 352a48482..b6f0fb619 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include "common/common_types.h" @@ -210,6 +211,9 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); class MemorySystem { public: + MemorySystem(); + ~MemorySystem(); + /// Currently active page table void SetCurrentPageTable(PageTable* page_table); PageTable* GetCurrentPageTable() const; @@ -248,13 +252,14 @@ public: /// Gets offset in FCRAM from a pointer inside FCRAM range u32 GetFCRAMOffset(u8* pointer); + /// Gets pointer in FCRAM with given offset + u8* GetFCRAMPointer(u32 offset); + /** * Mark each page touching the region as cached. */ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); - std::array fcram{}; - private: template T Read(const VAddr vaddr); @@ -270,10 +275,9 @@ private: */ u8* GetPointerForRasterizerCache(VAddr addr); - std::array vram{}; - std::array n3ds_extra_ram{}; + class Impl; - PageTable* current_page_table = nullptr; + std::unique_ptr impl; }; /// Determines if the given VAddr is valid for the specified process. diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 782557090..f8aba0fbe 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -12,7 +12,7 @@ class EmuWindow; class RendererBase; -namespace Memory{ +namespace Memory { class MemorySystem; }