Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
input.c
Go to the documentation of this file.
1#include "common.h"
2#include "nu/nusys.h"
3
9
10#define STICK_DEADZONE_THRESHOLD 4
11#define STICK_BUTTON_THRESHOLD 32
12#define STICK_RELEASE_THRESHOLD 16
13
14/*
15 * When converting analog stick input into digital direction buttons (BUTTON_STICK_LEFT/RIGHT/UP/DOWN),
16 * small oscillations near the threshold could trigger rapid spurious stick 'button' inputs. This code
17 * prevents such inputs by recording the most recent 'extreme' values of StickX/Y along with the direction
18 * of motion, inward or outward, and then only counting directional reversals from those extremes.
19 *
20 * How it works:
21 * - When the stick crosses the main threshold (|stick| > 32), the corresponding digital stick 'button' is set.
22 * - While held, the code tracks the furthest extreme reached in the 'outward' direction.
23 * - If the stick reverses inward by more than 16 units, it enters a release-check state.
24 * - If the stick then moves outward again by more than 16 units from the inward extreme, the stick button is cleared.
25 * and a new input may be triggered *without* having to fully return the stick to neutral.
26 */
27enum {
28 DIR_OUTWARD = 0, // track outward extremes while the stick is pressed past the threshold
29 DIR_INWARD = 1, // track inward motion and determine when the stick direction should be released
30};
31
44
52
53void update_input(void) {
55 b32 hasInput = false;
58 s16 stickX;
59 s16 stickY;
60
62 hasInput = true;
64 }
65
68 && (contData->button & (BUTTON_A | BUTTON_B | BUTTON_Z | BUTTON_START))
69 && hasInput
70 ) {
72 }
76 hasInput = true;
77 }
78
79 if (!hasInput) {
80 return;
81 }
82
83 stickX = contData->stick_x;
84 stickY = contData->stick_y;
85 if (stickX > 0) {
87 if (stickX < 0) {
88 stickX = 0;
89 }
90 }
91 if (stickX < 0) {
93 if (stickX > 0) {
94 stickX = 0;
95 }
96 }
97
98 if (stickY > 0) {
100 if (stickY < 0) {
101 stickY = 0;
102 }
103 }
104 if (stickY < 0) {
105 stickY += STICK_DEADZONE_THRESHOLD;
106 if (stickY > 0) {
107 stickY = 0;
108 }
109 }
110
111 gGameStatusPtr->stickX[0] = stickX;
112 gGameStatusPtr->stickY[0] = stickY;
113 buttons = contData->button;
114
115 // check if stickX is over the 'digital' threshold for a right stick 'button' press
116 stickButtonDetected = false;
117 if (stickX > STICK_BUTTON_THRESHOLD) {
118 stickButtonDetected = true;
121 StickExtremeX = stickX;
122 } else if (StickRetriggerStateX == DIR_OUTWARD) {
123 // track largest value during DIR_OUTWARD
124 if (StickExtremeX < stickX) {
125 StickExtremeX = stickX;
126 }
127 } else {
128 // track smallest value during DIR_INWARD
129 if (StickExtremeX > stickX) {
130 StickExtremeX = stickX;
131 }
132 }
133 }
134
135 // likewise for left stick 'button' (comparisons reversed since we are working with negative values)
136 if (stickX < -STICK_BUTTON_THRESHOLD) {
137 stickButtonDetected = true;
140 StickExtremeX = stickX;
141 } else if (StickRetriggerStateX == DIR_OUTWARD) {
142 if (StickExtremeX > stickX) {
143 StickExtremeX = stickX;
144 }
145 } else {
146 if (StickExtremeX < stickX)
147 {
148 StickExtremeX = stickX;
149 }
150 }
151 }
152
153 if (!stickButtonDetected) {
155 StickExtremeX = stickX;
156 }
157
158 // likewise for up stick 'button'
159 stickButtonDetected = false;
160 if (stickY > STICK_BUTTON_THRESHOLD) {
161 stickButtonDetected = true;
164 StickExtremeY = stickY;
165 } else if (StickRetriggerStateY == DIR_OUTWARD) {
166 if (StickExtremeY < stickY) {
167 StickExtremeY = stickY;
168 }
169 } else {
170 if (StickExtremeY > stickY) {
171 StickExtremeY = stickY;
172 }
173 }
174 }
175
176 // likewise for down stick 'button'
177 if (stickY < -STICK_BUTTON_THRESHOLD) {
178 stickButtonDetected = true;
181 StickExtremeY = stickY;
182 } else if (StickRetriggerStateY == DIR_OUTWARD) {
183 if (StickExtremeY > stickY) {
184 StickExtremeY = stickY;
185 }
186 } else {
187 if (StickExtremeY < stickY) {
188 StickExtremeY = stickY;
189 }
190 }
191 }
192
193 if (!stickButtonDetected) {
195 StickExtremeY = stickY;
196 }
197
198 if (stickX > STICK_BUTTON_THRESHOLD) {
199 // if stick changes direction of motion during a release (from inward back to outward),
200 // clear the old input and reset to DIR_OUTWARD in preparation for a new input. this allows quick
201 // repeated inputs by rocking the stick without having to fully return to neutral between each.
205 }
206 // if we ever fall RELEASE_THRESHOLD units below the maximum value recorded, begin DIR_INWARD reversal checks
207 if (StickExtremeX - stickX > STICK_RELEASE_THRESHOLD) {
209 }
210 }
211
212 if (stickX < -STICK_BUTTON_THRESHOLD) {
216 }
217 if (stickX - StickExtremeX > STICK_RELEASE_THRESHOLD) {
219 }
220 }
221
222 if (stickY > STICK_BUTTON_THRESHOLD) {
226 }
227 if (StickExtremeY - stickY > STICK_RELEASE_THRESHOLD) {
229 }
230 }
231
232 if (stickY < -STICK_BUTTON_THRESHOLD) {
236 }
237 if (stickY - StickExtremeY > STICK_RELEASE_THRESHOLD) {
239 }
240 }
241
245
246 if (gGameStatusPtr->curButtons[0] == 0) {
248 } else if (gGameStatusPtr->prevButtons[0] != gGameStatusPtr->curButtons[0]) {
249 // buttons changed this frame: treat new presses as an immediate "held" pulse
253 } else {
254 // no change in buttons and at least one button is still held
256 // repeat "held" input pulses at a regular interval
260 } else {
263 }
264 } else {
265 // initial delay before train of "held" pulses begin
269 } else {
272 }
273 }
274 }
275
277}
BSS s32 PopupMenu_SelectedIndex
s16 holdRepeatInterval[4]
u32 pressedButtons[4]
s16 holdDelayTime[4]
s32 b32
@ BUTTON_A
Definition enums.h:2776
@ BUTTON_START
Definition enums.h:2773
@ BUTTON_STICK_UP
Definition enums.h:2777
@ BUTTON_STICK_DOWN
Definition enums.h:2778
@ BUTTON_STICK_LEFT
Definition enums.h:2779
@ BUTTON_STICK_RIGHT
Definition enums.h:2780
@ BUTTON_B
Definition enums.h:2775
@ BUTTON_Z
Definition enums.h:2774
@ DEMO_STATE_CHANGE_MAP
Definition enums.h:3570
@ DEMO_STATE_NONE
Definition enums.h:3568
void clear_input(void)
Definition input.c:45
#define STICK_RELEASE_THRESHOLD
Definition input.c:12
@ DIR_INWARD
Definition input.c:29
@ DIR_OUTWARD
Definition input.c:28
BSS s16 StickRetriggerStateY
Definition input.c:8
#define STICK_BUTTON_THRESHOLD
Definition input.c:11
BSS s16 StickRetriggerStateX
Definition input.c:7
void reset_input_state(void)
Definition input.c:32
OSContPad ContPadData
Definition input.c:4
void update_input(void)
Definition input.c:53
#define STICK_DEADZONE_THRESHOLD
Definition input.c:10
BSS s16 StickExtremeX
Definition input.c:5
BSS s16 StickExtremeY
Definition input.c:6
#define BSS
Definition macros.h:6
GameStatus * gGameStatusPtr
Definition main_loop.c:31