This commit is contained in:
Ziemas 2025-12-15 11:42:33 +03:00 committed by GitHub
commit f27681fd25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 95 additions and 71 deletions

View File

@ -100,8 +100,8 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* settings_dialog,
"end of the block, not on the instruction which caused the exception. Refer to the console to see the address where the invalid " "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.")); "access occurred."));
dialog()->registerWidgetHelp(m_ui.extraMemory, tr("Enable 128MB RAM (Dev Console)"), tr("Unchecked"), dialog()->registerWidgetHelp(m_ui.extraMemory, tr("Enable Extended RAM (Dev Console)"), tr("Unchecked"),
tr("Exposes an additional 96MB of memory to the virtual machine.")); tr("Exposes additional memory to the virtual machine, expanding the EE and IOP memory to 128MB and 8MB respectively."));
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). " 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; <b>modifying this setting when a game is not having a visible problem will cause stability issues and/or crashes.</b>")); "The default value handles the vast majority of games; <b>modifying this setting when a game is not having a visible problem will cause stability issues and/or crashes.</b>"));

View File

@ -176,7 +176,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="extraMemory"> <widget class="QCheckBox" name="extraMemory">
<property name="text"> <property name="text">
<string>Enable 128MB RAM (Dev Console)</string> <string>Enable Extended RAM (Dev Console)</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -79,10 +79,9 @@ std::vector<IopMod> getIOPModules()
for (int i = 0; maddr != 0; i++) for (int i = 0; maddr != 0; i++)
{ {
if (maddr >= 0x200000) if (maddr >= Ps2MemSize::ExposedIopRam)
{ {
// outside of memory // outside of memory
// change if we ever support IOP ram extension
return {}; return {};
} }

View File

@ -1039,7 +1039,7 @@ bool R3000DebugInterface::isValidAddress(u32 addr)
return true; return true;
} }
if (addr < 0x200000) if (addr < Ps2MemSize::ExposedIopRam)
{ {
return true; return true;
} }

View File

@ -52,10 +52,11 @@ void iopMemReset()
// at 0x0, 0x8000, and 0xa000: // at 0x0, 0x8000, and 0xa000:
for (int i = 0; i < 0x0080; i++) for (int i = 0; i < 0x0080; i++)
{ {
psxMemWLUT[i + 0x0000] = (uptr)&iopMem->Main[(i & 0x1f) << 16]; u32 mask = (Ps2MemSize::ExposedIopRam / _64kb) - 1;
psxMemWLUT[i + 0x0000] = (uptr)&iopMem->Main[(i & mask) << 16];
// RLUTs, accessed through WLUT. // RLUTs, accessed through WLUT.
psxMemWLUT[i + 0x2000] = (uptr)&iopMem->Main[(i & 0x1f) << 16]; psxMemWLUT[i + 0x2000] = (uptr)&iopMem->Main[(i & mask) << 16];
} }
// A few single-page allocations for things we store in special locations. // A few single-page allocations for things we store in special locations.

View File

@ -37,7 +37,7 @@ static __fi const T* iopVirtMemR( u32 mem )
// Obtains a pointer to the IOP's physical mapping (bypasses the TLB) // Obtains a pointer to the IOP's physical mapping (bypasses the TLB)
static __fi u8* iopPhysMem( u32 addr ) static __fi u8* iopPhysMem( u32 addr )
{ {
return &iopMem->Main[addr & 0x1fffff]; return &iopMem->Main[addr & (Ps2MemSize::ExposedIopRam - 1)];
} }
#define psxSs8(mem) iopMem->Sif[(mem) & 0x00ff] #define psxSs8(mem) iopMem->Sif[(mem) & 0x00ff]

View File

