summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kescher2022-11-13 09:51:32 +0100
committerJeremy Kescher2022-11-13 09:51:32 +0100
commit08694c60886039ad7b705cf70c2232c1c081b4ad (patch)
tree1a9a12d4b01580d4d9318fc2bf29e8f3f26d236e
parent8cd836d25d663ca55effa58e33834cdf0ec1e869 (diff)
downloadaur-08694c60886039ad7b705cf70c2232c1c081b4ad.tar.gz
2.0-15 + online PR
-rw-r--r--.SRCINFO10
-rw-r--r--PKGBUILD17
-rw-r--r--gui.diff94
-rw-r--r--online.diff643
-rw-r--r--overlay.diff330
5 files changed, 932 insertions, 162 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 37cc54ab6bde..875eb4c1cb2d 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = cemu
pkgdesc = Software to emulate Wii U games and applications on PC (with cutting edge Linux patches)
- pkgver = 2.0.223
+ pkgver = 2.0.234
pkgrel = 1
url = https://cemu.info
install = cemu.install
@@ -25,21 +25,21 @@ pkgbase = cemu
optdepends = alsa-lib: Audio output
optdepends = vulkan-driver: Vulkan graphics
options = !strip
- source = git+https://github.com/cemu-project/Cemu#commit=138510106c63ff697d31fe8e57391e245e477b5c
+ source = git+https://github.com/cemu-project/Cemu#commit=e9d10a95810d1c5f21f976000c93d37238d5b4da
source = git+https://github.com/mozilla/cubeb#commit=dc511c6b3597b6384d28949285b9289e009830ea
source = git+https://github.com/ocornut/imgui#commit=8a44c31c95c8e0217f6e1fc814cbbbcca4981f14
source = git+https://github.com/Exzap/ZArchive#commit=d2c717730092c7bf8cbb033b12fd4001b7c4d932
source = git+https://github.com/arsenm/sanitizers-cmake#commit=aab6948fa863bc1cbe5d0850bc46b9ef02ed4c1a
source = git+https://github.com/google/googletest#commit=800f5422ac9d9e0ad59cd860a2ef3a679588acb4
source = overlay.diff
- source = gui.diff
+ source = online.diff
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
- sha256sums = f25d13fe76cc6a0b475f0131211a951288160ddae92cd7a815f5aea61d7cfc0f
- sha256sums = dcb405fd9b77d73eee4a9591c606a5b7d121999b936920520518e70dcb16ea0e
+ sha256sums = f0ebf654e94461a82409860ae83e8ffee1095fc51b5748aefd7bc5cb58b54225
+ sha256sums = c7da958b6c53c62477e1b52dabf6b736ac813bb4cb37a85a37c9bfa08e9ff963
pkgname = cemu
diff --git a/PKGBUILD b/PKGBUILD
index c38fd9520f9c..41f32c584c1d 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: Jeremy Kescher <jeremy@kescher.at>
pkgname=cemu
-pkgver=2.0.223
+pkgver=2.0.234
pkgrel=1
pkgdesc='Software to emulate Wii U games and applications on PC (with cutting edge Linux patches)'
arch=(x86_64)
@@ -31,7 +31,7 @@ optdepends=(
)
install=cemu.install
source=(
- git+https://github.com/cemu-project/Cemu#commit=138510106c63ff697d31fe8e57391e245e477b5c # v2.0-14
+ git+https://github.com/cemu-project/Cemu#commit=e9d10a95810d1c5f21f976000c93d37238d5b4da # v2.0-15
# submodules
git+https://github.com/mozilla/cubeb#commit=dc511c6b3597b6384d28949285b9289e009830ea
git+https://github.com/ocornut/imgui#commit=8a44c31c95c8e0217f6e1fc814cbbbcca4981f14
@@ -40,8 +40,8 @@ source=(
git+https://github.com/arsenm/sanitizers-cmake#commit=aab6948fa863bc1cbe5d0850bc46b9ef02ed4c1a
git+https://github.com/google/googletest#commit=800f5422ac9d9e0ad59cd860a2ef3a679588acb4
# upstream proposed patches
- overlay.diff # 6aa7a0c7b2003f625bfecd64f6143a10605234b2 (https://github.com/cemu-project/Cemu/pull/142)
- gui.diff # ffed93a69bb8f38a7c81624411bf8be0b45b8646 (https://github.com/cemu-project/Cemu/pull/439)
+ overlay.diff # f1e964bf02baadc3f6af86e4f38dcef7ea5c081c (https://github.com/cemu-project/Cemu/pull/480)
+ online.diff # 68d39331deaa47c812ea3624dc41be3003e5d104 (https://github.com/cemu-project/Cemu/pull/486)
)
sha256sums=('SKIP'
'SKIP'
@@ -49,8 +49,8 @@ sha256sums=('SKIP'
'SKIP'
'SKIP'
'SKIP'
- 'f25d13fe76cc6a0b475f0131211a951288160ddae92cd7a815f5aea61d7cfc0f'
- 'dcb405fd9b77d73eee4a9591c606a5b7d121999b936920520518e70dcb16ea0e')
+ 'f0ebf654e94461a82409860ae83e8ffee1095fc51b5748aefd7bc5cb58b54225'
+ 'c7da958b6c53c62477e1b52dabf6b736ac813bb4cb37a85a37c9bfa08e9ff963')
pkgver() {
cd Cemu
@@ -93,10 +93,7 @@ prepare() {
sed -i '/InsertColumn/s/kListIconWidth/&+8/;/SetColumnWidth/s/last_col_width/&-1/' src/gui/components/wxGameList.cpp
rm -rf src/util/SystemInfo
- git apply "$srcdir/overlay.diff"
- sed -i '/add_library/aSystemInfo/SystemInfo.cpp SystemInfo/SystemInfoLinux.cpp' src/util/CMakeLists.txt
-
- git apply "$srcdir/gui.diff"
+ git apply --whitespace=nowarn "$srcdir/overlay.diff" "$srcdir/online.diff"
}
build() {
diff --git a/gui.diff b/gui.diff
deleted file mode 100644
index 4e7d0de71c65..000000000000
--- a/gui.diff
+++ /dev/null
@@ -1,94 +0,0 @@
---- a/src/gui/MainWindow.cpp
-+++ b/src/gui/MainWindow.cpp
-@@ -1692,8 +1692,6 @@ class CemuAboutDialog : public wxDialog
- {
- SetIcon(wxICON(M_WND_ICON128));
-
-- this->SetBackgroundColour(wxColour(0xFFFFFFFF));
--
- wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this);
-
- wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
---- a/src/gui/components/wxGameList.cpp
-+++ b/src/gui/components/wxGameList.cpp
-@@ -358,16 +358,9 @@ long wxGameList::GetStyleFlags(Style style) const
- void wxGameList::UpdateItemColors(sint32 startIndex)
- {
- wxWindowUpdateLocker lock(this);
-- // get the background color so we can determine the theme in use
-- wxColour bgColour = GetBackgroundColour();
-- uint32 bgLightness = (bgColour.GetRed() + bgColour.GetGreen() + bgColour.GetBlue()) / 3;
-- bool isDarkTheme = bgLightness < 128;
-- wxColour bgColourPrimary = bgColour; // color for odd rows
-- wxColour bgColourSecondary = bgColour.ChangeLightness(isDarkTheme ? 110 : 90); // color for even rows
-
-- // for very light themes we'll use a blue tint to match the older Windows Cemu look
-- if (bgLightness > 250)
-- bgColourSecondary = wxColour(bgColour.Red() - 13, bgColour.Green() - 6, bgColour.Blue() - 2);
-+ wxColour bgColourPrimary = GetBackgroundColour();
-+ wxColour bgColourSecondary = wxHelper::CalculateAccentColour(bgColourPrimary);
-
- for (int i = startIndex; i < GetItemCount(); ++i)
- {
-@@ -1143,4 +1136,4 @@ bool wxGameList::QueryIconForTitle(TitleId titleId, int& icon, int& iconSmall)
- void wxGameList::DeleteCachedStrings()
- {
- m_name_cache.clear();
--}
-\ No newline at end of file
-+}
---- a/src/gui/components/wxTitleManagerList.cpp
-+++ b/src/gui/components/wxTitleManagerList.cpp
-@@ -172,10 +172,11 @@ wxString wxTitleManagerList::OnGetItemText(long item, long column) const
-
- wxItemAttr* wxTitleManagerList::OnGetItemAttr(long item) const
- {
-- const auto entry = GetTitleEntry(item);
-- const wxColour kSecondColor{ 0xFDF9F2 };
-- static wxListItemAttr s_coloured_attr(GetTextColour(), kSecondColor, GetFont());
-- return item % 2 == 0 ? nullptr : &s_coloured_attr;
-+ static wxColour bgColourPrimary = GetBackgroundColour();
-+ static wxColour bgColourSecondary = wxHelper::CalculateAccentColour(bgColourPrimary);
-+ static wxListItemAttr s_primary_attr(GetTextColour(), bgColourPrimary, GetFont());
-+ static wxListItemAttr s_secondary_attr(GetTextColour(), bgColourSecondary, GetFont());
-+ return item % 2 == 0 ? &s_primary_attr : &s_secondary_attr;
- }
-
- boost::optional<wxTitleManagerList::TitleEntry&> wxTitleManagerList::GetTitleEntry(long item)
-@@ -1274,4 +1275,4 @@ void wxTitleManagerList::ClearItems()
- void wxTitleManagerList::AutosizeColumns()
- {
- wxAutosizeColumns(this, ColumnTitleId, ColumnMAX - 1);
--}
-\ No newline at end of file
-+}
---- a/src/gui/input/panels/InputPanel.h
-+++ b/src/gui/input/panels/InputPanel.h
-@@ -12,7 +12,7 @@ class wxComboBox;
- class InputPanel : public wxPanel
- {
- public:
-- const wxColour kKeyColourNormalMode = 0xfafafa;
-+ const wxColour kKeyColourNormalMode = GetBackgroundColour();
- const wxColour kKeyColourEditMode = 0x99ccff;
- const wxColour kKeyColourActiveMode = 0xE0E0E0;
-
---- a/src/gui/wxHelper.h
-+++ b/src/gui/wxHelper.h
-@@ -22,5 +22,16 @@ namespace wxHelper
- return wxString::FromUTF8(str.data(), str.size());
- }
-
-+ inline wxColour CalculateAccentColour(const wxColour& bgColour)
-+ {
-+ wxColour bgColourSecondary;
-+ const uint32 bgLightness = (bgColour.GetRed() + bgColour.GetGreen() + bgColour.GetBlue()) / 3;
-+ const bool isDarkTheme = bgLightness < 128;
-+ bgColourSecondary = bgColour.ChangeLightness(isDarkTheme ? 110 : 90); // color for even rows
-+ // for very light themes we'll use a blue tint to match the older Windows Cemu look
-+ if (bgLightness > 250)
-+ bgColourSecondary = wxColour(bgColour.Red() - 13, bgColour.Green() - 6, bgColour.Blue() - 2);
-+ return bgColourSecondary;
-+ }
-
- };
diff --git a/online.diff b/online.diff
new file mode 100644
index 000000000000..cfac0e3fd8fe
--- /dev/null
+++ b/online.diff
@@ -0,0 +1,643 @@
+diff --git a/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp b/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp
+index 5ec75e6b..d32c51f2 100644
+--- a/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp
++++ b/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp
+@@ -455,11 +455,6 @@ void export_curl_multi_fdset(PPCInterpreter_t* hCPU)
+ ppcDefineParamMEMPTR(exceptionFd, wu_fd_set, 3);
+ ppcDefineParamU32BEPtr(maxFd, 4);
+
+-#if BOOST_OS_LINUX || BOOST_OS_MACOS
+- cemuLog_log(LogType::Force, "curl_multi_fdset(...) - todo");
+-
+- osLib_returnFromFunction(hCPU, 0);
+-#else
+ fd_set h_readFd;
+ fd_set h_writeFd;
+ fd_set h_exceptionFd;
+@@ -475,17 +470,36 @@ void export_curl_multi_fdset(PPCInterpreter_t* hCPU)
+ nsysnet::wuResetFD(exceptionFd.GetPtr());
+
+ sint32 c_maxFD = -1;
+- // fd read set
+- for (uint32 i = 0; i < h_readFd.fd_count; i++)
++
++ auto hostFdSet = [&](SOCKET s, wu_fd_set* fds)
+ {
+- sint32 wuSocket = nsysnet_getVirtualSocketHandleFromHostHandle(h_readFd.fd_array[i]);
++ sint32 wuSocket = nsysnet_getVirtualSocketHandleFromHostHandle(s);
+ if (wuSocket < 0)
+- wuSocket = nsysnet_createVirtualSocketFromExistingSocket(h_readFd.fd_array[i]);
++ wuSocket = nsysnet_createVirtualSocketFromExistingSocket(s);
+ if (wuSocket >= 0)
+ {
+ c_maxFD = std::max(wuSocket, c_maxFD);
+- nsysnet::wuSetFD(readFd.GetPtr(), wuSocket);
++ nsysnet::wuSetFD(fds, wuSocket);
+ }
++ };
++
++#if BOOST_OS_UNIX
++ for (int s = 0; s < h_maxFd + 1; s++)
++ {
++ if(FD_ISSET(s, &h_readFd))
++ hostFdSet(s, readFd.GetPtr());
++
++ if(FD_ISSET(s, &h_writeFd))
++ hostFdSet(s, writeFd.GetPtr());
++
++ if(FD_ISSET(s, &h_exceptionFd))
++ hostFdSet(s, exceptionFd.GetPtr());
++ }
++#else
++ // fd read set
++ for (uint32 i = 0; i < h_readFd.fd_count; i++)
++ {
++ hostFdSet(h_readFd.fd_array[i], readFd.GetPtr());
+ }
+ // fd write set
+ for (uint32 i = 0; i < h_writeFd.fd_count; i++)
+@@ -497,11 +511,10 @@ void export_curl_multi_fdset(PPCInterpreter_t* hCPU)
+ {
+ cemu_assert_debug(false);
+ }
++#endif
+
+ *maxFd = c_maxFD;
+ osLib_returnFromFunction(hCPU, result);
+-#endif
+-
+ }
+
+ void export_curl_multi_setopt(PPCInterpreter_t* hCPU)
+diff --git a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
+index ade207f9..5a8081e2 100644
+--- a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
++++ b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
+@@ -6,8 +6,24 @@
+
+ #include "Common/socket.h"
+
++#if BOOST_OS_UNIX
++
++#define WSAEWOULDBLOCK EWOULDBLOCK
++#define WSAEINPROGRESS EINPROGRESS
++#define WSAESHUTDOWN ESHUTDOWN
++#define WSAECONNABORTED ECONNABORTED
++#define WSAHOST_NOT_FOUND EAI_NONAME
++
++#define GETLASTERR errno
++
++#endif // BOOST_OS_UNIX
++
+ #if BOOST_OS_WINDOWS
+
++#define GETLASTERR WSAGetLastError()
++
++#endif //BOOST_OS_WINDOWS
++
+ #define WU_AF_INET 2
+
+ #define WU_SOCK_STREAM 1
+@@ -50,8 +66,10 @@ bool sockLibReady = false;
+ void nsysnetExport_socket_lib_init(PPCInterpreter_t* hCPU)
+ {
+ sockLibReady = true;
++#if BOOST_OS_WINDOWS
+ WSADATA wsa;
+ WSAStartup(MAKEWORD(2, 2), &wsa);
++#endif // BOOST_OS_WINDOWS
+ osLib_returnFromFunction(hCPU, 0); // 0 -> Success
+ }
+
+@@ -200,7 +218,9 @@ sint32 _getFreeSocketHandle()
+ return 0;
+ }
+
++#if BOOST_OS_WINDOWS
+ #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
++#endif // BOOST_OS_WINDOWS
+
+ WUSOCKET nsysnet_createVirtualSocket(sint32 family, sint32 type, sint32 protocol)
+ {
+@@ -219,6 +239,7 @@ WUSOCKET nsysnet_createVirtualSocket(sint32 family, sint32 type, sint32 protocol
+ virtualSocketTable[s - 1] = vs;
+ // init host socket
+ vs->s = socket(family, type, protocol);
++ #if BOOST_OS_WINDOWS
+ // disable reporting of PORT_UNREACHABLE for UDP sockets
+ if (protocol == IPPROTO_UDP)
+ {
+@@ -226,21 +247,14 @@ WUSOCKET nsysnet_createVirtualSocket(sint32 family, sint32 type, sint32 protocol
+ DWORD dwBytesReturned = 0;
+ WSAIoctl(vs->s, SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, 0, &dwBytesReturned, NULL, NULL);
+ }
++ #endif // BOOST_OS_WINDOWS
+ return vs->handle;
+ }
+
+ WUSOCKET nsysnet_createVirtualSocketFromExistingSocket(SOCKET existingSocket)
+ {
+ forceLogDebug_printf("nsysnet_createVirtualSocketFromExistingSocket - incomplete");
+- // SO_TYPE -> type
+- // SO_BSP_STATE -> protocol + other info
+- // SO_PROTOCOL_INFO -> protocol + type?
+-
+- WSAPROTOCOL_INFO protocolInfo = { 0 };
+- int optLen = sizeof(protocolInfo);
+- getsockopt(existingSocket, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&protocolInfo, &optLen);
+
+- // todo - translate protocolInfo
+
+ sint32 s = _getFreeSocketHandle();
+ if (s == 0)
+@@ -250,9 +264,34 @@ WUSOCKET nsysnet_createVirtualSocketFromExistingSocket(SOCKET existingSocket)
+ }
+ virtualSocket_t* vs = (virtualSocket_t*)malloc(sizeof(virtualSocket_t));
+ memset(vs, 0, sizeof(virtualSocket_t));
++#if BOOST_OS_WINDOWS
++ // SO_TYPE -> type
++ // SO_BSP_STATE -> protocol + other info
++ // SO_PROTOCOL_INFO -> protocol + type?
++
++ WSAPROTOCOL_INFO protocolInfo = { 0 };
++ int optLen = sizeof(protocolInfo);
++ getsockopt(existingSocket, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&protocolInfo, &optLen);
++ // todo - translate protocolInfo
+ vs->family = protocolInfo.iAddressFamily;
+ vs->type = protocolInfo.iSocketType;
+ vs->protocol = protocolInfo.iSocketType;
++#else
++ {
++ int type;
++ socklen_t optlen;
++ getsockopt(vs->s, SOL_SOCKET, SO_TYPE, &type, &optlen);
++ vs->type = type;
++ vs->protocol = type;
++ }
++ {
++ sockaddr saddr;
++ socklen_t len;
++ getsockname(vs->s, &saddr, &len);
++ vs->family = saddr.sa_family;
++ }
++#endif
++
+ vs->handle = s;
+ virtualSocketTable[s - 1] = vs;
+ vs->s = existingSocket;
+@@ -395,7 +434,19 @@ void nsysnetExport_socketclose(PPCInterpreter_t* hCPU)
+ }
+ osLib_returnFromFunction(hCPU, 0);
+ }
+-
++sint32 _socket_nonblock(SOCKET s, u_long mode)
++{
++#if BOOST_OS_WINDOWS
++ return ioctlsocket(s, FIONBIO, &mode);
++#else
++ int flags = fcntl(s, F_GETFL);
++ if(mode)
++ flags |= O_NONBLOCK;
++ else
++ flags &= ~O_NONBLOCK;
++ return fcntl(s, F_SETFL, flags);
++#endif
++}
+ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
+ {
+ socketLog_printf("setsockopt(%d,0x%x,0x%05x,0x%08x,%d)", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6], hCPU->gpr[7]);
+@@ -441,7 +492,7 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
+ else
+ cemu_assert_suspicious();
+ u_long mode = 1;
+- ioctlsocket(vs->s, FIONBIO, &mode);
++ _socket_nonblock(vs->s, mode);
+ vs->isNonBlocking = true;
+ }
+ else if (optname == WU_SO_NONBLOCK)
+@@ -450,16 +501,16 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
+ assert_dbg();
+ sint32 optvalLE = _swapEndianU32(*(uint32*)optval);
+ u_long mode = optvalLE; // 1 -> enable, 0 -> disable
+- ioctlsocket(vs->s, FIONBIO, &mode);
++ _socket_nonblock(vs->s, mode);
+ vs->isNonBlocking = mode != 0;
+ }
+ else if (optname == WU_SO_KEEPALIVE)
+ {
+- // todo
++ cemuLog_logDebug(LogType::Socket, "todo: setsockopt() for WU_SO_KEEPALIVE");
+ }
+ else if (optname == WU_SO_WINSCALE)
+ {
+- // todo
++ cemuLog_logDebug(LogType::Socket, "todo: setsockopt() for WU_SO_WINSCALE");
+ }
+ else if (optname == WU_SO_RCVBUF)
+ {
+@@ -549,9 +600,9 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
+ if (optname == WU_SO_LASTERROR)
+ {
+ int optvalLE = 0;
+- int optlenLE = 4;
++ socklen_t optlenLE = 4;
+ r = getsockopt(vs->s, hostLevel, SO_ERROR, (char*)&optvalLE, &optlenLE);
+- r = _translateError(r, WSAGetLastError());
++ r = _translateError(r, GETLASTERR);
+ if (memory_readU32(optlenMPTR) != 4)
+ assert_dbg();
+ memory_writeU32(optlenMPTR, 4);
+@@ -563,9 +614,9 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
+ else if (optname == WU_SO_RCVBUF)
+ {
+ int optvalLE = 0;
+- int optlenLE = 4;
++ socklen_t optlenLE = 4;
+ r = getsockopt(vs->s, hostLevel, SO_RCVBUF, (char*)&optvalLE, &optlenLE);
+- r = _translateError(r, WSAGetLastError());
++ r = _translateError(r, GETLASTERR);
+ if (memory_readU32(optlenMPTR) != 4)
+ assert_dbg();
+ memory_writeU32(optlenMPTR, 4);
+@@ -575,9 +626,9 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
+ else if (optname == WU_SO_SNDBUF)
+ {
+ int optvalLE = 0;
+- int optlenLE = 4;
++ socklen_t optlenLE = 4;
+ r = getsockopt(vs->s, hostLevel, SO_SNDBUF, (char*)&optvalLE, &optlenLE);
+- r = _translateError(r, WSAGetLastError());
++ r = _translateError(r, GETLASTERR);
+ if (memory_readU32(optlenMPTR) != 4)
+ assert_dbg();
+ memory_writeU32(optlenMPTR, 4);
+@@ -737,7 +788,7 @@ void nsysnetExport_bind(PPCInterpreter_t* hCPU)
+ hostAddr.sa_family = _swapEndianU16(addr->sa_family);
+ memcpy(hostAddr.sa_data, addr->sa_data, 14);
+ sint32 hr = bind(vs->s, &hostAddr, sizeof(sockaddr));
+- r = _translateError(hr, WSAGetLastError());
++ r = _translateError(hr, GETLASTERR);
+
+
+ socketLog_printf("bind address: %d.%d.%d.%d:%d result: %d", addr->sa_data[2], addr->sa_data[3], addr->sa_data[4], addr->sa_data[5], _swapEndianU16(*(uint16*)addr->sa_data), hr);
+@@ -797,7 +848,7 @@ void nsysnetExport_accept(PPCInterpreter_t* hCPU)
+ if (vs->isNonBlocking)
+ {
+ sockaddr hostAddr;
+- int hostLen = sizeof(sockaddr);
++ socklen_t hostLen = sizeof(sockaddr);
+ SOCKET hr = accept(vs->s, &hostAddr, &hostLen);
+ if (hr != SOCKET_ERROR)
+ {
+@@ -806,7 +857,7 @@ void nsysnetExport_accept(PPCInterpreter_t* hCPU)
+ }
+ else
+ {
+- r = _translateError((sint32)hr, (sint32)WSAGetLastError(), _ERROR_MODE_ACCEPT);
++ r = _translateError((sint32)hr, (sint32)GETLASTERR, _ERROR_MODE_ACCEPT);
+ }
+ sockaddr_host2guest(&hostAddr, addr);
+ }
+@@ -820,7 +871,6 @@ void nsysnetExport_accept(PPCInterpreter_t* hCPU)
+ osLib_returnFromFunction(hCPU, r);
+ }
+
+-
+ void nsysnetExport_connect(PPCInterpreter_t* hCPU)
+ {
+ socketLog_printf("connect(%d,0x%08x,%d)", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5]);
+@@ -844,7 +894,7 @@ void nsysnetExport_connect(PPCInterpreter_t* hCPU)
+ sint32 hr = connect(vs->s, &hostAddr, sizeof(sockaddr));
+ forceLog_printf("Attempt connect to %d.%d.%d.%d:%d", (sint32)(uint8)hostAddr.sa_data[2], (sint32)(uint8)hostAddr.sa_data[3], (sint32)(uint8)hostAddr.sa_data[4], (sint32)(uint8)hostAddr.sa_data[5], _swapEndianU16(*(uint16*)hostAddr.sa_data+0));
+
+- r = _translateError(hr, WSAGetLastError(), _ERROR_MODE_CONNECT);
++ r = _translateError(hr, GETLASTERR, _ERROR_MODE_CONNECT);
+
+ osLib_returnFromFunction(hCPU, r);
+ }
+@@ -852,7 +902,7 @@ void nsysnetExport_connect(PPCInterpreter_t* hCPU)
+ void _setSocketSendRecvNonBlockingMode(SOCKET s, bool isNonBlocking)
+ {
+ u_long mode = isNonBlocking ? 1 : 0;
+- sint32 r = ioctlsocket(s, FIONBIO, &mode);
++ sint32 r = _socket_nonblock(s, mode);
+ }
+
+ void nsysnetExport_send(PPCInterpreter_t* hCPU)
+@@ -881,7 +931,7 @@ void nsysnetExport_send(PPCInterpreter_t* hCPU)
+
+ sint32 hr = send(vs->s, msg, len, hostFlags);
+ socketLog_printf("Sent %d bytes", hr);
+- _translateError(hr <= 0 ? -1 : 0, WSAGetLastError());
++ _translateError(hr <= 0 ? -1 : 0, GETLASTERR);
+ r = hr;
+
+ osLib_returnFromFunction(hCPU, r);
+@@ -930,7 +980,7 @@ void nsysnetExport_recv(PPCInterpreter_t* hCPU)
+ break;
+ if (tr == 0)
+ break; // connection closed
+- if (tr < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
++ if (tr < 0 && GETLASTERR != WSAEWOULDBLOCK)
+ break;
+ // yield thread
+ coreinit::OSSleepTicks(coreinit::EspressoTime::GetTimerClock() / 5000); // let thread wait 0.2ms to give other threads CPU time
+@@ -940,7 +990,7 @@ void nsysnetExport_recv(PPCInterpreter_t* hCPU)
+ }
+ // receive
+ sint32 hr = recv(vs->s, msg, len, hostFlags);
+- _translateError(hr <= 0 ? -1 : 0, WSAGetLastError());
++ _translateError(hr <= 0 ? -1 : 0, GETLASTERR);
+ if (requestIsNonBlocking != vs->isNonBlocking)
+ _setSocketSendRecvNonBlockingMode(vs->s, vs->isNonBlocking);
+ socketLog_printf("Received %d bytes", hr);
+@@ -955,11 +1005,20 @@ struct wu_timeval
+ uint32 tv_usec;
+ };
+
+-void _translateFDSet(fd_set* hostSet, struct wu_fd_set* fdset, sint32 nfds)
++void _translateFDSet(fd_set* hostSet, struct wu_fd_set* fdset, sint32 nfds, int *hostnfds)
+ {
+- hostSet->fd_count = 0;
++ FD_ZERO(hostSet);
+ if (fdset == NULL)
+ return;
++
++#if BOOST_OS_UNIX
++ int maxfd;
++ if(hostnfds)
++ maxfd = *hostnfds;
++ else
++ maxfd = -1;
++#endif
++
+ uint32 mask = fdset->mask;
+ for (sint32 i = 0; i < nfds; i++)
+ {
+@@ -969,9 +1028,19 @@ void _translateFDSet(fd_set* hostSet, struct wu_fd_set* fdset, sint32 nfds)
+ virtualSocket_t* vs = nsysnet_getVirtualSocketObject(socketHandle);
+ if(vs == NULL)
+ continue; // socket invalid
+- hostSet->fd_array[hostSet->fd_count] = vs->s;
+- hostSet->fd_count++;
++
++#if BOOST_OS_UNIX
++ if(vs->s > maxfd)
++ maxfd = vs->s;
++#endif
++
++ FD_SET(vs->s, hostSet);
+ }
++
++#if BOOST_OS_UNIX
++ if(hostnfds)
++ *hostnfds = maxfd;
++#endif
+ }
+
+ void _translateFDSetRev(struct wu_fd_set* fdset, fd_set* hostSet, sint32 nfds)
+@@ -979,6 +1048,7 @@ void _translateFDSetRev(struct wu_fd_set* fdset, fd_set* hostSet, sint32 nfds)
+ if (fdset == NULL)
+ return;
+ uint32 mask = _swapEndianU32(0);
++#if BOOST_OS_WINDOWS
+ for (sint32 i = 0; i < (sint32)hostSet->fd_count; i++)
+ {
+ sint32 virtualSocketHandle = nsysnet_getVirtualSocketHandleFromHostHandle(hostSet->fd_array[i]);
+@@ -986,7 +1056,15 @@ void _translateFDSetRev(struct wu_fd_set* fdset, fd_set* hostSet, sint32 nfds)
+ cemu_assert_debug(false);
+ mask |= (1<<virtualSocketHandle);
+ }
++#else
++ for (sint32 i = 0; i < WU_SOCKET_LIMIT; i++)
++ {
++ if (virtualSocketTable[i] && virtualSocketTable[i]->s && FD_ISSET(virtualSocketTable[i]->s, hostSet))
++ mask |= (1 << virtualSocketTable[i]->handle);
++ }
++#endif
+ fdset->mask = mask;
++
+ }
+
+ void nsysnetExport_select(PPCInterpreter_t* hCPU)
+@@ -1025,8 +1103,10 @@ void nsysnetExport_select(PPCInterpreter_t* hCPU)
+ // when fd sets are empty but timeout is set, then just wait and do nothing?
+ // Lost Reavers seems to expect this case to return 0 (it hardcodes empty fd sets and timeout comes from curl_multi_timeout)
+
+- //_setSockError(WU_SO_EINVAL);
+- // todo - sleep here
++ timeval tv;
++ tv.tv_sec = timeOut->tv_sec;
++ tv.tv_usec = timeOut->tv_usec;
++ select(0, nullptr, nullptr, nullptr, &tv);
+ socketLog_printf("select returned 0 because of empty fdsets with timeout");
+ osLib_returnFromFunction(hCPU, 0);
+
+@@ -1042,15 +1122,16 @@ void nsysnetExport_select(PPCInterpreter_t* hCPU)
+ uint32 startTime = GetTickCount();
+ while (true)
+ {
+- _translateFDSet(&_readfds, readfds, nfds);
+- _translateFDSet(&_writefds, writefds, nfds);
+- _translateFDSet(&_exceptfds, exceptfds, nfds);
+- r = select(0, readfds ? &_readfds : NULL, writefds ? &_writefds : NULL, exceptfds ? &_exceptfds : NULL, &tv);
++ int hostnfds = -1;
++ _translateFDSet(&_readfds, readfds, nfds, &hostnfds);
++ _translateFDSet(&_writefds, writefds, nfds, &hostnfds);
++ _translateFDSet(&_exceptfds, exceptfds, nfds, &hostnfds);
++ r = select(hostnfds + 1, readfds ? &_readfds : NULL, writefds ? &_writefds : NULL, exceptfds ? &_exceptfds : NULL, &tv);
+ if (r < 0)
+ {
+ forceLogDebug_printf("select() failed");
+ // timeout
+- _translateError(r, WSAGetLastError());
++ _translateError(r, GETLASTERR);
+ //_setSockError(WU_SO_SUCCESS);
+ // in case of error, clear all FD sets (?)
+ if (readfds)
+@@ -1083,7 +1164,9 @@ void nsysnetExport_select(PPCInterpreter_t* hCPU)
+ }
+ else
+ {
+- socketLog_printf("select returned %d. Read %d Write %d Except %d", r, _readfds.fd_count, _writefds.fd_count, _exceptfds.fd_count);
++ // socketLog_printf("select returned %d. Read %d Write %d Except %d", r, _readfds.fd_count, _writefds.fd_count, _exceptfds.fd_count);
++ socketLog_printf("select returned %d.", r);
++
+ _translateFDSetRev(readfds, &_readfds, nfds);
+ _translateFDSetRev(writefds, &_writefds, nfds);
+ _translateFDSetRev(exceptfds, &_exceptfds, nfds);
+@@ -1116,7 +1199,7 @@ void nsysnetExport_getsockname(PPCInterpreter_t* hCPU)
+ else
+ {
+ struct sockaddr hostAddr;
+- sint32 hostLen = sizeof(struct sockaddr);
++ socklen_t hostLen = sizeof(struct sockaddr);
+ sint32 hr = getsockname(vs->s, &hostAddr, &hostLen);
+ if (hr == 0)
+ {
+@@ -1151,13 +1234,13 @@ void nsysnetExport_getpeername(PPCInterpreter_t* hCPU)
+ }
+
+ sockaddr saddr;
+- int saddrLen = sizeof(sockaddr);
++ socklen_t saddrLen = sizeof(sockaddr);
+
+ if (*nameLen < (uint32be)16)
+ assert_dbg();
+
+ sint32 r = getpeername(vs->s, &saddr, &saddrLen);
+- r = _translateError(r, WSAGetLastError());
++ r = _translateError(r, GETLASTERR);
+
+ name->sa_family = _swapEndianU16(saddr.sa_family);
+ memcpy(name->sa_data, saddr.sa_data, 14);
+@@ -1432,7 +1515,7 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
+ if (vs->isNonBlocking)
+ requestIsNonBlocking = vs->isNonBlocking;
+
+- sint32 fromLenHost = *fromLen;
++ socklen_t fromLenHost = *fromLen;
+ sockaddr fromAddrHost;
+ sint32 wsaError = 0;
+
+@@ -1447,16 +1530,20 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
+ return;
+ }
+ // use select to check for exceptions and read data
+- FD_SET fd_read;
+- FD_SET fd_exceptions;
++ fd_set fd_read;
++ fd_set fd_exceptions;
+ FD_ZERO(&fd_read);
+ FD_ZERO(&fd_exceptions);
+ FD_SET(vs->s, &fd_read);
+ FD_SET(vs->s, &fd_exceptions);
+- TIMEVAL t;
++ timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+- sint32 count = select(0, &fd_read, NULL, &fd_exceptions, &t);
++ int nfds = 0;
++#if BOOST_OS_UNIX
++ nfds = vs->s + 1;
++#endif
++ sint32 count = select(nfds, &fd_read, NULL, &fd_exceptions, &t);
+ if (count > 0)
+ {
+ if (FD_ISSET(vs->s, &fd_exceptions))
+@@ -1467,7 +1554,7 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
+ {
+ // data available
+ r = recvfrom(vs->s, msg, len, hostFlags, &fromAddrHost, &fromLenHost);
+- wsaError = WSAGetLastError();
++ wsaError = GETLASTERR;
+ if (r < 0)
+ cemu_assert_debug(false);
+ forceLogDebug_printf("recvfrom returned %d bytes", r);
+@@ -1504,7 +1591,7 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
+ while (true)
+ {
+ r = recvfrom(vs->s, msg, len, hostFlags, &fromAddrHost, &fromLenHost);
+- wsaError = WSAGetLastError();
++ wsaError = GETLASTERR;
+ if (r < 0)
+ {
+ if (wsaError != WSAEWOULDBLOCK)
+@@ -1576,7 +1663,7 @@ void nsysnetExport_recvfrom_ex(PPCInterpreter_t* hCPU)
+ if (vs->isNonBlocking)
+ requestIsNonBlocking = vs->isNonBlocking;
+
+- sint32 fromLenHost = *fromLen;
++ socklen_t fromLenHost = *fromLen;
+ sockaddr fromAddrHost;
+ sint32 wsaError = 0;
+
+@@ -1591,16 +1678,20 @@ void nsysnetExport_recvfrom_ex(PPCInterpreter_t* hCPU)
+ return;
+ }
+ // use select to check for exceptions and read data
+- FD_SET fd_read;
+- FD_SET fd_exceptions;
++ fd_set fd_read;
++ fd_set fd_exceptions;
+ FD_ZERO(&fd_read);
+ FD_ZERO(&fd_exceptions);
+ FD_SET(vs->s, &fd_read);
+ FD_SET(vs->s, &fd_exceptions);
+- TIMEVAL t;
++ timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+- sint32 count = select(0, &fd_read, NULL, &fd_exceptions, &t);
++ int nfds = 0;
++#if BOOST_OS_UNIX
++ nfds = vs->s + 1;
++#endif
++ sint32 count = select(nfds, &fd_read, NULL, &fd_exceptions, &t);
+ if (count > 0)
+ {
+ if (FD_ISSET(vs->s, &fd_exceptions))
+@@ -1611,7 +1702,7 @@ void nsysnetExport_recvfrom_ex(PPCInterpreter_t* hCPU)
+ {
+ // data available
+ r = recvfrom(vs->s, msg, len, hostFlags, &fromAddrHost, &fromLenHost);
+- wsaError = WSAGetLastError();
++ wsaError = GETLASTERR;
+ if (r < 0)
+ {
+ cemu_assert_debug(false);
+@@ -1693,7 +1784,7 @@ void nsysnetExport_sendto(PPCInterpreter_t* hCPU)
+ while (true)
+ {
+ r = sendto(vs->s, msg, len, hostFlags, &toAddrHost, toLen);
+- wsaError = WSAGetLastError();
++ wsaError = GETLASTERR;
+ if (r < 0)
+ {
+ if (wsaError != WSAEWOULDBLOCK)
+@@ -1711,7 +1802,7 @@ void nsysnetExport_sendto(PPCInterpreter_t* hCPU)
+ // non blocking
+ _setSocketSendRecvNonBlockingMode(vs->s, true);
+ r = sendto(vs->s, msg, len, hostFlags, &toAddrHost, toLen);
+- wsaError = WSAGetLastError();
++ wsaError = GETLASTERR;
+ _setSocketSendRecvNonBlockingMode(vs->s, vs->isNonBlocking);
+ }
+
+@@ -1818,8 +1909,6 @@ void nsysnetExport_sendto_multi_ex(PPCInterpreter_t* hCPU)
+ osLib_returnFromFunction(hCPU, sendLenSum); // return value correct?
+ }
+
+-#endif
+-
+ namespace nsysnet
+ {
+ std::vector<NSSLInternalState_t> g_nsslInternalStates;
+@@ -2030,7 +2119,6 @@ namespace nsysnet
+ void nsysnet_load()
+ {
+
+- #if BOOST_OS_WINDOWS
+ osLib_addFunction("nsysnet", "socket_lib_init", nsysnetExport_socket_lib_init);
+
+ // socket API
+@@ -2071,7 +2159,6 @@ void nsysnet_load()
+ osLib_addFunction("nsysnet", "sendto_multi", nsysnetExport_sendto_multi);
+ osLib_addFunction("nsysnet", "sendto_multi_ex", nsysnetExport_sendto_multi_ex);
+
+-#endif
+
+ // NSSL API
+ osLib_addFunction("nsysnet", "NSSLCreateContext", nsysnet::export_NSSLCreateContext);
+@@ -2084,10 +2171,3 @@ void nsysnet_load()
+ osLib_addFunction("nsysnet", "NSSLExportInternalServerCertificate", nsysnet::export_NSSLExportInternalServerCertificate);
+ osLib_addFunction("nsysnet", "NSSLExportInternalClientCertificate", nsysnet::export_NSSLExportInternalClientCertificate);
+ }
+-
+-#if BOOST_OS_LINUX || BOOST_OS_MACOS
+-void nsysnet_notifyCloseSharedSocket(SOCKET existingSocket)
+-{
+-
+-}
+-#endif
+\ No newline at end of file
diff --git a/overlay.diff b/overlay.diff
index 7ef31cf81880..947843be01a7 100644
--- a/overlay.diff
+++ b/overlay.diff
@@ -1,3 +1,5 @@
+diff --git a/src/Cafe/HW/Latte/Core/LatteOverlay.cpp b/src/Cafe/HW/Latte/Core/LatteOverlay.cpp
+index 21b70d25..441ec169 100644
--- a/src/Cafe/HW/Latte/Core/LatteOverlay.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteOverlay.cpp
@@ -12,30 +12,16 @@
@@ -33,7 +35,7 @@
std::vector<ProcessorTime> processor_times;
double fps{};
-@@ -565,83 +551,52 @@ void LatteOverlay_render(bool pad_view)
+@@ -562,83 +548,52 @@ void LatteOverlay_render(bool pad_view)
}
}
@@ -60,10 +62,10 @@
- return;
+ ProcessorTime now;
+ QueryProcTime(now);
-+
++
+ double cpu = ProcessorTime::Compare(g_state.processor_time_cemu, now);
+ cpu /= g_state.processor_count;
-+
++
+ g_state.cpu_usage = cpu * 100;
+ g_state.processor_time_cemu = now;
+}
@@ -73,7 +75,7 @@
+static void UpdateStats_CpuPerCore()
+{
+ std::vector<ProcessorTime> now(g_state.processor_count);
-+ QueryCoreTimes(g_state.processor_count, now.data());
++ QueryCoreTimes(g_state.processor_count, now);
-#if BOOST_OS_WINDOWS
- // update cemu cpu
@@ -147,6 +149,160 @@
// update vram
g_renderer->GetVRAMInfo(g_state.vramUsage, g_state.vramTotal);
+diff --git a/src/Cafe/HW/Latte/Core/LattePerformanceMonitor.cpp b/src/Cafe/HW/Latte/Core/LattePerformanceMonitor.cpp
+index 7104dbd9..714758e9 100644
+--- a/src/Cafe/HW/Latte/Core/LattePerformanceMonitor.cpp
++++ b/src/Cafe/HW/Latte/Core/LattePerformanceMonitor.cpp
+@@ -98,7 +98,10 @@ void LattePerformanceMonitor_frameEnd()
+ performanceMonitor.cycle[nextCycleIndex].recompilerLeaveCount = 0;
+ performanceMonitor.cycle[nextCycleIndex].threadLeaveCount = 0;
+ performanceMonitor.cycleIndex = nextCycleIndex;
+-
++
++ // next update in 1 second
++ performanceMonitor.cycle[performanceMonitor.cycleIndex].lastUpdate = GetTickCount();
++
+ if (isFirstUpdate)
+ {
+ LatteOverlay_updateStats(0.0, 0);
+@@ -109,8 +112,6 @@ void LattePerformanceMonitor_frameEnd()
+ LatteOverlay_updateStats(fps, drawCallCounter / elapsedFrames);
+ gui_updateWindowTitles(false, false, fps);
+ }
+- // next update in 1 second
+- performanceMonitor.cycle[performanceMonitor.cycleIndex].lastUpdate = GetTickCount();
+
+ // prevent hibernation and screen saver/monitor off
+ #if BOOST_OS_WINDOWS
+@@ -124,4 +125,4 @@ void LattePerformanceMonitor_frameBegin()
+ {
+ performanceMonitor.vk.numDrawBarriersPerFrame.reset();
+ performanceMonitor.vk.numBeginRenderpassPerFrame.reset();
+-}
+\ No newline at end of file
++}
+diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
+index 06c8f857..5af88176 100644
+--- a/src/util/CMakeLists.txt
++++ b/src/util/CMakeLists.txt
+@@ -16,8 +16,6 @@ add_library(CemuUtil
+ DXGIWrapper/DXGIWrapper.h
+ EventService.h
+ Fiber/Fiber.h
+- Fiber/FiberUnix.cpp
+- Fiber/FiberWin.cpp
+ helpers/ClassWrapper.h
+ helpers/ConcurrentQueue.h
+ helpers/enum_array.hpp
+@@ -50,8 +48,8 @@ add_library(CemuUtil
+ math/vector2.h
+ math/vector3.h
+ MemMapper/MemMapper.h
+- MemMapper/MemMapperUnix.cpp
+- MemMapper/MemMapperWin.cpp
++ SystemInfo/SystemInfo.cpp
++ SystemInfo/SystemInfo.h
+ ThreadPool/ThreadPool.cpp
+ ThreadPool/ThreadPool.h
+ tinyxml2/tinyxml2.cpp
+@@ -71,6 +69,23 @@ add_library(CemuUtil
+ Zir/Passes/ZpIRRegisterAllocator.cpp
+ )
+
++if(WIN32)
++ target_sources(CemuUtil PRIVATE Fiber/FiberWin.cpp)
++ target_sources(CemuUtil PRIVATE MemMapper/MemMapperWin.cpp)
++ target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoWin.cpp)
++elseif(UNIX)
++ target_sources(CemuUtil PRIVATE Fiber/FiberUnix.cpp)
++ target_sources(CemuUtil PRIVATE MemMapper/MemMapperUnix.cpp)
++ target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoUnix.cpp)
++ if(NOT APPLE)
++ target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoLinux.cpp)
++ else()
++ target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoMac.cpp)
++ endif()
++else()
++ target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoStub.cpp)
++endif()
++
+ set_property(TARGET CemuUtil PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+
+ target_include_directories(CemuUtil PUBLIC "../")
+diff --git a/src/util/Fiber/FiberUnix.cpp b/src/util/Fiber/FiberUnix.cpp
+index c2ced28b..7d3bf05a 100644
+--- a/src/util/Fiber/FiberUnix.cpp
++++ b/src/util/Fiber/FiberUnix.cpp
+@@ -1,5 +1,4 @@
+ #include "Fiber.h"
+-#if BOOST_OS_LINUX || BOOST_OS_MACOS
+ #include <ucontext.h>
+
+ thread_local Fiber* sCurrentFiber{};
+@@ -52,5 +51,3 @@ void* Fiber::GetFiberPrivateData()
+ {
+ return sCurrentFiber->m_privateData;
+ }
+-
+-#endif
+\ No newline at end of file
+diff --git a/src/util/Fiber/FiberWin.cpp b/src/util/Fiber/FiberWin.cpp
+index af7df700..ae5da517 100644
+--- a/src/util/Fiber/FiberWin.cpp
++++ b/src/util/Fiber/FiberWin.cpp
+@@ -1,5 +1,4 @@
+ #include "Fiber.h"
+-#if BOOST_OS_WINDOWS
+ #include <Windows.h>
+
+ thread_local Fiber* sCurrentFiber{};
+@@ -39,5 +38,3 @@ void* Fiber::GetFiberPrivateData()
+ {
+ return sCurrentFiber->m_privateData;
+ }
+-
+-#endif
+\ No newline at end of file
+diff --git a/src/util/MemMapper/MemMapperUnix.cpp b/src/util/MemMapper/MemMapperUnix.cpp
+index 0ea52aa0..0ade291d 100644
+--- a/src/util/MemMapper/MemMapperUnix.cpp
++++ b/src/util/MemMapper/MemMapperUnix.cpp
+@@ -1,6 +1,5 @@
+ #include "util/MemMapper/MemMapper.h"
+
+-#if BOOST_OS_LINUX || BOOST_OS_MACOS
+ #include <unistd.h>
+ #include <sys/mman.h>
+
+@@ -65,5 +64,3 @@ namespace MemMapper
+ }
+
+ };
+-
+-#endif
+\ No newline at end of file
+diff --git a/src/util/MemMapper/MemMapperWin.cpp b/src/util/MemMapper/MemMapperWin.cpp
+index 5c07949f..0e8d3496 100644
+--- a/src/util/MemMapper/MemMapperWin.cpp
++++ b/src/util/MemMapper/MemMapperWin.cpp
+@@ -1,7 +1,5 @@
+ #include "util/MemMapper/MemMapper.h"
+
+-#if BOOST_OS_WINDOWS
+-
+ #include <Windows.h>
+
+ namespace MemMapper
+@@ -63,5 +61,3 @@ namespace MemMapper
+ }
+
+ };
+-
+-#endif
+\ No newline at end of file
+diff --git a/src/util/SystemInfo/SystemInfo.cpp b/src/util/SystemInfo/SystemInfo.cpp
+new file mode 100644
+index 00000000..afda4e8b
--- /dev/null
+++ b/src/util/SystemInfo/SystemInfo.cpp
@@ -0,0 +1,34 @@
@@ -185,6 +341,9 @@
+ out.user = user;
+}
\ No newline at end of file
+diff --git a/src/util/SystemInfo/SystemInfo.h b/src/util/SystemInfo/SystemInfo.h
+new file mode 100644
+index 00000000..72ce98db
--- /dev/null
+++ b/src/util/SystemInfo/SystemInfo.h
@@ -0,0 +1,17 @@
@@ -193,7 +352,7 @@
+struct ProcessorTime
+{
+ uint64 idle{}, kernel{}, user{};
-+
++
+ uint64 work();
+ uint64 total();
+
@@ -204,21 +363,18 @@
+uint64 QueryRamUsage();
+void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel);
+void QueryProcTime(ProcessorTime &out);
-+void QueryCoreTimes(uint32 count, ProcessorTime out[]);
-\ No newline at end of file
++void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out);
+diff --git a/src/util/SystemInfo/SystemInfoLinux.cpp b/src/util/SystemInfo/SystemInfoLinux.cpp
+new file mode 100644
+index 00000000..d147893b
--- /dev/null
+++ b/src/util/SystemInfo/SystemInfoLinux.cpp
-@@ -0,0 +1,67 @@
-+#if BOOST_OS_LINUX
-+
+@@ -0,0 +1,46 @@
+#include "util/SystemInfo/SystemInfo.h"
+
-+#include <unistd.h>
-+#include <sys/times.h>
-+
+uint64 QueryRamUsage()
+{
-+ long page_size = sysconf(_SC_PAGESIZE);
++ static long page_size = sysconf(_SC_PAGESIZE);
+ if (page_size == -1)
+ {
+ return 0;
@@ -228,36 +384,22 @@
+ if (file)
+ {
+ file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
-+ uint64 no_pages;
-+ file >> no_pages;
++ uint64 pages;
++ file >> pages;
+
-+ return no_pages * page_size;
++ return pages * page_size;
+ }
-+ else
-+ {
-+ return 0;
-+ }
-+}
-+
-+void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
-+{
-+ struct tms time_info;
-+ clock_t clock_now = times(&time_info);
-+ clock_t clock_user = time_info.tms_utime;
-+ clock_t clock_kernel = time_info.tms_stime;
-+ out_now = static_cast<uint64>(clock_now);
-+ out_user = static_cast<uint64>(clock_user);
-+ out_kernel = static_cast<uint64>(clock_kernel);
++ return 0;
+}
+
-+void QueryCoreTimes(uint32 count, ProcessorTime out[])
++void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
+{
+ std::ifstream file("/proc/stat");
+ if (file)
+ {
+ file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+
-+ for (auto i = 0; i < count; ++i)
++ for (auto i = 0; i < out.size(); ++i)
+ {
+ uint64 user, nice, kernel, idle;
+ file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
@@ -274,14 +416,80 @@
+ for (auto i = 0; i < count; ++i) out[i] = { };
+ }
+}
+diff --git a/src/util/SystemInfo/SystemInfoMac.cpp b/src/util/SystemInfo/SystemInfoMac.cpp
+new file mode 100644
+index 00000000..608f1ffc
+--- /dev/null
++++ b/src/util/SystemInfo/SystemInfoMac.cpp
+@@ -0,0 +1,62 @@
++#include "util/SystemInfo/SystemInfo.h"
+
-+#endif
-\ No newline at end of file
++#include <unistd.h>
++#include <sys/resource.h>
++#include <sys/sysctl.h>
++#include <sys/types.h>
++#include <mach/mach.h>
++
++#include <mach/processor_info.h>
++#include <mach/mach_host.h>
++#include <mach/kern_return.h>
++
++// borrowed from https://en.wikichip.org/wiki/resident_set_size#OS_X
++uint64 QueryRamUsage()
++{
++ mach_task_basic_info info;
++ mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
++ if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS)
++ return info.resident_size;
++ return 0;
++}
++
++// apple official documentation is non-existsent.
++// based on https://github.com/giampaolo/psutil/blob/master/psutil/_psutil_osx.c#L623
++void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
++{
++ // initialize default
++ for (auto i = 0; i < out.size(); ++i)
++ {
++ out[i] = {};
++ }
++
++ natural_t cpu_count;
++ processor_info_array_t info_array;
++ mach_msg_type_number_t info_count;
++ kern_return_t error;
++
++ mach_port_t host_port = mach_host_self();
++ error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO, &cpu_count, &info_array, &info_count);
++ mach_port_deallocate(mach_task_self(), host_port);
++
++ if (error != KERN_SUCCESS)
++ return;
++
++ processor_cpu_load_info_data_t* cpuLoad = (processor_cpu_load_info_data_t*) info_array;
++
++ for (auto i = 0; i < cpu_count; ++i)
++ {
++ uint64 system = cpuLoad[i].cpu_ticks[CPU_STATE_SYSTEM];
++ uint64 user = cpuLoad[i].cpu_ticks[CPU_STATE_USER] + cpuLoad[i].cpu_ticks[CPU_STATE_NICE];
++ uint64 idle = cpuLoad[i].cpu_ticks[CPU_STATE_IDLE];
++
++ out[i].idle = idle;
++ out[i].kernel = system;
++ out[i].user = user;
++ }
++
++ int ret = vm_deallocate(mach_task_self(), (vm_address_t) info_array,
++ info_count * sizeof(int));
++ if (ret != KERN_SUCCESS)
++ cemuLog_force("vm_deallocate() failed");
++}
+diff --git a/src/util/SystemInfo/SystemInfoStub.cpp b/src/util/SystemInfo/SystemInfoStub.cpp
+new file mode 100644
+index 00000000..b6d1fc84
--- /dev/null
+++ b/src/util/SystemInfo/SystemInfoStub.cpp
-@@ -0,0 +1,25 @@
-+#if !BOOST_OS_WINDOWS && !BOOST_OS_LINUX
-+
+@@ -0,0 +1,21 @@
+#include "util/SystemInfo/SystemInfo.h"
+
+uint64 QueryRamUsage()
@@ -296,21 +504,40 @@
+ out_kernel = 0;
+}
+
-+void QueryCoreTimes(uint32 count, ProcessorTime out[])
++void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
+{
-+ for (auto i = 0; i < count; ++i)
++ for (auto i = 0; i < out.size(); ++i)
+ {
+ out[i] = { };
+ }
+}
+diff --git a/src/util/SystemInfo/SystemInfoUnix.cpp b/src/util/SystemInfo/SystemInfoUnix.cpp
+new file mode 100644
+index 00000000..87bd9f8c
+--- /dev/null
++++ b/src/util/SystemInfo/SystemInfoUnix.cpp
+@@ -0,0 +1,15 @@
++#include "util/SystemInfo/SystemInfo.h"
+
-+#endif
-\ No newline at end of file
++#include <sys/times.h>
++
++void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
++{
++ struct tms time_info;
++ clock_t clock_now = times(&time_info);
++ clock_t clock_user = time_info.tms_utime;
++ clock_t clock_kernel = time_info.tms_stime;
++ out_now = static_cast<uint64>(clock_now);
++ out_user = static_cast<uint64>(clock_user);
++ out_kernel = static_cast<uint64>(clock_kernel);
++}
++
+diff --git a/src/util/SystemInfo/SystemInfoWin.cpp b/src/util/SystemInfo/SystemInfoWin.cpp
+new file mode 100644
+index 00000000..375608ce
--- /dev/null
+++ b/src/util/SystemInfo/SystemInfoWin.cpp
-@@ -0,0 +1,72 @@
-+#if BOOST_OS_WINDOWS
-+
+@@ -0,0 +1,68 @@
+#include "util/SystemInfo/SystemInfo.h"
+
+#include <Psapi.h>
@@ -340,7 +567,7 @@
+ now.HighPart = ftime.dwHighDateTime;
+
+ if (GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fkernel, &fuser))
-+ {
++ {
+ kernel.LowPart = fkernel.dwLowDateTime;
+ kernel.HighPart = fkernel.dwHighDateTime;
+
@@ -359,14 +586,14 @@
+ }
+}
+
-+void QueryCoreTimes(uint32 count, ProcessorTime out[])
++void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
+{
+ std::vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> sppi(count);
+ if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi.data(), sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * count, nullptr)))
+ {
-+ for (auto i = 0; i < count; ++i)
++ for (auto i = 0; i < out.size(); ++i)
+ {
-+ out[i].idle = sppi[i].IdleTime.QuadPart;
++ out[i].idle = sppi[i].IdleTime.QuadPart;
+ out[i].kernel = sppi[i].KernelTime.QuadPart;
+ out[i].user = sppi[i].UserTime.QuadPart;
+ }
@@ -379,6 +606,3 @@
+ }
+ }
+}
-+
-+#endif
-\ No newline at end of file