mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Add a compat flag to map some extra memory at address 0.
Can be used to work around certain types of crashes without having to disable fast memory.
This commit is contained in:
@@ -154,6 +154,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
CheckSetting(iniFile, gameID, "SaveStatesNotRecommended", &flags_.SaveStatesNotRecommended);
|
||||
CheckSetting(iniFile, gameID, "IgnoreEnqueue", &flags_.IgnoreEnqueue);
|
||||
CheckSetting(iniFile, gameID, "MsgDialogAutoStatus", &flags_.MsgDialogAutoStatus);
|
||||
CheckSetting(iniFile, gameID, "NullPageValid", &flags_.NullPageValid);
|
||||
}
|
||||
|
||||
void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
|
||||
@@ -117,6 +117,7 @@ struct CompatFlags {
|
||||
bool SaveStatesNotRecommended;
|
||||
bool IgnoreEnqueue;
|
||||
bool MsgDialogAutoStatus;
|
||||
bool NullPageValid;
|
||||
};
|
||||
|
||||
struct VRCompat {
|
||||
|
||||
+20
-13
@@ -50,6 +50,7 @@ u8* base = nullptr;
|
||||
MemArena g_arena;
|
||||
// ==============
|
||||
|
||||
u8 *m_pNullPage;
|
||||
u8 *m_pPhysicalScratchPad;
|
||||
u8 *m_pUncachedScratchPad;
|
||||
// 64-bit: Pointers to high-mem mirrors
|
||||
@@ -67,8 +68,8 @@ u8 *m_pUncachedKernelRAM[3];
|
||||
// since when we write to the depth buffer (like with the depth rasterizer or the software renderer)
|
||||
// we write unswizzled data anyway. There are some exceptions, Silent Hill abuses the swizzling in ways that break
|
||||
// our software renderer.
|
||||
u8 *m_pPhysicalVRAM[4];
|
||||
u8 *m_pUncachedVRAM[4];
|
||||
static u8 *m_pPhysicalVRAM[4];
|
||||
static u8 *m_pUncachedVRAM[4];
|
||||
|
||||
// Holds the ending address of the PSP's user space.
|
||||
// Required for HD Remasters to work properly.
|
||||
@@ -77,11 +78,13 @@ u32 g_MemorySize;
|
||||
// Used to store the PSP model on game startup.
|
||||
u32 g_PSPModel;
|
||||
|
||||
static MemMapSetupFlags g_setupFlags;
|
||||
|
||||
std::recursive_mutex g_shutdownLock;
|
||||
|
||||
// We don't declare the IO region in here since its handled by other means.
|
||||
static MemoryView views[] =
|
||||
{
|
||||
static MemoryView views[] = {
|
||||
{&m_pNullPage, 0x00000000, 0x00010000, MV_NULL_PAGE}, // Null page, usually not enabled. Only used for working around some race condition bugs.
|
||||
{&m_pPhysicalScratchPad, 0x00010000, SCRATCHPAD_SIZE, 0},
|
||||
{&m_pUncachedScratchPad, 0x40010000, SCRATCHPAD_SIZE, MV_MIRROR_PREVIOUS},
|
||||
{&m_pPhysicalVRAM[0], 0x04000000, 0x00200000, 0},
|
||||
@@ -120,17 +123,19 @@ inline static bool CanIgnoreView(const MemoryView &view) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool SkipView(u32 flags, u32 viewFlags) {
|
||||
static bool SkipView(MemMapSetupFlags flags, u32 viewFlags) {
|
||||
#if PPSSPP_PLATFORM(IOS) && PPSSPP_ARCH(64BIT)
|
||||
// We use a limited memory map on iOS with masking, we don't need to allocate the kernel space views.
|
||||
if (viewFlags & MV_KERNEL) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if ((viewFlags & MV_NULL_PAGE) && !(flags & MemMapSetupFlags::AllocNullPage))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Memory_TryBase(u32 flags) {
|
||||
static bool Memory_TryBase(MemMapSetupFlags flags) {
|
||||
// OK, we know where to find free space. Now grab it!
|
||||
// We just mimic the popular BAT setup.
|
||||
|
||||
@@ -187,7 +192,6 @@ bail:
|
||||
continue;
|
||||
if (SkipView(flags, views[i].flags))
|
||||
continue;
|
||||
|
||||
if (views[j].out_ptr && *views[j].out_ptr) {
|
||||
if (!CanIgnoreView(views[j])) {
|
||||
g_arena.ReleaseView(0, *views[j].out_ptr, views[j].size);
|
||||
@@ -198,7 +202,8 @@ bail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemoryMap_Setup(u32 flags) {
|
||||
bool MemoryMap_Setup(MemMapSetupFlags flags) {
|
||||
g_setupFlags = flags;
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// We reserve the memory, then simply commit in TryBase.
|
||||
base = (u8*)VirtualAllocFromApp(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
@@ -268,9 +273,11 @@ bool MemoryMap_Setup(u32 flags) {
|
||||
return Memory_TryBase(flags);
|
||||
}
|
||||
|
||||
void MemoryMap_Shutdown(u32 flags) {
|
||||
void MemoryMap_Shutdown() {
|
||||
size_t position = 0;
|
||||
size_t last_position = 0;
|
||||
const MemMapSetupFlags flags = g_setupFlags;
|
||||
g_setupFlags = MemMapSetupFlags::Default;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(views); i++) {
|
||||
if (views[i].size == 0)
|
||||
@@ -296,7 +303,7 @@ void MemoryMap_Shutdown(u32 flags) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Init() {
|
||||
bool Init(MemMapSetupFlags flags) {
|
||||
// On some 32 bit platforms (like Android, iOS, etc.), you can only map < 32 megs at a time.
|
||||
const static int MAX_MMAP_SIZE = 31 * 1024 * 1024;
|
||||
_dbg_assert_msg_(g_MemorySize <= MAX_MMAP_SIZE * 3, "ACK - too much memory for three mmap views.");
|
||||
@@ -309,7 +316,6 @@ bool Init() {
|
||||
views[i].size = std::min(std::max((int)g_MemorySize - MAX_MMAP_SIZE * 2, 0), MAX_MMAP_SIZE);
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if (!MemoryMap_Setup(flags)) {
|
||||
return false;
|
||||
}
|
||||
@@ -324,8 +330,9 @@ bool Init() {
|
||||
void Reinit() {
|
||||
_assert_msg_(PSP_GetBootState() == BootState::Complete, "Cannot reinit during startup/shutdown");
|
||||
Core_NotifyLifecycle(CoreLifecycle::MEMORY_REINITING);
|
||||
MemMapSetupFlags flags = g_setupFlags;
|
||||
Shutdown();
|
||||
Init();
|
||||
Init(flags);
|
||||
Core_NotifyLifecycle(CoreLifecycle::MEMORY_REINITED);
|
||||
}
|
||||
|
||||
@@ -403,7 +410,7 @@ void DoState(PointerWrap &p) {
|
||||
void Shutdown() {
|
||||
std::lock_guard<std::recursive_mutex> guard(g_shutdownLock);
|
||||
u32 flags = 0;
|
||||
MemoryMap_Shutdown(flags);
|
||||
MemoryMap_Shutdown();
|
||||
base = nullptr;
|
||||
DEBUG_LOG(Log::MemMap, "Memory system shut down.");
|
||||
}
|
||||
|
||||
+12
-10
@@ -25,6 +25,7 @@
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "Core/Opcode.h"
|
||||
@@ -71,8 +72,7 @@ extern u32 g_PSPModel;
|
||||
#define MASKED_PSP_MEMORY
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
// This may be adjusted by remaster games.
|
||||
RAM_NORMAL_SIZE = 0x02000000,
|
||||
// Used if the PSP model is PSP-2000 (Slim).
|
||||
@@ -93,26 +93,28 @@ enum {
|
||||
MV_IS_PRIMARY_RAM = 0x100,
|
||||
MV_IS_EXTRA1_RAM = 0x200,
|
||||
MV_IS_EXTRA2_RAM = 0x400,
|
||||
MV_KERNEL = 0x800 // Can be skipped on platforms where memory is tight.
|
||||
MV_KERNEL = 0x800, // Can be skipped on platforms where memory is tight.
|
||||
MV_NULL_PAGE = 0x1000,
|
||||
};
|
||||
|
||||
struct MemoryView
|
||||
{
|
||||
struct MemoryView {
|
||||
u8 **out_ptr;
|
||||
u32 virtual_address;
|
||||
u32 size;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
// Uses a memory arena to set up an emulator-friendly memory map
|
||||
bool MemoryMap_Setup(u32 flags);
|
||||
void MemoryMap_Shutdown(u32 flags);
|
||||
enum class MemMapSetupFlags {
|
||||
Default = 0,
|
||||
AllocNullPage = 1,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(MemMapSetupFlags);
|
||||
|
||||
// Init and Shutdown
|
||||
bool Init();
|
||||
bool Init(MemMapSetupFlags flags);
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
void Clear();
|
||||
|
||||
// False when shutdown has already been called.
|
||||
bool IsActive();
|
||||
|
||||
|
||||
+6
-1
@@ -365,8 +365,13 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin
|
||||
HLEPlugins::Init();
|
||||
}
|
||||
|
||||
Memory::MemMapSetupFlags memMapFlags = Memory::MemMapSetupFlags::Default;
|
||||
if (g_CoreParameter.compat.flags().NullPageValid) {
|
||||
memMapFlags = Memory::MemMapSetupFlags::AllocNullPage;
|
||||
}
|
||||
|
||||
// Initialize the memory map as early as possible (now that we've read the PARAM.SFO).
|
||||
if (!Memory::Init()) {
|
||||
if (!Memory::Init(memMapFlags)) {
|
||||
// We're screwed.
|
||||
*errorString = "Memory init failed";
|
||||
return false;
|
||||
|
||||
@@ -2088,3 +2088,21 @@ ULUS10077 = true
|
||||
# Ghost Recon - Predator. See #20856
|
||||
ULUS10445 = true
|
||||
ULES01350 = True
|
||||
|
||||
[NullPageValid]
|
||||
# Works around crashes in some games (such as GoW: GoS, see issue #14958) that access invalid memory pages, by mapping some extra memory at address 0.
|
||||
# GOW : Ghost of Sparta
|
||||
UCUS98737 = true
|
||||
UCAS40323 = true
|
||||
NPHG00092 = true
|
||||
NPEG00044 = true
|
||||
NPEG00045 = true
|
||||
NPJG00120 = true
|
||||
NPUG80508 = true
|
||||
UCJS10114 = true
|
||||
UCES01401 = true
|
||||
UCES01473 = true
|
||||
# GOW : Ghost of Sparta Demo
|
||||
NPJG90095 = true
|
||||
NPEG90035 = true
|
||||
NPUG70125 = true
|
||||
|
||||
@@ -107,7 +107,7 @@ static void SetupJitHarness() {
|
||||
PSP_CoreParameter().cpuCore = CPUCore::INTERPRETER;
|
||||
PSP_CoreParameter().fastForward = true;
|
||||
|
||||
Memory::Init();
|
||||
Memory::Init(Memory::MemMapSetupFlags::Default);
|
||||
mipsr4k.Reset();
|
||||
CoreTiming::Init();
|
||||
InitVFPU();
|
||||
|
||||
Reference in New Issue
Block a user