234 float screenWidth = (float)platform->getVideo()->getScreenWidth();
235 float screenHeight = (float)platform->getVideo()->getScreenHeight();
237 for (
int i = 3; i >= 0; i--) {
242 VPADStatus vpadStatus;
243 VPADReadError vpadError;
244 VPADRead(VPAD_CHAN_0, &vpadStatus, 1, &vpadError);
246 if (vpadError == VPAD_READ_SUCCESS) {
250 padData.
hw_buttons_d[INPUT_HW_DRC] = MapVPADToGeneric(vpadStatus.trigger);
251 padData.
hw_buttons_h[INPUT_HW_DRC] = MapVPADToGeneric(vpadStatus.hold);
252 padData.
hw_buttons_r[INPUT_HW_DRC] = MapVPADToGeneric(vpadStatus.release);
254 padData.
hw_stickX[INPUT_HW_DRC] = clampf(vpadStatus.leftStick.x, -1.0f, 1.0f);
255 padData.
hw_stickY[INPUT_HW_DRC] = clampf(vpadStatus.leftStick.y, -1.0f, 1.0f);
256 padData.
hw_substickX[INPUT_HW_DRC] = clampf(vpadStatus.rightStick.x, -1.0f, 1.0f);
257 padData.
hw_substickY[INPUT_HW_DRC] = clampf(vpadStatus.rightStick.y, -1.0f, 1.0f);
259 padData.
hw_gforceX[INPUT_HW_DRC] = vpadStatus.accelerometer.acc.x;
260 padData.
hw_gforceY[INPUT_HW_DRC] = vpadStatus.accelerometer.acc.y;
261 padData.
hw_gforceZ[INPUT_HW_DRC] = vpadStatus.accelerometer.acc.z;
262 padData.
hw_pitch[INPUT_HW_DRC] = vpadStatus.angle.x * 360.0f;
263 padData.
hw_roll[INPUT_HW_DRC] = vpadStatus.angle.y * 360.0f;
264 padData.
hw_yaw[INPUT_HW_DRC] = vpadStatus.angle.z * 360.0f;
267 bool drcTouched = (vpadStatus.tpNormal.touched != 0);
271 VPADGetTPCalibratedPoint(VPAD_CHAN_0, &calib, &vpadStatus.tpNormal);
274 float posX = clampf((
float)calib.x * (screenWidth / 1280.0f), 0.0f, screenWidth);
275 float posY = clampf((
float)calib.y * (screenHeight / 720.0f), 0.0f, screenHeight);
282 drcLastTouchX = posX;
283 drcLastTouchY = posY;
287 if (drcTouched && !drcTouchedPrev) {
291 }
else if (drcTouched && drcTouchedPrev) {
294 }
else if (!drcTouched && drcTouchedPrev) {
305 drcTouchedPrev = drcTouched;
309 CarryForwardHwProfile(drcCache, padData, INPUT_HW_DRC);
311 drcCache.isTouch = padData.
isTouch;
313 drcCache.cursor_x = padData.
cursor_x;
314 drcCache.cursor_y = padData.
cursor_y;
315 }
else if (vpadError == VPAD_READ_NO_SAMPLES || vpadError == VPAD_READ_BUSY) {
318 if (drcCache.hw_connected[INPUT_HW_DRC]) {
319 CarryForwardHwProfile(padData, drcCache, INPUT_HW_DRC);
321 padData.
isTouch = drcCache.isTouch;
323 padData.
cursor_x = drcCache.cursor_x;
324 padData.
cursor_y = drcCache.cursor_y;
329 drcTouchedPrev =
false;
334 KPADStatus kpadStatusBuf[KPAD_SAMPLE_BUFFER];
335 KPADError kpadError = KPAD_ERROR_UNINITIALIZED;
336 uint32_t kpadRead = KPADReadEx((KPADChan)i, kpadStatusBuf, KPAD_SAMPLE_BUFFER, &kpadError);
343 if (kpadRead > 0 && kpadError == KPAD_ERROR_OK) {
344 KPADStatus& kpadStatus = kpadStatusBuf[0];
347 padData.
battery_level = WPADGetBatteryLevel((WPADChan)i) * 25;
350 kpadCache[i].validPointer =
false;
352 padData.
hw_gforceX[INPUT_HW_WIIMOTE] = kpadStatus.acc.x;
353 padData.
hw_gforceY[INPUT_HW_WIIMOTE] = kpadStatus.acc.y;
354 padData.
hw_gforceZ[INPUT_HW_WIIMOTE] = kpadStatus.acc.z;
357 float wmPitch = kpadCache[i].hw_pitch[INPUT_HW_WIIMOTE];
358 float wmRoll = kpadCache[i].hw_roll[INPUT_HW_WIIMOTE];
359 UpdateTiltAngles(kpadStatus.acc.x, kpadStatus.acc.y, kpadStatus.acc.z, wmPitch, wmRoll);
360 padData.
hw_pitch[INPUT_HW_WIIMOTE] = wmPitch;
361 padData.
hw_roll[INPUT_HW_WIIMOTE] = wmRoll;
363 if (kpadStatus.extensionType == WPAD_EXT_PRO_CONTROLLER) {
365 padData.
hw_buttons_d[INPUT_HW_WUPC] = MapKPADProToGeneric(kpadStatus.pro.trigger);
366 padData.
hw_buttons_h[INPUT_HW_WUPC] = MapKPADProToGeneric(kpadStatus.pro.hold);
367 padData.
hw_buttons_r[INPUT_HW_WUPC] = MapKPADProToGeneric(kpadStatus.pro.release);
369 padData.
hw_stickX[INPUT_HW_WUPC] = clampf(kpadStatus.pro.leftStick.x, -1.0f, 1.0f);
370 padData.
hw_stickY[INPUT_HW_WUPC] = clampf(kpadStatus.pro.leftStick.y, -1.0f, 1.0f);
371 padData.
hw_substickX[INPUT_HW_WUPC] = clampf(kpadStatus.pro.rightStick.x, -1.0f, 1.0f);
372 padData.
hw_substickY[INPUT_HW_WUPC] = clampf(kpadStatus.pro.rightStick.y, -1.0f, 1.0f);
374 controller[i]->setSideways(
false);
376 else if (kpadStatus.extensionType == WPAD_EXT_CLASSIC || kpadStatus.extensionType == WPAD_EXT_MPLUS_CLASSIC) {
378 padData.
hw_buttons_d[INPUT_HW_CLASSIC] = MapKPADClassicToGeneric(kpadStatus.classic.trigger);
379 padData.
hw_buttons_h[INPUT_HW_CLASSIC] = MapKPADClassicToGeneric(kpadStatus.classic.hold);
380 padData.
hw_buttons_r[INPUT_HW_CLASSIC] = MapKPADClassicToGeneric(kpadStatus.classic.release);
382 padData.
hw_stickX[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.leftStick.x, -1.0f, 1.0f);
383 padData.
hw_stickY[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.leftStick.y, -1.0f, 1.0f);
384 padData.
hw_substickX[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.rightStick.x, -1.0f, 1.0f);
385 padData.
hw_substickY[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.rightStick.y, -1.0f, 1.0f);
386 padData.
hw_triggerL[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.leftTrigger, 0.0f, 1.0f);
387 padData.
hw_triggerR[INPUT_HW_CLASSIC] = clampf(kpadStatus.classic.rightTrigger, 0.0f, 1.0f);
389 controller[i]->setSideways(
false);
393 padData.
hw_buttons_d[INPUT_HW_WIIMOTE] = MapKPADCoreToGeneric(kpadStatus.trigger);
394 padData.
hw_buttons_h[INPUT_HW_WIIMOTE] = MapKPADCoreToGeneric(kpadStatus.hold);
395 padData.
hw_buttons_r[INPUT_HW_WIIMOTE] = MapKPADCoreToGeneric(kpadStatus.release);
400 float rawX = clampf((kpadStatus.pos.x * 0.5f + 0.5f) * screenWidth, 0.0f, screenWidth);
401 float rawY = clampf((kpadStatus.pos.y * 0.5f + 0.5f) * screenHeight, 0.0f, screenHeight);
403 float deltaTime = platform->getVideo()->getDeltaTime();
404 float smoothX, smoothY;
406 if (!irSmoothInit[i]) {
410 irFilterX[i].reset();
411 irFilterY[i].reset();
412 smoothX = irFilterX[i].filter(rawX, deltaTime);
413 smoothY = irFilterY[i].filter(rawY, deltaTime);
414 irSmoothInit[i] =
true;
416 smoothX = irFilterX[i].filter(rawX, deltaTime);
417 smoothY = irFilterY[i].filter(rawY, deltaTime);
420 float cursorAngleDeg = std::atan2(kpadStatus.angle.y, kpadStatus.angle.x) * (180.0f / (float)M_PI);
429 kpadCache[i].validPointer =
true;
430 kpadCache[i].isTouch =
false;
431 kpadCache[i].cursor_x = smoothX;
432 kpadCache[i].cursor_y = smoothY;
433 kpadCache[i].cursor_angle = cursorAngleDeg;
434 }
else if (!kpadStatus.posValid) {
437 irSmoothInit[i] =
false;
440 if (kpadStatus.extensionType == WPAD_EXT_NUNCHUK || kpadStatus.extensionType == WPAD_EXT_MPLUS_NUNCHUK) {
443 padData.
hw_buttons_d[INPUT_HW_NUNCHUK] = MapKPADNunchukToGeneric(kpadStatus.nunchuk.trigger);
444 padData.
hw_buttons_h[INPUT_HW_NUNCHUK] = MapKPADNunchukToGeneric(kpadStatus.nunchuk.hold);
445 padData.
hw_buttons_r[INPUT_HW_NUNCHUK] = MapKPADNunchukToGeneric(kpadStatus.nunchuk.release);
447 padData.
hw_stickX[INPUT_HW_NUNCHUK] = clampf(kpadStatus.nunchuk.stick.x, -1.0f, 1.0f);
448 padData.
hw_stickY[INPUT_HW_NUNCHUK] = clampf(kpadStatus.nunchuk.stick.y, -1.0f, 1.0f);
450 padData.
hw_gforceX[INPUT_HW_NUNCHUK] = kpadStatus.nunchuk.acc.x;
451 padData.
hw_gforceY[INPUT_HW_NUNCHUK] = kpadStatus.nunchuk.acc.y;
452 padData.
hw_gforceZ[INPUT_HW_NUNCHUK] = kpadStatus.nunchuk.acc.z;
454 controller[i]->setSideways(
false);
462 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_WIIMOTE);
463 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_NUNCHUK);
464 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_CLASSIC);
465 CarryForwardHwProfile(kpadCache[i], padData, INPUT_HW_WUPC);
466 }
else if (kpadError == KPAD_ERROR_NO_SAMPLES || kpadError == KPAD_ERROR_BUSY) {
468 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_WIIMOTE);
469 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_NUNCHUK);
470 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_CLASSIC);
471 CarryForwardHwProfile(padData, kpadCache[i], INPUT_HW_WUPC);
473 if (kpadCache[i].hw_connected[INPUT_HW_WIIMOTE]) {
477 if (!padData.
validPointer && kpadCache[i].validPointer) {
480 padData.
cursor_x = kpadCache[i].cursor_x;
481 padData.
cursor_y = kpadCache[i].cursor_y;
488 irSmoothInit[i] =
false;
489 controller[i]->setSideways(
false);
493 for (uint32_t hw = 0; hw < INPUT_HW_MAX; hw++) {
509 if (std::abs(padData.
hw_yaw[hw]) > std::abs(padData.
yaw)) padData.
yaw = padData.
hw_yaw[hw];
513 controller[i]->update(padData, platform->getVideo()->getDeltaTime());
518 static constexpr int kMenuRumbleOnFrames = 2;
519 static constexpr int kMenuRumbleGapFrames = 6;
521 if (rumbleRequest[i]) {
522 rumbleRequest[i] =
false;
523 if (menuRumbleFrames[i] == 0 && menuRumbleGapFrames[i] == 0) {
524 menuRumbleFrames[i] = kMenuRumbleOnFrames;
528 bool menuWantRumble = menuRumbleFrames[i] > 0;
530 if (menuRumbleFrames[i] > 0) {
531 menuRumbleFrames[i]--;
532 if (menuRumbleFrames[i] == 0) menuRumbleGapFrames[i] = kMenuRumbleGapFrames;
533 }
else if (menuRumbleGapFrames[i] > 0) {
534 menuRumbleGapFrames[i]--;
537 bool wantRumble = menuWantRumble || continuousRumble[i];
538 bool motorOn =
false;
542 if (silenceFrames[i] > 0) {
544 continuousRumbleCount[i] = 0;
546 if (wantRumble && allowRumble) {
547 continuousRumbleCount[i]++;
548 if (continuousRumbleCount[i] > 70) {
549 silenceFrames[i] = 5;
550 continuousRumbleCount[i] = 0;
555 continuousRumbleCount[i] = 0;
560 WPADControlMotor((WPADChan)i, motorOn ? TRUE : FALSE);
566 VPADControlMotor(VPAD_CHAN_0, vpadRumblePattern,
sizeof(vpadRumblePattern));
568 VPADControlMotor(VPAD_CHAN_0, vpadMenuRumblePattern,
sizeof(vpadMenuRumblePattern));
571 VPADStopMotor(VPAD_CHAN_0);