mirror of
https://github.com/zeldaret/ss
synced 2026-05-23 15:01:38 -04:00
1446 lines
39 KiB
C++
1446 lines
39 KiB
C++
#include "d/d_pad.h"
|
|
|
|
#include "c/c_math.h"
|
|
#include "common.h"
|
|
#include "d/a/d_a_player.h"
|
|
#include "d/col/c/c_m3d_g_aab.h"
|
|
#include "d/d_cs_game.h"
|
|
#include "d/d_gfx.h"
|
|
#include "d/d_hbm.h"
|
|
#include "d/d_pad_manager.h"
|
|
#include "d/d_pad_nav.h"
|
|
#include "d/d_reset.h"
|
|
#include "d/d_sc_game.h"
|
|
#include "d/lyt/d_lyt_control_game.h"
|
|
#include "d/lyt/d_lyt_map.h"
|
|
#include "d/lyt/meter/d_lyt_meter.h"
|
|
#include "d/snd/d_snd_player_mgr.h"
|
|
#include "d/snd/d_snd_small_effect_mgr.h"
|
|
#include "d/snd/d_snd_wzsound.h"
|
|
#include "egg/core/eggController.h"
|
|
#include "egg/core/eggHeap.h"
|
|
#include "egg/math/eggMath.h"
|
|
#include "egg/math/eggVector.h"
|
|
#include "m/m_angle.h"
|
|
#include "m/m_mtx.h"
|
|
#include "m/m_pad.h"
|
|
#include "m/m_vec.h"
|
|
#include "nw4r/math/math_types.h"
|
|
#include "rvl/KPAD/KPAD.h"
|
|
#include "rvl/MTX/mtx.h"
|
|
#include "rvl/MTX/mtxvec.h"
|
|
#include "rvl/MTX/vec.h"
|
|
#include "rvl/WPAD/WPAD.h"
|
|
|
|
#include <cmath>
|
|
|
|
namespace dPad {
|
|
|
|
ex_c ex_c::m_ex[4];
|
|
ex_c *ex_c::m_current_ex = ex_c::m_ex;
|
|
|
|
WPADInfo ex_c::m_info[2][4];
|
|
|
|
bool ex_c::m_connected[4];
|
|
|
|
// TODO - the SDK decomp uses WPAD error codes for this
|
|
// callback, but I think they have different semantics.
|
|
// Refer to https://github.com/doldecomp/sdk_2009-12-11/blob/main/source/kpad/KPAD.c#L3607-L3639
|
|
// for logic.
|
|
void control_mpls_callback(s32 idx, s32 code) {
|
|
switch (code) {
|
|
// Called first
|
|
case 0: {
|
|
ex_c::on_0x54(idx);
|
|
break;
|
|
}
|
|
// Called when Mpls configuration failed - not actually reached?
|
|
case -1: {
|
|
ex_c::on_0x55(idx);
|
|
break;
|
|
}
|
|
// Called when Mpls + Nunchuk configuration failed -- called a bunch of times
|
|
case -2: {
|
|
ex_c::on_0x56(idx);
|
|
break;
|
|
}
|
|
// not sure - called last
|
|
case 1: {
|
|
ex_c::on_0x57(idx);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isDeviceTypeMpls(u32 type) {
|
|
switch (type) {
|
|
case WPAD_DEV_MOTION_PLUS:
|
|
case WPAD_DEV_MPLS_PT_FS:
|
|
case WPAD_DEV_MPLS_PT_CLASSIC:
|
|
case WPAD_DEV_MPLS_PT_UNKNOWN: return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
void initMpls(s32 chan) {
|
|
KPADResetMpls(chan);
|
|
KPADDisableMplsZeroPlay(chan);
|
|
KPADSetMplsZeroPlayParam(chan, 0.005f);
|
|
KPADSetMplsZeroDriftMode(chan, 2);
|
|
disableMplsDirRevise(chan);
|
|
KPADSetMplsDirReviseParam(chan, 0.35f);
|
|
KPADEnableMplsAccRevise(chan);
|
|
KPADSetMplsAccReviseParam(chan, 0.03f, 0.4f);
|
|
KPADEnableMplsDpdRevise(chan);
|
|
KPADSetMplsDpdReviseParam(chan, 0.5f);
|
|
}
|
|
|
|
extern "C" void fn_80194080();
|
|
void create() {
|
|
mPad::create();
|
|
|
|
KPADSetBtnRepeat(mPad::getCore(0)->getChannelID(), 0.5f, 0.1f);
|
|
ex_c::resetInfo();
|
|
|
|
KPADSetMplsWorkarea(new (0x20) u8[KPADGetMplsWorkSize()]);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
ex_c::m_ex[i].mMotion.init();
|
|
KPADSetReviseMode(i, 1);
|
|
KPADSetControlMplsCallback(i, control_mpls_callback);
|
|
ex_c::m_ex[i].gotoStateWaitForConnect(i);
|
|
}
|
|
fn_80194080();
|
|
}
|
|
|
|
void setMpls(bool enable, s32 chan) {
|
|
if (enable) {
|
|
if (ex_c::m_ex[chan].mMplsEnabled == false) {
|
|
ex_c::m_ex[chan].mMplsEnabled = true;
|
|
// WPAD_DEV_MODE_MPLS_PT_FS
|
|
// i.e. Skyward Sword wants both MotionPlus and Nunchuk
|
|
KPADEnableMpls(chan, 5);
|
|
initMpls(chan);
|
|
}
|
|
} else {
|
|
if (ex_c::m_ex[chan].mMplsEnabled) {
|
|
ex_c::m_ex[chan].mMplsEnabled = false;
|
|
KPADDisableMpls(chan);
|
|
}
|
|
}
|
|
}
|
|
|
|
void convertDpdPosToScreenPos(mVec2_c &in, mVec2_c &out) {
|
|
out.x = dGfx_c::getWidth4x3F() * 0.5f * (1.f + in.x) + dGfx_c::getWidth4x3LeftF();
|
|
out.y = dGfx_c::getCurrentScreenHeightF() * -0.5f * (1.f + in.y) + dGfx_c::getCurrentScreenTopF();
|
|
}
|
|
|
|
void beginPad_BR() {
|
|
mPad::beginPad();
|
|
|
|
if (mPad::getCore(0)->isConnected()) {
|
|
WPADSetAcceptConnection(0);
|
|
} else {
|
|
WPADSetAcceptConnection(1);
|
|
}
|
|
|
|
// Forces only first controller to be active
|
|
for (int i = 1; i < 4; ++i) {
|
|
if (mPad::getCore(i)->isConnected()) {
|
|
WPADDisconnect(i);
|
|
}
|
|
}
|
|
|
|
dPad::ex_c &ex = ex_c::m_ex[0];
|
|
ex.fn_800572A0(0);
|
|
if (mPad::getCore(0)->isConnected()) {
|
|
ex.getUnifiedWpadStatus(0);
|
|
ex.fn_80059300(0);
|
|
ex.fn_80056AF0(0);
|
|
ex.fn_80056B90(0);
|
|
ex.fn_80056CE0(0);
|
|
ex.workMplsCalibration(0);
|
|
bool isDpdReviseEnabled = KPADIsEnableMplsDpdRevise(0) >= 0.f;
|
|
if (ex.field_0x22CE) {
|
|
if (isDpdReviseEnabled) {
|
|
KPADDisableMplsDpdRevise(0);
|
|
}
|
|
} else {
|
|
if (!isDpdReviseEnabled) {
|
|
KPADEnableMplsDpdRevise(0);
|
|
}
|
|
}
|
|
ex.field_0x22CE = false;
|
|
|
|
const dAcPy_c *player = dAcPy_c::GetLink();
|
|
if (player && player->isAttacking()) {
|
|
mMtx_c m;
|
|
mVec3_c baseX;
|
|
mVec3_c baseY;
|
|
mVec3_c baseZ;
|
|
KPADVec kpadvec;
|
|
m.XrotS(mAng::deg2short(-30.f));
|
|
baseZ.z = m.m[2][2];
|
|
baseZ.y = m.m[1][2];
|
|
baseZ.x = m.m[0][2];
|
|
kpadvec[2].x = baseZ.x;
|
|
kpadvec[2].y = baseZ.y;
|
|
kpadvec[2].z = baseZ.z;
|
|
|
|
VECCrossProduct(ex_c::m_ex[0].mMPLS.mY, baseZ, baseX);
|
|
if (VECMag(baseX) > 0.05f) {
|
|
baseX.normalize();
|
|
kpadvec[0].z = baseX.z;
|
|
kpadvec[0].y = baseX.y;
|
|
kpadvec[0].x = baseX.x;
|
|
} else {
|
|
baseX = baseZ;
|
|
kpadvec[0].z = baseX.z;
|
|
kpadvec[0].y = baseX.y;
|
|
kpadvec[0].x = baseX.x;
|
|
}
|
|
|
|
VECCrossProduct(baseZ, baseX, baseY);
|
|
if (VECMag(baseY) > 0.05f) {
|
|
baseY.normalize();
|
|
kpadvec[1].z = baseY.z;
|
|
kpadvec[1].y = baseY.y;
|
|
kpadvec[1].x = baseY.x;
|
|
} else {
|
|
baseY = baseZ;
|
|
kpadvec[1].z = baseY.z;
|
|
kpadvec[1].y = baseY.y;
|
|
kpadvec[1].x = baseY.x;
|
|
}
|
|
|
|
KPADSetMplsDirReviseBase(0, kpadvec);
|
|
enableMplsDirRevise(0);
|
|
} else {
|
|
disableMplsDirRevise(0);
|
|
}
|
|
|
|
KPADEnableMplsAccRevise(0);
|
|
KPADSetMplsAccReviseParam(0, 0.03f, 0.4f);
|
|
|
|
if ((dCsGame_c::GetInstance() != nullptr && dCsGame_c::GetInstance()->shouldDraw() && !ex.field_0x22D0) ||
|
|
(dAcPy_c::GetLink() != nullptr &&
|
|
dAcPy_c::GetLink()->checkActionFlagsCont(0x400 | 0x100 | 0x80 | 0x40 | 0x10 | 0x4 | 0x2 | 0x1) &&
|
|
!dAcPy_c::GetLink()->vt_0x1C0() && !dLytMeter_c::GetMain()->getField_0x1377F()) ||
|
|
ex.field_0x22CF) {
|
|
if (dLytControlGame_c::getInstance() && dLytControlGame_c::getInstance()->isStateNormal()) {
|
|
if (!(dPadManager_c::GetInstance() && dPadManager_c::GetInstance()->getField_0x25())) {
|
|
KPADDisableMplsDpdRevise(0);
|
|
KPADDisableMplsAccRevise(0);
|
|
}
|
|
}
|
|
KPADDisableMplsDirRevise(0);
|
|
}
|
|
if (ex.mIsCalibrating || ex.field_0x48 != 0) {
|
|
KPADEnableMplsAccRevise(0);
|
|
KPADSetMplsAccReviseParam(0, 1.f, 0.6f);
|
|
if (--ex.field_0x48 < 0) {
|
|
ex.field_0x48 = 0;
|
|
}
|
|
}
|
|
|
|
ex.field_0x22CF = false;
|
|
ex.mFSStick.x = mPad::getCore(0)->getFreeStickX();
|
|
ex.mFSStick.y = mPad::getCore(0)->getFreeStickY();
|
|
ex.mFSStickDistance = ex.mFSStick.length();
|
|
ex.mFSStickAngle = -ex.mFSStick.ang();
|
|
|
|
ex.calcFSStickDirMask();
|
|
|
|
bool isMpls = mPad::isMpls(0) || mPad::isMplsPtFS(0);
|
|
if (isMpls) {
|
|
ex.mMPLSVelocity.copyFrom(&mPad::getCore(0)->getCoreStatus()->mpls_rot);
|
|
ex.mMPLS.mX.copyFrom(&mPad::getCore(0)->getCoreStatus()->mpls_basis_x);
|
|
ex.mMPLS.mY.copyFrom(&mPad::getCore(0)->getCoreStatus()->mpls_basis_y);
|
|
ex.mMPLS.mZ.copyFrom(&mPad::getCore(0)->getCoreStatus()->mpls_basis_z);
|
|
} else {
|
|
ex.mMPLSVelocity.set(0.f, 0.f, 0.f);
|
|
ex.mMPLS.mX = mVec3_c::Ex;
|
|
ex.mMPLS.mY = mVec3_c::Ey;
|
|
ex.mMPLS.mZ = mVec3_c::Ez;
|
|
}
|
|
|
|
ex.fn_80056790(0);
|
|
|
|
if (ex.field_0x50) {
|
|
ex.mDpdPos = ex.field_0x5C;
|
|
} else {
|
|
if (mPad::getCore(0)->getDpdValidFlag() > 0) {
|
|
ex.mDpdPos = mPad::getDpdRawPos(0);
|
|
} else {
|
|
ex.mDpdPos.set(-2.f, -2.f);
|
|
}
|
|
}
|
|
convertDpdPosToScreenPos(ex.mDpdPos, ex.mDpdPosScreen);
|
|
ex.updateStatus(0);
|
|
}
|
|
|
|
ex_c::m_current_ex = &ex_c::m_ex[mPad::getCurrentCoreID()];
|
|
|
|
if (dReset::Manage_c::GetInstance()->isSoftResetOrSafetyWait()) {
|
|
for (int i = 0; i < 4; ++i) {
|
|
EGG::CoreController *core = mPad::g_core[i];
|
|
core->getCoreStatus()->hold &= EGG::cCORE_BUTTON_HOME;
|
|
core->getCoreStatus()->trig &= EGG::cCORE_BUTTON_HOME;
|
|
core->getCoreStatus()->release &= EGG::cCORE_BUTTON_HOME;
|
|
}
|
|
}
|
|
dPadNav::calc();
|
|
}
|
|
|
|
void endPad_BR() {
|
|
mPad::endPad();
|
|
}
|
|
|
|
void connectCallback(const EGG::CoreControllerConnectArg &rArg) {
|
|
switch (rArg.result) {
|
|
case WPAD_ERR_OK: {
|
|
dSndPlayerMgr_c::GetInstance()->setupRmtSpeaker(rArg.chan);
|
|
ex_c::m_ex[rArg.chan].mDidConnect = true;
|
|
break;
|
|
}
|
|
case WPAD_ERR_NO_CONTROLLER: {
|
|
dSndPlayerMgr_c::GetInstance()->shutdownRmtSpeaker(rArg.chan);
|
|
ex_c::m_ex[rArg.chan].mDidDisconnect = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void setConnectCallback() {
|
|
EGG::CoreControllerMgr::setConnectCallback(connectCallback);
|
|
}
|
|
|
|
void enableMplsDirRevise(s32 chan) {
|
|
KPADEnableMplsDirRevise(chan);
|
|
}
|
|
|
|
void disableMplsDirRevise(s32 chan) {
|
|
KPADDisableMplsDirRevise(chan);
|
|
}
|
|
|
|
ex_c::ex_c()
|
|
: mDpdPos(0.f, 0.f),
|
|
mDpdPosScreen(0.f, 0.f),
|
|
mFSStick(0.f, 0.f),
|
|
mFSStickDistance(0.f),
|
|
mFSStickAngle(0),
|
|
mWPADProbeResult(0),
|
|
mWPADProbeResultStable(0),
|
|
mWPADProbeStableTimer(0),
|
|
mWPADDeviceType(0),
|
|
mWPADDeviceTypeStable(0xFF),
|
|
mWPADDeviceTypeStableTimer(0),
|
|
mConnectedStableTimer(0),
|
|
field_0x3C(0),
|
|
mCalibrationWork(0.f),
|
|
field_0x44(false),
|
|
field_0x45(false),
|
|
field_0x46(false),
|
|
mIsCalibrating(false),
|
|
field_0x48(0),
|
|
mDidConnect(false),
|
|
mDidDisconnect(false),
|
|
mNeedMplsCalibration(true),
|
|
field_0x4F(false),
|
|
field_0x50(true),
|
|
field_0x51(0),
|
|
mMplsEnabled(false),
|
|
field_0x53(false),
|
|
field_0x54(false),
|
|
field_0x55(false),
|
|
field_0x56(false),
|
|
field_0x57(false),
|
|
field_0x58(false),
|
|
field_0x59(false),
|
|
field_0x5A(false),
|
|
field_0x5B(false),
|
|
field_0x5C(0.f, 0.f),
|
|
field_0x64(0.f, 0.f),
|
|
mIsWPADDeviceTypeMplsStableTimer(0),
|
|
field_0x70(0x1200),
|
|
field_0x74(1.f, 0.f, 0.f),
|
|
field_0x80(0.f, 1.f, 0.f),
|
|
field_0x8C(0.f, 0.f, 1.f),
|
|
mState(0),
|
|
mOutOfHbmStableTimer(0),
|
|
field_0x2288(0),
|
|
field_0x22CE(0),
|
|
field_0x22CF(0),
|
|
field_0x22D0(0),
|
|
mFSStickMaskChanged(false),
|
|
mFSStickMask(0),
|
|
field_0x22D8(0) {
|
|
memset(&mStatus, 0, sizeof(mStatus));
|
|
}
|
|
|
|
void ex_c::fn_80055EF0(s32 chan) {
|
|
const s32 readLen = mPad::getCore(chan)->getReadLength();
|
|
|
|
// Shift all old acceleration values back
|
|
for (int i = 120 - 1; i >= readLen; i--) {
|
|
mMotion.mAccVecs[i] = mMotion.mAccVecs[i - readLen];
|
|
mMotion.mAccValues[i] = mMotion.mAccValues[i - readLen];
|
|
mFSMotion.mAccVecs[i] = mFSMotion.mAccVecs[i - readLen];
|
|
mFSMotion.mAccValues[i] = mFSMotion.mAccValues[i - readLen];
|
|
}
|
|
|
|
// Write newly read Wiimote acceleration values
|
|
// TODO - Missing an implicit != 0 check before the loop
|
|
for (int i = 0; i < readLen; i++) {
|
|
EGG::CoreStatus status = *mPad::getCore(chan)->getCoreStatus(i);
|
|
mMotion.mAccVecs[i].copyFrom(&status.acc);
|
|
mMotion.mAccValues[i] = status.acc_value;
|
|
}
|
|
|
|
mMotion.fn_80058AE0(chan, true);
|
|
|
|
// Write newly read Nunchuk acceleration values
|
|
for (int i = 0; i < readLen; ++i) {
|
|
if (mPad::getCore(chan)->getDevType() == EGG::cDEV_FREESTYLE ||
|
|
(mPad::isMplsPtFS(chan) && (u8)KPADGetMplsStatus(chan) == 5)) {
|
|
EGG::CoreStatus status = *mPad::getCore(chan)->getCoreStatus(i);
|
|
mFSMotion.mAccVecs[i].copyFrom(&status.acc);
|
|
mFSMotion.mAccValues[i] = status.acc_value;
|
|
} else {
|
|
mFSMotion.mAccVecs[i].set(0.f, 0.f, 0.f);
|
|
mFSMotion.mAccValues[i] = 0.f;
|
|
}
|
|
}
|
|
if (mPad::getCore(chan)->getDevType() == EGG::cDEV_FREESTYLE ||
|
|
(mPad::isMplsPtFS(chan) && (u8)KPADGetMplsStatus(chan) == 5)) {
|
|
mFSMotion.fn_80058AE0(chan, false);
|
|
}
|
|
}
|
|
|
|
void float_order_d_pad() {
|
|
EGG::Math<f32>::epsilon();
|
|
}
|
|
|
|
void ex_c::fn_800562B0(s32 chan, mVec3_c &mpls) {
|
|
if (field_0x53) {
|
|
mpls = m_ex[chan].mMPLS.mY;
|
|
mpls *= -1.f;
|
|
} else {
|
|
mpls = m_ex[chan].mMPLS.mZ;
|
|
}
|
|
}
|
|
|
|
void ex_c::fn_80056330(s32 chan) {
|
|
f32 mult = cM::minMaxLimit(1.f - field_0x8C.y * field_0x8C.y, 0.f, 1.f);
|
|
|
|
mVec3_c basis;
|
|
if (field_0x53) {
|
|
basis = m_ex[chan].mMPLS.mZ;
|
|
} else {
|
|
basis = m_ex[chan].mMPLS.mY;
|
|
}
|
|
// ??
|
|
field_0x74 = (mult * (mVec3_c::Ey - basis) + basis).cross(field_0x8C);
|
|
|
|
f32 mag = field_0x74.mag();
|
|
bool b = std::abs(mag) <= EGG::Math<f32>::epsilon();
|
|
if (b) {
|
|
field_0x74 = mVec3_c::Ex;
|
|
} else {
|
|
field_0x74 *= 1.f / mag;
|
|
}
|
|
|
|
field_0x80 = field_0x8C.cross(field_0x74);
|
|
field_0x80.normalize();
|
|
}
|
|
|
|
void ex_c::fn_80056580(s32 chan, const mVec2_c &vec) {
|
|
field_0x5C = vec;
|
|
field_0x53 = false;
|
|
|
|
mMtx_c m;
|
|
m.ZXYrotS(-field_0x5C.y * field_0x70, field_0x5C.x * field_0x70, 0);
|
|
MTXMultVecSR(m, m_ex[chan].mMPLS.mZ, field_0x8C);
|
|
|
|
fn_80056330(chan);
|
|
}
|
|
|
|
void ex_c::centerCursor(s32 chan, bool b) {
|
|
if (field_0x51 != 0 && b) {
|
|
return;
|
|
}
|
|
field_0x64 = field_0x5C;
|
|
|
|
// NON-MATCHING
|
|
bool tmp = false;
|
|
const EGG::Vector3f acc = mPad::getCore()->getAccelBad();
|
|
if (dAcPy_c::GetLink() && dAcPy_c::GetLink()->checkActionFlagsCont(0x2) && acc.z < -0.9f) {
|
|
tmp = true;
|
|
}
|
|
field_0x53 = tmp;
|
|
|
|
fn_800562B0(chan, field_0x8C);
|
|
fn_80056330(chan);
|
|
|
|
if (b) {
|
|
dSndSmallEffectMgr_c::GetInstance()->playSound(SE_S_POINTER_RESET);
|
|
field_0x51 = 3;
|
|
} else {
|
|
field_0x51 = 0;
|
|
field_0x5C.set(0.f, 0.f);
|
|
mDpdPos.set(0.f, 0.f);
|
|
convertDpdPosToScreenPos(mDpdPos, mDpdPosScreen);
|
|
}
|
|
}
|
|
|
|
void ex_c::fn_80056790(s32 chan) {
|
|
mVec2_c dpdRawPos = mPad::getDpdRawPos(chan);
|
|
|
|
f32 f;
|
|
if (dScGame_c::GetInstance() != nullptr && dLytMap_c::GetInstance() != nullptr &&
|
|
!dLytMap_c::GetInstance()->isVisible()) {
|
|
f = dScGame_c::GetInstance()->targetingScreenFn_801BBEC0();
|
|
} else {
|
|
f = 1.0f;
|
|
}
|
|
field_0x22D8 = 0;
|
|
EGG::CoreStatus coreStatus = *mPad::getCore(chan)->getCoreStatus(0);
|
|
if (coreStatus.dpd_valid_fg == 2) {
|
|
field_0x22D8 = 1;
|
|
}
|
|
mVec3_c v;
|
|
fn_800562B0(chan, v);
|
|
mVec3_c v2(v.dot(field_0x74), v.dot(field_0x80), v.dot(field_0x8C));
|
|
v2.z = nw4r::ut::Max(v2.z, field_0x70.cos());
|
|
|
|
s16 b1 = cM::atan2s(-v2.x, v2.z);
|
|
field_0x5C.x = cM::minMaxLimit(b1 * (1.0f / field_0x70), -1.0f, 1.0f);
|
|
s16 b2 = cM::atan2s(-v2.y, v2.z);
|
|
field_0x5C.y = cM::minMaxLimit(b2 * (1.0f / field_0x70), -f, f);
|
|
|
|
if (field_0x51 != 0) {
|
|
field_0x51--;
|
|
}
|
|
f32 f4 = field_0x51 * (1 / 3.0f);
|
|
// lerp
|
|
field_0x5C = field_0x5C * (1.0f - f4) + field_0x64 * f4;
|
|
}
|
|
|
|
void ex_c::setField_0x70(mAng ang) {
|
|
field_0x70 = ang;
|
|
}
|
|
|
|
void ex_c::setField_0x70() {
|
|
field_0x70.set(0x1200);
|
|
}
|
|
|
|
void ex_c::fn_80056AF0(s32 chan) {
|
|
if (mDidConnect) {
|
|
mDidConnect = false;
|
|
mConnectedStableTimer = 90;
|
|
field_0x44 = true;
|
|
|
|
m_ex[chan].field_0x46 = true;
|
|
m_ex[chan].field_0x3C = 120;
|
|
} else {
|
|
field_0x44 = false;
|
|
}
|
|
if (mDidDisconnect) {
|
|
mDidDisconnect = false;
|
|
field_0x45 = true;
|
|
m_ex[chan].mWPADDeviceTypeStable = WPAD_DEV_UNKNOWN;
|
|
} else {
|
|
field_0x45 = false;
|
|
}
|
|
}
|
|
|
|
bool ex_c::checkWPADProbeStable() {
|
|
return mWPADProbeResultStable == WPAD_ERR_OK;
|
|
}
|
|
|
|
void ex_c::fn_80056B90(s32 chan) {
|
|
u32 prevType = mWPADDeviceType;
|
|
WPADResult prevResult = mWPADProbeResult;
|
|
|
|
mWPADProbeResult = WPADProbe(chan, &mWPADDeviceType);
|
|
|
|
if (prevResult == mWPADProbeResult) {
|
|
mWPADProbeStableTimer++;
|
|
if (mWPADProbeStableTimer >= 5) {
|
|
mWPADProbeStableTimer = 5;
|
|
}
|
|
} else {
|
|
mWPADProbeStableTimer = 0;
|
|
}
|
|
if (mWPADProbeStableTimer >= 5) {
|
|
mWPADProbeResultStable = mWPADProbeResult;
|
|
}
|
|
if (mConnectedStableTimer > 0) {
|
|
mConnectedStableTimer--;
|
|
if (mConnectedStableTimer < 0) {
|
|
mConnectedStableTimer = 0;
|
|
}
|
|
}
|
|
|
|
if (prevType != mWPADDeviceType) {
|
|
mWPADDeviceTypeStableTimer = 0;
|
|
} else {
|
|
mWPADDeviceTypeStableTimer++;
|
|
if (mWPADDeviceTypeStableTimer > 20) {
|
|
mWPADDeviceTypeStableTimer = 20;
|
|
}
|
|
}
|
|
|
|
if (mWPADDeviceType != mWPADDeviceTypeStable && mWPADDeviceTypeStableTimer >= 20) {
|
|
mWPADDeviceTypeStable = mWPADDeviceType;
|
|
}
|
|
|
|
if (!isDeviceTypeMpls(mWPADDeviceTypeStable)) {
|
|
mNeedMplsCalibration = true;
|
|
mIsWPADDeviceTypeMplsStableTimer = 0;
|
|
}
|
|
if (isDeviceTypeMpls(mWPADDeviceTypeStable) && mIsWPADDeviceTypeMplsStableTimer < 8) {
|
|
mIsWPADDeviceTypeMplsStableTimer++;
|
|
}
|
|
}
|
|
|
|
void ex_c::fn_80056CE0(s32 chan) {
|
|
if (field_0x46 == false) {
|
|
return;
|
|
}
|
|
|
|
if (field_0x3C == 1) {
|
|
if (WPADCanSendStreamData(chan) && WPADGetRadioSensitivity(chan) > 50) {
|
|
WPADResult res = getInfo(chan);
|
|
if (res == WPAD_ERR_OK || res == WPAD_ERR_NO_CONTROLLER) {
|
|
field_0x46 = false;
|
|
} else {
|
|
field_0x3C = 120;
|
|
}
|
|
} else {
|
|
field_0x3C = 120;
|
|
}
|
|
}
|
|
field_0x3C--;
|
|
if (field_0x3C < 0) {
|
|
field_0x3C = 0;
|
|
}
|
|
}
|
|
|
|
void ex_c::startMplsCalibration(s32 chan) {
|
|
KPADStartMplsCalibration(chan);
|
|
mIsCalibrating = true;
|
|
mCalibrationWork = 1.0f;
|
|
field_0x48 = 0;
|
|
}
|
|
|
|
void ex_c::workMplsCalibration(s32 chan) {
|
|
if (!mIsCalibrating) {
|
|
return;
|
|
}
|
|
|
|
mCalibrationWork = KPADWorkMplsCalibration(chan);
|
|
if (mCalibrationWork == 0.0f) {
|
|
mIsCalibrating = false;
|
|
field_0x48 = 60;
|
|
}
|
|
}
|
|
|
|
f32 ex_c::getCalibrationWork() {
|
|
return mCalibrationWork;
|
|
}
|
|
|
|
void ex_c::stopMplsCalibration(s32 chan) {
|
|
mIsCalibrating = false;
|
|
mCalibrationWork = 0.0f;
|
|
KPADStopMplsCalibration(chan);
|
|
field_0x48 = 0;
|
|
}
|
|
|
|
void ex_c::centerCursor(s32 chan) {
|
|
centerCursor(chan, false);
|
|
field_0x48 = 0;
|
|
}
|
|
|
|
void ex_c::gotoStateWaitForConnect(s32 chan) {
|
|
mState = EX_STATE_WAITING_FOR_CONNECT;
|
|
}
|
|
|
|
void ex_c::executeStateWaitForConnect(s32 chan) {
|
|
if (mPad::getCore(chan)->isConnected()) {
|
|
gotoStatePostConnect(chan);
|
|
}
|
|
}
|
|
|
|
void ex_c::gotoStatePostConnect(s32 chan) {
|
|
mState = EX_STATE_POST_CONNECT;
|
|
}
|
|
|
|
void ex_c::executeStatePostConnect(s32 chan) {
|
|
if (dHbm::Manage_c::GetInstance()->getState() == dHbm::Manage_c::HBM_MANAGE_ACTIVE) {
|
|
// If we are in HBM, set some sort of cooldown
|
|
mOutOfHbmStableTimer = 110;
|
|
field_0x4F = true;
|
|
}
|
|
|
|
if (mPad::getCore(chan)->isConnected()) {
|
|
if (ex_c::checkWPADProbeStable() &&
|
|
dHbm::Manage_c::GetInstance()->getState() != dHbm::Manage_c::HBM_MANAGE_ACTIVE) {
|
|
// Enable Mpls after we leave HBM
|
|
gotoStateEnableMpls(chan);
|
|
}
|
|
}
|
|
|
|
if (!mPad::getCore(chan)->isConnected()) {
|
|
gotoStateWaitForConnect(chan);
|
|
}
|
|
}
|
|
|
|
void ex_c::gotoStateEnableMpls(s32 chan) {
|
|
mState = EX_STATE_ENABLE_MPLS;
|
|
setMpls(true, chan);
|
|
}
|
|
|
|
void ex_c::executeStateEnableMpls(s32 chan) {
|
|
if (fn_80059350(chan) || fn_80059370(chan)) {
|
|
gotoStateMplsConfigError(chan);
|
|
} else if (fn_80059390(chan)) {
|
|
gotoStateMplsConfigured(chan);
|
|
}
|
|
}
|
|
|
|
void ex_c::gotoStateDisconnectWpad(s32 chan) {
|
|
mState = EX_STATE_DISCONECT_WPAD;
|
|
WPADDisconnect(chan);
|
|
}
|
|
|
|
void ex_c::executeStateDisconnectWpad(s32 chan) {
|
|
gotoStatePostConnect(chan);
|
|
}
|
|
|
|
void ex_c::gotoStateMplsConfigError(s32 chan) {
|
|
mState = EX_STATE_MPLS_CONFIG_ERROR;
|
|
setMpls(false, chan);
|
|
field_0x2288 = 0;
|
|
}
|
|
|
|
void ex_c::executeStateMplsConfigError(s32 chan) {
|
|
if (fn_80059390(chan)) {
|
|
if (dHbm::Manage_c::GetInstance()->getState() == dHbm::Manage_c::HBM_MANAGE_ACTIVE) {
|
|
gotoStatePostConnect(chan);
|
|
} else {
|
|
gotoStateEnableMpls(chan);
|
|
}
|
|
} else {
|
|
if (dHbm::Manage_c::GetInstance()->getState() != dHbm::Manage_c::HBM_MANAGE_ACTIVE) {
|
|
if (field_0x2288 > 120) {
|
|
gotoStateDisconnectWpad(chan);
|
|
} else {
|
|
field_0x2288++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ex_c::gotoStateMplsConfigured(s32 chan) {
|
|
mState = EX_STATE_MPLS_CONFIGURED;
|
|
}
|
|
|
|
void ex_c::executeStateMplsConfigured(s32 chan) {
|
|
if (!mPad::getCore(chan)->isConnected()) {
|
|
setMpls(false, chan);
|
|
gotoStateWaitForConnect(chan);
|
|
} else {
|
|
if (fn_80059330(chan) || fn_80059350(chan) || fn_80059370(chan)) {
|
|
setMpls(false, chan);
|
|
}
|
|
}
|
|
if (!mMplsEnabled) {
|
|
gotoStatePostConnect(chan);
|
|
}
|
|
|
|
if (dHbm::Manage_c::GetInstance()->getState() == dHbm::Manage_c::HBM_MANAGE_ACTIVE) {
|
|
field_0x4F = false;
|
|
}
|
|
}
|
|
|
|
void ex_c::fn_800572A0(s32 chan) {
|
|
switch (mState) {
|
|
case EX_STATE_WAITING_FOR_CONNECT: executeStateWaitForConnect(chan); break;
|
|
case EX_STATE_POST_CONNECT: executeStatePostConnect(chan); break;
|
|
case EX_STATE_ENABLE_MPLS: executeStateEnableMpls(chan); break;
|
|
case EX_STATE_DISCONECT_WPAD: executeStateDisconnectWpad(chan); break;
|
|
case EX_STATE_MPLS_CONFIG_ERROR: executeStateMplsConfigError(chan); break;
|
|
case EX_STATE_MPLS_CONFIGURED: executeStateMplsConfigured(chan); break;
|
|
}
|
|
|
|
if (mState != EX_STATE_POST_CONNECT &&
|
|
dHbm::Manage_c::GetInstance()->getState() != dHbm::Manage_c::HBM_MANAGE_ACTIVE) {
|
|
if (mOutOfHbmStableTimer > 0) {
|
|
mOutOfHbmStableTimer--;
|
|
} else {
|
|
mOutOfHbmStableTimer = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ex_c::acc_c::init() {
|
|
for (int i = 0; i < 120; ++i) {
|
|
mAccVecs[i].set(0.f, 0.f, 0.f);
|
|
field_0x5A0[i].set(0.f, 0.f, 0.f);
|
|
mAccValues[i] = 0.f;
|
|
}
|
|
for (int i = 0; i < 39; ++i) {
|
|
field_0xD20[i].set(0.f, 0.f, 0.f);
|
|
}
|
|
for (int i = 0; i < 33; ++i) {
|
|
field_0xEF4[i].set(0.f, 0.f, 0.f);
|
|
}
|
|
field_0x1080.set(0.f, 0.f, 0.f);
|
|
field_0x108C.set(0.f, 0.f, 0.f);
|
|
|
|
MTXIdentity(field_0x1098);
|
|
field_0x10C8 = 0;
|
|
field_0x10CC = 0;
|
|
field_0x10D0 = 0;
|
|
field_0x10D4 = 0;
|
|
field_0x10D8 = 31;
|
|
}
|
|
|
|
f32 ex_c::acc_c::getMaxAccValue(s32 chan) {
|
|
s32 readLen = mPad::getCore(chan)->getReadLength();
|
|
if (readLen == 0) {
|
|
return 0.0f;
|
|
}
|
|
|
|
f32 max = 0.0f;
|
|
for (int i = 0; i < readLen; i++) {
|
|
if (max < mAccValues[i]) {
|
|
max = mAccValues[i];
|
|
}
|
|
}
|
|
return max;
|
|
}
|
|
|
|
void ex_c::acc_c::fn_800576D0(s32 chan) {
|
|
// unused
|
|
(void)nw4r::math::FSqrt(mAccVecs[0].squaredLength());
|
|
|
|
f32 maxAccValue = getMaxAccValue(chan);
|
|
if (maxAccValue <= 1.1f && mAccVecs[0].y < 0.35f) {
|
|
field_0x10D0++;
|
|
if (field_0x10D0 >= 6) {
|
|
field_0x10D0 = 6;
|
|
field_0x108C = mAccVecs[0];
|
|
mVec3_c dir(0.0f, -1.0f, 0.0f);
|
|
f32 len = mAccVecs[0].squaredLength();
|
|
if (!cM3d_IsZero(len)) {
|
|
// TODO - bad part start
|
|
mVec3_c acc = mAccVecs[0];
|
|
acc.normalize();
|
|
mVec3_c cross = acc.cross(dir);
|
|
f32 f = acc.dot(dir);
|
|
if (!cM3d_IsZero(cross.squaredLength())) {
|
|
cross.normalize();
|
|
f32 acos = std::acosf(f);
|
|
MTXRotAxisRad(field_0x1098, cross, acos);
|
|
// TODO - bad part end
|
|
} else {
|
|
MTXIdentity(field_0x1098);
|
|
}
|
|
} else {
|
|
MTXIdentity(field_0x1098);
|
|
}
|
|
}
|
|
} else {
|
|
field_0x10D0 = 0;
|
|
}
|
|
}
|
|
|
|
void ex_c::acc_c::fn_800578E0(s32 chan) {
|
|
const s32 readLen = mPad::getCore(chan)->getReadLength();
|
|
|
|
// Shift old values back
|
|
for (int i = readLen; i < 120; i++) {
|
|
field_0x5A0[i] = field_0x5A0[i - readLen];
|
|
}
|
|
|
|
// TODO - loop strength reduction too strong
|
|
f32 max = -8.0f;
|
|
bool b = false;
|
|
for (int i = 0; i < readLen; i++) {
|
|
if (max < mAccVecs[i].y) {
|
|
max = mAccVecs[i].y;
|
|
b = true;
|
|
}
|
|
MTXMultVec(field_0x1098, mAccVecs[i], field_0x5A0[i]);
|
|
field_0x5A0[i].y += 1.0f;
|
|
}
|
|
|
|
if (b) {
|
|
field_0x10D4 = max;
|
|
}
|
|
}
|
|
|
|
void ex_c::acc_c::fn_80057AC0(s32 chan, bool b) {
|
|
const s32 readLen = mPad::getCore(chan)->getReadLength();
|
|
|
|
// Shift field_0xD20 back by one
|
|
for (int i = 38; i > 0; i--) {
|
|
field_0xD20[i] = field_0xD20[i - 1];
|
|
}
|
|
|
|
for (int i = 0; i < readLen; i++) {
|
|
field_0x1080.x += mAccVecs[i].x;
|
|
field_0x1080.y += mAccVecs[i].y;
|
|
field_0x1080.z += mAccVecs[i].z;
|
|
}
|
|
|
|
if (b) {
|
|
field_0x1080 *= 0.96f;
|
|
} else {
|
|
field_0x1080 *= 0.98f;
|
|
}
|
|
|
|
// TODO - problematic part start
|
|
|
|
field_0xD20[0] = field_0x1080;
|
|
|
|
for (int i = 3; i < 36;) {
|
|
int k = i++ - 3;
|
|
f32 x = 0.0f;
|
|
f32 y = 0.0f;
|
|
f32 z = 0.0f;
|
|
for (int j = 0; j < 7; j++) {
|
|
x += field_0xD20[k + j].x / 7.0f;
|
|
y += field_0xD20[k + j].y / 7.0f;
|
|
z += field_0xD20[k + j].z / 7.0f;
|
|
}
|
|
field_0xEF4[k].set(x, y, z);
|
|
}
|
|
|
|
// TODO - problematic part end
|
|
}
|
|
|
|
f32 ex_c::acc_c::fn_80057F00(s32 chan) {
|
|
s32 offs = chan + 3;
|
|
return field_0xD20[offs].x - field_0xEF4[chan].x;
|
|
}
|
|
|
|
f32 ex_c::acc_c::fn_80057F30(s32 chan) {
|
|
s32 offs = chan + 3;
|
|
return field_0xD20[offs].y - field_0xEF4[chan].y;
|
|
}
|
|
|
|
f32 ex_c::acc_c::fn_80057F60(s32 chan) {
|
|
s32 offs = chan + 3;
|
|
return field_0xD20[offs].z - field_0xEF4[chan].z;
|
|
}
|
|
|
|
bool ex_c::acc_c::fn_80057F90(s32 idx, bool b) {
|
|
if ((b && ((fn_80057F00(idx) < -13.5f) || fn_80057F00(idx + 1) < -13.5f) &&
|
|
std::fabsf(fn_80057F00(idx + 1) - fn_80057F00(idx)) > 3.75f) ||
|
|
(!b && ((fn_80057F00(idx) < -5.0f) || fn_80057F00(idx + 1) < -5.0f) &&
|
|
std::fabsf(fn_80057F00(idx + 1) - fn_80057F00(idx)) > 2.75f)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
bool ex_c::acc_c::fn_800580C0(s32 idx, bool b) {
|
|
if ((b && ((fn_80057F00(idx) > 13.5f) || fn_80057F00(idx + 1) > 13.5f) &&
|
|
std::fabsf(fn_80057F00(idx + 1) - fn_80057F00(idx)) > 3.75f) ||
|
|
(!b && ((fn_80057F00(idx) > 5.0f) || fn_80057F00(idx + 1) > 5.0f) &&
|
|
std::fabsf(fn_80057F00(idx + 1) - fn_80057F00(idx)) > 2.75f)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ex_c::acc_c::fn_800581F0(s32 idx, bool b) {
|
|
if ((b && ((fn_80057F30(idx) < -13.5f) || fn_80057F30(idx + 1) < -13.5f) &&
|
|
std::fabsf(fn_80057F30(idx + 1) - fn_80057F30(idx)) > 3.75f) ||
|
|
(!b && ((fn_80057F30(idx) < -5.0f) || fn_80057F30(idx + 1) < -5.0f) &&
|
|
std::fabsf(fn_80057F30(idx + 1) - fn_80057F30(idx)) > 2.75f)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
bool ex_c::acc_c::fn_80058320(s32 idx, bool b) {
|
|
if ((b && ((fn_80057F30(idx) > 13.5f) || fn_80057F30(idx + 1) > 13.5f) &&
|
|
std::fabsf(fn_80057F30(idx + 1) - fn_80057F30(idx)) > 3.75f) ||
|
|
(!b && ((fn_80057F30(idx) > 5.0f) || fn_80057F30(idx + 1) > 5.0f) &&
|
|
std::fabsf(fn_80057F30(idx + 1) - fn_80057F30(idx)) > 2.75f)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ex_c::acc_c::fn_80058450(s32 idx, bool b) {
|
|
// Note - same behavior, whether b is set or not
|
|
if ((b && (fn_80057F60(idx) > 2.0f) && (fn_80057F60(idx + 1) - fn_80057F60(idx)) < -2.0f) ||
|
|
(!b && (fn_80057F60(idx) > 2.0f) && (fn_80057F60(idx + 1) - fn_80057F60(idx)) < -2.0f)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ex_c::acc_c::fn_80058540(s32 chan, bool b) {
|
|
bool b1 = false;
|
|
bool b2 = false;
|
|
bool b3 = false;
|
|
bool b4 = false;
|
|
// TODO condition
|
|
if (b && (mPad::isMpls(chan) || mPad::isMplsPtFS(chan))) {
|
|
if (m_ex[chan].mMPLSVelocity.x > 2.0f) {
|
|
b4 = true;
|
|
} else if (m_ex[chan].mMPLSVelocity.x < -2.0f) {
|
|
b3 = true;
|
|
} else if (m_ex[chan].mMPLSVelocity.y > 2.0f) {
|
|
b1 = true;
|
|
} else if (m_ex[chan].mMPLSVelocity.y < -2.0f) {
|
|
b2 = true;
|
|
}
|
|
} else {
|
|
int i1 = 0;
|
|
int i2 = 0;
|
|
int i3 = 0;
|
|
field_0x10D8++;
|
|
if (field_0x10D8 > 31) {
|
|
field_0x10D8 = 31;
|
|
}
|
|
|
|
bool b1_ = false;
|
|
bool b2_ = false;
|
|
bool b3_ = false;
|
|
bool b4_ = false;
|
|
|
|
int start = field_0x10D8;
|
|
for (int i = field_0x10D8; i >= 0; i--) {
|
|
if (fn_80057F90(i, b)) {
|
|
b1_ = true;
|
|
b2_ = false;
|
|
}
|
|
|
|
if (fn_800580C0(i, b)) {
|
|
b2_ = true;
|
|
b1_ = false;
|
|
}
|
|
|
|
if (fn_80057F90(i, b) || fn_800580C0(i, b)) {
|
|
i1 = 2;
|
|
} else {
|
|
i1--;
|
|
if (i1 < 0) {
|
|
i1 = 0;
|
|
b1_ = false;
|
|
b2_ = false;
|
|
}
|
|
}
|
|
|
|
if (fn_800581F0(i, b)) {
|
|
b3_ = true;
|
|
b4_ = false;
|
|
}
|
|
|
|
if (fn_80058320(i, b)) {
|
|
b4_ = true;
|
|
b3_ = false;
|
|
}
|
|
|
|
if (fn_800581F0(i, b) || fn_80058320(i, b)) {
|
|
i2 = 2;
|
|
} else {
|
|
i2--;
|
|
if (i2 < 0) {
|
|
i2 = 0;
|
|
b3_ = false;
|
|
b4_ = false;
|
|
}
|
|
}
|
|
|
|
if (fn_80058450(i, b)) {
|
|
i3 = 2;
|
|
} else {
|
|
i3--;
|
|
if (i3 < 0) {
|
|
i3 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (start != 0 && i3 > 0) {
|
|
if (b1_) {
|
|
field_0x10D8 = 0;
|
|
b1 = true;
|
|
}
|
|
if (b2_) {
|
|
field_0x10D8 = 0;
|
|
b2 = true;
|
|
}
|
|
if (b3_) {
|
|
field_0x10D8 = 0;
|
|
b3 = true;
|
|
}
|
|
if (b4_) {
|
|
field_0x10D8 = 0;
|
|
b4 = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn_80058990(0x1, b1);
|
|
fn_80058990(0x2, b2);
|
|
fn_80058990(0x4, b3);
|
|
fn_80058990(0x8, b4);
|
|
fn_80058990(0x10, b1 || b2 || b3 || b4);
|
|
|
|
bool b6;
|
|
if (b) {
|
|
b6 = getMaxAccValue(chan) > (field_0x10CC ? 2.0f : 3.0f);
|
|
} else {
|
|
b6 = getMaxAccValue(chan) > (field_0x10CC ? 1.5f : 2.0f);
|
|
}
|
|
fn_80058990(0x20, b6);
|
|
}
|
|
|
|
void ex_c::acc_c::fn_80058990(u32 mask, bool b) {
|
|
if (b) {
|
|
if ((field_0x10CC & mask) != 0) {
|
|
field_0x10C8 &= ~mask;
|
|
} else {
|
|
field_0x10C8 |= mask;
|
|
}
|
|
field_0x10CC |= mask;
|
|
} else {
|
|
field_0x10CC &= ~mask;
|
|
field_0x10C8 &= ~mask;
|
|
}
|
|
}
|
|
|
|
bool ex_c::acc_c::fn_800589F0() {
|
|
return true;
|
|
}
|
|
|
|
f32 ex_c::acc_c::fn_80058A00() {
|
|
cM3dGAab aab;
|
|
aab.ClearForMinMax();
|
|
for (int i = 0; i < 120; i++) {
|
|
aab.SetMinMax(mAccVecs[i]);
|
|
}
|
|
|
|
f32 lenSq = nw4r::math::VEC3LenSq(aab.GetMax() - aab.GetMin()) - 0.017f;
|
|
if (lenSq < 0.0f) {
|
|
lenSq = 0.0f;
|
|
}
|
|
return lenSq;
|
|
}
|
|
|
|
void ex_c::acc_c::fn_80058AE0(s32 chan, bool b) {
|
|
fn_800576D0(chan);
|
|
fn_800578E0(chan);
|
|
fn_80057AC0(chan, b);
|
|
fn_80058540(chan, b);
|
|
}
|
|
|
|
mMtx_c ex_c::mpls_c::getMtx() const {
|
|
mMtx_c m;
|
|
m.setBase(0, mX);
|
|
m.setBase(1, mY);
|
|
m.setBase(2, mZ);
|
|
m.setBase(3, mVec3_c::Zero);
|
|
return m;
|
|
}
|
|
|
|
bool ex_c::isMissingMpls() {
|
|
if (m_current_ex->mConnectedStableTimer != 0) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mOutOfHbmStableTimer != 0) {
|
|
return false;
|
|
}
|
|
|
|
return !isDeviceTypeMpls(m_current_ex->mWPADDeviceTypeStable);
|
|
}
|
|
|
|
bool ex_c::isMissingNunchuk() {
|
|
if (m_current_ex->mConnectedStableTimer != 0) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mOutOfHbmStableTimer != 0) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mState != EX_STATE_MPLS_CONFIGURED) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mWPADDeviceTypeStable == WPAD_DEV_FREESTYLE) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mWPADDeviceTypeStable == WPAD_DEV_MPLS_PT_FS) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ex_c::fn_80058C90(s32 chan) {
|
|
m_ex[chan].field_0x46 = true;
|
|
m_ex[chan].field_0x3C = 1;
|
|
}
|
|
|
|
bool ex_c::isLowBattery() {
|
|
return getBatteryLevel() == 1;
|
|
}
|
|
bool ex_c::isOutOfBattery() {
|
|
return getBatteryLevel() == 0;
|
|
}
|
|
|
|
void ex_c::resetInfo() {
|
|
for (int i = 0; i < 4; ++i) {
|
|
clearInfo(i);
|
|
}
|
|
}
|
|
void ex_c::clearInfo(s32 chan) {
|
|
m_connected[chan] = false;
|
|
m_info[0][chan].dpd = FALSE;
|
|
m_info[0][chan].speaker = FALSE;
|
|
m_info[0][chan].attach = FALSE;
|
|
m_info[0][chan].lowBat = FALSE;
|
|
m_info[0][chan].nearempty = FALSE;
|
|
m_info[0][chan].battery = 0;
|
|
m_info[0][chan].led = 0;
|
|
m_info[0][chan].protocol = 0;
|
|
m_info[0][chan].firmware = 0;
|
|
}
|
|
extern "C" void async_info_callback(WPADChannel chan, WPADResult result) {
|
|
switch (result) {
|
|
case WPAD_ERR_OK: {
|
|
ex_c::setInfo(chan, &ex_c::m_info[0][chan]);
|
|
break;
|
|
}
|
|
case WPAD_ERR_NO_CONTROLLER: {
|
|
ex_c::clearInfo(chan);
|
|
break;
|
|
}
|
|
case WPAD_ERR_BUSY: {
|
|
ex_c::m_ex[chan].field_0x46 = true;
|
|
ex_c::m_ex[chan].field_0x3C = 120;
|
|
break;
|
|
}
|
|
case WPAD_ERR_TRANSFER: {
|
|
ex_c::m_ex[chan].field_0x46 = true;
|
|
ex_c::m_ex[chan].field_0x3C = 120;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
s32 ex_c::getInfo(s32 chan) {
|
|
WPADResult res = WPADGetInfoAsync(chan, &ex_c::m_info[0][chan], async_info_callback);
|
|
if (res == WPAD_ERR_NO_CONTROLLER) {
|
|
clearInfo(chan);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
s32 ex_c::getBatteryLevel() {
|
|
return getBatteryLevel(mPad::g_currentCoreId);
|
|
}
|
|
s32 ex_c::getBatteryLevel(s32 chan) {
|
|
if (m_connected[chan]) {
|
|
return m_info[0][chan].battery;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void ex_c::setInfo(s32 chan, const WPADInfo *pInfo) {
|
|
m_info[0][chan] = *pInfo;
|
|
m_connected[chan] = true;
|
|
}
|
|
|
|
f32 ex_c::fn_80058F50() {
|
|
return m_current_ex->mMotion.fn_80058A00();
|
|
}
|
|
|
|
bool ex_c::startCurrentMplsCalibration() {
|
|
if (m_current_ex->mIsWPADDeviceTypeMplsStableTimer < 8) {
|
|
return true;
|
|
}
|
|
|
|
if (!m_current_ex->mMotion.fn_800589F0()) {
|
|
return true;
|
|
}
|
|
|
|
m_current_ex->mNeedMplsCalibration = false;
|
|
m_current_ex->startMplsCalibration(mPad::getCurrentCoreID());
|
|
m_current_ex->fn_80058C90(mPad::getCurrentCoreID());
|
|
initMpls(mPad::getCurrentCoreID());
|
|
|
|
return false;
|
|
}
|
|
|
|
f32 ex_c::getCurrentCalibrationWork() {
|
|
return m_current_ex->getCalibrationWork();
|
|
}
|
|
|
|
void ex_c::stopCurrentMplsCalibration() {
|
|
m_current_ex->stopMplsCalibration(mPad::getCurrentCoreID());
|
|
}
|
|
|
|
void ex_c::centerCurrentCursor() {
|
|
m_current_ex->centerCursor(mPad::getCurrentCoreID());
|
|
}
|
|
|
|
bool ex_c::needMplsCalibration() {
|
|
if (!mPad::getCore()->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
if (isMissingMpls()) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mOutOfHbmStableTimer != 0) {
|
|
return false;
|
|
}
|
|
|
|
if (isMissingNunchuk()) {
|
|
return false;
|
|
}
|
|
|
|
if (m_current_ex->mIsWPADDeviceTypeMplsStableTimer >= 8) {
|
|
return m_current_ex->mNeedMplsCalibration;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void ex_c::setCalibrateMpls() {
|
|
m_current_ex->mNeedMplsCalibration = true;
|
|
}
|
|
|
|
bool ex_c::fn_800590B0() {
|
|
bool ret = false;
|
|
switch (m_current_ex->mState) {
|
|
case EX_STATE_POST_CONNECT:
|
|
case EX_STATE_ENABLE_MPLS:
|
|
case EX_STATE_DISCONECT_WPAD:
|
|
case EX_STATE_MPLS_CONFIG_ERROR:
|
|
// TODO - one uneliminated dead branch in here
|
|
ret = m_current_ex->mState == EX_STATE_MPLS_CONFIG_ERROR || m_current_ex->mState == EX_STATE_ENABLE_MPLS ||
|
|
m_current_ex->mState == EX_STATE_POST_CONNECT;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ex_c::fn_800590E0() {
|
|
return m_current_ex->field_0x4F;
|
|
}
|
|
|
|
void ex_c::fn_800590F0() {
|
|
m_current_ex->field_0x4F = false;
|
|
}
|
|
|
|
bool ex_c::fn_80059100() {
|
|
return fn_80059110(mPad::g_currentCoreId);
|
|
}
|
|
|
|
bool ex_c::fn_80059110(s32 chan) {
|
|
return nw4r::math::VEC3LenSq(m_ex[chan].mMPLSVelocity) >= 0.01f || m_ex[chan].mFSStickDistance >= 0.0001f ||
|
|
mPad::g_core[chan]->getCoreStatus()->getHold() || mPad::g_core[chan]->getCoreStatus()->getTrigger() ||
|
|
m_ex[chan].mMotion.field_0x10C8 != 0;
|
|
}
|
|
|
|
void ex_c::fn_80059210() {
|
|
m_current_ex->field_0x22CE = 1;
|
|
}
|
|
|
|
void ex_c::fn_80059220() {
|
|
m_current_ex->field_0x22CF = 1;
|
|
}
|
|
|
|
void ex_c::fn_80059230() {
|
|
m_current_ex->field_0x22D0 = 1;
|
|
}
|
|
|
|
void ex_c::fn_80059240() {
|
|
m_current_ex->field_0x22D0 = 0;
|
|
}
|
|
|
|
void ex_c::on_0x54(s32 idx) {
|
|
m_ex[idx].field_0x54 = true;
|
|
}
|
|
void ex_c::on_0x55(s32 idx) {
|
|
m_ex[idx].field_0x55 = true;
|
|
}
|
|
void ex_c::on_0x56(s32 idx) {
|
|
m_ex[idx].field_0x56 = true;
|
|
}
|
|
void ex_c::on_0x57(s32 idx) {
|
|
m_ex[idx].field_0x57 = true;
|
|
}
|
|
|
|
void ex_c::fn_800592D0(s32 chan) {
|
|
m_ex[chan].field_0x54 = false;
|
|
m_ex[chan].field_0x55 = false;
|
|
m_ex[chan].field_0x56 = false;
|
|
m_ex[chan].field_0x57 = false;
|
|
}
|
|
|
|
void ex_c::fn_80059300(s32 chan) {
|
|
field_0x58 = field_0x54;
|
|
field_0x59 = field_0x55;
|
|
field_0x5A = field_0x56;
|
|
field_0x5B = field_0x57;
|
|
fn_800592D0(chan);
|
|
}
|
|
|
|
bool ex_c::fn_80059330(s32 chan) {
|
|
return m_ex[chan].field_0x58;
|
|
}
|
|
|
|
bool ex_c::fn_80059350(s32 chan) {
|
|
return m_ex[chan].field_0x59;
|
|
}
|
|
|
|
bool ex_c::fn_80059370(s32 chan) {
|
|
return m_ex[chan].field_0x5A;
|
|
}
|
|
|
|
bool ex_c::fn_80059390(s32 chan) {
|
|
return m_ex[chan].field_0x5B;
|
|
}
|
|
|
|
void ex_c::getUnifiedWpadStatus(s32 chan) {
|
|
KPADGetUnifiedWpadStatus(chan, &mStatus, 1);
|
|
}
|
|
|
|
void ex_c::calcFSStickDirMask() {
|
|
mFSStickMaskChanged = false;
|
|
if (mFSStickDistance < 0.8f) {
|
|
mFSStickMask = 0;
|
|
return;
|
|
}
|
|
u32 prevFSStickMask = mFSStickMask;
|
|
s32 ang = mFSStickAngle;
|
|
ang = ((ang + 0x11000) / 0x2000) % 8;
|
|
mFSStickMask = 1 << ang;
|
|
if (mFSStickMask != 0 && mFSStickMask != prevFSStickMask) {
|
|
mFSStickMaskChanged = true;
|
|
}
|
|
}
|
|
|
|
void ex_c::setNoSleep() {
|
|
WPADSetAutoSleepTime(0);
|
|
}
|
|
|
|
void ex_c::setAutoSleepTime() {
|
|
WPADSetAutoSleepTime(5);
|
|
WPADResetAutoSleepTimeCount(0);
|
|
}
|
|
|
|
} // namespace dPad
|