Skip to content

Commit b0cfde9

Browse files
libretro: add Wiimote IR passthrough
Adds dolphin_ir_passthrough, letting the frontend supply the Wiimote camera's view of the sensor bar directly instead of having the core synthesise it from a cursor position. The cursor path parks a notional remote two metres from the bar and rotates it by Total Yaw/Total Pitch, a scale with no physical derivation, so where the game draws its hand depends on a constant fitted per game. It also cannot express roll or distance. A frontend that knows the real geometry (a VR room, a tracked light gun) can compute the two dots outright, which BuildDesiredWiimoteState already supports and nothing exposed. * The option itself, off by default, under Wiimote IR. * The Pointer device registers all four touch indices instead of only the first, so the four IR objects ride on indices 0-3. Index 0 keeps its old names, leaving the mouse-mode IR binding untouched. * IRPassthrough is bound and enabled when the option is on: object N takes Pointer:XN+/YN+ over the camera's 0..1 field, PressedN as presence, and a small constant size. Bindings are cleared when off, since AreInputsBound() is half of what selects this path. * irPassthrough is raised at controller setup as well as on an option change, so the setting applies on a cold boot.
1 parent 3e215aa commit b0cfde9

5 files changed

Lines changed: 68 additions & 6 deletions

File tree

Source/Core/DolphinLibretro/Common/Options.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,20 @@ static struct retro_core_option_v2_definition option_defs[] = {
17151715
},
17161716
"disabled"
17171717
},
1718+
{
1719+
Libretro::Options::wiimote::IR_PASSTHROUGH,
1720+
"Wiimote IR > Wiimote IR Passthrough",
1721+
"Wiimote IR Passthrough",
1722+
"Take the Wiimote camera's view of the sensor bar straight from the frontend, instead of deriving it from a cursor position. The frontend supplies up to four IR objects on pointer indices 1-4; Wiimote IR Mode, Total Yaw, Total Pitch and Vertical Offset are all bypassed. For frontends that know the real geometry (a VR room, a tracked light gun) this is exact, and it carries roll and distance, which a cursor cannot. Leave off for a mouse or a gamepad.",
1723+
nullptr,
1724+
CATEGORY_WIIMOTE,
1725+
{
1726+
{ "disabled", nullptr },
1727+
{ "enabled", nullptr },
1728+
{ nullptr, nullptr }
1729+
},
1730+
"disabled"
1731+
},
17181732

17191733
#if defined(HAS_OPENGL) && defined(__WEBOS__)
17201734
{

Source/Core/DolphinLibretro/Common/Options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ namespace wiimote {
302302
constexpr const char IR_MODIFIER[] = "dolphin_ir_modifier";
303303
constexpr const char SWING_MODIFIER[] = "dolphin_swing_modifier";
304304
constexpr const char SWING_ANGLE[] = "dolphin_swing_angle";
305+
constexpr const char IR_PASSTHROUGH[] = "dolphin_ir_passthrough";
305306
} // namespace wiimote
306307

307308
// ======================================================

Source/Core/DolphinLibretro/Input.cpp

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "InputCommon/ControlReference/ExpressionParser.h"
3939
#include "InputCommon/ControllerEmu/Control/Control.h"
4040
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
41+
#include "InputCommon/ControllerEmu/ControlGroup/IRPassthrough.h"
4142
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
4243
#include "InputCommon/ControllerInterface/ControllerInterface.h"
4344
#include "InputCommon/GCAdapter.h"
@@ -407,11 +408,22 @@ Device::Device(unsigned device, unsigned p) : m_device(device), m_port(p)
407408
AddButton(RETRO_DEVICE_ID_MOUSE_BUTTON_5, "Button5");
408409
return;
409410
case RETRO_DEVICE_POINTER:
410-
AddButton(RETRO_DEVICE_ID_POINTER_PRESSED, "Pressed0", 0);
411-
AddAxis(RETRO_DEVICE_ID_POINTER_X, -0x8000, "X0-", 0);
412-
AddAxis(RETRO_DEVICE_ID_POINTER_X, 0x7FFF, "X0+", 0);
413-
AddAxis(RETRO_DEVICE_ID_POINTER_Y, -0x8000, "Y0-", 0);
414-
AddAxis(RETRO_DEVICE_ID_POINTER_Y, 0x7FFF, "Y0+", 0);
411+
// Four touch indices, one per IR object. Index 0 keeps its old names.
412+
{
413+
static const char* const kPressed[] = { "Pressed0", "Pressed1", "Pressed2", "Pressed3" };
414+
static const char* const kXNeg[] = { "X0-", "X1-", "X2-", "X3-" };
415+
static const char* const kXPos[] = { "X0+", "X1+", "X2+", "X3+" };
416+
static const char* const kYNeg[] = { "Y0-", "Y1-", "Y2-", "Y3-" };
417+
static const char* const kYPos[] = { "Y0+", "Y1+", "Y2+", "Y3+" };
418+
for (unsigned i = 0; i < 4; ++i)
419+
{
420+
AddButton(RETRO_DEVICE_ID_POINTER_PRESSED, kPressed[i], i);
421+
AddAxis(RETRO_DEVICE_ID_POINTER_X, -0x8000, kXNeg[i], i);
422+
AddAxis(RETRO_DEVICE_ID_POINTER_X, 0x7FFF, kXPos[i], i);
423+
AddAxis(RETRO_DEVICE_ID_POINTER_Y, -0x8000, kYNeg[i], i);
424+
AddAxis(RETRO_DEVICE_ID_POINTER_Y, 0x7FFF, kYPos[i], i);
425+
}
426+
}
415427
return;
416428
case RETRO_DEVICE_KEYBOARD:
417429
return;
@@ -946,6 +958,37 @@ void UpdateWiimoteMappings(const WiimoteUpdateFlags& f, unsigned port, unsigned
946958
}
947959
}
948960

