Compare commits

...

6 Commits

Author SHA1 Message Date
sepalani
7156b7de83
Merge 44ceefe2ec into 3564a256bf 2026-03-17 15:48:34 -04:00
JosJuice
3564a256bf
Merge pull request #14478 from JosJuice/wii-menu-headache
Move achievements code out of DVDInterface::SetDisc
2026-03-17 19:07:41 +01:00
Dentomologist
1ab9a867f6
Merge pull request #14396 from cscd98/fmt-fix
fmt: replace <fmt/base.h> with <fmt/format.h> as not available until fmt>=11
2026-03-17 10:34:00 -07:00
JosJuice
e123962bca Move achievements code out of DVDInterface::SetDisc
This should stop AchievementManager::LoadGame from being called for the
default ISO when CBoot::BootUp is booting something other than a disc or
IPL (most notably, the Wii Menu), while still detecting all disc changes
that happen while a disc game is running.
2026-03-17 09:07:34 +01:00
Craig Carnell
4caddbc12b fmt: change use of fmt/base.h to fmt/format.h as not provided until fmt>=11.0 2026-03-15 08:37:00 +00:00
Sepalani
44ceefe2ec AMMediaboard: Change accept non-blocking logic
Fix the function name in log messages.

Handle more accept edge cases such as: using closed sockets, valid sockets but not bound/listening.
2026-03-13 22:54:15 +04:00
5 changed files with 64 additions and 49 deletions

View File

@ -14,7 +14,7 @@
#include <unordered_map>
#include <vector>
#include <fmt/base.h>
#include <fmt/format.h>
#ifdef HAVE_LIBSYSTEMD
#include <systemd/sd-daemon.h>

View File

@ -524,6 +524,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
NOTICE_LOG_FMT(BOOT, "Booting from disc: {}", disc.path);
const DiscIO::VolumeDisc* volume =
SetDisc(system.GetDVDInterface(), std::move(disc.volume), disc.auto_disc_change_paths);
AchievementManager::GetInstance().LoadGame(volume);
if (!volume)
return false;
@ -642,17 +643,17 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
if (!Load_BS2(system, ipl.path))
return false;
const DiscIO::VolumeDisc* volume = nullptr;
if (ipl.disc)
{
NOTICE_LOG_FMT(BOOT, "Inserting disc: {}", ipl.disc->path);
SetDisc(system.GetDVDInterface(), DiscIO::CreateDiscForCore(ipl.disc->path),
ipl.disc->auto_disc_change_paths);
}
else
{
AchievementManager::GetInstance().LoadGame(nullptr);
volume = SetDisc(system.GetDVDInterface(), DiscIO::CreateDiscForCore(ipl.disc->path),
ipl.disc->auto_disc_change_paths);
}
AchievementManager::GetInstance().LoadGame(volume);
SConfig::OnTitleDirectlyBooted(guard);
return true;
}

View File

@ -7,7 +7,7 @@
#include <string>
#include <vector>
#include <fmt/base.h>
#include <fmt/format.h>
#include "Core/DSP/DSPTables.h"

View File

