mirror of https://github.com/zeldaret/tp.git
360 lines
9.9 KiB
C++
360 lines
9.9 KiB
C++
#include "JSystem/JUtility/JUTGamePad/JUTGamePad.h"
|
|
#include "global.h"
|
|
|
|
#ifdef NONMATCHING
|
|
// TODO(erin): probably ~easy to do, i just didn't do it yet :)
|
|
JUTGamePad::JUTGamePad(EPadPort port) : ptr_link(this) {
|
|
this->buttons.clear();
|
|
this->control_stick.clear();
|
|
this->c_stick.clear();
|
|
this->rumble.clear();
|
|
}
|
|
#else
|
|
asm JUTGamePad::JUTGamePad(EPadPort port) {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E06DC.s"
|
|
}
|
|
#endif
|
|
|
|
asm JUTGamePad::~JUTGamePad() {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E07B0.s"
|
|
}
|
|
|
|
void JUTGamePad::initList() {
|
|
if (/* mIsPadListInitialized */ lbl_804514D0 == false) {
|
|
/*mPadList*/ lbl_804343E4.initiate();
|
|
lbl_804514D0 = true;
|
|
}
|
|
}
|
|
|
|
s32 JUTGamePad::init() {
|
|
PADSetSpec(5);
|
|
/*sAnalogMode*/ sAnalogMode = 3;
|
|
PADSetAnalogMode(3);
|
|
|
|
return PADInit();
|
|
}
|
|
|
|
void JUTGamePad::clear() {
|
|
this->field_0x98 = 0;
|
|
this->field_0xa8 = 1;
|
|
}
|
|
|
|
asm void JUTGamePad::read() {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E08E4.s"
|
|
}
|
|
|
|
void JUTGamePad::assign() {
|
|
s32 iVar3 = 0;
|
|
|
|
for (s32 i = 4; i > 0; i--) {
|
|
if ((/* mPadStatus */ lbl_804343F0[iVar3].error == 0) &&
|
|
(/* *puVar2 */ lbl_804514D4[iVar3] == 0)) {
|
|
this->pad_port = iVar3;
|
|
/* JUTGamePad::mPadAssign[iVar3] */ /* *puVar2 */ lbl_804514D4[iVar3] = 1;
|
|
/* JUTGamePad::mPadButton */ lbl_80434420[iVar3].setRepeat(
|
|
this->buttons.field_0x24, this->buttons.field_0x28, this->buttons.field_0x2c);
|
|
this->rumble.clear(this);
|
|
|
|
return;
|
|
}
|
|
|
|
iVar3++;
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::checkResetCallback(OSTime unk) {
|
|
if (unk < /* sThreshold */ lbl_804514F8)
|
|
return;
|
|
|
|
lbl_80451501 = true;
|
|
lbl_80451504 = this->pad_port;
|
|
if (/* sCallback* */ lbl_804514EC != NULL) {
|
|
lbl_804514EC(this->pad_port, /* sCallbackArg */ lbl_804514F0);
|
|
}
|
|
}
|
|
|
|
asm void JUTGamePad::update() {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E0CD8.s"
|
|
}
|
|
|
|
void JUTGamePad::checkResetSwitch() {
|
|
if (lbl_80451501 == false) {
|
|
if ((s32)OSGetResetSwitchState() != 0) {
|
|
lbl_80451500 = true;
|
|
return;
|
|
}
|
|
|
|
if (lbl_80451500 == true) {
|
|
lbl_80451501 = true;
|
|
/* sResetOccurredPort */ lbl_80451504 = -1;
|
|
if (/* sCallback* */ lbl_804514EC != NULL) {
|
|
lbl_804514EC(-1, /* sCallbackArg */ lbl_804514F0);
|
|
}
|
|
}
|
|
|
|
lbl_80451500 = false;
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::clearForReset() {
|
|
CRumble::setEnabled((PADMask)0);
|
|
JUTGamePad::recalibrate(
|
|
(PADMask)(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT));
|
|
}
|
|
|
|
void JUTGamePad::CButton::clear() {
|
|
this->button_flags = 0;
|
|
this->field_0x4 = 0;
|
|
this->field_0x8 = 0;
|
|
this->field_0x18 = 0;
|
|
this->analog_a = 0;
|
|
this->analog_b = 0;
|
|
this->trigger_left = 0;
|
|
this->trigger_right = 0;
|
|
this->field_0x1c = 0;
|
|
this->field_0x20 = 0;
|
|
this->field_0x24 = 0;
|
|
this->field_0x28 = 0;
|
|
this->field_0x2c = 0;
|
|
}
|
|
|
|
asm u32 JUTGamePad::CButton::update(PADStatus const*, u32 unk) {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E108C.s"
|
|
}
|
|
|
|
void JUTGamePad::CStick::clear() {
|
|
float zero = lbl_80456028; // 0.0f
|
|
this->stick_x = zero;
|
|
this->stick_y = zero;
|
|
this->length_from_neutral = zero;
|
|
this->angle = 0;
|
|
}
|
|
|
|
asm u32 JUTGamePad::CStick::update(s8 unk0, s8 unk1, EStickMode mode, EWhichStick stick, u32 unk2) {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E1238.s"
|
|
}
|
|
|
|
asm u32 JUTGamePad::CStick::getButton(u32 unk) {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E1500.s"
|
|
}
|
|
|
|
void JUTGamePad::CRumble::clear() {
|
|
this->field_0x0 = 0;
|
|
this->field_0x4 = 0;
|
|
this->field_0x8 = 0;
|
|
this->field_0xc = 0;
|
|
this->field_0x10 = 0;
|
|
lbl_804514E8 = (PADMask)0xf0000000; // mEnabled
|
|
}
|
|
|
|
void JUTGamePad::CRumble::clear(JUTGamePad* pad) {
|
|
// TODO: potentially fake match
|
|
s16 tmp0 = (s16)pad->pad_port;
|
|
if ((tmp0 >= 0) && (tmp0 < 4)) {
|
|
lbl_804514E4[tmp0] = false; // mStatus
|
|
this->stopMotor(pad->pad_port, true);
|
|
}
|
|
|
|
this->clear();
|
|
}
|
|
|
|
void JUTGamePad::CRumble::startMotor(int channel) {
|
|
if ((/*mEnabled*/ lbl_804514E8 & /*sChannelMask*/ lbl_803CC5F0[channel]) != 0) {
|
|
PADControlMotor(channel, 1);
|
|
lbl_804514E4[channel] = true; // mStatus
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::CRumble::stopMotor(int channel, bool stop) {
|
|
if ((/*mEnabled*/ lbl_804514E8 & /*sChannelMask*/ lbl_803CC5F0[channel]) != 0) {
|
|
PADControlMotor(channel, (u8)(stop ? 2 : 0));
|
|
lbl_804514E4[channel] = false; // mStatus
|
|
}
|
|
}
|
|
|
|
extern "C" {
|
|
bool getNumBit(u8* buf, u32 n_bits) {
|
|
return (u8)((0x80 >> (n_bits & 0b111)) & (u32) * (buf + ((s32)n_bits >> 3))) != 0;
|
|
}
|
|
}
|
|
|
|
#ifdef NONMATCHING
|
|
void JUTGamePad::CRumble::update(s16 chn) {
|
|
// i can't get this to generate an `addic;subfe;clrlwi.`; it's just generating
|
|
// an `and.` :/
|
|
if ((/*mEnabled*/ lbl_804514E8 & /*sChannelMask*/ lbl_803CC5F0[chn]) == 0) {
|
|
this->field_0x0 = 0;
|
|
this->field_0x4 = 0;
|
|
this->field_0x8 = 0;
|
|
this->field_0xc = 0;
|
|
this->field_0x10 = 0;
|
|
}
|
|
|
|
if (this->field_0x4 == 0)
|
|
return;
|
|
|
|
if (this->field_0x0 >= this->field_0x4) {
|
|
stopMotor(chn, true);
|
|
this->field_0x4 = 0;
|
|
} else {
|
|
if (this->field_0xc == 0) {
|
|
if (!/* mStatus */ lbl_804514E4[chn]) {
|
|
startMotor(chn);
|
|
}
|
|
return;
|
|
}
|
|
|
|
u32 uVar3 = getNumBit(this->field_0x8, this->field_0x0 % this->field_0xc);
|
|
bool bVar1 = /* mStatus */ lbl_804514E4[chn];
|
|
if (((uVar3 & 0xff) != 0) && !bVar1) {
|
|
startMotor(chn);
|
|
}
|
|
// } else {
|
|
// if (uVar3 & 0xff == 0) {
|
|
// uVar3 = 0;
|
|
// if (this->field_0x10 != 0) {
|
|
// uVar3 = getNumBit(this->field_0x10, this->field_0x0 -
|
|
// (this->field_0x0/this->field_0xc) * this->field_0xc);
|
|
// }
|
|
// if (bVar1 == false) {
|
|
// if ((uVar3 & 0xff) != 0) {
|
|
// stopMotor(chn, true);
|
|
// }
|
|
// } else {
|
|
// stopMotor(chn, uVar3);
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
this->field_0x0 = this->field_0x0 + 1;
|
|
}
|
|
#else
|
|
asm void JUTGamePad::CRumble::update(s16 unk0) {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E1720.s"
|
|
}
|
|
#endif
|
|
|
|
void JUTGamePad::CRumble::triggerPatternedRumble(u32 unk0) {
|
|
if (this->field_0x8 == 0)
|
|
return;
|
|
|
|
if (this->field_0xc == 0)
|
|
return;
|
|
|
|
this->field_0x4 = unk0;
|
|
this->field_0x0 = 0;
|
|
}
|
|
|
|
void JUTGamePad::CRumble::startPatternedRumble(void* unk0, JUTGamePad::CRumble::ERumble rumble,
|
|
u32 unk1) {
|
|
this->field_0xc = (u32)(*((u8*)unk0) << 8) + (u32) * ((u8*)unk0 + 1);
|
|
this->field_0x8 = (u8*)unk0 + 2;
|
|
|
|
switch (rumble) {
|
|
case 0:
|
|
this->triggerPatternedRumble(this->field_0xc);
|
|
break;
|
|
case 1:
|
|
this->triggerPatternedRumble(-1);
|
|
break;
|
|
case 2:
|
|
this->triggerPatternedRumble(unk1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void JUTGamePad::CRumble::stopPatternedRumble(s16 pad_port) {
|
|
this->field_0x4 = 0;
|
|
this->stopMotor(pad_port, true);
|
|
}
|
|
|
|
void JUTGamePad::CRumble::stopPatternedRumbleAtThePeriod() {
|
|
this->field_0x4 = (field_0x0 + field_0xc - 1) % (field_0xc);
|
|
}
|
|
|
|
#ifdef NONMATCHING
|
|
/* TODO(erin): the issue here is that doing iterator++ removes a temp var fsr.
|
|
* if you comment out iterator++, you can get it to almost match, excepting the
|
|
* instruction that does link = link->mNext which will be missing. this is a
|
|
* matching issue in general; see JKRHeap::dispose or JKRThread::searchThread,
|
|
* both of which are currently nonmatching due to the same issue.
|
|
*/
|
|
JUTGamePad* JUTGamePad::getGamePad(int pad_index) {
|
|
JSUList<JUTGamePad>* threadList = &lbl_804343E4;
|
|
JSUListIterator<JUTGamePad> iterator;
|
|
for (iterator = threadList; iterator != threadList->getEnd(); iterator++) {
|
|
JUTGamePad* pad = iterator.getObject();
|
|
if (pad_index == pad->pad_port) {
|
|
return pad;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#else
|
|
asm JUTGamePad* JUTGamePad::getGamePad(int pad_index) {
|
|
nofralloc
|
|
#include "JSystem/JUtility/JUTGamePad/asm/func_802E199C.s"
|
|
}
|
|
#endif
|
|
|
|
void JUTGamePad::CRumble::setEnabled(PADMask pad_mask) {
|
|
JUTGamePad* pGamePad;
|
|
|
|
for (s32 channel = 0; channel < 4; channel++) {
|
|
if ((/* mEnabled */ lbl_804514E8 & /* channel_mask */ (u32)lbl_803CC600[channel]) == 0) {
|
|
if (/* mStatus */ lbl_804514E4[channel] != false) {
|
|
stopMotor(channel, false);
|
|
}
|
|
|
|
pGamePad = getGamePad(channel);
|
|
if (pGamePad != NULL) {
|
|
pGamePad->rumble.stopPatternedRumble(pGamePad->pad_port);
|
|
}
|
|
}
|
|
}
|
|
|
|
lbl_804514E8 =
|
|
(PADMask)(pad_mask & (PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT));
|
|
}
|
|
|
|
void JUTGamePad::CButton::setRepeat(u32 unk0, u32 unk1, u32 unk2) {
|
|
this->field_0x20 = 0;
|
|
this->field_0x1c = 0;
|
|
this->field_0x24 = unk0;
|
|
this->field_0x28 = unk1;
|
|
this->field_0x2c = unk2;
|
|
}
|
|
|
|
bool JUTGamePad::recalibrate(PADMask pad_mask) {
|
|
int iVar2 = 0;
|
|
for (int iVar3 = 4; iVar3 != 0; iVar3--) {
|
|
if ((/* sSuppressPadReset */ lbl_804514D8 & /* channel_mask */ (u32)lbl_803CC600[iVar2]) !=
|
|
0) {
|
|
pad_mask = (PADMask)((u32)pad_mask & (lbl_803CC600[iVar2] ^ 0xffffffff));
|
|
}
|
|
iVar2++;
|
|
}
|
|
|
|
s32 sVar1 = PADRecalibrate(pad_mask);
|
|
|
|
return sVar1;
|
|
}
|
|
|
|
void JUTGamePadLongPress::checkCallback(s32 unk0, u32 unk1) {
|
|
if ((0 <= unk0) && (unk1 >= this->field_0x1c)) {
|
|
this->field_0x11 = true;
|
|
this->field_0x48[unk0] = true;
|
|
if (this->callback != NULL) {
|
|
this->callback(unk0, this, this->field_0x50);
|
|
}
|
|
}
|
|
} |