Skip to content

Commit 20a91db

Browse files
committed
Achievements: Implement new memory mapping w/ extended memory support
1 parent 70f6169 commit 20a91db

1 file changed

Lines changed: 61 additions & 17 deletions

File tree

pcsx2/Achievements.cpp

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <map>
4545
#include <optional>
4646
#include <string>
47+
#include <utility>
4748
#include <vector>
4849

4950
#ifdef ENABLE_RAINTEGRATION
@@ -242,6 +243,50 @@ namespace Achievements
242243
static std::optional<AchievementProgressIndicator> s_active_progress_indicator;
243244
} // namespace Achievements
244245

246+
static u8* _get_ee_mem_address(u32 address)
247+
{
248+
// Given a virtual address and optional size argument, returns a pair of pointers to two
249+
// bytes that address and address+size correspond to. If either address or address+size is
250+
// invalid, nullptr is returned instead expressing that the range is invalid.
251+
252+
// When operating in 128MB mode, both system memory and Scratchpad memory will correspond
253+
// to the virtual addresses used by the console.
254+
// --
255+
// When operating outside of the 128MB mode, the Retroachievements integration places Scratchpad in 2 locations:
256+
// 1. (Legacy) Scratchpad is mapped directly above directly above the main 32MB of memory.
257+
// 2. (Modern) Scratchpad is mapped to its virtual address, 0x70000000U.
258+
// The second mapping ensures that scratchpad can be consistently accessed regardless of if 128MB memory is enabled,
259+
// while the first is for temporary backwards compatibility.
260+
261+
u32 max_ee_size = Ps2MemSize::MainRam;
262+
if (EmuConfig.Cpu.ExtraMemory)
263+
max_ee_size += Ps2MemSize::ExtraRam;
264+
265+
if (address < max_ee_size)
266+
{
267+
// Main memory mapping
268+
return &eeMem->Main[address];
269+
}
270+
else if (!EmuConfig.Cpu.ExtraMemory && address < Ps2MemSize::MainRam + Ps2MemSize::Scratch)
271+
{
272+
// 1. Legacy Scratchpad mapping (Scratchpad @ 0x02000000-0x02003FFF)
273+
return &eeMem->Scratch[address - Ps2MemSize::MainRam];
274+
}
275+
else if (address >= 0x70000000U && address < 0x70000000U + Ps2MemSize::Scratch)
276+
{
277+
// 2. Modern Scratchpad mapping (Scratchpad @ 0x70000000-0x70003FFF)
278+
address &= 0x0FFFFFFF;
279+
return &eeMem->Scratch[address];
280+
}
281+
return nullptr;
282+
}
283+
284+
static std::pair<u8*, u8*> get_ee_mem_address(u32 address, u32 size = 1)
285+
{
286+
if (size != 0)
287+
size -= 1;
288+
return {_get_ee_mem_address(address), _get_ee_mem_address(address + size)};
289+
}
245290

