static void SDIO_EventNotify_CPUThread(u64 userdata, s64 cycles_late) { auto device = static_cast<CWII_IPC_HLE_Device_sdio_slot0*>(GetDeviceByName("/dev/sdio/slot0").get()); if (device) device->EventNotify(); }
void SDIO_EventNotify() { CWII_IPC_HLE_Device_sdio_slot0 *pDevice = (CWII_IPC_HLE_Device_sdio_slot0*)GetDeviceByName("/dev/sdio/slot0"); if (pDevice) pDevice->EventNotify(); }
bool CTSProcessor::OpenFilter(LPCWSTR pszDevice, LPCWSTR pszName) { int Device = GetDeviceByName(pszDevice); if (Device < 0) return false; return OpenFilter(Device, pszName); }
void MainWindow::OnConnectWiiRemote(int id) { const auto ios = IOS::HLE::GetIOS(); if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) return; Core::RunAsCPUThread([&] { const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>( ios->GetDeviceByName("/dev/usb/oh1/57e/305")); const bool is_connected = bt && bt->AccessWiiMote(id | 0x100)->IsConnected(); Wiimote::Connect(id, !is_connected); }); }
void Host_ConnectWiimote(int wm_idx, bool connect) { Core::QueueHostJob([=] { const auto ios = IOS::HLE::GetIOS(); if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) return; bool was_unpaused = Core::PauseAndLock(true); const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>( ios->GetDeviceByName("/dev/usb/oh1/57e/305")); if (bt) bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); Host_UpdateMainFrame(); Core::PauseAndLock(false, was_unpaused); }); }
bool TriggerSTMPowerEvent() { const auto ios = IOS::HLE::GetIOS(); if (!ios) return false; const auto stm = ios->GetDeviceByName("/dev/stm/eventhook"); if (!stm || !std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled()) return false; Core::DisplayMessage("Shutting down", 30000); ProcessorInterface::PowerButton_Tap(); return true; }
void Connect(unsigned int index, bool connect) { if (SConfig::GetInstance().m_bt_passthrough_enabled || index >= MAX_BBMOTES) return; const auto ios = IOS::HLE::GetIOS(); if (!ios) return; const auto bluetooth = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>( ios->GetDeviceByName("/dev/usb/oh1/57e/305")); if (bluetooth) bluetooth->AccessWiiMote(index | 0x100)->Activate(connect); const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected"; Core::DisplayMessage(StringFromFormat(message, index + 1), 3000); }
void ControllersWindow::OnBluetoothPassthroughResetPressed() { const auto ios = IOS::HLE::GetIOS(); if (!ios) { ModalMessageBox::warning( this, tr("Warning"), tr("Saved Wii Remote pairings can only be reset when a Wii game is running.")); return; } auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); if (device != nullptr) { std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)->TriggerSyncButtonHeldEvent(); } }
void ControllersWindow::OnBluetoothPassthroughSyncPressed() { const auto ios = IOS::HLE::GetIOS(); if (!ios) { QMessageBox error(this); error.setIcon(QMessageBox::Warning); error.setText(tr("A sync can only be triggered when a Wii game is running.")); error.exec(); return; } auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); if (device != nullptr) { std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device) ->TriggerSyncButtonPressedEvent(); } }
void ExecuteCommand(u32 _Address) { bool CmdSuccess = false; IPCCommandType Command = static_cast<IPCCommandType>(Memory::Read_U32(_Address)); volatile s32 DeviceID = Memory::Read_U32(_Address + 8); IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr; INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", _Address, Command, DeviceID, pDevice); switch (Command) { case IPC_CMD_OPEN: { u32 Mode = Memory::Read_U32(_Address + 0x10); DeviceID = getFreeDeviceId(); std::string DeviceName = Memory::GetString(Memory::Read_U32(_Address + 0xC)); WARN_LOG(WII_IPC_HLE, "Trying to open %s as %d", DeviceName.c_str(), DeviceID); if (DeviceID >= 0) { if (DeviceName.find("/dev/es") == 0) { u32 j; for (j=0; j<ES_MAX_COUNT; j++) { if (!es_inuse[j]) { es_inuse[j] = true; g_FdMap[DeviceID] = es_handles[j]; CmdSuccess = es_handles[j]->Open(_Address, Mode); Memory::Write_U32(DeviceID, _Address+4); break; } } if (j == ES_MAX_COUNT) { Memory::Write_U32(FS_EESEXHAUSTED, _Address + 4); CmdSuccess = true; } } else if (DeviceName.find("/dev/") == 0) { pDevice = GetDeviceByName(DeviceName); if (pDevice) { g_FdMap[DeviceID] = pDevice; CmdSuccess = pDevice->Open(_Address, Mode); INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)", pDevice->GetDeviceName().c_str(), DeviceID, Mode); Memory::Write_U32(DeviceID, _Address+4); } else { WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str()); Memory::Write_U32(FS_ENOENT, _Address+4); CmdSuccess = true; } } else { pDevice = CreateFileIO(DeviceID, DeviceName); CmdSuccess = pDevice->Open(_Address, Mode); INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)", pDevice->GetDeviceName().c_str(), DeviceID, Mode); if (Memory::Read_U32(_Address + 4) == (u32)DeviceID) { g_FdMap[DeviceID] = pDevice; } else { delete pDevice; pDevice = nullptr; } } } else { Memory::Write_U32(FS_EFDEXHAUSTED, _Address + 4); CmdSuccess = true; } break; } case IPC_CMD_CLOSE: { if (pDevice) { CmdSuccess = pDevice->Close(_Address); for (u32 j=0; j<ES_MAX_COUNT; j++) { if (es_handles[j] == g_FdMap[DeviceID]) { es_inuse[j] = false; } } g_FdMap[DeviceID] = nullptr; // Don't delete hardware if (!pDevice->IsHardware()) { delete pDevice; pDevice = nullptr; } } else { Memory::Write_U32(FS_EINVAL, _Address + 4); CmdSuccess = true; } break; } case IPC_CMD_READ: { if (pDevice) { CmdSuccess = pDevice->Read(_Address); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); CmdSuccess = true; } break; } case IPC_CMD_WRITE: { if (pDevice) { CmdSuccess = pDevice->Write(_Address); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); CmdSuccess = true; } break; } case IPC_CMD_SEEK: { if (pDevice) { CmdSuccess = pDevice->Seek(_Address); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); CmdSuccess = true; } break; } case IPC_CMD_IOCTL: { if (pDevice) { CmdSuccess = pDevice->IOCtl(_Address); } break; } case IPC_CMD_IOCTLV: { if (pDevice) { CmdSuccess = pDevice->IOCtlV(_Address); } break; } default: { _dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address); break; } } if (CmdSuccess) { // The original hardware overwrites the command type with the async reply type. Memory::Write_U32(IPC_REP_ASYNC, _Address); // IOS also seems to write back the command that was responded to in the FD field. Memory::Write_U32(Command, _Address + 8); // Ensure replies happen in order, fairly ugly // Without this, tons of games fail now that DI commands have different reply delays int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0; if (!reply_delay) { int delay_us = 250; reply_delay = SystemTimers::GetTicksPerSecond() / 1000000 * delay_us; } const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks(); if (ticks_til_last_reply > 0) { reply_delay = (int)ticks_til_last_reply; } last_reply_time = CoreTiming::GetTicks() + reply_delay; // Generate a reply to the IPC command EnqueueReply(_Address, reply_delay); } }
void MainLoop() override { bool fullscreen = SConfig::GetInstance().bFullscreen; int last_window_width = SConfig::GetInstance().iRenderWindowWidth; int last_window_height = SConfig::GetInstance().iRenderWindowHeight; if (fullscreen) { rendererIsFullscreen = X11Utils::ToggleFullscreen(dpy, win); #if defined(HAVE_XRANDR) && HAVE_XRANDR XRRConfig->ToggleDisplayMode(True); #endif } // The actual loop while (s_running.IsSet()) { if (s_shutdown_requested.TestAndClear()) { const auto ios = IOS::HLE::GetIOS(); const auto stm = ios ? ios->GetDeviceByName("/dev/stm/eventhook") : nullptr; if (!s_tried_graceful_shutdown.IsSet() && stm && std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled()) { 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--) { XNextEvent(dpy, &event); switch (event.type) { case KeyPress: key = XLookupKeysym((XKeyEvent*)&event, 0); if (key == XK_Escape) { if (Core::GetState() == Core::State::Running) { if (SConfig::GetInstance().bHideCursor) XUndefineCursor(dpy, win); Core::SetState(Core::State::Paused); } else { if (SConfig::GetInstance().bHideCursor) XDefineCursor(dpy, win, blankCursor); Core::SetState(Core::State::Running); } } else if ((key == XK_Return) && (event.xkey.state & Mod1Mask)) { fullscreen = !fullscreen; X11Utils::ToggleFullscreen(dpy, win); #if defined(HAVE_XRANDR) && HAVE_XRANDR XRRConfig->ToggleDisplayMode(fullscreen); #endif } else if (key >= XK_F1 && key <= XK_F8) { int slot_number = key - XK_F1 + 1; if (event.xkey.state & ShiftMask) State::Save(slot_number); else State::Load(slot_number); } else if (key == XK_F9) Core::SaveScreenShot(); else if (key == XK_F11) State::LoadLastSaved(); else if (key == XK_F12) { if (event.xkey.state & ShiftMask) State::UndoLoadState(); else State::UndoSaveState(); } break; case FocusIn: rendererHasFocus = true; if (SConfig::GetInstance().bHideCursor && Core::GetState() != Core::State::Paused) XDefineCursor(dpy, win, blankCursor); break; case FocusOut: rendererHasFocus = false; if (SConfig::GetInstance().bHideCursor) XUndefineCursor(dpy, win); break; case ClientMessage: if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False)) s_shutdown_requested.Set(); break; case ConfigureNotify: { if (last_window_width != event.xconfigure.width || last_window_height != event.xconfigure.height) { last_window_width = event.xconfigure.width; last_window_height = event.xconfigure.height; // We call Renderer::ChangeSurface here to indicate the size has changed, // but pass the same window handle. This is needed for the Vulkan backend, // otherwise it cannot tell that the window has been resized on some drivers. if (g_renderer) g_renderer->ChangeSurface(s_window_handle); } } break; } } if (!fullscreen) { Window winDummy; unsigned int borderDummy, depthDummy; XGetGeometry(dpy, win, &winDummy, &SConfig::GetInstance().iRenderWindowXPos, &SConfig::GetInstance().iRenderWindowYPos, (unsigned int*)&SConfig::GetInstance().iRenderWindowWidth, (unsigned int*)&SConfig::GetInstance().iRenderWindowHeight, &borderDummy, &depthDummy); rendererIsFullscreen = false; } Core::HostDispatchJobs(); usleep(100000); } }
void ExecuteCommand(u32 _Address) { IPCCommandResult result = IWII_IPC_HLE_Device::GetNoReply(); IPCCommandType Command = static_cast<IPCCommandType>(Memory::Read_U32(_Address)); s32 DeviceID = Memory::Read_U32(_Address + 8); std::shared_ptr<IWII_IPC_HLE_Device> pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr; INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", _Address, Command, DeviceID, pDevice.get()); switch (Command) { case IPC_CMD_OPEN: { u32 Mode = Memory::Read_U32(_Address + 0x10); DeviceID = getFreeDeviceId(); std::string DeviceName = Memory::GetString(Memory::Read_U32(_Address + 0xC)); WARN_LOG(WII_IPC_HLE, "Trying to open %s as %d", DeviceName.c_str(), DeviceID); if (DeviceID >= 0) { if (DeviceName.find("/dev/es") == 0) { u32 j; for (j=0; j<ES_MAX_COUNT; j++) { if (!es_inuse[j]) { es_inuse[j] = true; g_FdMap[DeviceID] = es_handles[j]; result = es_handles[j]->Open(_Address, Mode); Memory::Write_U32(DeviceID, _Address+4); break; } } if (j == ES_MAX_COUNT) { Memory::Write_U32(FS_EESEXHAUSTED, _Address + 4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } } else if (DeviceName.find("/dev/") == 0) { pDevice = GetDeviceByName(DeviceName); if (pDevice) { g_FdMap[DeviceID] = pDevice; result = pDevice->Open(_Address, Mode); INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)", pDevice->GetDeviceName().c_str(), DeviceID, Mode); Memory::Write_U32(DeviceID, _Address+4); } else { WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str()); Memory::Write_U32(FS_ENOENT, _Address+4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } } else { pDevice = CreateFileIO(DeviceID, DeviceName); result = pDevice->Open(_Address, Mode); INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)", pDevice->GetDeviceName().c_str(), DeviceID, Mode); if (Memory::Read_U32(_Address + 4) == (u32)DeviceID) { g_FdMap[DeviceID] = pDevice; } } } else { Memory::Write_U32(FS_EFDEXHAUSTED, _Address + 4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } break; } case IPC_CMD_CLOSE: { if (pDevice) { result = pDevice->Close(_Address); for (u32 j=0; j<ES_MAX_COUNT; j++) { if (es_handles[j] == g_FdMap[DeviceID]) { es_inuse[j] = false; } } g_FdMap[DeviceID].reset(); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } break; } case IPC_CMD_READ: { if (pDevice) { result = pDevice->Read(_Address); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } break; } case IPC_CMD_WRITE: { if (pDevice) { result = pDevice->Write(_Address); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } break; } case IPC_CMD_SEEK: { if (pDevice) { result = pDevice->Seek(_Address); } else { Memory::Write_U32(FS_EINVAL, _Address + 4); result = IWII_IPC_HLE_Device::GetDefaultReply(); } break; } case IPC_CMD_IOCTL: { if (pDevice) { result = pDevice->IOCtl(_Address); } break; } case IPC_CMD_IOCTLV: { if (pDevice) { result = pDevice->IOCtlV(_Address); } break; } default: { _dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address); break; } } // Ensure replies happen in order const s64 ticks_until_last_reply = last_reply_time - CoreTiming::GetTicks(); if (ticks_until_last_reply > 0) result.reply_delay_ticks += ticks_until_last_reply; last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks; if (result.send_reply) { // The original hardware overwrites the command type with the async reply type. Memory::Write_U32(IPC_REP_ASYNC, _Address); // IOS also seems to write back the command that was responded to in the FD field. Memory::Write_U32(Command, _Address + 8); // Generate a reply to the IPC command EnqueueReply(_Address, (int)result.reply_delay_ticks); } }
void SDIO_EventNotify() { auto pDevice = static_cast<CWII_IPC_HLE_Device_sdio_slot0*>(GetDeviceByName("/dev/sdio/slot0").get()); if (pDevice) pDevice->EventNotify(); }