summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------externals/cpp-httplib0
-rw-r--r--externals/microprofile/microprofile.h2
-rw-r--r--externals/microprofile/microprofileui.h75
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/audio_core/CMakeLists.txt3
-rw-r--r--src/common/bounded_threadsafe_queue.h159
-rw-r--r--src/common/detached_tasks.cpp4
-rw-r--r--src/core/CMakeLists.txt5
-rw-r--r--src/core/arm/arm_interface.cpp2
-rw-r--r--src/core/core.cpp18
-rw-r--r--src/core/core.h4
-rw-r--r--src/core/cpu_manager.cpp131
-rw-r--r--src/core/cpu_manager.h19
-rw-r--r--src/core/debugger/debugger.cpp94
-rw-r--r--src/core/hle/kernel/k_process.cpp59
-rw-r--r--src/core/hle/kernel/k_process.h16
-rw-r--r--src/core/hle/kernel/k_thread.cpp8
-rw-r--r--src/core/hle/kernel/kernel.cpp49
-rw-r--r--src/core/hle/kernel/kernel.h11
-rw-r--r--src/core/hle/kernel/svc.cpp15
-rw-r--r--src/core/hle/service/glue/notif.cpp132
-rw-r--r--src/core/hle/service/glue/notif.h48
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp4
-rw-r--r--src/input_common/CMakeLists.txt1
-rw-r--r--src/shader_recompiler/CMakeLists.txt3
-rw-r--r--src/video_core/CMakeLists.txt5
-rw-r--r--src/video_core/gpu_thread.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp51
-rw-r--r--src/web_service/telemetry_json.cpp4
-rw-r--r--src/web_service/web_backend.cpp20
-rw-r--r--src/yuzu/bootmanager.cpp10
-rw-r--r--src/yuzu/bootmanager.h12
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp7
-rw-r--r--src/yuzu/configuration/configure_dialog.h2
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp78
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp10
-rw-r--r--src/yuzu/configuration/configure_per_game.h4
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp4
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.h2
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp8
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp4
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.h2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp16
-rw-r--r--src/yuzu/debugger/wait_tree.h8
-rw-r--r--src/yuzu/game_list.cpp14
-rw-r--r--src/yuzu/game_list.h4
-rw-r--r--src/yuzu/game_list_p.h8
-rw-r--r--src/yuzu/game_list_worker.cpp12
-rw-r--r--src/yuzu/game_list_worker.h8
-rw-r--r--src/yuzu/main.cpp13
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp4
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp4
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h2
-rw-r--r--src/yuzu_cmd/yuzu.cpp6
57 files changed, 665 insertions, 532 deletions
diff --git a/externals/cpp-httplib b/externals/cpp-httplib
Subproject 9648f950f5a8a41d18833cf4a85f5821b1bcac5 Subproject 305a7abcb9b4e9e349843c6d563212e6c1bbbf2
diff --git a/externals/microprofile/microprofile.h b/externals/microprofile/microprofile.h
index a06f6457d..639f3618c 100644
--- a/externals/microprofile/microprofile.h
+++ b/externals/microprofile/microprofile.h
@@ -1246,7 +1246,7 @@ struct MicroProfileScopeLock
1246{ 1246{
1247 bool bUseLock; 1247 bool bUseLock;
1248 std::recursive_mutex& m; 1248 std::recursive_mutex& m;
1249 MicroProfileScopeLock(std::recursive_mutex& m) : bUseLock(g_bUseLock), m(m) 1249 MicroProfileScopeLock(std::recursive_mutex& m_) : bUseLock(g_bUseLock), m(m_)
1250 { 1250 {
1251 if(bUseLock) 1251 if(bUseLock)
1252 m.lock(); 1252 m.lock();
diff --git a/externals/microprofile/microprofileui.h b/externals/microprofile/microprofileui.h
index 85fbf2cb9..1357a08fd 100644
--- a/externals/microprofile/microprofileui.h
+++ b/externals/microprofile/microprofileui.h
@@ -213,8 +213,8 @@ struct MicroProfileCustom
213 213
214struct SOptionDesc 214struct SOptionDesc
215{ 215{
216 SOptionDesc(){} 216 SOptionDesc()=default;
217 SOptionDesc(uint8_t nSubType, uint8_t nIndex, const char* fmt, ...):nSubType(nSubType), nIndex(nIndex) 217 SOptionDesc(uint8_t nSubType_, uint8_t nIndex_, const char* fmt, ...):nSubType(nSubType_), nIndex(nIndex_)
218 { 218 {
219 va_list args; 219 va_list args;
220 va_start (args, fmt); 220 va_start (args, fmt);
@@ -573,10 +573,10 @@ inline void MicroProfileToolTipMeta(MicroProfileStringArray* pToolTip)
573 } 573 }
574 else 574 else
575 { 575 {
576 for(int i = 0; i < MICROPROFILE_META_MAX; ++i) 576 for(int k = 0; k < MICROPROFILE_META_MAX; ++k)
577 { 577 {
578 nMetaSumInclusive[i] += nMetaSum[i]; 578 nMetaSumInclusive[k] += nMetaSum[k];
579 nMetaSum[i] = 0; 579 nMetaSum[k] = 0;
580 } 580 }
581 } 581 }
582 break; 582 break;
@@ -708,10 +708,10 @@ inline void MicroProfileDrawFloatTooltip(uint32_t nX, uint32_t nY, uint32_t nTok
708 708
709 if(UI.nMouseLeftMod) 709 if(UI.nMouseLeftMod)
710 { 710 {
711 int nIndex = (g_MicroProfileUI.LockedToolTipFront + MICROPROFILE_TOOLTIP_MAX_LOCKED - 1) % MICROPROFILE_TOOLTIP_MAX_LOCKED; 711 int nToolTipIndex = (g_MicroProfileUI.LockedToolTipFront + MICROPROFILE_TOOLTIP_MAX_LOCKED - 1) % MICROPROFILE_TOOLTIP_MAX_LOCKED;
712 g_MicroProfileUI.nLockedToolTipColor[nIndex] = S.TimerInfo[nTimerId].nColor; 712 g_MicroProfileUI.nLockedToolTipColor[nToolTipIndex] = S.TimerInfo[nTimerId].nColor;
713 MicroProfileStringArrayCopy(&g_MicroProfileUI.LockedToolTips[nIndex], &ToolTip); 713 MicroProfileStringArrayCopy(&g_MicroProfileUI.LockedToolTips[nToolTipIndex], &ToolTip);
714 g_MicroProfileUI.LockedToolTipFront = nIndex; 714 g_MicroProfileUI.LockedToolTipFront = nToolTipIndex;
715 715
716 } 716 }
717} 717}
@@ -917,9 +917,8 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
917 float fStart = floor(fMsBase*fRcpStep) * fStep; 917 float fStart = floor(fMsBase*fRcpStep) * fStep;
918 for(float f = fStart; f < fMsEnd; ) 918 for(float f = fStart; f < fMsEnd; )
919 { 919 {
920 float fStart = f;
921 float fNext = f + fStep; 920 float fNext = f + fStep;
922 MicroProfileDrawBox(((fStart-fMsBase) * fMsToScreen), nBaseY, (fNext-fMsBase) * fMsToScreen+1, nBaseY + nHeight, UI.nOpacityBackground | g_nMicroProfileBackColors[nColorIndex++ & 1]); 921 MicroProfileDrawBox(((f-fMsBase) * fMsToScreen), nBaseY, (fNext-fMsBase) * fMsToScreen+1, nBaseY + nHeight, UI.nOpacityBackground | g_nMicroProfileBackColors[nColorIndex++ & 1]);
923 f = fNext; 922 f = fNext;
924 } 923 }
925 } 924 }
@@ -1116,9 +1115,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
1116 1115
1117 nMaxStackDepth = MicroProfileMax(nMaxStackDepth, nStackPos); 1116 nMaxStackDepth = MicroProfileMax(nMaxStackDepth, nStackPos);
1118 float fMsStart = fToMs * MicroProfileLogTickDifference(nBaseTicks, nTickStart); 1117 float fMsStart = fToMs * MicroProfileLogTickDifference(nBaseTicks, nTickStart);
1119 float fMsEnd = fToMs * MicroProfileLogTickDifference(nBaseTicks, nTickEnd); 1118 float fMsEnd2 = fToMs * MicroProfileLogTickDifference(nBaseTicks, nTickEnd);
1120 float fXStart = fMsStart * fMsToScreen; 1119 float fXStart = fMsStart * fMsToScreen;
1121 float fXEnd = fMsEnd * fMsToScreen; 1120 float fXEnd = fMsEnd2 * fMsToScreen;
1122 float fYStart = (float)(nY + nStackPos * nYDelta); 1121 float fYStart = (float)(nY + nStackPos * nYDelta);
1123 float fYEnd = fYStart + (MICROPROFILE_DETAILED_BAR_HEIGHT); 1122 float fYEnd = fYStart + (MICROPROFILE_DETAILED_BAR_HEIGHT);
1124 float fXDist = MicroProfileMax(fXStart - fMouseX, fMouseX - fXEnd); 1123 float fXDist = MicroProfileMax(fXStart - fMouseX, fMouseX - fXEnd);
@@ -1269,22 +1268,22 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
1269 if(UI.nRangeBegin != UI.nRangeEnd) 1268 if(UI.nRangeBegin != UI.nRangeEnd)
1270 { 1269 {
1271 float fMsStart = fToMsCpu * MicroProfileLogTickDifference(nBaseTicksCpu, UI.nRangeBegin); 1270 float fMsStart = fToMsCpu * MicroProfileLogTickDifference(nBaseTicksCpu, UI.nRangeBegin);
1272 float fMsEnd = fToMsCpu * MicroProfileLogTickDifference(nBaseTicksCpu, UI.nRangeEnd); 1271 float fMsEnd3 = fToMsCpu * MicroProfileLogTickDifference(nBaseTicksCpu, UI.nRangeEnd);
1273 float fXStart = fMsStart * fMsToScreen; 1272 float fXStart = fMsStart * fMsToScreen;
1274 float fXEnd = fMsEnd * fMsToScreen; 1273 float fXEnd = fMsEnd3 * fMsToScreen;
1275 MicroProfileDrawBox(fXStart, nBaseY, fXEnd, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT, MicroProfileBoxTypeFlat); 1274 MicroProfileDrawBox(fXStart, nBaseY, fXEnd, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT, MicroProfileBoxTypeFlat);
1276 MicroProfileDrawLineVertical(fXStart, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT | 0x44000000); 1275 MicroProfileDrawLineVertical(fXStart, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT | 0x44000000);
1277 MicroProfileDrawLineVertical(fXEnd, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT | 0x44000000); 1276 MicroProfileDrawLineVertical(fXEnd, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT | 0x44000000);
1278 1277
1279 fMsStart += fDetailedOffset; 1278 fMsStart += fDetailedOffset;
1280 fMsEnd += fDetailedOffset; 1279 fMsEnd3 += fDetailedOffset;
1281 char sBuffer[32]; 1280 char sBuffer[32];
1282 uint32_t nLenStart = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsStart); 1281 uint32_t nLenStart = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsStart);
1283 float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart); 1282 float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
1284 float fStartTextX = fXStart - fStartTextWidth - 2; 1283 float fStartTextX = fXStart - fStartTextWidth - 2;
1285 MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); 1284 MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
1286 MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart); 1285 MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
1287 uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd); 1286 uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd3);
1288 MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); 1287 MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
1289 MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd); 1288 MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
1290 1289
@@ -1297,9 +1296,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
1297 if(UI.nRangeBeginGpu != UI.nRangeEndGpu) 1296 if(UI.nRangeBeginGpu != UI.nRangeEndGpu)
1298 { 1297 {
1299 float fMsStart = fToMsGpu * MicroProfileLogTickDifference(nBaseTicksGpu, UI.nRangeBeginGpu); 1298 float fMsStart = fToMsGpu * MicroProfileLogTickDifference(nBaseTicksGpu, UI.nRangeBeginGpu);
1300 float fMsEnd = fToMsGpu * MicroProfileLogTickDifference(nBaseTicksGpu, UI.nRangeEndGpu); 1299 float fMsEnd4 = fToMsGpu * MicroProfileLogTickDifference(nBaseTicksGpu, UI.nRangeEndGpu);
1301 float fXStart = fMsStart * fMsToScreen; 1300 float fXStart = fMsStart * fMsToScreen;
1302 float fXEnd = fMsEnd * fMsToScreen; 1301 float fXEnd = fMsEnd4 * fMsToScreen;
1303 MicroProfileDrawBox(fXStart, nBaseY, fXEnd, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT_GPU, MicroProfileBoxTypeFlat); 1302 MicroProfileDrawBox(fXStart, nBaseY, fXEnd, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT_GPU, MicroProfileBoxTypeFlat);
1304 MicroProfileDrawLineVertical(fXStart, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT_GPU | 0x44000000); 1303 MicroProfileDrawLineVertical(fXStart, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT_GPU | 0x44000000);
1305 MicroProfileDrawLineVertical(fXEnd, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT_GPU | 0x44000000); 1304 MicroProfileDrawLineVertical(fXEnd, nBaseY, nHeight, MICROPROFILE_FRAME_COLOR_HIGHTLIGHT_GPU | 0x44000000);
@@ -1307,14 +1306,14 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
1307 nBaseY += MICROPROFILE_TEXT_HEIGHT+1; 1306 nBaseY += MICROPROFILE_TEXT_HEIGHT+1;
1308 1307
1309 fMsStart += fDetailedOffset; 1308 fMsStart += fDetailedOffset;
1310 fMsEnd += fDetailedOffset; 1309 fMsEnd4 += fDetailedOffset;
1311 char sBuffer[32]; 1310 char sBuffer[32];
1312 uint32_t nLenStart = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsStart); 1311 uint32_t nLenStart = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsStart);
1313 float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart); 1312 float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
1314 float fStartTextX = fXStart - fStartTextWidth - 2; 1313 float fStartTextX = fXStart - fStartTextWidth - 2;
1315 MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); 1314 MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
1316 MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart); 1315 MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
1317 uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd); 1316 uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd4);
1318 MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); 1317 MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
1319 MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd); 1318 MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
1320 } 1319 }
@@ -1716,8 +1715,8 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
1716 uint32_t nTextCount = 0; 1715 uint32_t nTextCount = 0;
1717 uint32_t nGraphIndex = (S.nGraphPut + MICROPROFILE_GRAPH_HISTORY - int(MICROPROFILE_GRAPH_HISTORY*(1.f - fMouseXPrc))) % MICROPROFILE_GRAPH_HISTORY; 1716 uint32_t nGraphIndex = (S.nGraphPut + MICROPROFILE_GRAPH_HISTORY - int(MICROPROFILE_GRAPH_HISTORY*(1.f - fMouseXPrc))) % MICROPROFILE_GRAPH_HISTORY;
1718 1717
1719 uint32_t nX = UI.nMouseX; 1718 uint32_t nMouseX = UI.nMouseX;
1720 uint32_t nY = UI.nMouseY + 20; 1719 uint32_t nMouseY = UI.nMouseY + 20;
1721 1720
1722 for(uint32_t i = 0; i < MICROPROFILE_MAX_GRAPHS; ++i) 1721 for(uint32_t i = 0; i < MICROPROFILE_MAX_GRAPHS; ++i)
1723 { 1722 {
@@ -1736,7 +1735,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
1736 } 1735 }
1737 if(nTextCount) 1736 if(nTextCount)
1738 { 1737 {
1739 MicroProfileDrawFloatWindow(nX, nY, Strings.ppStrings, Strings.nNumStrings, 0, pColors); 1738 MicroProfileDrawFloatWindow(nMouseX, nMouseY, Strings.ppStrings, Strings.nNumStrings, 0, pColors);
1740 } 1739 }
1741 1740
1742 if(UI.nMouseRight) 1741 if(UI.nMouseRight)
@@ -2321,8 +2320,8 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
2321 uint32_t nMenuX[MICROPROFILE_MENU_MAX] = {0}; 2320 uint32_t nMenuX[MICROPROFILE_MENU_MAX] = {0};
2322 uint32_t nNumMenuItems = 0; 2321 uint32_t nNumMenuItems = 0;
2323 2322
2324 int nLen = snprintf(buffer, 127, "MicroProfile"); 2323 int nMPTextLen = snprintf(buffer, 127, "MicroProfile");
2325 MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen); 2324 MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nMPTextLen);
2326 nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1); 2325 nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1);
2327 pMenuText[nNumMenuItems++] = "Mode"; 2326 pMenuText[nNumMenuItems++] = "Mode";
2328 pMenuText[nNumMenuItems++] = "Groups"; 2327 pMenuText[nNumMenuItems++] = "Groups";
@@ -2438,16 +2437,16 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
2438 int nNumLines = 0; 2437 int nNumLines = 0;
2439 bool bSelected = false; 2438 bool bSelected = false;
2440 const char* pString = CB(nNumLines, &bSelected); 2439 const char* pString = CB(nNumLines, &bSelected);
2441 uint32_t nWidth = 0, nHeight = 0; 2440 uint32_t nTextWidth = 0, nTextHeight = 0;
2442 while(pString) 2441 while(pString)
2443 { 2442 {
2444 nWidth = MicroProfileMax<int>(nWidth, (int)strlen(pString)); 2443 nTextWidth = MicroProfileMax<int>(nTextWidth, (int)strlen(pString));
2445 nNumLines++; 2444 nNumLines++;
2446 pString = CB(nNumLines, &bSelected); 2445 pString = CB(nNumLines, &bSelected);
2447 } 2446 }
2448 nWidth = (2+nWidth) * (MICROPROFILE_TEXT_WIDTH+1); 2447 nTextWidth = (2+nTextWidth) * (MICROPROFILE_TEXT_WIDTH+1);
2449 nHeight = nNumLines * (MICROPROFILE_TEXT_HEIGHT+1); 2448 nTextHeight = nNumLines * (MICROPROFILE_TEXT_HEIGHT+1);
2450 if(UI.nMouseY <= nY + nHeight+0 && UI.nMouseY >= nY-0 && UI.nMouseX <= nX + nWidth + 0 && UI.nMouseX >= nX - 0) 2449 if(UI.nMouseY <= nY + nTextHeight+0 && UI.nMouseY >= nY-0 && UI.nMouseX <= nX + nTextWidth + 0 && UI.nMouseX >= nX - 0)
2451 { 2450 {
2452 UI.nActiveMenu = nMenu; 2451 UI.nActiveMenu = nMenu;
2453 } 2452 }
@@ -2455,21 +2454,21 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
2455 { 2454 {
2456 UI.nActiveMenu = UINT32_MAX; 2455 UI.nActiveMenu = UINT32_MAX;
2457 } 2456 }
2458 MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000|g_nMicroProfileBackColors[1]); 2457 MicroProfileDrawBox(nX, nY, nX + nTextWidth, nY + nTextHeight, 0xff000000|g_nMicroProfileBackColors[1]);
2459 for(int i = 0; i < nNumLines; ++i) 2458 for(int i = 0; i < nNumLines; ++i)
2460 { 2459 {
2461 bool bSelected = false; 2460 bool bSelected2 = false;
2462 const char* pString = CB(i, &bSelected); 2461 const char* pString2 = CB(i, &bSelected2);
2463 if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1) 2462 if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1)
2464 { 2463 {
2465 if(UI.nMouseLeft || UI.nMouseRight) 2464 if(UI.nMouseLeft || UI.nMouseRight)
2466 { 2465 {
2467 CBClick[nMenu](i); 2466 CBClick[nMenu](i);
2468 } 2467 }
2469 MicroProfileDrawBox(nX, nY, nX + nWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888); 2468 MicroProfileDrawBox(nX, nY, nX + nTextWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888);
2470 } 2469 }
2471 int nLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected ? '*' : ' ' ,pString); 2470 int nTextLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected2 ? '*' : ' ' ,pString2);
2472 MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen); 2471 MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nTextLen);
2473 nY += MICROPROFILE_TEXT_HEIGHT+1; 2472 nY += MICROPROFILE_TEXT_HEIGHT+1;
2474 } 2473 }
2475 } 2474 }
@@ -2605,7 +2604,7 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
2605 for(uint32_t i = 0; i < nCount; ++i) 2604 for(uint32_t i = 0; i < nCount; ++i)
2606 { 2605 {
2607 nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); 2606 nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
2608 uint32_t nWidth = MicroProfileMin(nMaxWidth, (uint32_t)(nMaxWidth * pMs[i] * fRcpReference)); 2607 nWidth = MicroProfileMin(nMaxWidth, (uint32_t)(nMaxWidth * pMs[i] * fRcpReference));
2609 MicroProfileDrawBox(nMaxOffsetX, nOffsetY, nMaxOffsetX+nWidth, nOffsetY+MICROPROFILE_TEXT_HEIGHT, pColors[i]|0xff000000); 2608 MicroProfileDrawBox(nMaxOffsetX, nOffsetY, nMaxOffsetX+nWidth, nOffsetY+MICROPROFILE_TEXT_HEIGHT, pColors[i]|0xff000000);
2610 } 2609 }
2611 } 2610 }
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9182dbfd4..39d038493 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -65,6 +65,10 @@ if (MSVC)
65 /we4305 # 'context': truncation from 'type1' to 'type2' 65 /we4305 # 'context': truncation from 'type1' to 'type2'
66 /we4388 # 'expression': signed/unsigned mismatch 66 /we4388 # 'expression': signed/unsigned mismatch
67 /we4389 # 'operator': signed/unsigned mismatch 67 /we4389 # 'operator': signed/unsigned mismatch
68 /we4456 # Declaration of 'identifier' hides previous local declaration
69 /we4457 # Declaration of 'identifier' hides function parameter
70 /we4458 # Declaration of 'identifier' hides class member
71 /we4459 # Declaration of 'identifier' hides global declaration
68 /we4505 # 'function': unreferenced local function has been removed 72 /we4505 # 'function': unreferenced local function has been removed
69 /we4547 # 'operator': operator before comma has no effect; expected operator with side-effect 73 /we4547 # 'operator': operator before comma has no effect; expected operator with side-effect
70 /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? 74 /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
@@ -92,6 +96,7 @@ else()
92 -Werror=missing-declarations 96 -Werror=missing-declarations
93 -Werror=missing-field-initializers 97 -Werror=missing-field-initializers
94 -Werror=reorder 98 -Werror=reorder
99 -Werror=shadow
95 -Werror=sign-compare 100 -Werror=sign-compare
96 -Werror=switch 101 -Werror=switch
97 -Werror=uninitialized 102 -Werror=uninitialized
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index e553b8203..89575a53e 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -49,9 +49,6 @@ if (NOT MSVC)
49 target_compile_options(audio_core PRIVATE 49 target_compile_options(audio_core PRIVATE
50 -Werror=conversion 50 -Werror=conversion
51 -Werror=ignored-qualifiers 51 -Werror=ignored-qualifiers
52 -Werror=shadow
53 -Werror=unused-parameter
54 -Werror=unused-variable
55 52
56 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 53 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
57 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 54 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h
index e83064c7f..7e465549b 100644
--- a/src/common/bounded_threadsafe_queue.h
+++ b/src/common/bounded_threadsafe_queue.h
@@ -1,10 +1,7 @@
1// SPDX-FileCopyrightText: Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se> 1// SPDX-FileCopyrightText: Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se>
2// SPDX-License-Identifier: MIT 2// SPDX-License-Identifier: MIT
3
3#pragma once 4#pragma once
4#ifdef _MSC_VER
5#pragma warning(push)
6#pragma warning(disable : 4324)
7#endif
8 5
9#include <atomic> 6#include <atomic>
10#include <bit> 7#include <bit>
@@ -12,105 +9,63 @@
12#include <memory> 9#include <memory>
13#include <mutex> 10#include <mutex>
14#include <new> 11#include <new>
15#include <stdexcept>
16#include <stop_token> 12#include <stop_token>
17#include <type_traits> 13#include <type_traits>
18#include <utility> 14#include <utility>
19 15
20namespace Common { 16namespace Common {
21namespace mpsc { 17
22#if defined(__cpp_lib_hardware_interference_size) 18#if defined(__cpp_lib_hardware_interference_size)
23constexpr size_t hardware_interference_size = std::hardware_destructive_interference_size; 19constexpr size_t hardware_interference_size = std::hardware_destructive_interference_size;
24#else 20#else
25constexpr size_t hardware_interference_size = 64; 21constexpr size_t hardware_interference_size = 64;
26#endif 22#endif
27 23
28template <typename T> 24#ifdef _MSC_VER
29using AlignedAllocator = std::allocator<T>; 25#pragma warning(push)
30 26#pragma warning(disable : 4324)
31template <typename T> 27#endif
32struct Slot {
33 ~Slot() noexcept {
34 if (turn.test()) {
35 destroy();
36 }
37 }
38
39 template <typename... Args>
40 void construct(Args&&... args) noexcept {
41 static_assert(std::is_nothrow_constructible_v<T, Args&&...>,
42 "T must be nothrow constructible with Args&&...");
43 std::construct_at(reinterpret_cast<T*>(&storage), std::forward<Args>(args)...);
44 }
45
46 void destroy() noexcept {
47 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible");
48 std::destroy_at(reinterpret_cast<T*>(&storage));
49 }
50
51 T&& move() noexcept {
52 return reinterpret_cast<T&&>(storage);
53 }
54
55 // Align to avoid false sharing between adjacent slots
56 alignas(hardware_interference_size) std::atomic_flag turn{};
57 struct aligned_store {
58 struct type {
59 alignas(T) unsigned char data[sizeof(T)];
60 };
61 };
62 typename aligned_store::type storage;
63};
64 28
65template <typename T, typename Allocator = AlignedAllocator<Slot<T>>> 29template <typename T, size_t capacity = 0x400>
66class Queue { 30class MPSCQueue {
67public: 31public:
68 explicit Queue(const size_t capacity, const Allocator& allocator = Allocator()) 32 explicit MPSCQueue() : allocator{std::allocator<Slot<T>>()} {
69 : allocator_(allocator) {
70 if (capacity < 1) {
71 throw std::invalid_argument("capacity < 1");
72 }
73 // Ensure that the queue length is an integer power of 2
74 // This is so that idx(i) can be a simple i & mask_ insted of i % capacity
75 // https://github.com/rigtorp/MPMCQueue/pull/36
76 if (!std::has_single_bit(capacity)) {
77 throw std::invalid_argument("capacity must be an integer power of 2");
78 }
79
80 mask_ = capacity - 1;
81
82 // Allocate one extra slot to prevent false sharing on the last slot 33 // Allocate one extra slot to prevent false sharing on the last slot
83 slots_ = allocator_.allocate(mask_ + 2); 34 slots = allocator.allocate(capacity + 1);
84 // Allocators are not required to honor alignment for over-aligned types 35 // Allocators are not required to honor alignment for over-aligned types
85 // (see http://eel.is/c++draft/allocator.requirements#10) so we verify 36 // (see http://eel.is/c++draft/allocator.requirements#10) so we verify
86 // alignment here 37 // alignment here
87 if (reinterpret_cast<uintptr_t>(slots_) % alignof(Slot<T>) != 0) { 38 if (reinterpret_cast<uintptr_t>(slots) % alignof(Slot<T>) != 0) {
88 allocator_.deallocate(slots_, mask_ + 2); 39 allocator.deallocate(slots, capacity + 1);
89 throw std::bad_alloc(); 40 throw std::bad_alloc();
90 } 41 }
91 for (size_t i = 0; i < mask_ + 1; ++i) { 42 for (size_t i = 0; i < capacity; ++i) {
92 std::construct_at(&slots_[i]); 43 std::construct_at(&slots[i]);
93 } 44 }
45 static_assert(std::has_single_bit(capacity), "capacity must be an integer power of 2");
94 static_assert(alignof(Slot<T>) == hardware_interference_size, 46 static_assert(alignof(Slot<T>) == hardware_interference_size,
95 "Slot must be aligned to cache line boundary to prevent false sharing"); 47 "Slot must be aligned to cache line boundary to prevent false sharing");
96 static_assert(sizeof(Slot<T>) % hardware_interference_size == 0, 48 static_assert(sizeof(Slot<T>) % hardware_interference_size == 0,
97 "Slot size must be a multiple of cache line size to prevent " 49 "Slot size must be a multiple of cache line size to prevent "
98 "false sharing between adjacent slots"); 50 "false sharing between adjacent slots");
99 static_assert(sizeof(Queue) % hardware_interference_size == 0, 51 static_assert(sizeof(MPSCQueue) % hardware_interference_size == 0,
100 "Queue size must be a multiple of cache line size to " 52 "Queue size must be a multiple of cache line size to "
101 "prevent false sharing between adjacent queues"); 53 "prevent false sharing between adjacent queues");
102 } 54 }
103 55
104 ~Queue() noexcept { 56 ~MPSCQueue() noexcept {
105 for (size_t i = 0; i < mask_ + 1; ++i) { 57 for (size_t i = 0; i < capacity; ++i) {
106 slots_[i].~Slot(); 58 std::destroy_at(&slots[i]);
107 } 59 }
108 allocator_.deallocate(slots_, mask_ + 2); 60 allocator.deallocate(slots, capacity + 1);
109 } 61 }
110 62
111 // non-copyable and non-movable 63 // The queue must be both non-copyable and non-movable
112 Queue(const Queue&) = delete; 64 MPSCQueue(const MPSCQueue&) = delete;
113 Queue& operator=(const Queue&) = delete; 65 MPSCQueue& operator=(const MPSCQueue&) = delete;
66
67 MPSCQueue(MPSCQueue&&) = delete;
68 MPSCQueue& operator=(MPSCQueue&&) = delete;
114 69
115 void Push(const T& v) noexcept { 70 void Push(const T& v) noexcept {
116 static_assert(std::is_nothrow_copy_constructible_v<T>, 71 static_assert(std::is_nothrow_copy_constructible_v<T>,
@@ -125,8 +80,8 @@ public:
125 80
126 void Pop(T& v, std::stop_token stop) noexcept { 81 void Pop(T& v, std::stop_token stop) noexcept {
127 auto const tail = tail_.fetch_add(1); 82 auto const tail = tail_.fetch_add(1);
128 auto& slot = slots_[idx(tail)]; 83 auto& slot = slots[idx(tail)];
129 if (false == slot.turn.test()) { 84 if (!slot.turn.test()) {
130 std::unique_lock lock{cv_mutex}; 85 std::unique_lock lock{cv_mutex};
131 cv.wait(lock, stop, [&slot] { return slot.turn.test(); }); 86 cv.wait(lock, stop, [&slot] { return slot.turn.test(); });
132 } 87 }
@@ -137,12 +92,46 @@ public:
137 } 92 }
138 93
139private: 94private:
95 template <typename U = T>
96 struct Slot {
97 ~Slot() noexcept {
98 if (turn.test()) {
99 destroy();
100 }
101 }
102
103 template <typename... Args>
104 void construct(Args&&... args) noexcept {
105 static_assert(std::is_nothrow_constructible_v<U, Args&&...>,
106 "T must be nothrow constructible with Args&&...");
107 std::construct_at(reinterpret_cast<U*>(&storage), std::forward<Args>(args)...);
108 }
109
110 void destroy() noexcept {
111 static_assert(std::is_nothrow_destructible_v<U>, "T must be nothrow destructible");
112 std::destroy_at(reinterpret_cast<U*>(&storage));
113 }
114
115 U&& move() noexcept {
116 return reinterpret_cast<U&&>(storage);
117 }
118
119 // Align to avoid false sharing between adjacent slots
120 alignas(hardware_interference_size) std::atomic_flag turn{};
121 struct aligned_store {
122 struct type {
123 alignas(U) unsigned char data[sizeof(U)];
124 };
125 };
126 typename aligned_store::type storage;
127 };
128
140 template <typename... Args> 129 template <typename... Args>
141 void emplace(Args&&... args) noexcept { 130 void emplace(Args&&... args) noexcept {
142 static_assert(std::is_nothrow_constructible_v<T, Args&&...>, 131 static_assert(std::is_nothrow_constructible_v<T, Args&&...>,
143 "T must be nothrow constructible with Args&&..."); 132 "T must be nothrow constructible with Args&&...");
144 auto const head = head_.fetch_add(1); 133 auto const head = head_.fetch_add(1);
145 auto& slot = slots_[idx(head)]; 134 auto& slot = slots[idx(head)];
146 slot.turn.wait(true); 135 slot.turn.wait(true);
147 slot.construct(std::forward<Args>(args)...); 136 slot.construct(std::forward<Args>(args)...);
148 slot.turn.test_and_set(); 137 slot.turn.test_and_set();
@@ -150,31 +139,29 @@ private:
150 } 139 }
151 140
152 constexpr size_t idx(size_t i) const noexcept { 141 constexpr size_t idx(size_t i) const noexcept {
153 return i & mask_; 142 return i & mask;
154 } 143 }
155 144
156 std::conditional_t<true, std::condition_variable_any, std::condition_variable> cv; 145 static constexpr size_t mask = capacity - 1;
157 std::mutex cv_mutex;
158 size_t mask_;
159 Slot<T>* slots_;
160 [[no_unique_address]] Allocator allocator_;
161 146
162 // Align to avoid false sharing between head_ and tail_ 147 // Align to avoid false sharing between head_ and tail_
163 alignas(hardware_interference_size) std::atomic<size_t> head_{0}; 148 alignas(hardware_interference_size) std::atomic<size_t> head_{0};
164 alignas(hardware_interference_size) std::atomic<size_t> tail_{0}; 149 alignas(hardware_interference_size) std::atomic<size_t> tail_{0};
165 150
151 std::mutex cv_mutex;
152 std::condition_variable_any cv;
153
154 Slot<T>* slots;
155 [[no_unique_address]] std::allocator<Slot<T>> allocator;
156
166 static_assert(std::is_nothrow_copy_assignable_v<T> || std::is_nothrow_move_assignable_v<T>, 157 static_assert(std::is_nothrow_copy_assignable_v<T> || std::is_nothrow_move_assignable_v<T>,
167 "T must be nothrow copy or move assignable"); 158 "T must be nothrow copy or move assignable");
168 159
169 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible"); 160 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible");
170}; 161};
171} // namespace mpsc
172
173template <typename T, typename Allocator = mpsc::AlignedAllocator<mpsc::Slot<T>>>
174using MPSCQueue = mpsc::Queue<T, Allocator>;
175
176} // namespace Common
177 162
178#ifdef _MSC_VER 163#ifdef _MSC_VER
179#pragma warning(pop) 164#pragma warning(pop)
180#endif 165#endif
166
167} // namespace Common
diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp
index c1362631e..ec31d0b88 100644
--- a/src/common/detached_tasks.cpp
+++ b/src/common/detached_tasks.cpp
@@ -33,9 +33,9 @@ void DetachedTasks::AddTask(std::function<void()> task) {
33 ++instance->count; 33 ++instance->count;
34 std::thread([task{std::move(task)}]() { 34 std::thread([task{std::move(task)}]() {
35 task(); 35 task();
36 std::unique_lock lock{instance->mutex}; 36 std::unique_lock thread_lock{instance->mutex};
37 --instance->count; 37 --instance->count;
38 std::notify_all_at_thread_exit(instance->cv, std::move(lock)); 38 std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock));
39 }).detach(); 39 }).detach();
40} 40}
41 41
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2bd720f08..670410e75 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -743,16 +743,11 @@ if (MSVC)
743 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data 743 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
744 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch 744 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
745 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 745 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
746 /we4456 # Declaration of 'identifier' hides previous local declaration
747 /we4457 # Declaration of 'identifier' hides function parameter
748 /we4458 # Declaration of 'identifier' hides class member
749 /we4459 # Declaration of 'identifier' hides global declaration
750 ) 746 )
751else() 747else()
752 target_compile_options(core PRIVATE 748 target_compile_options(core PRIVATE
753 -Werror=conversion 749 -Werror=conversion
754 -Werror=ignored-qualifiers 750 -Werror=ignored-qualifiers
755 -Werror=shadow
756 751
757 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> 752 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess>
758 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 753 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 9b5a5ca57..9a285dfc6 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -107,6 +107,7 @@ void ARM_Interface::Run() {
107 } 107 }
108 108
109 // Otherwise, run the thread. 109 // Otherwise, run the thread.
110 system.EnterDynarmicProfile();
110 if (current_thread->GetStepState() == StepState::StepPending) { 111 if (current_thread->GetStepState() == StepState::StepPending) {
111 hr = StepJit(); 112 hr = StepJit();
112 113
@@ -116,6 +117,7 @@ void ARM_Interface::Run() {
116 } else { 117 } else {
117 hr = RunJit(); 118 hr = RunJit();
118 } 119 }
120 system.ExitDynarmicProfile();
119 121
120 // Notify the debugger and go to sleep if a breakpoint was hit. 122 // Notify the debugger and go to sleep if a breakpoint was hit.
121 if (Has(hr, breakpoint)) { 123 if (Has(hr, breakpoint)) {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 954136adb..7723d9782 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -138,7 +138,6 @@ struct System::Impl {
138 138
139 kernel.Suspend(false); 139 kernel.Suspend(false);
140 core_timing.SyncPause(false); 140 core_timing.SyncPause(false);
141 cpu_manager.Pause(false);
142 is_paused = false; 141 is_paused = false;
143 142
144 return status; 143 return status;
@@ -150,25 +149,22 @@ struct System::Impl {
150 149
151 core_timing.SyncPause(true); 150 core_timing.SyncPause(true);
152 kernel.Suspend(true); 151 kernel.Suspend(true);
153 cpu_manager.Pause(true);
154 is_paused = true; 152 is_paused = true;
155 153
156 return status; 154 return status;
157 } 155 }
158 156
159 std::unique_lock<std::mutex> StallCPU() { 157 std::unique_lock<std::mutex> StallProcesses() {
160 std::unique_lock<std::mutex> lk(suspend_guard); 158 std::unique_lock<std::mutex> lk(suspend_guard);
161 kernel.Suspend(true); 159 kernel.Suspend(true);
162 core_timing.SyncPause(true); 160 core_timing.SyncPause(true);
163 cpu_manager.Pause(true);
164 return lk; 161 return lk;
165 } 162 }
166 163
167 void UnstallCPU() { 164 void UnstallProcesses() {
168 if (!is_paused) { 165 if (!is_paused) {
169 core_timing.SyncPause(false); 166 core_timing.SyncPause(false);
170 kernel.Suspend(false); 167 kernel.Suspend(false);
171 cpu_manager.Pause(false);
172 } 168 }
173 } 169 }
174 170
@@ -334,6 +330,8 @@ struct System::Impl {
334 gpu_core->NotifyShutdown(); 330 gpu_core->NotifyShutdown();
335 } 331 }
336 332
333 kernel.ShutdownCores();
334 cpu_manager.Shutdown();
337 debugger.reset(); 335 debugger.reset();
338 services.reset(); 336 services.reset();
339 service_manager.reset(); 337 service_manager.reset();
@@ -499,12 +497,12 @@ void System::DetachDebugger() {
499 } 497 }
500} 498}
501 499
502std::unique_lock<std::mutex> System::StallCPU() { 500std::unique_lock<std::mutex> System::StallProcesses() {
503 return impl->StallCPU(); 501 return impl->StallProcesses();
504} 502}
505 503
506void System::UnstallCPU() { 504void System::UnstallProcesses() {
507 impl->UnstallCPU(); 505 impl->UnstallProcesses();
508} 506}
509 507
510void System::InitializeDebugger() { 508void System::InitializeDebugger() {
diff --git a/src/core/core.h b/src/core/core.h
index 5c367349e..60efe4410 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -163,8 +163,8 @@ public:
163 /// Forcibly detach the debugger if it is running. 163 /// Forcibly detach the debugger if it is running.
164 void DetachDebugger(); 164 void DetachDebugger();
165 165
166 std::unique_lock<std::mutex> StallCPU(); 166 std::unique_lock<std::mutex> StallProcesses();
167 void UnstallCPU(); 167 void UnstallProcesses();
168 168
169 /** 169 /**
170 * Initialize the debugger. 170 * Initialize the debugger.
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index b4718fbbe..1c07dc90e 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -16,31 +16,28 @@
16 16
17namespace Core { 17namespace Core {
18 18
19CpuManager::CpuManager(System& system_) 19CpuManager::CpuManager(System& system_) : system{system_} {}
20 : pause_barrier{std::make_unique<Common::Barrier>(1)}, system{system_} {}
21CpuManager::~CpuManager() = default; 20CpuManager::~CpuManager() = default;
22 21
23void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, 22void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
24 std::size_t core) { 23 std::size_t core) {
25 cpu_manager.RunThread(stop_token, core); 24 cpu_manager.RunThread(core);
26} 25}
27 26
28void CpuManager::Initialize() { 27void CpuManager::Initialize() {
29 running_mode = true; 28 num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
30 if (is_multicore) { 29
31 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 30 for (std::size_t core = 0; core < num_cores; core++) {
32 core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); 31 core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
33 }
34 pause_barrier = std::make_unique<Common::Barrier>(Core::Hardware::NUM_CPU_CORES + 1);
35 } else {
36 core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0);
37 pause_barrier = std::make_unique<Common::Barrier>(2);
38 } 32 }
39} 33}
40 34
41void CpuManager::Shutdown() { 35void CpuManager::Shutdown() {
42 running_mode = false; 36 for (std::size_t core = 0; core < num_cores; core++) {
43 Pause(false); 37 if (core_data[core].host_thread.joinable()) {
38 core_data[core].host_thread.join();
39 }
40 }
44} 41}
45 42
46std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { 43std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() {
@@ -51,8 +48,8 @@ std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() {
51 return IdleThreadFunction; 48 return IdleThreadFunction;
52} 49}
53 50
54std::function<void(void*)> CpuManager::GetSuspendThreadStartFunc() { 51std::function<void(void*)> CpuManager::GetShutdownThreadStartFunc() {
55 return SuspendThreadFunction; 52 return ShutdownThreadFunction;
56} 53}
57 54
58void CpuManager::GuestThreadFunction(void* cpu_manager_) { 55void CpuManager::GuestThreadFunction(void* cpu_manager_) {
@@ -82,17 +79,12 @@ void CpuManager::IdleThreadFunction(void* cpu_manager_) {
82 } 79 }
83} 80}
84 81
85void CpuManager::SuspendThreadFunction(void* cpu_manager_) { 82void CpuManager::ShutdownThreadFunction(void* cpu_manager) {
86 CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_); 83 static_cast<CpuManager*>(cpu_manager)->ShutdownThread();
87 if (cpu_manager->is_multicore) {
88 cpu_manager->MultiCoreRunSuspendThread();
89 } else {
90 cpu_manager->SingleCoreRunSuspendThread();
91 }
92} 84}
93 85
94void* CpuManager::GetStartFuncParamater() { 86void* CpuManager::GetStartFuncParameter() {
95 return static_cast<void*>(this); 87 return this;
96} 88}
97 89
98/////////////////////////////////////////////////////////////////////////////// 90///////////////////////////////////////////////////////////////////////////////
@@ -113,12 +105,10 @@ void CpuManager::MultiCoreRunGuestLoop() {
113 105
114 while (true) { 106 while (true) {
115 auto* physical_core = &kernel.CurrentPhysicalCore(); 107 auto* physical_core = &kernel.CurrentPhysicalCore();
116 system.EnterDynarmicProfile();
117 while (!physical_core->IsInterrupted()) { 108 while (!physical_core->IsInterrupted()) {
118 physical_core->Run(); 109 physical_core->Run();
119 physical_core = &kernel.CurrentPhysicalCore(); 110 physical_core = &kernel.CurrentPhysicalCore();
120 } 111 }
121 system.ExitDynarmicProfile();
122 { 112 {
123 Kernel::KScopedDisableDispatch dd(kernel); 113 Kernel::KScopedDisableDispatch dd(kernel);
124 physical_core->ArmInterface().ClearExclusiveState(); 114 physical_core->ArmInterface().ClearExclusiveState();
@@ -134,21 +124,6 @@ void CpuManager::MultiCoreRunIdleThread() {
134 } 124 }
135} 125}
136 126
137void CpuManager::MultiCoreRunSuspendThread() {
138 auto& kernel = system.Kernel();
139 kernel.CurrentScheduler()->OnThreadStart();
140 while (true) {
141 auto core = kernel.CurrentPhysicalCoreIndex();
142 auto& scheduler = *kernel.CurrentScheduler();
143 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
144 current_thread->DisableDispatch();
145
146 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
147 ASSERT(core == kernel.CurrentPhysicalCoreIndex());
148 scheduler.RescheduleCurrentCore();
149 }
150}
151
152/////////////////////////////////////////////////////////////////////////////// 127///////////////////////////////////////////////////////////////////////////////
153/// SingleCore /// 128/// SingleCore ///
154/////////////////////////////////////////////////////////////////////////////// 129///////////////////////////////////////////////////////////////////////////////
@@ -166,12 +141,10 @@ void CpuManager::SingleCoreRunGuestLoop() {
166 auto& kernel = system.Kernel(); 141 auto& kernel = system.Kernel();
167 while (true) { 142 while (true) {
168 auto* physical_core = &kernel.CurrentPhysicalCore(); 143 auto* physical_core = &kernel.CurrentPhysicalCore();
169 system.EnterDynarmicProfile();
170 if (!physical_core->IsInterrupted()) { 144 if (!physical_core->IsInterrupted()) {
171 physical_core->Run(); 145 physical_core->Run();
172 physical_core = &kernel.CurrentPhysicalCore(); 146 physical_core = &kernel.CurrentPhysicalCore();
173 } 147 }
174 system.ExitDynarmicProfile();
175 kernel.SetIsPhantomModeForSingleCore(true); 148 kernel.SetIsPhantomModeForSingleCore(true);
176 system.CoreTiming().Advance(); 149 system.CoreTiming().Advance();
177 kernel.SetIsPhantomModeForSingleCore(false); 150 kernel.SetIsPhantomModeForSingleCore(false);
@@ -194,21 +167,6 @@ void CpuManager::SingleCoreRunIdleThread() {
194 } 167 }
195} 168}
196 169
197void CpuManager::SingleCoreRunSuspendThread() {
198 auto& kernel = system.Kernel();
199 kernel.CurrentScheduler()->OnThreadStart();
200 while (true) {
201 auto core = kernel.GetCurrentHostThreadID();
202 auto& scheduler = *kernel.CurrentScheduler();
203 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
204 current_thread->DisableDispatch();
205
206 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[0].host_context);
207 ASSERT(core == kernel.GetCurrentHostThreadID());
208 scheduler.RescheduleCurrentCore();
209 }
210}
211
212void CpuManager::PreemptSingleCore(bool from_running_enviroment) { 170void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
213 { 171 {
214 auto& kernel = system.Kernel(); 172 auto& kernel = system.Kernel();
@@ -241,24 +199,16 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
241 } 199 }
242} 200}
243 201
244void CpuManager::Pause(bool paused) { 202void CpuManager::ShutdownThread() {
245 std::scoped_lock lk{pause_lock}; 203 auto& kernel = system.Kernel();
246 204 auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0;
247 if (pause_state == paused) { 205 auto* current_thread = kernel.GetCurrentEmuThread();
248 return;
249 }
250
251 // Set the new state
252 pause_state.store(paused);
253
254 // Wake up any waiting threads
255 pause_state.notify_all();
256 206
257 // Wait for all threads to successfully change state before returning 207 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
258 pause_barrier->Sync(); 208 UNREACHABLE();
259} 209}
260 210
261void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { 211void CpuManager::RunThread(std::size_t core) {
262 /// Initialization 212 /// Initialization
263 system.RegisterCoreThread(core); 213 system.RegisterCoreThread(core);
264 std::string name; 214 std::string name;
@@ -272,8 +222,6 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
272 Common::SetCurrentThreadPriority(Common::ThreadPriority::High); 222 Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
273 auto& data = core_data[core]; 223 auto& data = core_data[core];
274 data.host_context = Common::Fiber::ThreadToFiber(); 224 data.host_context = Common::Fiber::ThreadToFiber();
275 const bool sc_sync = !is_async_gpu && !is_multicore;
276 bool sc_sync_first_use = sc_sync;
277 225
278 // Cleanup 226 // Cleanup
279 SCOPE_EXIT({ 227 SCOPE_EXIT({
@@ -281,32 +229,13 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
281 MicroProfileOnThreadExit(); 229 MicroProfileOnThreadExit();
282 }); 230 });
283 231
284 /// Running 232 // Running
285 while (running_mode) { 233 if (!is_async_gpu && !is_multicore) {
286 if (pause_state.load(std::memory_order_relaxed)) { 234 system.GPU().ObtainContext();
287 // Wait for caller to acknowledge pausing
288 pause_barrier->Sync();
289
290 // Wait until unpaused
291 pause_state.wait(true, std::memory_order_relaxed);
292
293 // Wait for caller to acknowledge unpausing
294 pause_barrier->Sync();
295 }
296
297 if (sc_sync_first_use) {
298 system.GPU().ObtainContext();
299 sc_sync_first_use = false;
300 }
301
302 // Emulation was stopped
303 if (stop_token.stop_requested()) {
304 return;
305 }
306
307 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
308 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
309 } 235 }
236
237 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
238 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
310} 239}
311 240
312} // namespace Core 241} // namespace Core
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
index ddd9691ca..681bdaf19 100644
--- a/src/core/cpu_manager.h
+++ b/src/core/cpu_manager.h
@@ -46,12 +46,10 @@ public:
46 void Initialize(); 46 void Initialize();
47 void Shutdown(); 47 void Shutdown();
48 48
49 void Pause(bool paused);
50
51 static std::function<void(void*)> GetGuestThreadStartFunc(); 49 static std::function<void(void*)> GetGuestThreadStartFunc();
52 static std::function<void(void*)> GetIdleThreadStartFunc(); 50 static std::function<void(void*)> GetIdleThreadStartFunc();
53 static std::function<void(void*)> GetSuspendThreadStartFunc(); 51 static std::function<void(void*)> GetShutdownThreadStartFunc();
54 void* GetStartFuncParamater(); 52 void* GetStartFuncParameter();
55 53
56 void PreemptSingleCore(bool from_running_enviroment = true); 54 void PreemptSingleCore(bool from_running_enviroment = true);
57 55
@@ -63,38 +61,33 @@ private:
63 static void GuestThreadFunction(void* cpu_manager); 61 static void GuestThreadFunction(void* cpu_manager);
64 static void GuestRewindFunction(void* cpu_manager); 62 static void GuestRewindFunction(void* cpu_manager);
65 static void IdleThreadFunction(void* cpu_manager); 63 static void IdleThreadFunction(void* cpu_manager);
66 static void SuspendThreadFunction(void* cpu_manager); 64 static void ShutdownThreadFunction(void* cpu_manager);
67 65
68 void MultiCoreRunGuestThread(); 66 void MultiCoreRunGuestThread();
69 void MultiCoreRunGuestLoop(); 67 void MultiCoreRunGuestLoop();
70 void MultiCoreRunIdleThread(); 68 void MultiCoreRunIdleThread();
71 void MultiCoreRunSuspendThread();
72 69
73 void SingleCoreRunGuestThread(); 70 void SingleCoreRunGuestThread();
74 void SingleCoreRunGuestLoop(); 71 void SingleCoreRunGuestLoop();
75 void SingleCoreRunIdleThread(); 72 void SingleCoreRunIdleThread();
76 void SingleCoreRunSuspendThread();
77 73
78 static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core); 74 static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
79 75
80 void RunThread(std::stop_token stop_token, std::size_t core); 76 void ShutdownThread();
77 void RunThread(std::size_t core);
81 78
82 struct CoreData { 79 struct CoreData {
83 std::shared_ptr<Common::Fiber> host_context; 80 std::shared_ptr<Common::Fiber> host_context;
84 std::jthread host_thread; 81 std::jthread host_thread;
85 }; 82 };
86 83
87 std::atomic<bool> running_mode{};
88 std::atomic<bool> pause_state{};
89 std::unique_ptr<Common::Barrier> pause_barrier{};
90 std::mutex pause_lock{};
91
92 std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{}; 84 std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{};
93 85
94 bool is_async_gpu{}; 86 bool is_async_gpu{};
95 bool is_multicore{}; 87 bool is_multicore{};
96 std::atomic<std::size_t> current_core{}; 88 std::atomic<std::size_t> current_core{};
97 std::size_t idle_count{}; 89 std::size_t idle_count{};
90 std::size_t num_cores{};
98 static constexpr std::size_t max_cycle_runs = 5; 91 static constexpr std::size_t max_cycle_runs = 5;
99 92
100 System& system; 93 System& system;
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index edf991d71..ab3940922 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -67,17 +67,19 @@ public:
67 } 67 }
68 68
69 bool SignalDebugger(SignalInfo signal_info) { 69 bool SignalDebugger(SignalInfo signal_info) {
70 std::scoped_lock lk{connection_lock}; 70 {
71 std::scoped_lock lk{connection_lock};
71 72
72 if (stopped) { 73 if (stopped) {
73 // Do not notify the debugger about another event. 74 // Do not notify the debugger about another event.
74 // It should be ignored. 75 // It should be ignored.
75 return false; 76 return false;
76 } 77 }
77 78
78 // Set up the state. 79 // Set up the state.
79 stopped = true; 80 stopped = true;
80 info = signal_info; 81 info = signal_info;
82 }
81 83
82 // Write a single byte into the pipe to wake up the debug interface. 84 // Write a single byte into the pipe to wake up the debug interface.
83 boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped))); 85 boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped)));
@@ -141,9 +143,6 @@ private:
141 AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); }); 143 AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); });
142 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); 144 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); });
143 145
144 // Stop the emulated CPU.
145 AllCoreStop();
146
147 // Set the active thread. 146 // Set the active thread.
148 UpdateActiveThread(); 147 UpdateActiveThread();
149 148
@@ -159,7 +158,7 @@ private:
159 switch (info.type) { 158 switch (info.type) {
160 case SignalType::Stopped: 159 case SignalType::Stopped:
161 // Stop emulation. 160 // Stop emulation.
162 AllCoreStop(); 161 PauseEmulation();
163 162
164 // Notify the client. 163 // Notify the client.
165 active_thread = info.thread; 164 active_thread = info.thread;
@@ -171,7 +170,6 @@ private:
171 frontend->ShuttingDown(); 170 frontend->ShuttingDown();
172 171
173 // Wait for emulation to shut down gracefully now. 172 // Wait for emulation to shut down gracefully now.
174 suspend.reset();
175 signal_pipe.close(); 173 signal_pipe.close();
176 client_socket.shutdown(boost::asio::socket_base::shutdown_both); 174 client_socket.shutdown(boost::asio::socket_base::shutdown_both);
177 LOG_INFO(Debug_GDBStub, "Shut down server"); 175 LOG_INFO(Debug_GDBStub, "Shut down server");
@@ -189,32 +187,29 @@ private:
189 std::scoped_lock lk{connection_lock}; 187 std::scoped_lock lk{connection_lock};
190 stopped = true; 188 stopped = true;
191 } 189 }
192 AllCoreStop(); 190 PauseEmulation();
193 UpdateActiveThread(); 191 UpdateActiveThread();
194 frontend->Stopped(active_thread); 192 frontend->Stopped(active_thread);
195 break; 193 break;
196 } 194 }
197 case DebuggerAction::Continue: 195 case DebuggerAction::Continue:
198 active_thread->SetStepState(Kernel::StepState::NotStepping); 196 MarkResumed([&] { ResumeEmulation(); });
199 ResumeInactiveThreads();
200 AllCoreResume();
201 break; 197 break;
202 case DebuggerAction::StepThreadUnlocked: 198 case DebuggerAction::StepThreadUnlocked:
203 active_thread->SetStepState(Kernel::StepState::StepPending); 199 MarkResumed([&] {
204 ResumeInactiveThreads(); 200 active_thread->SetStepState(Kernel::StepState::StepPending);
205 AllCoreResume(); 201 active_thread->Resume(Kernel::SuspendType::Debug);
202 ResumeEmulation(active_thread);
203 });
206 break; 204 break;
207 case DebuggerAction::StepThreadLocked: 205 case DebuggerAction::StepThreadLocked: {
208 active_thread->SetStepState(Kernel::StepState::StepPending); 206 MarkResumed([&] {
209 SuspendInactiveThreads(); 207 active_thread->SetStepState(Kernel::StepState::StepPending);
210 AllCoreResume(); 208 active_thread->Resume(Kernel::SuspendType::Debug);
209 });
211 break; 210 break;
211 }
212 case DebuggerAction::ShutdownEmulation: { 212 case DebuggerAction::ShutdownEmulation: {
213 // Suspend all threads and release any locks held
214 active_thread->RequestSuspend(Kernel::SuspendType::Debug);
215 SuspendInactiveThreads();
216 AllCoreResume();
217
218 // Spawn another thread that will exit after shutdown, 213 // Spawn another thread that will exit after shutdown,
219 // to avoid a deadlock 214 // to avoid a deadlock
220 Core::System* system_ref{&system}; 215 Core::System* system_ref{&system};
@@ -226,33 +221,33 @@ private:
226 } 221 }
227 } 222 }
228 223
229 void AllCoreStop() { 224 void PauseEmulation() {
230 if (!suspend) { 225 // Put all threads to sleep on next scheduler round.
231 suspend = system.StallCPU(); 226 for (auto* thread : ThreadList()) {
227 thread->RequestSuspend(Kernel::SuspendType::Debug);
232 } 228 }
233 }
234 229
235 void AllCoreResume() { 230 // Signal an interrupt so that scheduler will fire.
236 stopped = false; 231 system.Kernel().InterruptAllPhysicalCores();
237 system.UnstallCPU();
238 suspend.reset();
239 } 232 }
240 233
241 void SuspendInactiveThreads() { 234 void ResumeEmulation(Kernel::KThread* except = nullptr) {
235 // Wake up all threads.
242 for (auto* thread : ThreadList()) { 236 for (auto* thread : ThreadList()) {
243 if (thread != active_thread) { 237 if (thread == except) {
244 thread->RequestSuspend(Kernel::SuspendType::Debug); 238 continue;
245 } 239 }
240
241 thread->SetStepState(Kernel::StepState::NotStepping);
242 thread->Resume(Kernel::SuspendType::Debug);
246 } 243 }
247 } 244 }
248 245
249 void ResumeInactiveThreads() { 246 template <typename Callback>
250 for (auto* thread : ThreadList()) { 247 void MarkResumed(Callback&& cb) {
251 if (thread != active_thread) { 248 std::scoped_lock lk{connection_lock};
252 thread->Resume(Kernel::SuspendType::Debug); 249 stopped = false;
253 thread->SetStepState(Kernel::StepState::NotStepping); 250 cb();
254 }
255 }
256 } 251 }
257 252
258 void UpdateActiveThread() { 253 void UpdateActiveThread() {
@@ -260,8 +255,6 @@ private:
260 if (std::find(threads.begin(), threads.end(), active_thread) == threads.end()) { 255 if (std::find(threads.begin(), threads.end(), active_thread) == threads.end()) {
261 active_thread = threads[0]; 256 active_thread = threads[0];
262 } 257 }
263 active_thread->Resume(Kernel::SuspendType::Debug);
264 active_thread->SetStepState(Kernel::StepState::NotStepping);
265 } 258 }
266 259
267 const std::vector<Kernel::KThread*>& ThreadList() { 260 const std::vector<Kernel::KThread*>& ThreadList() {
@@ -277,7 +270,6 @@ private:
277 boost::asio::io_context io_context; 270 boost::asio::io_context io_context;
278 boost::process::async_pipe signal_pipe; 271 boost::process::async_pipe signal_pipe;
279 boost::asio::ip::tcp::socket client_socket; 272 boost::asio::ip::tcp::socket client_socket;
280 std::optional<std::unique_lock<std::mutex>> suspend;
281 273
282 SignalInfo info; 274 SignalInfo info;
283 Kernel::KThread* active_thread; 275 Kernel::KThread* active_thread;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 8c79b4f0f..cd863e715 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -275,11 +275,15 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a
275 shmem->Close(); 275 shmem->Close();
276} 276}
277 277
278void KProcess::RegisterThread(const KThread* thread) { 278void KProcess::RegisterThread(KThread* thread) {
279 KScopedLightLock lk{list_lock};
280
279 thread_list.push_back(thread); 281 thread_list.push_back(thread);
280} 282}
281 283
282void KProcess::UnregisterThread(const KThread* thread) { 284void KProcess::UnregisterThread(KThread* thread) {
285 KScopedLightLock lk{list_lock};
286
283 thread_list.remove(thread); 287 thread_list.remove(thread);
284} 288}
285 289
@@ -297,6 +301,50 @@ ResultCode KProcess::Reset() {
297 return ResultSuccess; 301 return ResultSuccess;
298} 302}
299 303
304ResultCode KProcess::SetActivity(ProcessActivity activity) {
305 // Lock ourselves and the scheduler.
306 KScopedLightLock lk{state_lock};
307 KScopedLightLock list_lk{list_lock};
308 KScopedSchedulerLock sl{kernel};
309
310 // Validate our state.
311 R_UNLESS(status != ProcessStatus::Exiting, ResultInvalidState);
312 R_UNLESS(status != ProcessStatus::Exited, ResultInvalidState);
313
314 // Either pause or resume.
315 if (activity == ProcessActivity::Paused) {
316 // Verify that we're not suspended.
317 if (is_suspended) {
318 return ResultInvalidState;
319 }
320
321 // Suspend all threads.
322 for (auto* thread : GetThreadList()) {
323 thread->RequestSuspend(SuspendType::Process);
324 }
325
326 // Set ourselves as suspended.
327 SetSuspended(true);
328 } else {
329 ASSERT(activity == ProcessActivity::Runnable);
330
331 // Verify that we're suspended.
332 if (!is_suspended) {
333 return ResultInvalidState;
334 }
335
336 // Resume all threads.
337 for (auto* thread : GetThreadList()) {
338 thread->Resume(SuspendType::Process);
339 }
340
341 // Set ourselves as resumed.
342 SetSuspended(false);
343 }
344
345 return ResultSuccess;
346}
347
300ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, 348ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
301 std::size_t code_size) { 349 std::size_t code_size) {
302 program_id = metadata.GetTitleID(); 350 program_id = metadata.GetTitleID();
@@ -556,9 +604,10 @@ bool KProcess::IsSignaled() const {
556} 604}
557 605
558KProcess::KProcess(KernelCore& kernel_) 606KProcess::KProcess(KernelCore& kernel_)
559 : KAutoObjectWithSlabHeapAndContainer{kernel_}, 607 : KAutoObjectWithSlabHeapAndContainer{kernel_}, page_table{std::make_unique<KPageTable>(
560 page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_}, 608 kernel_.System())},
561 address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {} 609 handle_table{kernel_}, address_arbiter{kernel_.System()}, condition_var{kernel_.System()},
610 state_lock{kernel_}, list_lock{kernel_} {}
562 611
563KProcess::~KProcess() = default; 612KProcess::~KProcess() = default;
564 613
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 9f171e3da..e562a79b8 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -63,6 +63,11 @@ enum class ProcessStatus {
63 DebugBreak, 63 DebugBreak,
64}; 64};
65 65
66enum class ProcessActivity : u32 {
67 Runnable,
68 Paused,
69};
70
66class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { 71class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
67 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); 72 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
68 73
@@ -282,17 +287,17 @@ public:
282 u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const; 287 u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const;
283 288
284 /// Gets the list of all threads created with this process as their owner. 289 /// Gets the list of all threads created with this process as their owner.
285 const std::list<const KThread*>& GetThreadList() const { 290 std::list<KThread*>& GetThreadList() {
286 return thread_list; 291 return thread_list;
287 } 292 }
288 293
289 /// Registers a thread as being created under this process, 294 /// Registers a thread as being created under this process,
290 /// adding it to this process' thread list. 295 /// adding it to this process' thread list.
291 void RegisterThread(const KThread* thread); 296 void RegisterThread(KThread* thread);
292 297
293 /// Unregisters a thread from this process, removing it 298 /// Unregisters a thread from this process, removing it
294 /// from this process' thread list. 299 /// from this process' thread list.
295 void UnregisterThread(const KThread* thread); 300 void UnregisterThread(KThread* thread);
296 301
297 /// Clears the signaled state of the process if and only if it's signaled. 302 /// Clears the signaled state of the process if and only if it's signaled.
298 /// 303 ///
@@ -347,6 +352,8 @@ public:
347 352
348 void DoWorkerTaskImpl(); 353 void DoWorkerTaskImpl();
349 354
355 ResultCode SetActivity(ProcessActivity activity);
356
350 void PinCurrentThread(s32 core_id); 357 void PinCurrentThread(s32 core_id);
351 void UnpinCurrentThread(s32 core_id); 358 void UnpinCurrentThread(s32 core_id);
352 void UnpinThread(KThread* thread); 359 void UnpinThread(KThread* thread);
@@ -442,7 +449,7 @@ private:
442 std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; 449 std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{};
443 450
444 /// List of threads that are running with this process as their owner. 451 /// List of threads that are running with this process as their owner.
445 std::list<const KThread*> thread_list; 452 std::list<KThread*> thread_list;
446 453
447 /// List of shared memory that are running with this process as their owner. 454 /// List of shared memory that are running with this process as their owner.
448 std::list<KSharedMemoryInfo*> shared_memory_list; 455 std::list<KSharedMemoryInfo*> shared_memory_list;
@@ -475,6 +482,7 @@ private:
475 KThread* exception_thread{}; 482 KThread* exception_thread{};
476 483
477 KLightLock state_lock; 484 KLightLock state_lock;
485 KLightLock list_lock;
478 486
479 using TLPTree = 487 using TLPTree =
480 Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>; 488 Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index ea2160099..8d48a7901 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -267,15 +267,15 @@ ResultCode KThread::InitializeDummyThread(KThread* thread) {
267ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { 267ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) {
268 return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, 268 return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main,
269 Core::CpuManager::GetIdleThreadStartFunc(), 269 Core::CpuManager::GetIdleThreadStartFunc(),
270 system.GetCpuManager().GetStartFuncParamater()); 270 system.GetCpuManager().GetStartFuncParameter());
271} 271}
272 272
273ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, 273ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread,
274 KThreadFunction func, uintptr_t arg, 274 KThreadFunction func, uintptr_t arg,
275 s32 virt_core) { 275 s32 virt_core) {
276 return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, 276 return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority,
277 Core::CpuManager::GetSuspendThreadStartFunc(), 277 Core::CpuManager::GetShutdownThreadStartFunc(),
278 system.GetCpuManager().GetStartFuncParamater()); 278 system.GetCpuManager().GetStartFuncParameter());
279} 279}
280 280
281ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, 281ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread,
@@ -284,7 +284,7 @@ ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread,
284 system.Kernel().GlobalSchedulerContext().AddThread(thread); 284 system.Kernel().GlobalSchedulerContext().AddThread(thread);
285 return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, 285 return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner,
286 ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), 286 ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(),
287 system.GetCpuManager().GetStartFuncParamater()); 287 system.GetCpuManager().GetStartFuncParameter());
288} 288}
289 289
290void KThread::PostDestroy(uintptr_t arg) { 290void KThread::PostDestroy(uintptr_t arg) {
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b2c4f12b4..73593c7a0 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -76,7 +76,7 @@ struct KernelCore::Impl {
76 InitializeMemoryLayout(); 76 InitializeMemoryLayout();
77 Init::InitializeKPageBufferSlabHeap(system); 77 Init::InitializeKPageBufferSlabHeap(system);
78 InitializeSchedulers(); 78 InitializeSchedulers();
79 InitializeSuspendThreads(); 79 InitializeShutdownThreads();
80 InitializePreemption(kernel); 80 InitializePreemption(kernel);
81 81
82 RegisterHostThread(); 82 RegisterHostThread();
@@ -143,9 +143,9 @@ struct KernelCore::Impl {
143 CleanupObject(system_resource_limit); 143 CleanupObject(system_resource_limit);
144 144
145 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 145 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
146 if (suspend_threads[core_id]) { 146 if (shutdown_threads[core_id]) {
147 suspend_threads[core_id]->Close(); 147 shutdown_threads[core_id]->Close();
148 suspend_threads[core_id] = nullptr; 148 shutdown_threads[core_id] = nullptr;
149 } 149 }
150 150
151 schedulers[core_id]->Finalize(); 151 schedulers[core_id]->Finalize();
@@ -247,14 +247,14 @@ struct KernelCore::Impl {
247 system.CoreTiming().ScheduleEvent(time_interval, preemption_event); 247 system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
248 } 248 }
249 249
250 void InitializeSuspendThreads() { 250 void InitializeShutdownThreads() {
251 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 251 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
252 suspend_threads[core_id] = KThread::Create(system.Kernel()); 252 shutdown_threads[core_id] = KThread::Create(system.Kernel());
253 ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id], {}, {}, 253 ASSERT(KThread::InitializeHighPriorityThread(system, shutdown_threads[core_id], {}, {},
254 core_id) 254 core_id)
255 .IsSuccess()); 255 .IsSuccess());
256 suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id)); 256 shutdown_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id));
257 suspend_threads[core_id]->DisableDispatch(); 257 shutdown_threads[core_id]->DisableDispatch();
258 } 258 }
259 } 259 }
260 260
@@ -769,7 +769,7 @@ struct KernelCore::Impl {
769 std::weak_ptr<ServiceThread> default_service_thread; 769 std::weak_ptr<ServiceThread> default_service_thread;
770 Common::ThreadWorker service_threads_manager; 770 Common::ThreadWorker service_threads_manager;
771 771
772 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; 772 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
773 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; 773 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
774 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 774 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
775 775
@@ -920,6 +920,12 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
920 return *impl->global_object_list_container; 920 return *impl->global_object_list_container;
921} 921}
922 922
923void KernelCore::InterruptAllPhysicalCores() {
924 for (auto& physical_core : impl->cores) {
925 physical_core.Interrupt();
926 }
927}
928
923void KernelCore::InvalidateAllInstructionCaches() { 929void KernelCore::InvalidateAllInstructionCaches() {
924 for (auto& physical_core : impl->cores) { 930 for (auto& physical_core : impl->cores) {
925 physical_core.ArmInterface().ClearInstructionCache(); 931 physical_core.ArmInterface().ClearInstructionCache();
@@ -1067,17 +1073,20 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
1067 return *impl->hidbus_shared_mem; 1073 return *impl->hidbus_shared_mem;
1068} 1074}
1069 1075
1070void KernelCore::Suspend(bool in_suspention) { 1076void KernelCore::Suspend(bool suspended) {
1071 const bool should_suspend = exception_exited || in_suspention; 1077 const bool should_suspend{exception_exited || suspended};
1072 { 1078 const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
1073 KScopedSchedulerLock lock(*this); 1079
1074 const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; 1080 for (auto* process : GetProcessList()) {
1075 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 1081 process->SetActivity(activity);
1076 impl->suspend_threads[core_id]->SetState(state); 1082 }
1077 impl->suspend_threads[core_id]->SetWaitReasonForDebugging( 1083}
1078 ThreadWaitReasonForDebugging::Suspended); 1084
1079 } 1085void KernelCore::ShutdownCores() {
1086 for (auto* thread : impl->shutdown_threads) {
1087 void(thread->Run());
1080 } 1088 }
1089 InterruptAllPhysicalCores();
1081} 1090}
1082 1091
1083bool KernelCore::IsMulticore() const { 1092bool KernelCore::IsMulticore() const {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 926e14c6f..4e7beab0e 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -184,6 +184,8 @@ public:
184 184
185 const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; 185 const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const;
186 186
187 void InterruptAllPhysicalCores();
188
187 void InvalidateAllInstructionCaches(); 189 void InvalidateAllInstructionCaches();
188 190
189 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); 191 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
@@ -269,12 +271,15 @@ public:
269 /// Gets the shared memory object for HIDBus services. 271 /// Gets the shared memory object for HIDBus services.
270 const Kernel::KSharedMemory& GetHidBusSharedMem() const; 272 const Kernel::KSharedMemory& GetHidBusSharedMem() const;
271 273
272 /// Suspend/unsuspend the OS. 274 /// Suspend/unsuspend all processes.
273 void Suspend(bool in_suspention); 275 void Suspend(bool suspend);
274 276
275 /// Exceptional exit the OS. 277 /// Exceptional exit all processes.
276 void ExceptionalExit(); 278 void ExceptionalExit();
277 279
280 /// Notify emulated CPU cores to shut down.
281 void ShutdownCores();
282
278 bool IsMulticore() const; 283 bool IsMulticore() const;
279 284
280 bool IsShuttingDown() const; 285 bool IsShuttingDown() const;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 584fa5b1c..2ff6d5fa6 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -15,6 +15,7 @@
15#include "common/scope_exit.h" 15#include "common/scope_exit.h"
16#include "core/core.h" 16#include "core/core.h"
17#include "core/core_timing.h" 17#include "core/core_timing.h"
18#include "core/debugger/debugger.h"
18#include "core/hle/kernel/k_client_port.h" 19#include "core/hle/kernel/k_client_port.h"
19#include "core/hle/kernel/k_client_session.h" 20#include "core/hle/kernel/k_client_session.h"
20#include "core/hle/kernel/k_code_memory.h" 21#include "core/hle/kernel/k_code_memory.h"
@@ -627,6 +628,12 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
627 const auto thread_processor_id = current_thread->GetActiveCore(); 628 const auto thread_processor_id = current_thread->GetActiveCore();
628 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); 629 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
629 } 630 }
631
632 if (system.DebuggerEnabled()) {
633 auto* thread = system.Kernel().GetCurrentEmuThread();
634 system.GetDebugger().NotifyThreadStopped(thread);
635 thread->RequestSuspend(Kernel::SuspendType::Debug);
636 }
630} 637}
631 638
632static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { 639static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) {
@@ -1719,11 +1726,12 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
1719/// Exits the current process 1726/// Exits the current process
1720static void ExitProcess(Core::System& system) { 1727static void ExitProcess(Core::System& system) {
1721 auto* current_process = system.Kernel().CurrentProcess(); 1728 auto* current_process = system.Kernel().CurrentProcess();
1722 UNIMPLEMENTED();
1723 1729
1724 LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); 1730 LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID());
1725 ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, 1731 ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running,
1726 "Process has already exited"); 1732 "Process has already exited");
1733
1734 system.Exit();
1727} 1735}
1728 1736
1729static void ExitProcess32(Core::System& system) { 1737static void ExitProcess32(Core::System& system) {
@@ -2530,7 +2538,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
2530 return ResultOutOfRange; 2538 return ResultOutOfRange;
2531 } 2539 }
2532 2540
2533 const auto* const current_process = system.Kernel().CurrentProcess(); 2541 auto* const current_process = system.Kernel().CurrentProcess();
2534 const auto total_copy_size = out_thread_ids_size * sizeof(u64); 2542 const auto total_copy_size = out_thread_ids_size * sizeof(u64);
2535 2543
2536 if (out_thread_ids_size > 0 && 2544 if (out_thread_ids_size > 0 &&
@@ -2982,7 +2990,6 @@ static const FunctionDef* GetSVCInfo64(u32 func_num) {
2982} 2990}
2983 2991
2984void Call(Core::System& system, u32 immediate) { 2992void Call(Core::System& system, u32 immediate) {
2985 system.ExitDynarmicProfile();
2986 auto& kernel = system.Kernel(); 2993 auto& kernel = system.Kernel();
2987 kernel.EnterSVCProfile(); 2994 kernel.EnterSVCProfile();
2988 2995
@@ -3007,8 +3014,6 @@ void Call(Core::System& system, u32 immediate) {
3007 auto* host_context = thread->GetHostContext().get(); 3014 auto* host_context = thread->GetHostContext().get();
3008 host_context->Rewind(); 3015 host_context->Rewind();
3009 } 3016 }
3010
3011 system.EnterDynarmicProfile();
3012} 3017}
3013 3018
3014} // namespace Kernel::Svc 3019} // namespace Kernel::Svc
diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp
index b971846e7..3ace2dabd 100644
--- a/src/core/hle/service/glue/notif.cpp
+++ b/src/core/hle/service/glue/notif.cpp
@@ -1,6 +1,11 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm>
5#include <cstring>
6
7#include "common/assert.h"
8#include "common/logging/log.h"
4#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
5#include "core/hle/service/glue/notif.h" 10#include "core/hle/service/glue/notif.h"
6 11
@@ -9,11 +14,11 @@ namespace Service::Glue {
9NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} { 14NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} {
10 // clang-format off 15 // clang-format off
11 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
12 {500, nullptr, "RegisterAlarmSetting"}, 17 {500, &NOTIF_A::RegisterAlarmSetting, "RegisterAlarmSetting"},
13 {510, nullptr, "UpdateAlarmSetting"}, 18 {510, &NOTIF_A::UpdateAlarmSetting, "UpdateAlarmSetting"},
14 {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"}, 19 {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"},
15 {530, nullptr, "LoadApplicationParameter"}, 20 {530, &NOTIF_A::LoadApplicationParameter, "LoadApplicationParameter"},
16 {540, nullptr, "DeleteAlarmSetting"}, 21 {540, &NOTIF_A::DeleteAlarmSetting, "DeleteAlarmSetting"},
17 {1000, &NOTIF_A::Initialize, "Initialize"}, 22 {1000, &NOTIF_A::Initialize, "Initialize"},
18 }; 23 };
19 // clang-format on 24 // clang-format on
@@ -23,21 +28,132 @@ NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} {
23 28
24NOTIF_A::~NOTIF_A() = default; 29NOTIF_A::~NOTIF_A() = default;
25 30
31void NOTIF_A::RegisterAlarmSetting(Kernel::HLERequestContext& ctx) {
32 const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0);
33 const auto application_parameter_size = ctx.GetReadBufferSize(1);
34
35 ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting),
36 "alarm_setting_buffer_size is not 0x40 bytes");
37 ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter),
38 "application_parameter_size is bigger than 0x400 bytes");
39
40 AlarmSetting new_alarm{};
41 memcpy(&new_alarm, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting));
42
43 // TODO: Count alarms per game id
44 if (alarms.size() >= max_alarms) {
45 LOG_ERROR(Service_NOTIF, "Alarm limit reached");
46 IPC::ResponseBuilder rb{ctx, 2};
47 rb.Push(ResultUnknown);
48 return;
49 }
50
51 new_alarm.alarm_setting_id = last_alarm_setting_id++;
52 alarms.push_back(new_alarm);
53
54 // TODO: Save application parameter data
55
56 LOG_WARNING(Service_NOTIF,
57 "(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}",
58 application_parameter_size, new_alarm.alarm_setting_id, new_alarm.kind,
59 new_alarm.muted);
60
61 IPC::ResponseBuilder rb{ctx, 2};
62 rb.Push(ResultSuccess);
63 rb.Push(new_alarm.alarm_setting_id);
64}
65
66void NOTIF_A::UpdateAlarmSetting(Kernel::HLERequestContext& ctx) {
67 const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0);
68 const auto application_parameter_size = ctx.GetReadBufferSize(1);
69
70 ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting),
71 "alarm_setting_buffer_size is not 0x40 bytes");
72 ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter),
73 "application_parameter_size is bigger than 0x400 bytes");
74
75 AlarmSetting alarm_setting{};
76 memcpy(&alarm_setting, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting));
77
78 const auto alarm_it = GetAlarmFromId(alarm_setting.alarm_setting_id);
79 if (alarm_it != alarms.end()) {
80 LOG_DEBUG(Service_NOTIF, "Alarm updated");
81 *alarm_it = alarm_setting;
82 // TODO: Save application parameter data
83 }
84
85 LOG_WARNING(Service_NOTIF,
86 "(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}",
87 application_parameter_size, alarm_setting.alarm_setting_id, alarm_setting.kind,
88 alarm_setting.muted);
89
90 IPC::ResponseBuilder rb{ctx, 2};
91 rb.Push(ResultSuccess);
92}
93
26void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) { 94void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) {
27 // Returns an array of AlarmSetting 95 LOG_INFO(Service_NOTIF, "called, alarm_count={}", alarms.size());
28 constexpr s32 alarm_count = 0;
29 96
30 LOG_WARNING(Service_NOTIF, "(STUBBED) called"); 97 // TODO: Only return alarms of this game id
98 ctx.WriteBuffer(alarms);
31 99
32 IPC::ResponseBuilder rb{ctx, 3}; 100 IPC::ResponseBuilder rb{ctx, 3};
33 rb.Push(ResultSuccess); 101 rb.Push(ResultSuccess);
34 rb.Push(alarm_count); 102 rb.Push(static_cast<u32>(alarms.size()));
103}
104
105void NOTIF_A::LoadApplicationParameter(Kernel::HLERequestContext& ctx) {
106 IPC::RequestParser rp{ctx};
107 const auto alarm_setting_id{rp.Pop<AlarmSettingId>()};
108
109 const auto alarm_it = GetAlarmFromId(alarm_setting_id);
110 if (alarm_it == alarms.end()) {
111 LOG_ERROR(Service_NOTIF, "Invalid alarm setting id={}", alarm_setting_id);
112 IPC::ResponseBuilder rb{ctx, 2};
113 rb.Push(ResultUnknown);
114 return;
115 }
116
117 // TODO: Read application parameter related to this setting id
118 ApplicationParameter application_parameter{};
119
120 LOG_WARNING(Service_NOTIF, "(STUBBED) called, alarm_setting_id={}", alarm_setting_id);
121
122 ctx.WriteBuffer(application_parameter);
123
124 IPC::ResponseBuilder rb{ctx, 2};
125 rb.Push(ResultSuccess);
126 rb.Push(static_cast<u32>(application_parameter.size()));
127}
128
129void NOTIF_A::DeleteAlarmSetting(Kernel::HLERequestContext& ctx) {
130 IPC::RequestParser rp{ctx};
131 const auto alarm_setting_id{rp.Pop<AlarmSettingId>()};
132
133 std::erase_if(alarms, [alarm_setting_id](const AlarmSetting& alarm) {
134 return alarm.alarm_setting_id == alarm_setting_id;
135 });
136
137 LOG_INFO(Service_NOTIF, "called, alarm_setting_id={}", alarm_setting_id);
138
139 IPC::ResponseBuilder rb{ctx, 2};
140 rb.Push(ResultSuccess);
35} 141}
36 142
37void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) { 143void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) {
144 // TODO: Load previous alarms from config
145
38 LOG_WARNING(Service_NOTIF, "(STUBBED) called"); 146 LOG_WARNING(Service_NOTIF, "(STUBBED) called");
39 IPC::ResponseBuilder rb{ctx, 2}; 147 IPC::ResponseBuilder rb{ctx, 2};
40 rb.Push(ResultSuccess); 148 rb.Push(ResultSuccess);
41} 149}
42 150
151std::vector<NOTIF_A::AlarmSetting>::iterator NOTIF_A::GetAlarmFromId(
152 AlarmSettingId alarm_setting_id) {
153 return std::find_if(alarms.begin(), alarms.end(),
154 [alarm_setting_id](const AlarmSetting& alarm) {
155 return alarm.alarm_setting_id == alarm_setting_id;
156 });
157}
158
43} // namespace Service::Glue 159} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/notif.h b/src/core/hle/service/glue/notif.h
index 7310d7f72..4467e1f35 100644
--- a/src/core/hle/service/glue/notif.h
+++ b/src/core/hle/service/glue/notif.h
@@ -3,6 +3,10 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <array>
7#include <vector>
8
9#include "common/uuid.h"
6#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
7 11
8namespace Core { 12namespace Core {
@@ -17,8 +21,52 @@ public:
17 ~NOTIF_A() override; 21 ~NOTIF_A() override;
18 22
19private: 23private:
24 static constexpr std::size_t max_alarms = 8;
25
26 // This is nn::notification::AlarmSettingId
27 using AlarmSettingId = u16;
28 static_assert(sizeof(AlarmSettingId) == 0x2, "AlarmSettingId is an invalid size");
29
30 using ApplicationParameter = std::array<u8, 0x400>;
31 static_assert(sizeof(ApplicationParameter) == 0x400, "ApplicationParameter is an invalid size");
32
33 struct DailyAlarmSetting {
34 s8 hour;
35 s8 minute;
36 };
37 static_assert(sizeof(DailyAlarmSetting) == 0x2, "DailyAlarmSetting is an invalid size");
38
39 struct WeeklyScheduleAlarmSetting {
40 INSERT_PADDING_BYTES(0xA);
41 std::array<DailyAlarmSetting, 0x7> day_of_week;
42 };
43 static_assert(sizeof(WeeklyScheduleAlarmSetting) == 0x18,
44 "WeeklyScheduleAlarmSetting is an invalid size");
45
46 // This is nn::notification::AlarmSetting
47 struct AlarmSetting {
48 AlarmSettingId alarm_setting_id;
49 u8 kind;
50 u8 muted;
51 INSERT_PADDING_BYTES(0x4);
52 Common::UUID account_id;
53 u64 application_id;
54 INSERT_PADDING_BYTES(0x8);
55 WeeklyScheduleAlarmSetting schedule;
56 };
57 static_assert(sizeof(AlarmSetting) == 0x40, "AlarmSetting is an invalid size");
58
59 void RegisterAlarmSetting(Kernel::HLERequestContext& ctx);
60 void UpdateAlarmSetting(Kernel::HLERequestContext& ctx);
20 void ListAlarmSettings(Kernel::HLERequestContext& ctx); 61 void ListAlarmSettings(Kernel::HLERequestContext& ctx);
62 void LoadApplicationParameter(Kernel::HLERequestContext& ctx);
63 void DeleteAlarmSetting(Kernel::HLERequestContext& ctx);
21 void Initialize(Kernel::HLERequestContext& ctx); 64 void Initialize(Kernel::HLERequestContext& ctx);
65
66 std::vector<AlarmSetting>::iterator GetAlarmFromId(AlarmSettingId alarm_setting_id);
67
68 std::vector<AlarmSetting> alarms{};
69 AlarmSettingId last_alarm_setting_id{};
22}; 70};
23 71
24} // namespace Service::Glue 72} // namespace Service::Glue
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 705fefc83..527531f29 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -150,9 +150,9 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
150 event.event->GetWritableEvent().Clear(); 150 event.event->GetWritableEvent().Clear();
151 if (events_interface.failed[event_id]) { 151 if (events_interface.failed[event_id]) {
152 { 152 {
153 auto lk = system.StallCPU(); 153 auto lk = system.StallProcesses();
154 gpu.WaitFence(params.syncpt_id, target_value); 154 gpu.WaitFence(params.syncpt_id, target_value);
155 system.UnstallCPU(); 155 system.UnstallProcesses();
156 } 156 }
157 std::memcpy(output.data(), &params, sizeof(params)); 157 std::memcpy(output.data(), &params, sizeof(params));
158 events_interface.failed[event_id] = false; 158 events_interface.failed[event_id] = false;
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index d4fa69a77..48e799cf5 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -44,7 +44,6 @@ else()
44 -Werror 44 -Werror
45 -Werror=conversion 45 -Werror=conversion
46 -Werror=ignored-qualifiers 46 -Werror=ignored-qualifiers
47 -Werror=shadow
48 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 47 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
49 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 48 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
50 -Werror=unused-variable 49 -Werror=unused-variable
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index 4c76ce1ea..ae1dbe619 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -253,9 +253,6 @@ else()
253 -Werror 253 -Werror
254 -Werror=conversion 254 -Werror=conversion
255 -Werror=ignored-qualifiers 255 -Werror=ignored-qualifiers
256 -Werror=implicit-fallthrough
257 -Werror=shadow
258 -Werror=sign-compare
259 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 256 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
260 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 257 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
261 -Werror=unused-variable 258 -Werror=unused-variable
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 256695804..14de7bc89 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -258,10 +258,6 @@ if (MSVC)
258 target_compile_options(video_core PRIVATE 258 target_compile_options(video_core PRIVATE
259 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data 259 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
260 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data 260 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
261 /we4456 # Declaration of 'identifier' hides previous local declaration
262 /we4457 # Declaration of 'identifier' hides function parameter
263 /we4458 # Declaration of 'identifier' hides class member
264 /we4459 # Declaration of 'identifier' hides global declaration
265 ) 261 )
266else() 262else()
267 target_compile_options(video_core PRIVATE 263 target_compile_options(video_core PRIVATE
@@ -269,7 +265,6 @@ else()
269 -Wno-error=sign-conversion 265 -Wno-error=sign-conversion
270 -Werror=pessimizing-move 266 -Werror=pessimizing-move
271 -Werror=redundant-move 267 -Werror=redundant-move
272 -Werror=shadow
273 -Werror=type-limits 268 -Werror=type-limits
274 269
275 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> 270 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess>
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index ad9fd5eff..be0ac2214 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -98,7 +98,7 @@ struct CommandDataContainer {
98struct SynchState final { 98struct SynchState final {
99 using CommandQueue = Common::MPSCQueue<CommandDataContainer>; 99 using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
100 std::mutex write_lock; 100 std::mutex write_lock;
101 CommandQueue queue{512}; // size must be 2^n 101 CommandQueue queue;
102 u64 last_fence{}; 102 u64 last_fence{};
103 std::atomic<u64> signaled_fence{}; 103 std::atomic<u64> signaled_fence{};
104 std::condition_variable_any cv; 104 std::condition_variable_any cv;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index a3d478837..4cba777e6 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -328,31 +328,32 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
328 const VkImageAspectFlags aspect_mask = image.AspectMask(); 328 const VkImageAspectFlags aspect_mask = image.AspectMask();
329 const VkImage vk_image = image.Handle(); 329 const VkImage vk_image = image.Handle();
330 const bool is_initialized = image.ExchangeInitialization(); 330 const bool is_initialized = image.ExchangeInitialization();
331 scheduler.Record( 331 scheduler.Record([vk_pipeline, vk_image, aspect_mask,
332 [vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) { 332 is_initialized](vk::CommandBuffer cmdbuf) {
333 const VkImageMemoryBarrier image_barrier{ 333 const VkImageMemoryBarrier image_barrier{
334 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 334 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
335 .pNext = nullptr, 335 .pNext = nullptr,
336 .srcAccessMask = is_initialized ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_NONE, 336 .srcAccessMask = static_cast<VkAccessFlags>(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT
337 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 337 : VK_ACCESS_NONE),
338 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, 338 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
339 .newLayout = VK_IMAGE_LAYOUT_GENERAL, 339 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
340 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 340 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
341 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 341 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
342 .image = vk_image, 342 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
343 .subresourceRange{ 343 .image = vk_image,
344 .aspectMask = aspect_mask, 344 .subresourceRange{
345 .baseMipLevel = 0, 345 .aspectMask = aspect_mask,
346 .levelCount = VK_REMAINING_MIP_LEVELS, 346 .baseMipLevel = 0,
347 .baseArrayLayer = 0, 347 .levelCount = VK_REMAINING_MIP_LEVELS,
348 .layerCount = VK_REMAINING_ARRAY_LAYERS, 348 .baseArrayLayer = 0,
349 }, 349 .layerCount = VK_REMAINING_ARRAY_LAYERS,
350 }; 350 },
351 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT 351 };
352 : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 352 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
353 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); 353 : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
354 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); 354 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
355 }); 355 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
356 });
356 for (const VideoCommon::SwizzleParameters& swizzle : swizzles) { 357 for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
357 const size_t input_offset = swizzle.buffer_offset + map.offset; 358 const size_t input_offset = swizzle.buffer_offset + map.offset;
358 const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 8U); 359 const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 8U);
diff --git a/src/web_service/telemetry_json.cpp b/src/web_service/telemetry_json.cpp
index 6215c914f..46faddb61 100644
--- a/src/web_service/telemetry_json.cpp
+++ b/src/web_service/telemetry_json.cpp
@@ -13,8 +13,8 @@ namespace WebService {
13namespace Telemetry = Common::Telemetry; 13namespace Telemetry = Common::Telemetry;
14 14
15struct TelemetryJson::Impl { 15struct TelemetryJson::Impl {
16 Impl(std::string host, std::string username, std::string token) 16 Impl(std::string host_, std::string username_, std::string token_)
17 : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} {} 17 : host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} {}
18 18
19 nlohmann::json& TopSection() { 19 nlohmann::json& TopSection() {
20 return sections[static_cast<u8>(Telemetry::FieldType::None)]; 20 return sections[static_cast<u8>(Telemetry::FieldType::None)];
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index 58b0c2f10..dce9772fe 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -30,10 +30,10 @@ constexpr std::array<const char, 1> API_VERSION{'1'};
30constexpr std::size_t TIMEOUT_SECONDS = 30; 30constexpr std::size_t TIMEOUT_SECONDS = 30;
31 31
32struct Client::Impl { 32struct Client::Impl {
33 Impl(std::string host, std::string username, std::string token) 33 Impl(std::string host_, std::string username_, std::string token_)
34 : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} { 34 : host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} {
35 std::scoped_lock lock{jwt_cache.mutex}; 35 std::scoped_lock lock{jwt_cache.mutex};
36 if (this->username == jwt_cache.username && this->token == jwt_cache.token) { 36 if (username == jwt_cache.username && token == jwt_cache.token) {
37 jwt = jwt_cache.jwt; 37 jwt = jwt_cache.jwt;
38 } 38 }
39 } 39 }
@@ -69,8 +69,8 @@ struct Client::Impl {
69 */ 69 */
70 WebResult GenericRequest(const std::string& method, const std::string& path, 70 WebResult GenericRequest(const std::string& method, const std::string& path,
71 const std::string& data, const std::string& accept, 71 const std::string& data, const std::string& accept,
72 const std::string& jwt = "", const std::string& username = "", 72 const std::string& jwt_ = "", const std::string& username_ = "",
73 const std::string& token = "") { 73 const std::string& token_ = "") {
74 if (cli == nullptr) { 74 if (cli == nullptr) {
75 cli = std::make_unique<httplib::Client>(host.c_str()); 75 cli = std::make_unique<httplib::Client>(host.c_str());
76 } 76 }
@@ -85,14 +85,14 @@ struct Client::Impl {
85 cli->set_write_timeout(TIMEOUT_SECONDS); 85 cli->set_write_timeout(TIMEOUT_SECONDS);
86 86
87 httplib::Headers params; 87 httplib::Headers params;
88 if (!jwt.empty()) { 88 if (!jwt_.empty()) {
89 params = { 89 params = {
90 {std::string("Authorization"), fmt::format("Bearer {}", jwt)}, 90 {std::string("Authorization"), fmt::format("Bearer {}", jwt_)},
91 }; 91 };
92 } else if (!username.empty()) { 92 } else if (!username_.empty()) {
93 params = { 93 params = {
94 {std::string("x-username"), username}, 94 {std::string("x-username"), username_},
95 {std::string("x-token"), token}, 95 {std::string("x-token"), token_},
96 }; 96 };
97 } 97 }
98 98
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index bde465485..cbe4e2daa 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -127,7 +127,7 @@ void EmuThread::run() {
127class OpenGLSharedContext : public Core::Frontend::GraphicsContext { 127class OpenGLSharedContext : public Core::Frontend::GraphicsContext {
128public: 128public:
129 /// Create the original context that should be shared from 129 /// Create the original context that should be shared from
130 explicit OpenGLSharedContext(QSurface* surface) : surface(surface) { 130 explicit OpenGLSharedContext(QSurface* surface_) : surface{surface_} {
131 QSurfaceFormat format; 131 QSurfaceFormat format;
132 format.setVersion(4, 6); 132 format.setVersion(4, 6);
133 format.setProfile(QSurfaceFormat::CompatibilityProfile); 133 format.setProfile(QSurfaceFormat::CompatibilityProfile);
@@ -364,9 +364,9 @@ void GRenderWindow::RestoreGeometry() {
364 QWidget::restoreGeometry(geometry); 364 QWidget::restoreGeometry(geometry);
365} 365}
366 366
367void GRenderWindow::restoreGeometry(const QByteArray& geometry) { 367void GRenderWindow::restoreGeometry(const QByteArray& geometry_) {
368 // Make sure users of this class don't need to deal with backing up the geometry themselves 368 // Make sure users of this class don't need to deal with backing up the geometry themselves
369 QWidget::restoreGeometry(geometry); 369 QWidget::restoreGeometry(geometry_);
370 BackupGeometry(); 370 BackupGeometry();
371} 371}
372 372
@@ -1014,8 +1014,8 @@ QStringList GRenderWindow::GetUnsupportedGLExtensions() const {
1014 return unsupported_ext; 1014 return unsupported_ext;
1015} 1015}
1016 1016
1017void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { 1017void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread_) {
1018 this->emu_thread = emu_thread; 1018 emu_thread = emu_thread_;
1019} 1019}
1020 1020
1021void GRenderWindow::OnEmulationStopping() { 1021void GRenderWindow::OnEmulationStopping() {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index d01538039..81fe52c0e 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -56,12 +56,12 @@ public:
56 56
57 /** 57 /**
58 * Sets whether the emulation thread is running or not 58 * Sets whether the emulation thread is running or not
59 * @param running Boolean value, set the emulation thread to running if true 59 * @param running_ Boolean value, set the emulation thread to running if true
60 * @note This function is thread-safe 60 * @note This function is thread-safe
61 */ 61 */
62 void SetRunning(bool running) { 62 void SetRunning(bool running_) {
63 std::unique_lock lock{running_mutex}; 63 std::unique_lock lock{running_mutex};
64 this->running = running; 64 running = running_;
65 lock.unlock(); 65 lock.unlock();
66 running_cv.notify_all(); 66 running_cv.notify_all();
67 if (!running) { 67 if (!running) {
@@ -138,8 +138,8 @@ public:
138 138
139 void BackupGeometry(); 139 void BackupGeometry();
140 void RestoreGeometry(); 140 void RestoreGeometry();
141 void restoreGeometry(const QByteArray& geometry); // overridden 141 void restoreGeometry(const QByteArray& geometry_); // overridden
142 QByteArray saveGeometry(); // overridden 142 QByteArray saveGeometry(); // overridden
143 143
144 qreal windowPixelRatio() const; 144 qreal windowPixelRatio() const;
145 145
@@ -189,7 +189,7 @@ public:
189 void Exit(); 189 void Exit();
190 190
191public slots: 191public slots:
192 void OnEmulationStarting(EmuThread* emu_thread); 192 void OnEmulationStarting(EmuThread* emu_thread_);
193 void OnEmulationStopping(); 193 void OnEmulationStopping();
194 void OnFramebufferSizeChanged(); 194 void OnFramebufferSizeChanged();
195 195
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index b415a1cc4..e99657bd6 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -27,12 +27,11 @@
27#include "yuzu/hotkeys.h" 27#include "yuzu/hotkeys.h"
28#include "yuzu/uisettings.h" 28#include "yuzu/uisettings.h"
29 29
30ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, 30ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
31 InputCommon::InputSubsystem* input_subsystem, 31 InputCommon::InputSubsystem* input_subsystem,
32 Core::System& system_) 32 Core::System& system_)
33 : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, 33 : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
34 registry(registry), system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, 34 system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, this)},
35 this)},
36 cpu_tab{std::make_unique<ConfigureCpu>(system_, this)}, 35 cpu_tab{std::make_unique<ConfigureCpu>(system_, this)},
37 debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)}, 36 debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
38 filesystem_tab{std::make_unique<ConfigureFilesystem>(this)}, 37 filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 32ddfd4e0..12cf25daf 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -40,7 +40,7 @@ class ConfigureDialog : public QDialog {
40 Q_OBJECT 40 Q_OBJECT
41 41
42public: 42public:
43 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, 43 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
44 InputCommon::InputSubsystem* input_subsystem, Core::System& system_); 44 InputCommon::InputSubsystem* input_subsystem, Core::System& system_);
45 ~ConfigureDialog() override; 45 ~ConfigureDialog() override;
46 46
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 1c05dd0f3..f3be9a374 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -264,15 +264,16 @@ QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param,
264 return QObject::tr("[unknown]"); 264 return QObject::tr("[unknown]");
265} 265}
266 266
267ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, 267ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index_,
268 QWidget* bottom_row, 268 QWidget* bottom_row_,
269 InputCommon::InputSubsystem* input_subsystem_, 269 InputCommon::InputSubsystem* input_subsystem_,
270 InputProfiles* profiles_, Core::HID::HIDCore& hid_core_, 270 InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
271 bool is_powered_on_, bool debug) 271 bool is_powered_on_, bool debug_)
272 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), 272 : QWidget(parent),
273 debug(debug), is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, 273 ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index{player_index_}, debug{debug_},
274 profiles(profiles_), timeout_timer(std::make_unique<QTimer>()), 274 is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_),
275 poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row), hid_core{hid_core_} { 275 timeout_timer(std::make_unique<QTimer>()),
276 poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
276 if (player_index == 0) { 277 if (player_index == 0) {
277 auto* emulated_controller_p1 = 278 auto* emulated_controller_p1 =
278 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); 279 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
@@ -696,39 +697,38 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
696 UpdateControllerEnabledButtons(); 697 UpdateControllerEnabledButtons();
697 UpdateControllerButtonNames(); 698 UpdateControllerButtonNames();
698 UpdateMotionButtons(); 699 UpdateMotionButtons();
699 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), 700 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
700 [this, player_index](int) { 701 UpdateControllerAvailableButtons();
701 UpdateControllerAvailableButtons(); 702 UpdateControllerEnabledButtons();
702 UpdateControllerEnabledButtons(); 703 UpdateControllerButtonNames();
703 UpdateControllerButtonNames(); 704 UpdateMotionButtons();
704 UpdateMotionButtons(); 705 const Core::HID::NpadStyleIndex type =
705 const Core::HID::NpadStyleIndex type = 706 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
706 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); 707
707 708 if (player_index == 0) {
708 if (player_index == 0) { 709 auto* emulated_controller_p1 =
709 auto* emulated_controller_p1 = 710 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
710 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); 711 auto* emulated_controller_handheld =
711 auto* emulated_controller_handheld = 712 hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
712 hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); 713 bool is_connected = emulated_controller->IsConnected(true);
713 bool is_connected = emulated_controller->IsConnected(true); 714
714 715 emulated_controller_p1->SetNpadStyleIndex(type);
715 emulated_controller_p1->SetNpadStyleIndex(type); 716 emulated_controller_handheld->SetNpadStyleIndex(type);
716 emulated_controller_handheld->SetNpadStyleIndex(type); 717 if (is_connected) {
717 if (is_connected) { 718 if (type == Core::HID::NpadStyleIndex::Handheld) {
718 if (type == Core::HID::NpadStyleIndex::Handheld) { 719 emulated_controller_p1->Disconnect();
719 emulated_controller_p1->Disconnect(); 720 emulated_controller_handheld->Connect(true);
720 emulated_controller_handheld->Connect(true); 721 emulated_controller = emulated_controller_handheld;
721 emulated_controller = emulated_controller_handheld; 722 } else {
722 } else { 723 emulated_controller_handheld->Disconnect();
723 emulated_controller_handheld->Disconnect(); 724 emulated_controller_p1->Connect(true);
724 emulated_controller_p1->Connect(true); 725 emulated_controller = emulated_controller_p1;
725 emulated_controller = emulated_controller_p1;
726 }
727 }
728 ui->controllerFrame->SetController(emulated_controller);
729 } 726 }
730 emulated_controller->SetNpadStyleIndex(type); 727 }
731 }); 728 ui->controllerFrame->SetController(emulated_controller);
729 }
730 emulated_controller->SetNpadStyleIndex(type);
731 });
732 732
733 connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this, 733 connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
734 &ConfigureInputPlayer::UpdateMappingWithDefaults); 734 &ConfigureInputPlayer::UpdateMappingWithDefaults);
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 54b3fe150..af8343b2e 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -35,10 +35,10 @@
35#include "yuzu/uisettings.h" 35#include "yuzu/uisettings.h"
36#include "yuzu/util/util.h" 36#include "yuzu/util/util.h"
37 37
38ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id, const std::string& file_name, 38ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
39 Core::System& system_) 39 Core::System& system_)
40 : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), 40 : QDialog(parent),
41 title_id(title_id), system{system_} { 41 ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_} {
42 const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); 42 const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
43 const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) 43 const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
44 : fmt::format("{:016X}", title_id); 44 : fmt::format("{:016X}", title_id);
@@ -116,8 +116,8 @@ void ConfigurePerGame::HandleApplyButtonClicked() {
116 ApplyConfiguration(); 116 ApplyConfiguration();
117} 117}
118 118
119void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { 119void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file_) {
120 this->file = std::move(file); 120 file = std::move(file_);
121 LoadConfiguration(); 121 LoadConfiguration();
122} 122}
123 123
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index e6dc05546..17a98a0f3 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -39,14 +39,14 @@ class ConfigurePerGame : public QDialog {
39 39
40public: 40public:
41 // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263 41 // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263
42 explicit ConfigurePerGame(QWidget* parent, u64 title_id, const std::string& file_name, 42 explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
43 Core::System& system_); 43 Core::System& system_);
44 ~ConfigurePerGame() override; 44 ~ConfigurePerGame() override;
45 45
46 /// Save all button configurations to settings file 46 /// Save all button configurations to settings file
47 void ApplyConfiguration(); 47 void ApplyConfiguration();
48 48
49 void LoadFromFile(FileSys::VirtualFile file); 49 void LoadFromFile(FileSys::VirtualFile file_);
50 50
51private: 51private:
52 void changeEvent(QEvent* event) override; 52 void changeEvent(QEvent* event) override;
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 7893a85bb..4906997ab 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -89,8 +89,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() {
89 Settings::values.disabled_addons[title_id] = disabled_addons; 89 Settings::values.disabled_addons[title_id] = disabled_addons;
90} 90}
91 91
92void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file) { 92void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file_) {
93 this->file = std::move(file); 93 file = std::move(file_);
94 LoadConfiguration(); 94 LoadConfiguration();
95} 95}
96 96
diff --git a/src/yuzu/configuration/configure_per_game_addons.h b/src/yuzu/configuration/configure_per_game_addons.h
index 24b017494..14690fba8 100644
--- a/src/yuzu/configuration/configure_per_game_addons.h
+++ b/src/yuzu/configuration/configure_per_game_addons.h
@@ -35,7 +35,7 @@ public:
35 /// Save all button configurations to settings file 35 /// Save all button configurations to settings file
36 void ApplyConfiguration(); 36 void ApplyConfiguration();
37 37
38 void LoadFromFile(FileSys::VirtualFile file); 38 void LoadFromFile(FileSys::VirtualFile file_);
39 39
40 void SetTitleId(u64 id); 40 void SetTitleId(u64 id);
41 41
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp
index 4fcc22b7a..688c2dd38 100644
--- a/src/yuzu/configuration/configure_ringcon.cpp
+++ b/src/yuzu/configuration/configure_ringcon.cpp
@@ -165,10 +165,10 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
165 const std::string invert_str = invert_value ? "+" : "-"; 165 const std::string invert_str = invert_value ? "+" : "-";
166 param.Set("invert_x", invert_str); 166 param.Set("invert_x", invert_str);
167 emulated_device->SetRingParam(param); 167 emulated_device->SetRingParam(param);
168 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; 168 for (int sub_button_id2 = 0; sub_button_id2 < ANALOG_SUB_BUTTONS_NUM;
169 ++sub_button_id) { 169 ++sub_button_id2) {
170 analog_map_buttons[sub_button_id]->setText( 170 analog_map_buttons[sub_button_id2]->setText(
171 AnalogToText(param, analog_sub_buttons[sub_button_id])); 171 AnalogToText(param, analog_sub_buttons[sub_button_id2]));
172 } 172 }
173 }); 173 });
174 context_menu.exec( 174 context_menu.exec(
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index c17da6fd1..06cc452c3 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -68,10 +68,10 @@ static QString ButtonToText(const Common::ParamPackage& param) {
68} 68}
69 69
70ConfigureTouchFromButton::ConfigureTouchFromButton( 70ConfigureTouchFromButton::ConfigureTouchFromButton(
71 QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps, 71 QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps_,
72 InputCommon::InputSubsystem* input_subsystem_, const int default_index) 72 InputCommon::InputSubsystem* input_subsystem_, const int default_index)
73 : QDialog(parent), ui(std::make_unique<Ui::ConfigureTouchFromButton>()), 73 : QDialog(parent), ui(std::make_unique<Ui::ConfigureTouchFromButton>()),
74 touch_maps(touch_maps), input_subsystem{input_subsystem_}, selected_index(default_index), 74 touch_maps{touch_maps_}, input_subsystem{input_subsystem_}, selected_index{default_index},
75 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { 75 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
76 ui->setupUi(this); 76 ui->setupUi(this);
77 binding_list_model = new QStandardItemModel(0, 3, this); 77 binding_list_model = new QStandardItemModel(0, 3, this);
diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h
index e1400481a..b8c55db66 100644
--- a/src/yuzu/configuration/configure_touch_from_button.h
+++ b/src/yuzu/configuration/configure_touch_from_button.h
@@ -37,7 +37,7 @@ class ConfigureTouchFromButton : public QDialog {
37 37
38public: 38public:
39 explicit ConfigureTouchFromButton(QWidget* parent, 39 explicit ConfigureTouchFromButton(QWidget* parent,
40 const std::vector<Settings::TouchFromButtonMap>& touch_maps, 40 const std::vector<Settings::TouchFromButtonMap>& touch_maps_,
41 InputCommon::InputSubsystem* input_subsystem_, 41 InputCommon::InputSubsystem* input_subsystem_,
42 int default_index = 0); 42 int default_index = 0);
43 ~ConfigureTouchFromButton() override; 43 ~ConfigureTouchFromButton() override;
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 8f486a131..0ea31cd33 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -113,9 +113,9 @@ QString WaitTreeText::GetText() const {
113 return text; 113 return text;
114} 114}
115 115
116WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table, 116WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address_, const Kernel::KHandleTable& handle_table,
117 Core::System& system_) 117 Core::System& system_)
118 : mutex_address(mutex_address), system{system_} { 118 : mutex_address{mutex_address_}, system{system_} {
119 mutex_value = system.Memory().Read32(mutex_address); 119 mutex_value = system.Memory().Read32(mutex_address);
120 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); 120 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask);
121 owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe(); 121 owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe();
@@ -140,8 +140,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() cons
140 return list; 140 return list;
141} 141}
142 142
143WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread, Core::System& system_) 143WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_)
144 : thread(thread), system{system_} {} 144 : thread{thread_}, system{system_} {}
145WaitTreeCallstack::~WaitTreeCallstack() = default; 145WaitTreeCallstack::~WaitTreeCallstack() = default;
146 146
147QString WaitTreeCallstack::GetText() const { 147QString WaitTreeCallstack::GetText() const {
@@ -171,8 +171,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
171} 171}
172 172
173WaitTreeSynchronizationObject::WaitTreeSynchronizationObject( 173WaitTreeSynchronizationObject::WaitTreeSynchronizationObject(
174 const Kernel::KSynchronizationObject& o, Core::System& system_) 174 const Kernel::KSynchronizationObject& object_, Core::System& system_)
175 : object(o), system{system_} {} 175 : object{object_}, system{system_} {}
176WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default; 176WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default;
177 177
178WaitTreeExpandableItem::WaitTreeExpandableItem() = default; 178WaitTreeExpandableItem::WaitTreeExpandableItem() = default;
@@ -380,8 +380,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
380 return list; 380 return list;
381} 381}
382 382
383WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object, Core::System& system_) 383WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_)
384 : WaitTreeSynchronizationObject(object, system_) {} 384 : WaitTreeSynchronizationObject(object_, system_) {}
385WaitTreeEvent::~WaitTreeEvent() = default; 385WaitTreeEvent::~WaitTreeEvent() = default;
386 386
387WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_) 387WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_)
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 4a36dfc48..f21b9f467 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -78,7 +78,7 @@ public:
78class WaitTreeMutexInfo : public WaitTreeExpandableItem { 78class WaitTreeMutexInfo : public WaitTreeExpandableItem {
79 Q_OBJECT 79 Q_OBJECT
80public: 80public:
81 explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table, 81 explicit WaitTreeMutexInfo(VAddr mutex_address_, const Kernel::KHandleTable& handle_table,
82 Core::System& system_); 82 Core::System& system_);
83 ~WaitTreeMutexInfo() override; 83 ~WaitTreeMutexInfo() override;
84 84
@@ -97,7 +97,7 @@ private:
97class WaitTreeCallstack : public WaitTreeExpandableItem { 97class WaitTreeCallstack : public WaitTreeExpandableItem {
98 Q_OBJECT 98 Q_OBJECT
99public: 99public:
100 explicit WaitTreeCallstack(const Kernel::KThread& thread, Core::System& system_); 100 explicit WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_);
101 ~WaitTreeCallstack() override; 101 ~WaitTreeCallstack() override;
102 102
103 QString GetText() const override; 103 QString GetText() const override;
@@ -112,7 +112,7 @@ private:
112class WaitTreeSynchronizationObject : public WaitTreeExpandableItem { 112class WaitTreeSynchronizationObject : public WaitTreeExpandableItem {
113 Q_OBJECT 113 Q_OBJECT
114public: 114public:
115 explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object, 115 explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object_,
116 Core::System& system_); 116 Core::System& system_);
117 ~WaitTreeSynchronizationObject() override; 117 ~WaitTreeSynchronizationObject() override;
118 118
@@ -162,7 +162,7 @@ private:
162class WaitTreeEvent : public WaitTreeSynchronizationObject { 162class WaitTreeEvent : public WaitTreeSynchronizationObject {
163 Q_OBJECT 163 Q_OBJECT
164public: 164public:
165 explicit WaitTreeEvent(const Kernel::KReadableEvent& object, Core::System& system_); 165 explicit WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_);
166 ~WaitTreeEvent() override; 166 ~WaitTreeEvent() override;
167}; 167};
168 168
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 6321afc83..05d309827 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -28,8 +28,8 @@
28#include "yuzu/uisettings.h" 28#include "yuzu/uisettings.h"
29#include "yuzu/util/controller_navigation.h" 29#include "yuzu/util/controller_navigation.h"
30 30
31GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) 31GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent)
32 : QObject(parent), gamelist{gamelist} {} 32 : QObject(parent), gamelist{gamelist_} {}
33 33
34// EventFilter in order to process systemkeys while editing the searchfield 34// EventFilter in order to process systemkeys while editing the searchfield
35bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) { 35bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) {
@@ -80,9 +80,9 @@ bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* eve
80 return QObject::eventFilter(obj, event); 80 return QObject::eventFilter(obj, event);
81} 81}
82 82
83void GameListSearchField::setFilterResult(int visible, int total) { 83void GameListSearchField::setFilterResult(int visible_, int total_) {
84 this->visible = visible; 84 visible = visible_;
85 this->total = total; 85 total = total_;
86 86
87 label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); 87 label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible));
88} 88}
@@ -309,9 +309,9 @@ void GameList::OnFilterCloseClicked() {
309 main_window->filterBarSetChecked(false); 309 main_window->filterBarSetChecked(false);
310} 310}
311 311
312GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvider* provider, 312GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvider* provider_,
313 Core::System& system_, GMainWindow* parent) 313 Core::System& system_, GMainWindow* parent)
314 : QWidget{parent}, vfs(std::move(vfs)), provider(provider), system{system_} { 314 : QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_}, system{system_} {
315 watcher = new QFileSystemWatcher(this); 315 watcher = new QFileSystemWatcher(this);
316 connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory); 316 connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory);
317 317
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 464da98ad..bc36d015a 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -67,8 +67,8 @@ public:
67 COLUMN_COUNT, // Number of columns 67 COLUMN_COUNT, // Number of columns
68 }; 68 };
69 69
70 explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs, 70 explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
71 FileSys::ManualContentProvider* provider, Core::System& system_, 71 FileSys::ManualContentProvider* provider_, Core::System& system_,
72 GMainWindow* parent = nullptr); 72 GMainWindow* parent = nullptr);
73 ~GameList() override; 73 ~GameList() override;
74 74
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index f2a986ed8..cd7d63536 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -225,8 +225,8 @@ public:
225 static constexpr int GameDirRole = Qt::UserRole + 2; 225 static constexpr int GameDirRole = Qt::UserRole + 2;
226 226
227 explicit GameListDir(UISettings::GameDir& directory, 227 explicit GameListDir(UISettings::GameDir& directory,
228 GameListItemType dir_type = GameListItemType::CustomDir) 228 GameListItemType dir_type_ = GameListItemType::CustomDir)
229 : dir_type{dir_type} { 229 : dir_type{dir_type_} {
230 setData(type(), TypeRole); 230 setData(type(), TypeRole);
231 231
232 UISettings::GameDir* game_dir = &directory; 232 UISettings::GameDir* game_dir = &directory;
@@ -348,7 +348,7 @@ public:
348 explicit GameListSearchField(GameList* parent = nullptr); 348 explicit GameListSearchField(GameList* parent = nullptr);
349 349
350 QString filterText() const; 350 QString filterText() const;
351 void setFilterResult(int visible, int total); 351 void setFilterResult(int visible_, int total_);
352 352
353 void clear(); 353 void clear();
354 void setFocus(); 354 void setFocus();
@@ -356,7 +356,7 @@ public:
356private: 356private:
357 class KeyReleaseEater : public QObject { 357 class KeyReleaseEater : public QObject {
358 public: 358 public:
359 explicit KeyReleaseEater(GameList* gamelist, QObject* parent = nullptr); 359 explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr);
360 360
361 private: 361 private:
362 GameList* gamelist = nullptr; 362 GameList* gamelist = nullptr;
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index ca1899b5c..63326968b 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -223,12 +223,12 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
223} 223}
224} // Anonymous namespace 224} // Anonymous namespace
225 225
226GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs, 226GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_,
227 FileSys::ManualContentProvider* provider, 227 FileSys::ManualContentProvider* provider_,
228 QVector<UISettings::GameDir>& game_dirs, 228 QVector<UISettings::GameDir>& game_dirs_,
229 const CompatibilityList& compatibility_list, Core::System& system_) 229 const CompatibilityList& compatibility_list_, Core::System& system_)
230 : vfs(std::move(vfs)), provider(provider), game_dirs(game_dirs), 230 : vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
231 compatibility_list(compatibility_list), system{system_} {} 231 compatibility_list{compatibility_list_}, system{system_} {}
232 232
233GameListWorker::~GameListWorker() = default; 233GameListWorker::~GameListWorker() = default;
234 234
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 622d241fb..24a4e92c3 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -33,10 +33,10 @@ class GameListWorker : public QObject, public QRunnable {
33 Q_OBJECT 33 Q_OBJECT
34 34
35public: 35public:
36 explicit GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs, 36 explicit GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
37 FileSys::ManualContentProvider* provider, 37 FileSys::ManualContentProvider* provider_,
38 QVector<UISettings::GameDir>& game_dirs, 38 QVector<UISettings::GameDir>& game_dirs_,
39 const CompatibilityList& compatibility_list, Core::System& system_); 39 const CompatibilityList& compatibility_list_, Core::System& system_);
40 ~GameListWorker() override; 40 ~GameListWorker() override;
41 41
42 /// Starts the processing of directory tree information. 42 /// Starts the processing of directory tree information.
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 33886e50e..b460020b1 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -934,8 +934,7 @@ void GMainWindow::InitializeWidgets() {
934 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan); 934 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan);
935 } else { 935 } else {
936 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); 936 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL);
937 const auto filter = Settings::values.scaling_filter.GetValue(); 937 if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
938 if (filter == Settings::ScalingFilter::Fsr) {
939 Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor); 938 Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor);
940 UpdateFilterText(); 939 UpdateFilterText();
941 } 940 }
@@ -1442,7 +1441,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
1442 } 1441 }
1443 return false; 1442 return false;
1444 } 1443 }
1445 game_path = filename; 1444 current_game_path = filename;
1446 1445
1447 system->TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt"); 1446 system->TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt");
1448 return true; 1447 return true;
@@ -1508,7 +1507,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1508 1507
1509 // Register an ExecuteProgram callback such that Core can execute a sub-program 1508 // Register an ExecuteProgram callback such that Core can execute a sub-program
1510 system->RegisterExecuteProgramCallback( 1509 system->RegisterExecuteProgramCallback(
1511 [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); 1510 [this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); });
1512 1511
1513 // Register an Exit callback such that Core can exit the currently running application. 1512 // Register an Exit callback such that Core can exit the currently running application.
1514 system->RegisterExitCallback([this]() { render_window->Exit(); }); 1513 system->RegisterExitCallback([this]() { render_window->Exit(); });
@@ -1641,7 +1640,7 @@ void GMainWindow::ShutdownGame() {
1641 emu_frametime_label->setVisible(false); 1640 emu_frametime_label->setVisible(false);
1642 renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); 1641 renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan);
1643 1642
1644 game_path.clear(); 1643 current_game_path.clear();
1645 1644
1646 // When closing the game, destroy the GLWindow to clear the context after the game is closed 1645 // When closing the game, destroy the GLWindow to clear the context after the game is closed
1647 render_window->ReleaseRenderTarget(); 1646 render_window->ReleaseRenderTarget();
@@ -2560,7 +2559,7 @@ void GMainWindow::OnRestartGame() {
2560 return; 2559 return;
2561 } 2560 }
2562 // Make a copy since BootGame edits game_path 2561 // Make a copy since BootGame edits game_path
2563 BootGame(QString(game_path)); 2562 BootGame(QString(current_game_path));
2564} 2563}
2565 2564
2566void GMainWindow::OnPauseGame() { 2565void GMainWindow::OnPauseGame() {
@@ -2989,7 +2988,7 @@ void GMainWindow::OnToggleAdaptingFilter() {
2989 2988
2990void GMainWindow::OnConfigurePerGame() { 2989void GMainWindow::OnConfigurePerGame() {
2991 const u64 title_id = system->GetCurrentProcessProgramID(); 2990 const u64 title_id = system->GetCurrentProcessProgramID();
2992 OpenPerGameConfiguration(title_id, game_path.toStdString()); 2991 OpenPerGameConfiguration(title_id, current_game_path.toStdString());
2993} 2992}
2994 2993
2995void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { 2994void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 600647015..8cf224c9c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -369,7 +369,7 @@ private:
369 bool emulation_running = false; 369 bool emulation_running = false;
370 std::unique_ptr<EmuThread> emu_thread; 370 std::unique_ptr<EmuThread> emu_thread;
371 // The path to the game currently running 371 // The path to the game currently running
372 QString game_path; 372 QString current_game_path;
373 373
374 bool auto_paused = false; 374 bool auto_paused = false;
375 bool auto_muted = false; 375 bool auto_muted = false;
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 9746585f5..58b885465 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -20,7 +20,7 @@ enum class MouseButton;
20 20
21class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { 21class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
22public: 22public:
23 explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem, Core::System& system_); 23 explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_);
24 ~EmuWindow_SDL2(); 24 ~EmuWindow_SDL2();
25 25
26 /// Whether the window is still open, and a close request hasn't yet been sent 26 /// Whether the window is still open, and a close request hasn't yet been sent
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index 8075c9082..9b660c13c 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -73,9 +73,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
73 return unsupported_ext.empty(); 73 return unsupported_ext.empty();
74} 74}
75 75
76EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, 76EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_,
77 Core::System& system_, bool fullscreen) 77 Core::System& system_, bool fullscreen)
78 : EmuWindow_SDL2{input_subsystem, system_} { 78 : EmuWindow_SDL2{input_subsystem_, system_} {
79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
80 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); 80 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); 81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
index d159166fd..39346e704 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
@@ -17,7 +17,7 @@ class InputSubsystem;
17 17
18class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { 18class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 {
19public: 19public:
20 explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, Core::System& system_, 20 explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_,
21 bool fullscreen); 21 bool fullscreen);
22 ~EmuWindow_SDL2_GL(); 22 ~EmuWindow_SDL2_GL();
23 23
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index d5fe35aa0..65455c86e 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -21,9 +21,9 @@
21#include <SDL.h> 21#include <SDL.h>
22#include <SDL_syswm.h> 22#include <SDL_syswm.h>
23 23
24EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, 24EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_,
25 Core::System& system_, bool fullscreen) 25 Core::System& system_, bool fullscreen)
26 : EmuWindow_SDL2{input_subsystem, system_} { 26 : EmuWindow_SDL2{input_subsystem_, system_} {
27 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, 27 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name,
28 Common::g_scm_branch, Common::g_scm_desc); 28 Common::g_scm_branch, Common::g_scm_desc);
29 render_window = 29 render_window =
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
index d92e3aaab..e39ad754d 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
@@ -18,7 +18,7 @@ class InputSubsystem;
18 18
19class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { 19class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 {
20public: 20public:
21 explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, Core::System& system, 21 explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system,
22 bool fullscreen); 22 bool fullscreen);
23 ~EmuWindow_SDL2_VK() override; 23 ~EmuWindow_SDL2_VK() override;
24 24
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 0dce5e274..e840732e2 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -138,6 +138,12 @@ int main(int argc, char** argv) {
138 138
139 Config config{config_path}; 139 Config config{config_path};
140 140
141 // apply the log_filter setting
142 // the logger was initialized before and doesn't pick up the filter on its own
143 Common::Log::Filter filter;
144 filter.ParseFilterString(Settings::values.log_filter.GetValue());
145 Common::Log::SetGlobalFilter(filter);
146
141 if (!program_args.empty()) { 147 if (!program_args.empty()) {
142 Settings::values.program_args = program_args; 148 Settings::values.program_args = program_args;
143 } 149 }