summaryrefslogtreecommitdiff
path: root/src/code/sys_rumble.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/code/sys_rumble.c')
-rw-r--r--src/code/sys_rumble.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/code/sys_rumble.c b/src/code/sys_rumble.c
new file mode 100644
index 000000000..4101758be
--- /dev/null
+++ b/src/code/sys_rumble.c
@@ -0,0 +1,160 @@
+/*
+ * File: sys_rumble.c
+ * Description: Internal scheduler system for rumble requests
+ */
+
+#include "global.h"
+#include "z64rumble.h"
+
+// sRumbleWasEnabledOnLastTick/sWillDisableRumble? Probably name it after updateEnabled
+u8 D_801D1E70 = true;
+
+void RumbleManager_Update(RumbleManager* rumbleMgr) {
+ s32 strongestIndex = -1;
+ s32 i;
+ s32 temp;
+
+ // Turn rumbling off for all controllers
+ for (i = 0; i < ARRAY_COUNT(rumbleMgr->rumbleEnabled); i++) {
+ rumbleMgr->rumbleEnabled[i] = false;
+ }
+
+ if (!rumbleMgr->updateEnabled) {
+ // Rumbling update is disabled
+
+ if (D_801D1E70) {
+ for (i = 0; i < MAXCONTROLLERS; i++) {
+ func_8017544C(i, false);
+ }
+ }
+
+ D_801D1E70 = rumbleMgr->updateEnabled;
+ func_80175434();
+
+ return;
+ }
+
+ D_801D1E70 = rumbleMgr->updateEnabled;
+
+ // Start up the manager by wiping old requests
+ if (rumbleMgr->state == RUMBLEMANAGER_STATE_INITIAL) {
+ for (i = 0; i < MAXCONTROLLERS; i++) {
+ func_8017544C(i, false);
+ }
+
+ for (i = 0; i < RUMBLE_REQUEST_BUFFER_SIZE; i++) {
+ rumbleMgr->requestIntensities[i] = 0;
+ rumbleMgr->requestDecayTimers[i] = 0;
+ rumbleMgr->requestDecaySteps[i] = 0;
+ rumbleMgr->requestAccumulators[i] = 0;
+ }
+
+ rumbleMgr->rumblingDuration = 0;
+ rumbleMgr->downTime = 0;
+
+ rumbleMgr->overrideIntensity = 0;
+ rumbleMgr->overrideDecayTimer = 0;
+ rumbleMgr->overrideDecayStep = 0;
+ rumbleMgr->overrideAccumulator = 0;
+
+ rumbleMgr->state = RUMBLEMANAGER_STATE_RUNNING;
+
+ func_80175434();
+ }
+
+ if (rumbleMgr->state != RUMBLEMANAGER_STATE_WIPE) {
+ // Process arrays of rumble requests
+ for (i = 0; i < RUMBLE_REQUEST_BUFFER_SIZE; i++) {
+ if (rumbleMgr->requestIntensities[i] != 0) { // This entry has a non-empty rumble request
+ if (rumbleMgr->requestDecayTimers[i] > 0) {
+ rumbleMgr->requestDecayTimers[i]--;
+ } else {
+ temp = rumbleMgr->requestIntensities[i] - rumbleMgr->requestDecaySteps[i];
+ if (temp > 0) {
+ rumbleMgr->requestIntensities[i] = temp;
+ } else {
+ rumbleMgr->requestIntensities[i] = 0;
+ }
+ }
+
+ temp = rumbleMgr->requestAccumulators[i] + rumbleMgr->requestIntensities[i];
+ rumbleMgr->requestAccumulators[i] = temp; // overflows
+ if (strongestIndex == -1) {
+ strongestIndex = i;
+ rumbleMgr->rumbleEnabled[0] = (temp >= 0x100);
+ } else if (rumbleMgr->requestIntensities[strongestIndex] < rumbleMgr->requestIntensities[i]) {
+ strongestIndex = i;
+ rumbleMgr->rumbleEnabled[0] = (temp >= 0x100);
+ }
+ }
+ }
+
+ // Process Override request. Note it takes priority over the values set by the request arrays
+ if (rumbleMgr->overrideIntensity != 0) {
+ if (rumbleMgr->overrideDecayTimer > 0) {
+ rumbleMgr->overrideDecayTimer--;
+ } else {
+ temp = rumbleMgr->overrideIntensity - rumbleMgr->overrideDecayStep;
+ if (temp > 0) {
+ rumbleMgr->overrideIntensity = temp;
+ } else {
+ rumbleMgr->overrideIntensity = 0;
+ }
+ }
+
+ temp = rumbleMgr->overrideAccumulator + rumbleMgr->overrideIntensity;
+ rumbleMgr->overrideAccumulator = temp; // overflows
+ rumbleMgr->rumbleEnabled[0] = (temp >= 0x100);
+ }
+
+ if (rumbleMgr->overrideIntensity != 0) {
+ temp = rumbleMgr->overrideIntensity;
+ } else if (strongestIndex == -1) {
+ temp = 0;
+ } else {
+ temp = rumbleMgr->requestIntensities[strongestIndex];
+ }
+
+ // Keep track of how long this have been rumbling (almost) nonstop
+ if (temp == 0) {
+ rumbleMgr->downTime++;
+ if (rumbleMgr->downTime > 5) {
+ rumbleMgr->rumblingDuration = 0;
+ rumbleMgr->downTime = 5;
+ }
+ } else {
+ rumbleMgr->downTime = 0;
+ rumbleMgr->rumblingDuration++;
+ if (rumbleMgr->rumblingDuration > 2 * 60 * 60) { // 2 minutes
+ // Rumbling has lasted too long, clear system
+ rumbleMgr->state = RUMBLEMANAGER_STATE_WIPE;
+ }
+ }
+ } else { // RUMBLEMANAGER_STATE_WIPE
+ for (i = 0; i < RUMBLE_REQUEST_BUFFER_SIZE; i++) {
+ rumbleMgr->requestIntensities[i] = 0;
+ rumbleMgr->requestDecayTimers[i] = 0;
+ rumbleMgr->requestDecaySteps[i] = 0;
+ rumbleMgr->requestAccumulators[i] = 0;
+ }
+
+ rumbleMgr->rumblingDuration = 0;
+ rumbleMgr->downTime = 0;
+
+ rumbleMgr->overrideIntensity = 0;
+ rumbleMgr->overrideDecayTimer = 0;
+ rumbleMgr->overrideDecayStep = 0;
+ rumbleMgr->overrideAccumulator = 0;
+
+ func_80175434();
+ }
+}
+
+void RumbleManager_Init(RumbleManager* rumbleMgr) {
+ bzero(rumbleMgr, sizeof(RumbleManager));
+ rumbleMgr->state = RUMBLEMANAGER_STATE_INITIAL;
+ rumbleMgr->updateEnabled = true;
+}
+
+void RumbleManager_Destroy(RumbleManager* rumbleMgr) {
+}