mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-23 22:40:05 +00:00
Memory/RasterizerCache: Ignore unmapped memory regions when caching physical regions.
Not all physical regions need to be mapped into the address space of every process, for example, system modules do not have a VRAM mapping. This fixes a crash when loading applets and system modules.
This commit is contained in:
parent
a7758b0b36
commit
41f6c9f87f
@ -316,8 +316,15 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
|
|||||||
|
|
||||||
for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
|
for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
|
||||||
boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr);
|
boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr);
|
||||||
if (!maybe_vaddr)
|
// While the physical <-> virtual mapping is 1:1 for the regions supported by the cache,
|
||||||
|
// some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond
|
||||||
|
// the end address of VRAM, causing the Virtual->Physical translation to fail when flushing
|
||||||
|
// parts of the texture.
|
||||||
|
if (!maybe_vaddr) {
|
||||||
|
LOG_ERROR(HW_Memory,
|
||||||
|
"Trying to flush a cached region to an invalid physical address %08X", paddr);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
VAddr vaddr = *maybe_vaddr;
|
VAddr vaddr = *maybe_vaddr;
|
||||||
|
|
||||||
u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS];
|
u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS];
|
||||||
@ -329,6 +336,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
|
|||||||
if (res_count == 0) {
|
if (res_count == 0) {
|
||||||
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||||
switch (page_type) {
|
switch (page_type) {
|
||||||
|
case PageType::Unmapped:
|
||||||
|
// It is not necessary for a process to have this region mapped into its address
|
||||||
|
// space, for example, a system module need not have a VRAM mapping.
|
||||||
|
break;
|
||||||
case PageType::Memory:
|
case PageType::Memory:
|
||||||
page_type = PageType::RasterizerCachedMemory;
|
page_type = PageType::RasterizerCachedMemory;
|
||||||
current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
|
current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
|
||||||
@ -347,6 +358,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
|
|||||||
if (res_count == 0) {
|
if (res_count == 0) {
|
||||||
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||||
switch (page_type) {
|
switch (page_type) {
|
||||||
|
case PageType::Unmapped:
|
||||||
|
// It is not necessary for a process to have this region mapped into its address
|
||||||
|
// space, for example, a system module need not have a VRAM mapping.
|
||||||
|
break;
|
||||||
case PageType::RasterizerCachedMemory: {
|
case PageType::RasterizerCachedMemory: {
|
||||||
u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
|
u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
|
||||||
if (pointer == nullptr) {
|
if (pointer == nullptr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user