961+
// Raw IR: the frontend supplies the camera's view directly, bypassing the
962+
// Point group and Total Yaw/Pitch. Objects arrive on pointer indices 0-3,
963+
// X/Y over the camera's 0..1 field, PRESSED marking the object visible.
964+
// Size is a constant; games only read it to reject noise.
965+
if (f.irPassthrough)
966+
{
967+
auto* wmIRPass = static_cast<ControllerEmu::IRPassthrough*>(
968+
wm->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::IRPassthrough));
969+
const bool passthrough =
970+
Libretro::Options::GetCached<bool>(Libretro::Options::wiimote::IR_PASSTHROUGH);
971+
972+
if (wmIRPass)
973+
{
974+
const std::string devPointer =
975+
Libretro::Input::GetQualifiedName(port, RETRO_DEVICE_POINTER);
976+
wmIRPass->enabled.SetValue(passthrough);
977+
static const char* const kObj[] = { "0", "1", "2", "3" };
978+
for (int i = 0; i < 4; ++i)
979+
{
980+
// Cleared when off; AreInputsBound() is half of what selects this path.
981+
const std::string idx = kObj[i];
982+
wmIRPass->SetControlExpression(i * 3 + 0,
983+
passthrough ? "`" + devPointer + ":X" + idx + "+`" : "");
984+
wmIRPass->SetControlExpression(i * 3 + 1,
985+
passthrough ? "`" + devPointer + ":Y" + idx + "+`" : "");
986+
wmIRPass->SetControlExpression(i * 3 + 2,
987+
passthrough ? "`" + devPointer + ":Pressed" + idx + "` * 0.2" : "");
988+
}
989+
}
990+
}
991+
949992
if (f.swingAngle)
950993
{
951994
ControllerEmu::ControlGroup* wmSwing = wm->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Swing);
@@ -1516,6 +1559,8 @@ void retro_set_controller_port_device_wii(unsigned port, unsigned device)
15161559
f.irModifier = true;
15171560
f.swingModifier = true;
15181561
f.sideways = true;
1562+
// Raised at setup so the option applies on a cold boot.
1563+
f.irPassthrough = true;
15191564
Libretro::Input::UpdateWiimoteMappings(f, port, device);
15201565

15211566
wmShake->SetControlExpression(0, bindMouse("L2", devMouse + ":Middle")); // Wiimote shake X

Source/Core/DolphinLibretro/Input.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ struct WiimoteUpdateFlags
1919
bool sideways = false;
2020
bool rumble = false;
2121
bool gcMicBtn = false;
22+
bool irPassthrough = false;
2223

2324
bool any() const {
2425
return irMode || irOffset || irYaw || irPitch ||
2526
irDeadzone || irModifier || swingModifier ||
26-
swingAngle || sideways || rumble || gcMicBtn;
27+
swingAngle || sideways || rumble || gcMicBtn || irPassthrough;
2728
}
2829
};
2930

Source/Core/DolphinLibretro/Main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ void retro_run(void)
389389
flags.swingModifier = Libretro::Options::IsUpdated(Libretro::Options::wiimote::SWING_MODIFIER);
390390
flags.swingAngle = Libretro::Options::IsUpdated(Libretro::Options::wiimote::SWING_ANGLE);
391391
flags.sideways = Libretro::Options::IsUpdated(Libretro::Options::wiimote::HOTKEY_SIDEWAYS_TOGGLE);
392+
flags.irPassthrough = Libretro::Options::IsUpdated(Libretro::Options::wiimote::IR_PASSTHROUGH);
392393
}
393394

394395
flags.rumble = Libretro::Options::IsUpdated(Libretro::Options::sysconf::ENABLE_RUMBLE);

0 commit comments

Comments
 (0)