summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kescher2022-11-20 21:42:13 +0100
committerJeremy Kescher2022-11-20 21:42:13 +0100
commit7f48d064458d767f51a7ddb11d2b857feb8e149d (patch)
tree8025d41f1b980027c6e7ee53781be97b03be2ba6
parentdddfd525e62dd86c9384760336c50851dd89e0d1 (diff)
downloadaur-7f48d064458d767f51a7ddb11d2b857feb8e149d.tar.gz
2.0-17
-rw-r--r--.SRCINFO8
-rw-r--r--PKGBUILD15
-rw-r--r--fix-range-check.diff22
-rw-r--r--overlay.diff575
4 files changed, 5 insertions, 615 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 9a9c3d8f0670..b06c55751b51 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.236
+ pkgver = 2.0.241
pkgrel = 1
url = https://cemu.info
install = cemu.install
@@ -25,21 +25,17 @@ pkgbase = cemu
optdepends = alsa-lib: Audio output
optdepends = vulkan-driver: Vulkan graphics
options = !strip
- source = git+https://github.com/cemu-project/Cemu#tag=v2.0-16
+ source = git+https://github.com/cemu-project/Cemu#tag=v2.0-17
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 = fix-range-check.diff
- source = overlay.diff
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
- sha256sums = 0887677b0e06999e516e7e3dddb4a7cb4230d2beb2f884592558811bf2ff11a2
- sha256sums = a4272ac6b31216e7226d25abeff8ee89a5551fddf791e2eb811ee2ff492fbfee
pkgname = cemu
diff --git a/PKGBUILD b/PKGBUILD
index 3c0c752765b5..d79888687d28 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: Jeremy Kescher <jeremy@kescher.at>
pkgname=cemu
-pkgver=2.0.236
+pkgver=2.0.241
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#tag=v2.0-16
+ git+https://github.com/cemu-project/Cemu#tag=v2.0-17
# submodules
git+https://github.com/mozilla/cubeb#commit=dc511c6b3597b6384d28949285b9289e009830ea
git+https://github.com/ocornut/imgui#commit=8a44c31c95c8e0217f6e1fc814cbbbcca4981f14
@@ -39,19 +39,13 @@ source=(
# cubeb submodules
git+https://github.com/arsenm/sanitizers-cmake#commit=aab6948fa863bc1cbe5d0850bc46b9ef02ed4c1a
git+https://github.com/google/googletest#commit=800f5422ac9d9e0ad59cd860a2ef3a679588acb4
- # backported patches from main
- fix-range-check.diff # https://github.com/cemu-project/Cemu/commit/57c8dec33589ff46b57041ea1c2cd9b4342e30eb
- # upstream proposed patches
- overlay.diff # 402b24ef19f401aef27c37ba580c4efe6e3d0bba (https://github.com/cemu-project/Cemu/pull/480)
)
sha256sums=('SKIP'
'SKIP'
'SKIP'
'SKIP'
'SKIP'
- 'SKIP'
- '0887677b0e06999e516e7e3dddb4a7cb4230d2beb2f884592558811bf2ff11a2'
- 'a4272ac6b31216e7226d25abeff8ee89a5551fddf791e2eb811ee2ff492fbfee')
+ 'SKIP')
pkgver() {
cd Cemu
@@ -92,9 +86,6 @@ prepare() {
# gamelist column width improvement
sed -i '/InsertColumn/s/kListIconWidth/&+8/;/SetColumnWidth/s/last_col_width/&-1/' src/gui/components/wxGameList.cpp
-
- rm -rf src/util/SystemInfo
- git apply --whitespace=nowarn "$srcdir/fix-range-check.diff" "$srcdir/overlay.diff"
}
build() {
diff --git a/fix-range-check.diff b/fix-range-check.diff
deleted file mode 100644
index 49d9e72341f8..000000000000
--- a/fix-range-check.diff
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterALU.hpp
-+++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterALU.hpp
-@@ -421,7 +421,7 @@ static void PPCInterpreter_MULLWO(PPCInterpreter_t* hCPU, uint32 opcode)
- PPC_OPC_TEMPL3_XO();
- sint64 result = (sint64)hCPU->gpr[rA] * (sint64)hCPU->gpr[rB];
- hCPU->gpr[rD] = (uint32)result;
-- if (result < -0x80000000ll && result > 0x7FFFFFFFLL)
-+ if (result < -0x80000000ll || result > 0x7FFFFFFFLL)
- {
- hCPU->spr.XER |= XER_SO;
- hCPU->spr.XER |= XER_OV;
---- a/src/Cemu/PPCAssembler/ppcAssembler.cpp
-+++ b/src/Cemu/PPCAssembler/ppcAssembler.cpp
-@@ -653,7 +653,7 @@ class EncodedOperand_MemLoc
- {
- immD = ep.Evaluate(svExpressionPart);
- sint32 imm = (sint32)immD;
-- if (imm < -32768 && imm > 32767)
-+ if (imm < -32768 || imm > 32767)
- {
- std::string msg = fmt::format("\"{}\" evaluates to offset out of range (Valid range is -32768 to 32767)", svExpressionPart);
- ppcAssembler_setError(assemblerCtx->ctx, msg);
diff --git a/overlay.diff b/overlay.diff
deleted file mode 100644
index 6cf28ef29fdf..000000000000
--- a/overlay.diff
+++ /dev/null
@@ -1,575 +0,0 @@
---- a/src/Cafe/HW/Latte/Core/LatteOverlay.cpp
-+++ b/src/Cafe/HW/Latte/Core/LatteOverlay.cpp
-@@ -12,30 +12,16 @@
- #include "imgui/imgui_extension.h"
-
- #include "input/InputManager.h"
-+#include "util/SystemInfo/SystemInfo.h"
-
- #include <cinttypes>
-
--#if BOOST_OS_WINDOWS
--#include <Psapi.h>
--#include <winternl.h>
--#pragma comment(lib, "ntdll.lib")
--#endif
--
- struct OverlayStats
- {
- OverlayStats() {};
-
- int processor_count = 1;
--
-- // cemu cpu stats
-- uint64_t last_cpu{}, kernel{}, user{};
--
-- // global cpu stats
-- struct ProcessorTime
-- {
-- uint64_t idle{}, kernel{}, user{};
-- };
--
-+ ProcessorTime processor_time_cemu;
- std::vector<ProcessorTime> processor_times;
-
- double fps{};
-@@ -562,83 +548,52 @@ void LatteOverlay_render(bool pad_view)
- }
- }
-
--
- void LatteOverlay_init()
- {
--#if BOOST_OS_WINDOWS
-- SYSTEM_INFO sys_info;
-- GetSystemInfo(&sys_info);
-- g_state.processor_count = sys_info.dwNumberOfProcessors;
-+ g_state.processor_count = GetProcessorCount();
-
- g_state.processor_times.resize(g_state.processor_count);
- g_state.cpu_per_core.resize(g_state.processor_count);
--#else
-- g_state.processor_count = 1;
--#endif
- }
-
--void LatteOverlay_updateStats(double fps, sint32 drawcalls)
-+static void UpdateStats_CemuCpu()
- {
-- if (GetConfig().overlay.position == ScreenPosition::kDisabled)
-- 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;
-+}
-
-- g_state.fps = fps;
-- g_state.draw_calls_per_frame = drawcalls;
-+static void UpdateStats_CpuPerCore()
-+{
-+ std::vector<ProcessorTime> now(g_state.processor_count);
-+ QueryCoreTimes(g_state.processor_count, now);
-
--#if BOOST_OS_WINDOWS
-- // update cemu cpu
-- FILETIME ftime, fkernel, fuser;
-- LARGE_INTEGER now, kernel, user;
-- GetSystemTimeAsFileTime(&ftime);
-- now.LowPart = ftime.dwLowDateTime;
-- now.HighPart = ftime.dwHighDateTime;
--
-- GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fkernel, &fuser);
-- kernel.LowPart = fkernel.dwLowDateTime;
-- kernel.HighPart = fkernel.dwHighDateTime;
--
-- user.LowPart = fuser.dwLowDateTime;
-- user.HighPart = fuser.dwHighDateTime;
--
-- double percent = (kernel.QuadPart - g_state.kernel) + (user.QuadPart - g_state.user);
-- percent /= (now.QuadPart - g_state.last_cpu);
-- percent /= g_state.processor_count;
-- g_state.cpu_usage = percent * 100;
-- g_state.last_cpu = now.QuadPart;
-- g_state.user = user.QuadPart;
-- g_state.kernel = kernel.QuadPart;
--
-- // update cpu per core
-- std::vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> sppi(g_state.processor_count);
-- if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi.data(), sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * g_state.processor_count, nullptr)))
-+ for (int32_t i = 0; i < g_state.processor_count; ++i)
- {
-- for (sint32 i = 0; i < g_state.processor_count; ++i)
-- {
-- const uint64 kernel_diff = sppi[i].KernelTime.QuadPart - g_state.processor_times[i].kernel;
-- const uint64 user_diff = sppi[i].UserTime.QuadPart - g_state.processor_times[i].user;
-- const uint64 idle_diff = sppi[i].IdleTime.QuadPart - g_state.processor_times[i].idle;
--
-- const auto total = kernel_diff + user_diff; // kernel time already includes idletime
-- const double cpu = total == 0 ? 0 : (1.0 - ((double)idle_diff / total)) * 100.0;
-+ double cpu = ProcessorTime::Compare(g_state.processor_times[i], now[i]);
-
-- g_state.cpu_per_core[i] = cpu;
-- //total_cpu += cpu;
-+ g_state.cpu_per_core[i] = cpu * 100;
-+ g_state.processor_times[i] = now[i];
-+ }
-+}
-
-- g_state.processor_times[i].idle = sppi[i].IdleTime.QuadPart;
-- g_state.processor_times[i].kernel = sppi[i].KernelTime.QuadPart;
-- g_state.processor_times[i].user = sppi[i].UserTime.QuadPart;
-- }
-+void LatteOverlay_updateStats(double fps, sint32 drawcalls)
-+{
-+ if (GetConfig().overlay.position == ScreenPosition::kDisabled)
-+ return;
-
-- //total_cpu /= g_state.processor_count;
-- //g_state.cpu_usage = total_cpu;
-- }
-+ g_state.fps = fps;
-+ g_state.draw_calls_per_frame = drawcalls;
-+ UpdateStats_CemuCpu();
-+ UpdateStats_CpuPerCore();
-
- // update ram
-- PROCESS_MEMORY_COUNTERS pmc{};
-- pmc.cb = sizeof(pmc);
-- GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
-- g_state.ram_usage = (pmc.WorkingSetSize / 1000) / 1000;
--#endif
-+ g_state.ram_usage = (QueryRamUsage() / 1000) / 1000;
-
- // update vram
- g_renderer->GetVRAMInfo(g_state.vramUsage, g_state.vramTotal);
---- 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
-+}
---- 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 "../")
---- 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
---- 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
---- 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
---- 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
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfo.cpp
-@@ -0,0 +1,34 @@
-+#include "util/SystemInfo/SystemInfo.h"
-+
-+uint64 ProcessorTime::work()
-+{
-+ return user + kernel;
-+}
-+
-+uint64 ProcessorTime::total()
-+{
-+ return idle + user + kernel;
-+}
-+
-+double ProcessorTime::Compare(ProcessorTime &last, ProcessorTime &now)
-+{
-+ auto dwork = now.work() - last.work();
-+ auto dtotal = now.total() - last.total();
-+
-+ return (double)dwork / dtotal;
-+}
-+
-+uint32 GetProcessorCount()
-+{
-+ return std::thread::hardware_concurrency();
-+}
-+
-+void QueryProcTime(ProcessorTime &out)
-+{
-+ uint64 now, user, kernel;
-+ QueryProcTime(now, user, kernel);
-+
-+ out.idle = now - (user + kernel);
-+ out.kernel = kernel;
-+ out.user = user;
-+}
-\ No newline at end of file
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfo.h
-@@ -0,0 +1,17 @@
-+#pragma once
-+
-+struct ProcessorTime
-+{
-+ uint64 idle{}, kernel{}, user{};
-+
-+ uint64 work();
-+ uint64 total();
-+
-+ static double Compare(ProcessorTime &last, ProcessorTime &now);
-+};
-+
-+uint32 GetProcessorCount();
-+uint64 QueryRamUsage();
-+void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel);
-+void QueryProcTime(ProcessorTime &out);
-+void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out);
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfoLinux.cpp
-@@ -0,0 +1,48 @@
-+#include "util/SystemInfo/SystemInfo.h"
-+
-+#include <unistd.h>
-+
-+uint64 QueryRamUsage()
-+{
-+ static long page_size = sysconf(_SC_PAGESIZE);
-+ if (page_size == -1)
-+ {
-+ return 0;
-+ }
-+
-+ std::ifstream file("/proc/self/statm");
-+ if (file)
-+ {
-+ file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
-+ uint64 pages;
-+ file >> pages;
-+
-+ return pages * page_size;
-+ }
-+ return 0;
-+}
-+
-+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 < out.size(); ++i)
-+ {
-+ uint64 user, nice, kernel, idle;
-+ file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
-+ file >> user >> nice >> kernel >> idle;
-+ file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
-+
-+ out[i].idle = idle;
-+ out[i].kernel = kernel;
-+ out[i].user = user + nice;
-+ }
-+ }
-+ else
-+ {
-+ for (auto i = 0; i < count; ++i) out[i] = { };
-+ }
-+}
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfoMac.cpp
-@@ -0,0 +1,62 @@
-+#include "util/SystemInfo/SystemInfo.h"
-+
-+#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");
-+}
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfoStub.cpp
-@@ -0,0 +1,21 @@
-+#include "util/SystemInfo/SystemInfo.h"
-+
-+uint64 QueryRamUsage()
-+{
-+ return 0;
-+}
-+
-+void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
-+{
-+ out_now = 0;
-+ out_user = 0;
-+ out_kernel = 0;
-+}
-+
-+void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
-+{
-+ for (auto i = 0; i < out.size(); ++i)
-+ {
-+ out[i] = { };
-+ }
-+}
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfoUnix.cpp
-@@ -0,0 +1,15 @@
-+#include "util/SystemInfo/SystemInfo.h"
-+
-+#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);
-+}
-+
---- /dev/null
-+++ b/src/util/SystemInfo/SystemInfoWin.cpp
-@@ -0,0 +1,68 @@
-+#include "util/SystemInfo/SystemInfo.h"
-+
-+#include <Psapi.h>
-+#include <winternl.h>
-+#pragma comment(lib, "ntdll.lib")
-+
-+uint64 QueryRamUsage()
-+{
-+ PROCESS_MEMORY_COUNTERS pmc{};
-+ pmc.cb = sizeof(pmc);
-+ if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))
-+ {
-+ return pmc.WorkingSetSize;
-+ }
-+ else
-+ {
-+ return 0;
-+ }
-+}
-+
-+void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
-+{
-+ FILETIME ftime, fkernel, fuser;
-+ LARGE_INTEGER now, kernel, user;
-+ GetSystemTimeAsFileTime(&ftime);
-+ now.LowPart = ftime.dwLowDateTime;
-+ now.HighPart = ftime.dwHighDateTime;
-+
-+ if (GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fkernel, &fuser))
-+ {
-+ kernel.LowPart = fkernel.dwLowDateTime;
-+ kernel.HighPart = fkernel.dwHighDateTime;
-+
-+ user.LowPart = fuser.dwLowDateTime;
-+ user.HighPart = fuser.dwHighDateTime;
-+
-+ out_now = now.QuadPart;
-+ out_user = user.QuadPart;
-+ out_kernel = kernel.QuadPart;
-+ }
-+ else
-+ {
-+ out_now = 0;
-+ out_user = 0;
-+ out_kernel = 0;
-+ }
-+}
-+
-+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 < out.size(); ++i)
-+ {
-+ out[i].idle = sppi[i].IdleTime.QuadPart;
-+ out[i].kernel = sppi[i].KernelTime.QuadPart;
-+ out[i].user = sppi[i].UserTime.QuadPart;
-+ }
-+ }
-+ else
-+ {
-+ for (auto i = 0; i < count; ++i)
-+ {
-+ out[i] = { };
-+ }
-+ }
-+}