mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-23 06:34:18 -04:00
Implement & link JUTGamePad.cpp
This commit is contained in:
@@ -400,7 +400,7 @@ JSYSTEM_BASE = [
|
||||
"-lang=c++",
|
||||
"-inline on",
|
||||
"-fp fmadd",
|
||||
"-fp_contract on",
|
||||
#"-fp_contract on",
|
||||
#"-pool off", # this is wrong
|
||||
"-Cpp_exceptions off",
|
||||
"-RTTI on",
|
||||
|
||||
@@ -403,4 +403,4 @@ forced_types:
|
||||
0x800a8138: ENTRY
|
||||
0x800a8140: ENTRY
|
||||
0x800a8148: ENTRY
|
||||
0x800ab260: ENTRY
|
||||
# 0x800ab260: ENTRY
|
||||
@@ -138,6 +138,8 @@ config/dol.yml:
|
||||
bootdata/logo_nin_v:
|
||||
addrs: [0x800c30c0, 0x800c3100]
|
||||
type: vtx
|
||||
JSystem/JUtility/FontData/Ascfont_fix12.bfn:
|
||||
addrs: [0x800ab260, 0x800af3c0]
|
||||
|
||||
config/rel.yml:
|
||||
wipe1_v:
|
||||
|
||||
@@ -5,4 +5,5 @@ symbol_aligns:
|
||||
0x800b9140: 32 # align gam_win_moji1_tex to 32 bytes
|
||||
0x801f71c0: 32 # align texture_buffer_data to 32 bytes
|
||||
0x800daaa0: 32 # align texture_cache_data_func to 32 bytes
|
||||
0x80206f30: 16 # malloc.c align 16 bytes
|
||||
0x80206f30: 16 # malloc.c align 16 bytes
|
||||
0x800ab260: 32
|
||||
@@ -230,6 +230,15 @@ JSystem/JSupport/JSUInputStream.cpp:
|
||||
# .text: [0x8006e3e4, 0x8006e604]
|
||||
# .data: [0x800dedb8, 0x800dee60]
|
||||
# .sdata: [0x80218068, 0x80218088]
|
||||
JSystem/JUtility/JUTGamePad.cpp:
|
||||
.text: [0x80070274, 0x800713b0]
|
||||
.ctors: [0x800a97ac, 0x800a97b0]
|
||||
.rodata: [0x800ab240, 0x800ab260]
|
||||
.data: [0x800def60, 0x800defa0]
|
||||
.bss: [0x802070e0, 0x80207268]
|
||||
.sdata: [0x802180b8, 0x802180d0]
|
||||
.sbss: [0x80218808, 0x80218838]
|
||||
.sdata2: [0x802192c0, 0x80219300]
|
||||
dolphin/BASE/ppcarch.c:
|
||||
.text: [0x8007867c, 0x80078718]
|
||||
dolphin/os/OSArena.c:
|
||||
|
||||
@@ -2927,6 +2927,7 @@ global:
|
||||
0x800ab010: tblc
|
||||
0x800ab110: pows
|
||||
0x800ab170: saoAboutEncoding___10JUTResFont
|
||||
0x800ab260: JUTResFONT_Ascfont_fix12
|
||||
0x800af3c0: __constants
|
||||
0x800af4e0: two_over_pi
|
||||
0x800af5e8: npio2_hw
|
||||
|
||||
@@ -2,26 +2,70 @@
|
||||
#define _JSYSTEM_JUT_JUTASSERTION_H
|
||||
|
||||
#include "types.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void JC_JUTAssertion_changeDevice(u32);
|
||||
namespace JUTAssertion
|
||||
{
|
||||
void create();
|
||||
void flushMessage();
|
||||
void flushMessage_dbPrint();
|
||||
u32 getSDevice(void);
|
||||
|
||||
void showAssert_f(u32 device, char const *file, int line, char const *errormsg, ...);
|
||||
inline void showAssert(u32 device, char const *file, int line, char const *errormsg) {
|
||||
showAssert_f(device, file, line, "%s", errormsg);
|
||||
}
|
||||
|
||||
void setConfirmMessage(u32 device, char *file, int line, bool condition, const char *msg);
|
||||
void setWarningMessage_f(u32 device, char *file, int line, char const *, ...);
|
||||
inline void setWarningMessage(u32 device, char *file, int line, char const *errormsg) {
|
||||
setWarningMessage_f(device, file, line, "%s", errormsg);
|
||||
}
|
||||
|
||||
void setLogMessage_f(u32 device, char *file, int line, char const *fmt, ...);
|
||||
extern "C"
|
||||
{
|
||||
void showAssert_f_va(u32 device, const char *file, int line, const char *fmt, va_list vl);
|
||||
void setWarningMessage_f_va(u32 device, char *file, int line, const char *fmt, va_list vl);
|
||||
void setLogMessage_f_va(u32 device, char *file, int line, const char *fmt, va_list vl);
|
||||
}
|
||||
}
|
||||
|
||||
#define JUT_PANIC(...)
|
||||
#define JUT_PANIC_F(...)
|
||||
#define JUT_CONFIRM_MESSAGE(...)
|
||||
#define JUT_WARNING(...)
|
||||
#define JUT_WARNING_F(...)
|
||||
#define JUT_ASSERT(...)
|
||||
#define JUT_ASSERT_F(...)
|
||||
#define JUT_ASSERT_MSG(...)
|
||||
#define JUT_MINMAX_ASSERT(...)
|
||||
#define JUT_MAX_ASSERT(...)
|
||||
#define JUT_LOG_F(...)
|
||||
|
||||
#ifndef DEBUG
|
||||
#define JUT_ASSERT(...)
|
||||
#define JUT_ASSERT_F(...)
|
||||
#else
|
||||
|
||||
#define JUT_ASSERT(COND) \
|
||||
if ((COND) == false) \
|
||||
{ \
|
||||
JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, __LINE__, #COND); \
|
||||
OSHalt("Halt"); \
|
||||
}
|
||||
|
||||
#define JUT_ASSERT_F(COND, ...) \
|
||||
if ((COND) == false) \
|
||||
{ \
|
||||
JUTAssertion::showAssert_f(JUTAssertion::getSDevice(), __FILE__, __LINE__, __VA_ARGS__); \
|
||||
OSHalt("Halt"); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,11 +6,28 @@
|
||||
#include "dolphin/os/OSTime.h"
|
||||
#include "dolphin/pad.h"
|
||||
#include "JSystem/JKernel/JKRDisposer.h"
|
||||
#include "JSystem/JUtility/JUTAssertion.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
class JUTGamePadRecordBase
|
||||
{
|
||||
public:
|
||||
JUTGamePadRecordBase();
|
||||
virtual ~JUTGamePadRecordBase();
|
||||
virtual void read(PADStatus* status) = 0;
|
||||
virtual void write(PADStatus* status) = 0;
|
||||
|
||||
bool mActive;
|
||||
/* more that are unknown */
|
||||
|
||||
bool isActive() {
|
||||
return this->mActive;
|
||||
}
|
||||
};
|
||||
|
||||
typedef void (*JUTResetBtnCb)(int, void*);
|
||||
class JUTGamePad : public JKRDisposer
|
||||
{
|
||||
@@ -56,6 +73,13 @@ public:
|
||||
Clamped
|
||||
};
|
||||
|
||||
enum EClampMode
|
||||
{
|
||||
NoClamp,
|
||||
Clamp,
|
||||
ClampCircle
|
||||
};
|
||||
|
||||
enum EWhichStick
|
||||
{
|
||||
WhichStick_MainStick,
|
||||
@@ -67,7 +91,7 @@ public:
|
||||
virtual ~JUTGamePad();
|
||||
|
||||
void assign();
|
||||
void checkResetSwitch();
|
||||
void checkResetCallback(OSTime time);
|
||||
void clearForReset();
|
||||
static void init();
|
||||
void initList();
|
||||
@@ -75,60 +99,181 @@ public:
|
||||
static bool recalibrate(u32);
|
||||
void setButtonRepeat(u32, u32, u32);
|
||||
void update();
|
||||
void clear();
|
||||
|
||||
static void setResetCallback(JUTResetBtnCb callback, void *param_0)
|
||||
{
|
||||
C3ButtonReset::sCallback = callback;
|
||||
C3ButtonReset::sCallbackArg = param_0;
|
||||
static void checkResetSwitch();
|
||||
|
||||
static bool mListInitialized;
|
||||
static u8 mPadAssign[PAD_CONTROLLER_NUM];
|
||||
static u32 mSuppressPadReset;
|
||||
static u32 sAnalogMode;
|
||||
|
||||
static void setAnalogMode(u32 mode) {
|
||||
JUTGamePad::sAnalogMode = mode;
|
||||
PADSetAnalogMode(mode);
|
||||
}
|
||||
|
||||
static void setResetCallback(JUTResetBtnCb callback, void* arg) {
|
||||
C3ButtonReset::sCallback = callback;
|
||||
C3ButtonReset::sCallbackArg = arg;
|
||||
}
|
||||
|
||||
static void clearResetOccurred() {
|
||||
C3ButtonReset::sResetOccurred = false;
|
||||
}
|
||||
|
||||
static EClampMode getClampMode() {
|
||||
return JUTGamePad::sClampMode;
|
||||
}
|
||||
|
||||
static s8 getPortStatus(EPadPort port) {
|
||||
JUT_ASSERT(0 <= port && port < 4);
|
||||
return mPadStatus[port].err;
|
||||
}
|
||||
|
||||
bool isPushing3ButtonReset() const {
|
||||
bool pushing = false;
|
||||
|
||||
if (this->mPortNum != -1 && this->mButtonReset.mReset != false) {
|
||||
pushing = true;
|
||||
}
|
||||
|
||||
return pushing;
|
||||
}
|
||||
|
||||
int getErrorStatus() const {
|
||||
return this->mErrorStatus;
|
||||
}
|
||||
|
||||
u8 getAnalogR() const {
|
||||
return this->mButtons.mAnalogR;
|
||||
}
|
||||
|
||||
f32 getAnalogRf() const {
|
||||
return this->mButtons.mAnalogRf;
|
||||
}
|
||||
|
||||
u8 getAnalogL() const {
|
||||
return this->mButtons.mAnalogL;
|
||||
}
|
||||
|
||||
f32 getAnalogLf() const {
|
||||
return this->mButtons.mAnalogLf;
|
||||
}
|
||||
|
||||
u8 getAnalogB() const {
|
||||
return this->mButtons.mAnalogB;
|
||||
}
|
||||
|
||||
u8 getAnalogA() const {
|
||||
return this->mButtons.mAnalogA;
|
||||
}
|
||||
|
||||
int getSubStickAngle() const {
|
||||
return this->mSubStick.mAngle;
|
||||
}
|
||||
|
||||
f32 getSubStickValue() const {
|
||||
return this->mSubStick.mValue;
|
||||
}
|
||||
|
||||
f32 getSubStickY() const {
|
||||
return this->mSubStick.mY;
|
||||
}
|
||||
|
||||
f32 getSubStickX() const {
|
||||
return this->mSubStick.mX;
|
||||
}
|
||||
|
||||
int getMainStickAngle() const {
|
||||
return this->mMainStick.mAngle;
|
||||
}
|
||||
|
||||
f32 getMainStickValue() const {
|
||||
return this->mMainStick.mValue;
|
||||
}
|
||||
|
||||
f32 getMainStickY() const {
|
||||
return this->mMainStick.mY;
|
||||
}
|
||||
|
||||
f32 getMainStickX() const {
|
||||
return this->mMainStick.mX;
|
||||
}
|
||||
|
||||
u32 getTrigger() const {
|
||||
return this->mButtons.mTrigger;
|
||||
}
|
||||
|
||||
u32 getButton() const {
|
||||
return this->mButtons.mButton;
|
||||
}
|
||||
|
||||
u32 getRelease() const {
|
||||
return this->mButtons.mRelease;
|
||||
}
|
||||
|
||||
u32 getRepeat() const {
|
||||
return this->mButtons.mRepeat;
|
||||
}
|
||||
|
||||
bool testButton(u32 mask) const {
|
||||
return mButtons.mButton & mask;
|
||||
return this->mButtons.mButton & mask;
|
||||
}
|
||||
|
||||
bool testTrigger(u32 mask) const {
|
||||
return mButtons.mTrigger & mask;
|
||||
return this->mButtons.mTrigger & mask;
|
||||
}
|
||||
|
||||
s16 getPortNum() const {
|
||||
return this->mPortNum;
|
||||
}
|
||||
|
||||
JUTGamePadRecordBase* getPadRecord() const {
|
||||
return this->mPadRecord;
|
||||
}
|
||||
|
||||
JUTGamePadRecordBase* getPadReplay() const {
|
||||
return this->mPadReplay;
|
||||
}
|
||||
|
||||
class CButton
|
||||
{
|
||||
public:
|
||||
CButton();
|
||||
CButton() { this->clear(); };
|
||||
|
||||
void clear();
|
||||
void update(const PADStatus*, u32);
|
||||
void setRepeat(u32, u32, u32);
|
||||
void update(const PADStatus* padStatus, u32 buttons);
|
||||
void setRepeat(u32 mask, u32 delay, u32 frequency);
|
||||
|
||||
u32 mButton; // _0
|
||||
u32 mTrigger;
|
||||
u32 mRelease;
|
||||
u8 mAnalogA; // _C
|
||||
u8 mAnalogB; // _D
|
||||
u8 mAnalogL; // _E
|
||||
u8 mAnalogR; // _F
|
||||
f32 mAnalogLf; // _10
|
||||
f32 mAnalogRf; // _14
|
||||
u32 mRepeat;
|
||||
u32 _1C;
|
||||
u32 _20;
|
||||
u32 _24;
|
||||
u32 _28;
|
||||
u32 _2C;
|
||||
u32 mButton; // buttons held down
|
||||
u32 mTrigger; // buttons newly pressed this frame
|
||||
u32 mRelease; // buttons released this frame
|
||||
u8 mAnalogA; //
|
||||
u8 mAnalogB; //
|
||||
u8 mAnalogL; // left trigger percent
|
||||
u8 mAnalogR; // right trigger percent
|
||||
f32 mAnalogLf; // left trigger analog percent
|
||||
f32 mAnalogRf; // right trigger analog percent
|
||||
u32 mRepeat; // buttons currently marked as "repeated" triggers when held
|
||||
u32 mRepeatTimer; // frames since current button combo has been held
|
||||
u32 mRepeatLastButton; // last buttons pressed
|
||||
u32 mRepeatMask; // button mask to allow repeating trigger inputs
|
||||
u32 mRepeatDelay; // delay before beginning repeated input
|
||||
u32 mRepeatFrequency; // repeat input every X frames
|
||||
};
|
||||
|
||||
class CStick
|
||||
{
|
||||
public:
|
||||
CStick();
|
||||
CStick() { this->clear(); }
|
||||
|
||||
void clear();
|
||||
u32 update(s8 x, s8 y, JUTGamePad::EStickMode, JUTGamePad::EWhichStick);
|
||||
u32 update(s8 x, s8 y, JUTGamePad::EStickMode, JUTGamePad::EWhichStick, u32);
|
||||
u32 getButton();
|
||||
|
||||
f32 mStickX;
|
||||
f32 mStickY;
|
||||
f32 mX;
|
||||
f32 mY;
|
||||
f32 mValue;
|
||||
s16 mAngle;
|
||||
};
|
||||
@@ -136,16 +281,34 @@ public:
|
||||
class CRumble
|
||||
{
|
||||
public:
|
||||
void clear(JUTGamePad*);
|
||||
static void stopMotor(s32);
|
||||
static void stopMotorHard(s32);
|
||||
void update(u16);
|
||||
enum ERumble {
|
||||
Rumble0,
|
||||
Rumble1,
|
||||
Rumble2
|
||||
};
|
||||
|
||||
CRumble(JUTGamePad* gamePad) { this->clear(gamePad); }
|
||||
|
||||
static u8 mStatus[PAD_CONTROLLER_NUM];
|
||||
static u32 mEnabled;
|
||||
|
||||
static void startMotor(int port);
|
||||
static void stopMotor(int port);
|
||||
static void stopMotorHard(int port);
|
||||
|
||||
static bool isEnabled(u32 channel) {
|
||||
return (JUTGamePad::CRumble::mEnabled & channel) != 0;
|
||||
}
|
||||
|
||||
void clear();
|
||||
void clear(JUTGamePad* gamePad);
|
||||
void update(s16);
|
||||
void setEnable(u32);
|
||||
|
||||
u32 _0;
|
||||
u32 _4;
|
||||
u32 _8;
|
||||
u32 _C;
|
||||
u32 mFrame;
|
||||
u32 mLength;
|
||||
u8* mData;
|
||||
u32 mFrameCount;
|
||||
};
|
||||
|
||||
class C3ButtonReset {
|
||||
@@ -154,52 +317,41 @@ public:
|
||||
|
||||
static u32 sResetPattern;
|
||||
static u32 sResetMaskPattern;
|
||||
static JUTResetBtnCb sCallback;
|
||||
static void *sCallbackArg;
|
||||
static OSTime sThreshold;
|
||||
static s32 sResetOccurredPort;
|
||||
static bool sResetOccurred;
|
||||
static bool sResetSwitchPushing;
|
||||
|
||||
private:
|
||||
static JUTResetBtnCb sCallback;
|
||||
static void* sCallbackArg;
|
||||
static OSTime sThreshold;
|
||||
static bool sResetSwitchPushing;
|
||||
static bool sResetOccurred;
|
||||
static s32 sResetOccurredPort;
|
||||
|
||||
bool mReset;
|
||||
};
|
||||
|
||||
static bool isPadOk() { // fabricated
|
||||
bool ret = false;
|
||||
switch(mPadStatus[0].err) {
|
||||
case -1:
|
||||
case 0:
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PADStatus *getPadStatus(int idx) { return &mPadStatus[idx]; }
|
||||
|
||||
static JSUList<JUTGamePad> mPadList;
|
||||
static CButton mPadButton[PAD_CONTROLLER_NUM];
|
||||
static CStick mPadMStick[PAD_CONTROLLER_NUM];
|
||||
static CStick mPadSStick[PAD_CONTROLLER_NUM];
|
||||
static EStickMode sStickMode;
|
||||
static EClampMode sClampMode;
|
||||
static f32 sPressPoint;
|
||||
static f32 sReleasePoint;
|
||||
static PADStatus mPadStatus[PAD_CONTROLLER_NUM];
|
||||
|
||||
static PADStatus mPadStatus[4];
|
||||
|
||||
CButton mButtons; // _18
|
||||
CStick mMainStick; // _48
|
||||
CStick mSubStick; // _58
|
||||
CRumble mRumble; // _68
|
||||
u16 mPort; // _78
|
||||
s16 mPortNum; // _78
|
||||
s8 mErrorStatus; // _7A
|
||||
JSULink<JUTGamePad> mPtrLink; // _7C
|
||||
u32 _8C;
|
||||
u32 _90;
|
||||
JSULink<JUTGamePad> mLink; // _7C
|
||||
JUTGamePadRecordBase* mPadRecord;
|
||||
JUTGamePadRecordBase* mPadReplay;
|
||||
u32 _94;
|
||||
C3ButtonReset mButtonReset; // _98
|
||||
u8 _99;
|
||||
u8 _9A;
|
||||
u8 _9B;
|
||||
u8 _9C;
|
||||
u8 _9D; // padding?
|
||||
u8 _9E; // ^^
|
||||
u8 _9F; // ^^
|
||||
OSTime mResetTime; // _A0
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,15 @@ inline float fabsf(float x) {
|
||||
return (float)fabs((double)x);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
f64 atan2(f64, f64);
|
||||
f64 acos(f32);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -63,7 +63,7 @@ void OSInit(void);
|
||||
u32 OSGetConsoleType();
|
||||
#define OS_CONSOLE_IS_DEV() ((OSGetConsoleType() & OS_CONSOLE_DEV_MASK) != 0)
|
||||
|
||||
|
||||
#define OSHalt(msg) OSPanic(__FILE__, __LINE__, msg)
|
||||
|
||||
typedef void (*OSExceptionHandler)(u8, OSContext*);
|
||||
OSExceptionHandler __OSSetExceptionHandler(u8, OSExceptionHandler);
|
||||
|
||||
@@ -16,7 +16,6 @@ u32 __busclock AT_ADDRESS(0x800000F8);
|
||||
|
||||
#define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4)
|
||||
|
||||
#define OSTicksToCycles(ticks) (((ticks) * ((OS_CORE_CLOCK * 2) / OS_TIMER_CLOCK)) / 2)
|
||||
#define OSTicksToSeconds(ticks) ((ticks) / OS_TIMER_CLOCK)
|
||||
#define OSTicksToMilliseconds(ticks) ((ticks) / (OS_TIMER_CLOCK / 1000))
|
||||
#define OSTicksToMicroseconds(ticks) (((ticks)*8) / (OS_TIMER_CLOCK / 125000))
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PAD_CONTROLLER_NUM 4
|
||||
|
||||
#define PAD_MOTOR_STOP 0
|
||||
#define PAD_MOTOR_RUMBLE 1
|
||||
#define PAD_MOTOR_STOP_HARD 2
|
||||
|
||||
@@ -619,7 +619,8 @@ s32 JKRExpHeap::getUsedSize(u8 groupId) const
|
||||
bool JKRExpHeap::isEmpty()
|
||||
{
|
||||
u32 newSize;
|
||||
JUT_ASSERT(1269, newSize > 0);
|
||||
#line 1269
|
||||
JUT_ASSERT(newSize > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ JKRHeap* JKRHeap::becomeCurrentHeap()
|
||||
|
||||
void JKRHeap::destroy(JKRHeap* heap)
|
||||
{
|
||||
JUT_ASSERT(200, heap != 0);
|
||||
#line 200
|
||||
JUT_ASSERT(heap != 0);
|
||||
heap->destroy();
|
||||
}
|
||||
|
||||
@@ -399,13 +400,15 @@ JKRHeap::TState::TState(const JKRHeap::TState &other, const JKRHeap::TState::TLo
|
||||
|
||||
void JKRHeap::state_register(JKRHeap::TState* p, u32) const
|
||||
{
|
||||
JUT_ASSERT(1132, p != 0);
|
||||
JUT_ASSERT(1133, p->getHeap() == this);
|
||||
#line 1132
|
||||
JUT_ASSERT(p != 0);
|
||||
JUT_ASSERT(p->getHeap() == this);
|
||||
}
|
||||
|
||||
bool JKRHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const
|
||||
{
|
||||
JUT_ASSERT(1141, r1.getHeap() == r2.getHeap());
|
||||
#line 1141
|
||||
JUT_ASSERT(r1.getHeap() == r2.getHeap());
|
||||
return (r1.getCheckCode() == r2.getCheckCode());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
#include "JSystem/JUtility/JUTGamePad.h"
|
||||
|
||||
#include "MSL_C/w_math.h"
|
||||
#include "MSL_C/math.h"
|
||||
|
||||
static u32 channel_mask[PAD_CONTROLLER_NUM] = {
|
||||
0x80000000 >> 0,
|
||||
0x80000000 >> 1,
|
||||
0x80000000 >> 2,
|
||||
0x80000000 >> 3
|
||||
};
|
||||
|
||||
JUTGamePad::EStickMode JUTGamePad::sStickMode = Clamped;
|
||||
u32 JUTGamePad::C3ButtonReset::sResetPattern = START | X | B;
|
||||
f32 JUTGamePad::sPressPoint = 0.5f;
|
||||
f32 JUTGamePad::sReleasePoint = 0.25f;
|
||||
u32 JUTGamePad::C3ButtonReset::sResetMaskPattern = 0xFFFF;
|
||||
|
||||
JSUList<JUTGamePad> JUTGamePad::mPadList(false);
|
||||
PADStatus JUTGamePad::mPadStatus[PAD_CONTROLLER_NUM];
|
||||
JUTGamePad::CButton JUTGamePad::mPadButton[PAD_CONTROLLER_NUM];
|
||||
JUTGamePad::CStick JUTGamePad::mPadMStick[PAD_CONTROLLER_NUM];
|
||||
JUTGamePad::CStick JUTGamePad::mPadSStick[PAD_CONTROLLER_NUM];
|
||||
|
||||
bool JUTGamePad::mListInitialized = false;
|
||||
u8 JUTGamePad::mPadAssign[PAD_CONTROLLER_NUM];
|
||||
u32 JUTGamePad::mSuppressPadReset = 0;
|
||||
u32 JUTGamePad::sAnalogMode = 0;
|
||||
u8 JUTGamePad::CRumble::mStatus[PAD_CONTROLLER_NUM];
|
||||
u32 JUTGamePad::CRumble::mEnabled = 0;
|
||||
JUTResetBtnCb JUTGamePad::C3ButtonReset::sCallback = nullptr;
|
||||
void* JUTGamePad::C3ButtonReset::sCallbackArg = nullptr;
|
||||
OSTime JUTGamePad::C3ButtonReset::sThreshold = (OSTime)(OS_TIMER_CLOCK / 60) * 30;
|
||||
bool JUTGamePad::C3ButtonReset::sResetSwitchPushing = false;
|
||||
bool JUTGamePad::C3ButtonReset::sResetOccurred = false;
|
||||
s32 JUTGamePad::C3ButtonReset::sResetOccurredPort = 0;
|
||||
|
||||
JUTGamePad::JUTGamePad(EPadPort port)
|
||||
: mButtons(),
|
||||
mMainStick(),
|
||||
mSubStick(),
|
||||
mRumble(this),
|
||||
mLink(this),
|
||||
mButtonReset() {
|
||||
this->mPortNum = port;
|
||||
mPadAssign[port]++;
|
||||
this->initList();
|
||||
JUTGamePad::mPadList.append(&this->mLink);
|
||||
this->update();
|
||||
this->mPadRecord = nullptr;
|
||||
this->mPadReplay = nullptr;
|
||||
}
|
||||
|
||||
JUTGamePad::JUTGamePad()
|
||||
: mButtons(),
|
||||
mMainStick(),
|
||||
mSubStick(),
|
||||
mRumble(this),
|
||||
mLink(this),
|
||||
mButtonReset() {
|
||||
this->mPortNum = -1;
|
||||
this->initList();
|
||||
JUTGamePad::mPadList.append(&this->mLink);
|
||||
this->mPadRecord = nullptr;
|
||||
this->mPadReplay = nullptr;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
JUTGamePad::~JUTGamePad() {
|
||||
if (this->mPortNum != -1) {
|
||||
mPadAssign[this->mPortNum]--;
|
||||
this->mPortNum = -1;
|
||||
}
|
||||
|
||||
JUTGamePad::mPadList.remove(&this->mLink);
|
||||
}
|
||||
|
||||
void JUTGamePad::initList() {
|
||||
if (!JUTGamePad::mListInitialized) {
|
||||
JUTGamePad::mPadList.initiate();
|
||||
JUTGamePad::mListInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::init() {
|
||||
PADSetSpec(5);
|
||||
JUTGamePad::sAnalogMode = 3;
|
||||
PADSetAnalogMode(3);
|
||||
PADInit();
|
||||
}
|
||||
|
||||
void JUTGamePad::clear() {
|
||||
this->mButtonReset.mReset = false;
|
||||
}
|
||||
|
||||
void JUTGamePad::read() {
|
||||
PADRead(JUTGamePad::mPadStatus);
|
||||
PADClamp(JUTGamePad::mPadStatus);
|
||||
|
||||
u32 mask;
|
||||
u32 resetControllerMask = 0;
|
||||
|
||||
for (s32 i = 0; i < PAD_CONTROLLER_NUM; i++) {
|
||||
mask = 0x80000000 >> i;
|
||||
|
||||
if (JUTGamePad::mPadStatus[i].err == 0) {
|
||||
PADStatus* status = &JUTGamePad::mPadStatus[i];
|
||||
u32 buttons;
|
||||
|
||||
buttons = (JUTGamePad::mPadMStick[i].update(status->stickX, status->stickY, JUTGamePad::sStickMode, WhichStick_MainStick) << 24);
|
||||
buttons |= (JUTGamePad::mPadSStick[i].update(status->substickX, status->substickY, JUTGamePad::sStickMode, WhichStick_SubStick) << 16);
|
||||
JUTGamePad::mPadButton[i].update(status, buttons);
|
||||
}
|
||||
else if (JUTGamePad::mPadStatus[i].err == -1) {
|
||||
JUTGamePad::mPadMStick[i].update(0, 0, JUTGamePad::sStickMode, WhichStick_MainStick);
|
||||
JUTGamePad::mPadSStick[i].update(0, 0, JUTGamePad::sStickMode, WhichStick_SubStick);
|
||||
JUTGamePad::mPadButton[i].update(nullptr, 0);
|
||||
|
||||
if ((JUTGamePad::mSuppressPadReset & mask) == 0) {
|
||||
resetControllerMask |= mask;
|
||||
}
|
||||
}
|
||||
else {
|
||||
JUTGamePad::mPadButton[i].mTrigger = 0;
|
||||
JUTGamePad::mPadButton[i].mRelease = 0;
|
||||
JUTGamePad::mPadButton[i].mRepeat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
JSUListIterator<JUTGamePad> it;
|
||||
for (it = JUTGamePad::mPadList.getFirst(); it != JUTGamePad::mPadList.getEnd(); it++) {
|
||||
if (it->getPadReplay() != nullptr) {
|
||||
PADStatus status;
|
||||
u32 buttons;
|
||||
|
||||
it->getPadReplay()->read(&status);
|
||||
buttons = it->mMainStick.update(status.stickX, status.stickY, JUTGamePad::sStickMode, WhichStick_MainStick) << 24;
|
||||
buttons |= it->mSubStick.update(status.substickX, status.substickY, JUTGamePad::sStickMode, WhichStick_SubStick) << 16;
|
||||
it->mButtons.update(&status, buttons);
|
||||
}
|
||||
else {
|
||||
if (it->mPortNum == -1) {
|
||||
it->assign();
|
||||
}
|
||||
|
||||
it->update();
|
||||
}
|
||||
|
||||
if (it->getPadRecord() != nullptr && it->mPortNum != -1) {
|
||||
int port = it->mPortNum;
|
||||
|
||||
if (JUTGamePad::mPadStatus[port].err == 0) {
|
||||
it->getPadRecord()->write(&JUTGamePad::mPadStatus[port]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resetControllerMask != 0) {
|
||||
PADReset(resetControllerMask);
|
||||
}
|
||||
|
||||
JUTGamePad::checkResetSwitch();
|
||||
}
|
||||
|
||||
void JUTGamePad::assign() {
|
||||
for (s32 i = 0; i < PAD_CONTROLLER_NUM; i++) {
|
||||
if (JUTGamePad::mPadStatus[i].err == 0 && JUTGamePad::mPadAssign[i] == 0) {
|
||||
this->mPortNum = i;
|
||||
JUTGamePad::mPadAssign[i] = 1;
|
||||
JUTGamePad::mPadButton[i].setRepeat(this->mButtons.mRepeatMask, this->mButtons.mRepeatDelay, this->mButtons.mRepeatFrequency);
|
||||
this->mRumble.clear(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::checkResetCallback(OSTime time) {
|
||||
if (this->mPortNum != -1 && time >= JUTGamePad::C3ButtonReset::sThreshold) {
|
||||
JUTGamePad::C3ButtonReset::sResetOccurred = true;
|
||||
JUTGamePad::C3ButtonReset::sResetOccurredPort = this->mPortNum;
|
||||
|
||||
if (JUTGamePad::C3ButtonReset::sCallback != NULL) {
|
||||
(*JUTGamePad::C3ButtonReset::sCallback)(this->mPortNum, JUTGamePad::C3ButtonReset::sCallbackArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::update() {
|
||||
if (this->mPortNum != -1) {
|
||||
this->mButtons = JUTGamePad::mPadButton[this->mPortNum];
|
||||
this->mMainStick = JUTGamePad::mPadMStick[this->mPortNum];
|
||||
this->mSubStick = JUTGamePad::mPadSStick[this->mPortNum];
|
||||
this->mErrorStatus = JUTGamePad::mPadStatus[this->mPortNum].err;
|
||||
|
||||
if (JUTGamePad::C3ButtonReset::sResetOccurred == false) {
|
||||
if (JUTGamePad::C3ButtonReset::sResetPattern == (JUTGamePad::C3ButtonReset::sResetPattern & this->mButtons.mButton)) {
|
||||
if (this->mButtonReset.mReset == true) {
|
||||
this->checkResetCallback(OSGetTime() - this->mResetTime);
|
||||
}
|
||||
else {
|
||||
this->mButtonReset.mReset = true;
|
||||
this->mResetTime = OSGetTime();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->mButtonReset.mReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
this->mRumble.update(this->mPortNum);
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::checkResetSwitch() {
|
||||
if (!JUTGamePad::C3ButtonReset::sResetOccurred) {
|
||||
if (OSGetResetSwitchState() != 0) {
|
||||
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
|
||||
}
|
||||
else {
|
||||
if (JUTGamePad::C3ButtonReset::sResetSwitchPushing == true) {
|
||||
JUTGamePad::C3ButtonReset::sResetOccurred = true;
|
||||
JUTGamePad::C3ButtonReset::sResetOccurredPort = -1;
|
||||
|
||||
if (*JUTGamePad::C3ButtonReset::sCallback != nullptr) {
|
||||
(*JUTGamePad::C3ButtonReset::sCallback)(-1, JUTGamePad::C3ButtonReset::sCallbackArg);
|
||||
}
|
||||
}
|
||||
|
||||
JUTGamePad::C3ButtonReset::sResetSwitchPushing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::CButton::clear() {
|
||||
this->mButton = 0;
|
||||
this->mTrigger = 0;
|
||||
this->mRelease = 0;
|
||||
this->mRepeat = 0;
|
||||
this->mAnalogA = 0;
|
||||
this->mAnalogB = 0;
|
||||
this->mAnalogL = 0;
|
||||
this->mAnalogR = 0;
|
||||
this->mRepeatTimer = 0;
|
||||
this->mRepeatLastButton = 0;
|
||||
this->mRepeatMask = 0;
|
||||
this->mRepeatDelay = 0;
|
||||
this->mRepeatFrequency = 0;
|
||||
}
|
||||
|
||||
void JUTGamePad::CButton::update(const PADStatus* padStatus, u32 stick_buttons) {
|
||||
u32 tempButtons;
|
||||
u32 buttons;
|
||||
|
||||
if (padStatus != nullptr) {
|
||||
tempButtons = padStatus->button;
|
||||
}
|
||||
else {
|
||||
tempButtons = 0;
|
||||
}
|
||||
|
||||
buttons = stick_buttons | tempButtons;
|
||||
this->mRepeat = 0;
|
||||
|
||||
if (this->mRepeatDelay != 0) {
|
||||
if (this->mRepeatMask != 0) {
|
||||
u32 repeatButtons = buttons & this->mRepeatMask;
|
||||
this->mRepeat = 0;
|
||||
|
||||
if (repeatButtons == 0) {
|
||||
this->mRepeatLastButton = 0;
|
||||
this->mRepeatTimer = 0;
|
||||
}
|
||||
else if (this->mRepeatLastButton == repeatButtons) {
|
||||
this->mRepeatTimer++;
|
||||
if (
|
||||
this->mRepeatTimer == this->mRepeatDelay ||
|
||||
(this->mRepeatTimer > this->mRepeatDelay && ((this->mRepeatTimer - this->mRepeatDelay) % this->mRepeatFrequency) == 0)
|
||||
) {
|
||||
this->mRepeat = repeatButtons;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->mRepeat = repeatButtons & (this->mRepeatLastButton ^ 0xFFFFFFFF);
|
||||
this->mRepeatLastButton = repeatButtons;
|
||||
this->mRepeatTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->mTrigger = buttons & (buttons ^ this->mButton);
|
||||
this->mRelease = this->mButton & (buttons ^ this->mButton);
|
||||
this->mButton = buttons;
|
||||
this->mRepeat |= (this->mRepeatMask ^ 0xFFFFFFFF) & this->mTrigger;
|
||||
|
||||
if (padStatus != nullptr) {
|
||||
this->mAnalogA = padStatus->analogA;
|
||||
this->mAnalogB = padStatus->analogB;
|
||||
this->mAnalogL = padStatus->triggerLeft;
|
||||
this->mAnalogR = padStatus->triggerRight;
|
||||
}
|
||||
else {
|
||||
this->mAnalogA = 0;
|
||||
this->mAnalogB = 0;
|
||||
this->mAnalogL = 0;
|
||||
this->mAnalogR = 0;
|
||||
}
|
||||
|
||||
this->mAnalogLf = (f32)(int)this->mAnalogL / 150.0f;
|
||||
this->mAnalogRf = (f32)(int)this->mAnalogR / 150.0f;
|
||||
}
|
||||
|
||||
void JUTGamePad::CStick::clear() {
|
||||
this->mX = 0.0f;
|
||||
this->mY = 0.0f;
|
||||
this->mValue = 0.0f;
|
||||
this->mAngle = 0;
|
||||
}
|
||||
|
||||
u32 JUTGamePad::CStick::update(s8 x, s8 y, EStickMode stickMode, EWhichStick whichStick) {
|
||||
int stickMax = whichStick == WhichStick_MainStick ? 54 : 42;
|
||||
|
||||
this->mX = (f32)x / (f32)stickMax;
|
||||
this->mY = (f32)y / (f32)stickMax;
|
||||
this->mValue = sqrtf(this->mX * this->mX + this->mY * this->mY);
|
||||
|
||||
if (this->mValue > 1.0f) {
|
||||
if (stickMode == Clamped) {
|
||||
this->mX /= this->mValue;
|
||||
this->mY /= this->mValue;
|
||||
}
|
||||
|
||||
this->mValue = 1.0f;
|
||||
}
|
||||
|
||||
if (this->mValue > 0.0f) {
|
||||
if (this->mY == 0.0f) {
|
||||
if (this->mX > 0.0f) {
|
||||
this->mAngle = 0x4000;
|
||||
}
|
||||
else {
|
||||
this->mAngle = -0x4000;
|
||||
}
|
||||
}
|
||||
else {
|
||||
f32 angle = atan2(this->mX, -this->mY);
|
||||
this->mAngle = angle * 10430.379f; //((f32)0x8000 / F_PI);
|
||||
}
|
||||
}
|
||||
|
||||
return this->getButton();
|
||||
}
|
||||
|
||||
u32 JUTGamePad::CStick::getButton() {
|
||||
u32 button = 0;
|
||||
|
||||
if (-0.25f < this->mX && this->mX < 0.25f) {
|
||||
button &= ~(DPAD_LEFT | DPAD_RIGHT);
|
||||
}
|
||||
else if (this->mX <= -0.5f) {
|
||||
button |= DPAD_LEFT;
|
||||
}
|
||||
else if (this->mX >= 0.5f) {
|
||||
button |= DPAD_RIGHT;
|
||||
}
|
||||
|
||||
if (-0.25f < this->mY && this->mY < 0.25f) {
|
||||
button &= ~(DPAD_DOWN | DPAD_UP);
|
||||
}
|
||||
else if (this->mY <= -0.5f) {
|
||||
button |= DPAD_DOWN;
|
||||
}
|
||||
else if (this->mY >= 0.5f) {
|
||||
button |= DPAD_UP;
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
void JUTGamePad::CRumble::clear() {
|
||||
this->mFrame = 0;
|
||||
this->mLength = 0;
|
||||
this->mData = nullptr;
|
||||
this->mFrameCount = 0;
|
||||
JUTGamePad::CRumble::mEnabled = 0xF0000000;
|
||||
}
|
||||
|
||||
void JUTGamePad::CRumble::clear(JUTGamePad* gamePad) {
|
||||
if (0 <= gamePad->getPortNum() && gamePad->getPortNum() < PAD_CONTROLLER_NUM) {
|
||||
JUTGamePad::CRumble::mStatus[gamePad->getPortNum()] = 0;
|
||||
this->stopMotorHard(gamePad->getPortNum());
|
||||
}
|
||||
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void JUTGamePad::CRumble::startMotor(int port) {
|
||||
if (JUTGamePad::CRumble::isEnabled(channel_mask[port])) {
|
||||
PADControlMotor(port, PAD_MOTOR_RUMBLE);
|
||||
JUTGamePad::CRumble::mStatus[port] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::CRumble::stopMotor(int port) {
|
||||
if (JUTGamePad::CRumble::isEnabled(channel_mask[port])) {
|
||||
PADControlMotor(port, PAD_MOTOR_STOP);
|
||||
JUTGamePad::CRumble::mStatus[port] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::CRumble::stopMotorHard(int port) {
|
||||
if (JUTGamePad::CRumble::isEnabled(channel_mask[port])) {
|
||||
PADControlMotor(port, PAD_MOTOR_STOP_HARD);
|
||||
JUTGamePad::CRumble::mStatus[port] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline u8 getNumBit(const u8* data, int bit) {
|
||||
return (((0x80 >> (bit & 7)) & data[(u32)bit >> 3]) & 0xFF);
|
||||
}
|
||||
|
||||
void JUTGamePad::CRumble::update(s16 port) {
|
||||
if (!JUTGamePad::CRumble::isEnabled(channel_mask[port])) {
|
||||
this->mFrame = 0;
|
||||
this->mLength = 0;
|
||||
this->mData = nullptr;
|
||||
this->mFrameCount = 0;
|
||||
}
|
||||
|
||||
if (this->mLength != 0) {
|
||||
if (this->mFrame >= this->mLength) {
|
||||
JUTGamePad::CRumble::stopMotorHard(port);
|
||||
this->mLength = 0;
|
||||
}
|
||||
else {
|
||||
if (this->mFrameCount == 0) {
|
||||
if (JUTGamePad::CRumble::mStatus[port] == 0) {
|
||||
JUTGamePad::CRumble::startMotor(port);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
u8 bit = getNumBit(this->mData, this->mFrame % this->mFrameCount);
|
||||
if (bit != 0 && JUTGamePad::CRumble::mStatus[port] == 0) {
|
||||
JUTGamePad::CRumble::startMotor(port);
|
||||
}
|
||||
else if (bit == 0 && JUTGamePad::CRumble::mStatus[port] != 0) {
|
||||
JUTGamePad::CRumble::stopMotorHard(port);
|
||||
}
|
||||
}
|
||||
|
||||
this->mFrame++;
|
||||
}
|
||||
}
|
||||
|
||||
void JUTGamePad::CButton::setRepeat(u32 repeatMask, u32 repeatDelay, u32 repeatFreq) {
|
||||
this->mRepeatLastButton = 0;
|
||||
this->mRepeatTimer = 0;
|
||||
this->mRepeatMask = repeatMask;
|
||||
this->mRepeatDelay = repeatDelay;
|
||||
this->mRepeatFrequency = repeatFreq;
|
||||
}
|
||||
|
||||
bool JUTGamePad::recalibrate(u32 channels) {
|
||||
u32 channelMasks[PAD_CONTROLLER_NUM] = {
|
||||
0x80000000 >> 0,
|
||||
0x80000000 >> 1,
|
||||
0x80000000 >> 2,
|
||||
0x80000000 >> 3
|
||||
};
|
||||
|
||||
for (int i = 0; i < PAD_CONTROLLER_NUM; i++) {
|
||||
if ((JUTGamePad::mSuppressPadReset & channelMasks[i]) != 0) {
|
||||
channels &= channelMasks[i] ^ 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
return PADRecalibrate(channels);
|
||||
}
|
||||
Reference in New Issue
Block a user