diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index 426d025950..a96017b16b 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -446,7 +446,7 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr contex gcm_cfg.zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main); gcm_cfg.tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main); - vm::_ref(gcm_cfg.gcm_info.context_addr) = gcm_cfg.current_context; + vm::write(gcm_cfg.gcm_info.context_addr, gcm_cfg.current_context); context->set(gcm_cfg.gcm_info.context_addr); // 0x40 is to offset CellGcmControl from RsxDmaControl @@ -590,7 +590,7 @@ ret_type gcmSetPrepareFlip(ppu_thread& ppu, vm::ptr ctxt, u3 if (!old_api && ctxt.addr() == gcm_cfg.gcm_info.context_addr) { - vm::_ref(gcm_cfg.gcm_info.control_addr).put += cmd_size; + vm::_ptr(gcm_cfg.gcm_info.control_addr)->put += cmd_size; } return static_cast(not_an_error(id)); @@ -1463,7 +1463,7 @@ s32 cellGcmCallback(ppu_thread& ppu, vm::ptr context, u32 co auto& gcm_cfg = g_fxo->get(); - auto& ctrl = vm::_ref(gcm_cfg.gcm_info.control_addr); + auto& ctrl = *vm::_ptr(gcm_cfg.gcm_info.control_addr); // Flush command buffer (ie allow RSX to read up to context->current) ctrl.put.exchange(getOffsetFromAddress(context->current.addr())); diff --git a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp index e35d154eef..7cdb317cc2 100644 --- a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp @@ -4134,7 +4134,7 @@ s32 _spurs::create_task(vm::ptr taskset, vm::ptr task_id, u32 tmp_task_id; - vm::light_op(vm::_ref>(taskset.ptr(&CellSpursTaskset::enabled).addr()), [&](atomic_be_t& ptr) + vm::light_op(*vm::_ptr>(taskset.ptr(&CellSpursTaskset::enabled).addr()), [&](atomic_be_t& ptr) { // NOTE: Realfw processes this using 4 32-bits atomic loops // But here its processed within a single 128-bit atomic op diff --git a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp index 43b3e04c8b..a6cdeb6d82 100644 --- a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp @@ -1594,12 +1594,12 @@ s32 spursTasksetProcessRequest(spu_thread& spu, s32 request, u32* taskId, u32* i spursHalt(spu); } - vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::waiting)) = waiting; - vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::running)) = running; - vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::ready)) = ready; - vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::pending_ready)) = v128{}; - vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::enabled)) = enabled; - vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::signalled)) = signalled; + // vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::waiting)) = waiting; + // vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::running)) = running; + // vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::ready)) = ready; + // vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::pending_ready)) = v128{}; + // vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::enabled)) = enabled; + // vm::_ref(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::signalled)) = signalled; std::memcpy(spu._ptr(0x2700), spu._ptr(0x100), 128); // Copy data }//); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 47a4784104..04268f3ca1 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -3367,7 +3367,10 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) fmt::throw_exception("PPU %s: Unaligned address: 0x%08x", sizeof(T) == 4 ? "STWCX" : "STDCX", addr); } - auto& data = vm::_ref>(addr & -8); + // Notify breakpoint handler + vm::write(addr, T{0}, &ppu); + + auto& data = const_cast&>(vm::_ref>(addr & -8)); auto& res = vm::reservation_acquire(addr); const u64 rtime = ppu.rtime; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index db53a22f61..3ab6a10a61 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -3833,14 +3833,14 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args) { if (addr - spurs_addr <= 0x80) { - mov_rdata(vm::_ref(addr), to_write); + mov_rdata(*vm::_ptr(addr), to_write); res += 64; return true; } } else if (!g_use_rtm) { - vm::_ref>(addr) += 0; + *vm::_ptr>(addr) += 0; } if (g_use_rtm) [[likely]] diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 87176ae035..0c912490bd 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -181,7 +181,7 @@ error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr mem_handle, vm: if (u32 addr = rsx::get_current_renderer()->driver_info) { - vm::_ref(addr).memory_size = size; + vm::_ptr(addr)->memory_size = size; } *mem_addr = rsx::constants::local_mem_base; @@ -265,7 +265,7 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr context_id, vm *lpar_driver_info = dma_address + 0x100000; *lpar_reports = dma_address + 0x200000; - auto &reports = vm::_ref(vm::cast(*lpar_reports)); + auto &reports = *vm::_ptr(vm::cast(*lpar_reports)); std::memset(&reports, 0, sizeof(RsxReports)); for (usz i = 0; i < std::size(reports.notify); ++i) @@ -273,10 +273,10 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr context_id, vm for (usz i = 0; i < std::size(reports.semaphore); i += 4) { - 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; + reports.semaphore[i + 0] = 0x1337C0D3; + reports.semaphore[i + 1] = 0x1337BABE; + reports.semaphore[i + 2] = 0x1337BEEF; + reports.semaphore[i + 3] = 0x1337F001; } for (usz i = 0; i < std::size(reports.report); ++i) @@ -286,7 +286,7 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr context_id, vm reports.report[i].pad = -1; } - auto &driverInfo = vm::_ref(vm::cast(*lpar_driver_info)); + auto &driverInfo = *vm::_ptr(vm::cast(*lpar_driver_info)); std::memset(&driverInfo, 0, sizeof(RsxDriverInfo)); @@ -303,7 +303,7 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr context_id, vm render->driver_info = vm::cast(*lpar_driver_info); - auto &dmaControl = vm::_ref(vm::cast(*lpar_dma_control)); + auto &dmaControl = *vm::_ptr(vm::cast(*lpar_dma_control)); dmaControl.get = 0; dmaControl.put = 0; dmaControl.ref = 0; // Set later to -1 by cellGcmSys @@ -527,7 +527,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 return { CELL_EINVAL, "context_id is 0x%x", context_id }; } - auto &driverInfo = vm::_ref(render->driver_info); + auto &driverInfo = *vm::_ptr(render->driver_info); switch (package_id) { case 0x001: // FIFO @@ -862,7 +862,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 // seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip // NOTE: Realhw resets 16 bytes of this semaphore for some reason - vm::_ref>(render->label_addr + 0x10).store(u128{}); + vm::_ptr>(render->label_addr + 0x10)->store(u128{}); render->send_event(0, SYS_RSX_EVENT_FLIP_BASE << 1, 0); break; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index 5188453c5b..44f02a697d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -87,10 +87,7 @@ struct RsxDmaControl be_t unk1; }; -struct RsxSemaphore -{ - atomic_be_t val; -}; +using RsxSemaphore = be_t; struct alignas(16) RsxNotify { diff --git a/rpcs3/Emu/Cell/lv2/sys_ss.cpp b/rpcs3/Emu/Cell/lv2/sys_ss.cpp index 7eb36d4e19..a602cd6ee7 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ss.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ss.cpp @@ -553,7 +553,7 @@ error_code sys_ss_individual_info_manager(u64 pkg_id, u64 a2, vm::ptr out_s case 0x17002: { // TODO - vm::_ref(a5) = a4; // Write back size of buffer + vm::write(a5, a4); // Write back size of buffer break; } // Get EID size diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 48157c1e63..25ff1cd33e 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -8,14 +8,14 @@ #include "util/to_endian.hpp" +class ppu_thread; + #ifdef RPCS3_HAS_MEMORY_BREAKPOINTS #include "rpcs3qt/breakpoint_handler.h" #include "util/logs.hpp" LOG_CHANNEL(debugbp_log, "DebugBP"); -class ppu_thread; - void ppubreak(ppu_thread& ppu); #endif @@ -282,9 +282,10 @@ namespace vm } // Convert specified PS3 address to a reference of specified (possibly converted to BE) type - template inline to_be_t& _ref(const U& addr) + // Const lvalue: prevent abused writes + template inline const to_be_t& _ref(const U& addr) { - return *static_cast*>(base(addr)); + return *static_cast*>(base(addr)); } // Access memory bypassing memory protection @@ -300,42 +301,43 @@ namespace vm } #ifdef RPCS3_HAS_MEMORY_BREAKPOINTS - inline void write16(u32 addr, be_t value, ppu_thread* ppu = nullptr) + template + inline void write(u32 addr, U value, ppu_thread* ppu = nullptr) #else - inline void write16(u32 addr, be_t value) + template + inline void write(u32 addr, U value, ppu_thread* = nullptr) #endif { - _ref(addr) = value; + using dest_t = std::conditional_t, U, T>; + + if constexpr (!std::is_void_v) + { + *_ptr(addr) = value; + } #ifdef RPCS3_HAS_MEMORY_BREAKPOINTS if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write)) { - debugbp_log.success("BPMW: breakpoint writing(16) 0x%x at 0x%x", value, addr); + debugbp_log.success("BPMW: breakpoint writing(%d) 0x%x at 0x%x", + sizeof(dest_t) * CHAR_BIT, value, addr); ppubreak(*ppu); } #endif } + inline void write16(u32 addr, be_t value, ppu_thread* ppu = nullptr) + { + write>(addr, value, ppu); + } + inline const be_t& read32(u32 addr) { return _ref(addr); } -#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS inline void write32(u32 addr, be_t value, ppu_thread* ppu = nullptr) -#else - inline void write32(u32 addr, be_t value) -#endif { - _ref(addr) = value; - -#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS - if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write)) - { - debugbp_log.success("BPMW: breakpoint writing(32) 0x%x at 0x%x", value, addr); - ppubreak(*ppu); - } -#endif + write>(addr, value, ppu); } inline const be_t& read64(u32 addr) @@ -343,41 +345,9 @@ namespace vm return _ref(addr); } -#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS inline void write64(u32 addr, be_t value, ppu_thread* ppu = nullptr) -#else - inline void write64(u32 addr, be_t value) -#endif { - _ref(addr) = value; - -#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS - if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write)) - { - debugbp_log.success("BPMW: breakpoint writing(64) 0x%x at 0x%x", value, addr); - ppubreak(*ppu); - } -#endif - } - -#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS - template - inline void write(u32 addr, U value, ppu_thread* ppu = nullptr) -#else - template - inline void write(u32 addr, U value) -#endif - { - _ref(addr) = static_cast(value); - -#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS - if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write)) - { - debugbp_log.success("BPMW: breakpoint writing(%d) 0x%x at 0x%x", - sizeof(T) * CHAR_BIT, value, addr); - ppubreak(*ppu); - } -#endif + write>(addr, value, ppu); } void init(); diff --git a/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp b/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp index 92e3b1af53..cbb04d140a 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp @@ -15,7 +15,7 @@ namespace rsx RSX(ctx)->sync(); // Write ref+get (get will be written again with the same value at command end) - auto& dma = vm::_ref(RSX(ctx)->dma_address); + auto& dma = *vm::_ptr(RSX(ctx)->dma_address); dma.get.release(RSX(ctx)->fifo_ctrl->get_pos()); dma.ref.store(arg); } @@ -28,7 +28,7 @@ namespace rsx // Syncronization point, may be associated with memory changes without actually changing addresses RSX(ctx)->m_graphics_state |= rsx::pipeline_state::fragment_program_needs_rehash; - const auto& sema = vm::_ref(addr).val; + const auto& sema = vm::_ref(addr); if (sema == arg) { diff --git a/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp index eeb52a2242..d0298cf359 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp @@ -566,7 +566,7 @@ namespace rsx default: rsx_log.error("NV4097_GET_REPORT: Bad type %d", type); - vm::_ref>(address_ptr).atomic_op([&](CellGcmReportData& data) + vm::_ptr>(address_ptr)->atomic_op([&](CellGcmReportData& data) { data.timer = RSX(ctx)->timestamp(); data.padding = 0; @@ -651,7 +651,7 @@ namespace rsx ensure(addr != umax); - vm::_ref>(addr).store( + vm::_ptr>(addr)->store( { RSX(ctx)->timestamp(), 0 diff --git a/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp b/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp index 1ab5371d9a..9f39f84c00 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp @@ -21,7 +21,7 @@ namespace rsx // First, queue the GPU work. If it flushes the queue for us, the following routines will be faster. const bool handled = RSX(ctx)->get_backend_config().supports_host_gpu_labels && RSX(ctx)->release_GCM_label(address, data); - if (vm::_ref(address).val == data) + if (vm::_ref(address) == data) { // It's a no-op to write the same value (although there is a delay in real-hw so it's more accurate to allow GPU label in this case) return; @@ -57,7 +57,7 @@ namespace rsx } } - vm::_ref(address).val = data; + vm::write>(address, data); } } } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7e908c01ab..ffd09a742f 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1212,7 +1212,7 @@ namespace rsx if (const u64 get_put = new_get_put.exchange(u64{umax}); get_put != umax) { - vm::_ref>(dma_address + ::offset32(&RsxDmaControl::put)).release(get_put); + vm::_ptr>(dma_address + ::offset32(&RsxDmaControl::put))->release(get_put); fifo_ctrl->set_get(static_cast(get_put)); fifo_ctrl->abort(); fifo_ret_addr = RSX_CALL_STACK_EMPTY; @@ -2457,7 +2457,7 @@ namespace rsx } rsx::reservation_lock lock(sink, 16); - vm::_ref>(sink).store({timestamp(), value, 0}); + vm::_ptr>(sink)->store({timestamp(), value, 0}); } u32 thread::copy_zcull_stats(u32 memory_range_start, u32 memory_range, u32 destination) diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 5a8e9e3fcc..903a10c582 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -62,7 +62,7 @@ namespace rsx RSX(ctx)->reset(); RSX(ctx)->on_frame_end(arg); RSX(ctx)->request_emu_flip(arg); - vm::_ref>(RSX(ctx)->label_addr + 0x10).store(u128{}); + vm::_ptr>(RSX(ctx)->label_addr + 0x10)->store(u128{}); } void user_command(context* ctx, u32, u32 arg)