From 2d42a4e25b25f1d2e412b5ac6f04175b90c45863 Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Tue, 13 Jan 2026 13:57:00 +0200 Subject: [PATCH] rsx/gcm: Do not rely on GCM IOMAP table in HLE gcmIoOffsetToAddress --- rpcs3/Emu/Cell/Modules/cellGcmSys.cpp | 40 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index d9fc8be3d3..4c219b71b0 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -98,16 +98,26 @@ u32 gcmGetLocalMemorySize(u32 sdk_version) error_code gcmMapEaIoAddress(ppu_thread& ppu, u32 ea, u32 io, u32 size, bool is_strict); -u32 gcmIoOffsetToAddress(u32 ioOffset) +u32 gcmIoOffsetToAddress(u32 io_offs) { - const u32 upper12Bits = g_fxo->get().offsetTable.eaAddress[ioOffset >> 20]; + u32 upper_12bits = 0; - if (upper12Bits > 0xBFF) + if (io_offs < 0x20000000) { - return 0; + upper_12bits = rsx::get_current_renderer()->iomap_table.ea[io_offs >> 20]; + + if (upper_12bits >= rsx::constants::local_mem_base) + { + upper_12bits = 0; + } } - return (upper12Bits << 20) | (ioOffset & 0xFFFFF); + if (!upper_12bits) + { + cellGcmSys.error("Failed to convert io offset: 0x%x", io_offs); + } + + return upper_12bits | (io_offs & 0xFFFFF); } void InitOffsetTable() @@ -132,15 +142,15 @@ u32 cellGcmGetLabelAddress(u8 index) return rsx::get_current_renderer()->label_addr + 0x10 * index; } -vm::ptr cellGcmGetReportDataAddressLocation(u32 index, u32 location) +vm::ptr cellGcmGetReportDataAddressLocation(ppu_thread& ppu, u32 index, u32 location) { - cellGcmSys.warning("cellGcmGetReportDataAddressLocation(index=%d, location=%d)", index, location); + cellGcmSys.trace("cellGcmGetReportDataAddressLocation(index=%d, location=%d)", index, location); if (location == CELL_GCM_LOCATION_MAIN) { if (index >= 1024 * 1024) { - cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index); + cellGcmSys.error("%s: Wrong main index (%d)", ppu.current_function, index); } return vm::cast(gcmIoOffsetToAddress(0x0e000000 + index * 0x10)); @@ -150,7 +160,7 @@ vm::ptr cellGcmGetReportDataAddressLocation(u32 index, u32 lo if (index >= 2048) { - cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index); + cellGcmSys.error("%s: Wrong local index (%d)", ppu.current_function, index); } return vm::cast(rsx::get_current_renderer()->label_addr + ::offset32(&RsxReports::report) + index * 0x10); @@ -225,21 +235,21 @@ u32 cellGcmGetReportDataAddress(u32 index) return rsx::get_current_renderer()->label_addr + ::offset32(&RsxReports::report) + index * 0x10; } -u32 cellGcmGetReportDataLocation(u32 index, u32 location) +u32 cellGcmGetReportDataLocation(ppu_thread& ppu, u32 index, u32 location) { cellGcmSys.warning("cellGcmGetReportDataLocation(index=%d, location=%d)", index, location); - vm::ptr report = cellGcmGetReportDataAddressLocation(index, location); - ensure(!!report); + vm::ptr report = cellGcmGetReportDataAddressLocation(ppu, index, location); return report->value; } -u64 cellGcmGetTimeStampLocation(u32 index, u32 location) +u64 cellGcmGetTimeStampLocation(ppu_thread& ppu, u32 index, u32 location) { cellGcmSys.trace("cellGcmGetTimeStampLocation(index=%d, location=%d)", index, location); - vm::ptr report = cellGcmGetReportDataAddressLocation(index, location); - ensure(!!report); + vm::ptr report = cellGcmGetReportDataAddressLocation(ppu, index, location); + + // Timestamp reports don't need host GPU access and are much faster to emulate return vm::get_super_ptr(report.addr())->timer; }