@ -45,6 +45,7 @@ BIOS
namespace Ps2MemSize namespace Ps2MemSize
{ {
u32 ExposedRam = MainRam; u32 ExposedRam = MainRam;
u32 ExposedIopRam = IopRam;
} // namespace Ps2MemSize } // namespace Ps2MemSize
namespace SysMemory namespace SysMemory
@ -305,6 +306,7 @@ void memSetExtraMemMode(bool mode)
// update the amount of RAM exposed to the VM // update the amount of RAM exposed to the VM
Ps2MemSize::ExposedRam = mode ? Ps2MemSize::TotalRam : Ps2MemSize::MainRam; Ps2MemSize::ExposedRam = mode ? Ps2MemSize::TotalRam : Ps2MemSize::MainRam;
Ps2MemSize::ExposedIopRam = mode ? Ps2MemSize::TotalIopRam: Ps2MemSize::IopRam;
} }
void memSetKernelMode() { void memSetKernelMode() {

View File

@ -16,11 +16,14 @@ namespace Ps2MemSize
static constexpr u32 Scratch = _16kb; static constexpr u32 Scratch = _16kb;
static constexpr u32 IopRam = _1mb * 2; // 2MB main ram on the IOP. static constexpr u32 IopRam = _1mb * 2; // 2MB main ram on the IOP.
static constexpr u32 ExtraIopRam = _1mb * 6; // 2MB main ram on the IOP.
static constexpr u32 TotalIopRam = _8mb; // 2MB main ram on the IOP.
static constexpr u32 IopHardware = _64kb; static constexpr u32 IopHardware = _64kb;
static constexpr u32 GSregs = 0x00002000; // 8k for the GS registers and stuff. static constexpr u32 GSregs = 0x00002000; // 8k for the GS registers and stuff.
extern u32 ExposedRam; extern u32 ExposedRam;
extern u32 ExposedIopRam;
} // namespace Ps2MemSize } // namespace Ps2MemSize
typedef u8 mem8_t; typedef u8 mem8_t;
@ -32,12 +35,11 @@ typedef u128 mem128_t;
// Needs to fit within EEmemSize of Memory.h // Needs to fit within EEmemSize of Memory.h
struct EEVM_MemoryAllocMess struct EEVM_MemoryAllocMess
{ {
u8 Main[Ps2MemSize::MainRam]; // Main memory (hard-wired to 32MB) u8 Main[Ps2MemSize::TotalRam]; // Main memory
u8 ExtraMemory[Ps2MemSize::ExtraRam]; // Extra memory (32MB up to 128MB => 96MB). u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad!
u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad! u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB)
u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB) u8 ROM1[Ps2MemSize::Rom1]; // DVD player (4MB)
u8 ROM1[Ps2MemSize::Rom1]; // DVD player (4MB) u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions
u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions
// Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB). // Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB).
// Such accesses are not documented as causing bus errors but as the memory does // Such accesses are not documented as causing bus errors but as the memory does
@ -51,9 +53,9 @@ struct EEVM_MemoryAllocMess
// Needs to fit within IOPmemSize of Memory.h // Needs to fit within IOPmemSize of Memory.h
struct IopVM_MemoryAllocMess struct IopVM_MemoryAllocMess
{ {
u8 Main[Ps2MemSize::IopRam]; // Main memory (hard-wired to 2MB) u8 Main[Ps2MemSize::TotalRam]; // Main memory
u8 P[_64kb]; // I really have no idea what this is... --air u8 P[_64kb]; // I really have no idea what this is... --air
u8 Sif[0x100]; // a few special SIF/SBUS registers (likely not needed) u8 Sif[0x100]; // a few special SIF/SBUS registers (likely not needed)
}; };

View File

@ -537,7 +537,7 @@ public:
const char* GetFilename() const override { return "iopMemory.bin"; } const char* GetFilename() const override { return "iopMemory.bin"; }
u8* GetDataPtr() const override { return iopMem->Main; } u8* GetDataPtr() const override { return iopMem->Main; }
uint GetDataSize() const override { return sizeof(iopMem->Main); } uint GetDataSize() const override { return Ps2MemSize::ExposedIopRam; }
}; };
class SavestateEntry_HwRegs final : public MemorySavestateEntry class SavestateEntry_HwRegs final : public MemorySavestateEntry

View File

