diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 596d8c1399..09c2f3196b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -198,17 +198,18 @@ error_code sys_rsx_context_allocate(vm::ptr context_id, vm::ptr lpar_d auto &reports = vm::_ref(vm::cast(*lpar_reports, HERE)); std::memset(&reports, 0, sizeof(RsxReports)); - for (int i = 0; i < 64; ++i) + for (size_t i = 0; i < std::size(reports.notify); ++i) reports.notify[i].timestamp = -1; - for (int i = 0; i < 256; ++i) + for (size_t i = 0; i < std::size(reports.semaphore); i += 4) { - reports.semaphore[i].val = 0x1337C0D3; - reports.semaphore[i].zero = 0x1337BABE; - reports.semaphore[i].zero2 = 0x1337BEEF1337F001; + reports.semaphore[i + 0].val.raw() = 0x1337C0D3; + reports.semaphore[i + 1].val.raw() = 0x1337BABE; + reports.semaphore[i + 2].val.raw() = 0x1337BEEF; + reports.semaphore[i + 3].val.raw() = 0x1337F001; } - for (int i = 0; i < 2048; ++i) + for (size_t i = 0; i < std::size(reports.report); ++i) { reports.report[i].val = 0; reports.report[i].timestamp = -1; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index 308a71cb05..65b6eca25c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -84,11 +84,9 @@ struct RsxDmaControl be_t unk1; }; -struct alignas(16) RsxSemaphore +struct RsxSemaphore { - be_t val; - be_t zero; - be_t zero2; + atomic_be_t val; }; struct alignas(16) RsxNotify @@ -106,7 +104,7 @@ struct alignas(16) RsxReport struct RsxReports { - RsxSemaphore semaphore[0x100]; + RsxSemaphore semaphore[0x400]; RsxNotify notify[64]; RsxReport report[2048]; }; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 27e44b40cc..036ec7d54d 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -55,7 +55,7 @@ namespace rsx rsx->sync_point_request.release(true); const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e(), HERE); - const auto& sema = vm::_ref>(addr); + const auto& sema = vm::_ref(addr).val; // TODO: Remove vblank semaphore hack if (addr == rsx->device_addr + 0x30) return; @@ -126,7 +126,14 @@ namespace rsx { rsx->sync(); - const u32 offset = method_registers.semaphore_offset_406e() & -16; + const u32 offset = method_registers.semaphore_offset_406e(); + + if (offset % 4) + { + rsx_log.warning("NV406E semaphore release is using unaligned semaphore, ignoring. (offset=0x%x)", offset); + return; + } + const u32 ctxt = method_registers.semaphore_context_dma_406e(); // By avoiding doing this on flip's semaphore release @@ -147,7 +154,7 @@ namespace rsx res = &vm::reservation_lock(addr, 4); } - vm::_ref>(addr).store({arg, 0, 0}); + vm::_ref(addr).val = arg; if (res) { @@ -225,13 +232,16 @@ namespace rsx // lle-gcm likes to inject system reserved semaphores, presumably for system/vsh usage // Avoid calling render to avoid any havoc(flickering) they may cause from invalid flush/write - const u32 offset = method_registers.semaphore_offset_4097() & -16; - vm::_ref>(get_address(offset, method_registers.semaphore_context_dma_4097(), HERE)).store( + const u32 offset = method_registers.semaphore_offset_4097(); + + if (offset % 16) { - arg, - 0, - 0 - }); + rsx_log.error("NV4097 semaphore using unaligned offset, recovering. (offset=0x%x)", offset); + rsx->recover_fifo(); + return; + } + + vm::_ref(get_address(offset, method_registers.semaphore_context_dma_4097(), HERE)).val = arg; } void back_end_write_semaphore_release(thread* rsx, u32 _reg, u32 arg) @@ -240,14 +250,17 @@ namespace rsx g_fxo->get()->sync(); rsx->sync(); - const u32 offset = method_registers.semaphore_offset_4097() & -16; - const u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff); - vm::_ref>(get_address(offset, method_registers.semaphore_context_dma_4097(), HERE)).store( + const u32 offset = method_registers.semaphore_offset_4097(); + + if (offset % 16) { - val, - 0, - 0 - }); + rsx_log.error("NV4097 semaphore using unaligned offset, recovering. (offset=0x%x)", offset); + rsx->recover_fifo(); + return; + } + + const u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff); + vm::_ref(get_address(offset, method_registers.semaphore_context_dma_4097(), HERE)).val = val; } /**