12#include <wiiuse/wpad.h>
14#include "WiiInputDriver.h"
15#include "WiiPlatform.h"
17#include "../OgcInputUtil.h"
18#include "../../Platform.h"
19#include "../../InputController.h"
21static void WiimotePowerButtonCallback(s32) { NotifyWiiShutdownRequested(); }
23WiiInputDriver::~WiiInputDriver() {
29 SYS_SetPowerCallback(NotifyWiiShutdownRequested);
33 WPAD_SetDataFormat(WPAD_CHAN_ALL, WPAD_FMT_BTNS_ACC_IR);
34 WPAD_SetVRes(WPAD_CHAN_ALL, platform->getVideo()->getScreenWidth(), platform->getVideo()->getScreenHeight());
35 WPAD_SetPowerButtonCallback(WiimotePowerButtonCallback);
44 return CONF_GetPadMotorMode() != 0;
48 WPAD_Rumble(channel, on ? 1 : 0);
55static uint32_t MapWiimoteToGeneric(uint32_t wpad_btns)
57 uint32_t mask = INPUT_BTN_NONE;
59 if (wpad_btns & WPAD_BUTTON_A) mask |= INPUT_BTN_A;
60 if (wpad_btns & WPAD_BUTTON_B) mask |= INPUT_BTN_B;
61 if (wpad_btns & WPAD_BUTTON_1) mask |= INPUT_BTN_1;
62 if (wpad_btns & WPAD_BUTTON_2) mask |= INPUT_BTN_2;
63 if (wpad_btns & WPAD_BUTTON_UP) mask |= INPUT_BTN_UP;
64 if (wpad_btns & WPAD_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
65 if (wpad_btns & WPAD_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
66 if (wpad_btns & WPAD_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
67 if (wpad_btns & WPAD_BUTTON_PLUS) mask |= INPUT_BTN_PLUS;
68 if (wpad_btns & WPAD_BUTTON_MINUS) mask |= INPUT_BTN_MINUS;
69 if (wpad_btns & WPAD_BUTTON_HOME) mask |= INPUT_BTN_HOME;
74static uint32_t MapNunchukToGeneric(uint32_t wpad_btns)
76 uint32_t mask = INPUT_BTN_NONE;
78 if (wpad_btns & WPAD_NUNCHUK_BUTTON_Z) mask |= INPUT_TRIGGER_ZL;
79 if (wpad_btns & WPAD_NUNCHUK_BUTTON_C) mask |= INPUT_TRIGGER_L;
84static uint32_t MapClassicToGeneric(uint32_t wpad_btns)
86 uint32_t mask = INPUT_BTN_NONE;
89 if (wpad_btns & WPAD_CLASSIC_BUTTON_A) mask |= INPUT_BTN_A;
90 if (wpad_btns & WPAD_CLASSIC_BUTTON_B) mask |= INPUT_BTN_B;
91 if (wpad_btns & WPAD_CLASSIC_BUTTON_X) mask |= INPUT_BTN_X;
92 if (wpad_btns & WPAD_CLASSIC_BUTTON_Y) mask |= INPUT_BTN_Y;
93 if (wpad_btns & WPAD_CLASSIC_BUTTON_UP) mask |= INPUT_BTN_UP;
94 if (wpad_btns & WPAD_CLASSIC_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
95 if (wpad_btns & WPAD_CLASSIC_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
96 if (wpad_btns & WPAD_CLASSIC_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
97 if (wpad_btns & WPAD_CLASSIC_BUTTON_PLUS) mask |= INPUT_BTN_PLUS;
98 if (wpad_btns & WPAD_CLASSIC_BUTTON_MINUS) mask |= INPUT_BTN_MINUS;
99 if (wpad_btns & WPAD_CLASSIC_BUTTON_HOME) mask |= INPUT_BTN_HOME;
100 if (wpad_btns & WPAD_CLASSIC_BUTTON_FULL_L) mask |= INPUT_TRIGGER_L;
101 if (wpad_btns & WPAD_CLASSIC_BUTTON_FULL_R) mask |= INPUT_TRIGGER_R;
102 if (wpad_btns & WPAD_CLASSIC_BUTTON_ZL) mask |= INPUT_TRIGGER_ZL;
103 if (wpad_btns & WPAD_CLASSIC_BUTTON_ZR) mask |= INPUT_TRIGGER_ZR;
108static uint32_t MapWiiUGamepadToGeneric(uint32_t drc_btns) {
109 uint32_t mask = INPUT_BTN_NONE;
110 if (drc_btns & WIIDRC_BUTTON_A) mask |= INPUT_BTN_A;
111 if (drc_btns & WIIDRC_BUTTON_B) mask |= INPUT_BTN_B;
112 if (drc_btns & WIIDRC_BUTTON_X) mask |= INPUT_BTN_X;
113 if (drc_btns & WIIDRC_BUTTON_Y) mask |= INPUT_BTN_Y;
114 if (drc_btns & WIIDRC_BUTTON_UP) mask |= INPUT_BTN_UP;
115 if (drc_btns & WIIDRC_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
116 if (drc_btns & WIIDRC_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
117 if (drc_btns & WIIDRC_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
118 if (drc_btns & WIIDRC_BUTTON_PLUS) mask |= INPUT_BTN_PLUS;
119 if (drc_btns & WIIDRC_BUTTON_MINUS) mask |= INPUT_BTN_MINUS;
120 if (drc_btns & WIIDRC_BUTTON_HOME) mask |= INPUT_BTN_HOME;
121 if (drc_btns & WIIDRC_BUTTON_L) mask |= INPUT_TRIGGER_L;
122 if (drc_btns & WIIDRC_BUTTON_R) mask |= INPUT_TRIGGER_R;
123 if (drc_btns & WIIDRC_BUTTON_ZL) mask |= INPUT_TRIGGER_ZL;
124 if (drc_btns & WIIDRC_BUTTON_ZR) mask |= INPUT_TRIGGER_ZR;
131static float NormalizeWPADAnalog(
int pos,
int min,
int max,
int center) {
132 if (min == max)
return 0.0f;
135 if ((min >= center) || (max <= center)) {
136 min = 0; max = 64; center = 32;
138 int offset = pos - center;
140 return OgcClampf((
float)offset / (
float)(max - center), 0.0f, 1.0f);
142 return OgcClampf((
float)offset / (
float)(center - min), -1.0f, 0.0f);
150 readWiimote(channel, pad);
158void WiiInputDriver::readWiimote(
int channel,
InputPadData & padData) {
159 uint32_t exp_type = WPAD_EXP_NONE;
161 if (WPAD_Probe(channel, &exp_type) != WPAD_ERR_NONE)
164 WPADData* wpad = WPAD_Data(channel);
170 padData.
hw_gforceX[INPUT_HW_WIIMOTE] = wpad->gforce.x;
171 padData.
hw_gforceY[INPUT_HW_WIIMOTE] = wpad->gforce.y;
172 padData.
hw_gforceZ[INPUT_HW_WIIMOTE] = wpad->gforce.z;
173 padData.
hw_pitch[INPUT_HW_WIIMOTE] = wpad->orient.pitch;
174 padData.
hw_roll[INPUT_HW_WIIMOTE] = wpad->orient.roll;
175 padData.
hw_yaw[INPUT_HW_WIIMOTE] = wpad->orient.yaw;
177 if (exp_type == WPAD_EXP_NONE) {
178 padData.
hw_buttons_d[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_d);
179 padData.
hw_buttons_h[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_h);
180 padData.
hw_buttons_r[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_u);
182 if (wpad->ir.valid) {
192 else if (exp_type == WPAD_EXP_NUNCHUK) {
193 padData.
hw_buttons_d[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_d);
194 padData.
hw_buttons_h[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_h);
195 padData.
hw_buttons_r[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_u);
198 padData.
hw_buttons_d[INPUT_HW_NUNCHUK] = MapNunchukToGeneric(wpad->btns_d);
199 padData.
hw_buttons_h[INPUT_HW_NUNCHUK] = MapNunchukToGeneric(wpad->btns_h);
200 padData.
hw_buttons_r[INPUT_HW_NUNCHUK] = MapNunchukToGeneric(wpad->btns_u);
201 joystick_t* js = &wpad->exp.nunchuk.js;
202 padData.
hw_stickX[INPUT_HW_NUNCHUK] = NormalizeWPADAnalog(js->pos.x, js->min.x, js->max.x, js->center.x);
203 padData.
hw_stickY[INPUT_HW_NUNCHUK] = NormalizeWPADAnalog(js->pos.y, js->min.y, js->max.y, js->center.y);
205 padData.
hw_gforceX[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.gforce.x;
206 padData.
hw_gforceY[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.gforce.y;
207 padData.
hw_gforceZ[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.gforce.z;
208 padData.
hw_pitch[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.orient.pitch;
209 padData.
hw_roll[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.orient.roll;
210 padData.
hw_yaw[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.orient.yaw;
213 if (wpad->ir.valid) {
223 else if (exp_type == WPAD_EXP_CLASSIC) {
224 bool isWUPC = (wpad->exp.classic.type == 2);
225 int hw = isWUPC ? INPUT_HW_WUPC : INPUT_HW_CLASSIC;
228 padData.
hw_buttons_d[hw] = MapClassicToGeneric(wpad->btns_d);
229 padData.
hw_buttons_h[hw] = MapClassicToGeneric(wpad->btns_h);
230 padData.
hw_buttons_r[hw] = MapClassicToGeneric(wpad->btns_u);
232 joystick_t* ljs = &wpad->exp.classic.ljs;
233 joystick_t* rjs = &wpad->exp.classic.rjs;
234 padData.
hw_stickX[hw] = NormalizeWPADAnalog(ljs->pos.x, ljs->min.x, ljs->max.x, ljs->center.x);
235 padData.
hw_stickY[hw] = NormalizeWPADAnalog(ljs->pos.y, ljs->min.y, ljs->max.y, ljs->center.y);
236 padData.
hw_substickX[hw] = NormalizeWPADAnalog(rjs->pos.x, rjs->min.x, rjs->max.x, rjs->center.x);
237 padData.
hw_substickY[hw] = NormalizeWPADAnalog(rjs->pos.y, rjs->min.y, rjs->max.y, rjs->center.y);
238 padData.
hw_triggerL[hw] = OgcClampf(wpad->exp.classic.l_shoulder, 0.0f, 1.0f);
239 padData.
hw_triggerR[hw] = OgcClampf(wpad->exp.classic.r_shoulder, 0.0f, 1.0f);
248void WiiInputDriver::readGamePad(
InputPadData & padData) {
249 if (!WiiDRC_Inited() || !WiiDRC_Connected())
253 padData.
hw_buttons_d[INPUT_HW_DRC] = MapWiiUGamepadToGeneric(WiiDRC_ButtonsDown());
254 padData.
hw_buttons_h[INPUT_HW_DRC] = MapWiiUGamepadToGeneric(WiiDRC_ButtonsHeld());
255 padData.
hw_buttons_r[INPUT_HW_DRC] = MapWiiUGamepadToGeneric(WiiDRC_ButtonsUp());
256 padData.
hw_stickX[INPUT_HW_DRC] = OgcStickToFloat(WiiDRC_lStickX());
257 padData.
hw_stickY[INPUT_HW_DRC] = OgcStickToFloat(WiiDRC_lStickY());
258 padData.
hw_substickX[INPUT_HW_DRC] = OgcStickToFloat(WiiDRC_rStickX());
259 padData.
hw_substickY[INPUT_HW_DRC] = OgcStickToFloat(WiiDRC_rStickY());