[cmake] MinGW builds; fix line endings; fix weird multiplayer lobby behavior (#2835)

MinGW builds perform pretty dramatically better than MSVC in my (brief) testing, getting 40% better FPS on my KVM than MSVC. How this will translate to the real world, who knows, but this is a really good target to have.

TODO: Add this to CI, potentially replace clang-cl

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2835
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
crueter 2025-10-26 17:28:14 +01:00
parent 470214412b
commit a0769ad835
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
12 changed files with 269 additions and 254 deletions

View file

@ -1201,7 +1201,7 @@ endif()
target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json RenderDoc::API MbedTLS::mbedcrypto MbedTLS::mbedtls)
if (MINGW)
target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY})
target_link_libraries(core PRIVATE ws2_32 mswsock wlanapi)
endif()
if (ENABLE_WEB_SERVICE)

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -7,43 +10,43 @@
#include "core/hle/service/server_manager.h"
#include "core/hle/service/sm/sm.h"
#include <vector>
namespace Service::MM {
enum class Module : u32 {
CPU = 0,
GPU = 1,
EMC = 2,
SYS_BUS = 3,
M_SELECT = 4,
NVDEC = 5,
NVENC = 6,
NVJPG = 7,
TEST = 8
};
class Session {
public:
Session(Module module_, u32 request_id_, bool is_auto_clear_event_) {
this->module = module_;
this->request_id = request_id_;
this->is_auto_clear_event = is_auto_clear_event_;
this->min = 0;
this->max = -1;
};
public:
Module module;
u32 request_id, min;
s32 max;
bool is_auto_clear_event;
#include <vector>
namespace Service::MM {
enum class Module : u32 {
CPU = 0,
GPU = 1,
EMC = 2,
SYS_BUS = 3,
M_SELECT = 4,
NVDEC = 5,
NVENC = 6,
NVJPG = 7,
TEST = 8
};
class Session {
public:
Session(Module module_, u32 request_id_, bool is_auto_clear_event_) {
this->module = module_;
this->request_id = request_id_;
this->is_auto_clear_event = is_auto_clear_event_;
this->min = 0;
this->max = -1;
};
public:
Module module;
u32 request_id, min;
s32 max;
bool is_auto_clear_event;
void SetAndWait(u32 min_, s32 max_) {
this->min = min_;
this->max = max_;
}
};
void SetAndWait(u32 min_, s32 max_) {
this->min = min_;
this->max = max_;
}
};
class MM_U final : public ServiceFramework<MM_U> {
public:
explicit MM_U(Core::System& system_) : ServiceFramework{system_, "mm:u"} {
@ -65,53 +68,53 @@ public:
private:
void InitializeOld(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
rp.Pop<u32>();
const auto event_clear_mode = rp.Pop<u32>();
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
rp.Pop<u32>();
const auto event_clear_mode = rp.Pop<u32>();
const bool is_auto_clear_event = event_clear_mode == 1;
sessions.push_back({module, request_id++, is_auto_clear_event});
const bool is_auto_clear_event = event_clear_mode == 1;
sessions.push_back({module, request_id++, is_auto_clear_event});
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void FinalizeOld(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
for (auto it = sessions.begin(); it != sessions.end(); ++it) {
if (it->module == module) {
sessions.erase(it);
break;
}
}
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
for (auto it = sessions.begin(); it != sessions.end(); ++it) {
if (it->module == module) {
sessions.erase(it);
break;
}
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SetAndWaitOld(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
const auto min = rp.Pop<u32>();
const auto max = rp.Pop<s32>();
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
const auto min = rp.Pop<u32>();
const auto max = rp.Pop<s32>();
for (auto& session : sessions) {
if (session.module == module) {
session.SetAndWait(min, max);
break;
}
}
for (auto& session : sessions) {
if (session.module == module) {
session.SetAndWait(min, max);
break;
}
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
@ -119,72 +122,72 @@ private:
void GetOld(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
for (const auto& session : sessions) {
if (session.module == module) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(session.min);
return;
}
}
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
for (const auto& session : sessions) {
if (session.module == module) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(session.min);
return;
}
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(0);
rb.Push<u32>(0);
}
void Initialize(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
rp.Pop<u32>();
const auto event_clear_mode = rp.Pop<u32>();
const bool is_auto_clear_event = event_clear_mode == 1;
sessions.push_back({module, request_id++, is_auto_clear_event});
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto module = rp.PopEnum<Module>();
rp.Pop<u32>();
const auto event_clear_mode = rp.Pop<u32>();
const bool is_auto_clear_event = event_clear_mode == 1;
sessions.push_back({module, request_id++, is_auto_clear_event});
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(request_id - 1);
rb.Push(request_id - 1);
}
void Finalize(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto id = rp.Pop<u32>();
for (auto it = sessions.begin(); it != sessions.end(); ++it) {
if (it->request_id == id) {
sessions.erase(it);
break;
}
}
IPC::RequestParser rp{ctx};
const auto id = rp.Pop<u32>();
for (auto it = sessions.begin(); it != sessions.end(); ++it) {
if (it->request_id == id) {
sessions.erase(it);
break;
}
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SetAndWait(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto id = rp.Pop<u32>();
const auto min = rp.Pop<u32>();
const auto max = rp.Pop<s32>();
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto id = rp.Pop<u32>();
const auto min = rp.Pop<u32>();
const auto max = rp.Pop<s32>();
for (auto& session : sessions) {
if (session.request_id == id) {
session.SetAndWait(min, max);
break;
}
}
for (auto& session : sessions) {
if (session.request_id == id) {
session.SetAndWait(min, max);
break;
}
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
@ -192,25 +195,25 @@ private:
void Get(HLERequestContext& ctx) {
LOG_DEBUG(Service_MM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto id = rp.Pop<u32>();
for (const auto& session : sessions) {
if (session.request_id == id) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(session.min);
return;
}
}
IPC::RequestParser rp{ctx};
const auto id = rp.Pop<u32>();
for (const auto& session : sessions) {
if (session.request_id == id) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(session.min);
return;
}
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(0);
rb.Push<u32>(0);
}
std::vector<Session> sessions;
u32 request_id{1};
std::vector<Session> sessions;
u32 request_id{1};
};
void LoopProcess(Core::System& system) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -232,7 +235,7 @@ public:
{2, nullptr, "ClearDebugResponse"},
{3, nullptr, "RegisterDebugResponse"},
{4, &NIM_ECA::IsLargeResourceAvailable, "IsLargeResourceAvailable"},
{5, &NIM_ECA::CreateServerInterface2, "CreateServerInterface2"} // 17.0.0+
{5, &NIM_ECA::CreateServerInterface2, "CreateServerInterface2"} // 17.0.0+
};
// clang-format on
@ -241,7 +244,7 @@ public:
private:
void CreateServerInterface(HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "(STUBBED) called");
LOG_DEBUG(Service_NIM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAccessServer>(system);
@ -258,14 +261,14 @@ private:
rb.Push(ResultSuccess);
rb.Push(false);
}
void CreateServerInterface2(HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "(STUBBED) called.");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAccessServer>(system);
}
void CreateServerInterface2(HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "(STUBBED) called.");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAccessServer>(system);
}
};
class NIM_SHP final : public ServiceFramework<NIM_SHP> {

View file

@ -20,6 +20,7 @@ target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann
find_package(OpenSSL REQUIRED)
target_link_libraries(web_service PRIVATE OpenSSL::SSL OpenSSL::Crypto)
target_compile_definitions(web_service PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(web_service PRIVATE precompiled_headers.h)

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -18,6 +21,10 @@
#pragma GCC diagnostic pop
#endif
#ifdef YUZU_BUNDLED_OPENSSL
#include <openssl/cert.h>
#endif
#include "common/logging/log.h"
#include "web_service/web_backend.h"
#include "web_service/web_result.h"
@ -80,6 +87,9 @@ struct Client::Impl {
cli->set_connection_timeout(TIMEOUT_SECONDS);
cli->set_read_timeout(TIMEOUT_SECONDS);
cli->set_write_timeout(TIMEOUT_SECONDS);
#ifdef YUZU_BUNDLED_OPENSSL
cli->load_ca_cert_store(kCert, sizeof(kCert));
#endif
}
if (!cli->is_valid()) {
LOG_ERROR(WebService, "Invalid URL {}", host + path);

View file

@ -386,6 +386,7 @@ elseif(WIN32)
set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
elseif(MINGW)
set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "-Wl,--subsystem,windows")
target_link_libraries(yuzu PRIVATE dwmapi)
endif()
endif()