summaryrefslogtreecommitdiff
path: root/src/egg/core/eggController.cpp
diff options
context:
space:
mode:
authorElijah Thomas <42302100+elijah-thomas774@users.noreply.github.com>2024-05-12 13:03:51 -0400
committerGitHub <noreply@github.com>2024-05-12 13:03:51 -0400
commitebd2338333da42ee9d06184e259e1d894ace879e (patch)
tree422782381f8557ee7dc6b404b4030a484e9726c2 /src/egg/core/eggController.cpp
parentbab615cc58e6e20e10ca7e51113bbf9b0f50af4d (diff)
parentebdf0bb3818334acf76981c59a876e9405ff315c (diff)
Merge pull request #20 from robojumper/controller-stuff
Match eggDisposer, some eggController stuff
Diffstat (limited to 'src/egg/core/eggController.cpp')
-rw-r--r--src/egg/core/eggController.cpp391
1 files changed, 386 insertions, 5 deletions
diff --git a/src/egg/core/eggController.cpp b/src/egg/core/eggController.cpp
index 645eca40..fb359817 100644
--- a/src/egg/core/eggController.cpp
+++ b/src/egg/core/eggController.cpp
@@ -1,14 +1,395 @@
#include "egg/core/eggController.h"
+#include "egg/core/eggAllocator.h"
+#include "egg/core/eggExpHeap.h"
+#include "egg/core/eggSystem.h"
+#include "MSL_C/string.h"
+#include "rvl/VI.h"
+EGG::NullController null_controller;
+namespace EGG {
-namespace EGG
-{
-
-void CoreControllerMgr::beginFrame() {
+CoreControllerMgr *CoreControllerMgr::sInstance;
+CoreControllerMgr::T__Disposer *CoreControllerMgr::T__Disposer::sStaticDisposer;
+ControllerFactory CoreControllerMgr::sCoreControllerFactory;
+ConnectCallback CoreControllerMgr::sConnectCallback;
+// This controls whether EggController registers an allocator within the WPAD driver
+bool CoreControllerMgr::sUseBuiltinWpadAllocator;
+static Allocator *sWPADAllocator;
+
+/* 0x80498F90 */ void CoreStatus::init() {
+ memset(this, 0, sizeof(CoreStatus));
+}
+
+/* 0x80498FA0 */ u32 CoreStatus::getFSStickButton() const {
+ f32 button = this->fsStickButton;
+ u32 result = 0;
+ // TODO what are these flags and why is this code so weird?
+
+ if (!(-0.25f < button) || !(button < 0.25f)) {
+ if (button <= -0.5f) {
+ result = 0;
+ result |= 0x40000;
+ } else if (button >= 0.5f) {
+ result = 0;
+ result |= 0x80000;
+ }
+ }
+
+ button = this->fsStickButton2;
+ if (!(-0.25f < button) || !(button < 0.25f)) {
+ if (button <= -0.5f) {
+ result &= ~0x10000;
+ result |= 0x20000;
+ } else if (button >= 0.5f) {
+ result &= ~0x20000;
+ result |= 0x10000;
+ }
+ }
+
+ return result;
+}
+
+/* 0x80499050 */ CoreController::CoreController() : mDpdPos(), mAccel(), mAccelFlags(), mFlag(0) {
+ this->mRumbleMgr = nullptr;
+ this->mButtonHeld = 0;
+ this->mButtonTriggered = 0;
+ this->mButtonReleased = 0;
+ this->sceneReset();
+ this->mFlag.makeAllZero();
+}
+
+/* 0x804990B0 */ void CoreController::sceneReset() {
+ this->mAccel.set(0.0, 0.0, 0.0);
+ this->mDpdPos.x = 0.0;
+ this->mDpdPos.y = 0.0;
+ this->field_0xf28 = 0;
+ this->mPostureMatrixPrev.makeIdentity();
+ this->mPostureMatrix.makeIdentity();
+ this->mMaxAccelFrameTime = 10;
+ this->mMaxAccelDiff = 0.13;
+ this->mPrevAccel.set(0.0, 0.0, 0.0);
+ this->mAccelFlags.makeAllZero();
+ this->mAccelFrameTimeZ = 0;
+ this->mAccelFrameTimeY = 0;
+ this->mAccelFrameTimeX = 0;
+ this->mMotorPattern = 0;
+ this->mMotorFrameDuration = 0;
+ this->mEnableMotor = false;
+ this->mMotorPatternLength = 0x20;
+ this->mMotorPatternPos = 0x1f;
+ this->stopRumbleMgr();
+}
+
+/* 0x80499170 */ Vector2f CoreController::getDpdRawPos() const {
+ return Vector2f(this->coreStatus[0].dpdRawX, this->coreStatus[0].dpdRawY);
+}
+
+/* 0x80499190 */ s32 CoreController::getDpdDistance() const {
+ return this->coreStatus[0].dpdDistance;
+}
+
+// TODO
+extern "C" void fn_803DB1E0(s32 channel, bool arg);
+
+/* 0x804991A0 */ void CoreController::startMotor() {
+ fn_803DB1E0(mChannelID, true);
+}
+
+/* 0x804991B0 */ void CoreController::stopMotor() {
+ fn_803DB1E0(mChannelID, false);
+}
+
+/* 0x804991C0 */ void CoreController::createRumbleMgr(u8 numUnits) {
+ this->mRumbleMgr = new ControllerRumbleMgr();
+ this->mRumbleMgr->createUnit(numUnits, this);
+}
+
+/* 0x80499220 */ void CoreController::startPatternRumble(const char *pattern, int duration, bool bGrabActive) {
+ if (this->mRumbleMgr) {
+ this->mRumbleMgr->startPattern(pattern, duration, bGrabActive);
+ }
+}
+
+/* 0x80499240 */ void CoreController::stopRumbleMgr() {
+ if (this->mRumbleMgr) {
+ this->mRumbleMgr->stop();
+ }
+}
+
+/* 0x80499260 */ CoreStatus *CoreController::getCoreStatus(s32 idx) {
+ return &this->coreStatus[idx];
+}
+
+/* 0x80499270 */ void CoreController::calc_posture_matrix(Matrix34f &mat, bool someBool) {
+ if (!someBool || this->mAccelFlags.onBit(7)) {
+ Vector3f vec = Vector3f(-mat(2, 3), -mat(2, 2), -mat(2, 1));
+ Vector3f vec3 = vec;
+ vec.normalise();
+ // TODO lots of inlined math
+ }
+}
+
+/* 0x80499660 */ void CoreController::beginFrame(void *padStatus) {}
+
+/* 0x80499A60 */ void CoreController::endFrame() {
+ this->mAccel(0) = this->coreStatus[0].accel[0];
+ this->mAccel(1) = this->coreStatus[0].accel[1];
+ this->mAccel(2) = this->coreStatus[0].accel[2];
+ this->mDpdPos = this->getDpdRawPos();
+}
+
+/* 0x80499AC0 */ f32 CoreController::getFreeStickX() const {
+ if (this->coreStatus[0].field_0x00[0x5C] == 0) {
+ return 0.0;
+ }
+ return ((f32 *)(&this->coreStatus[0].field_0x00))[0x18];
+}
+
+/* 0x80499AE0 */ f32 CoreController::getFreeStickY() const {
+ if (this->coreStatus[0].field_0x00[0x5C] == 0) {
+ return 0.0;
+ }
+ return ((f32 *)(&this->coreStatus[0].field_0x00))[0x19];
+}
+
+/* 0x80499B00 */ CoreControllerMgr::T__Disposer::~T__Disposer() {
+ if (this == CoreControllerMgr::T__Disposer::sStaticDisposer) {
+ deleteInstance();
+ }
+}
+
+/* 0x80499B80 */ CoreControllerMgr *CoreControllerMgr::createInstance() {
+ if (CoreControllerMgr::sInstance == nullptr) {
+ CoreControllerMgr *mgr = new CoreControllerMgr();
+ CoreControllerMgr::sInstance = mgr;
+ CoreControllerMgr::T__Disposer::sStaticDisposer = &mgr->mDisposer;
+ }
+ return CoreControllerMgr::sInstance;
+}
+
+/* 0x80499BD0 */ void CoreControllerMgr::deleteInstance() {
+ CoreControllerMgr::sInstance = nullptr;
+ CoreControllerMgr::T__Disposer::sStaticDisposer = nullptr;
+}
+
+/* 0x80499BE0 */ EGG::CoreController *CoreControllerMgr::getNthController(s32 n) {
+ return this->mControllers(n);
+}
+
+/* 0x80499C70 */ void *CoreControllerMgr::allocThunk(size_t size) {
+ return sWPADAllocator->alloc(size);
+}
+
+/* 0x80499C90 */ int CoreControllerMgr::deleteThunk(void *ptr) {
+ sWPADAllocator->free(ptr);
+ return 1;
+}
+
+/* 0x80499CD0 */ void CoreControllerMgr::connectCallback(int a1, int a2) {
+ int args[] = {a1, a2};
+ if (sConnectCallback != nullptr) {
+ (sConnectCallback)(args);
+ }
+}
+
+extern "C" long lbl_80574EE8;
+// TODO headers
+extern "C" void fn_803D9400(void *a, void *b);
+extern "C" void fn_803F2040(void *a, int b);
+extern "C" void fn_803F26B0(int a, void *b);
+
+/* 0x80499D10 */ CoreControllerMgr::CoreControllerMgr() {
+ const int idxes[] = {0, 1, 2, 3};
+ if (sUseBuiltinWpadAllocator == false) {
+ Heap *heap = ExpHeap::create(lbl_80574EE8, BaseSystem::mConfigData->mRootHeapMem2, 0);
+ heap->mName = "EGG::CoreControllerMgr";
+ sWPADAllocator = new Allocator(heap, 0x20);
+ fn_803D9400(allocThunk, deleteThunk);
+ }
+ fn_803F2040(field_0x20, 0x40);
+ beginFrame();
+ endFrame();
+ VIWaitForRetrace();
+
+ for (int i = 0; i < 4; i++) {
+ fn_803F26B0(idxes[i], connectCallback);
+ }
+
+ // TODO these allocate calls cause the relevant inline buffer functions to be moved
+ // from the bottom of the TU to after this ctor. How to fix?
+ mControllers.allocate(4, 0);
+ for (int i = 0; i < 4; i++) {
+ if (sCoreControllerFactory != nullptr) {
+ mControllers(i) = (sCoreControllerFactory)();
+ } else {
+ mControllers(i) = new CoreController();
+ }
+ }
+
+ mDevTypes.allocate(4, 0);
+ for (int i = 0; i < 4; i++) {
+ mControllers(i)->mChannelID = idxes[i];
+ mDevTypes(i) = (eCoreDevType)0xfd;
+ }
+ field_0x10A0 = 0;
+}
+
+/* 0x8049A130 */ void CoreControllerMgr::beginFrame() {
for (int i = 0; i < mControllers.getSize(); ++i) {
mControllers(i)->beginFrame(NULL);
}
-}
+}
+
+/* 0x8049A1E0 */ void CoreControllerMgr::endFrame() {
+ for (int i = 0; i < mControllers.mSize; i++) {
+ mControllers(i)->endFrame();
+ // TODO WPADprobe
+ // Update device type after probe?
+ }
+}
+
+/* 0x8049A3B0 */ void ControllerRumbleUnit::init() {
+ this->mPattern = nullptr;
+ this->mPatternPos = nullptr;
+ this->mTimer = 0;
+ this->mIntensity = 0.0;
+ this->mRampUp = 0.0;
+ this->mFlag.makeAllZero();
+}
+
+/* 0x8049A3E0 */ void ControllerRumbleUnit::startPattern(const char *pattern, int duration) {
+ this->mPattern = pattern;
+ this->mPatternPos = pattern;
+
+ this->mFlag.value &= 0xef;
+ this->mFlag.value &= 0xdf;
+
+ if (duration < 0) {
+ this->mFlag.set(0x10);
+ } else if (duration > 0) {
+ this->mFlag.set(0x30);
+ }
+
+ this->mTimer = duration;
+ this->mFlag.value = ((this->mFlag.value | 0x01) & 0xfd) | 0x8;
+}
+
+/* 0x8049A440 */ f32 ControllerRumbleUnit::calc() {
+ f32 result = 0.0f;
+ if (this->mFlag.onBit(3)) {
+ if (this->mFlag.onBit(0)) {
+ char x = *++this->mPatternPos;
+ if (x == '\0') {
+ if (this->mFlag.onBit(4)) {
+ this->mPatternPos = this->mPattern;
+ } else {
+ this->mFlag.reset(~0xf7);
+ }
+ } else if (x == '*') {
+ result = 1.0f;
+ }
+
+ if (this->mFlag.offBit(5)) {
+ return result;
+ }
+
+ if (--this->mTimer > 0) {
+ return result;
+ }
+ this->mFlag.reset(~0xf7);
+ return result;
+ } else {
+ f32 intensity = this->mIntensity + this->mRampUp;
+ this->mIntensity = intensity;
+ if (intensity >= 1.0f) {
+ result = 1.0f;
+ this->mIntensity = 0.0f;
+ }
+
+ // infinite flag?
+ if (this->mFlag.onBit(2)) {
+ return result;
+ }
+
+ if (--this->mTimer > 0) {
+ return result;
+ }
+ }
+ this->mFlag.reset(~0xf7);
+ return result;
+ } else {
+ return -1.0f;
+ }
+}
+
+/* 0x8049A530 */ ControllerRumbleMgr::ControllerRumbleMgr() {
+ this->mController = nullptr;
+ // TODO offsetof macro
+ List_Init(&this->mActiveUnitList, 0x1c);
+ List_Init(&this->mInactiveUnitList, 0x1c);
+}
+
+/* 0x8049A590 */ void ControllerRumbleMgr::createUnit(u8 numUnits, CoreController *ctrl) {
+ for (u8 created = 0; created < numUnits; created++) {
+ ControllerRumbleUnit *unit = new ControllerRumbleUnit();
+ List_Append(&this->mInactiveUnitList, unit);
+ }
+ this->mController = ctrl;
+}
+
+/* 0x8049A620 */ void ControllerRumbleMgr::stop() {
+ this->mController->stopMotor();
+ while (List_GetSize(&this->mActiveUnitList) != 0) {
+ ControllerRumbleUnit *unit = static_cast<ControllerRumbleUnit *>(List_GetNext(&this->mActiveUnitList, nullptr));
+ List_Remove(&this->mActiveUnitList, unit);
+ List_Append(&this->mInactiveUnitList, unit);
+ }
+}
+
+/* 0x8049A690 */ void ControllerRumbleMgr::calc() {
+ if (List_GetSize(&this->mActiveUnitList) != 0) {
+ void *object = List_GetFirst(&this->mActiveUnitList);
+ f32 acc = 0.0f;
+
+ while (object != nullptr) {
+ ControllerRumbleUnit *unit = static_cast<ControllerRumbleUnit *>(object);
+ f32 x = unit->calc();
+ void *nextObject = List_GetNext(&this->mActiveUnitList, object);
+ if (x < 0.0f) {
+ List_Remove(&this->mActiveUnitList, object);
+ List_Append(&this->mInactiveUnitList, object);
+ } else {
+ acc += x;
+ }
+ object = nextObject;
+ }
+
+ if (acc >= 1.0f) {
+ this->mController->startMotor();
+ } else {
+ this->mController->stopMotor();
+ }
+ }
+}
+
+/* 0x8049A7A0 */ void ControllerRumbleMgr::startPattern(const char *pattern, int duration, bool bGrabActive) {
+ EGG::ControllerRumbleUnit *unit = getUnitFromList(bGrabActive);
+ if (unit != nullptr) {
+ unit->startPattern(pattern, duration);
+ }
+}
+
+/* 0x8049A7F0 */ ControllerRumbleUnit *ControllerRumbleMgr::getUnitFromList(bool bGrabActive) {
+ void *first = List_GetFirst(&this->mInactiveUnitList);
+ if (first != nullptr) {
+ List_Remove(&this->mInactiveUnitList, first);
+ List_Append(&this->mActiveUnitList, first);
+ } else if (bGrabActive && (first = List_GetFirst(&this->mActiveUnitList), first != nullptr)) {
+ List_Remove(&this->mActiveUnitList, first);
+ List_Append(&this->mActiveUnitList, first);
+ }
+ return static_cast<ControllerRumbleUnit *>(first);
+}
} // namespace EGG