@ -394,22 +394,6 @@ static GuestSocket socket_(int af, int type, int protocol)
return guest_socket;
}
static GuestSocket accept_(int fd, sockaddr* addr, socklen_t* len)
{
const auto guest_socket = GetAvailableGuestSocket();
if (guest_socket == INVALID_GUEST_SOCKET)
return INVALID_GUEST_SOCKET;
const s32 host_fd = accept(fd, addr, len);
if (host_fd < 0)
return INVALID_GUEST_SOCKET;
Common::SetPlatformSocketOptions(host_fd);
s_sockets[u32(guest_socket)] = host_fd;
return guest_socket;
}
static inline void PrintMBBuffer(u32 address, u32 length)
{
const auto& system = Core::System::GetInstance();
@ -846,25 +830,52 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, u8* guest_addr_ptr,
}
const auto host_socket = GetHostSocket(guest_socket);
WSAPOLLFD pfds[1]{{.fd = host_socket, .events = POLLIN}};
// FYI: Currently using a 0ms timeout to make accept calls always non-blocking.
constexpr auto timeout = std::chrono::milliseconds{0};
DEBUG_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: {}({})", host_socket, int(guest_socket));
const int poll_result = PlatformPoll(pfds, timeout);
if (poll_result < 0) [[unlikely]]
if (host_socket == SOCKET_ERROR)
{
// Poll failure.
ERROR_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: PlatformPoll: {}", Common::StrNetworkError());
ERROR_LOG_FMT(AMMEDIABOARD_NET, "NetDIMMAccept: fd is not open: {}({})", host_socket,
int(guest_socket));
s_last_error = SOCKET_ERROR;
// TODO: Not hardware tested.
s_last_error = SSC_EBADF;
return INVALID_GUEST_SOCKET;
}
if ((pfds[0].revents & POLLIN) == 0)
const auto client_sock = GetAvailableGuestSocket();
if (client_sock == INVALID_GUEST_SOCKET)
{
ERROR_LOG_FMT(AMMEDIABOARD_NET,
"NetDIMMAccept: accept( {}({}) ) failed, descriptor table is full", host_socket,
int(guest_socket));
// TODO: Not hardware tested.
s_last_error = SSC_AEMFILE;
return INVALID_GUEST_SOCKET;
}
// There is no easy way to check if the accept's socket is valid:
// - getsockopt's SO_ACCEPTCONN isn't available on all systems
// - poll/select result might be empty even if accept is called beforehand
//
// Might impact performance when accept is called too often.
// TODO: Find a better way.
{
// Set socket to non-blocking
u_long val = 1;
ioctlsocket(host_socket, FIONBIO, &val);
}
Common::ScopeGuard guard{[&] {
// Restore blocking mode
u_long val = 0;
ioctlsocket(host_socket, FIONBIO, &val);
}};
sockaddr_in addr{};
socklen_t addrlen = sizeof(addr);
const s32 res = accept(host_socket, reinterpret_cast<sockaddr*>(&addr), &addrlen);
const int err = WSAGetLastError();
DEBUG_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: {}({})", host_socket, int(guest_socket));
if (res < 0 && err == WSAEWOULDBLOCK)
{
// Timeout.
DEBUG_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: Timeout.");
@ -873,21 +884,20 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, u8* guest_addr_ptr,
return INVALID_GUEST_SOCKET;
}
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
const auto client_sock = accept_(host_socket, reinterpret_cast<sockaddr*>(&addr), &addrlen);
if (client_sock == INVALID_GUEST_SOCKET)
if (res < 0)
{
ERROR_LOG_FMT(AMMEDIABOARD, "AMMBCommandAccept: accept( {}({}) ) failed: {}", host_socket,
int(guest_socket), Common::StrNetworkError());
ERROR_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: accept( {}({}) ) failed with error {}: {}",
host_socket, int(guest_socket), err, Common::DecodeNetworkError(err));
s_last_error = SOCKET_ERROR;
return INVALID_GUEST_SOCKET;
}
Common::SetPlatformSocketOptions(res);
s_sockets[u32(client_sock)] = res;
s_last_error = SSC_SUCCESS;
NOTICE_LOG_FMT(AMMEDIABOARD, "AMMBCommandAccept: {}:{}",
NOTICE_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: {}:{}",
Common::IPAddressToString(std::bit_cast<Common::IPAddress>(addr.sin_addr)),
ntohs(addr.sin_port));
@ -906,7 +916,7 @@ static GuestSocket NetDIMMAccept(GuestSocket guest_socket, u8* guest_addr_ptr,
guest_addr.ip_address = adjusted_ipv4port->ip_address;
guest_addr.port = adjusted_ipv4port->port;
NOTICE_LOG_FMT(AMMEDIABOARD, "AMMBCommandAccept: Translating result to: {}:{}",
NOTICE_LOG_FMT(AMMEDIABOARD, "NetDIMMAccept: Translating result to: {}:{}",
Common::IPAddressToString(guest_addr.ip_address), ntohs(guest_addr.port));
}

View File

@ -420,8 +420,6 @@ void DVDInterface::SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
m_auto_disc_change_index = 0;
}
AchievementManager::GetInstance().LoadGame(disc.get());
// Assume that inserting a disc requires having an empty disc before
if (had_disc != has_disc)
ExpansionInterface::g_rtc_flags[ExpansionInterface::RTCFlag::DiscChanged] = true;
@ -444,6 +442,7 @@ void DVDInterface::AutoChangeDiscCallback(Core::System& system, u64 userdata, s6
void DVDInterface::EjectDiscCallback(Core::System& system, u64 userdata, s64 cyclesLate)
{
AchievementManager::GetInstance().LoadGame(nullptr);
system.GetDVDInterface().SetDisc(nullptr, {});
}
@ -454,9 +453,14 @@ void DVDInterface::InsertDiscCallback(Core::System& system, u64 userdata, s64 cy
DiscIO::CreateDiscForCore(di.m_disc_path_to_insert);
if (new_disc)
{
AchievementManager::GetInstance().LoadGame(new_disc.get());
di.SetDisc(std::move(new_disc), {});
}
else
{
PanicAlertFmtT("The disc that was about to be inserted couldn't be found.");
}
di.m_disc_path_to_insert.clear();
}