From c68d484a6572fbf5a992d738ea9a4491f1cdcaab Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 5 Mar 2023 21:50:00 -0800 Subject: [PATCH 1/9] OGL: Convert SupportedESPointSize to an enum class --- Source/Core/VideoBackends/OGL/OGLConfig.cpp | 13 ++++++++----- Source/Core/VideoBackends/OGL/OGLConfig.h | 10 +++++++++- .../Core/VideoBackends/OGL/ProgramShaderCache.cpp | 5 +++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp index ab31592bd2..9d426c2ff6 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp +++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp @@ -368,9 +368,10 @@ bool PopulateConfig(GLContext* m_main_gl_context) if (m_main_gl_context->IsGLES()) { - g_ogl_config.SupportedESPointSize = GLExtensions::Supports("GL_OES_geometry_point_size") ? 1 : - GLExtensions::Supports("GL_EXT_geometry_point_size") ? 2 : - 0; + g_ogl_config.SupportedESPointSize = + GLExtensions::Supports("GL_OES_geometry_point_size") ? EsPointSizeType::PointSizeOes : + GLExtensions::Supports("GL_EXT_geometry_point_size") ? EsPointSizeType::PointSizeExt : + EsPointSizeType::PointSizeNone; g_ogl_config.SupportedESTextureBuffer = GLExtensions::Supports("VERSION_GLES_3_2") ? EsTexbufType::TexbufCore : GLExtensions::Supports("GL_OES_texture_buffer") ? EsTexbufType::TexbufOes : @@ -410,7 +411,8 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_Config.backend_info.bSupportsGeometryShaders = g_ogl_config.bSupportsAEP; g_Config.backend_info.bSupportsComputeShaders = true; g_Config.backend_info.bSupportsGSInstancing = - g_Config.backend_info.bSupportsGeometryShaders && g_ogl_config.SupportedESPointSize > 0; + g_Config.backend_info.bSupportsGeometryShaders && + g_ogl_config.SupportedESPointSize != EsPointSizeType::PointSizeNone; g_Config.backend_info.bSupportsSSAA = g_ogl_config.bSupportsAEP; g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true; g_ogl_config.bSupportsMSAA = true; @@ -434,7 +436,8 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_ogl_config.bSupportsImageLoadStore = true; g_Config.backend_info.bSupportsGeometryShaders = true; g_Config.backend_info.bSupportsComputeShaders = true; - g_Config.backend_info.bSupportsGSInstancing = g_ogl_config.SupportedESPointSize > 0; + g_Config.backend_info.bSupportsGSInstancing = + g_ogl_config.SupportedESPointSize != EsPointSizeType::PointSizeNone; g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsSSAA = true; g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true; diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.h b/Source/Core/VideoBackends/OGL/OGLConfig.h index 570e1954eb..6e8946bc50 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.h +++ b/Source/Core/VideoBackends/OGL/OGLConfig.h @@ -22,6 +22,14 @@ enum GlslVersion GlslEs310, // GLES 3.1 GlslEs320, // GLES 3.2 }; + +enum class EsPointSizeType +{ + PointSizeNone, + PointSizeOes, + PointSizeExt, +}; + enum class EsTexbufType { TexbufNone, @@ -51,7 +59,7 @@ struct VideoConfig bool bSupportsAEP; bool bSupportsDebug; bool bSupportsCopySubImage; - u8 SupportedESPointSize; + EsPointSizeType SupportedESPointSize; EsTexbufType SupportedESTextureBuffer; bool bSupportsTextureStorage; bool bSupports2DTextureStorageMultisample; diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index eff1497e7f..b7dba51cf2 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -664,12 +664,13 @@ void ProgramShaderCache::CreateHeader() std::string SupportedESTextureBuffer; switch (g_ogl_config.SupportedESPointSize) { - case 1: + case EsPointSizeType::PointSizeOes: SupportedESPointSize = "#extension GL_OES_geometry_point_size : enable"; break; - case 2: + case EsPointSizeType::PointSizeExt: SupportedESPointSize = "#extension GL_EXT_geometry_point_size : enable"; break; + case EsPointSizeType::PointSizeNone: default: SupportedESPointSize = ""; break; From 53beda526bf9d8b72cc8316550fbcacb107fd2f1 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 5 Mar 2023 21:41:52 -0800 Subject: [PATCH 2/9] OGL: Remove bSupports2DTextureStorageMultisample and bSupports3DTextureStorageMultisample bSupports2DTextureStorageMultisample is completely unused, while bSupports3DTextureStorageMultisample is practically unused. In the past, these were checked and fell back to sampler2DMS instead of sampler2DMSArray on GLES 3.1, but this path was removed in f039149198657c1891e1c6462ed30c31ed4b8486 and Dolphin always uses array textures now. --- Source/Core/VideoBackends/OGL/OGLConfig.cpp | 15 --------------- Source/Core/VideoBackends/OGL/OGLConfig.h | 2 -- 2 files changed, 17 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp index 9d426c2ff6..575993c8bf 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp +++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp @@ -333,11 +333,6 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_ogl_config.bSupportsDebug = GLExtensions::Supports("GL_KHR_debug") || GLExtensions::Supports("GL_ARB_debug_output"); g_ogl_config.bSupportsTextureStorage = GLExtensions::Supports("GL_ARB_texture_storage"); - g_ogl_config.bSupports3DTextureStorageMultisample = - GLExtensions::Supports("GL_ARB_texture_storage_multisample") || - GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array"); - g_ogl_config.bSupports2DTextureStorageMultisample = - GLExtensions::Supports("GL_ARB_texture_storage_multisample"); g_ogl_config.bSupportsImageLoadStore = GLExtensions::Supports("GL_ARB_shader_image_load_store"); g_ogl_config.bSupportsConservativeDepth = GLExtensions::Supports("GL_ARB_conservative_depth"); g_ogl_config.bSupportsAniso = GLExtensions::Supports("GL_EXT_texture_filter_anisotropic"); @@ -417,16 +412,8 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true; g_ogl_config.bSupportsMSAA = true; g_ogl_config.bSupportsTextureStorage = true; - g_ogl_config.bSupports2DTextureStorageMultisample = true; g_Config.backend_info.bSupportsBitfield = true; g_Config.backend_info.bSupportsDynamicSamplerIndexing = g_ogl_config.bSupportsAEP; - if (g_ActiveConfig.stereo_mode != StereoMode::Off && g_ActiveConfig.iMultisamples > 1 && - !g_ogl_config.bSupports3DTextureStorageMultisample) - { - // GLES 3.1 can't support stereo rendering and MSAA - OSD::AddMessage("MSAA Stereo rendering isn't supported by your GPU.", 10000); - Config::SetCurrent(Config::GFX_MSAA, UINT32_C(1)); - } } else { @@ -446,8 +433,6 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_ogl_config.bSupportsDebug = true; g_ogl_config.bSupportsMSAA = true; g_ogl_config.bSupportsTextureStorage = true; - g_ogl_config.bSupports2DTextureStorageMultisample = true; - g_ogl_config.bSupports3DTextureStorageMultisample = true; g_Config.backend_info.bSupportsBitfield = true; g_Config.backend_info.bSupportsDynamicSamplerIndexing = true; g_Config.backend_info.bSupportsSettingObjectNames = true; diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.h b/Source/Core/VideoBackends/OGL/OGLConfig.h index 6e8946bc50..8ee717f0b3 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.h +++ b/Source/Core/VideoBackends/OGL/OGLConfig.h @@ -62,8 +62,6 @@ struct VideoConfig EsPointSizeType SupportedESPointSize; EsTexbufType SupportedESTextureBuffer; bool bSupportsTextureStorage; - bool bSupports2DTextureStorageMultisample; - bool bSupports3DTextureStorageMultisample; bool bSupportsConservativeDepth; bool bSupportsImageLoadStore; bool bSupportsAniso; From 3f143d1bc979421afadcee9debe7988c887a1970 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 5 Mar 2023 22:02:42 -0800 Subject: [PATCH 3/9] OGL: Only specify precision for sampler2DMSArray when it is defined See https://bugs.dolphin-emu.org/issues/13198 --- Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index b7dba51cf2..f13ca7eb8e 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -722,6 +722,9 @@ void ProgramShaderCache::CreateHeader() break; } + // The sampler2DMSArray keyword is reserved in GLSL ES 3.0 and 3.1, but is available in 3.2. + const bool use_multisample_2d_array_precision = v >= GlslEs320; + std::string shader_shuffle_string; if (g_ogl_config.bSupportsKHRShaderSubgroup) { @@ -849,7 +852,7 @@ void ProgramShaderCache::CreateHeader() (is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ? "precision highp usamplerBuffer;" : "", - v > GlslEs300 ? "precision highp sampler2DMSArray;" : "", + use_multisample_2d_array_precision ? "precision highp sampler2DMSArray;" : "", v >= GlslEs310 ? "precision highp image2DArray;" : ""); } From 8b0bd31e72beaacff3be2dbd9cb44208fc4b0442 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 5 Mar 2023 22:03:26 -0800 Subject: [PATCH 4/9] OGL: Use GL_OES_texture_storage_multisample_2d_array when supported See https://bugs.dolphin-emu.org/issues/13198 --- Source/Core/VideoBackends/OGL/OGLConfig.cpp | 8 ++++++++ Source/Core/VideoBackends/OGL/OGLConfig.h | 8 ++++++++ Source/Core/VideoBackends/OGL/OGLTexture.cpp | 8 +++++++- .../Core/VideoBackends/OGL/ProgramShaderCache.cpp | 15 +++++++++++++-- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp index 575993c8bf..e5e1bff83f 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp +++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp @@ -333,6 +333,7 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_ogl_config.bSupportsDebug = GLExtensions::Supports("GL_KHR_debug") || GLExtensions::Supports("GL_ARB_debug_output"); g_ogl_config.bSupportsTextureStorage = GLExtensions::Supports("GL_ARB_texture_storage"); + g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageNone; g_ogl_config.bSupportsImageLoadStore = GLExtensions::Supports("GL_ARB_shader_image_load_store"); g_ogl_config.bSupportsConservativeDepth = GLExtensions::Supports("GL_ARB_conservative_depth"); g_ogl_config.bSupportsAniso = GLExtensions::Supports("GL_EXT_texture_filter_anisotropic"); @@ -412,6 +413,8 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true; g_ogl_config.bSupportsMSAA = true; g_ogl_config.bSupportsTextureStorage = true; + if (GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array")) + g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageOes; g_Config.backend_info.bSupportsBitfield = true; g_Config.backend_info.bSupportsDynamicSamplerIndexing = g_ogl_config.bSupportsAEP; } @@ -433,6 +436,7 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_ogl_config.bSupportsDebug = true; g_ogl_config.bSupportsMSAA = true; g_ogl_config.bSupportsTextureStorage = true; + g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore; g_Config.backend_info.bSupportsBitfield = true; g_Config.backend_info.bSupportsDynamicSamplerIndexing = true; g_Config.backend_info.bSupportsSettingObjectNames = true; @@ -440,6 +444,9 @@ bool PopulateConfig(GLContext* m_main_gl_context) } else { + if (GLExtensions::Supports("GL_ARB_texture_storage_multisample")) + g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore; + if (GLExtensions::Version() < 300) { PanicAlertFmtT("GPU: OGL ERROR: Need at least GLSL 1.30\n" @@ -486,6 +493,7 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_ogl_config.eSupportedGLSLVersion = Glsl430; } g_ogl_config.bSupportsTextureStorage = true; + g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore; g_ogl_config.bSupportsImageLoadStore = true; g_Config.backend_info.bSupportsSSAA = true; g_Config.backend_info.bSupportsSettingObjectNames = true; diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.h b/Source/Core/VideoBackends/OGL/OGLConfig.h index 8ee717f0b3..4929901b09 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.h +++ b/Source/Core/VideoBackends/OGL/OGLConfig.h @@ -45,6 +45,13 @@ enum class EsFbFetchType FbFetchArm, }; +enum class MultisampleTexStorageType +{ + TexStorageNone, + TexStorageCore, + TexStorageOes, +}; + // ogl-only config, so not in VideoConfig.h struct VideoConfig { @@ -62,6 +69,7 @@ struct VideoConfig EsPointSizeType SupportedESPointSize; EsTexbufType SupportedESTextureBuffer; bool bSupportsTextureStorage; + MultisampleTexStorageType SupportedMultisampleTexStorage; bool bSupportsConservativeDepth; bool bSupportsImageLoadStore; bool bSupportsAniso; diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index ad0e32bb39..f2b0081d86 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -130,12 +130,18 @@ OGLTexture::OGLTexture(const TextureConfig& tex_config, std::string_view name) GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true); if (tex_config.IsMultisampled()) { - if (g_ogl_config.bSupportsTextureStorage) + ASSERT(g_ogl_config.bSupportsMSAA); + if (g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone) + { glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, m_config.height, m_config.layers, GL_FALSE); + } else + { + ASSERT(!g_ogl_config.bIsES); glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, m_config.height, m_config.layers, GL_FALSE); + } } else if (g_ogl_config.bSupportsTextureStorage) { diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index f13ca7eb8e..a149c9fad0 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -722,8 +722,12 @@ void ProgramShaderCache::CreateHeader() break; } - // The sampler2DMSArray keyword is reserved in GLSL ES 3.0 and 3.1, but is available in 3.2. - const bool use_multisample_2d_array_precision = v >= GlslEs320; + // The sampler2DMSArray keyword is reserved in GLSL ES 3.0 and 3.1, but is available in 3.2 and + // with GL_OES_texture_storage_multisample_2d_array for 3.1. + // See https://bugs.dolphin-emu.org/issues/13198. + const bool use_multisample_2d_array_precision = + v >= GlslEs320 || + g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone; std::string shader_shuffle_string; if (g_ogl_config.bSupportsKHRShaderSubgroup) @@ -762,6 +766,7 @@ void ProgramShaderCache::CreateHeader() "{}\n" // shader thread shuffle "{}\n" // derivative control "{}\n" // query levels + "{}\n" // OES multisample texture storage // Precision defines for GLSL ES "{}\n" @@ -847,6 +852,12 @@ void ProgramShaderCache::CreateHeader() g_ActiveConfig.backend_info.bSupportsTextureQueryLevels ? "#extension GL_ARB_texture_query_levels : enable" : "", + // Note: GL_ARB_texture_storage_multisample doesn't have an #extension, as it doesn't + // need to change GLSL, but on GLES 3.1 sampler2DMSArray is a reserved keyword unless + // the extension is enabled. Thus, we don't need to check TexStorageCore/have an ARB version. + g_ogl_config.SupportedMultisampleTexStorage == MultisampleTexStorageType::TexStorageOes ? + "#extension GL_OES_texture_storage_multisample_2d_array : enable" : + "", is_glsles ? "precision highp float;" : "", is_glsles ? "precision highp int;" : "", is_glsles ? "precision highp sampler2DArray;" : "", (is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ? From 37a30a5e506107aac7ea1c2d6d215edde41019c2 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 17 Apr 2023 03:43:29 +0200 Subject: [PATCH 5/9] IOS/WiiSockMan: Remove declaration to nonexistent DecodeError(). --- Source/Core/Core/IOS/Network/Socket.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h index 2a2350d752..127e42bc72 100644 --- a/Source/Core/Core/IOS/Network/Socket.h +++ b/Source/Core/Core/IOS/Network/Socket.h @@ -252,7 +252,6 @@ public: }; static s32 GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw); - static char* DecodeError(s32 ErrorCode); static WiiSockMan& GetInstance() { From b2ee95805864168e38fe79845ba071d6fd60868e Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 17 Apr 2023 04:38:48 +0200 Subject: [PATCH 6/9] IOS/WiiSockMan: Move instance to IOS Kernel. --- Source/Core/Core/IOS/IOS.cpp | 17 +++++- Source/Core/Core/IOS/IOS.h | 5 ++ Source/Core/Core/IOS/Network/IP/Top.cpp | 60 +++++++++---------- .../Core/Core/IOS/Network/KD/NetKDRequest.cpp | 8 ++- Source/Core/Core/IOS/Network/SSL.cpp | 12 ++-- Source/Core/Core/IOS/Network/Socket.cpp | 28 +++++---- Source/Core/Core/IOS/Network/Socket.h | 26 ++++---- Source/Core/Core/State.cpp | 2 +- .../Core/DolphinQt/Debugger/NetworkWidget.cpp | 20 +++++-- 9 files changed, 104 insertions(+), 74 deletions(-) diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 82f51dac33..bc09da7837 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -308,6 +308,7 @@ Kernel::~Kernel() { std::lock_guard lock(m_device_map_mutex); m_device_map.clear(); + m_socket_manager.reset(); } if (m_is_responsible_for_nand_root) @@ -363,6 +364,11 @@ std::shared_ptr Kernel::GetES() return std::static_pointer_cast(m_device_map.at("/dev/es")); } +std::shared_ptr Kernel::GetSocketManager() +{ + return m_socket_manager; +} + // Since we don't have actual processes, we keep track of only the PPC's UID/GID. // These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC). void Kernel::SetUidForPPC(u32 uid) @@ -562,6 +568,11 @@ void Kernel::AddStaticDevices() AddDevice(std::make_unique(*this, "/dev/sdio/slot1")); // Network modules + if (HasFeature(features, Feature::KD) || HasFeature(features, Feature::SO) || + HasFeature(features, Feature::SSL)) + { + m_socket_manager = std::make_shared(); + } if (HasFeature(features, Feature::KD)) { AddDevice(std::make_unique(*this, "/dev/net/kd/request")); @@ -825,7 +836,8 @@ void Kernel::UpdateDevices() void Kernel::UpdateWantDeterminism(const bool new_want_determinism) { - WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism); + if (m_socket_manager) + m_socket_manager->UpdateWantDeterminism(new_want_determinism); for (const auto& device : m_device_map) device.second->UpdateWantDeterminism(new_want_determinism); } @@ -846,6 +858,9 @@ void Kernel::DoState(PointerWrap& p) if (m_title_id == Titles::MIOS) return; + if (m_socket_manager) + m_socket_manager->DoState(p); + for (const auto& entry : m_device_map) entry.second->DoState(p); diff --git a/Source/Core/Core/IOS/IOS.h b/Source/Core/Core/IOS/IOS.h index a9ca0ec0f5..878bb56ccc 100644 --- a/Source/Core/Core/IOS/IOS.h +++ b/Source/Core/Core/IOS/IOS.h @@ -35,6 +35,7 @@ class FileSystem; class Device; class ESDevice; class FSDevice; +class WiiSockMan; struct Request; struct OpenRequest; @@ -130,6 +131,9 @@ public: std::shared_ptr GetFSDevice(); std::shared_ptr GetES(); + // This is only available on an EmulationKernel if the IOS features require it. + std::shared_ptr GetSocketManager(); + void EnqueueIPCRequest(u32 address); void EnqueueIPCReply(const Request& request, s32 return_value, s64 cycles_in_future = 0, CoreTiming::FromThread from = CoreTiming::FromThread::CPU); @@ -179,6 +183,7 @@ protected: IOSC m_iosc; std::shared_ptr m_fs; + std::shared_ptr m_socket_manager; }; // HLE for an IOS tied to emulation: base kernel which may have additional modules loaded. diff --git a/Source/Core/Core/IOS/Network/IP/Top.cpp b/Source/Core/Core/IOS/Network/IP/Top.cpp index 27487918d0..261b6db9b7 100644 --- a/Source/Core/Core/IOS/Network/IP/Top.cpp +++ b/Source/Core/Core/IOS/Network/IP/Top.cpp @@ -77,7 +77,6 @@ NetIPTopDevice::NetIPTopDevice(Kernel& ios, const std::string& device_name) void NetIPTopDevice::DoState(PointerWrap& p) { Device::DoState(p); - WiiSockMan::GetInstance().DoState(p); } static int inet_pton(const char* src, unsigned char* dst) @@ -371,7 +370,7 @@ void NetIPTopDevice::Update() m_async_replies.pop(); } } - WiiSockMan::GetInstance().Update(); + m_ios.GetSocketManager()->Update(); } IPCReply NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request) @@ -389,8 +388,7 @@ IPCReply NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request) const u32 type = memory.Read_U32(request.buffer_in + 4); const u32 prot = memory.Read_U32(request.buffer_in + 8); - WiiSockMan& sm = WiiSockMan::GetInstance(); - const s32 return_value = sm.NewSocket(af, type, prot); + const s32 return_value = m_ios.GetSocketManager()->NewSocket(af, type, prot); INFO_LOG_FMT(IOS_NET, "IOCTL_SO_SOCKET " "Socket: {:08x} ({},{},{}), BufferIn: ({:08x}, {}), BufferOut: ({:08x}, {})", @@ -407,8 +405,7 @@ IPCReply NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request) const u32 pf = memory.Read_U32(request.buffer_in); - WiiSockMan& sm = WiiSockMan::GetInstance(); - const s32 return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP); + const s32 return_value = m_ios.GetSocketManager()->NewSocket(pf, SOCK_RAW, IPPROTO_ICMP); INFO_LOG_FMT(IOS_NET, "IOCTL_SO_ICMPSOCKET({:x}) {}", pf, return_value); return IPCReply(return_value); } @@ -419,8 +416,7 @@ IPCReply NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request) auto& memory = system.GetMemory(); const u32 fd = memory.Read_U32(request.buffer_in); - WiiSockMan& sm = WiiSockMan::GetInstance(); - const s32 return_value = sm.DeleteSocket(fd); + const s32 return_value = m_ios.GetSocketManager()->DeleteSocket(fd); const char* const close_fn = request.request == IOCTL_SO_ICMPCLOSE ? "IOCTL_SO_ICMPCLOSE" : "IOCTL_SO_CLOSE"; @@ -435,8 +431,7 @@ std::optional NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest& auto& memory = system.GetMemory(); const u32 fd = memory.Read_U32(request.buffer_in); - WiiSockMan& sm = WiiSockMan::GetInstance(); - sm.DoSock(fd, request, static_cast(request.request)); + m_ios.GetSocketManager()->DoSock(fd, request, static_cast(request.request)); return std::nullopt; } @@ -454,8 +449,7 @@ IPCReply NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request) const u32 fd = memory.Read_U32(request.buffer_in); const u32 how = memory.Read_U32(request.buffer_in + 4); - WiiSockMan& sm = WiiSockMan::GetInstance(); - const s32 return_value = sm.ShutdownSocket(fd, how); + const s32 return_value = m_ios.GetSocketManager()->ShutdownSocket(fd, how); INFO_LOG_FMT(IOS_NET, "IOCTL_SO_SHUTDOWN(fd={}, how={}) = {}", fd, how, return_value); return IPCReply(return_value); @@ -468,10 +462,11 @@ IPCReply NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request) u32 fd = memory.Read_U32(request.buffer_in); u32 BACKLOG = memory.Read_U32(request.buffer_in + 0x04); - u32 ret = listen(WiiSockMan::GetInstance().GetHostSocket(fd), BACKLOG); + auto socket_manager = m_ios.GetSocketManager(); + u32 ret = listen(socket_manager->GetHostSocket(fd), BACKLOG); request.Log(GetDeviceName(), Common::Log::LogType::IOS_WC24); - return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false)); + return IPCReply(socket_manager->GetNetErrorCode(ret, "SO_LISTEN", false)); } IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request) @@ -492,16 +487,17 @@ IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request) u8 optval[20]; u32 optlen = 4; - int ret = getsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname, - (char*)&optval, (socklen_t*)&optlen); - const s32 return_value = WiiSockMan::GetNetErrorCode(ret, "SO_GETSOCKOPT", false); + auto socket_manager = m_ios.GetSocketManager(); + int ret = getsockopt(socket_manager->GetHostSocket(fd), nat_level, nat_optname, (char*)&optval, + (socklen_t*)&optlen); + const s32 return_value = socket_manager->GetNetErrorCode(ret, "SO_GETSOCKOPT", false); memory.Write_U32(optlen, request.buffer_out + 0xC); memory.CopyToEmu(request.buffer_out + 0x10, optval, optlen); if (optname == SO_ERROR) { - s32 last_error = WiiSockMan::GetInstance().GetLastNetError(); + s32 last_error = socket_manager->GetLastNetError(); memory.Write_U32(sizeof(s32), request.buffer_out + 0xC); memory.Write_U32(last_error, request.buffer_out + 0x10); @@ -543,9 +539,10 @@ IPCReply NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request) const int nat_level = MapWiiSockOptLevelToNative(level); const int nat_optname = MapWiiSockOptNameToNative(optname); - const int ret = setsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname, + auto socket_manager = m_ios.GetSocketManager(); + const int ret = setsockopt(socket_manager->GetHostSocket(fd), nat_level, nat_optname, reinterpret_cast(optval), optlen); - return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false)); + return IPCReply(socket_manager->GetNetErrorCode(ret, "SO_SETSOCKOPT", false)); } IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request) @@ -559,7 +556,7 @@ IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request) sockaddr sa; socklen_t sa_len = sizeof(sa); - const int ret = getsockname(WiiSockMan::GetInstance().GetHostSocket(fd), &sa, &sa_len); + const int ret = getsockname(m_ios.GetSocketManager()->GetHostSocket(fd), &sa, &sa_len); if (request.buffer_out_size < 2 + sizeof(sa.sa_data)) WARN_LOG_FMT(IOS_NET, "IOCTL_SO_GETSOCKNAME output buffer is too small. Truncating"); @@ -586,7 +583,7 @@ IPCReply NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request) sockaddr sa; socklen_t sa_len = sizeof(sa); - const int ret = getpeername(WiiSockMan::GetInstance().GetHostSocket(fd), &sa, &sa_len); + const int ret = getpeername(m_ios.GetSocketManager()->GetHostSocket(fd), &sa, &sa_len); if (request.buffer_out_size < 2 + sizeof(sa.sa_data)) WARN_LOG_FMT(IOS_NET, "IOCTL_SO_GETPEERNAME output buffer is too small. Truncating"); @@ -677,7 +674,7 @@ IPCReply NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request) std::optional NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request) { - WiiSockMan& sm = WiiSockMan::GetInstance(); + auto sm = m_ios.GetSocketManager(); if (!request.buffer_in || !request.buffer_out) return IPCReply(-SO_EINVAL); @@ -700,7 +697,7 @@ std::optional NetIPTopDevice::HandlePollRequest(const IOCtlRequest& re for (u32 i = 0; i < nfds; ++i) { const s32 wii_fd = memory.Read_U32(request.buffer_out + 0xc * i); - ufds[i].fd = sm.GetHostSocket(wii_fd); // fd + ufds[i].fd = sm->GetHostSocket(wii_fd); // fd const int events = memory.Read_U32(request.buffer_out + 0xc * i + 4); // events ufds[i].revents = 0; @@ -717,7 +714,7 @@ std::optional NetIPTopDevice::HandlePollRequest(const IOCtlRequest& re } // Prevents blocking emulation on a blocking poll - sm.AddPollCommand({request.address, request.buffer_out, std::move(ufds), timeout}); + sm->AddPollCommand({request.address, request.buffer_out, std::move(ufds), timeout}); return std::nullopt; } @@ -1014,8 +1011,7 @@ std::optional NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest& auto& memory = system.GetMemory(); u32 fd = memory.Read_U32(request.in_vectors[1].address); - WiiSockMan& sm = WiiSockMan::GetInstance(); - sm.DoSock(fd, request, IOCTLV_SO_SENDTO); + m_ios.GetSocketManager()->DoSock(fd, request, IOCTLV_SO_SENDTO); return std::nullopt; } @@ -1025,8 +1021,7 @@ std::optional NetIPTopDevice::HandleRecvFromRequest(const IOCtlVReques auto& memory = system.GetMemory(); u32 fd = memory.Read_U32(request.in_vectors[0].address); - WiiSockMan& sm = WiiSockMan::GetInstance(); - sm.DoSock(fd, request, IOCTLV_SO_RECVFROM); + m_ios.GetSocketManager()->DoSock(fd, request, IOCTLV_SO_RECVFROM); return std::nullopt; } @@ -1181,11 +1176,12 @@ IPCReply NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request) icmp_length = 22; } - int ret = icmp_echo_req(WiiSockMan::GetInstance().GetHostSocket(fd), &addr, data, icmp_length); + auto socket_manager = m_ios.GetSocketManager(); + int ret = icmp_echo_req(socket_manager->GetHostSocket(fd), &addr, data, icmp_length); if (ret == icmp_length) { - ret = icmp_echo_rep(WiiSockMan::GetInstance().GetHostSocket(fd), &addr, - static_cast(timeout), icmp_length); + ret = icmp_echo_rep(socket_manager->GetHostSocket(fd), &addr, static_cast(timeout), + icmp_length); } // TODO proper error codes diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp index cc1469bdfa..fd7988cf44 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp @@ -161,7 +161,9 @@ NetKDRequestDevice::NetKDRequestDevice(Kernel& ios, const std::string& device_na NetKDRequestDevice::~NetKDRequestDevice() { - WiiSockMan::GetInstance().Clean(); + auto socket_manager = m_ios.GetSocketManager(); + if (socket_manager) + socket_manager->Clean(); } void NetKDRequestDevice::Update() @@ -348,7 +350,7 @@ std::optional NetKDRequestDevice::IOCtl(const IOCtlRequest& request) case IOCTL_NWC24_CLEANUP_SOCKET: INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_CLEANUP_SOCKET"); - WiiSockMan::GetInstance().Clean(); + m_ios.GetSocketManager()->Clean(); break; case IOCTL_NWC24_LOCK_SOCKET: // WiiMenu @@ -452,7 +454,7 @@ std::optional NetKDRequestDevice::IOCtl(const IOCtlRequest& request) // SOGetInterfaceOpt(0xfffe,0xc001); // DHCP lease time remaining? // SOGetInterfaceOpt(0xfffe,0x1003); // Error // Call /dev/net/ip/top 0x1b (SOCleanup), it closes all sockets - WiiSockMan::GetInstance().Clean(); + m_ios.GetSocketManager()->Clean(); return_value = IPC_SUCCESS; break; } diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp index a26d2451db..bbd182347a 100644 --- a/Source/Core/Core/IOS/Network/SSL.cpp +++ b/Source/Core/Core/IOS/Network/SSL.cpp @@ -496,8 +496,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request) WII_SSL* ssl = &_SSL[sslID]; mbedtls_ssl_setup(&ssl->ctx, &ssl->config); ssl->sockfd = memory.Read_U32(BufferOut2); - WiiSockMan& sm = WiiSockMan::GetInstance(); - ssl->hostfd = sm.GetHostSocket(ssl->sockfd); + ssl->hostfd = m_ios.GetSocketManager()->GetHostSocket(ssl->sockfd); INFO_LOG_FMT(IOS_SSL, "IOCTLV_NET_SSL_CONNECT socket = {}", ssl->sockfd); mbedtls_ssl_set_bio(&ssl->ctx, ssl, SSLSendWithoutSNI, SSLRecv, nullptr); WriteReturnValue(SSL_OK, BufferIn); @@ -520,8 +519,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request) int sslID = memory.Read_U32(BufferOut) - 1; if (IsSSLIDValid(sslID)) { - WiiSockMan& sm = WiiSockMan::GetInstance(); - sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE); + m_ios.GetSocketManager()->DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE); return std::nullopt; } else @@ -535,8 +533,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request) const int sslID = memory.Read_U32(BufferOut) - 1; if (IsSSLIDValid(sslID)) { - WiiSockMan& sm = WiiSockMan::GetInstance(); - sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE); + m_ios.GetSocketManager()->DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE); return std::nullopt; } else @@ -559,8 +556,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request) int sslID = memory.Read_U32(BufferOut) - 1; if (IsSSLIDValid(sslID)) { - WiiSockMan& sm = WiiSockMan::GetInstance(); - sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ); + m_ios.GetSocketManager()->DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ); return std::nullopt; } else diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index ff60c09b20..9e1b45097e 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -85,6 +85,10 @@ static s32 TranslateErrorCode(s32 native_error, bool is_rw) } } +WiiSockMan::WiiSockMan() = default; + +WiiSockMan::~WiiSockMan() = default; + // Don't use string! (see https://github.com/dolphin-emu/dolphin/pull/3143) s32 WiiSockMan::GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw) { @@ -96,7 +100,7 @@ s32 WiiSockMan::GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw) if (ret >= 0) { - WiiSockMan::GetInstance().SetLastNetError(ret); + SetLastNetError(ret); return ret; } @@ -104,7 +108,7 @@ s32 WiiSockMan::GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw) Common::DecodeNetworkError(error_code), ret); const s32 return_value = TranslateErrorCode(error_code, is_rw); - WiiSockMan::GetInstance().SetLastNetError(return_value); + SetLastNetError(return_value); return return_value; } @@ -158,7 +162,7 @@ s32 WiiSocket::Shutdown(u32 how) // Adjust pending operations // Values based on https://dolp.in/pr8758 hwtest - const s32 ret = WiiSockMan::GetNetErrorCode(shutdown(fd, how), "SO_SHUTDOWN", false); + const s32 ret = m_socket_manager.GetNetErrorCode(shutdown(fd, how), "SO_SHUTDOWN", false); const bool shut_read = how == 0 || how == 2; const bool shut_write = how == 1 || how == 2; for (auto& op : pending_sockops) @@ -198,11 +202,11 @@ s32 WiiSocket::CloseFd() if (fd >= 0) { s32 ret = closesocket(fd); - ReturnValue = WiiSockMan::GetNetErrorCode(ret, "CloseFd", false); + ReturnValue = m_socket_manager.GetNetErrorCode(ret, "CloseFd", false); } else { - ReturnValue = WiiSockMan::GetNetErrorCode(EITHER(WSAENOTSOCK, EBADF), "CloseFd", false); + ReturnValue = m_socket_manager.GetNetErrorCode(EITHER(WSAENOTSOCK, EBADF), "CloseFd", false); } fd = -1; @@ -273,7 +277,7 @@ void WiiSocket::Update(bool read, bool write, bool except) WiiSockMan::ToNativeAddrIn(addr, &local_name); int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name)); - ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_BIND", false); + ReturnValue = m_socket_manager.GetNetErrorCode(ret, "SO_BIND", false); INFO_LOG_FMT(IOS_NET, "IOCTL_SO_BIND ({:08X}, {}:{}) = {}", wii_fd, inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port), ret); @@ -286,7 +290,7 @@ void WiiSocket::Update(bool read, bool write, bool except) WiiSockMan::ToNativeAddrIn(addr, &local_name); int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name)); - ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_CONNECT", false); + ReturnValue = m_socket_manager.GetNetErrorCode(ret, "SO_CONNECT", false); UpdateConnectingState(ReturnValue); INFO_LOG_FMT(IOS_NET, "IOCTL_SO_CONNECT ({:08x}, {}:{}) = {}", wii_fd, @@ -312,7 +316,7 @@ void WiiSocket::Update(bool read, bool write, bool except) ret = static_cast(accept(fd, nullptr, nullptr)); } - ReturnValue = WiiSockMan::GetInstance().AddSocket(ret, true); + ReturnValue = m_socket_manager.AddSocket(ret, true); ioctl.Log("IOCTL_SO_ACCEPT", Common::Log::LogType::IOS_NET); break; @@ -593,7 +597,7 @@ void WiiSocket::Update(bool read, bool write, bool except) auto* to = has_destaddr ? reinterpret_cast(&local_name) : nullptr; socklen_t tolen = has_destaddr ? sizeof(sockaddr) : 0; const int ret = sendto(fd, data, BufferInSize, flags, to, tolen); - ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true); + ReturnValue = m_socket_manager.GetNetErrorCode(ret, "SO_SENDTO", true); if (ret > 0) system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite(data, ret, fd, to); @@ -651,8 +655,8 @@ void WiiSocket::Update(bool read, bool write, bool except) auto* from = BufferOutSize2 ? reinterpret_cast(&local_name) : nullptr; socklen_t* fromlen = BufferOutSize2 ? &addrlen : nullptr; const int ret = recvfrom(fd, data, data_len, flags, from, fromlen); - ReturnValue = - WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true); + ReturnValue = m_socket_manager.GetNetErrorCode( + ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true); if (ret > 0) system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead(data, ret, fd, from); @@ -862,7 +866,7 @@ s32 WiiSockMan::AddSocket(s32 fd, bool is_rw) } else { - WiiSocket& sock = WiiSockets[wii_fd]; + WiiSocket& sock = WiiSockets.emplace(wii_fd, *this).first->second; sock.SetFd(fd); sock.SetWiiFd(wii_fd); Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->OnNewSocket(fd); diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h index 127e42bc72..6c236e38b3 100644 --- a/Source/Core/Core/IOS/Network/Socket.h +++ b/Source/Core/Core/IOS/Network/Socket.h @@ -174,10 +174,12 @@ struct WiiSockAddrIn }; #pragma pack(pop) +class WiiSockMan; + class WiiSocket { public: - WiiSocket() = default; + explicit WiiSocket(WiiSockMan& socket_manager) : m_socket_manager(socket_manager) {} WiiSocket(const WiiSocket&) = delete; WiiSocket(WiiSocket&&) = default; ~WiiSocket(); @@ -225,6 +227,8 @@ private: bool IsValid() const { return fd >= 0; } bool IsTCP() const; + WiiSockMan& m_socket_manager; + s32 fd = -1; s32 wii_fd = -1; bool nonBlock = false; @@ -251,13 +255,15 @@ public: s64 timeout = 0; }; - static s32 GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw); + WiiSockMan(); + WiiSockMan(const WiiSockMan&) = delete; + WiiSockMan& operator=(const WiiSockMan&) = delete; + WiiSockMan(WiiSockMan&&) = delete; + WiiSockMan& operator=(WiiSockMan&&) = delete; + ~WiiSockMan(); + + s32 GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw); - static WiiSockMan& GetInstance() - { - static WiiSockMan instance; // Guaranteed to be destroyed. - return instance; // Instantiated on first use. - } void Update(); static void ToNativeAddrIn(const u8* from, sockaddr_in* to); static void ToWiiAddrIn(const sockaddr_in& from, u8* to, @@ -295,12 +301,6 @@ public: void UpdateWantDeterminism(bool want); private: - WiiSockMan() = default; - WiiSockMan(const WiiSockMan&) = delete; - WiiSockMan& operator=(const WiiSockMan&) = delete; - WiiSockMan(WiiSockMan&&) = delete; - WiiSockMan& operator=(WiiSockMan&&) = delete; - void UpdatePollCommands(); std::unordered_map WiiSockets; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index a82da71663..c298dd121e 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -96,7 +96,7 @@ static size_t s_state_writes_in_queue; static std::condition_variable s_state_write_queue_is_empty; // Don't forget to increase this after doing changes on the savestate system -constexpr u32 STATE_VERSION = 161; // Last changed in PR 11655 +constexpr u32 STATE_VERSION = 162; // Last changed in PR 11767 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list, diff --git a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp index 6439a061ba..b9504e64ff 100644 --- a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp @@ -24,8 +24,10 @@ #include "Common/FileUtil.h" #include "Core/Config/MainSettings.h" +#include "Core/Core.h" #include "Core/IOS/Network/SSL.h" #include "Core/IOS/Network/Socket.h" +#include "Core/System.h" #include "DolphinQt/Host.h" #include "DolphinQt/Settings.h" @@ -95,9 +97,8 @@ QTableWidgetItem* GetSocketState(s32 host_fd) return new QTableWidgetItem(QTableWidget::tr("Unbound")); } -QTableWidgetItem* GetSocketBlocking(s32 wii_fd) +static QTableWidgetItem* GetSocketBlocking(const IOS::HLE::WiiSockMan& socket_manager, s32 wii_fd) { - const auto& socket_manager = IOS::HLE::WiiSockMan::GetInstance(); if (socket_manager.GetHostSocket(wii_fd) < 0) return new QTableWidgetItem(); const bool is_blocking = socket_manager.IsSocketBlocking(wii_fd); @@ -238,16 +239,27 @@ void NetworkWidget::Update() if (!isVisible()) return; + // needed because there's a race condition on the IOS instance otherwise + Core::CPUThreadGuard guard(Core::System::GetInstance()); + + auto* ios = IOS::HLE::GetIOS(); + if (!ios) + return; + + auto socket_manager = ios->GetSocketManager(); + if (!socket_manager) + return; + m_socket_table->setRowCount(0); for (u32 wii_fd = 0; wii_fd < IOS::HLE::WII_SOCKET_FD_MAX; wii_fd++) { m_socket_table->insertRow(wii_fd); - const s32 host_fd = IOS::HLE::WiiSockMan::GetInstance().GetHostSocket(wii_fd); + const s32 host_fd = socket_manager->GetHostSocket(wii_fd); m_socket_table->setItem(wii_fd, 0, new QTableWidgetItem(QString::number(wii_fd))); m_socket_table->setItem(wii_fd, 1, GetSocketDomain(host_fd)); m_socket_table->setItem(wii_fd, 2, GetSocketType(host_fd)); m_socket_table->setItem(wii_fd, 3, GetSocketState(host_fd)); - m_socket_table->setItem(wii_fd, 4, GetSocketBlocking(wii_fd)); + m_socket_table->setItem(wii_fd, 4, GetSocketBlocking(*socket_manager, wii_fd)); m_socket_table->setItem(wii_fd, 5, GetSocketName(host_fd)); } m_socket_table->resizeColumnsToContents(); From 9ba26670b874d14110390f6b8faad4cac98dffca Mon Sep 17 00:00:00 2001 From: get <45425365+Minty-Meeo@users.noreply.github.com> Date: Sun, 16 Apr 2023 02:21:18 -0500 Subject: [PATCH 7/9] Do not use magic numbers for RAM sizes/masks in PPCCache Memory Override + Write-Back Cache emulation = game crash --- Source/Core/Core/PowerPC/PPCCache.cpp | 68 ++++++++++++++++----------- Source/Core/Core/PowerPC/PPCCache.h | 7 +-- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCCache.cpp b/Source/Core/Core/PowerPC/PPCCache.cpp index d159eba1f2..03e5ef3a1a 100644 --- a/Source/Core/Core/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/PowerPC/PPCCache.cpp @@ -3,6 +3,7 @@ #include "Core/PowerPC/PPCCache.h" +#include #include #include "Common/ChunkFile.h" @@ -99,9 +100,9 @@ void Cache::Reset() valid.fill(0); plru.fill(0); modified.fill(0); - lookup_table.fill(0xFF); - lookup_table_ex.fill(0xFF); - lookup_table_vmem.fill(0xFF); + std::fill(lookup_table.begin(), lookup_table.end(), 0xFF); + std::fill(lookup_table_ex.begin(), lookup_table_ex.end(), 0xFF); + std::fill(lookup_table_vmem.begin(), lookup_table_vmem.end(), 0xFF); } void InstructionCache::Reset() @@ -112,8 +113,14 @@ void InstructionCache::Reset() void Cache::Init() { + auto& system = Core::System::GetInstance(); + auto& memory = system.GetMemory(); + data.fill({}); addrs.fill({}); + lookup_table.resize(memory.GetRamSize() >> 5); + lookup_table_ex.resize(memory.GetExRamSize() >> 5); + lookup_table_vmem.resize(memory.GetFakeVMemSize() >> 5); Reset(); } @@ -160,6 +167,9 @@ void Cache::FlushAll() void Cache::Invalidate(u32 addr) { + auto& system = Core::System::GetInstance(); + auto& memory = system.GetMemory(); + auto [set, way] = GetCache(addr, true); if (way == 0xff) @@ -168,11 +178,11 @@ void Cache::Invalidate(u32 addr) if (valid[set] & (1U << way)) { if (addrs[set][way] & CACHE_VMEM_BIT) - lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff; else if (addrs[set][way] & CACHE_EXRAM_BIT) - lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff; + lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff; else - lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff; valid[set] &= ~(1U << way); modified[set] &= ~(1U << way); @@ -195,11 +205,11 @@ void Cache::Flush(u32 addr) memory.CopyToEmu((addr & ~0x1f), reinterpret_cast(data[set][way].data()), 32); if (addrs[set][way] & CACHE_VMEM_BIT) - lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff; else if (addrs[set][way] & CACHE_EXRAM_BIT) - lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff; + lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff; else - lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff; valid[set] &= ~(1U << way); modified[set] &= ~(1U << way); @@ -222,15 +232,15 @@ std::pair Cache::GetCache(u32 addr, bool locked) if (addr & CACHE_VMEM_BIT) { - way = lookup_table_vmem[(addr >> 5) & 0xfffff]; + way = lookup_table_vmem[(addr & memory.GetFakeVMemMask()) >> 5]; } else if (addr & CACHE_EXRAM_BIT) { - way = lookup_table_ex[(addr >> 5) & 0x1fffff]; + way = lookup_table_ex[(addr & memory.GetExRamMask()) >> 5]; } else { - way = lookup_table[(addr >> 5) & 0xfffff]; + way = lookup_table[(addr & memory.GetRamMask()) >> 5]; } // load to the cache @@ -249,22 +259,22 @@ std::pair Cache::GetCache(u32 addr, bool locked) memory.CopyToEmu(addrs[set][way], reinterpret_cast(data[set][way].data()), 32); if (addrs[set][way] & CACHE_VMEM_BIT) - lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff; else if (addrs[set][way] & CACHE_EXRAM_BIT) - lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff; + lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff; else - lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff; } // load memory.CopyFromEmu(reinterpret_cast(data[set][way].data()), (addr & ~0x1f), 32); if (addr & CACHE_VMEM_BIT) - lookup_table_vmem[(addr >> 5) & 0xfffff] = way; + lookup_table_vmem[(addr & memory.GetFakeVMemMask()) >> 5] = way; else if (addr & CACHE_EXRAM_BIT) - lookup_table_ex[(addr >> 5) & 0x1fffff] = way; + lookup_table_ex[(addr & memory.GetExRamMask()) >> 5] = way; else - lookup_table[(addr >> 5) & 0xfffff] = way; + lookup_table[(addr & memory.GetRamMask()) >> 5] = way; addrs[set][way] = addr; valid[set] |= (1 << way); @@ -341,6 +351,9 @@ void Cache::Write(u32 addr, const void* buffer, u32 len, bool locked) void Cache::DoState(PointerWrap& p) { + auto& system = Core::System::GetInstance(); + auto& memory = system.GetMemory(); + if (p.IsReadMode()) { // Clear valid parts of the lookup tables (this is done instead of using fill(0xff) to avoid @@ -352,11 +365,11 @@ void Cache::DoState(PointerWrap& p) if ((valid[set] & (1 << way)) != 0) { if (addrs[set][way] & CACHE_VMEM_BIT) - lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff; else if (addrs[set][way] & CACHE_EXRAM_BIT) - lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff; + lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff; else - lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff; } } } @@ -378,11 +391,11 @@ void Cache::DoState(PointerWrap& p) if ((valid[set] & (1 << way)) != 0) { if (addrs[set][way] & CACHE_VMEM_BIT) - lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff; else if (addrs[set][way] & CACHE_EXRAM_BIT) - lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff; + lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff; else - lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff; } } } @@ -405,6 +418,7 @@ u32 InstructionCache::ReadInstruction(u32 addr) void InstructionCache::Invalidate(u32 addr) { auto& system = Core::System::GetInstance(); + auto& memory = system.GetMemory(); auto& ppc_state = system.GetPPCState(); if (!HID0(ppc_state).ICE || m_disable_icache) return; @@ -416,11 +430,11 @@ void InstructionCache::Invalidate(u32 addr) if (valid[set] & (1U << way)) { if (addrs[set][way] & CACHE_VMEM_BIT) - lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff; else if (addrs[set][way] & CACHE_EXRAM_BIT) - lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff; + lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff; else - lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff; + lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff; } } valid[set] = 0; diff --git a/Source/Core/Core/PowerPC/PPCCache.h b/Source/Core/Core/PowerPC/PPCCache.h index 49843c9b74..8214b116af 100644 --- a/Source/Core/Core/PowerPC/PPCCache.h +++ b/Source/Core/Core/PowerPC/PPCCache.h @@ -5,6 +5,7 @@ #include #include +#include #include "Common/CommonTypes.h" @@ -36,9 +37,9 @@ struct Cache // Note: This is only for performance purposes; this same data could be computed at runtime // from the tags and valid fields (and that's how it's done on the actual cache) - std::array lookup_table{}; - std::array lookup_table_ex{}; - std::array lookup_table_vmem{}; + std::vector lookup_table{}; + std::vector lookup_table_ex{}; + std::vector lookup_table_vmem{}; void Store(u32 addr); void Invalidate(u32 addr); From c9b26e3db207c8349238e328a4f8570d56f831aa Mon Sep 17 00:00:00 2001 From: get <45425365+Minty-Meeo@users.noreply.github.com> Date: Sun, 23 Apr 2023 02:53:23 -0500 Subject: [PATCH 8/9] Update mGBA submodule to 8739b22fbc90fdf0b4f6612ef9c0520f0ba44a51 --- Externals/mGBA/mgba | 2 +- Externals/mGBA/mgba.vcxproj | 7 +++++-- Source/Core/Core/HW/GBACore.cpp | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Externals/mGBA/mgba b/Externals/mGBA/mgba index 89f8873df3..8739b22fbc 160000 --- a/Externals/mGBA/mgba +++ b/Externals/mGBA/mgba @@ -1 +1 @@ -Subproject commit 89f8873df366a99dfdf40347f72e68763fb50bd9 +Subproject commit 8739b22fbc90fdf0b4f6612ef9c0520f0ba44a51 diff --git a/Externals/mGBA/mgba.vcxproj b/Externals/mGBA/mgba.vcxproj index 6f1d3b3f6f..d1235246e3 100644 --- a/Externals/mGBA/mgba.vcxproj +++ b/Externals/mGBA/mgba.vcxproj @@ -150,23 +150,25 @@ + + - - + + @@ -214,6 +216,7 @@ + diff --git a/Source/Core/Core/HW/GBACore.cpp b/Source/Core/Core/HW/GBACore.cpp index cb62141522..5c8ac7b275 100644 --- a/Source/Core/Core/HW/GBACore.cpp +++ b/Source/Core/Core/HW/GBACore.cpp @@ -305,7 +305,7 @@ CoreInfo Core::GetCoreInfo() const info.has_rom = !m_rom_path.empty(); info.has_ereader = info.is_gba && static_cast<::GBA*>(m_core->board)->memory.hw.devices & HW_EREADER; - m_core->desiredVideoDimensions(m_core, &info.width, &info.height); + m_core->currentVideoSize(m_core, &info.width, &info.height); info.game_title = m_game_title; return info; } @@ -392,7 +392,7 @@ void Core::SetSIODriver() void Core::SetVideoBuffer() { u32 width, height; - m_core->desiredVideoDimensions(m_core, &width, &height); + m_core->currentVideoSize(m_core, &width, &height); m_video_buffer.resize(width * height); m_core->setVideoBuffer(m_core, m_video_buffer.data(), width); if (auto host = m_host.lock()) From 00e4fc4b70001280d968348c3f5008c44c3391df Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Wed, 16 Nov 2022 04:31:01 +0100 Subject: [PATCH 9/9] Netplay: Check if save is readable before marking it for sync. --- Source/Core/Core/NetPlayServer.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 91f494f8df..2359dea9c3 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -1721,7 +1721,15 @@ std::optional NetPlayServer::CollectSaveSyncInfo() for (const u64 title : ios.GetES()->GetInstalledTitles()) { auto save = WiiSave::MakeNandStorage(sync_info.configured_fs.get(), title); - sync_info.wii_saves.emplace_back(title, std::move(save)); + if (save && save->ReadHeader().has_value() && save->ReadBkHeader().has_value() && + save->ReadFiles().has_value()) + { + sync_info.wii_saves.emplace_back(title, std::move(save)); + } + else + { + INFO_LOG_FMT(NETPLAY, "Skipping Wii save of title {:016x}.", title); + } } } else if (sync_info.game->GetPlatform() == DiscIO::Platform::WiiDisc ||