Merge pull request #4244 from leoetlino/stm-shutdown
Shut down Wii software gracefully
This commit is contained in:
commit
5e8bc4aa1d
|
@ -314,7 +314,7 @@ void SysConf::GenerateSysConf()
|
||||||
|
|
||||||
// IPL.IDL
|
// IPL.IDL
|
||||||
current_offset += create_item(items[23], Type_SmallArray, "IPL.IDL", 1, current_offset);
|
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
|
// IPL.EULA
|
||||||
current_offset += create_item(items[24], Type_Bool, "IPL.EULA", 1, current_offset);
|
current_offset += create_item(items[24], Type_Bool, "IPL.EULA", 1, current_offset);
|
||||||
|
|
|
@ -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.PGS", StartUp.bProgressive);
|
||||||
SConfig::GetInstance().m_SYSCONF->SetData("IPL.E60", StartUp.bPAL60);
|
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
|
// Run the game
|
||||||
// Init the core
|
// Init the core
|
||||||
if (!Core::Init())
|
if (!Core::Init())
|
||||||
|
|
|
@ -143,6 +143,7 @@ set(SRCS ActionReplay.cpp
|
||||||
IPC_HLE/WII_Socket.cpp
|
IPC_HLE/WII_Socket.cpp
|
||||||
IPC_HLE/WII_IPC_HLE_Device_net.cpp
|
IPC_HLE/WII_IPC_HLE_Device_net.cpp
|
||||||
IPC_HLE/WII_IPC_HLE_Device_net_ssl.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_sdio_slot0.cpp
|
||||||
IPC_HLE/WII_IPC_HLE_Device_usb.cpp
|
IPC_HLE/WII_IPC_HLE_Device_usb.cpp
|
||||||
IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp
|
IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp
|
||||||
|
|
|
@ -183,6 +183,7 @@
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_net.cpp" />
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_net.cpp" />
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_net_ssl.cpp" />
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_net_ssl.cpp" />
|
||||||
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_stm.cpp" />
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.cpp" />
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.cpp" />
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb.cpp" />
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb.cpp" />
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_kbd.cpp" />
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_kbd.cpp" />
|
||||||
|
@ -386,8 +387,8 @@
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_hid.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_hid.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_net.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_net.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_net_ssl.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_net_ssl.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.h" />
|
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_stm.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_stm.h" />
|
||||||
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_kbd.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_kbd.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.h" />
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.h" />
|
||||||
|
@ -480,4 +481,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -585,6 +585,9 @@
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.cpp">
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.cpp">
|
||||||
<Filter>IPC HLE %28IOS/Starlet%29\SDIO - SD Card</Filter>
|
<Filter>IPC HLE %28IOS/Starlet%29\SDIO - SD Card</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_stm.cpp">
|
||||||
|
<Filter>IPC HLE %28IOS/Starlet%29</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_hid.cpp">
|
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_hid.cpp">
|
||||||
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
|
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -1247,4 +1250,4 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="CMakeLists.txt" />
|
<Text Include="CMakeLists.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -37,6 +37,9 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate);
|
||||||
static CoreTiming::EventType* iosNotifyResetButton;
|
static CoreTiming::EventType* iosNotifyResetButton;
|
||||||
static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate);
|
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
|
// Let the PPC know that an external exception is set/cleared
|
||||||
void UpdateException();
|
void UpdateException();
|
||||||
|
|
||||||
|
@ -75,6 +78,8 @@ void Init()
|
||||||
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", ToggleResetButtonCallback);
|
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", ToggleResetButtonCallback);
|
||||||
iosNotifyResetButton =
|
iosNotifyResetButton =
|
||||||
CoreTiming::RegisterEvent("IOSNotifyResetButton", IOSNotifyResetButtonCallback);
|
CoreTiming::RegisterEvent("IOSNotifyResetButton", IOSNotifyResetButtonCallback);
|
||||||
|
iosNotifyPowerButton =
|
||||||
|
CoreTiming::RegisterEvent("IOSNotifyPowerButton", IOSNotifyPowerButtonCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
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<IWII_IPC_HLE_Device> stm =
|
||||||
|
WII_IPC_HLE_Interface::GetDeviceByName("/dev/stm/eventhook");
|
||||||
|
if (stm)
|
||||||
|
std::static_pointer_cast<CWII_IPC_HLE_Device_stm_eventhook>(stm)->PowerButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ResetButton_Tap()
|
void ResetButton_Tap()
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent(0, toggleResetButton, true, CoreTiming::FromThread::ANY);
|
CoreTiming::ScheduleEvent(0, toggleResetButton, true, CoreTiming::FromThread::ANY);
|
||||||
|
@ -222,4 +238,9 @@ void ResetButton_Tap()
|
||||||
CoreTiming::FromThread::ANY);
|
CoreTiming::FromThread::ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PowerButton_Tap()
|
||||||
|
{
|
||||||
|
CoreTiming::ScheduleEvent(0, iosNotifyPowerButton, 0, CoreTiming::FromThread::ANY);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ProcessorInterface
|
} // namespace ProcessorInterface
|
||||||
|
|
|
@ -76,5 +76,6 @@ void SetInterrupt(u32 _causemask, bool _bSet = true);
|
||||||
|
|
||||||
// Thread-safe func which sets and clears reset button state automagically
|
// Thread-safe func which sets and clears reset button state automagically
|
||||||
void ResetButton_Tap();
|
void ResetButton_Tap();
|
||||||
|
void PowerButton_Tap();
|
||||||
|
|
||||||
} // namespace ProcessorInterface
|
} // namespace ProcessorInterface
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
void QueueHostJob(std::function<void()> 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)
|
||||||
|
{
|
||||||
|
INFO_LOG(WII_IPC_STM, "STM immediate: Open");
|
||||||
|
Memory::Write_U32(GetDeviceID(), command_address + 4);
|
||||||
|
m_Active = true;
|
||||||
|
return GetDefaultReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::Close(u32 command_address, bool force)
|
||||||
|
{
|
||||||
|
INFO_LOG(WII_IPC_STM, "STM immediate: Close");
|
||||||
|
if (!force)
|
||||||
|
Memory::Write_U32(0, command_address + 4);
|
||||||
|
m_Active = false;
|
||||||
|
return GetDefaultReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address)
|
||||||
|
{
|
||||||
|
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(buffer_out, 0, buffer_out_size);
|
||||||
|
u32 return_value = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
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(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)
|
||||||
|
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", 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(return_value, command_address + 0x4);
|
||||||
|
return GetDefaultReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Open(u32 command_address, u32 mode)
|
||||||
|
{
|
||||||
|
Memory::Write_U32(GetDeviceID(), command_address + 4);
|
||||||
|
m_Active = true;
|
||||||
|
return GetDefaultReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Close(u32 command_address, bool force)
|
||||||
|
{
|
||||||
|
s_event_hook_address = 0;
|
||||||
|
|
||||||
|
INFO_LOG(WII_IPC_STM, "STM eventhook: Close");
|
||||||
|
if (!force)
|
||||||
|
Memory::Write_U32(0, command_address + 4);
|
||||||
|
m_Active = false;
|
||||||
|
return GetDefaultReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 command_address)
|
||||||
|
{
|
||||||
|
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, command_address + 4);
|
||||||
|
return GetDefaultReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
// IOCTL_STM_EVENTHOOK waits until the reset button or power button
|
||||||
|
// is pressed.
|
||||||
|
s_event_hook_address = command_address;
|
||||||
|
return GetNoReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWII_IPC_HLE_Device_stm_eventhook::TriggerEvent(const u32 event) const
|
||||||
|
{
|
||||||
|
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(s_event_hook_address + 0x18);
|
||||||
|
Memory::Write_U32(event, buffer_out);
|
||||||
|
|
||||||
|
// Fill in command buffer.
|
||||||
|
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(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);
|
||||||
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -32,155 +31,37 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
// The /dev/stm/immediate
|
// 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:
|
public:
|
||||||
CWII_IPC_HLE_Device_stm_immediate(u32 _DeviceID, const std::string& _rDeviceName)
|
CWII_IPC_HLE_Device_stm_immediate(u32 device_id, const std::string& device_name)
|
||||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
: IWII_IPC_HLE_Device(device_id, device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_stm_immediate() {}
|
~CWII_IPC_HLE_Device_stm_immediate() override = default;
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override
|
IPCCommandResult Open(u32 command_address, u32 mode) override;
|
||||||
{
|
IPCCommandResult Close(u32 command_address, bool force) override;
|
||||||
INFO_LOG(WII_IPC_STM, "STM immediate: Open");
|
IPCCommandResult IOCtl(u32 command_address) override;
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The /dev/stm/eventhook
|
// 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:
|
public:
|
||||||
CWII_IPC_HLE_Device_stm_eventhook(u32 _DeviceID, const std::string& _rDeviceName)
|
CWII_IPC_HLE_Device_stm_eventhook(u32 device_id, const std::string& device_name)
|
||||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName), m_EventHookAddress(0)
|
: IWII_IPC_HLE_Device(device_id, device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_stm_eventhook() {}
|
~CWII_IPC_HLE_Device_stm_eventhook() override = default;
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override
|
IPCCommandResult Open(u32 command_address, u32 mode) override;
|
||||||
{
|
IPCCommandResult Close(u32 command_address, bool force) override;
|
||||||
Memory::Write_U32(GetDeviceID(), _CommandAddress + 4);
|
IPCCommandResult IOCtl(u32 command_address) override;
|
||||||
m_Active = true;
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override
|
void ResetButton() const;
|
||||||
{
|
void PowerButton() const;
|
||||||
m_EventHookAddress = 0;
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_STM, "STM eventhook: Close");
|
private:
|
||||||
if (!_bForce)
|
void TriggerEvent(u32 event) const;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
|
||||||
u32 m_EventHookAddress;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,6 +158,7 @@ private:
|
||||||
bool m_bGameLoading = false;
|
bool m_bGameLoading = false;
|
||||||
bool m_bClosing = false;
|
bool m_bClosing = false;
|
||||||
bool m_confirmStop = false;
|
bool m_confirmStop = false;
|
||||||
|
bool m_tried_graceful_shutdown = false;
|
||||||
int m_saveSlot = 1;
|
int m_saveSlot = 1;
|
||||||
|
|
||||||
std::vector<std::string> drives;
|
std::vector<std::string> drives;
|
||||||
|
|
|
@ -1148,9 +1148,12 @@ void CFrame::DoStop()
|
||||||
Core::SetState(Core::CORE_PAUSE);
|
Core::SetState(Core::CORE_PAUSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMessageDialog m_StopDlg(this, _("Do you want to stop the current emulation?"),
|
wxMessageDialog m_StopDlg(
|
||||||
_("Please confirm..."),
|
this, !m_tried_graceful_shutdown ? _("Do you want to stop the current emulation?") :
|
||||||
wxYES_NO | wxSTAY_ON_TOP | wxICON_EXCLAMATION, wxDefaultPosition);
|
_("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);
|
HotkeyManagerEmu::Enable(false);
|
||||||
int Ret = m_StopDlg.ShowModal();
|
int Ret = m_StopDlg.ShowModal();
|
||||||
|
@ -1165,6 +1168,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 (UseDebugger && g_pCodeWindow)
|
||||||
{
|
{
|
||||||
if (g_pCodeWindow->m_WatchWindow)
|
if (g_pCodeWindow->m_WatchWindow)
|
||||||
|
@ -1200,6 +1213,7 @@ void CFrame::DoStop()
|
||||||
void CFrame::OnStopped()
|
void CFrame::OnStopped()
|
||||||
{
|
{
|
||||||
m_confirmStop = false;
|
m_confirmStop = false;
|
||||||
|
m_tried_graceful_shutdown = false;
|
||||||
|
|
||||||
#if defined(HAVE_X11) && HAVE_X11
|
#if defined(HAVE_X11) && HAVE_X11
|
||||||
if (SConfig::GetInstance().bDisableScreenSaver)
|
if (SConfig::GetInstance().bDisableScreenSaver)
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
static bool rendererHasFocus = true;
|
static bool rendererHasFocus = true;
|
||||||
static bool rendererIsFullscreen = false;
|
static bool rendererIsFullscreen = false;
|
||||||
static Common::Flag s_running{true};
|
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)
|
static void signal_handler(int)
|
||||||
{
|
{
|
||||||
|
@ -41,7 +43,12 @@ static void signal_handler(int)
|
||||||
if (write(STDERR_FILENO, message, sizeof(message)) < 0)
|
if (write(STDERR_FILENO, message, sizeof(message)) < 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
s_running.Clear();
|
s_shutdown_requested.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ProcessorInterface
|
||||||
|
{
|
||||||
|
void PowerButton_Tap();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Platform
|
class Platform
|
||||||
|
@ -222,6 +229,19 @@ class PlatformX11 : public Platform
|
||||||
// The actual loop
|
// The actual loop
|
||||||
while (s_running.IsSet())
|
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;
|
XEvent event;
|
||||||
KeySym key;
|
KeySym key;
|
||||||
for (int num_events = XPending(dpy); num_events > 0; num_events--)
|
for (int num_events = XPending(dpy); num_events > 0; num_events--)
|
||||||
|
@ -286,7 +306,7 @@ class PlatformX11 : public Platform
|
||||||
break;
|
break;
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
|
if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
|
||||||
s_running.Clear();
|
s_shutdown_requested.Set();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,6 +395,7 @@ int main(int argc, char* argv[])
|
||||||
UICommon::SetUserDirectory(""); // Auto-detect user folder
|
UICommon::SetUserDirectory(""); // Auto-detect user folder
|
||||||
UICommon::Init();
|
UICommon::Init();
|
||||||
|
|
||||||
|
Core::SetOnStoppedCallback([]() { s_running.Clear(); });
|
||||||
platform->Init();
|
platform->Init();
|
||||||
|
|
||||||
// Shut down cleanly on SIGINT and SIGTERM
|
// Shut down cleanly on SIGINT and SIGTERM
|
||||||
|
|
Loading…
Reference in New Issue