From 5f7e97c27c966059ba80e93ba800ae5fc0398de3 Mon Sep 17 00:00:00 2001 From: Benjamin Moir Date: Mon, 29 Apr 2024 15:33:58 +1000 Subject: [PATCH] [SAVEVERSION+] EE: Expose advanced option for extra memory --- pcsx2-qt/Settings/AdvancedSettingsWidget.cpp | 4 ++ pcsx2-qt/Settings/AdvancedSettingsWidget.ui | 7 +++ pcsx2/Achievements.cpp | 35 +++++++----- pcsx2/Config.h | 6 ++ pcsx2/DebugTools/DebugInterface.cpp | 2 +- pcsx2/Dmac.cpp | 4 +- pcsx2/Memory.cpp | 37 ++++++++++++- pcsx2/Memory.h | 3 +- pcsx2/MemoryTypes.h | 3 + pcsx2/Pcsx2Config.cpp | 2 + pcsx2/R5900.cpp | 10 ++++ pcsx2/R5900OpcodeImpl.cpp | 13 +++++ pcsx2/R5900OpcodeTables.h | 4 +- pcsx2/SaveState.cpp | 21 ++++--- pcsx2/SaveState.h | 6 +- pcsx2/VMManager.cpp | 7 +++ pcsx2/vtlb.cpp | 12 ++-- pcsx2/x86/ix86-32/iR5900.cpp | 58 ++++++++++++-------- 18 files changed, 169 insertions(+), 65 deletions(-) diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp index 773ac2d04f..3279b70007 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.cpp @@ -24,6 +24,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeWaitLoopDetection, "EmuCore/Speedhacks", "WaitLoop", true); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeFastmem, "EmuCore/CPU/Recompiler", "EnableFastmem", true); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnTLBMiss, "EmuCore/CPU/Recompiler", "PauseOnTLBMiss", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.extraMemory, "EmuCore/CPU", "ExtraMemory", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu0Recompiler, "EmuCore/CPU/Recompiler", "EnableVU0", true); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true); @@ -86,6 +87,9 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget* "end of the block, not on the instruction which caused the exception. Refer to the console to see the address where the invalid " "access occurred.")); + dialog->registerWidgetHelp(m_ui.extraMemory, tr("Enable 128MB RAM (Dev Console)"), tr("Unchecked"), + tr("Exposes an additional 96MB of memory to the virtual machine.")); + dialog->registerWidgetHelp(m_ui.vu0RoundingMode, tr("VU0 Rounding Mode"), tr("Chop/Zero (Default)"), tr("Changes how PCSX2 handles rounding while emulating the Emotion Engine's Vector Unit 0 (EE VU0). " "The default value handles the vast majority of games; modifying this setting when a game is not having a visible problem will cause stability issues and/or crashes.")); diff --git a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui index d2d859f7bd..cb816515da 100644 --- a/pcsx2-qt/Settings/AdvancedSettingsWidget.ui +++ b/pcsx2-qt/Settings/AdvancedSettingsWidget.ui @@ -200,6 +200,13 @@ + + + + Enable 128MB RAM (Dev Console) + + + diff --git a/pcsx2/Achievements.cpp b/pcsx2/Achievements.cpp index 92f519ccc3..aa8413cba1 100644 --- a/pcsx2/Achievements.cpp +++ b/pcsx2/Achievements.cpp @@ -52,9 +52,6 @@ namespace Achievements { - // Size of the EE physical memory exposed to RetroAchievements. - static constexpr u32 EXPOSED_EE_MEMORY_SIZE = Ps2MemSize::MainRam + Ps2MemSize::Scratch; - static constexpr u32 LEADERBOARD_NEARBY_ENTRIES_TO_FETCH = 10; static constexpr u32 LEADERBOARD_ALL_FETCH_SIZE = 20; @@ -132,6 +129,9 @@ namespace Achievements static void UpdateGameSummary(); static void DownloadImage(std::string url, std::string cache_filename); + // Size of the EE physical memory exposed to RetroAchievements. + static u32 GetExposedEEMemorySize(); + static bool CreateClient(rc_client_t** client, std::unique_ptr* http); static void DestroyClient(rc_client_t** client, std::unique_ptr* http); static void ClientMessageCallback(const char* message, const rc_client_t* client); @@ -444,6 +444,11 @@ bool Achievements::Initialize() return true; } +u32 Achievements::GetExposedEEMemorySize() +{ + return Ps2MemSize::ExposedRam + Ps2MemSize::Scratch; +} + bool Achievements::CreateClient(rc_client_t** client, std::unique_ptr* http) { *http = HTTPDownloader::Create(Host::GetHTTPUserAgent()); @@ -599,7 +604,7 @@ void Achievements::ClientMessageCallback(const char* message, const rc_client_t* uint32_t Achievements::ClientReadMemory(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client) { - if ((static_cast(address) + num_bytes) > EXPOSED_EE_MEMORY_SIZE) [[unlikely]] + if ((static_cast(address) + num_bytes) > GetExposedEEMemorySize()) [[unlikely]] { DevCon.Warning("[Achievements] Ignoring out of bounds memory peek of %u bytes at %08X.", num_bytes, address); return 0u; @@ -608,7 +613,7 @@ uint32_t Achievements::ClientReadMemory(uint32_t address, uint8_t* buffer, uint3 // RA uses a fake memory map with the scratchpad directly above physical memory. // The scratchpad is not meant to be accessible via physical addressing, only virtual. // This also means that the upper 96MB of memory will never be accessible to achievements. - const u8* ptr = (address < Ps2MemSize::MainRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::MainRam]; + const u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam]; // Fast paths for known data sizes. switch (num_bytes) @@ -3020,7 +3025,7 @@ void Achievements::RAIntegration::InitializeRAIntegration(void* main_window_hand RA_SetConsoleID(PlayStation2); // EE physical memory and scratchpad are currently exposed (matching direct rcheevos implementation). - RA_InstallMemoryBank(0, RACallbackReadMemory, RACallbackWriteMemory, EXPOSED_EE_MEMORY_SIZE); + RA_InstallMemoryBank(0, RACallbackReadMemory, RACallbackWriteMemory, GetExposedEEMemorySize()); RA_InstallMemoryBankBlockReader(0, RACallbackReadBlock); // Fire off a login anyway. Saves going into the menu and doing it. @@ -3127,50 +3132,50 @@ void Achievements::RAIntegration::RACallbackLoadROM(const char* unused) unsigned char Achievements::RAIntegration::RACallbackReadMemory(unsigned int address) { - if ((static_cast(address) + sizeof(unsigned char)) > EXPOSED_EE_MEMORY_SIZE) + if ((static_cast(address) + sizeof(unsigned char)) > GetExposedEEMemorySize()) { DevCon.Warning("[Achievements] Ignoring out of bounds memory peek at %08X.", address); return 0u; } unsigned char value; - const u8* ptr = (address < Ps2MemSize::MainRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::MainRam]; + const u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam]; std::memcpy(&value, ptr, sizeof(value)); return value; } unsigned int Achievements::RAIntegration::RACallbackReadBlock(unsigned int address, unsigned char* buffer, unsigned int bytes) { - if ((address >= EXPOSED_EE_MEMORY_SIZE)) [[unlikely]] + if ((address >= GetExposedEEMemorySize())) [[unlikely]] { DevCon.Warning("[Achievements] Ignoring out of bounds block memory read for %u bytes at %08X.", bytes, address); return 0u; } - if (address < Ps2MemSize::MainRam && (address + bytes) > Ps2MemSize::MainRam) [[unlikely]] + if (address < Ps2MemSize::ExposedRam && (address + bytes) > Ps2MemSize::ExposedRam) [[unlikely]] { // Split across RAM+Scratch. - const unsigned int bytes_from_ram = Ps2MemSize::MainRam - address; + const unsigned int bytes_from_ram = Ps2MemSize::ExposedRam - address; const unsigned int bytes_from_scratch = bytes - bytes_from_ram; return (RACallbackReadBlock(address, buffer, bytes_from_ram) + RACallbackReadBlock(address + bytes_from_ram, buffer + bytes_from_ram, bytes_from_scratch)); } - const unsigned int read_byte_count = std::min(EXPOSED_EE_MEMORY_SIZE - address, bytes); - const u8* ptr = (address < Ps2MemSize::MainRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::MainRam]; + const unsigned int read_byte_count = std::min(GetExposedEEMemorySize() - address, bytes); + const u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam]; std::memcpy(buffer, ptr, read_byte_count); return read_byte_count; } void Achievements::RAIntegration::RACallbackWriteMemory(unsigned int address, unsigned char value) { - if ((static_cast(address) + sizeof(value)) > EXPOSED_EE_MEMORY_SIZE) [[unlikely]] + if ((static_cast(address) + sizeof(value)) > GetExposedEEMemorySize()) [[unlikely]] { DevCon.Warning("[Achievements] Ignoring out of bounds memory poke at %08X (value %08X).", address, value); return; } - u8* ptr = (address < Ps2MemSize::MainRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::MainRam]; + u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam]; std::memcpy(ptr, &value, sizeof(value)); } diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 9245f5921e..e4ab52b9a4 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -540,6 +540,11 @@ struct Pcsx2Config // ------------------------------------------------------------------------ struct CpuOptions { + BITFIELD32() + bool + ExtraMemory : 1; + BITFIELD_END + RecompilerOptions Recompiler; FPControlRegister FPUFPCR; @@ -1248,6 +1253,7 @@ namespace EmuFolders #define CHECK_CACHE (EmuConfig.Cpu.Recompiler.EnableEECache) #define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP) #define CHECK_FASTMEM (EmuConfig.Cpu.Recompiler.EnableEE && EmuConfig.Cpu.Recompiler.EnableFastmem) +#define CHECK_EXTRAMEM (memGetExtraMemMode()) //------------ SPECIAL GAME FIXES!!! --------------- #define CHECK_VUADDSUBHACK (EmuConfig.Gamefixes.VuAddSubHack) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index ea4e00f9fc..b9eb5982ca 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -670,7 +670,7 @@ bool R5900DebugInterface::isValidAddress(u32 addr) // [ 0000_8000 - 01FF_FFFF ] RAM // [ 2000_8000 - 21FF_FFFF ] RAM MIRROR // [ 3000_8000 - 31FF_FFFF ] RAM MIRROR - if (lopart >= 0x80000 && lopart <= 0x1ffFFff) + if (lopart >= 0x80000 && lopart < Ps2MemSize::ExposedRam) return !!vtlb_GetPhyPtr(lopart); break; case 1: diff --git a/pcsx2/Dmac.cpp b/pcsx2/Dmac.cpp index 3127d9ae2f..622c3d8c21 100644 --- a/pcsx2/Dmac.cpp +++ b/pcsx2/Dmac.cpp @@ -91,7 +91,7 @@ __fi tDMA_TAG* SPRdmaGetAddr(u32 addr, bool write) // FIXME: Why??? DMA uses physical addresses addr &= 0x1ffffff0; - if (addr < Ps2MemSize::MainRam) + if (addr < Ps2MemSize::ExposedRam) { return (tDMA_TAG*)&eeMem->Main[addr]; } @@ -154,7 +154,7 @@ __ri tDMA_TAG *dmaGetAddr(u32 addr, bool write) // FIXME: Why??? DMA uses physical addresses addr &= 0x1ffffff0; - if (addr < Ps2MemSize::MainRam) + if (addr < Ps2MemSize::ExposedRam) { return (tDMA_TAG*)&eeMem->Main[addr]; } diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index c30cf0eb5e..3644d4df87 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -36,11 +36,17 @@ BIOS #include "ps2/BiosTools.h" #include "common/AlignedMalloc.h" +#include "common/Error.h" #ifdef ENABLECACHE #include "Cache.h" #endif +namespace Ps2MemSize +{ + u32 ExposedRam = MainRam; +} // namespace Ps2MemSize + namespace SysMemory { static u8* TryAllocateVirtualMemory(const char* name, void* file_handle, uptr base, size_t size); @@ -66,6 +72,7 @@ static u16 s_dve_regs[0xff]; static bool s_ba_command_executing = false; static bool s_ba_error_detected = false; static u16 s_ba_current_reg = 0; +static bool s_extra_memory = false; namespace HostMemoryMap { @@ -282,6 +289,19 @@ void* SysMemory::GetDataFileHandle() return s_data_memory_file_handle; } +bool memGetExtraMemMode() +{ + return s_extra_memory; +} + +void memSetExtraMemMode(bool mode) +{ + s_extra_memory = mode; + + // update the amount of RAM exposed to the VM + Ps2MemSize::ExposedRam = mode ? Ps2MemSize::TotalRam : Ps2MemSize::MainRam; +} + void memSetKernelMode() { //Do something here MemMode = 0; @@ -442,9 +462,10 @@ void memMapVUmicro() void memMapPhy() { // Main memory - vtlb_MapBlock(eeMem->Main, 0x00000000,Ps2MemSize::MainRam);//mirrored on first 256 mb ? + vtlb_MapBlock(eeMem->Main, 0x00000000,Ps2MemSize::ExposedRam);//mirrored on first 256 mb ? + // High memory, uninstalled on the configuration we emulate - vtlb_MapHandler(null_handler, Ps2MemSize::MainRam, 0x10000000 - Ps2MemSize::MainRam); + vtlb_MapHandler(null_handler, Ps2MemSize::ExposedRam, 0x10000000 - Ps2MemSize::ExposedRam); // Various ROMs (all read-only) vtlb_MapBlock(eeMem->ROM, 0x1fc00000, Ps2MemSize::Rom); @@ -1145,7 +1166,7 @@ void memRelease() eeMem = nullptr; } -bool SaveStateBase::memFreeze() +bool SaveStateBase::memFreeze(Error* error) { Freeze(s_ba); Freeze(s_dve_regs); @@ -1153,5 +1174,15 @@ bool SaveStateBase::memFreeze() Freeze(s_ba_error_detected); Freeze(s_ba_current_reg); + bool extra_memory = s_extra_memory; + Freeze(extra_memory); + + if (extra_memory != s_extra_memory) + { + Error::SetStringFmt(error, "Memory size mismatch, save state requires {}, but VM currently has {}.", + extra_memory ? "128MB" : "32MB", s_extra_memory ? "128MB" : "32MB"); + return false; + } + return IsOkay(); } diff --git a/pcsx2/Memory.h b/pcsx2/Memory.h index 987a062a99..f1eebe13a1 100644 --- a/pcsx2/Memory.h +++ b/pcsx2/Memory.h @@ -203,7 +203,8 @@ extern void memSetUserMode(); extern void memSetPageAddr(u32 vaddr, u32 paddr); extern void memClearPageAddr(u32 vaddr); extern void memBindConditionalHandlers(); - +extern bool memGetExtraMemMode(); +extern void memSetExtraMemMode(bool mode); extern void memMapVUmicro(); #define memRead8 vtlb_memRead diff --git a/pcsx2/MemoryTypes.h b/pcsx2/MemoryTypes.h index 41bbb15776..c62492696b 100644 --- a/pcsx2/MemoryTypes.h +++ b/pcsx2/MemoryTypes.h @@ -8,6 +8,7 @@ namespace Ps2MemSize { static constexpr u32 MainRam = _32mb; // 32 MB main memory. static constexpr u32 ExtraRam = _1mb * 96; // 32+96 MB devkit memory. + static constexpr u32 TotalRam = _1mb * 128;// 128 MB total memory. static constexpr u32 Rom = _1mb * 4; // 4 MB main rom static constexpr u32 Rom1 = _1mb * 4; // DVD player static constexpr u32 Rom2 = 0x00080000; // Chinese rom extension @@ -18,6 +19,8 @@ namespace Ps2MemSize static constexpr u32 IopHardware = _64kb; static constexpr u32 GSregs = 0x00002000; // 8k for the GS registers and stuff. + + extern u32 ExposedRam; } // namespace Ps2MemSize typedef u8 mem8_t; diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 7f2c93f7d8..c308903a6a 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -513,6 +513,7 @@ Pcsx2Config::CpuOptions::CpuOptions() VU0FPCR = DEFAULT_VU_FP_CONTROL_REGISTER; VU1FPCR = DEFAULT_VU_FP_CONTROL_REGISTER; AffinityControlMode = 0; + ExtraMemory = false; } void Pcsx2Config::CpuOptions::ApplySanityCheck() @@ -544,6 +545,7 @@ void Pcsx2Config::CpuOptions::LoadSave(SettingsWrapper& wrap) read_fpcr(VU1FPCR, "VU1"); SettingsWrapEntry(AffinityControlMode); + SettingsWrapBitBool(ExtraMemory); Recompiler.LoadSave(wrap); } diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 407b3d33f9..026a744599 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -711,6 +711,16 @@ void eeloadHook() } VMManager::Internal::ELFLoadingOnCPUThread(std::move(elfname)); + + if (CHECK_EXTRAMEM) + { + // Map extra memory. + vtlb_VMap(Ps2MemSize::MainRam, Ps2MemSize::MainRam, Ps2MemSize::ExtraRam); + + // Map RAM mirrors for extra memory. + vtlb_VMap(0x20000000 | Ps2MemSize::MainRam, Ps2MemSize::MainRam, Ps2MemSize::ExtraRam); + vtlb_VMap(0x30000000 | Ps2MemSize::MainRam, Ps2MemSize::MainRam, Ps2MemSize::ExtraRam); + } } // Called from recompilers; define is mandatory. diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index 2ebf43d94d..f0d55a74e0 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -953,6 +953,12 @@ void SYSCALL() } } break; + case Syscall::RFU060: + if (CHECK_EXTRAMEM && cpuRegs.GPR.n.a1.UL[0] == 0xFFFFFFFF) + { + cpuRegs.GPR.n.a1.UL[0] = Ps2MemSize::ExposedRam - cpuRegs.GPR.n.a2.SL[0]; + } + break; case Syscall::SetOsdConfigParam: // The whole thing gets written back to BIOS memory, so it'll be in the right place, no need to continue HLEing AllowParams1 = true; @@ -1148,6 +1154,13 @@ void SYSCALL() } break; } + case Syscall::GetMemorySize: + if (CHECK_EXTRAMEM) + { + cpuRegs.GPR.n.v0.UL[0] = Ps2MemSize::ExposedRam; + return; + } + break; default: diff --git a/pcsx2/R5900OpcodeTables.h b/pcsx2/R5900OpcodeTables.h index 290d029eeb..ec32c835c8 100644 --- a/pcsx2/R5900OpcodeTables.h +++ b/pcsx2/R5900OpcodeTables.h @@ -14,13 +14,15 @@ enum Syscall : u8 SetVTLBRefillHandler = 13, StartThread = 34, ChangeThreadPriority = 41, + RFU060 = 60, SetOsdConfigParam = 74, GetOsdConfigParam = 75, SetOsdConfigParam2 = 110, GetOsdConfigParam2 = 111, sysPrintOut = 117, sceSifSetDma = 119, - Deci2Call = 124 + Deci2Call = 124, + GetMemorySize = 127 }; // TODO : Move these into the OpcodeTables namespace diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index 901b24d058..1377fbe4ba 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -164,7 +164,7 @@ bool SaveStateBase::FreezeBios() return IsOkay(); } -bool SaveStateBase::FreezeInternals() +bool SaveStateBase::FreezeInternals(Error* error) { // Print this until the MTVU problem in gifPathFreeze is taken care of (rama) if (THREAD_VU1) @@ -203,7 +203,7 @@ bool SaveStateBase::FreezeInternals() return false; bool okay = rcntFreeze(); - okay = okay && memFreeze(); + okay = okay && memFreeze(error); okay = okay && gsFreeze(); okay = okay && vuMicroFreeze(); okay = okay && vuJITFreeze(); @@ -510,7 +510,7 @@ public: const char* GetFilename() const override { return "eeMemory.bin"; } u8* GetDataPtr() const override { return eeMem->Main; } - uint GetDataSize() const override { return sizeof(eeMem->Main); } + uint GetDataSize() const override { return Ps2MemSize::ExposedRam; } virtual bool FreezeIn(zip_file_t* zf) const override { @@ -720,9 +720,11 @@ std::unique_ptr SaveState_DownloadState(Error* error) return nullptr; } - if (!saveme.FreezeInternals()) + if (!saveme.FreezeInternals(error)) { - Error::SetString(error, "FreezeInternals() failed"); + if (!error->IsValid()) + Error::SetString(error, "FreezeInternals() failed"); + return nullptr; } @@ -1077,7 +1079,7 @@ static zip_int64_t CheckFileExistsInState(zip_t* zf, const char* name, bool requ return index; } -static bool LoadInternalStructuresState(zip_t* zf, s64 index) +static bool LoadInternalStructuresState(zip_t* zf, s64 index, Error* error) { zip_stat_t zst; if (zip_stat_index(zf, index, 0, &zst) != 0 || zst.size > std::numeric_limits::max()) @@ -1096,7 +1098,7 @@ static bool LoadInternalStructuresState(zip_t* zf, s64 index) if (!state.FreezeBios()) return false; - if (!state.FreezeInternals()) + if (!state.FreezeInternals(error)) return false; return true; @@ -1145,9 +1147,10 @@ bool SaveState_UnzipFromDisk(const std::string& filename, Error* error) PreLoadPrep(); - if (!LoadInternalStructuresState(zf.get(), internal_index)) + if (!LoadInternalStructuresState(zf.get(), internal_index, error)) { - Error::SetString(error, "Save state corruption in internal structures."); + if (!error->IsValid()) + Error::SetString(error, "Save state corruption in internal structures."); return false; } diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 1111b3cb46..777d93e606 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -25,7 +25,7 @@ enum class FreezeAction // [SAVEVERSION+] // This informs the auto updater that the users savestates will be invalidated. -static const u32 g_SaveVersion = (0x9A4C << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A4D << 16) | 0x0000; // the freezing data between submodules and core @@ -92,7 +92,7 @@ public: } bool FreezeBios(); - bool FreezeInternals(); + bool FreezeInternals(Error* error); // Loads or saves an arbitrary data type. Usable on atomic types, structs, and arrays. // For dynamically allocated pointers use FreezeMem instead. @@ -192,7 +192,7 @@ protected: bool vmFreeze(); bool mtvuFreeze(); bool rcntFreeze(); - bool memFreeze(); + bool memFreeze(Error* error); bool vuMicroFreeze(); bool vuJITFreeze(); bool vif0Freeze(); diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 50a56a4e92..5ef9e7e24d 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -1376,6 +1376,7 @@ bool VMManager::Initialize(VMBootParameters boot_params) s_cpu_implementation_changed = false; UpdateCPUImplementations(); + memSetExtraMemMode(EmuConfig.Cpu.ExtraMemory); Internal::ClearCPUExecutionCaches(); FPControlRegister::SetCurrent(EmuConfig.Cpu.FPUFPCR); memBindConditionalHandlers(); @@ -1616,6 +1617,7 @@ void VMManager::Reset() if (elf_was_changed) HandleELFChange(false); + memSetExtraMemMode(EmuConfig.Cpu.ExtraMemory); Internal::ClearCPUExecutionCaches(); memBindConditionalHandlers(); SysMemory::Reset(); @@ -3023,6 +3025,11 @@ void VMManager::WarnAboutUnsafeSettings() append(ICON_PF_MICROCHIP, TRANSLATE_SV("VMManager", "VU Clamp Mode is not set to default, this may break some games.")); } + if (EmuConfig.Cpu.ExtraMemory) + { + append(ICON_PF_MICROCHIP, + TRANSLATE_SV("VMManager", "128MB RAM is enabled. Compatibility with some games may be affected.")); + } if (!EmuConfig.EnableGameFixes) { append(ICON_FA_GAMEPAD, diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index f255f49b45..82def73c52 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -832,7 +832,7 @@ static bool vtlb_GetMainMemoryOffsetFromPtr(uptr ptr, u32* mainmem_offset, u32* if (ptr >= (uptr)eeMem->Main && page_end <= (uptr)eeMem->ZeroRead) { const u32 eemem_offset = static_cast(ptr - (uptr)eeMem->Main); - const bool writeable = ((eemem_offset < Ps2MemSize::MainRam) ? (mmap_GetRamPageInfo(eemem_offset) != ProtMode_Write) : true); + const bool writeable = ((eemem_offset < Ps2MemSize::ExposedRam) ? (mmap_GetRamPageInfo(eemem_offset) != ProtMode_Write) : true); *mainmem_offset = (eemem_offset + HostMemoryMap::EEmemOffset); *mainmem_size = (offsetof(EEVM_MemoryAllocMess, ZeroRead) - eemem_offset); *prot = PageProtectionMode().Read().Write(writeable); @@ -1382,7 +1382,7 @@ struct vtlb_PageProtectionInfo vtlb_ProtectionMode Mode; }; -alignas(16) static vtlb_PageProtectionInfo m_PageProtectInfo[Ps2MemSize::MainRam >> __pageshift]; +alignas(16) static vtlb_PageProtectionInfo m_PageProtectInfo[Ps2MemSize::TotalRam >> __pageshift]; // returns: @@ -1398,7 +1398,7 @@ vtlb_ProtectionMode mmap_GetRamPageInfo(u32 paddr) uptr ptr = (uptr)PSM(paddr); uptr rampage = ptr - (uptr)eeMem->Main; - if (!ptr || rampage >= Ps2MemSize::MainRam) + if (!ptr || rampage >= Ps2MemSize::ExposedRam) return ProtMode_NotRequired; //not in ram, no tracking done ... rampage >>= __pageshift; @@ -1482,7 +1482,7 @@ bool PageFaultHandler::HandlePageFault(uptr pc, uptr addr, bool is_write) { // get bad virtual address uptr offset = addr - (uptr)eeMem->Main; - if (offset >= Ps2MemSize::MainRam) + if (offset >= Ps2MemSize::ExposedRam) return false; mmap_ClearCpuBlock(offset); @@ -1499,6 +1499,6 @@ void mmap_ResetBlockTracking() //DbgCon.WriteLn( "vtlb/mmap: Block Tracking reset..." ); std::memset(m_PageProtectInfo, 0, sizeof(m_PageProtectInfo)); if (eeMem) - HostSys::MemProtect(eeMem->Main, Ps2MemSize::MainRam, PageAccess_ReadWrite()); - vtlb_UpdateFastmemProtection(0, Ps2MemSize::MainRam, PageAccess_ReadWrite()); + HostSys::MemProtect(eeMem->Main, Ps2MemSize::ExposedRam, PageAccess_ReadWrite()); + vtlb_UpdateFastmemProtection(0, Ps2MemSize::ExposedRam, PageAccess_ReadWrite()); } diff --git a/pcsx2/x86/ix86-32/iR5900.cpp b/pcsx2/x86/ix86-32/iR5900.cpp index 0a4230f624..fbf7190092 100644 --- a/pcsx2/x86/ix86-32/iR5900.cpp +++ b/pcsx2/x86/ix86-32/iR5900.cpp @@ -18,6 +18,7 @@ #include "common/AlignedMalloc.h" #include "common/FastJmp.h" +#include "common/HeapArray.h" #include "common/Perf.h" // Only for MOVQ workaround. @@ -68,9 +69,10 @@ eeProfiler EE::Profiler; #define X86 -static u8* recRAMCopy = nullptr; -static u8* recLutReserve_RAM = nullptr; -static const size_t recLutSize = (Ps2MemSize::MainRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) * wordsize / 4; +static DynamicHeapArray recRAMCopy; +static DynamicHeapArray recLutReserve_RAM; +static size_t recLutSize; +static bool extraRam; static BASEBLOCK* recRAM = nullptr; // and the ptr to the blocks here static BASEBLOCK* recROM = nullptr; // and here @@ -497,24 +499,19 @@ static __ri void ClearRecLUT(BASEBLOCK* base, int memsize) base[i].SetFnptr((uptr)JITCompile); } -static void recReserve() +static void recReserveRAM() { - recPtr = SysMemory::GetEERec(); - recPtrEnd = SysMemory::GetEERecEnd() - _64kb; + recLutSize = (Ps2MemSize::ExposedRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) * wordsize / 4; - if (!recRAMCopy) - { - recRAMCopy = (u8*)_aligned_malloc(Ps2MemSize::MainRam, 4096); - } + if (recRAMCopy.size() != Ps2MemSize::ExposedRam) + recRAMCopy.resize(Ps2MemSize::ExposedRam); - if (!recRAM) - { - recLutReserve_RAM = (u8*)_aligned_malloc(recLutSize, 4096); - } + if (recLutReserve_RAM.size() != recLutSize) + recLutReserve_RAM.resize(recLutSize); - BASEBLOCK* basepos = (BASEBLOCK*)recLutReserve_RAM; + BASEBLOCK* basepos = reinterpret_cast(recLutReserve_RAM.data()); recRAM = basepos; - basepos += (Ps2MemSize::MainRam / 4); + basepos += (Ps2MemSize::ExposedRam / 4); recROM = basepos; basepos += (Ps2MemSize::Rom / 4); recROM1 = basepos; @@ -525,7 +522,7 @@ static void recReserve() for (int i = 0; i < 0x10000; i++) recLUT_SetPage(recLUT, 0, 0, 0, i, 0); - for (int i = 0x0000; i < (int)(Ps2MemSize::MainRam / 0x10000); i++) + for (int i = 0x0000; i < (int)(Ps2MemSize::ExposedRam / 0x10000); i++) { recLUT_SetPage(recLUT, hwLUT, recRAM, 0x0000, i, i); recLUT_SetPage(recLUT, hwLUT, recRAM, 0x2000, i, i); @@ -557,6 +554,13 @@ static void recReserve() recLUT_SetPage(recLUT, hwLUT, recROM2, 0x8000, i, i - 0x1e40); recLUT_SetPage(recLUT, hwLUT, recROM2, 0xa000, i, i - 0x1e40); } +} + +static void recReserve() +{ + recPtr = SysMemory::GetEERec(); + recPtrEnd = SysMemory::GetEERecEnd() - _64kb; + recReserveRAM(); pxAssertRel(!s_pInstCache, "InstCache not allocated"); s_nInstCacheSize = 128; @@ -565,14 +569,20 @@ static void recReserve() pxFailRel("Failed to allocate R5900 InstCache array"); } -alignas(16) static u16 manual_page[Ps2MemSize::MainRam >> 12]; -alignas(16) static u8 manual_counter[Ps2MemSize::MainRam >> 12]; +alignas(16) static u16 manual_page[Ps2MemSize::TotalRam >> 12]; +alignas(16) static u8 manual_counter[Ps2MemSize::TotalRam >> 12]; //////////////////////////////////////////////////// static void recResetRaw() { Console.WriteLn(Color_StrongBlack, "EE/iR5900 Recompiler Reset"); + if (CHECK_EXTRAMEM != extraRam) + { + recReserveRAM(); + extraRam = !extraRam; + } + EE::Profiler.Reset(); xSetPtr(SysMemory::GetEERec()); @@ -580,8 +590,8 @@ static void recResetRaw() vtlb_DynGenDispatchers(); recPtr = xGetPtr(); - ClearRecLUT((BASEBLOCK*)recLutReserve_RAM, recLutSize); - memset(recRAMCopy, 0, Ps2MemSize::MainRam); + ClearRecLUT(reinterpret_cast(recLutReserve_RAM.data()), recLutSize); + recRAMCopy.fill(0); maxrecmem = 0; @@ -598,8 +608,8 @@ static void recResetRaw() void recShutdown() { - safe_aligned_free(recRAMCopy); - safe_aligned_free(recLutReserve_RAM); + recRAMCopy.deallocate(); + recLutReserve_RAM.deallocate(); recBlocks.Reset(); @@ -2638,7 +2648,7 @@ StartRecomp: pxAssert((pc - startpc) >> 2 <= 0xffff); s_pCurBlockEx->size = (pc - startpc) >> 2; - if (HWADDR(pc) <= Ps2MemSize::MainRam) + if (HWADDR(pc) <= Ps2MemSize::ExposedRam) { BASEBLOCKEX* oldBlock; int i;