diff --git a/configure.py b/configure.py index f8fadf0c..be944602 100755 --- a/configure.py +++ b/configure.py @@ -1078,8 +1078,8 @@ def MatchingFor(*versions): "Kameda", [], [ - Object(NonMatching, "Kameda/Motor.cpp"), - Object(NonMatching, "Kameda/MotorManager.cpp"), + Object(Matching, "Kameda/Motor.cpp"), + Object(Matching, "Kameda/MotorManager.cpp"), Object(Matching, "Kameda/J2DManager.cpp"), Object(Matching, "Kameda/Task.cpp"), Object(NonMatching, "Kameda/Goal2D.cpp"), diff --git a/include/Kameda/Motor.h b/include/Kameda/Motor.h index 27eda56c..c2ce819f 100644 --- a/include/Kameda/Motor.h +++ b/include/Kameda/Motor.h @@ -1,41 +1,82 @@ #ifndef MOTOR_H #define MOTOR_H -#include "types.h" #include "JSystem/JKernel/JKRHeap.h" #include "JSystem/JORReflexible.h" #include "Kaneshige/HioMgr.h" #include "Osako/kartPad.h" +#include "types.h" -class MotorParam : public JORReflexible { +class MotorParam : public JORReflexible +{ public: - // Inline/Unused MotorParam(); virtual ~MotorParam() {} + + struct + { + bool flag; // 0x48 + u8 _49[0x100 - 1]; // 0x49 + } mUnknownContainer[4]; + + f32 mUnknownFloat; // 0x448 + u8 mUnknownValue; // 0x44c + bool mUnknownFlag; // 0x44d }; -class MotorHioNode : public HioNode { +class MotorHioNode : public HioNode +{ public: - MotorHioNode(); + MotorHioNode() : HioNode("モーター", &mParam, 0, 0) {} virtual ~MotorHioNode() {} MotorParam mParam; }; -class Motor { // Autogenerated +class Motor +{ public: - Motor(JKRHeap *); // 0x801304d8 - void init(); // 0x801305c4 - ~Motor(); // 0x80130668 - void exec(); // 0x8013073c - void triggerWave(KartGamePad *, int); // 0x80130ad8 - void powerWave(KartGamePad *, f32, u8, u8); // 0x80130b50 - void stop(); // 0x80130cbc - static const char *mPatternWave[26]; // 0x803942e8 - // Inline/Unused - void loopWave(KartGamePad *, int); - void loopWave(KartGamePad *, char *); - void checkLoop(int, const char *); - void triggerWave(KartGamePad *, char *); -}; // class Motor -#endif // MOTOR_H + Motor(JKRHeap *heap); // 0x801304d8 + void init(); // 0x801305c4 + ~Motor(); // 0x80130668 + void exec(); // 0x8013073c + void loopWave(KartGamePad *, int); // Unused + void loopWave(KartGamePad *, char *); // Unused + void checkLoop(int, const char *); // Unused + void triggerWave(KartGamePad *kartGamePad, int index); // 0x80130ad8 + void triggerWave(KartGamePad *, char *); // Unused + void powerWave(KartGamePad *kartGamePad, + f32 strength, + u8 phase1Duration, + u8 phase2Duration); // 0x80130b50 + void stop(); // 0x80130cbc + +private: + static const char *mPatternWave[26]; // 0x803942e8 + + struct + { + KartGamePad *mKartGamePad; // 0x0 + + struct + { + const char *pattern; // 0x4 + s32 pos; // 0x8 + } mDriverMotor[4]; + + struct + { + const char *pattern; // 0x24 + s32 pos; // 0x28 + } mPartnerMotor[4]; + + s32 mUnknown[4]; // 0x44 + } mMotorData[4]; + + s32 mUnknown; // 0x150 + s32 mSomeCount; // 0x154 + + MotorHioNode *mHioNode; // 0x158 (344) +}; + +#endif // MOTOR_H diff --git a/include/Kameda/MotorManager.h b/include/Kameda/MotorManager.h index 7b1f4e9b..9d454256 100644 --- a/include/Kameda/MotorManager.h +++ b/include/Kameda/MotorManager.h @@ -2,13 +2,12 @@ #define MOTORMANAGER_H #include "JSystem/JKernel/JKRDisposer.h" - +#include "Kameda/Motor.h" #include "types.h" class MotorManager : JKRDisposer -{ // Autogenerated +{ public: - // Global enum MotorType { MotorType_0, @@ -33,24 +32,34 @@ class MotorManager : JKRDisposer MotorType_19, MotorType_20, MotorType_21, - MotorType_22 + MotorType_22, + MotorType_23, + MotorType_24, + MotorType_MAX, }; - MotorManager(JKRHeap *); // 0x80130e58 - virtual ~MotorManager(); // 0x80130ee0 - void reset(); // 0x80130f48 - void exec(); // 0x80130fc0 - void setMotor(MotorType, int); // 0x8013103c - void setAwardMotor(MotorType); // 0x80131218 - void setPowerMotor(int, f32, u8, u8); // 0x801312e8 + MotorManager(JKRHeap *heap); // 0x80130e58 + virtual ~MotorManager(); // 0x80130ee0 - static MotorManager *getManager() { return mThis; }; + void reset(); // 0x80130f48 + void exec(); // 0x80130fc0 + + static void setMotor(MotorType motorType, int kart); // 0x8013103c + static void setAwardMotor(MotorType motorType); // 0x80131218 + static void setPowerMotor(int kart, + f32 strength, + u8 phase1Duration, + u8 phase2Duration); // 0x801312e8 - static int mCountFrame[0x19]; // 0x803fb640 - static MotorManager *mThis; // 0x80416280 + static MotorManager *getManager() { return mThis; }; private: - u8 _0[8]; + static int mCountFrame[8][MotorType_MAX]; // 0x803fb640 + + static MotorManager *mThis; // 0x80416280 + + Motor *mMotor; // 0x18 + int mKartNumber; // 0x1c }; -#endif +#endif // MOTORMANAGER_H diff --git a/include/Kameda/SequenceInfo.h b/include/Kameda/SequenceInfo.h index c785ca40..7bca7fbf 100644 --- a/include/Kameda/SequenceInfo.h +++ b/include/Kameda/SequenceInfo.h @@ -153,7 +153,11 @@ class SequenceInfo KartGamePad *_18; // 18 // Size: 0x1c } _318[2]; // 318 - int _350; // + +public: + int _350; // 350 (number of [human] players?) + +private: int _354; // ERaceLevel mLevel; // u8 _35c; // diff --git a/include/Osako/kartPad.h b/include/Osako/kartPad.h index 8be1c29c..4bbeb8d2 100644 --- a/include/Osako/kartPad.h +++ b/include/Osako/kartPad.h @@ -18,6 +18,7 @@ class KartGamePad : public JUTGamePad PORT_2 = 1, PORT_3 = 2, PORT_4 = 3, + PORT_COUNT = 4, }; enum PadType diff --git a/src/Kameda/Motor.cpp b/src/Kameda/Motor.cpp index bad2d640..b426c9ba 100644 --- a/src/Kameda/Motor.cpp +++ b/src/Kameda/Motor.cpp @@ -1,5 +1,24 @@ #include "Kameda/Motor.h" +#include "Kameda/PauseManager.h" +#include "Kaneshige/RaceMgr.h" +#include "Osako/SystemRecord.h" +#include "Osako/kartPad.h" +#include "Yamamoto/kartCtrl.h" +#include "dolphin/pad.h" + +MotorParam::MotorParam() +{ + mUnknownContainer[0].flag = false; + mUnknownContainer[1].flag = false; + mUnknownContainer[2].flag = false; + mUnknownContainer[3].flag = false; + mUnknownFloat = 1.0f; + mUnknownValue = 0x1e; + mUnknownFlag = false; +} + +// clang-format off const char *Motor::mPatternWave[26] = { "/", "*****---**--*", @@ -24,23 +43,295 @@ const char *Motor::mPatternWave[26] = { "********/", "**------*-----*---*--*-*-******-*-*--*--*---*----*-----*------*-------*--------*---------*----------*", "***-------*-------*------*-----*----*----*---*---*---*---*---*--*--*--*-*-*-*-*-*-*-*-*-*-*-*--*--*--*--*---*---*---*---*---*---*---*---*----*----*-----*-----*-----*------*------*------*-------*-------*-------*-------*--------*----------*------------*", - "******---*-------*/", - "******-***-**-*--*------*", - "*****--**--*" + "******---*-------*/", + "******-***-**-*--*------*", + "*****--**--*", }; +// clang-format on + +Motor::Motor(JKRHeap *heap) +{ + mHioNode = new (heap, 0) MotorHioNode(); + + init(); +} + +void Motor::init() +{ + for (int i = 0; i < KartGamePad::PORT_COUNT; ++i) + { + mMotorData[i].mKartGamePad = nullptr; + + for (int j = 0; j < 4; ++j) + { + mMotorData[i].mDriverMotor[j].pattern = mPatternWave[0]; + mMotorData[i].mDriverMotor[j].pos = -1; + + mMotorData[i].mUnknown[j] = 0; + + mMotorData[i].mPartnerMotor[j].pattern = mPatternWave[0]; + mMotorData[i].mPartnerMotor[j].pos = -1; + } + } + + mUnknown = 0; + mSomeCount = 0; + + stop(); +} + +Motor::~Motor() { delete mHioNode; } + +void Motor::exec() +{ + if (!(gSystemRecord.isRumble() && !PauseManager::tstPause() && + !RaceMgr::getManager()->isRaceEnd() && + RaceMgr::getManager()->getRacePhase() != PHASE_CRS_DEMO && + !RaceMgr::getManager()->isReplayMode() && !RaceMgr::getManager()->isWaitDemoMode())) + { + stop(); + return; + } + + for (int i = 0; i < KartGamePad::PORT_COUNT; ++i) + { + KartGamePad *kartGamePad = mMotorData[i].mKartGamePad; + if (!kartGamePad) + continue; + + int patternValue = '/'; + + for (int j = 0; j < 4; ++j) + { + s32 pos = mMotorData[i].mDriverMotor[j].pos; + if (pos >= 0 && mMotorData[i].mUnknown[j]) + { + if (mMotorData[i].mDriverMotor[j].pattern[pos] == '0') + { + mMotorData[i].mDriverMotor[j].pos = pos + 1; + } + + if (mMotorData[i].mDriverMotor[j].pattern[mMotorData[i].mDriverMotor[j].pos] == '1') + { + for (pos = 0; mMotorData[i].mDriverMotor[j].pattern[pos] != '\0'; ++pos) + { + if (mMotorData[i].mDriverMotor[j].pattern[pos] == '0') + break; + } + mMotorData[i].mDriverMotor[j].pos = pos + 1; + } + + if (mMotorData[i].mDriverMotor[j].pattern[mMotorData[i].mDriverMotor[j].pos] == + '\0') + { + mMotorData[i].mDriverMotor[j].pos = 0; + } + } + + pos = mMotorData[i].mPartnerMotor[j].pos; + if (pos >= 0) + { + if (mMotorData[i].mPartnerMotor[j].pattern[pos] == '0') + { + mMotorData[i].mPartnerMotor[j].pos = pos + 1; + } + + if (mMotorData[i].mPartnerMotor[j].pattern[mMotorData[i].mPartnerMotor[j].pos] == + '1') + { + for (pos = 0; mMotorData[i].mPartnerMotor[j].pattern[pos] != '\0'; ++pos) + { + if (mMotorData[i].mPartnerMotor[j].pattern[pos] == '0') + break; + } + mMotorData[i].mPartnerMotor[j].pos = pos + 1; + } + + if (mMotorData[i].mPartnerMotor[j].pattern[mMotorData[i].mPartnerMotor[j].pos] == + '\0') + { + mMotorData[i].mPartnerMotor[j].pos = -1; + } + } + + pos = mMotorData[i].mDriverMotor[j].pos; + if (pos >= 0 && mMotorData[i].mUnknown[j]) + { + int value = mMotorData[i].mDriverMotor[j].pattern[pos]; + if (value == '*') + { + patternValue = value; + } + else if (value == '-' && patternValue != '*') + { + patternValue = value; + } + } + + s32 partnerPatternPos = mMotorData[i].mPartnerMotor[j].pos; + if (partnerPatternPos >= 0) + { + int value = mMotorData[i].mPartnerMotor[j].pattern[partnerPatternPos]; + if (value == '*') + { + patternValue = value; + } + else if (value == '-' && patternValue != '*') + { + patternValue = value; + } + } + + if (pos >= 0) + { + mMotorData[i].mDriverMotor[j].pos += 1; + } + if (mMotorData[i].mPartnerMotor[j].pos >= 0) + { + mMotorData[i].mPartnerMotor[j].pos += 1; + } + + mMotorData[i].mUnknown[j] = 0; + } + + switch (patternValue) + { + case '-': + { + KartGamePad::PadPort padPort = mMotorData[i].mKartGamePad->getPadPort(); + if (0 <= padPort && padPort < KartGamePad::PORT_COUNT) + { + PADControlMotor(padPort, 0); + } + break; + } + case '*': + { + KartGamePad::PadPort padPort = mMotorData[i].mKartGamePad->getPadPort(); + if (0 <= padPort && padPort < KartGamePad::PORT_COUNT) + { + PADControlMotor(padPort, 1); + } + break; + } + case '/': + { + KartGamePad::PadPort padPort = mMotorData[i].mKartGamePad->getPadPort(); + if (0 <= padPort && padPort < KartGamePad::PORT_COUNT) + { + PADControlMotor(padPort, 2); + } + break; + } + default: +#line 363 + JUT_ASSERT(0); + } + } +} + +void Motor::loopWave(KartGamePad *, int) {} +void Motor::loopWave(KartGamePad *, char *) {} +void Motor::checkLoop(int, const char *) {} + +void Motor::triggerWave(KartGamePad *kartGamePad, int index) +{ + if (!kartGamePad) + return; + + KartGamePad::PadPort padPort = kartGamePad->getPadPort(); + if (0 <= padPort && padPort < KartGamePad::PORT_COUNT) + { + mMotorData[padPort].mKartGamePad = kartGamePad; + + mMotorData[padPort].mPartnerMotor[mSomeCount].pattern = mPatternWave[index]; + mMotorData[padPort].mPartnerMotor[mSomeCount].pos = 0; + + if (++mSomeCount >= 4) + { + mSomeCount = 0; + } + } +} + +void Motor::triggerWave(KartGamePad *, char *) {} + +void Motor::powerWave(KartGamePad *kartGamePad, f32 strength, u8 phase1Duration, u8 phase2Duration) +{ + KartGamePad::PadPort padPort = kartGamePad->getPadPort(); + if (0 <= padPort && padPort < KartGamePad::PORT_COUNT) + { + static char patterns[KartGamePad::PORT_COUNT][512]; + + f32 power = 0.0f; + + for (s32 duration = phase1Duration + phase2Duration, i = 0; duration > 0; --duration) + { + if (i < phase1Duration) + { + power += strength; + + if (power >= 1.0f) + { + power = power - 1.0f; + patterns[padPort][i] = '*'; + } + else + { + patterns[padPort][i] = '-'; + } + } + else + { + power += strength * (1.0f - (i - phase1Duration) / (f32)phase2Duration); + + if (power >= 1.0f) + { + power = power - 1.0f; + patterns[padPort][i] = '*'; + } + else + { + patterns[padPort][i] = '-'; + } + } + + ++i; + } -Motor::Motor(JKRHeap *) {} + char *pattern = patterns[padPort]; + pattern[phase1Duration + phase2Duration] = '\0'; -void Motor::init() {} + if (!kartGamePad) + return; -Motor::~Motor() {} + KartGamePad::PadPort padPort = kartGamePad->getPadPort(); + if (0 <= padPort && padPort < KartGamePad::PORT_COUNT) + { + mMotorData[padPort].mKartGamePad = kartGamePad; -void Motor::exec() {} + mMotorData[padPort].mPartnerMotor[mSomeCount].pattern = pattern; + mMotorData[padPort].mPartnerMotor[mSomeCount].pos = 0; -void Motor::triggerWave(KartGamePad *, int) {} + if (++mSomeCount >= 4) + { + mSomeCount = 0; + } + } + } +} -void Motor::powerWave(KartGamePad *, f32, u8, u8) {} +void Motor::stop() +{ + PADControlMotor(0, 0); + PADControlMotor(1, 0); + PADControlMotor(2, 0); + PADControlMotor(3, 0); -void Motor::stop() {} + for (int i = 0; i < RaceMgr::getManager()->getKartNumber(); ++i) + { + KartCtrl::getKartCtrl()->getKartBody(i)->getHandle()->StopMotor(); + } +} -#include "JSystem/JAudio/JASFakeMatch2.h" +#include "JSystem/JAudio/JASFakeMatch2.h" // For static initializer diff --git a/src/Kameda/MotorManager.cpp b/src/Kameda/MotorManager.cpp index f48c3caf..a7d99d06 100644 --- a/src/Kameda/MotorManager.cpp +++ b/src/Kameda/MotorManager.cpp @@ -1,21 +1,113 @@ #include "Kameda/MotorManager.h" -#include "mathHelper.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "Kameda/SequenceInfo.h" +#include "Kaneshige/RaceMgr.h" +#include "Osako/kartPad.h" +#include "mathHelper.h" // For unused data + +int MotorManager::mCountFrame[8][MotorManager::MotorType_MAX]; -int MotorManager::mCountFrame[0x19]; MotorManager *MotorManager::mThis; -MotorManager::MotorManager(JKRHeap *) {} +MotorManager::MotorManager(JKRHeap *heap) +{ + if (!heap) + { + heap = JKRHeap::getCurrentHeap(); + } + + mThis = this; + + mMotor = new (heap, 0) Motor(heap); + mKartNumber = RaceMgr::getManager()->getKartNumber(); +} + +MotorManager::~MotorManager() { delete mMotor; } + +void MotorManager::reset() +{ + mMotor->init(); + + for (s32 i = 0; i < mKartNumber; ++i) + { + for (s32 j = 0; j < MotorType_MAX; ++j) + { + mCountFrame[i][j] = 0; + } + } +} + +void MotorManager::exec() +{ + mMotor->exec(); + + for (s32 i = 0; i < mKartNumber; ++i) + { + for (s32 j = 0; j < MotorType_MAX; ++j) + { + mCountFrame[i][j] += 1; + } + } +} + +void MotorManager::setMotor(MotorManager::MotorType motorType, int kart) +{ +#line 117 + JUT_MINMAX_ASSERT(0, motorType, MotorType_MAX); + JUT_MINMAX_ASSERT(0, kart, 8); + + RaceMgr *raceMgr = RaceMgr::getManager(); + if (!raceMgr->isRaceEnd() && !raceMgr->getKartChecker(kart)->isDead()) + { + if (mCountFrame[kart][motorType] >= 10) + { + mCountFrame[kart][motorType] = 0; + + KartGamePad *kartGamePad = KartCtrl::getKartCtrl()->getPad(kart); + KartGamePad *kartGamePadCo = KartCtrl::getKartCtrl()->getCoPad(kart); + + s32 patternIndex = motorType + 1; + mThis->mMotor->triggerWave(kartGamePad, patternIndex); + + if ((KartCtrl::getKartCtrl()->GetGameStatus(kart) & 1) != 0) + { + mThis->mMotor->triggerWave(kartGamePadCo, patternIndex); + } + } + } +} -MotorManager::~MotorManager() {} +void MotorManager::setAwardMotor(MotorManager::MotorType motorType) +{ +#line 157 + JUT_MINMAX_ASSERT(0, motorType, MotorType_MAX); -void MotorManager::reset() {} + s32 patternIndex = motorType + 1; + for (s32 i = 0; i < gSequenceInfo._350; ++i) + { + mThis->mMotor->triggerWave(gpaKartPad[i], patternIndex); + } +} -void MotorManager::exec() {} +void MotorManager::setPowerMotor(int kart, f32 strength, u8 phase1Duration, u8 phase2Duration) +{ +#line 176 + JUT_MINMAX_ASSERT(0, kart, 8); -void MotorManager::setMotor(MotorManager::MotorType, int) {} + RaceMgr *raceMgr = RaceMgr::getManager(); + if (!raceMgr->isRaceEnd() && !raceMgr->getKartChecker(kart)->isDead()) + { + KartGamePad *kartGamePad = KartCtrl::getKartCtrl()->getPad(kart); + KartGamePad *kartGamePadCo = KartCtrl::getKartCtrl()->getCoPad(kart); -void MotorManager::setAwardMotor(MotorManager::MotorType) {} + mThis->mMotor->powerWave(kartGamePad, strength, phase1Duration, phase2Duration); -void MotorManager::setPowerMotor(int, f32, u8, u8) {} + if ((KartCtrl::getKartCtrl()->GetGameStatus(kart) & 1) != 0) + { + mThis->mMotor->powerWave(kartGamePadCo, strength, phase1Duration, phase2Duration); + } + } +} -#include "JSystem/JAudio/JASFakeMatch2.h" +#include "JSystem/JAudio/JASFakeMatch2.h" // For static initializer