diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/memory.cpp | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index a6b5f6c99..9b394f84b 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -325,8 +325,15 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { | |||
| 325 | 325 | ||
| 326 | for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { | 326 | for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { |
| 327 | boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr); | 327 | boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr); |
| 328 | if (!maybe_vaddr) | 328 | // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache, |
| 329 | // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond | ||
| 330 | // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing | ||
| 331 | // parts of the texture. | ||
| 332 | if (!maybe_vaddr) { | ||
| 333 | LOG_ERROR(HW_Memory, | ||
| 334 | "Trying to flush a cached region to an invalid physical address %08X", paddr); | ||
| 329 | continue; | 335 | continue; |
| 336 | } | ||
| 330 | VAddr vaddr = *maybe_vaddr; | 337 | VAddr vaddr = *maybe_vaddr; |
| 331 | 338 | ||
| 332 | u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; | 339 | u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; |
| @@ -338,6 +345,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { | |||
| 338 | if (res_count == 0) { | 345 | if (res_count == 0) { |
| 339 | PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 346 | PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; |
| 340 | switch (page_type) { | 347 | switch (page_type) { |
| 348 | case PageType::Unmapped: | ||
| 349 | // It is not necessary for a process to have this region mapped into its address | ||
| 350 | // space, for example, a system module need not have a VRAM mapping. | ||
| 351 | break; | ||
| 341 | case PageType::Memory: | 352 | case PageType::Memory: |
| 342 | page_type = PageType::RasterizerCachedMemory; | 353 | page_type = PageType::RasterizerCachedMemory; |
| 343 | current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; | 354 | current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; |
| @@ -356,6 +367,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { | |||
| 356 | if (res_count == 0) { | 367 | if (res_count == 0) { |
| 357 | PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 368 | PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; |
| 358 | switch (page_type) { | 369 | switch (page_type) { |
| 370 | case PageType::Unmapped: | ||
| 371 | // It is not necessary for a process to have this region mapped into its address | ||
| 372 | // space, for example, a system module need not have a VRAM mapping. | ||
| 373 | break; | ||
| 359 | case PageType::RasterizerCachedMemory: { | 374 | case PageType::RasterizerCachedMemory: { |
| 360 | u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); | 375 | u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); |
| 361 | if (pointer == nullptr) { | 376 | if (pointer == nullptr) { |