Skip to content

Commit

Permalink
Merge pull request #4244 from leoetlino/stm-shutdown
Browse files Browse the repository at this point in the history
Shut down Wii software gracefully
  • Loading branch information
shuffle2 committed Oct 3, 2016
2 parents 8fcc3b0 + 453c4a4 commit 5e8bc4a
Show file tree
Hide file tree
Showing 12 changed files with 268 additions and 146 deletions.
2 changes: 1 addition & 1 deletion Source/Core/Common/SysConf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,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);
Expand Down
9 changes: 9 additions & 0 deletions Source/Core/Core/BootManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
</ClCompile>
<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_stm.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_kbd.cpp" />
Expand Down Expand Up @@ -386,8 +387,8 @@
<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_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_sdio_slot0.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_ven.h" />
Expand Down Expand Up @@ -480,4 +481,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
5 changes: 4 additions & 1 deletion Source/Core/Core/Core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\SDIO - SD Card</Filter>
</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">
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
</ClCompile>
Expand Down Expand Up @@ -1247,4 +1250,4 @@
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>
21 changes: 21 additions & 0 deletions Source/Core/Core/HW/ProcessorInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
{
CoreTiming::ScheduleEvent(0, toggleResetButton, true, CoreTiming::FromThread::ANY);
Expand All @@ -222,4 +238,9 @@ void ResetButton_Tap()
CoreTiming::FromThread::ANY);
}

void PowerButton_Tap()
{
CoreTiming::ScheduleEvent(0, iosNotifyPowerButton, 0, CoreTiming::FromThread::ANY);
}

} // namespace ProcessorInterface
1 change: 1 addition & 0 deletions Source/Core/Core/HW/ProcessorInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
169 changes: 169 additions & 0 deletions Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_stm.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
Loading

0 comments on commit 5e8bc4a

Please sign in to comment.