246291
std::unique_lock<std::recursive_mutex> Achievements::GetLock()
247292
{
@@ -488,7 +533,7 @@ bool Achievements::Initialize()
488533

489534
u32 Achievements::GetExposedEEMemorySize()
490535
{
491-
return Ps2MemSize::ExposedRam + Ps2MemSize::Scratch;
536+
return Ps2MemSize::ExposedRam + Ps2MemSize::ExtraRam + Ps2MemSize::Scratch;
492537
}
493538

494539
bool Achievements::CreateClient(rc_client_t** client, std::unique_ptr<HTTPDownloader>* http)
@@ -714,17 +759,14 @@ void Achievements::ClientMessageCallback(const char* message, const rc_client_t*
714759

715760
uint32_t Achievements::ClientReadMemory(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client)
716761
{
717-
if ((static_cast<u64>(address) + num_bytes) > GetExposedEEMemorySize()) [[unlikely]]
762+
const auto [ptr, end] = get_ee_mem_address(address, num_bytes);
763+
764+
if (ptr == nullptr || end == nullptr) [[unlikely]]
718765
{
719766
DevCon.Warning("[Achievements] Ignoring out of bounds memory peek of %u bytes at %08X.", num_bytes, address);
720767
return 0u;
721768
}
722769

723-
// RA uses a fake memory map with the scratchpad directly above physical memory.
724-
// The scratchpad is not meant to be accessible via physical addressing, only virtual.
725-
// This also means that the upper 96MB of memory will never be accessible to achievements.
726-
const u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam];
727-
728770
// Fast paths for known data sizes.
729771
switch (num_bytes)
730772
{
@@ -3767,27 +3809,30 @@ void Achievements::RAIntegration::RACallbackLoadROM(const char* unused)
37673809

37683810
unsigned char Achievements::RAIntegration::RACallbackReadMemory(unsigned int address)
37693811
{
3770-
if ((static_cast<u64>(address) + sizeof(unsigned char)) > GetExposedEEMemorySize())
3812+
const auto [ptr, end] = get_ee_mem_address(address, sizeof(unsigned char));
3813+
3814+
if (ptr == nullptr || end == nullptr) [[unlikely]]
37713815
{
37723816
DevCon.Warning("[Achievements] Ignoring out of bounds memory peek at %08X.", address);
37733817
return 0u;
37743818
}
37753819

37763820
unsigned char value;
3777-
const u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam];
37783821
std::memcpy(&value, ptr, sizeof(value));
37793822
return value;
37803823
}
37813824

37823825
unsigned int Achievements::RAIntegration::RACallbackReadBlock(unsigned int address, unsigned char* buffer, unsigned int bytes)
37833826
{
3784-
if ((address >= GetExposedEEMemorySize())) [[unlikely]]
3827+
const auto [ptr, end] = get_ee_mem_address(address, bytes);
3828+
3829+
if (ptr == nullptr || end == nullptr) [[unlikely]]
37853830
{
37863831
DevCon.Warning("[Achievements] Ignoring out of bounds block memory read for %u bytes at %08X.", bytes, address);
37873832
return 0u;
37883833
}
37893834

3790-
if (address < Ps2MemSize::ExposedRam && (address + bytes) > Ps2MemSize::ExposedRam) [[unlikely]]
3835+
if (!EmuConfig.Cpu.ExtraMemory && address < Ps2MemSize::ExposedRam && (address + bytes) > Ps2MemSize::ExposedRam) [[unlikely]]
37913836
{
37923837
// Split across RAM+Scratch.
37933838
const unsigned int bytes_from_ram = Ps2MemSize::ExposedRam - address;
@@ -3796,21 +3841,20 @@ unsigned int Achievements::RAIntegration::RACallbackReadBlock(unsigned int addre
37963841
RACallbackReadBlock(address + bytes_from_ram, buffer + bytes_from_ram, bytes_from_scratch));
37973842
}
37983843

3799-
const unsigned int read_byte_count = std::min<unsigned int>(GetExposedEEMemorySize() - address, bytes);
3800-
const u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam];
3801-
std::memcpy(buffer, ptr, read_byte_count);
3802-
return read_byte_count;
3844+
std::memcpy(buffer, ptr, bytes);
3845+
return bytes;
38033846
}
38043847

38053848
void Achievements::RAIntegration::RACallbackWriteMemory(unsigned int address, unsigned char value)
38063849
{
3807-
if ((static_cast<u64>(address) + sizeof(value)) > GetExposedEEMemorySize()) [[unlikely]]
3850+
const auto [ptr, end] = get_ee_mem_address(address, sizeof(value));
3851+
3852+
if (ptr == nullptr || end == nullptr) [[unlikely]]
38083853
{
38093854
DevCon.Warning("[Achievements] Ignoring out of bounds memory poke at %08X (value %08X).", address, value);
38103855
return;
38113856
}
38123857

3813-
u8* ptr = (address < Ps2MemSize::ExposedRam) ? &eeMem->Main[address] : &eeMem->Scratch[address - Ps2MemSize::ExposedRam];
38143858
std::memcpy(ptr, &value, sizeof(value));
38153859
}
38163860

0 commit comments

Comments
 (0)