From faf202f0f6d6c2f584b735874734ed64216401a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 18 Sep 2016 23:32:53 +0200 Subject: [PATCH 1/7] IPC_HLE/stm: Separate header and implementation There was as far as I know no reason to put everything in the header. Separating the declaration from the implementation reduces build times in case the implementation is updated without changing any declaration. --- Source/Core/Core/CMakeLists.txt | 1 + Source/Core/Core/Core.vcxproj | 5 +- Source/Core/Core/Core.vcxproj.filters | 5 +- .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp | 134 +++++++++++++++++ .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.h | 138 ++---------------- 5 files changed, 151 insertions(+), 132 deletions(-) create mode 100644 Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 5989d47399..ef5c3e9d1e 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -143,6 +143,7 @@ set(SRCS ActionReplay.cpp IPC_HLE/WII_Socket.cpp IPC_HLE/WII_IPC_HLE_Device_net.cpp IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp + IPC_HLE/WII_IPC_HLE_Device_stm.cpp IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp IPC_HLE/WII_IPC_HLE_Device_usb.cpp IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index e89a1d6a41..f0a54a74f3 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -183,6 +183,7 @@ + @@ -386,8 +387,8 @@ - + @@ -480,4 +481,4 @@ - \ No newline at end of file + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index bc12b068ac..082b302901 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -585,6 +585,9 @@ IPC HLE %28IOS/Starlet%29\SDIO - SD Card + + IPC HLE %28IOS/Starlet%29 + IPC HLE %28IOS/Starlet%29\USB @@ -1247,4 +1250,4 @@ - \ No newline at end of file + diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp new file mode 100644 index 0000000000..7b801b5c1c --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp @@ -0,0 +1,134 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h" + +IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Open(u32 _CommandAddress, u32 _Mode) +{ + INFO_LOG(WII_IPC_STM, "STM immediate: Open"); + Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); + m_Active = true; + return GetDefaultReply(); +} + +IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Close(u32 _CommandAddress, bool _bForce) +{ + INFO_LOG(WII_IPC_STM, "STM immediate: Close"); + if (!_bForce) + Memory::Write_U32(0, _CommandAddress + 4); + m_Active = false; + return GetDefaultReply(); +} + +IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 _CommandAddress) +{ + u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C); + u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); + u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); + u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); + u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); + + // Prepare the out buffer(s) with zeroes as a safety precaution + // to avoid returning bad values + Memory::Memset(BufferOut, 0, BufferOutSize); + u32 ReturnValue = 0; + + switch (Parameter) + { + case IOCTL_STM_RELEASE_EH: + INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); + INFO_LOG(WII_IPC_STM, " IOCTL_STM_RELEASE_EH"); + break; + + case IOCTL_STM_HOTRESET: + INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); + INFO_LOG(WII_IPC_STM, " IOCTL_STM_HOTRESET"); + break; + + case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes) + INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); + INFO_LOG(WII_IPC_STM, " IOCTL_STM_VIDIMMING"); + // DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_STM); + // Memory::Write_U32(1, BufferOut); + // ReturnValue = 1; + break; + + case IOCTL_STM_LEDMODE: // (Input: 20 bytes, Output: 20 bytes) + INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); + INFO_LOG(WII_IPC_STM, " IOCTL_STM_LEDMODE"); + break; + + default: + { + _dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_immediate: 0x%x", Parameter); + + INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); + DEBUG_LOG(WII_IPC_STM, " Parameter: 0x%x", Parameter); + DEBUG_LOG(WII_IPC_STM, " InBuffer: 0x%08x", BufferIn); + DEBUG_LOG(WII_IPC_STM, " InBufferSize: 0x%08x", BufferInSize); + DEBUG_LOG(WII_IPC_STM, " OutBuffer: 0x%08x", BufferOut); + DEBUG_LOG(WII_IPC_STM, " OutBufferSize: 0x%08x", BufferOutSize); + } + break; + } + + // Write return value to the IPC call + Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); + return GetDefaultReply(); +} + +IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Open(u32 _CommandAddress, u32 _Mode) +{ + Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); + m_Active = true; + return GetDefaultReply(); +} + +IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Close(u32 _CommandAddress, bool _bForce) +{ + m_EventHookAddress = 0; + + INFO_LOG(WII_IPC_STM, "STM eventhook: Close"); + if (!_bForce) + Memory::Write_U32(0, _CommandAddress + 4); + m_Active = false; + return GetDefaultReply(); +} + +IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 _CommandAddress) +{ + u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C); + if (Parameter != IOCTL_STM_EVENTHOOK) + { + ERROR_LOG(WII_IPC_STM, "Bad IOCtl in CWII_IPC_HLE_Device_stm_eventhook"); + Memory::Write_U32(FS_EINVAL, _CommandAddress + 4); + return GetDefaultReply(); + } + + // IOCTL_STM_EVENTHOOK waits until the reset button or power button + // is pressed. + m_EventHookAddress = _CommandAddress; + return GetNoReply(); +} + +void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() +{ + if (!m_Active || m_EventHookAddress == 0) + { + // If the device isn't open, ignore the button press. + return; + } + + // The reset button returns STM_EVENT_RESET. + u32 BufferOut = Memory::Read_U32(m_EventHookAddress + 0x18); + Memory::Write_U32(STM_EVENT_RESET, BufferOut); + + // Fill in command buffer. + Memory::Write_U32(FS_SUCCESS, m_EventHookAddress + 4); + Memory::Write_U32(IPC_REP_ASYNC, m_EventHookAddress); + Memory::Write_U32(IPC_CMD_IOCTL, m_EventHookAddress + 8); + + // Generate a reply to the IPC command. + WII_IPC_HLE_Interface::EnqueueReply(m_EventHookAddress); +} diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h index b8c78b2776..10f5ed6000 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h @@ -4,7 +4,6 @@ #pragma once -#include #include "Core/IPC_HLE/WII_IPC_HLE_Device.h" enum @@ -40,80 +39,10 @@ public: { } - virtual ~CWII_IPC_HLE_Device_stm_immediate() {} - IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override - { - INFO_LOG(WII_IPC_STM, "STM immediate: Open"); - Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); - m_Active = true; - return GetDefaultReply(); - } - - IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override - { - INFO_LOG(WII_IPC_STM, "STM immediate: Close"); - if (!_bForce) - Memory::Write_U32(0, _CommandAddress + 4); - m_Active = false; - return GetDefaultReply(); - } - - IPCCommandResult IOCtl(u32 _CommandAddress) override - { - u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C); - u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); - u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); - u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); - u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); - - // Prepare the out buffer(s) with zeroes as a safety precaution - // to avoid returning bad values - Memory::Memset(BufferOut, 0, BufferOutSize); - u32 ReturnValue = 0; - - switch (Parameter) - { - case IOCTL_STM_RELEASE_EH: - INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - INFO_LOG(WII_IPC_STM, " IOCTL_STM_RELEASE_EH"); - break; - - case IOCTL_STM_HOTRESET: - INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - INFO_LOG(WII_IPC_STM, " IOCTL_STM_HOTRESET"); - break; - - case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes) - INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - INFO_LOG(WII_IPC_STM, " IOCTL_STM_VIDIMMING"); - // DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_STM); - // Memory::Write_U32(1, BufferOut); - // ReturnValue = 1; - break; - - case IOCTL_STM_LEDMODE: // (Input: 20 bytes, Output: 20 bytes) - INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - INFO_LOG(WII_IPC_STM, " IOCTL_STM_LEDMODE"); - break; - - default: - { - _dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_immediate: 0x%x", Parameter); - - INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - DEBUG_LOG(WII_IPC_STM, " Parameter: 0x%x", Parameter); - DEBUG_LOG(WII_IPC_STM, " InBuffer: 0x%08x", BufferIn); - DEBUG_LOG(WII_IPC_STM, " InBufferSize: 0x%08x", BufferInSize); - DEBUG_LOG(WII_IPC_STM, " OutBuffer: 0x%08x", BufferOut); - DEBUG_LOG(WII_IPC_STM, " OutBufferSize: 0x%08x", BufferOutSize); - } - break; - } - - // Write return value to the IPC call - Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); - return GetDefaultReply(); - } + ~CWII_IPC_HLE_Device_stm_immediate() override = default; + IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override; + IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override; + IPCCommandResult IOCtl(u32 _CommandAddress) override; }; // The /dev/stm/eventhook @@ -125,61 +54,12 @@ public: { } - virtual ~CWII_IPC_HLE_Device_stm_eventhook() {} - IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override - { - Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); - m_Active = true; - return GetDefaultReply(); - } + ~CWII_IPC_HLE_Device_stm_eventhook() override = default; + IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override; + IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override; + IPCCommandResult IOCtl(u32 _CommandAddress) override; - IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override - { - m_EventHookAddress = 0; - - INFO_LOG(WII_IPC_STM, "STM eventhook: Close"); - if (!_bForce) - Memory::Write_U32(0, _CommandAddress + 4); - m_Active = false; - return GetDefaultReply(); - } - - IPCCommandResult IOCtl(u32 _CommandAddress) override - { - u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C); - if (Parameter != IOCTL_STM_EVENTHOOK) - { - ERROR_LOG(WII_IPC_STM, "Bad IOCtl in CWII_IPC_HLE_Device_stm_eventhook"); - Memory::Write_U32(FS_EINVAL, _CommandAddress + 4); - return GetDefaultReply(); - } - - // IOCTL_STM_EVENTHOOK waits until the reset button or power button - // is pressed. - m_EventHookAddress = _CommandAddress; - return GetNoReply(); - } - - void ResetButton() - { - if (!m_Active || m_EventHookAddress == 0) - { - // If the device isn't open, ignore the button press. - return; - } - - // The reset button returns STM_EVENT_RESET. - u32 BufferOut = Memory::Read_U32(m_EventHookAddress + 0x18); - Memory::Write_U32(STM_EVENT_RESET, BufferOut); - - // Fill in command buffer. - Memory::Write_U32(FS_SUCCESS, m_EventHookAddress + 4); - Memory::Write_U32(IPC_REP_ASYNC, m_EventHookAddress); - Memory::Write_U32(IPC_CMD_IOCTL, m_EventHookAddress + 8); - - // Generate a reply to the IPC command. - WII_IPC_HLE_Interface::EnqueueReply(m_EventHookAddress); - } + void ResetButton(); // STATE_TO_SAVE u32 m_EventHookAddress; From 5fb17a9014ee9dc0ea908592e5a0c57a5481ab77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 18 Sep 2016 23:41:43 +0200 Subject: [PATCH 2/7] IPC_HLE/stm: Clean up naming Switches to the new naming conventions. --- .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp | 84 +++++++++---------- .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.h | 26 +++--- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp index 7b801b5c1c..42c6dddae2 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp @@ -4,37 +4,37 @@ #include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h" -IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Open(u32 _CommandAddress, u32 _Mode) +IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Open(u32 command_address, u32 mode) { INFO_LOG(WII_IPC_STM, "STM immediate: Open"); - Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); + Memory::Write_U32(GetDeviceID(), command_address + 4); m_Active = true; return GetDefaultReply(); } -IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Close(u32 _CommandAddress, bool _bForce) +IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Close(u32 command_address, bool force) { INFO_LOG(WII_IPC_STM, "STM immediate: Close"); - if (!_bForce) - Memory::Write_U32(0, _CommandAddress + 4); + if (!force) + Memory::Write_U32(0, command_address + 4); m_Active = false; return GetDefaultReply(); } -IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 _CommandAddress) +IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address) { - u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C); - u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); - u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); - u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); - u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); + u32 parameter = Memory::Read_U32(command_address + 0x0C); + u32 buffer_in = Memory::Read_U32(command_address + 0x10); + u32 buffer_in_size = Memory::Read_U32(command_address + 0x14); + u32 buffer_out = Memory::Read_U32(command_address + 0x18); + u32 buffer_out_size = Memory::Read_U32(command_address + 0x1C); // Prepare the out buffer(s) with zeroes as a safety precaution // to avoid returning bad values - Memory::Memset(BufferOut, 0, BufferOutSize); - u32 ReturnValue = 0; + Memory::Memset(buffer_out, 0, buffer_out_size); + u32 return_value = 0; - switch (Parameter) + switch (parameter) { case IOCTL_STM_RELEASE_EH: INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); @@ -49,9 +49,9 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 _CommandAddress) case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes) INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); INFO_LOG(WII_IPC_STM, " IOCTL_STM_VIDIMMING"); - // DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_STM); - // Memory::Write_U32(1, BufferOut); - // ReturnValue = 1; + // DumpCommands(buffer_in, buffer_in_size / 4, LogTypes::WII_IPC_STM); + // Memory::Write_U32(1, buffer_out); + // return_value = 1; break; case IOCTL_STM_LEDMODE: // (Input: 20 bytes, Output: 20 bytes) @@ -61,74 +61,74 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 _CommandAddress) default: { - _dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_immediate: 0x%x", Parameter); + _dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_immediate: 0x%x", parameter); INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - DEBUG_LOG(WII_IPC_STM, " Parameter: 0x%x", Parameter); - DEBUG_LOG(WII_IPC_STM, " InBuffer: 0x%08x", BufferIn); - DEBUG_LOG(WII_IPC_STM, " InBufferSize: 0x%08x", BufferInSize); - DEBUG_LOG(WII_IPC_STM, " OutBuffer: 0x%08x", BufferOut); - DEBUG_LOG(WII_IPC_STM, " OutBufferSize: 0x%08x", BufferOutSize); + DEBUG_LOG(WII_IPC_STM, " parameter: 0x%x", parameter); + DEBUG_LOG(WII_IPC_STM, " InBuffer: 0x%08x", buffer_in); + DEBUG_LOG(WII_IPC_STM, " InBufferSize: 0x%08x", buffer_in_size); + DEBUG_LOG(WII_IPC_STM, " OutBuffer: 0x%08x", buffer_out); + DEBUG_LOG(WII_IPC_STM, " OutBufferSize: 0x%08x", buffer_out_size); } break; } // Write return value to the IPC call - Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); + Memory::Write_U32(return_value, command_address + 0x4); return GetDefaultReply(); } -IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Open(u32 _CommandAddress, u32 _Mode) +IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Open(u32 command_address, u32 mode) { - Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); + Memory::Write_U32(GetDeviceID(), command_address + 4); m_Active = true; return GetDefaultReply(); } -IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Close(u32 _CommandAddress, bool _bForce) +IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Close(u32 command_address, bool force) { - m_EventHookAddress = 0; + m_event_hook_address = 0; INFO_LOG(WII_IPC_STM, "STM eventhook: Close"); - if (!_bForce) - Memory::Write_U32(0, _CommandAddress + 4); + if (!force) + Memory::Write_U32(0, command_address + 4); m_Active = false; return GetDefaultReply(); } -IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 _CommandAddress) +IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 command_address) { - u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C); - if (Parameter != IOCTL_STM_EVENTHOOK) + u32 parameter = Memory::Read_U32(command_address + 0x0C); + if (parameter != IOCTL_STM_EVENTHOOK) { ERROR_LOG(WII_IPC_STM, "Bad IOCtl in CWII_IPC_HLE_Device_stm_eventhook"); - Memory::Write_U32(FS_EINVAL, _CommandAddress + 4); + Memory::Write_U32(FS_EINVAL, command_address + 4); return GetDefaultReply(); } // IOCTL_STM_EVENTHOOK waits until the reset button or power button // is pressed. - m_EventHookAddress = _CommandAddress; + m_event_hook_address = command_address; return GetNoReply(); } void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() { - if (!m_Active || m_EventHookAddress == 0) + if (!m_Active || m_event_hook_address == 0) { // If the device isn't open, ignore the button press. return; } // The reset button returns STM_EVENT_RESET. - u32 BufferOut = Memory::Read_U32(m_EventHookAddress + 0x18); - Memory::Write_U32(STM_EVENT_RESET, BufferOut); + u32 buffer_out = Memory::Read_U32(m_event_hook_address + 0x18); + Memory::Write_U32(STM_EVENT_RESET, buffer_out); // Fill in command buffer. - Memory::Write_U32(FS_SUCCESS, m_EventHookAddress + 4); - Memory::Write_U32(IPC_REP_ASYNC, m_EventHookAddress); - Memory::Write_U32(IPC_CMD_IOCTL, m_EventHookAddress + 8); + Memory::Write_U32(FS_SUCCESS, m_event_hook_address + 4); + Memory::Write_U32(IPC_REP_ASYNC, m_event_hook_address); + Memory::Write_U32(IPC_CMD_IOCTL, m_event_hook_address + 8); // Generate a reply to the IPC command. - WII_IPC_HLE_Interface::EnqueueReply(m_EventHookAddress); + WII_IPC_HLE_Interface::EnqueueReply(m_event_hook_address); } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h index 10f5ed6000..a305e2d0f0 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h @@ -31,36 +31,36 @@ enum }; // The /dev/stm/immediate -class CWII_IPC_HLE_Device_stm_immediate : public IWII_IPC_HLE_Device +class CWII_IPC_HLE_Device_stm_immediate final : public IWII_IPC_HLE_Device { public: - CWII_IPC_HLE_Device_stm_immediate(u32 _DeviceID, const std::string& _rDeviceName) - : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) + CWII_IPC_HLE_Device_stm_immediate(u32 device_id, const std::string& device_name) + : IWII_IPC_HLE_Device(device_id, device_name) { } ~CWII_IPC_HLE_Device_stm_immediate() override = default; - IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override; - IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override; - IPCCommandResult IOCtl(u32 _CommandAddress) override; + IPCCommandResult Open(u32 command_address, u32 mode) override; + IPCCommandResult Close(u32 command_address, bool force) override; + IPCCommandResult IOCtl(u32 command_address) override; }; // The /dev/stm/eventhook -class CWII_IPC_HLE_Device_stm_eventhook : public IWII_IPC_HLE_Device +class CWII_IPC_HLE_Device_stm_eventhook final : public IWII_IPC_HLE_Device { public: - CWII_IPC_HLE_Device_stm_eventhook(u32 _DeviceID, const std::string& _rDeviceName) - : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName), m_EventHookAddress(0) + CWII_IPC_HLE_Device_stm_eventhook(u32 device_id, const std::string& device_name) + : IWII_IPC_HLE_Device(device_id, device_name) { } ~CWII_IPC_HLE_Device_stm_eventhook() override = default; - IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override; - IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override; - IPCCommandResult IOCtl(u32 _CommandAddress) override; + IPCCommandResult Open(u32 command_address, u32 mode) override; + IPCCommandResult Close(u32 command_address, bool force) override; + IPCCommandResult IOCtl(u32 command_address) override; void ResetButton(); // STATE_TO_SAVE - u32 m_EventHookAddress; + u32 m_event_hook_address = 0; }; From fcd08be34a47e103bcf1b87f2e12d2092099cb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 18 Sep 2016 23:46:06 +0200 Subject: [PATCH 3/7] IPC_HLE/stm: const correctness for ResetButton --- Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp | 2 +- Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp index 42c6dddae2..0c1dd43d13 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp @@ -112,7 +112,7 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 command_address) return GetNoReply(); } -void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() +void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const { if (!m_Active || m_event_hook_address == 0) { diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h index a305e2d0f0..fa9153c25e 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h @@ -59,7 +59,7 @@ public: IPCCommandResult Close(u32 command_address, bool force) override; IPCCommandResult IOCtl(u32 command_address) override; - void ResetButton(); + void ResetButton() const; // STATE_TO_SAVE u32 m_event_hook_address = 0; From ae723f5251402283ea8e32bb932e0d62659b85dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Tue, 20 Sep 2016 19:33:08 +0200 Subject: [PATCH 4/7] IPC_HLE/stm: Implement STM_UnregisterStateEvent --- .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp | 32 +++++++++++++------ .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.h | 3 -- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp index 0c1dd43d13..38612a4929 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp @@ -4,6 +4,8 @@ #include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h" +static u32 s_event_hook_address = 0; + IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Open(u32 command_address, u32 mode) { INFO_LOG(WII_IPC_STM, "STM immediate: Open"); @@ -37,8 +39,17 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address) switch (parameter) { case IOCTL_STM_RELEASE_EH: - INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str()); - INFO_LOG(WII_IPC_STM, " IOCTL_STM_RELEASE_EH"); + if (s_event_hook_address == 0) + { + return_value = FS_ENOENT; + break; + } + Memory::Write_U32(0, Memory::Read_U32(s_event_hook_address + 0x18)); + Memory::Write_U32(FS_SUCCESS, s_event_hook_address + 4); + Memory::Write_U32(IPC_REP_ASYNC, s_event_hook_address); + Memory::Write_U32(IPC_CMD_IOCTL, s_event_hook_address + 8); + WII_IPC_HLE_Interface::EnqueueReply(s_event_hook_address); + s_event_hook_address = 0; break; case IOCTL_STM_HOTRESET: @@ -87,7 +98,7 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Open(u32 command_address, u3 IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Close(u32 command_address, bool force) { - m_event_hook_address = 0; + s_event_hook_address = 0; INFO_LOG(WII_IPC_STM, "STM eventhook: Close"); if (!force) @@ -108,27 +119,28 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 command_address) // IOCTL_STM_EVENTHOOK waits until the reset button or power button // is pressed. - m_event_hook_address = command_address; + s_event_hook_address = command_address; return GetNoReply(); } void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const { - if (!m_Active || m_event_hook_address == 0) + if (!m_Active || s_event_hook_address == 0) { // If the device isn't open, ignore the button press. return; } // The reset button returns STM_EVENT_RESET. - u32 buffer_out = Memory::Read_U32(m_event_hook_address + 0x18); + u32 buffer_out = Memory::Read_U32(s_event_hook_address + 0x18); Memory::Write_U32(STM_EVENT_RESET, buffer_out); // Fill in command buffer. - Memory::Write_U32(FS_SUCCESS, m_event_hook_address + 4); - Memory::Write_U32(IPC_REP_ASYNC, m_event_hook_address); - Memory::Write_U32(IPC_CMD_IOCTL, m_event_hook_address + 8); + Memory::Write_U32(FS_SUCCESS, s_event_hook_address + 4); + Memory::Write_U32(IPC_REP_ASYNC, s_event_hook_address); + Memory::Write_U32(IPC_CMD_IOCTL, s_event_hook_address + 8); // Generate a reply to the IPC command. - WII_IPC_HLE_Interface::EnqueueReply(m_event_hook_address); + WII_IPC_HLE_Interface::EnqueueReply(s_event_hook_address); + s_event_hook_address = 0; } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h index fa9153c25e..a84837bb29 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h @@ -60,7 +60,4 @@ public: IPCCommandResult IOCtl(u32 command_address) override; void ResetButton() const; - - // STATE_TO_SAVE - u32 m_event_hook_address = 0; }; From 9b72b5f144da14be215554efd2938097086becc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 19 Sep 2016 00:49:15 +0200 Subject: [PATCH 5/7] Shut down Wii software gracefully This adds support for triggering the power event (in the STM), so that stopping emulation first triggers a shutdown event, which notably gives emulated software time to save game data (issue 8979) and clean up SYSCONF (to disconnect Wiimotes and update their state in the SYSCONF). On the first press, the stop button/hotkey/whatever will trigger a STM power event. On a second try, we will forcefully stop emulation, just like how it was working before. --- Source/Core/Core/HW/ProcessorInterface.cpp | 21 +++++++++++++++ Source/Core/Core/HW/ProcessorInterface.h | 1 + .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp | 27 +++++++++++++++++-- .../Core/IPC_HLE/WII_IPC_HLE_Device_stm.h | 4 +++ Source/Core/DolphinWX/Frame.h | 1 + Source/Core/DolphinWX/FrameTools.cpp | 20 +++++++++++--- 6 files changed, 69 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp index 04fec4cd07..a24f5529b6 100644 --- a/Source/Core/Core/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/HW/ProcessorInterface.cpp @@ -37,6 +37,9 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate); static CoreTiming::EventType* iosNotifyResetButton; static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate); +static CoreTiming::EventType* iosNotifyPowerButton; +static void IOSNotifyPowerButtonCallback(u64 userdata, s64 cyclesLate); + // Let the PPC know that an external exception is set/cleared void UpdateException(); @@ -75,6 +78,8 @@ void Init() toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", ToggleResetButtonCallback); iosNotifyResetButton = CoreTiming::RegisterEvent("IOSNotifyResetButton", IOSNotifyResetButtonCallback); + iosNotifyPowerButton = + CoreTiming::RegisterEvent("IOSNotifyPowerButton", IOSNotifyPowerButtonCallback); } void RegisterMMIO(MMIO::Mapping* mmio, u32 base) @@ -214,6 +219,17 @@ static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate) } } +static void IOSNotifyPowerButtonCallback(u64 userdata, s64 cyclesLate) +{ + if (SConfig::GetInstance().bWii) + { + std::shared_ptr stm = + WII_IPC_HLE_Interface::GetDeviceByName("/dev/stm/eventhook"); + if (stm) + std::static_pointer_cast(stm)->PowerButton(); + } +} + void ResetButton_Tap() { CoreTiming::ScheduleEvent(0, toggleResetButton, true, CoreTiming::FromThread::ANY); @@ -222,4 +238,9 @@ void ResetButton_Tap() CoreTiming::FromThread::ANY); } +void PowerButton_Tap() +{ + CoreTiming::ScheduleEvent(0, iosNotifyPowerButton, 0, CoreTiming::FromThread::ANY); +} + } // namespace ProcessorInterface diff --git a/Source/Core/Core/HW/ProcessorInterface.h b/Source/Core/Core/HW/ProcessorInterface.h index 5b9310e9fb..3f42105358 100644 --- a/Source/Core/Core/HW/ProcessorInterface.h +++ b/Source/Core/Core/HW/ProcessorInterface.h @@ -76,5 +76,6 @@ void SetInterrupt(u32 _causemask, bool _bSet = true); // Thread-safe func which sets and clears reset button state automagically void ResetButton_Tap(); +void PowerButton_Tap(); } // namespace ProcessorInterface diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp index 38612a4929..0bd3f8f257 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp @@ -4,6 +4,12 @@ #include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h" +namespace Core +{ +void QueueHostJob(std::function job, bool run_during_stop); +void Stop(); +} + static u32 s_event_hook_address = 0; IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Open(u32 command_address, u32 mode) @@ -38,6 +44,12 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address) switch (parameter) { + case IOCTL_STM_IDLE: + case IOCTL_STM_SHUTDOWN: + NOTICE_LOG(WII_IPC_STM, "IOCTL_STM_IDLE or IOCTL_STM_SHUTDOWN received, shutting down"); + Core::QueueHostJob(&Core::Stop, false); + break; + case IOCTL_STM_RELEASE_EH: if (s_event_hook_address == 0) { @@ -123,7 +135,7 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 command_address) return GetNoReply(); } -void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const +void CWII_IPC_HLE_Device_stm_eventhook::TriggerEvent(const u32 event) const { if (!m_Active || s_event_hook_address == 0) { @@ -133,7 +145,7 @@ void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const // The reset button returns STM_EVENT_RESET. u32 buffer_out = Memory::Read_U32(s_event_hook_address + 0x18); - Memory::Write_U32(STM_EVENT_RESET, buffer_out); + Memory::Write_U32(event, buffer_out); // Fill in command buffer. Memory::Write_U32(FS_SUCCESS, s_event_hook_address + 4); @@ -144,3 +156,14 @@ void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const WII_IPC_HLE_Interface::EnqueueReply(s_event_hook_address); s_event_hook_address = 0; } + +void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const +{ + // The reset button returns STM_EVENT_RESET. + TriggerEvent(STM_EVENT_RESET); +} + +void CWII_IPC_HLE_Device_stm_eventhook::PowerButton() const +{ + TriggerEvent(STM_EVENT_POWER); +} diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h index a84837bb29..56adc6a929 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.h @@ -60,4 +60,8 @@ public: IPCCommandResult IOCtl(u32 command_address) override; void ResetButton() const; + void PowerButton() const; + +private: + void TriggerEvent(u32 event) const; }; diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 43a5a3745a..1e7c5eec0a 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -158,6 +158,7 @@ private: bool m_bGameLoading = false; bool m_bClosing = false; bool m_confirmStop = false; + bool m_tried_graceful_shutdown = false; int m_saveSlot = 1; std::vector drives; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 2b690c0e5a..e20cc15411 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -1155,9 +1155,12 @@ void CFrame::DoStop() Core::SetState(Core::CORE_PAUSE); } - wxMessageDialog m_StopDlg(this, _("Do you want to stop the current emulation?"), - _("Please confirm..."), - wxYES_NO | wxSTAY_ON_TOP | wxICON_EXCLAMATION, wxDefaultPosition); + wxMessageDialog m_StopDlg( + this, !m_tried_graceful_shutdown ? _("Do you want to stop the current emulation?") : + _("A shutdown is already in progress. Unsaved data " + "may be lost if you stop the current emulation " + "before it completes. Force stop?"), + _("Please confirm..."), wxYES_NO | wxSTAY_ON_TOP | wxICON_EXCLAMATION, wxDefaultPosition); HotkeyManagerEmu::Enable(false); int Ret = m_StopDlg.ShowModal(); @@ -1172,6 +1175,16 @@ void CFrame::DoStop() } } + if (SConfig::GetInstance().bWii && !m_tried_graceful_shutdown) + { + Core::DisplayMessage("Shutting down", 30000); + Core::SetState(Core::CORE_RUN); + ProcessorInterface::PowerButton_Tap(); + m_confirmStop = false; + m_tried_graceful_shutdown = true; + return; + } + if (UseDebugger && g_pCodeWindow) { if (g_pCodeWindow->m_WatchWindow) @@ -1207,6 +1220,7 @@ void CFrame::DoStop() void CFrame::OnStopped() { m_confirmStop = false; + m_tried_graceful_shutdown = false; #if defined(HAVE_X11) && HAVE_X11 if (SConfig::GetInstance().bDisableScreenSaver) From 5d8d696185358e8c65fd16acc935ad1b54f1188d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 25 Sep 2016 13:45:07 +0200 Subject: [PATCH 6/7] Force disable WC24 standby mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When standby mode is enabled, this causes games to ES_Launch the system menu instead of directly asking IOS (the STM more precisely) to shut down, which prevents graceful shutdown from working (it'll appear to hang). Dolphin never supported WC24 standby mode anyway, so this shouldn't cause any issues. (This should be reverted if and when WC24 standby is implemented…) --- Source/Core/Common/SysConf.cpp | 2 +- Source/Core/Core/BootManager.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/SysConf.cpp b/Source/Core/Common/SysConf.cpp index 980318c06b..6bf6d950ea 100644 --- a/Source/Core/Common/SysConf.cpp +++ b/Source/Core/Common/SysConf.cpp @@ -310,7 +310,7 @@ void SysConf::GenerateSysConf() // IPL.IDL current_offset += create_item(items[23], Type_SmallArray, "IPL.IDL", 1, current_offset); - items[23].data[0] = 0x01; + items[23].data[0] = 0x00; // IPL.EULA current_offset += create_item(items[24], Type_Bool, "IPL.EULA", 1, current_offset); diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index f7651b5bce..6370bbf9d1 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -392,6 +392,15 @@ bool BootCore(const std::string& _rFilename) SConfig::GetInstance().m_SYSCONF->SetData("IPL.PGS", StartUp.bProgressive); SConfig::GetInstance().m_SYSCONF->SetData("IPL.E60", StartUp.bPAL60); + if (StartUp.bWii) + { + // Disable WiiConnect24's standby mode. If it is enabled, it prevents us from receiving + // shutdown commands in the State Transition Manager (STM). + // TODO: remove this if and once Dolphin supports WC24 standby mode. + SConfig::GetInstance().m_SYSCONF->SetData("IPL.IDL", 0x00); + NOTICE_LOG(BOOT, "Disabling WC24 'standby' (shutdown to idle) to avoid hanging on shutdown"); + } + // Run the game // Init the core if (!Core::Init()) From 453c4a4915883de9b35b6207dbb046caea7c3bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 1 Oct 2016 21:35:29 +0200 Subject: [PATCH 7/7] MainNoGUI: Shut down Wii software gracefully --- Source/Core/DolphinWX/MainNoGUI.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index 1d06ff559a..c954539e79 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -34,6 +34,8 @@ static bool rendererHasFocus = true; static bool rendererIsFullscreen = false; static Common::Flag s_running{true}; +static Common::Flag s_shutdown_requested{false}; +static Common::Flag s_tried_graceful_shutdown{false}; static void signal_handler(int) { @@ -41,7 +43,12 @@ static void signal_handler(int) if (write(STDERR_FILENO, message, sizeof(message)) < 0) { } - s_running.Clear(); + s_shutdown_requested.Set(); +} + +namespace ProcessorInterface +{ +void PowerButton_Tap(); } class Platform @@ -222,6 +229,19 @@ class PlatformX11 : public Platform // The actual loop while (s_running.IsSet()) { + if (s_shutdown_requested.TestAndClear()) + { + if (!s_tried_graceful_shutdown.IsSet() && SConfig::GetInstance().bWii) + { + ProcessorInterface::PowerButton_Tap(); + s_tried_graceful_shutdown.Set(); + } + else + { + s_running.Clear(); + } + } + XEvent event; KeySym key; for (int num_events = XPending(dpy); num_events > 0; num_events--) @@ -286,7 +306,7 @@ class PlatformX11 : public Platform break; case ClientMessage: if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False)) - s_running.Clear(); + s_shutdown_requested.Set(); break; } } @@ -375,6 +395,7 @@ int main(int argc, char* argv[]) UICommon::SetUserDirectory(""); // Auto-detect user folder UICommon::Init(); + Core::SetOnStoppedCallback([]() { s_running.Clear(); }); platform->Init(); // Shut down cleanly on SIGINT and SIGTERM