From 3b6afc1d9acb62d00c580a07d7884212a05251eb Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Fri, 27 Feb 2026 08:02:46 +0100 Subject: [PATCH] Final sys_ fixes --- rpcs3/Emu/Cell/lv2/sys_config.cpp | 34 ++++++++----- rpcs3/Emu/Cell/lv2/sys_config.h | 7 ++- rpcs3/Emu/Cell/lv2/sys_dbg.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_event.cpp | 20 ++++---- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 18 ++----- rpcs3/Emu/Cell/lv2/sys_mmapper.cpp | 17 +++++-- rpcs3/Emu/Cell/lv2/sys_net.cpp | 48 +++++++++---------- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h | 2 +- .../Cell/lv2/sys_net/lv2_socket_native.cpp | 6 +-- .../Emu/Cell/lv2/sys_net/lv2_socket_native.h | 2 +- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp | 4 +- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h | 2 +- .../Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp | 9 +--- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h | 2 +- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp | 3 +- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h | 2 +- rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_prx.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp | 16 +++---- rpcs3/Emu/Cell/lv2/sys_ss.cpp | 3 +- rpcs3/Emu/Cell/lv2/sys_uart.cpp | 6 ++- rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 16 ++++--- rpcs3/Emu/Cell/lv2/sys_vm.cpp | 2 +- 23 files changed, 110 insertions(+), 114 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_config.cpp b/rpcs3/Emu/Cell/lv2/sys_config.cpp index 0179a6b7f2..54cb2d6ce8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_config.cpp @@ -174,20 +174,28 @@ bool lv2_config_service_listener::check_service(const lv2_config_service& servic return true; } -bool lv2_config_service_listener::notify(const shared_ptr& event) -{ - service_events.emplace_back(event); - return event->notify(); -} - bool lv2_config_service_listener::notify(const shared_ptr& service) { - if (!check_service(*service)) - return false; + { + std::lock_guard lock(mutex_service_events); - // Create service event and notify queue! - const auto event = lv2_config_service_event::create(handle, service, *this); - return notify(event); + if (!check_service(*service)) + return false; + + // Create service event and notify queue! + const auto event = lv2_config_service_event::create(handle, service, *this); + service_events.emplace_back(event); + + if (!event->notify()) + { + // If we fail to deliver the event to the queue just clean the event up or it'll hold the listener alive forever + g_fxo->get().remove_service_event(event->id); + service_events.pop_back(); + return false; + } + } + + return true; } void lv2_config_service_listener::notify_all() @@ -267,7 +275,7 @@ void lv2_config_service_event::write(sys_config_service_event_t *dst) const { const auto registered = service->is_registered(); - dst->service_listener_handle = listener.get_id(); + dst->service_listener_handle = listener_id; dst->registered = registered; dst->service_id = service->id; dst->user_id = service->user_id; @@ -346,7 +354,7 @@ error_code sys_config_get_service_event(u32 config_hdl, u32 event_id, vm::ptrget().find_event(event_id); - if (!event) + if (!event || event->handle != cfg) { return CELL_ESRCH; } diff --git a/rpcs3/Emu/Cell/lv2/sys_config.h b/rpcs3/Emu/Cell/lv2/sys_config.h index 0804671141..aaf4c6f5d0 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.h +++ b/rpcs3/Emu/Cell/lv2/sys_config.h @@ -296,11 +296,10 @@ private: // The service listener owns the service events - service events will not be freed as long as their corresponding listener exists // This has been confirmed to be the case in realhw + shared_mutex mutex_service_events; std::vector> service_events; shared_ptr handle; - bool notify(const shared_ptr& event); - public: const sys_config_service_id service_id; const u64 min_verbosity; @@ -370,14 +369,14 @@ public: // This has been confirmed to be the case in realhw const shared_ptr handle; const shared_ptr service; - const lv2_config_service_listener& listener; + const u32 listener_id; // Constructors (should not be used directly) lv2_config_service_event(shared_ptr _handle, shared_ptr _service, const lv2_config_service_listener& _listener) noexcept : id(get_next_id()) , handle(std::move(_handle)) , service(std::move(_service)) - , listener(_listener) + , listener_id(_listener.get_id()) { } diff --git a/rpcs3/Emu/Cell/lv2/sys_dbg.cpp b/rpcs3/Emu/Cell/lv2/sys_dbg.cpp index 27fa51b148..eb04cff61b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_dbg.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_dbg.cpp @@ -105,7 +105,7 @@ error_code sys_dbg_write_process_memory(s32 pid, u32 address, u32 size, vm::cptr i += op_size; } - if (!is_exec || i >= end) + if ((!is_exec || i >= end) && exec_update_size > 0) { // Commit executable data update // The read memory is also super ptr so memmove can work correctly on all implementations diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 2d8417cbfc..c5fa15cf55 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -308,6 +308,15 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return CELL_EBUSY; } + for (auto cpu = head; cpu; cpu = cpu->get_next_cpu()) + { + if (cpu->state & cpu_flag::again) + { + ppu.state += cpu_flag::again; + return CELL_EAGAIN; + } + } + if (!queue.events.empty()) { // Copy events for logging, does not empty @@ -320,17 +329,6 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) { qlock.unlock(); } - else - { - for (auto cpu = head; cpu; cpu = cpu->get_next_cpu()) - { - if (cpu->state & cpu_flag::again) - { - ppu.state += cpu_flag::again; - return CELL_EAGAIN; - } - } - } return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 961d0d6ad3..312754af8a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -382,7 +382,7 @@ lv2_fs_object::lv2_fs_object(utils::serial& ar, bool) u64 lv2_file::op_read(const fs::file& file, vm::ptr buf, u64 size, u64 opt_pos) { - if (u64 region = buf.addr() >> 28, region_end = (buf.addr() & 0xfff'ffff) + (size & 0xfff'ffff); region == region_end && ((region >> 28) == 0 || region >= 0xC)) + if (u64 region = buf.addr() >> 28, region_end = (buf.addr() + size) >> 28; region == region_end && region == 0) { // Optimize reads from safe memory return (opt_pos == umax ? file.read(buf.get_ptr(), size) : file.read_at(opt_pos, buf.get_ptr(), size)); @@ -1391,7 +1391,8 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr path, vm::ptr fd) // Add additional entries for split file candidates (while ends with .66600) while (mp.mp != &g_mp_sys_dev_hdd1 && data.back().name.ends_with(".66600")) { - data.emplace_back(data.back()).name.resize(data.back().name.size() - 6); + fs::dir_entry copy = data.back(); + data.emplace_back(copy).name.resize(copy.name.size() - 6); } } @@ -2147,6 +2148,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 sys_fs.notice("sys_fs_fcntl(0xc0000006): %s", vpath); // Check only mountpoint + vpath = vpath.substr(0, vpath.find_first_of('\0')); vpath = vpath.substr(0, vpath.find_first_of("/", 1)); // Some mountpoints seem to be handled specially @@ -2635,8 +2637,6 @@ error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd) { - lv2_obj::sleep(ppu); - sys_fs.trace("sys_fs_fdadasync(fd=%d)", fd); const auto file = idm::get_unlocked(fd); @@ -2661,8 +2661,6 @@ error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd) error_code sys_fs_fsync(ppu_thread& ppu, u32 fd) { - lv2_obj::sleep(ppu); - sys_fs.trace("sys_fs_fsync(fd=%d)", fd); const auto file = idm::get_unlocked(fd); @@ -2903,14 +2901,6 @@ error_code sys_fs_chmod(ppu_thread&, vm::cptr path, s32 mode) { // Try to locate split files - for (u32 i = 66601; i <= 66699; i++) - { - if (mp != &g_mp_sys_dev_hdd1 && !fs::get_stat(fmt::format("%s.%u", local_path, i), info) && !info.is_directory) - { - break; - } - } - if (fs::get_stat(local_path + ".66600", info) && !info.is_directory) { break; diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index d7b66adfd8..0723564a5e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -333,7 +333,7 @@ error_code sys_mmapper_allocate_shared_memory_ext(ppu_thread& ppu, u64 ipc_key, } } - if (flags & ~SYS_MEMORY_PAGE_SIZE_MASK) + if (flags & ~SYS_MEMORY_GRANULARITY_MASK) { return CELL_EINVAL; } @@ -401,6 +401,11 @@ error_code sys_mmapper_allocate_shared_memory_from_container_ext(ppu_thread& ppu sys_mmapper.todo("sys_mmapper_allocate_shared_memory_from_container_ext(ipc_key=0x%x, size=0x%x, flags=0x%x, cid=0x%x, entries=*0x%x, entry_count=0x%x, mem_id=*0x%x)", ipc_key, size, flags, cid, entries, entry_count, mem_id); + if (size == 0) + { + return CELL_EALIGN; + } + switch (flags & SYS_MEMORY_PAGE_SIZE_MASK) { case SYS_MEMORY_PAGE_SIZE_1M: @@ -546,8 +551,7 @@ error_code sys_mmapper_free_address(ppu_thread& ppu, u32 addr) // If a memory block is freed, remove it from page notification table. auto& pf_entries = g_fxo->get(); - std::lock_guard lock(pf_entries.mutex); - + std::unique_lock lock(pf_entries.mutex); auto ind_to_remove = pf_entries.entries.begin(); for (; ind_to_remove != pf_entries.entries.end(); ++ind_to_remove) { @@ -558,7 +562,11 @@ error_code sys_mmapper_free_address(ppu_thread& ppu, u32 addr) } if (ind_to_remove != pf_entries.entries.end()) { + u32 port_id = ind_to_remove->port_id; pf_entries.entries.erase(ind_to_remove); + lock.unlock(); + sys_event_port_disconnect(ppu, port_id); + sys_event_port_destroy(ppu, port_id); } return CELL_OK; @@ -826,7 +834,6 @@ error_code sys_mmapper_enable_page_fault_notification(ppu_thread& ppu, u32 start vm::var port_id(0); error_code res = sys_event_port_create(ppu, port_id, SYS_EVENT_PORT_LOCAL, SYS_MEMORY_PAGE_FAULT_EVENT_KEY); - sys_event_port_connect_local(ppu, *port_id, event_queue_id); if (res + 0u == CELL_EAGAIN) { @@ -834,6 +841,8 @@ error_code sys_mmapper_enable_page_fault_notification(ppu_thread& ppu, u32 start return CELL_EAGAIN; } + sys_event_port_connect_local(ppu, *port_id, event_queue_id); + auto& pf_entries = g_fxo->get(); std::unique_lock lock(pf_entries.mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index 27731e44ca..a860d43b12 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -563,37 +563,34 @@ error_code sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptr(-SYS_NET_EINTR)) + if (state & cpu_flag::signal) { - return -SYS_NET_EINTR; + break; } - if (result) - { - if (result < 0) - { - return sys_net_error{result}; - } + ppu.state.wait(state); + } - return not_an_error(result); + if (ppu.gpr[3] == static_cast(-SYS_NET_EINTR)) + { + return -SYS_NET_EINTR; + } + + if (result) + { + if (result < 0) + { + return sys_net_error{result}; } + + return not_an_error(result); } return CELL_OK; @@ -1295,7 +1292,7 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 n if (auto sock = idm::check_unlocked(fds_buf[i].fd)) { - signaled += sock->poll(fds_buf[i], _fds[i]); + sock->poll(fds_buf[i], _fds[i]); #ifdef _WIN32 connecting[i] = sock->is_connecting(); #endif @@ -1303,7 +1300,6 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 n else { fds_buf[i].revents |= SYS_NET_POLLNVAL; - signaled++; } } @@ -1536,9 +1532,9 @@ error_code sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr select(bs_t selected, pollfd& native_pfd) = 0; error_code abort_socket(s32 flags); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp index 2eb47d7b55..b422db814b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp @@ -1147,14 +1147,14 @@ s32 lv2_socket_native::shutdown(s32 how) return -get_last_error(false); } -s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) +void lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) { // Check for fake packet for dns interceptions auto& dnshook = g_fxo->get(); if (sn_pfd.events & SYS_NET_POLLIN && dnshook.is_dns(sn_pfd.fd) && dnshook.is_dns_queue(sn_pfd.fd)) { sn_pfd.revents |= SYS_NET_POLLIN; - return 1; + return; } if (sn_pfd.events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT | SYS_NET_POLLERR)) { @@ -1171,8 +1171,6 @@ s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) { native_pfd.events |= POLLOUT; } - - return 0; } std::tuple lv2_socket_native::select(bs_t selected, pollfd& native_pfd) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h index 84f4218cbd..af9e6a57b7 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h @@ -50,7 +50,7 @@ public: std::optional sendto(s32 flags, const std::vector& buf, std::optional opt_sn_addr, bool is_lock = true) override; std::optional sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) override; - s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; + void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; std::tuple select(bs_t selected, pollfd& native_pfd) override; bool is_socket_connected(); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp index 67cefe3e3e..903752085b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp @@ -364,7 +364,7 @@ s32 lv2_socket_p2p::shutdown([[maybe_unused]] s32 how) return CELL_OK; } -s32 lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd) +void lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd) { std::lock_guard lock(mutex); ensure(vport); @@ -381,8 +381,6 @@ s32 lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native { sn_pfd.revents |= SYS_NET_POLLOUT; } - - return sn_pfd.revents ? 1 : 0; } std::tuple lv2_socket_p2p::select(bs_t selected, [[maybe_unused]] pollfd& native_pfd) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h index b8fadb3d53..ec6c1d8b31 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h @@ -30,7 +30,7 @@ public: void close() override; s32 shutdown(s32 how) override; - s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; + void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; std::tuple select(bs_t selected, pollfd& native_pfd) override; void handle_new_data(sys_net_sockaddr_in_p2p p2p_addr, std::vector p2p_data); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp index 771402809e..cb59557458 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp @@ -985,7 +985,7 @@ s32 lv2_socket_p2ps::shutdown([[maybe_unused]] s32 how) return CELL_OK; } -s32 lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd) +void lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd) { std::lock_guard lock(mutex); sys_net.trace("[P2PS] poll checking for 0x%X", sn_pfd.events); @@ -1002,14 +1002,7 @@ s32 lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& nativ { sn_pfd.revents |= SYS_NET_POLLOUT; } - - if (sn_pfd.revents) - { - return 1; - } } - - return 0; } std::tuple lv2_socket_p2ps::select(bs_t selected, [[maybe_unused]] pollfd& native_pfd) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h index 8158138936..ac23528d57 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h @@ -89,7 +89,7 @@ public: void close() override; s32 shutdown(s32 how) override; - s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; + void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; std::tuple select(bs_t selected, pollfd& native_pfd) override; private: diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp index 6e74bd512f..39ae39e5b5 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp @@ -134,10 +134,9 @@ s32 lv2_socket_raw::shutdown([[maybe_unused]] s32 how) return {}; } -s32 lv2_socket_raw::poll([[maybe_unused]] sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd) +void lv2_socket_raw::poll([[maybe_unused]] sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native_pfd) { LOG_ONCE(raw_poll, "lv2_socket_raw::poll"); - return {}; } std::tuple lv2_socket_raw::select([[maybe_unused]] bs_t selected, [[maybe_unused]] pollfd& native_pfd) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h index 01b7255884..a03339354f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h @@ -32,6 +32,6 @@ public: void close() override; s32 shutdown(s32 how) override; - s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; + void poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; std::tuple select(bs_t selected, pollfd& native_pfd) override; }; diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index e2463ca101..f26b650346 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -305,6 +305,7 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id) { // Join and notify thread (it is detached from IDM now so it must be done explicitly now) *ptr = thread_state::finished; + return CELL_OK; } return result; diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 046d19c48e..f20b6be6cb 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -899,7 +899,7 @@ error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr library) { for (u32 lib_addr = prx.exports_start, index = 0; lib_addr < prx.exports_end; index++, lib_addr += vm::read8(lib_addr) ? vm::read8(lib_addr) : sizeof_lib) { - if (std::memcpy(vm::base(lib_addr), mem_copy.data(), sizeof_lib) == 0) + if (std::memcmp(vm::base(lib_addr), mem_copy.data(), sizeof_lib) == 0) { atomic_storage::release(prx.m_external_loaded_flags[index], true); return true; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp index 2ba15b1146..29a1fa3501 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp @@ -46,14 +46,14 @@ namespace rsxaudio_ringbuf_reader static void set_timestamp(rsxaudio_shmem::ringbuf_t& ring_buf, u64 timestamp) { const s32 entry_idx_raw = (ring_buf.read_idx + ring_buf.rw_max_idx - (ring_buf.rw_max_idx > 2) - 1) % ring_buf.rw_max_idx; - const s32 entry_idx = std::clamp(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ); + const s32 entry_idx = std::clamp(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1); ring_buf.entries[entry_idx].timestamp = convert_to_timebased_time(timestamp); } static std::tuple update_status(rsxaudio_shmem::ringbuf_t& ring_buf) { - const s32 read_idx = std::clamp(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ); + const s32 read_idx = std::clamp(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1); if ((ring_buf.entries[read_idx].valid & 1) == 0U) { @@ -61,7 +61,7 @@ namespace rsxaudio_ringbuf_reader } const s32 entry_idx_raw = (ring_buf.read_idx + ring_buf.rw_max_idx - (ring_buf.rw_max_idx > 2)) % ring_buf.rw_max_idx; - const s32 entry_idx = std::clamp(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ); + const s32 entry_idx = std::clamp(entry_idx_raw, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1); ring_buf.entries[read_idx].valid = 0; ring_buf.queue_notify_idx = (ring_buf.queue_notify_idx + 1) % ring_buf.queue_notify_step; @@ -72,7 +72,7 @@ namespace rsxaudio_ringbuf_reader static std::pair get_addr(const rsxaudio_shmem::ringbuf_t& ring_buf) { - const s32 read_idx = std::clamp(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ); + const s32 read_idx = std::clamp(ring_buf.read_idx, 0, SYS_RSXAUDIO_RINGBUF_SZ - 1); if (ring_buf.entries[read_idx].valid & 1) { @@ -1392,9 +1392,9 @@ void rsxaudio_backend_thread::operator()() return; } - static rsxaudio_state ra_state{}; - static emu_audio_cfg emu_cfg{}; - static bool backend_failed = false; + rsxaudio_state ra_state{}; + emu_audio_cfg emu_cfg{}; + bool backend_failed = false; for (;;) { @@ -2018,7 +2018,7 @@ void rsxaudio_periodic_tmr::cancel_timer_unlocked() { const u64 flag = 1; const auto wr_res = write(cancel_event, &flag, sizeof(flag)); - ensure(wr_res == sizeof(flag) || wr_res == -EAGAIN); + ensure(wr_res == sizeof(flag) || errno == EAGAIN); } #elif defined(BSD) || defined(__APPLE__) handle[TIMER_ID].flags = (handle[TIMER_ID].flags & ~EV_ENABLE) | EV_DISABLE; diff --git a/rpcs3/Emu/Cell/lv2/sys_ss.cpp b/rpcs3/Emu/Cell/lv2/sys_ss.cpp index 2c4b1282fd..725adbcfc3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ss.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ss.cpp @@ -24,7 +24,7 @@ struct lv2_update_manager // For example, 4.90 should be converted to 0x4900000000000 std::erase(version_str, '.'); - if (std::from_chars(version_str.data(), version_str.data() + version_str.size(), system_sw_version, 16).ec != std::errc{}) + if (std::from_chars(version_str.data(), version_str.data() + version_str.size(), system_sw_version, 16).ec == std::errc{}) system_sw_version <<= 40; else system_sw_version = 0; @@ -79,6 +79,7 @@ struct lv2_update_manager if (malloc_set.count(addr)) { + malloc_set.erase(addr); return vm::dealloc(addr, vm::main); } diff --git a/rpcs3/Emu/Cell/lv2/sys_uart.cpp b/rpcs3/Emu/Cell/lv2/sys_uart.cpp index 67e91b97a0..0049b60ffe 100644 --- a/rpcs3/Emu/Cell/lv2/sys_uart.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_uart.cpp @@ -1531,9 +1531,11 @@ private: } }(); + if (sce_idx == umax) + return PS3AV_STATUS_INVALID_VIDEO_PARAM; + const video_sce_param &sce_param = sce_param_arr[sce_idx]; - if (sce_idx == umax || - video_head_cfg.video_head > PS3AV_HEAD_B_ANALOG || + if (video_head_cfg.video_head > PS3AV_HEAD_B_ANALOG || video_head_cfg.video_order > 1 || video_head_cfg.video_format > 16 || video_head_cfg.video_out_format > 16 || diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index e1c3caf9d7..dca61f3be8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -1173,11 +1173,15 @@ error_code sys_usbd_get_device_list(ppu_thread& ppu, u32 handle, vm::ptr - u32 i_tocopy = std::min(max_devices, ::size32(usbh.handled_devices)); + const u32 i_tocopy = std::min(max_devices, ::size32(usbh.handled_devices)); + u32 index = 0; - for (u32 index = 0; index < i_tocopy; index++) + for (const auto& [_, device] : usbh.handled_devices) { - device_list[index] = usbh.handled_devices[index].first; + if (index == i_tocopy) + break; + + device_list[index++] = device.first; } return not_an_error(i_tocopy); @@ -1409,7 +1413,7 @@ error_code sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr arg1 if (is_stopped(state)) { - std::lock_guard lock(usbh.mutex); + std::lock_guard lock(usbh.mutex_sq); for (auto cpu = +usbh.sq; cpu; cpu = cpu->next_cpu) { @@ -1587,7 +1591,7 @@ error_code sys_usbd_get_transfer_status(ppu_thread& ppu, u32 handle, u32 id_tran std::lock_guard lock(usbh.mutex); - if (!usbh.is_init) + if (!usbh.is_init || id_transfer >= MAX_SYS_USBD_TRANSFERS) return CELL_EINVAL; const auto status = usbh.get_transfer_status(id_transfer); @@ -1607,7 +1611,7 @@ error_code sys_usbd_get_isochronous_transfer_status(ppu_thread& ppu, u32 handle, std::lock_guard lock(usbh.mutex); - if (!usbh.is_init) + if (!usbh.is_init || id_transfer >= MAX_SYS_USBD_TRANSFERS) return CELL_EINVAL; const auto status = usbh.get_isochronous_transfer_status(id_transfer); diff --git a/rpcs3/Emu/Cell/lv2/sys_vm.cpp b/rpcs3/Emu/Cell/lv2/sys_vm.cpp index 2a224d2339..49337cf223 100644 --- a/rpcs3/Emu/Cell/lv2/sys_vm.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_vm.cpp @@ -97,7 +97,7 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u64 vsize, u64 psize, u32 cid, u64 // Look for unmapped space if (const auto area = vm::find_map(0x10000000, 0x10000000, 2 | (flag & SYS_MEMORY_PAGE_SIZE_MASK))) { - sys_vm.warning("sys_vm_memory_map(): Found VM 0x%x area (vsize=0x%x)", addr, vsize); + sys_vm.warning("sys_vm_memory_map(): Found VM 0x%x area (vsize=0x%x)", area->addr, vsize); // Alloc all memory (shall not fail) ensure(area->alloc(static_cast(vsize)));