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