@ -282,7 +282,7 @@ void ohci_hard_reset(OHCIState* ohci)
/* Get an array of dwords from main memory */ /* Get an array of dwords from main memory */
__fi static int get_dwords(u32 addr, u32* buf, u32 num) __fi static int get_dwords(u32 addr, u32* buf, u32 num)
{ {
if ((addr + (num * sizeof(u32))) > sizeof(iopMem->Main)) if ((addr + (num * sizeof(u32))) > Ps2MemSize::ExposedIopRam)
return 0; return 0;
std::memcpy(buf, iopMem->Main + addr, num * sizeof(u32)); std::memcpy(buf, iopMem->Main + addr, num * sizeof(u32));
@ -292,7 +292,7 @@ __fi static int get_dwords(u32 addr, u32* buf, u32 num)
/* Get an array of words from main memory */ /* Get an array of words from main memory */
__fi static int get_words(u32 addr, u16* buf, u32 num) __fi static int get_words(u32 addr, u16* buf, u32 num)
{ {
if ((addr + (num * sizeof(u16))) > sizeof(iopMem->Main)) if ((addr + (num * sizeof(u16))) > Ps2MemSize::ExposedIopRam)
return 0; return 0;
std::memcpy(buf, iopMem->Main + addr, num * sizeof(u16)); std::memcpy(buf, iopMem->Main + addr, num * sizeof(u16));
@ -302,7 +302,7 @@ __fi static int get_words(u32 addr, u16* buf, u32 num)
/* Put an array of dwords in to main memory */ /* Put an array of dwords in to main memory */
__fi static int put_dwords(u32 addr, u32* buf, u32 num) __fi static int put_dwords(u32 addr, u32* buf, u32 num)
{ {
if ((addr + (num * sizeof(u32))) > sizeof(iopMem->Main)) if ((addr + (num * sizeof(u32))) > Ps2MemSize::ExposedIopRam)
return 0; return 0;
std::memcpy(iopMem->Main + addr, buf, num * sizeof(u32)); std::memcpy(iopMem->Main + addr, buf, num * sizeof(u32));
@ -312,7 +312,7 @@ __fi static int put_dwords(u32 addr, u32* buf, u32 num)
/* Put an array of dwords in to main memory */ /* Put an array of dwords in to main memory */
__fi static int put_words(u32 addr, u16* buf, u32 num) __fi static int put_words(u32 addr, u16* buf, u32 num)
{ {
if ((addr + (num * sizeof(u16))) > sizeof(iopMem->Main)) if ((addr + (num * sizeof(u16))) > Ps2MemSize::ExposedIopRam)
return 0; return 0;
std::memcpy(iopMem->Main + addr, buf, num * sizeof(u16)); std::memcpy(iopMem->Main + addr, buf, num * sizeof(u16));
@ -362,7 +362,7 @@ static int ohci_copy_td(OHCIState* ohci, struct ohci_td* td, uint8_t* buf, u32 l
u32 ptr = td->cbp; u32 ptr = td->cbp;
const u32 n = std::min<u32>(0x1000 - (ptr & 0xfff), len); const u32 n = std::min<u32>(0x1000 - (ptr & 0xfff), len);
if ((ptr + n) > sizeof(iopMem->Main)) if ((ptr + n) > Ps2MemSize::ExposedIopRam)
return 1; return 1;
if (write) if (write)
@ -376,7 +376,7 @@ static int ohci_copy_td(OHCIState* ohci, struct ohci_td* td, uint8_t* buf, u32 l
buf += n; buf += n;
len -= n; len -= n;
if ((ptr + n) > sizeof(iopMem->Main)) if ((ptr + n) > Ps2MemSize::ExposedIopRam)
return 1; return 1;
if (write) if (write)
@ -394,7 +394,7 @@ static int ohci_copy_iso_td(OHCIState* ohci, u32 start_addr, u32 end_addr,
u32 ptr = start_addr; u32 ptr = start_addr;
const u32 n = std::min<u32>(0x1000 - (ptr & 0xfff), len); const u32 n = std::min<u32>(0x1000 - (ptr & 0xfff), len);
if ((ptr + n) > sizeof(iopMem->Main)) if ((ptr + n) > Ps2MemSize::ExposedIopRam)
return 1; return 1;
if (write) if (write)
@ -408,7 +408,7 @@ static int ohci_copy_iso_td(OHCIState* ohci, u32 start_addr, u32 end_addr,
buf += n; buf += n;
len -= n; len -= n;
if ((ptr + n) > sizeof(iopMem->Main)) if ((ptr + n) > Ps2MemSize::ExposedIopRam)
return 1; return 1;
if (write) if (write)
@ -1099,7 +1099,7 @@ void ohci_frame_boundary(void* opaque)
{ {
OHCIState* ohci = (OHCIState*)opaque; OHCIState* ohci = (OHCIState*)opaque;
if (ohci->hcca + sizeof(ohci_hcca) > sizeof(iopMem->Main)) if (ohci->hcca + sizeof(ohci_hcca) > Ps2MemSize::ExposedIopRam)
{ {
Console.Error("ohci->hcca pointer is out of range."); Console.Error("ohci->hcca pointer is out of range.");
return; return;

View File

@ -3290,7 +3290,7 @@ void VMManager::WarnAboutUnsafeSettings()
if (EmuConfig.Cpu.ExtraMemory) if (EmuConfig.Cpu.ExtraMemory)
{ {
append(ICON_PF_MICROCHIP, append(ICON_PF_MICROCHIP,
TRANSLATE_SV("VMManager", "128MB RAM is enabled. Compatibility with some games may be affected.")); TRANSLATE_SV("VMManager", "Extended RAM is enabled. Compatibility with some games may be affected."));
} }
if (!EmuConfig.EnableGameFixes) if (!EmuConfig.EnableGameFixes)
{ {

View File

@ -94,19 +94,28 @@ mem8_t iopHwRead8_Page1( u32 addr )
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
mem8_t iopHwRead8_Page3( u32 addr ) mem8_t iopHwRead8_Page3(u32 addr)
{ {
// all addresses are assumed to be prefixed with 0x1f803xxx: // all addresses are assumed to be prefixed with 0x1f803xxx:
pxAssume( (addr >> 12) == 0x1f803 ); pxAssume((addr >> 12) == 0x1f803);
const u32 masked_addr = addr & 0x0fff;
mem8_t ret; mem8_t ret;
if( addr == 0x1f803100 ) // PS/EE/IOP conf related switch (masked_addr)
//ret = 0x10; // Dram 2M {
ret = 0xFF; //all high bus is the corect default state for CEX PS2! case 0x100: // TOOL config switches
else ret = 0;
ret = psxHu8( addr ); break;
case 0x204: // TOOL board id
ret = 0x7c;
break;
default:
ret = psxHu8(addr);
break;
}
IopHwTraceLog<mem8_t>( addr, ret, true ); IopHwTraceLog<mem8_t>(addr, ret, true);
return ret; return ret;
} }

View File

@ -8,6 +8,7 @@
#include "IopBios.h" #include "IopBios.h"
#include "IopHw.h" #include "IopHw.h"
#include "Common.h" #include "Common.h"
#include "common/HeapArray.h"
#include "VMManager.h" #include "VMManager.h"
#include <time.h> #include <time.h>
@ -840,37 +841,39 @@ void psxRecompileCodeConst3(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode,
noconstcode(info); noconstcode(info);
} }
static u8* m_recBlockAlloc = NULL; static DynamicHeapArray<BASEBLOCK, 4096> recLutReserve;
static size_t recLutEntries;
static bool extraRam = false;
static const uint m_recBlockAllocSize = static void recReserveRAM()
(((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) / 4) * sizeof(BASEBLOCK)); {
// Goal: Allocate BASEBLOCKs for every possible branch target in IOP memory.
// Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are
// always 4 bytes long).
recLutEntries =
((Ps2MemSize::ExposedIopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) / 4);
if (recLutReserve.size() != recLutEntries)
recLutReserve.resize(recLutEntries);
BASEBLOCK* curpos = recLutReserve.data();
recRAM = curpos;
curpos += (Ps2MemSize::ExposedIopRam / 4);
recROM = curpos;
curpos += (Ps2MemSize::Rom / 4);
recROM1 = curpos;
curpos += (Ps2MemSize::Rom1 / 4);
recROM2 = curpos;
curpos += (Ps2MemSize::Rom2 / 4);
}
static void recReserve() static void recReserve()
{ {
recPtr = SysMemory::GetIOPRec(); recPtr = SysMemory::GetIOPRec();
recPtrEnd = SysMemory::GetIOPRecEnd() - _64kb; recPtrEnd = SysMemory::GetIOPRecEnd() - _64kb;
// Goal: Allocate BASEBLOCKs for every possible branch target in IOP memory. recReserveRAM();
// Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are
// always 4 bytes long).
if (!m_recBlockAlloc)
{
// We're on 64-bit, if these memory allocations fail, we're in real trouble.
m_recBlockAlloc = (u8*)_aligned_malloc(m_recBlockAllocSize, 4096);
if (!m_recBlockAlloc)
pxFailRel("Failed to allocate R3000A BASEBLOCK lookup tables");
}
u8* curpos = m_recBlockAlloc;
recRAM = (BASEBLOCK*)curpos;
curpos += (Ps2MemSize::IopRam / 4) * sizeof(BASEBLOCK);
recROM = (BASEBLOCK*)curpos;
curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK);
recROM1 = (BASEBLOCK*)curpos;
curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);
recROM2 = (BASEBLOCK*)curpos;
curpos += (Ps2MemSize::Rom2 / 4) * sizeof(BASEBLOCK);
pxAssertRel(!s_pInstCache, "InstCache not allocated"); pxAssertRel(!s_pInstCache, "InstCache not allocated");
s_nInstCacheSize = 128; s_nInstCacheSize = 128;
@ -883,12 +886,18 @@ void recResetIOP()
{ {
DevCon.WriteLn("iR3000A Recompiler reset."); DevCon.WriteLn("iR3000A Recompiler reset.");
if (CHECK_EXTRAMEM != extraRam)
{
recReserveRAM();
extraRam = !extraRam;
}
xSetPtr(SysMemory::GetIOPRec()); xSetPtr(SysMemory::GetIOPRec());
_DynGen_Dispatchers(); _DynGen_Dispatchers();
recPtr = xGetPtr(); recPtr = xGetPtr();
iopClearRecLUT((BASEBLOCK*)m_recBlockAlloc, iopClearRecLUT(reinterpret_cast<BASEBLOCK*>(recLutReserve.data()),
(((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) / 4))); Ps2MemSize::ExposedIopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2);
for (int i = 0; i < 0x10000; i++) for (int i = 0; i < 0x10000; i++)
recLUT_SetPage(psxRecLUT, 0, 0, 0, i, 0); recLUT_SetPage(psxRecLUT, 0, 0, 0, i, 0);
@ -899,13 +908,15 @@ void recResetIOP()
// the pc indexer into it's lower common denominator. // the pc indexer into it's lower common denominator.
// We're only mapping 20 pages here in 4 places. // We're only mapping 20 pages here in 4 places.
// 0x80 comes from : (Ps2MemSize::IopRam / 0x10000) * 4 // 0x80 comes from : (Ps2MemSize::IopRam / _64kb) * 4
for (int i = 0; i < 0x80; i++) for (int i = 0; i < 0x80; i++)
{ {
recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0x0000, i, i & 0x1f); u32 mask = (Ps2MemSize::ExposedIopRam / _64kb) - 1;
recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0x8000, i, i & 0x1f);
recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0xa000, i, i & 0x1f); recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0x0000, i, i & mask);
recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0x8000, i, i & mask);
recLUT_SetPage(psxRecLUT, psxhwLUT, recRAM, 0xa000, i, i & mask);
} }
for (int i = 0x1fc0; i < 0x2000; i++) for (int i = 0x1fc0; i < 0x2000; i++)
@ -940,7 +951,7 @@ void recResetIOP()
static void recShutdown() static void recShutdown()
{ {
safe_aligned_free(m_recBlockAlloc); recLutReserve.deallocate();
safe_free(s_pInstCache); safe_free(s_pInstCache);
s_nInstCacheSize = 0; s_nInstCacheSize = 0;
@ -951,7 +962,7 @@ static void recShutdown()
static void iopClearRecLUT(BASEBLOCK* base, int count) static void iopClearRecLUT(BASEBLOCK* base, int count)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count / 4; i++)
base[i].SetFnptr((uptr)iopJITCompile); base[i].SetFnptr((uptr)iopJITCompile);
} }
@ -1039,7 +1050,7 @@ static __fi u32 psxRecClearMem(u32 pc)
} }
} }
iopClearRecLUT(PSX_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4); iopClearRecLUT(PSX_GETBLOCK(lowerextent), upperextent - lowerextent);
return upperextent - pc; return upperextent - pc;
} }

View File

@ -1115,7 +1115,7 @@ static void rpsxLoad(int size, bool sign)
is_ram_read.SetTarget(); is_ram_read.SetTarget();
// read from psM directly // read from psM directly
xAND(arg1regd, 0x1fffff); xAND(arg1regd, Ps2MemSize::ExposedIopRam - 1);
auto addr = xComplexAddress(rax, iopMem->Main, arg1reg); auto addr = xComplexAddress(rax, iopMem->Main, arg1reg);
switch (size) switch (size)