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
246291std::unique_lock<std::recursive_mutex> Achievements::GetLock ()
247292{
@@ -488,7 +533,7 @@ bool Achievements::Initialize()
488533
489534u32 Achievements::GetExposedEEMemorySize ()
490535{
491- return Ps2MemSize::ExposedRam + Ps2MemSize::Scratch;
536+ return Ps2MemSize::ExposedRam + Ps2MemSize::ExtraRam + Ps2MemSize:: Scratch;
492537}
493538
494539bool 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
715760uint32_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
37683810unsigned 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
37823825unsigned 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
38053848void 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