mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-25 15:05:06 -04:00
4e8adeef59
* Jut cleanup work * data section fix * match the last of JUtility * added more helpful comment * Add missed null terminator * do while -> while loop * replace more do whiles * Fix wii regression * Add suggestions * fix null check --------- Co-authored-by: roeming <roeming@users.noreply.github.com>
613 lines
17 KiB
C++
613 lines
17 KiB
C++
#include "JSystem/JSystem.h" // IWYU pragma: keep
|
|
|
|
#include "JSystem/JUtility/JUTGamePad.h"
|
|
#include <cmath>
|
|
|
|
u32 JUTGamePad::CRumble::sChannelMask[4] = {
|
|
PAD_CHAN0_BIT,
|
|
PAD_CHAN1_BIT,
|
|
PAD_CHAN2_BIT,
|
|
PAD_CHAN3_BIT,
|
|
};
|
|
|
|
static u32 channel_mask[4] = {PAD_CHAN0_BIT, PAD_CHAN1_BIT, PAD_CHAN2_BIT, PAD_CHAN3_BIT};
|
|
|
|
JSUList<JUTGamePad> JUTGamePad::mPadList(false);
|
|
|
|
bool JUTGamePad::mListInitialized;
|
|
|
|
u8 JUTGamePad::mPadAssign[4];
|
|
|
|
JUTGamePad::JUTGamePad(EPadPort port) : mRumble(this), mLink(this) {
|
|
mPortNum = port;
|
|
if (mPortNum >= 0) {
|
|
mPadAssign[port]++;
|
|
}
|
|
|
|
initList();
|
|
mPadList.append(&mLink);
|
|
update();
|
|
mPadRecord = 0;
|
|
mPadReplay = 0;
|
|
clear();
|
|
}
|
|
|
|
JUTGamePad::~JUTGamePad() {
|
|
if (mPortNum >= 0) {
|
|
mPadAssign[mPortNum]--;
|
|
mPortNum = EPortInvalid;
|
|
}
|
|
|
|
mPadList.remove(&mLink);
|
|
}
|
|
|
|
void JUTGamePad::initList() {
|
|
if (!mListInitialized) {
|
|
mPadList.initiate();
|
|
mListInitialized = true;
|
|
}
|
|
}
|
|
|
|
u32 JUTGamePad::sSuppressPadReset;
|
|
|
|
u8 data_8074CFA4_debug;
|
|
|
|
s32 JUTGamePad::sAnalogMode;
|
|
|
|
BOOL JUTGamePad::init() {
|
|
PADSetSpec(PAD_SPEC_5);
|
|
setAnalogMode(3);
|
|
return PADInit();
|
|
}
|
|
|
|
void JUTGamePad::clear() {
|
|
mButtonReset.mReset = false;
|
|
field_0xa8 = 1;
|
|
}
|
|
|
|
PADStatus JUTGamePad::mPadStatus[4];
|
|
|
|
JUTGamePad::CButton JUTGamePad::mPadButton[4];
|
|
|
|
JUTGamePad::CStick JUTGamePad::mPadMStick[4];
|
|
|
|
JUTGamePad::CStick JUTGamePad::mPadSStick[4];
|
|
|
|
JUTGamePad::EStickMode JUTGamePad::sStickMode = EStickMode1;
|
|
|
|
int JUTGamePad::sClampMode = EClampStick;
|
|
|
|
u32 JUTGamePad::sRumbleSupported;
|
|
|
|
u32 JUTGamePad::read() {
|
|
sRumbleSupported = PADRead(mPadStatus);
|
|
|
|
switch (sClampMode) {
|
|
case EClampStick:
|
|
PADClamp(mPadStatus);
|
|
break;
|
|
case EClampCircle:
|
|
PADClampCircle(mPadStatus);
|
|
break;
|
|
}
|
|
|
|
u32 bittest;
|
|
u32 reset_mask = 0;
|
|
for (int i = 0; i < 4; i++) {
|
|
bittest = PAD_CHAN0_BIT >> i;
|
|
|
|
if (mPadStatus[i].err == 0) {
|
|
PADStatus* pad_status = &mPadStatus[i];
|
|
u32 stick_status;
|
|
stick_status = mPadMStick[i].update(pad_status->stickX, pad_status->stickY, sStickMode, EMainStick, mPadButton[i].mButton) << 0x18;
|
|
stick_status |= (mPadSStick[i].update(pad_status->substickX, pad_status->substickY, sStickMode, ESubStick, mPadButton[i].mButton) << 0x10);
|
|
|
|
mPadButton[i].update(pad_status, stick_status);
|
|
} else if (mPadStatus[i].err == -1) {
|
|
mPadMStick[i].update(0, 0, sStickMode, EMainStick, 0);
|
|
mPadSStick[i].update(0, 0, sStickMode, ESubStick, 0);
|
|
mPadButton[i].update(NULL, 0);
|
|
|
|
if (!(sSuppressPadReset & bittest)) {
|
|
reset_mask |= bittest;
|
|
}
|
|
} else {
|
|
if (data_8074CFA4_debug) {
|
|
OS_REPORT("game pad read error (%d)\n", mPadStatus[i].err);
|
|
}
|
|
mPadButton[i].mTrigger = 0;
|
|
mPadButton[i].mRelease = 0;
|
|
mPadButton[i].mRepeat = 0;
|
|
}
|
|
}
|
|
|
|
for (JSUListIterator<JUTGamePad> pad(mPadList.getFirst()); pad != mPadList.getEnd(); ++pad) {
|
|
if (pad->getPadReplay() != NULL && pad->getPadReplay()->isActive()) {
|
|
PADStatus status;
|
|
pad->getPadReplay()->getStatus(&status);
|
|
|
|
u32 stick_status;
|
|
stick_status = pad->mMainStick.update(status.stickX, status.stickY, sStickMode,
|
|
EMainStick, pad->mButton.mButton) << 0x18;
|
|
stick_status |= pad->mSubStick.update(status.substickX, status.substickY, sStickMode,
|
|
ESubStick, pad->mButton.mButton) << 0x10;
|
|
|
|
pad->mButton.update(&status, stick_status);
|
|
} else {
|
|
if (pad->mPortNum == EPortInvalid) {
|
|
pad->assign();
|
|
}
|
|
pad->update();
|
|
}
|
|
|
|
if (pad->getPadRecord() != NULL && pad->getPadRecord()->isActive()) {
|
|
if (pad->mPortNum >= 0) {
|
|
int port = pad->mPortNum;
|
|
if (mPadStatus[port].err == 0) {
|
|
pad->getPadRecord()->write(&mPadStatus[port]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (reset_mask != 0) {
|
|
PADReset(reset_mask);
|
|
}
|
|
|
|
checkResetSwitch();
|
|
return sRumbleSupported;
|
|
}
|
|
|
|
void JUTGamePad::assign() {
|
|
for (int i = 0; i < 4; i++) {
|
|
if (mPadStatus[i].err == 0 && mPadAssign[i] == 0) {
|
|
mPortNum = i;
|
|
mPadAssign[i] = 1;
|
|
mPadButton[i].setRepeat(mButton.mRepeatMask, mButton.mRepeatDelay, mButton.mRepeatRate);
|
|
mRumble.clear(this);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
u8 JUTGamePad::CRumble::mStatus[4];
|
|
|
|
u32 JUTGamePad::CRumble::mEnabled;
|
|
|
|
callbackFn JUTGamePad::C3ButtonReset::sCallback;
|
|
|
|
void* JUTGamePad::C3ButtonReset::sCallbackArg;
|
|
|
|
OSTime JUTGamePad::C3ButtonReset::sThreshold = (OSTime)(OS_TIMER_CLOCK / 60) * 30;
|
|
|
|
bool JUTGamePad::C3ButtonReset::sResetSwitchPushing;
|
|
|
|
bool JUTGamePad::C3ButtonReset::sResetOccurred;
|
|
|
|
s32 JUTGamePad::C3ButtonReset::sResetOccurredPort;
|
|
|
|
void JUTGamePad::checkResetCallback(OSTime holdTime) {
|
|
if (holdTime >= JUTGamePad::C3ButtonReset::sThreshold) {
|
|
JUTGamePad::C3ButtonReset::sResetOccurred = true;
|
|
JUTGamePad::C3ButtonReset::sResetOccurredPort = mPortNum;
|
|
|
|
if (JUTGamePad::C3ButtonReset::sCallback != NULL) {
|
|
JUTGamePad::C3ButtonReset::sCallback(mPortNum, JUTGamePad::C3ButtonReset::sCallbackArg);
|
|
}
|
|
}
|
|
}
|
|
|
|
f32 JUTGamePad::CStick::sPressPoint = 0.5f;
|
|
|
|
f32 JUTGamePad::CStick::sReleasePoint = 0.25f;
|
|
|
|
u32 JUTGamePad::C3ButtonReset::sResetPattern = PAD_BUTTON_START | PAD_BUTTON_X | PAD_BUTTON_B;
|
|
|
|
u32 JUTGamePad::C3ButtonReset::sResetMaskPattern = 0x0000FFFF;
|
|
|
|
void JUTGamePad::update() {
|
|
if (mPortNum != EPortInvalid) {
|
|
if (mPortNum >= 0 && mPortNum < 4) {
|
|
mButton = mPadButton[mPortNum];
|
|
mMainStick = mPadMStick[mPortNum];
|
|
mSubStick = mPadSStick[mPortNum];
|
|
mErrorStatus = mPadStatus[mPortNum].err;
|
|
}
|
|
|
|
if (field_0xa8 == 0 || C3ButtonReset::sResetPattern != (mButton.mButton & C3ButtonReset::sResetMaskPattern)) {
|
|
mButtonReset.mReset = false;
|
|
} else if (!JUTGamePad::C3ButtonReset::sResetOccurred) {
|
|
if (mButtonReset.mReset == true) {
|
|
OSTime hold_time = OSGetTime() - mResetHoldStartTime;
|
|
checkResetCallback(hold_time);
|
|
} else {
|
|
mButtonReset.mReset = true;
|
|
mResetHoldStartTime = OSGetTime();
|
|
}
|
|
}
|
|
|
|
for (JSUListIterator<JUTGamePadLongPress> pad(JUTGamePadLongPress::sPatternList.getFirst()); pad != JUTGamePadLongPress::sPatternList.getEnd(); ++pad) {
|
|
if (pad->isValid()) {
|
|
if (mPortNum >= 0 && mPortNum < 4) {
|
|
if ((mButton.mButton & pad->getMaskPattern()) == pad->getPattern()) {
|
|
if (pad->mLongPressStatus[mPortNum] == true) {
|
|
OSTime hold_time = OSGetTime() - pad->mStartHoldTime[mPortNum];
|
|
pad->checkCallback(mPortNum, hold_time);
|
|
} else {
|
|
pad->mLongPressStatus[mPortNum] = true;
|
|
pad->mStartHoldTime[mPortNum] = OSGetTime();
|
|
}
|
|
} else {
|
|
pad->mLongPressStatus[mPortNum] = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mPortNum >= 0 && mPortNum < 4) {
|
|
mRumble.update(mPortNum);
|
|
}
|
|
}
|
|
}
|
|
|
|
JSUList<JUTGamePadLongPress> JUTGamePadLongPress::sPatternList(false);
|
|
|
|
void JUTGamePad::checkResetSwitch() {
|
|
if (!JUTGamePad::C3ButtonReset::sResetOccurred) {
|
|
int unused;
|
|
if (OSGetResetSwitchState()) {
|
|
C3ButtonReset::sResetSwitchPushing = true;
|
|
} else {
|
|
if (C3ButtonReset::sResetSwitchPushing == true) {
|
|
C3ButtonReset::sResetOccurred = true;
|
|
C3ButtonReset::sResetOccurredPort = EPortInvalid;
|
|
|
|
if (C3ButtonReset::sCallback != NULL) {
|
|
C3ButtonReset::sCallback(EPortInvalid, C3ButtonReset::sCallbackArg);
|
|
}
|
|
}
|
|
C3ButtonReset::sResetSwitchPushing = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::clearForReset() {
|
|
CRumble::setEnabled(0);
|
|
recalibrate(PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT);
|
|
}
|
|
|
|
void JUTGamePad::CButton::clear() {
|
|
mButton = 0;
|
|
mTrigger = 0;
|
|
mRelease = 0;
|
|
mRepeat = 0;
|
|
mAnalogA = 0;
|
|
mAnalogB = 0;
|
|
mAnalogL = 0;
|
|
mAnalogR = 0;
|
|
mRepeatCount = 0;
|
|
mRepeatStart = 0;
|
|
mRepeatMask = 0;
|
|
mRepeatDelay = 0;
|
|
mRepeatRate = 0;
|
|
}
|
|
|
|
void JUTGamePad::CButton::update(const PADStatus* padStatus, u32 stickStatus) {
|
|
u32 buttons = stickStatus | (padStatus != NULL ? padStatus->button : 0);
|
|
mRepeat = 0;
|
|
|
|
if (mRepeatDelay != 0 && mRepeatMask != 0) {
|
|
u32 repeatButton = buttons & mRepeatMask;
|
|
mRepeat = 0;
|
|
|
|
if (repeatButton == 0) {
|
|
mRepeatStart = 0;
|
|
mRepeatCount = 0;
|
|
} else if (mRepeatStart == repeatButton) {
|
|
mRepeatCount++;
|
|
|
|
if (mRepeatCount == mRepeatDelay ||
|
|
(mRepeatCount > mRepeatDelay && (mRepeatCount - mRepeatDelay) % mRepeatRate == 0))
|
|
{
|
|
mRepeat = repeatButton;
|
|
}
|
|
} else {
|
|
mRepeat = repeatButton & (mRepeatStart ^ 0xFFFFFFFF);
|
|
mRepeatStart = repeatButton;
|
|
mRepeatCount = 0;
|
|
}
|
|
}
|
|
|
|
mTrigger = buttons & (buttons ^ mButton);
|
|
mRelease = mButton & (buttons ^ mButton);
|
|
mButton = buttons;
|
|
mRepeat |= (mRepeatMask ^ 0xFFFFFFFF) & mTrigger;
|
|
|
|
if (padStatus != NULL) {
|
|
mAnalogA = padStatus->analogA;
|
|
mAnalogB = padStatus->analogB;
|
|
mAnalogL = padStatus->triggerLeft;
|
|
mAnalogR = padStatus->triggerRight;
|
|
} else {
|
|
mAnalogA = 0;
|
|
mAnalogB = 0;
|
|
mAnalogL = 0;
|
|
mAnalogR = 0;
|
|
}
|
|
|
|
mAnalogLf = (s32)mAnalogL / 150.0f;
|
|
mAnalogRf = (s32)mAnalogR / 150.0f;
|
|
}
|
|
|
|
void JUTGamePad::CStick::clear() {
|
|
mPosX = 0.0f;
|
|
mPosY = 0.0f;
|
|
mValue = 0.0f;
|
|
mAngle = 0;
|
|
}
|
|
|
|
u32 JUTGamePad::CStick::update(s8 x, s8 y, JUTGamePad::EStickMode mode,
|
|
JUTGamePad::EWhichStick stick, u32 buttons) {
|
|
s32 clamp;
|
|
switch (getClampMode()) {
|
|
case EClampStick:
|
|
clamp = stick == EMainStick ? 54 : 42;
|
|
break;
|
|
case EClampCircle:
|
|
clamp = stick == EMainStick ? 38 : 29;
|
|
break;
|
|
default:
|
|
clamp = stick == EMainStick ? 69 : 57;
|
|
break;
|
|
}
|
|
|
|
mRawX = x;
|
|
mRawY = y;
|
|
mPosX = (f32)x / (f32)clamp;
|
|
mPosY = (f32)y / (f32)clamp;
|
|
mValue = sqrtf((mPosX * mPosX) + (mPosY * mPosY));
|
|
|
|
if (mValue > 1.0f) {
|
|
if (mode == EStickMode1) {
|
|
mPosX /= mValue;
|
|
mPosY /= mValue;
|
|
}
|
|
mValue = 1.0f;
|
|
}
|
|
|
|
if (mValue > 0.0f) {
|
|
if (mPosY == 0.0f) {
|
|
if (mPosX > 0.0f) {
|
|
mAngle = 0x4000;
|
|
} else {
|
|
mAngle = -0x4000;
|
|
}
|
|
} else {
|
|
mAngle = (0x8000 / 3.1415926f) * atan2f(mPosX, -mPosY);
|
|
}
|
|
}
|
|
|
|
return getButton(buttons >> (stick == EMainStick ? 0x18 : 0x10));
|
|
}
|
|
|
|
u32 JUTGamePad::CStick::getButton(u32 buttons) {
|
|
u32 button = buttons & (PAD_BUTTON_UP | PAD_BUTTON_DOWN | PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT);
|
|
|
|
if (-sReleasePoint < mPosX && mPosX < sReleasePoint) {
|
|
button &= ~(PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT);
|
|
} else if (mPosX <= -sPressPoint) {
|
|
button &= ~PAD_BUTTON_RIGHT;
|
|
button |= PAD_BUTTON_LEFT;
|
|
} else if (mPosX >= sPressPoint) {
|
|
button &= ~PAD_BUTTON_LEFT;
|
|
button |= PAD_BUTTON_RIGHT;
|
|
}
|
|
|
|
if (-sReleasePoint < mPosY && mPosY < sReleasePoint) {
|
|
button &= ~(PAD_BUTTON_UP | PAD_BUTTON_DOWN);
|
|
} else if (mPosY <= -sPressPoint) {
|
|
button &= ~PAD_BUTTON_UP;
|
|
button |= PAD_BUTTON_DOWN;
|
|
} else if (mPosY >= sPressPoint) {
|
|
button &= ~PAD_BUTTON_DOWN;
|
|
button |= PAD_BUTTON_UP;
|
|
}
|
|
|
|
return button;
|
|
}
|
|
|
|
void JUTGamePad::CRumble::clear() {
|
|
mFrame = 0;
|
|
mLength = 0;
|
|
mPattern = NULL;
|
|
mFrameCount = 0;
|
|
field_0x10 = 0;
|
|
mEnabled = (PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT);
|
|
}
|
|
|
|
void JUTGamePad::CRumble::clear(JUTGamePad* pad) {
|
|
if (pad->getPortNum() >= 0 && pad->getPortNum() < 4) {
|
|
mStatus[pad->getPortNum()] = false;
|
|
pad->stopMotorHard();
|
|
}
|
|
clear();
|
|
}
|
|
|
|
void JUTGamePad::CRumble::startMotor(int port) {
|
|
if (isEnabledPort(port)) {
|
|
PADControlMotor(port, PAD_MOTOR_RUMBLE);
|
|
mStatus[port] = true;
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::CRumble::stopMotor(int port, bool hard_stop) {
|
|
u8 command;
|
|
if (isEnabledPort(port)) {
|
|
if (hard_stop) {
|
|
command = PAD_MOTOR_STOP_HARD;
|
|
} else {
|
|
command = PAD_MOTOR_STOP;
|
|
}
|
|
PADControlMotor(port, command);
|
|
mStatus[port] = false;
|
|
}
|
|
}
|
|
|
|
static bool getNumBit(u8* pattern, int index) {
|
|
u8 bit = pattern[index >> 3] & (0x80 >> (index & 7));
|
|
return bit != 0;
|
|
}
|
|
|
|
void JUTGamePad::CRumble::update(s16 port) {
|
|
if (isEnabledPort(port) == false) {
|
|
mFrame = 0;
|
|
mLength = 0;
|
|
mPattern = NULL;
|
|
mFrameCount = 0;
|
|
field_0x10 = NULL;
|
|
}
|
|
|
|
if (mLength == 0) {
|
|
return;
|
|
}
|
|
|
|
if (mFrame >= mLength) {
|
|
stopMotorHard(port);
|
|
mLength = 0;
|
|
} else if (mFrameCount == 0) {
|
|
if (mStatus[port] == false) {
|
|
startMotor(port);
|
|
}
|
|
return;
|
|
} else {
|
|
bool enabled = getNumBit(mPattern, mFrame % mFrameCount);
|
|
u32 status = mStatus[port] != false;
|
|
|
|
if (enabled && !status) {
|
|
startMotor(port);
|
|
} else if (!enabled) {
|
|
bool hard_stop = false;
|
|
if (field_0x10) {
|
|
hard_stop = getNumBit(field_0x10, mFrame % mFrameCount);
|
|
}
|
|
|
|
if (status) {
|
|
stopMotor(port, hard_stop);
|
|
} else if (hard_stop) {
|
|
stopMotor(port, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
mFrame++;
|
|
}
|
|
|
|
void JUTGamePad::CRumble::triggerPatternedRumble(u32 length) {
|
|
if (mPattern != NULL && mFrameCount != 0) {
|
|
mLength = length;
|
|
mFrame = 0;
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::CRumble::startPatternedRumble(void* data, JUTGamePad::CRumble::ERumble rumble,
|
|
u32 length) {
|
|
mFrameCount = ((*(u8*)data) << 8) + *((u8*)data + 1);
|
|
mPattern = (u8*)data + 2;
|
|
|
|
switch (rumble) {
|
|
case JUTGamePad::CRumble::VAL_0:
|
|
triggerPatternedRumble(mFrameCount);
|
|
break;
|
|
case JUTGamePad::CRumble::VAL_1:
|
|
triggerPatternedRumble(-1);
|
|
break;
|
|
case JUTGamePad::CRumble::VAL_2:
|
|
triggerPatternedRumble(length);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::CRumble::stopPatternedRumble(s16 port) {
|
|
JUT_ASSERT(1341, 0 <= port && port < 4);
|
|
mLength = 0;
|
|
stopMotorHard(port);
|
|
}
|
|
|
|
void JUTGamePad::CRumble::stopPatternedRumbleAtThePeriod() {
|
|
u32 r31 = mFrame % mFrameCount;
|
|
mLength = (mFrame + mFrameCount - 1) % mFrameCount;
|
|
}
|
|
|
|
JUTGamePad* JUTGamePad::getGamePad(int port) {
|
|
for (JSUListIterator<JUTGamePad> pad(mPadList.getFirst()); pad != mPadList.getEnd(); ++pad) {
|
|
if (port == pad->mPortNum) {
|
|
return pad.getObject();
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void JUTGamePad::CRumble::setEnabled(u32 mask) {
|
|
mask = (mask & (PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT));
|
|
for (int i = 0; i < 4; i++) {
|
|
if ((mEnabled & channel_mask[i]) == 0) {
|
|
if (mStatus[i]) {
|
|
stopMotor(i);
|
|
}
|
|
|
|
JUTGamePad* pad = getGamePad(i);
|
|
if (pad != NULL) {
|
|
pad->stopMotorWaveHard();
|
|
}
|
|
}
|
|
}
|
|
|
|
mEnabled = mask;
|
|
}
|
|
|
|
void JUTGamePad::CButton::setRepeat(u32 mask, u32 delay, u32 rate) {
|
|
mRepeatStart = 0;
|
|
mRepeatCount = 0;
|
|
mRepeatMask = mask;
|
|
mRepeatDelay = delay;
|
|
mRepeatRate = rate;
|
|
}
|
|
|
|
void JUTGamePad::setButtonRepeat(u32 mask, u32 delay, u32 rate) {
|
|
mButton.setRepeat(mask, delay, rate);
|
|
if (mPortNum >= 0) {
|
|
mPadButton[mPortNum].setRepeat(mask, delay, rate);
|
|
}
|
|
}
|
|
|
|
bool JUTGamePad::recalibrate(u32 mask) {
|
|
for (int i = 0; i < 4; i++) {
|
|
if (sSuppressPadReset & channel_mask[i]) {
|
|
mask &= channel_mask[i] ^ 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
BOOL result = PADRecalibrate(mask);
|
|
return result;
|
|
}
|
|
|
|
void JUTGamePadLongPress::checkCallback(int port, u32 hold_time) {
|
|
if (port < 0) {
|
|
return;
|
|
}
|
|
|
|
JUT_ASSERT(1673, 0 <= port && port < 4);
|
|
|
|
if (hold_time < mThreshold) {
|
|
return;
|
|
}
|
|
|
|
field_0x11 = true;
|
|
field_0x48[port] = true;
|
|
|
|
if (mCallback != NULL) {
|
|
mCallback(port, this, field_0x50);
|
|
}
|
|
}
|