Reset controller colours on emulator shutdown (#4537)

* Reset controller colours on emulator shutdown

* bruh moment

* Don't use the destructor for this

* clang, formatter of night

* forgot to stage this file

* ffs

* fix tests

* fixed tests?

* gcn tests fixed?

* now?

* possible fixed

---------

Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
kalaposfos13
2026-06-07 23:39:50 +02:00
committed by GitHub
parent c151eeea87
commit 852539829a
11 changed files with 92 additions and 29 deletions
+3 -3
View File
@@ -3,6 +3,7 @@
#include "common/arch.h"
#include "common/assert.h"
#include "emulator.h"
#if defined(ARCH_X86_64)
#define Crash() __asm__ __volatile__("int $3")
@@ -13,13 +14,12 @@
#endif
void assert_fail_impl() {
Common::Log::Flush();
Common::Singleton<Core::Emulator>::Instance()->Shutdown();
Crash();
}
[[noreturn]] void unreachable_impl() {
Common::Log::Flush();
Crash();
assert_fail_impl();
throw std::runtime_error("Unreachable code");
}
@@ -548,7 +548,7 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
return ret;
}
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(u32 error, s64 unk) {
if (unk != 0) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
@@ -556,7 +556,7 @@ s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) {
s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(u32 error, s64 unk) {
if (unk != 0) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
+2 -8
View File
@@ -556,18 +556,12 @@ int PS4_SYSV_ABI scePadResetLightBar(s32 handle) {
s32 colour_index = u ? u->user_color - 1 : 0;
Input::Colour colour{255, 0, 0};
if (colour_index >= 0 && colour_index <= 3) {
static constexpr Input::Colour colours[4]{
{0, 0, 255}, // blue
{255, 0, 0}, // red
{0, 255, 0}, // green
{255, 0, 255}, // pink
};
colour = colours[colour_index];
colour = Input::g_user_colours[colour_index];
} else {
LOG_ERROR(Lib_Pad, "Invalid user colour value {} for controller {}, falling back to blue",
colour_index, handle);
}
controller.SetLightBarRGB(colour.r, colour.g, colour.b);
controller.SetLightBarRGB(colour);
return ORBIS_OK;
}
+6 -6
View File
@@ -7,6 +7,7 @@
#include "common/signal_context.h"
#include "core/libraries/kernel/threads/exception.h"
#include "core/signals.h"
#include "emulator.h"
#ifdef _WIN32
#include <windows.h>
@@ -52,10 +53,6 @@ static LONG WINAPI SignalHandler(EXCEPTION_POINTERS* pExp) noexcept {
case DBG_PRINTEXCEPTION_WIDE_C:
// Used by OutputDebugString functions.
return EXCEPTION_CONTINUE_EXECUTION;
case EXCEPTION_BREAKPOINT:
// This is almost certainly coming from our asserts/unreachables, no need to log it again.
Common::Log::Flush();
return EXCEPTION_CONTINUE_SEARCH;
default:
break;
}
@@ -64,8 +61,11 @@ static LONG WINAPI SignalHandler(EXCEPTION_POINTERS* pExp) noexcept {
return EXCEPTION_CONTINUE_EXECUTION;
}
LOG_CRITICAL(Debug, "Unhandled Exception code {:#x} at {}", code, address);
Common::Log::Flush();
// Breakpoints almost certainly come from our asserts/unreachables, no need to log it again.
if (code != EXCEPTION_BREAKPOINT) {
LOG_CRITICAL(Debug, "Unhandled Exception code {:#x} at {}", code, address);
Common::Singleton<Core::Emulator>::Instance()->Shutdown();
}
return EXCEPTION_CONTINUE_SEARCH;
}
+18
View File
@@ -57,6 +57,8 @@ Frontend::WindowSDL* g_window = nullptr;
namespace Core {
std::mutex exit_mutex{};
Emulator::Emulator() {
// Initialize NT API functions, set high priority and disable WER
#ifdef _WIN32
@@ -68,10 +70,26 @@ Emulator::Emulator() {
WSADATA wsaData;
WSAStartup(versionWanted, &wsaData);
#endif
std::at_quick_exit([]() { Common::Singleton<Core::Emulator>::Instance()->Shutdown(); });
}
Emulator::~Emulator() {}
void Emulator::Shutdown() {
static bool exit_done = false;
std::scoped_lock l{exit_mutex};
if (exit_done) {
return;
}
Common::Log::Flush();
if (controllers) {
controllers->ResetLightbarColors();
// need to give SDL time to do this before the runtime exits
std::this_thread::sleep_for(std::chrono::milliseconds{10});
}
exit_done = true;
}
s32 ReadCompiledSdkVersion(const std::filesystem::path& file) {
Core::Loader::Elf elf;
elf.Open(file);
+1
View File
@@ -29,6 +29,7 @@ public:
void Run(std::filesystem::path file, std::vector<std::string> args = {},
std::optional<std::filesystem::path> game_folder = {});
void UpdatePlayTime(const std::string& serial);
void Shutdown();
/**
* This will kill the current process and launch a new process with the same configuration
+21 -1
View File
@@ -150,7 +150,7 @@ void GameController::UpdateAxisSmoothing() {
m_state.UpdateAxisSmoothing();
}
void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
void GameController::SetLightBarRGB(u8 const r, u8 const g, u8 const b) {
if (override_colour.has_value()) {
return;
}
@@ -160,6 +160,10 @@ void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
}
}
void GameController::SetLightBarRGB(Colour const c) {
SetLightBarRGB(c.r, c.g, c.b);
}
Colour GameController::GetLightBarRGB() {
return colour;
}
@@ -170,6 +174,22 @@ void GameController::PollLightColour() {
}
}
void GameControllers::ResetLightbarColors() {
for (auto& c : controllers) {
auto const* u = UserManagement.GetUserByID(c->user_id);
if (!u || !c->m_sdl_gamepad) {
continue;
}
auto const i = u->user_color - 1;
if (i < 0 || i > 3) {
continue;
}
auto const& col = g_user_colours[i];
c->override_colour = std::nullopt;
c->SetLightBarRGB(col);
}
}
bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) {
if (m_sdl_gamepad != nullptr) {
return SDL_RumbleGamepad(m_sdl_gamepad, (smallMotor / 255.0f) * 0xFFFF,
+9 -1
View File
@@ -43,6 +43,12 @@ struct TouchpadEntry {
struct Colour {
u8 r, g, b;
};
static constexpr Input::Colour g_user_colours[4]{
{0, 0, 255}, // blue
{255, 0, 0}, // red
{0, 255, 0}, // green
{255, 0, 255}, // pink
};
struct State {
private:
@@ -127,7 +133,8 @@ public:
void UpdateGyro(const float gyro[3]);
void UpdateAcceleration(const float acceleration[3]);
void UpdateAxisSmoothing();
void SetLightBarRGB(u8 r, u8 g, u8 b);
void SetLightBarRGB(u8 const r, u8 const g, u8 const b);
void SetLightBarRGB(Colour const c);
Colour GetLightBarRGB();
void PollLightColour();
bool SetVibration(u8 smallMotor, u8 largeMotor);
@@ -205,6 +212,7 @@ public:
controllers[i]->SetLightBarRGB(r, g, b);
controllers[i]->override_colour = {r, g, b};
}
void ResetLightbarColors();
};
} // namespace Input
+4
View File
@@ -25,6 +25,7 @@ set(SETTINGS_TEST_SOURCES
# Stubs that replace dependencies
stubs/common_stub.cpp
stubs/core_stub.cpp
stubs/scm_rev_stub.cpp
stubs/sdl_stub.cpp
@@ -115,6 +116,8 @@ set(GCN_TEST_SOURCES
stubs/common_stub.cpp
stubs/resource_tracking_pass_stub.cpp
stubs/scm_rev_stub.cpp
stubs/sdl_stub.cpp
stubs/core_stub.cpp
gcn/gcn_test_runner.hpp
gcn/gcn_test_runner.cpp
@@ -226,6 +229,7 @@ set(HTTP_TEST_SOURCES
stubs/scm_rev_stub.cpp
stubs/sdl_stub.cpp
stubs/loader_stub.cpp
stubs/core_stub.cpp
stubs/kernel_stub.cpp
# Tests
+12
View File
@@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "emulator.h"
namespace Core {
Emulator::Emulator() {}
Emulator::~Emulator() {}
void Emulator::Shutdown() {}
} // namespace Core
+14 -8
View File
@@ -2,17 +2,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <SDL3/SDL_messagebox.h>
#include "sdl_window.h"
namespace Frontend {
WindowSDL::~WindowSDL() = default;
}
extern "C" {
bool SDL_ShowMessageBox(const SDL_MessageBoxData* /* messageboxdata */, int* buttonid) {
if (buttonid) *buttonid = 0; // "No",skip migration
return true;
}
bool SDL_ShowMessageBox(const SDL_MessageBoxData* /* messageboxdata */, int* buttonid) {
if (buttonid)
*buttonid = 0; // "No",skip migration
return true;
}
bool SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags /* flags */, const char* /* title */,
const char* /* message */, SDL_Window* /* window */) {
return true;
}
bool SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags /* flags */, const char* /* title */,
const char* /* message */, SDL_Window* /* window */) {
return true;
}
} // extern "C"