diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index dfaa9bca4e..1a39cb4255 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -997,31 +997,39 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr offset) if (!size || (ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE; - u32 io = RSXIOMem.Map(ea, size); - - const auto render = rsx::get_current_renderer(); - - //check if the mapping was successfull - if (RSXIOMem.RealAddr(io) == ea) + // Use the offset table to find the next free io address + for (u32 io = RSXIOMem.GetRangeStart() >> 20, end = RSXIOMem.GetRangeEnd() >> 20, unmap_count = 1; io < end; unmap_count++) { - //fill the offset table - for (u32 i = 0; i<(size >> 20); i++) + if (static_cast(offsetTable.eaAddress[io]) < 0) { - offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i); - offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i); + if (unmap_count >= (size >> 20)) + { + io <<= 20; + + RSXIOMem.Map(ea, size, io); + *offset = io; + + io >>= 20, ea >>= 20; + + //fill the offset table + for (u32 i = 0; i<(size >> 20); ++i) + { + offsetTable.ioAddress[ea + i] = io + i; + offsetTable.eaAddress[io + i] = ea + i; + } + + return CELL_OK; + } + } + else + { + io += unmap_count; + unmap_count = 0; } - - *offset = io; - } - else - { - cellGcmSys.error("cellGcmMapMainMemory: CELL_GCM_ERROR_NO_IO_PAGE_TABLE"); - return CELL_GCM_ERROR_NO_IO_PAGE_TABLE; } - render->main_mem_addr = render->ioAddress; - - return CELL_OK; + cellGcmSys.error("cellGcmMapMainMemory: CELL_GCM_ERROR_NO_IO_PAGE_TABLE"); + return CELL_GCM_ERROR_NO_IO_PAGE_TABLE; } s32 cellGcmReserveIoMapSize(u32 size) diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.h b/rpcs3/Emu/Cell/Modules/cellGcmSys.h index 59583ce442..415e46258a 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.h +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.h @@ -1,7 +1,5 @@ #pragma once - - #include "Emu/RSX/GCM.h" enum @@ -20,5 +18,7 @@ struct CellGcmOffsetTable vm::bptr eaAddress; }; +void InitOffsetTable(); + // Auxiliary functions s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict); diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index f8ccc14878..4d0fdcfa8f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -9,16 +9,10 @@ #include "sys_event.h" - logs::channel sys_rsx("sys_rsx"); extern u64 get_timebased_time(); -struct SysRsxConfig { - be_t rsx_event_port{ 0 }; - u32 driverInfo{ 0 }; -}; - u64 rsxTimeStamp() { return get_timebased_time(); } diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index 52199bd67a..efb66e8f4d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -99,6 +99,12 @@ struct RsxDisplayInfo be_t height; }; +struct SysRsxConfig +{ + be_t rsx_event_port{ 0 }; + u32 driverInfo{ 0 }; +}; + // SysCalls s32 sys_rsx_device_open(); s32 sys_rsx_device_close(); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 9c16ffe98c..02c3b365e2 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -13,35 +13,7 @@ VirtualMemoryBlock* VirtualMemoryBlock::SetRange(const u32 start, const u32 size bool VirtualMemoryBlock::IsInMyRange(const u32 addr, const u32 size) { - return addr >= m_range_start && addr + size - 1 <= m_range_start + m_range_size - 1 - GetReservedAmount(); -} - -u32 VirtualMemoryBlock::Map(u32 realaddr, u32 size) -{ - for (u32 addr = m_range_start; addr <= m_range_start + m_range_size - 1 - GetReservedAmount() - size;) - { - bool is_good_addr = true; - - // check if address is already mapped - for (u32 i = 0; i= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) || - (m_mapped_memory[i].addr >= addr && m_mapped_memory[i].addr < addr + size)) - { - is_good_addr = false; - addr = m_mapped_memory[i].addr + m_mapped_memory[i].size; - break; - } - } - - if (!is_good_addr) continue; - - m_mapped_memory.emplace_back(addr, realaddr, size); - - return addr; - } - - return 0; + return addr >= m_range_start && addr + size <= m_range_start + m_range_size - GetReservedAmount(); } bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr) @@ -117,7 +89,7 @@ bool VirtualMemoryBlock::getRealAddr(u32 addr, u32& result) return false; } -u32 VirtualMemoryBlock::getMappedAddress(u32 realAddress) +s32 VirtualMemoryBlock::getMappedAddress(u32 realAddress) { for (u32 i = 0; i g_access_violation_handler; @@ -2332,6 +2336,28 @@ namespace rsx void thread::on_notify_memory_unmapped(u32 base_address, u32 size) { + { + s32 io_addr = RSXIOMem.getMappedAddress(base_address); + if (io_addr >= 0) + { + if (!isHLE) + { + const u64 unmap_key = u64((1ull << (size >> 20)) - 1) << ((io_addr >> 20) & 0x3f); + const u64 gcm_flag = 0x100000000ull << (io_addr >> 26); + sys_event_port_send(fxm::get()->rsx_event_port, 0, gcm_flag, unmap_key); + } + else + { + const u32 end = (base_address + size) >> 20; + for (base_address >>= 20, io_addr >>= 20; base_address < end;) + { + offsetTable.ioAddress[base_address++] = 0xFFFF; + offsetTable.eaAddress[io_addr++] = 0xFFFF; + } + } + } + } + writer_lock lock(m_mtx_task); m_invalidated_memory_ranges.push_back({ base_address, size }); }