1 /*
2 * PROPRIETARY INFORMATION. This software is proprietary to POWDER
3 * Development, and is not to be reproduced, transmitted, or disclosed
4 * in any way without written permission.
5 *
6 * Produced by: Jeff Lait
7 *
8 * POWDER Development
9 *
10 * NAME: control.cpp ( POWDER Library, C++ )
11 *
12 * COMMENTS:
13 * Gameboy Advance specific implementation of controls.
14 */
15
16 #include "control.h"
17
18 #include <mygba.h>
19 #include "control.h"
20 #include "gfxengine.h"
21
22 // Global variables, these store our previous button states.
23 // If old state is 1, the oldframe contains which frame the button
24 // was last pressed on.
25 int glb_oldstate[NUM_BUTTONS];
26 int glb_oldframe[NUM_BUTTONS];
27
28 #define SHORT_REPEAT 10 // 6 per sec
29 #define LONG_REPEAT 20 // 3 per sec
30
31 int glb_repeatrate[NUM_BUTTONS] =
32 {
33 SHORT_REPEAT, // UP
34 SHORT_REPEAT, // DOWN
35 SHORT_REPEAT, // LEFT
36 SHORT_REPEAT, // RIGHT
37 LONG_REPEAT, // A
38 LONG_REPEAT, // B
39 LONG_REPEAT, // START
40 LONG_REPEAT, // SELECT
41 LONG_REPEAT, // R
42 LONG_REPEAT, // L
43 LONG_REPEAT, // X
44 LONG_REPEAT, // Y
45 SHORT_REPEAT, // TOUCH (We use as directions when repeated)
46 LONG_REPEAT // LID
47 };
48
49 // Conversion from button enums to valid key presses.
50 #define MAX_KEYEQUIV 3
51 int glb_buttonkeys[NUM_BUTTONS][MAX_KEYEQUIV] =
52 {
53 { GFX_KEYUP, 'k', '8' },
54 { GFX_KEYDOWN, 'j', '2' },
55 { GFX_KEYLEFT, 'h', '4' },
56 { GFX_KEYRIGHT, 'l', '6' },
57 { '\r', ' ', '5' }, // A
58 { '\x1b', '0', 0 }, // B
59 { 0, 0, 0 }, // START
60 { 'i', 0, 0 }, // SELECT
61 { 0, 0, 0 }, // R
62 { 'p', 0, 0 }, // L
63
64 { 0, 0, 0 }, // X
65 { 0, 0, 0 }, // Y
66 { GFX_KEYLMB, 0, 0 }, // TOUCH
67 { 0, 0, 0 }, // LID
68 };
69
70 void
ctrl_init()71 ctrl_init()
72 {
73 memset(glb_oldstate, 0, sizeof(int) * NUM_BUTTONS);
74 memset(glb_oldframe, 0, sizeof(int) * NUM_BUTTONS);
75 }
76
77 void
ctrl_setrepeat(BUTTONS button,int timedelay)78 ctrl_setrepeat(BUTTONS button, int timedelay)
79 {
80 glb_repeatrate[button] = timedelay;
81 }
82
83 int
ctrl_anyrawpressed()84 ctrl_anyrawpressed()
85 {
86 #ifdef HAS_KEYBOARD
87 return 0;
88 #else
89 if (~R_CTRLINPUT & 0x3FF)
90 return 1;
91 else
92 return 0;
93 #endif
94 }
95
96 int
ctrl_rawpressed(int button)97 ctrl_rawpressed(int button)
98 {
99 #ifdef HAS_KEYBOARD
100 return 0;
101 #else
102 switch (button)
103 {
104 case BUTTON_UP:
105 return F_CTRLINPUT_UP_PRESSED;
106 case BUTTON_DOWN:
107 return F_CTRLINPUT_DOWN_PRESSED;
108 case BUTTON_LEFT:
109 return F_CTRLINPUT_LEFT_PRESSED;
110 case BUTTON_RIGHT:
111 return F_CTRLINPUT_RIGHT_PRESSED;
112 case BUTTON_A:
113 return F_CTRLINPUT_A_PRESSED;
114 case BUTTON_B:
115 return F_CTRLINPUT_B_PRESSED;
116 case BUTTON_R:
117 return F_CTRLINPUT_R_PRESSED;
118 case BUTTON_L:
119 return F_CTRLINPUT_L_PRESSED;
120 case BUTTON_SELECT:
121 return F_CTRLINPUT_SELECT_PRESSED;
122 case BUTTON_START:
123 return F_CTRLINPUT_START_PRESSED;
124 #ifdef HAS_XYBUTTON
125 case BUTTON_X:
126 case BUTTON_Y:
127 return hamfake_isPressed((BUTTONS) button);
128 #else
129 case BUTTON_X:
130 case BUTTON_Y:
131 return false;
132 #endif
133 #ifdef USING_DS
134 case BUTTON_TOUCH:
135 case BUTTON_LID:
136 return hamfake_isPressed((BUTTONS) button);
137 #else
138 case BUTTON_TOUCH:
139 return hamfake_getstylusstate();
140 case BUTTON_LID:
141 return false;
142 #endif
143 }
144 #endif
145
146 return 0;
147 }
148
149 bool
ctrl_hit(int button)150 ctrl_hit(int button)
151 {
152 #ifdef HAS_KEYBOARD
153 int key, equiv;
154
155 key = hamfake_peekKeyPress();
156
157 // Trivial failure if no key hit.
158 if (!key)
159 return false;
160
161 // See if this key matches this button's list.
162 for (equiv = 0; equiv < MAX_KEYEQUIV; equiv++)
163 {
164 if (glb_buttonkeys[button][equiv] == key)
165 {
166 // Consume the keypress.
167 hamfake_getKeyPress(false);
168 return true;
169 }
170 }
171
172 // Not found, ignore.
173 return false;
174
175 #else
176 int curstate;
177 int curframe = -1;
178
179 // Now, see if we are pressed...
180 curstate = ctrl_rawpressed(button);
181 if (!curstate)
182 {
183 // We know the answer, just make sure our old state is clear.
184 glb_oldstate[button] = 0;
185 return false;
186 }
187
188 if (glb_oldstate[button])
189 {
190 curframe = gfx_getframecount();
191 if (curframe < glb_oldframe[button] + glb_repeatrate[button])
192 {
193 // Not enough time since the last press, fail.
194 return false;
195 }
196 }
197
198 // Success! We will return 1 from here, but first update the
199 // old state with our current pos.
200 curframe = gfx_getframecount();
201 glb_oldframe[button] = curframe;
202 glb_oldstate[button] = 1;
203
204 return true;
205 #endif
206 }
207
208 void
ctrl_getdir(int & dx,int & dy,int raw,bool allowdiag)209 ctrl_getdir(int &dx, int &dy, int raw, bool allowdiag)
210 {
211 dx = dy = 0;
212
213 #ifdef HAS_KEYBOARD
214 int key;
215
216 key = hamfake_peekKeyPress();
217
218 ctrl_getdirfromkey(key, dx, dy, allowdiag);
219 if (dx || dy)
220 {
221 // Consume the key
222 hamfake_getKeyPress(false);
223 }
224
225 #else
226
227 if (raw)
228 {
229 if (ctrl_rawpressed(BUTTON_LEFT))
230 dx--;
231 if (ctrl_rawpressed(BUTTON_RIGHT))
232 dx++;
233 if (ctrl_rawpressed(BUTTON_UP))
234 dy--;
235 if (ctrl_rawpressed(BUTTON_DOWN))
236 dy++;
237 }
238 else
239 {
240 if (ctrl_hit(BUTTON_LEFT))
241 dx--;
242 if (ctrl_hit(BUTTON_RIGHT))
243 dx++;
244 if (ctrl_hit(BUTTON_UP))
245 dy--;
246 if (ctrl_hit(BUTTON_DOWN))
247 dy++;
248 }
249
250 #endif
251 // We prohibit diagonals as they are really hard to do with our
252 // first down methods.
253 if (!allowdiag && dx && dy)
254 dy = 0;
255 }
256
257 void
ctrl_getdirfromkey(int keypress,int & dx,int & dy,bool allowdiag)258 ctrl_getdirfromkey(int keypress, int &dx, int &dy, bool allowdiag)
259 {
260 #ifndef HAS_KEYBOARD
261 ctrl_getdir(dx, dy);
262 #else
263 dx = dy = 0;
264
265 switch (keypress)
266 {
267 case '8':
268 case GFX_KEYUP:
269 case 'k':
270 dy--;
271 break;
272 case '2':
273 case GFX_KEYDOWN:
274 case 'j':
275 dy++;
276 break;
277 case '4':
278 case GFX_KEYLEFT:
279 case 'h':
280 dx--;
281 break;
282 case '6':
283 case GFX_KEYRIGHT:
284 case 'l':
285 dx++;
286 break;
287 }
288
289 if (allowdiag)
290 {
291 switch (keypress)
292 {
293 case '7':
294 case 'y':
295 dy--; dx--;
296 break;
297 case '9':
298 case 'u':
299 dy--; dx++;
300 break;
301 case '1':
302 case 'b':
303 dy++; dx--;
304 break;
305 case '3':
306 case 'n':
307 dy++; dx++;
308 break;
309 }
310 }
311 #endif
312 }
313