235 float screenWidth = (float)platform->getVideo()->getScreenWidth();
236 float screenHeight = (float)platform->getVideo()->getScreenHeight();
238 for (
int i = 3; i >= 0; i--) {
243 VPADStatus vpadStatus;
244 VPADReadError vpadError;
245 VPADRead(VPAD_CHAN_0, &vpadStatus, 1, &vpadError);
247 if (vpadError == VPAD_READ_SUCCESS) {
251 padData.
hw_buttons_d[INPUT_HW_DRC] = MapVPADToGeneric(vpadStatus.trigger);
252 padData.
hw_buttons_h[INPUT_HW_DRC] = MapVPADToGeneric(vpadStatus.hold);
253 padData.
hw_buttons_r[INPUT_HW_DRC] = MapVPADToGeneric(vpadStatus.release);
255 padData.
hw_stickX[INPUT_HW_DRC] = clampf(vpadStatus.leftStick.x, -1.0f, 1.0f);
256 padData.
hw_stickY[INPUT_HW_DRC] = clampf(vpadStatus.leftStick.y, -1.0f, 1.0f);
257 padData.
hw_substickX[INPUT_HW_DRC] = clampf(vpadStatus.rightStick.x, -1.0f, 1.0f);
258 padData.
hw_substickY[INPUT_HW_DRC] = clampf(vpadStatus.rightStick.y, -1.0f, 1.0f);
260 padData.
hw_gforceX[INPUT_HW_DRC] = vpadStatus.accelorometer.acc.x;
261 padData.
hw_gforceY[INPUT_HW_DRC] = vpadStatus.accelorometer.acc.y;
262 padData.
hw_gforceZ[INPUT_HW_DRC] = vpadStatus.accelorometer.acc.z;
263 padData.
hw_pitch[INPUT_HW_DRC] = vpadStatus.angle.x * 360.0f;
264 padData.
hw_roll[INPUT_HW_DRC] = vpadStatus.angle.y * 360.0f;
265 padData.
hw_yaw[INPUT_HW_DRC] = vpadStatus.angle.z * 360.0f;
268 bool drcTouched = (vpadStatus.tpNormal.touched != 0);
272 VPADGetTPCalibratedPoint(VPAD_CHAN_0, &calib, &vpadStatus.tpNormal);
275 float posX = clampf((
float)calib.x * (screenWidth / 1280.0f), 0.0f, screenWidth);
276 float posY = clampf((
float)calib.y * (screenHeight / 720.0f), 0.0f, screenHeight);
283 drcLastTouchX = posX;
284 drcLastTouchY = posY;
288 if (drcTouched && !drcTouchedPrev) {
292 }
else if (drcTouched && drcTouchedPrev) {
295 }
else if (!drcTouched && drcTouchedPrev) {
306 drcTouchedPrev = drcTouched;
310 CarryForwardHwProfile(drcCache, padData, INPUT_HW_DRC);
312 drcCache.isTouch = padData.
isTouch;
314 drcCache.cursor_x = padData.
cursor_x;
315 drcCache.cursor_y = padData.
cursor_y;
316 }
else if (vpadError == VPAD_READ_NO_SAMPLES || vpadError == VPAD_READ_BUSY) {
319 if (drcCache.hw_connected[INPUT_HW_DRC]) {
320 CarryForwardHwProfile(padData, drcCache, INPUT_HW_DRC);
322 padData.
isTouch = drcCache.isTouch;
324 padData.
cursor_x = drcCache.cursor_x;
325 padData.
cursor_y = drcCache.cursor_y;
330 drcTouchedPrev =
false;
335 KPADStatus kpadStatusBuf[KPAD_SAMPLE_BUFFER];
336 KPADError kpadError = KPAD_ERROR_UNINITIALIZED;
337 uint32_t kpadRead = KPADReadEx((KPADChan)i, kpadStatusBuf, KPAD_SAMPLE_BUFFER, &kpadError);
344 if (kpadRead > 0 && kpadError == KPAD_ERROR_OK) {
345 KPADStatus& kpadStatus = kpadStatusBuf[0];
348 padData.
battery_level = WPADGetBatteryLevel((WPADChan)i) * 25;
351 kpadCache[i].validPointer =
false;
353 padData.
hw_gforceX[INPUT_HW_WIIMOTE] = kpadStatus.acc.x;
354 padData.
hw_gforceY[INPUT_HW_WIIMOTE] = kpadStatus.acc.y;
355 padData.
hw_gforceZ[INPUT_HW_WIIMOTE] = kpadStatus.acc.z;
358 float wmPitch = kpadCache[i].hw_pitch[INPUT_HW_WIIMOTE];
359 float wmRoll = kpadCache[i].hw_roll[INPUT_HW_WIIMOTE];
360 UpdateTiltAngles(kpadStatus.acc.x, kpadStatus.acc.y, kpadStatus.acc.z, wmPitch, wmRoll);
361 padData.
hw_pitch[INPUT_HW_WIIMOTE] = wmPitch;
362 padData.
hw_roll[INPUT_HW_WIIMOTE] = wmRoll;
364 if (kpadStatus.extensionType == WPAD_EXT_PRO_CONTROLLER) {
366 padData.
hw_buttons_d[INPUT_HW_WUPC] = MapKPADProToGeneric(kpadStatus.pro.trigger);
367 padData.
hw_buttons_h[INPUT_HW_WUPC] = MapKPADProToGeneric(kpadStatus.pro.hold);
368 padData.
hw_buttons_r[INPUT_HW_WUPC] = MapKPADProToGeneric(kpadStatus.pro.release);
370 padData.
hw_stickX[INPUT_HW_WUPC] = clampf(kpadStatus.pro.leftStick.x, -1.0f, 1.0f);
371 padData.
hw_stickY[INPUT_HW_WUPC] = clampf(kpadStatus.pro.leftStick.y, -1.0f, 1.0f);
372 padData.
hw_substickX[INPUT_HW_WUPC] = clampf(kpadStatus.pro.rightStick.x, -1.0f, 1.0f);
373 padData.
hw_substickY[INPUT_HW_WUPC] = clampf(kpadStatus.pro.rightStick.y, -1.0f, 1.0f);
375 controller[i]->setSideways(
false);
377 else if (kpadStatus.extensionType == WPAD_EXT_CLASSIC || kpadStatus.extensionType == WPAD_EXT_MPLUS_CLASSIC) {
379 padData.
hw_buttons_d[INPUT_HW_CLASSIC] = MapKPADClassicToGeneric(kpadStatus.classic.trigger);
380 padData.
hw_buttons_h[INPUT_HW_CLASSIC] = MapKPADClassicToGeneric(kpadStatus.classic.hold);
381 padData.
hw_buttons_r[INPUT_HW_CLASSIC] = MapKPADClassicToGeneric(kpadStatus.classic.release);
383 padData.
hw_stickX[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.leftStick.x, -1.0f, 1.0f);
384 padData.
hw_stickY[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.leftStick.y, -1.0f, 1.0f);
385 padData.
hw_substickX[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.rightStick.x, -1.0f, 1.0f);
386 padData.
hw_substickY[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.rightStick.y, -1.0f, 1.0f);
387 padData.
hw_triggerL[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.leftTrigger, 0.0f, 1.0f);
388 padData.
hw_triggerR[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.rightTrigger, 0.0f, 1.0f);
390 controller[i]->setSideways(
false);
394 padData.
hw_buttons_d[INPUT_HW_WIIMOTE] = MapKPADCoreToGeneric(kpadStatus.trigger);
395 padData.
hw_buttons_h[INPUT_HW_WIIMOTE] = MapKPADCoreToGeneric(kpadStatus.hold);
396 padData.
hw_buttons_r[INPUT_HW_WIIMOTE] = MapKPADCoreToGeneric(kpadStatus.release);
401 float rawX = clampf((kpadStatus.pos.x * 0.5f + 0.5f) * screenWidth, 0.0f, screenWidth);
402 float rawY = clampf((kpadStatus.pos.y * 0.5f + 0.5f) * screenHeight, 0.0f, screenHeight);
404 float deltaTime = platform->getVideo()->getDeltaTime();
405 float smoothX, smoothY;
407 if (!irSmoothInit[i]) {
411 irFilterX[i].reset();
412 irFilterY[i].reset();
413 smoothX = irFilterX[i].filter(rawX, deltaTime);
414 smoothY = irFilterY[i].filter(rawY, deltaTime);
415 irSmoothInit[i] =
true;
417 smoothX = irFilterX[i].filter(rawX, deltaTime);
418 smoothY = irFilterY[i].filter(rawY, deltaTime);
421 float cursorAngleDeg = std::atan2(kpadStatus.angle.y, kpadStatus.angle.x) * (180.0f / (float)M_PI);
430 kpadCache[i].validPointer =
true;
431 kpadCache[i].isTouch =
false;
432 kpadCache[i].cursor_x = smoothX;
433 kpadCache[i].cursor_y = smoothY;
434 kpadCache[i].cursor_angle = cursorAngleDeg;
435 }
else if (!kpadStatus.posValid) {
438 irSmoothInit[i] =
false;
441 if (kpadStatus.extensionType == WPAD_EXT_NUNCHUK || kpadStatus.extensionType == WPAD_EXT_MPLUS_NUNCHUK) {
444 padData.
hw_buttons_d[INPUT_HW_NUNCHUK] = MapKPADNunchukToGeneric(kpadStatus.nunchuk.trigger);
445 padData.
hw_buttons_h[INPUT_HW_NUNCHUK] = MapKPADNunchukToGeneric(kpadStatus.nunchuk.hold);
446 padData.
hw_buttons_r[INPUT_HW_NUNCHUK] = MapKPADNunchukToGeneric(kpadStatus.nunchuk.release);
448 padData.
hw_stickX[INPUT_HW_NUNCHUK] = clampf(kpadStatus.nunchuk.stick.x, -1.0f, 1.0f);
449 padData.
hw_stickY[INPUT_HW_NUNCHUK] = clampf(kpadStatus.nunchuk.stick.y, -1.0f, 1.0f);
451 padData.
hw_gforceX[INPUT_HW_NUNCHUK] = kpadStatus.nunchuk.acc.x;
452 padData.
hw_gforceY[INPUT_HW_NUNCHUK] = kpadStatus.nunchuk.acc.y;
453 padData.
hw_gforceZ[INPUT_HW_NUNCHUK] = kpadStatus.nunchuk.acc.z;
455 controller[i]->setSideways(
false);
463 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_WIIMOTE);
464 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_NUNCHUK);
465 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_CLASSIC);
466 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_WUPC);
467 }
else if (kpadError == KPAD_ERROR_NO_SAMPLES || kpadError == KPAD_ERROR_BUSY) {
469 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_WIIMOTE);
470 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_NUNCHUK);
471 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_CLASSIC);
472 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_WUPC);
474 if (kpadCache[i].hw_connected[INPUT_HW_WIIMOTE]) {
478 if (!padData.
validPointer && kpadCache[i].validPointer) {
481 padData.
cursor_x = kpadCache[i].cursor_x;
482 padData.
cursor_y = kpadCache[i].cursor_y;
489 irSmoothInit[i] =
false;
490 controller[i]->setSideways(
false);
494 for (uint32_t hw = 0; hw < INPUT_HW_MAX; hw++) {
510 if (std::abs(padData.
hw_yaw[hw]) > std::abs(padData.
yaw)) padData.
yaw = padData.
hw_yaw[hw];
514 controller[i]->update(padData, platform->getVideo()->getDeltaTime());
519 static constexpr int kMenuRumbleOnFrames = 2;
520 static constexpr int kMenuRumbleGapFrames = 6;
522 if (rumbleRequest[i]) {
523 rumbleRequest[i] =
false;
524 if (menuRumbleFrames[i] == 0 && menuRumbleGapFrames[i] == 0) {
525 menuRumbleFrames[i] = kMenuRumbleOnFrames;
529 bool menuWantRumble = menuRumbleFrames[i] > 0;
531 if (menuRumbleFrames[i] > 0) {
532 menuRumbleFrames[i]--;
533 if (menuRumbleFrames[i] == 0) menuRumbleGapFrames[i] = kMenuRumbleGapFrames;
534 }
else if (menuRumbleGapFrames[i] > 0) {
535 menuRumbleGapFrames[i]--;
538 bool wantRumble = menuWantRumble || continuousRumble[i];
539 bool motorOn =
false;
543 if (silenceFrames[i] > 0) {
545 continuousRumbleCount[i] = 0;
547 if (wantRumble && allowRumble) {
548 continuousRumbleCount[i]++;
549 if (continuousRumbleCount[i] > 70) {
550 silenceFrames[i] = 5;
551 continuousRumbleCount[i] = 0;
556 continuousRumbleCount[i] = 0;
561 WPADControlMotor((WPADChan)i, motorOn ? TRUE : FALSE);
567 VPADControlMotor(VPAD_CHAN_0, vpadRumblePattern,
sizeof(vpadRumblePattern));
569 VPADControlMotor(VPAD_CHAN_0, vpadMenuRumblePattern,
sizeof(vpadMenuRumblePattern));
572 VPADStopMotor(VPAD_CHAN_0);