From 67a4f184caf160e1be6ca248a45b48acf014eee6 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 5 Feb 2026 20:08:57 -0600 Subject: [PATCH] AMMediaboard: Clean up and make a function for AMMBCommandAccept. --- Source/Core/Core/HW/DVD/AMMediaboard.cpp | 92 +++++++++++++----------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.cpp b/Source/Core/Core/HW/DVD/AMMediaboard.cpp index 3d3cf6b32b..deee54dd55 100644 --- a/Source/Core/Core/HW/DVD/AMMediaboard.cpp +++ b/Source/Core/Core/HW/DVD/AMMediaboard.cpp @@ -483,7 +483,8 @@ static int PlatformPoll(std::span pfds, std::chrono::milliseconds tim static GuestSocket NetDIMMAccept(GuestSocket guest_socket, sockaddr* addr, socklen_t* len) { - WSAPOLLFD pfds[1]{{.fd = GetHostSocket(guest_socket), .events = POLLIN}}; + const auto host_socket = GetHostSocket(guest_socket); + WSAPOLLFD pfds[1]{{.fd = host_socket, .events = POLLIN}}; constexpr auto timeout = std::chrono::milliseconds{10}; @@ -491,7 +492,7 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, sockaddr* addr, sockl if (result > 0 && (pfds[0].revents & POLLIN) != 0) { - const auto client_sock = accept_(GetHostSocket(guest_socket), addr, len); + const auto client_sock = accept_(host_socket, addr, len); if (client_sock == INVALID_GUEST_SOCKET) { ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: accept() failed in NetDIMMAccept ({})", @@ -754,6 +755,51 @@ static void AMMBCommandConnect(u32 parameter_offset, u32 network_buffer_base) s_media_buffer_32[1] = ret; } +static void AMMBCommandAccept(u32 parameter_offset, u32 network_buffer_base) +{ + const auto guest_socket = GuestSocket(s_media_buffer_32[parameter_offset]); + const u32 addr_off = s_media_buffer_32[parameter_offset + 1]; + const u32 addrlen_off = s_media_buffer_32[parameter_offset + 2]; + + u32 ret{}; + + // Either both parameters should be provided, or neither. + if ((addr_off != 0) != (addrlen_off != 0)) + { + WARN_LOG_FMT(AMMEDIABOARD_NET, "AMMBCommandAccept: Unexpected parameters: {}, {}, {}", + u32(guest_socket), addr_off, addrlen_off); + + // TODO: Not hardware tested. + s_last_error = SSC_EFAULT; + ret = SOCKET_ERROR; + } + else + { + sockaddr addr; + socklen_t addrlen = sizeof(addr); + ret = u32(NetDIMMAccept(guest_socket, &addr, &addrlen)); + + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: accept( {} ):{}", u32(guest_socket), u32(ret)); + + auto* const addrlen_ptr = + GetSafePtr(s_network_command_buffer, network_buffer_base, addrlen_off, sizeof(u32)); + if (addrlen_ptr != nullptr) + { + // Read the buffer size. + addrlen = std::min(addrlen, Common::BitCastPtr(addrlen_ptr)); + // Write out the proper length. + Common::BitCastPtr(addrlen_ptr) = sizeof(addr); + + auto* const addr_ptr = + GetSafePtr(s_network_command_buffer, network_buffer_base, addr_off, addrlen); + if (addr_ptr != nullptr) + memcpy(addr_ptr, &addr, addrlen); + } + } + + s_media_buffer_32[1] = ret; +} + // Expects a pointer to a GuestFdSet or nullptr. static void FillPollFdsFromGuestFdSet(std::span pfds, const void* guest_fds_ptr, short requested_events) @@ -1152,48 +1198,8 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u s_media_buffer[4] = 1; break; case AMMBCommand::Accept: - { - const auto guest_socket = GuestSocket(s_media_buffer_32[2]); - GuestSocket ret = INVALID_GUEST_SOCKET; - sockaddr addr; - socklen_t len = 0; - - // Handle optional parameters - if (s_media_buffer_32[3] == 0 || s_media_buffer_32[4] == 0) - { - ret = NetDIMMAccept(guest_socket, nullptr, nullptr); - } - else - { - const u32 addr_off = s_media_buffer_32[3] - NetworkCommandAddress2; - const u32 len_off = s_media_buffer_32[4] - NetworkCommandAddress2; - - if (!NetworkCMDBufferCheck(addr_off, sizeof(sockaddr)) || - !NetworkCMDBufferCheck(len_off, sizeof(u32))) - { - break; - } - - // TODO: Check that the current implementation is correct. Currently, `len=0`, - // so `accept()` might not write to `addr` properly. It might be missing the - // following (assuming the code, address and endianness are correct): - // - // // socklen_t might be larger than u32 - // const u32 addr_len = Common::BitCastPtr(s_network_command_buffer + len_off); - // len = addr_len; - ret = NetDIMMAccept(guest_socket, &addr, &len); - if (len) - { - memcpy(s_network_command_buffer + addr_off, &addr, sizeof(sockaddr)); - memcpy(s_network_command_buffer + len_off, &len, sizeof(u32)); - } - } - - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: accept( {}({}) ):{}", u32(guest_socket), - u32(guest_socket), u32(ret)); - s_media_buffer_32[1] = u32(ret); + AMMBCommandAccept(2, NetworkCommandAddress2); break; - } case AMMBCommand::Bind: { const auto fd = GetHostSocket(GuestSocket(s_media_buffer_32[2]));