Make reset button (Emulation -> Reset) work correctly for Wii games.
Fixes issue 8328. As far as I know, this works the same way as console. Games will generally react to the reset button the same way as Home->Reset, so this is only marginally useful, but possibly nice to have in certain situations. Note that if you try to use Reset, and you're running a WAD which isn't installed, it will likely crash because WADs respond to the reset button by launching themselves with ES_LAUNCH. It might be a good idea to add some sort of hack to make this work as expected. It would be easy to extend this to support the power button, but it's unclear how exactly that should be exposed in the UI. See also issue 8979. Needs to be rebased once PR #3811 is merged.
This commit is contained in:
parent
10682dbf58
commit
e01a33f69b
|
@ -10,6 +10,8 @@
|
|||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HW/MMIO.h"
|
||||
#include "Core/HW/ProcessorInterface.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
namespace ProcessorInterface
|
||||
|
@ -31,6 +33,9 @@ static u32 m_Unknown;
|
|||
static int toggleResetButton;
|
||||
static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate);
|
||||
|
||||
static int iosNotifyResetButton;
|
||||
static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate);
|
||||
|
||||
// Let the PPC know that an external exception is set/cleared
|
||||
void UpdateException();
|
||||
|
||||
|
@ -67,6 +72,8 @@ void Init()
|
|||
m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
|
||||
|
||||
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", ToggleResetButtonCallback);
|
||||
iosNotifyResetButton =
|
||||
CoreTiming::RegisterEvent("IOSNotifyResetButton", IOSNotifyResetButtonCallback);
|
||||
}
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
|
@ -195,9 +202,21 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate)
|
|||
SetResetButton(!!userdata);
|
||||
}
|
||||
|
||||
static void IOSNotifyResetButtonCallback(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)->ResetButton();
|
||||
}
|
||||
}
|
||||
|
||||
void ResetButton_Tap()
|
||||
{
|
||||
CoreTiming::ScheduleEvent_AnyThread(0, toggleResetButton, true);
|
||||
CoreTiming::ScheduleEvent_AnyThread(0, iosNotifyResetButton, 0);
|
||||
CoreTiming::ScheduleEvent_AnyThread(243000000, toggleResetButton, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,12 @@ enum
|
|||
IOCTL_STM_READDDRREG2 = 0x4002,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
STM_EVENT_RESET = 0x00020000,
|
||||
STM_EVENT_POWER = 0x00000800
|
||||
};
|
||||
|
||||
// The /dev/stm/immediate
|
||||
class CWII_IPC_HLE_Device_stm_immediate : public IWII_IPC_HLE_Device
|
||||
{
|
||||
|
@ -141,42 +147,38 @@ public:
|
|||
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 zeros as a safety precaution
|
||||
// to avoid returning bad values
|
||||
Memory::Memset(BufferOut, 0, BufferOutSize);
|
||||
u32 ReturnValue = 0;
|
||||
|
||||
// write return value
|
||||
switch (Parameter)
|
||||
if (Parameter != IOCTL_STM_EVENTHOOK)
|
||||
{
|
||||
case IOCTL_STM_EVENTHOOK:
|
||||
{
|
||||
m_EventHookAddress = _CommandAddress;
|
||||
|
||||
INFO_LOG(WII_IPC_STM, "%s registers event hook:", GetDeviceName().c_str());
|
||||
DEBUG_LOG(WII_IPC_STM, "%x - IOCTL_STM_EVENTHOOK", Parameter);
|
||||
DEBUG_LOG(WII_IPC_STM, "BufferIn: 0x%08x", BufferIn);
|
||||
DEBUG_LOG(WII_IPC_STM, "BufferInSize: 0x%08x", BufferInSize);
|
||||
DEBUG_LOG(WII_IPC_STM, "BufferOut: 0x%08x", BufferOut);
|
||||
DEBUG_LOG(WII_IPC_STM, "BufferOutSize: 0x%08x", BufferOutSize);
|
||||
|
||||
DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_STM);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbg_assert_msg_(WII_IPC_STM, 0, "unknown %s ioctl %x", GetDeviceName().c_str(), Parameter);
|
||||
break;
|
||||
ERROR_LOG(WII_IPC_STM, "Bad IOCtl in CWII_IPC_HLE_Device_stm_eventhook");
|
||||
Memory::Write_U32(FS_EINVAL, _CommandAddress + 4);
|
||||
return GetDefaultReply();
|
||||
}
|
||||
|
||||
// Write return value to the IPC call, 0 means success
|
||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
||||
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_Immediate(m_EventHookAddress);
|
||||
}
|
||||
|
||||
// STATE_TO_SAVE
|
||||
|
|
Loading…
Reference in New Issue