1 /*
2 * file w32_joystick.c - joystick support
3 *
4 * $Id: w32_joystick.c,v 1.6 2006/02/19 13:33:01 lodott Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #include "xblast.h"
24 #include "w32_joystick.h"
25 #include "gui.h"
26
27 //#include "w32_mm.h"
28
29 /*
30 * local macros
31 */
32 #define MAX_JOYSTICK 2
33
34 /* flags for joystick X and Y positions */
35 #define JOYDIR_NONE 0x00
36 #define JOYDIR_UP 0x01
37 #define JOYDIR_DOWN 0x02
38 #define JOYDIR_Y 0x03
39 #define JOYDIR_LEFT 0x04
40 #define JOYDIR_RIGHT 0x08
41 #define JOYDIR_X 0x0C
42
43 /*
44 * local types
45 */
46
47 /* joystick data */
48 typedef struct
49 {
50 XBEventCode event; /* event code to send */
51 unsigned dir; /* current direction */
52 unsigned xLow; /* calibration data */
53 unsigned xHigh; /* calibration data */
54 unsigned yLow; /* calibration data */
55 unsigned yHigh; /* calibration data */
56 } XBJoystick;
57
58 /*
59 * local variables
60 */
61
62 /* available joystick IDs */
63 static const UINT joyDevice[MAX_JOYSTICK] = {
64 JOYSTICKID1,
65 JOYSTICKID2,
66 };
67
68 /* joystick parameters */
69 static XBJoystick joystick[MAX_JOYSTICK];
70
71 /*
72 * how many joystick do we support
73 */
74 int
GUI_NumJoysticks(void)75 GUI_NumJoysticks (void)
76 {
77 int i, num;
78
79 for (i = 0, num = 0; i < MAX_JOYSTICK; i++) {
80 if (XBE_NONE != joystick[i].event) {
81 num++;
82 }
83 }
84 return num;
85 } /* GUI_NumJoysticks */
86
87 /*
88 * init joystick support
89 */
90 XBBool
InitJoystick(void)91 InitJoystick (void)
92 {
93 int i, j;
94 UINT joyThres;
95 static JOYCAPS joyCaps;
96
97 memset (joystick, 0, sizeof (joystick));
98 for (i = 0, j = 0; i < joyGetNumDevs () && i < MAX_JOYSTICK && j < MAX_JOYSTICK; i++) {
99 /* get device */
100 if (JOYERR_NOERROR != joyGetDevCaps (joyDevice[i], &joyCaps, sizeof (joyCaps))) {
101 continue;
102 }
103 /* set threshold */
104 joyThres = ABS ((int)joyCaps.wYmin - (int)joyCaps.wYmax) / 8;
105 if (JOYERR_NOERROR != joySetThreshold (joyDevice[i], joyThres)) {
106 continue;
107 }
108 if (JOYERR_NOERROR != joySetCapture (window, joyDevice[i], 0, TRUE)) {
109 continue;
110 }
111 joystick[i].event = XBE_JOYST_1 + j;
112 joystick[i].dir = JOYDIR_NONE;
113 joystick[i].xLow = 3 * (joyCaps.wXmin / 4) + 1 * (joyCaps.wXmax / 4);
114 joystick[i].xHigh = 1 * (joyCaps.wXmin / 4) + 3 * (joyCaps.wXmax / 4);
115 joystick[i].yLow = 3 * (joyCaps.wYmin / 4) + 1 * (joyCaps.wYmax / 4);
116 joystick[i].yHigh = 1 * (joyCaps.wYmin / 4) + 3 * (joyCaps.wYmax / 4);
117 j++;
118 Dbg_Out ("Joystick (%d) %s connected as XBE_JOYST_%d. x=(%u,%u) y=(%u,%u)\n",
119 i + 1, joyCaps.szPname, j, joyCaps.wXmin, joyCaps.wXmax, joyCaps.wYmin,
120 joyCaps.wYmax);
121 }
122 return XBTrue;
123 } /* InitJoystick */
124
125 /*
126 * finish joystick support
127 */
128 void
FinishJoystick(void)129 FinishJoystick (void)
130 {
131 size_t i;
132
133 for (i = 0; i < MAX_JOYSTICK; i++) {
134 if (XBE_NONE != joystick[i].event) {
135 joyReleaseCapture (joyDevice[i]);
136 }
137 }
138 } /* FinishJoystick */
139
140 /*
141 * calculate new joystick position for window message
142 */
143 static unsigned
EvalJoystickMove(LONG lParam,const XBJoystick * pJoy)144 EvalJoystickMove (LONG lParam, const XBJoystick * pJoy)
145 {
146 UINT xPos, yPos;
147 unsigned newDir = 0;
148
149 /* sanity check */
150 assert (NULL != pJoy);
151
152 /* get x-position */
153 xPos = LOWORD (lParam);
154 if (pJoy->xHigh < pJoy->xLow) {
155 if (xPos < pJoy->xHigh) {
156 newDir |= JOYDIR_LEFT;
157 }
158 else if (xPos > pJoy->xLow) {
159 newDir |= JOYDIR_RIGHT;
160 }
161 }
162 else {
163 if (xPos > pJoy->xHigh) {
164 newDir |= JOYDIR_RIGHT;
165 }
166 else if (xPos < pJoy->xLow) {
167 newDir |= JOYDIR_LEFT;
168 }
169 }
170 /* get y-position */
171 yPos = HIWORD (lParam);
172 if (pJoy->yHigh < pJoy->yLow) {
173 if (yPos < pJoy->yHigh) {
174 newDir |= JOYDIR_UP;
175 }
176 else if (yPos > pJoy->yLow) {
177 newDir |= JOYDIR_DOWN;
178 }
179 }
180 else {
181 if (yPos > pJoy->yHigh) {
182 newDir |= JOYDIR_DOWN;
183 }
184 else if (yPos < pJoy->yLow) {
185 newDir |= JOYDIR_UP;
186 }
187 }
188 return newDir;
189 } /* EvalJoyMove */
190
191 /*
192 * handle joysticks messages in menu mode
193 */
194 void
HandleMenuJoy(UINT message,UINT wParam,LONG lParam)195 HandleMenuJoy (UINT message, UINT wParam, LONG lParam)
196 {
197 XBJoystick *pJoy;
198 unsigned newDir;
199
200 switch (message) {
201 /* button presses */
202 case MM_JOY1BUTTONDOWN:
203 case MM_JOY2BUTTONDOWN:
204 QueueEventValue (XBE_MENU, XBMK_SELECT);
205 break;
206 /* joystick movement */
207 case MM_JOY1MOVE:
208 case MM_JOY2MOVE:
209 if (message == MM_JOY1MOVE) {
210 pJoy = joystick + 0;
211 }
212 else {
213 pJoy = joystick + 1;
214 }
215 newDir = EvalJoystickMove (lParam, pJoy);
216 if (newDir != pJoy->dir) {
217 /* test changes in y dir */
218 if ((newDir & JOYDIR_Y) != (pJoy->dir & JOYDIR_Y)) {
219 switch (newDir & JOYDIR_Y) {
220 case JOYDIR_UP:
221 QueueEventValue (XBE_MENU, XBMK_UP);
222 break;
223 case JOYDIR_DOWN:
224 QueueEventValue (XBE_MENU, XBMK_DOWN);
225 break;
226 }
227 }
228 if ((newDir & JOYDIR_X) != (pJoy->dir & JOYDIR_X)) {
229 switch (newDir & JOYDIR_X) {
230 case JOYDIR_LEFT:
231 QueueEventValue (XBE_MENU, XBMK_LEFT);
232 break;
233 case JOYDIR_RIGHT:
234 QueueEventValue (XBE_MENU, XBMK_RIGHT);
235 break;
236 }
237 }
238 pJoy->dir = newDir;
239 }
240 }
241 } /* HandleMenuJoy */
242
243 /*
244 * handle joysticks messages in game mode
245 */
246 void
HandleXBlastJoy(UINT message,UINT wParam,LONG lParam)247 HandleXBlastJoy (UINT message, UINT wParam, LONG lParam)
248 {
249 XBJoystick *pJoy;
250 unsigned newDir;
251 int value;
252
253 switch (message) {
254 /* button presses */
255 case MM_JOY1BUTTONDOWN:
256 case MM_JOY2BUTTONDOWN:
257 if (message == MM_JOY1BUTTONDOWN) {
258 pJoy = joystick + 0;
259 }
260 else {
261 pJoy = joystick + 1;
262 }
263 if (pJoy->event != XBE_NONE) {
264 if (JOY_BUTTON1CHG & wParam) {
265 QueueEventValue (pJoy->event, XBGK_BOMB);
266 }
267 if (JOY_BUTTON2CHG & wParam) {
268 QueueEventValue (pJoy->event, XBGK_SPECIAL);
269 }
270 }
271 break;
272 /* moving */
273 case MM_JOY1MOVE:
274 case MM_JOY2MOVE:
275 if (message == MM_JOY1MOVE) {
276 pJoy = joystick + 0;
277 }
278 else {
279 pJoy = joystick + 1;
280 }
281 if (pJoy->event != XBE_NONE) {
282 newDir = EvalJoystickMove (lParam, pJoy);
283 switch (newDir) {
284 case JOYDIR_UP:
285 value = XBGK_GO_UP;
286 break;
287 case JOYDIR_DOWN:
288 value = XBGK_GO_DOWN;
289 break;
290 case JOYDIR_LEFT:
291 value = XBGK_GO_LEFT;
292 break;
293 case JOYDIR_RIGHT:
294 value = XBGK_GO_RIGHT;
295 break;
296 case JOYDIR_NONE:
297 value = XBGK_STOP_ALL;
298 break;
299 default:
300 value = XBGK_NONE;
301 break;
302 }
303 if (value != XBGK_NONE && newDir != pJoy->dir) {
304 QueueEventValue (pJoy->event, value);
305 pJoy->dir = newDir;
306 }
307 }
308 break;
309 }
310 } /* HandleXBlastJoy */
311
312 /*
313 * end fo file w32_joystick.c
314 */
315