]> icculus.org git repositories - btb/d2x.git/blob - arch/win32/joyhh.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / arch / win32 / joyhh.c
1 //JOYC.C for D1_3Dfx and D1OpenGL
2 //D1_3Dfx is a Win32 executable using Glide and DirectX 3
3 //D1OpenGL is a Win32 executable using OpenGL and DirectX 3
4 //This joystick code should run on DirectInput 2 and higher
5 //We are not using DirectX 5 for now, since we want to stay compatible to the HH-loved Windows NT :).
6 //So ForceFeedback is not supported
7
8 //Notes:
9 // 1) Windows DirectX supports up to 7 axes, D1/DOS only 4, so we needed to increase the number to 7 at several points
10 //    Also JOY_ALL_AXIS must be (1+2+4+8+16+32+64) in JOY.H file
11 // 2) Windows DirectX supports up to 32 buttons. So far we however only support 4. Adding support for more should be however easily possible.
12 // 3) _enable and _disable are not needed
13 // 4) joy_bogus_reading is not needed, so all calls are just removed
14 // 5) The joystick query goes over the DirectInputs function
15 //    MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
16 //    All functions reading over BIOS, including the ASM code are removed
17
18
19
20 /*
21 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
22 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
23 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
24 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
25 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
26 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
27 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
28 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
29 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
30 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
31 */
32
33 /*
34 Modifications by Heiko Herrmann
35 Later modified by Owen Evans to work with D1X (3/7/99)
36 */
37
38
39 #define _WIN32_OS               //HH
40
41 #include <windows.h>    //HH
42 #include <mmsystem.h>   //HH
43 #include <stdlib.h>
44 #include <stdio.h>
45
46 #include "types.h"
47 #include "joy.h"
48 #include "timer.h"
49 #include "args.h"
50
51 #define my_hwnd g_hWnd // D1X compatibility
52 extern HWND g_hWnd;
53
54 char joy_installed = 0;
55 char joy_present = 0;
56
57 typedef struct Button_info {
58         ubyte           ignore;
59         ubyte           state;
60         ubyte           last_state;
61         int             timedown;
62         ubyte           downcount;
63         ubyte           upcount;
64 } Button_info;
65
66 typedef struct Joy_info {
67         int                     joyid;
68         ubyte                   present_mask;
69         ubyte       hat_present;
70         ubyte                   slow_read;
71         int                     max_timer;
72         int                     read_count;
73         ubyte                   last_value;
74         Button_info buttons[JOY_MAX_BUTTONS];
75         int                     axis_min[JOY_NUM_AXES];    //changed 
76         int                     axis_center[JOY_NUM_AXES]; //changed --orulz
77         int                     axis_max[JOY_NUM_AXES];    //changed 
78 } Joy_info;
79
80 Joy_info joystick;
81
82
83 int joy_deadzone = 0;
84
85 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
86 {
87         int i;
88
89         for (i=0; i<JOY_NUM_AXES; i++)             {       //changed - orulz
90                 axis_min[i] = joystick.axis_min[i];
91                 axis_center[i] = joystick.axis_center[i];
92                 axis_max[i] = joystick.axis_max[i];
93         }
94 }
95
96 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
97 {
98         int i;
99
100         for (i=0; i<JOY_NUM_AXES; i++)             {       //changed - orulz
101                 joystick.axis_min[i] = axis_min[i];
102                 joystick.axis_center[i] = axis_center[i];
103                 joystick.axis_max[i] = axis_max[i];
104         }
105 }
106
107 ubyte joy_get_present_mask()    {
108         return joystick.present_mask;
109 }
110
111 void joy_set_timer_rate(int max_value ) {
112         joystick.max_timer = max_value;
113 }
114
115 int joy_get_timer_rate()        {
116         return joystick.max_timer;
117 }
118
119 void joy_flush()        {
120         int i;
121
122         if (!joy_installed) return;
123
124         for (i = 0; i < JOY_MAX_BUTTONS; i++)
125         {
126                 joystick.buttons[i].ignore = 0;
127                 joystick.buttons[i].state = 0;  
128                 joystick.buttons[i].timedown = 0;       
129                 joystick.buttons[i].downcount = 0;      
130                 joystick.buttons[i].upcount = 0;        
131         }
132
133 }
134
135
136 //Begin section modified 3/7/99 - Owen Evans
137
138 ubyte joy_read_raw_buttons()
139 {
140         JOYINFOEX joy;
141         int i;
142
143         if (!joy_present)
144                 return 0; 
145         
146         memset(&joy, 0, sizeof(joy));
147         joy.dwSize = sizeof(joy);
148         joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
149         
150         if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
151                 return 0;
152
153         for (i = 0; i < JOY_MAX_BUTTONS; i++)
154         {
155                 joystick.buttons[i].last_state = joystick.buttons[i].state;
156                 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
157                 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
158                         joystick.buttons[i].timedown = timer_get_fixed_seconds();
159                         joystick.buttons[i].downcount++;
160                 }
161         }
162
163         /* Hat stuff */
164
165         if (joystick.hat_present && joy.dwPOV != JOY_POVCENTERED)
166          {
167            joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
168            joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
169            joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
170            joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
171          }
172
173         return (ubyte)joy.dwButtons;
174 }
175
176 //end changed section - OE
177
178
179 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
180 {
181         JOYINFOEX       joy;
182         ubyte read_masks = 0;
183
184         axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
185         axis[2] = 0; axis[3] = 0;
186         axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
187         
188         if (!joy_installed) {
189                 return 0;
190         }
191
192         memset(&joy, 0, sizeof(joy));
193         joy.dwSize = sizeof(joy);
194         joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
195         if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
196                 return 0;
197         }
198                         
199         mask &= joystick.present_mask;                  // Don't read non-present channels
200         if ( mask==0 )  {
201                 return 0;               // Don't read if no stick connected.
202         }
203
204         if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
205         if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
206 //orulz:
207 //        if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
208 //        if (mask & JOY_1_POV)    { axis[3] = joy.dwPOV;  read_masks |= JOY_1_POV;    }
209 //        if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
210 //        if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
211 //        if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
212         if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
213         if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
214         if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
215         if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
216
217         return read_masks;
218 }
219
220 int hh_average(int val1, int val2)
221 {
222         return abs(val1-val2)/2;
223 }
224
225 int joy_init(int joyid) //HH: added joyid parameter
226 {
227         int i;
228         int temp_axis[JOY_NUM_AXES];       //changed - orulz
229         JOYCAPS pjc;
230
231         if (FindArg("-nojoystick"))
232                 return 0;
233
234         atexit(joy_close);      //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
235
236         joy_flush();
237         memset(&joystick, 0, sizeof(joystick));
238
239         for (i = 0; i < JOY_MAX_BUTTONS; i++)
240                 joystick.buttons[i].last_state = 0;
241
242         if ( !joy_installed )   {
243                 joy_present = 0;
244                 joy_installed = 1;
245                 joystick.max_timer = 65536;
246                 joystick.read_count = 0;
247                 joystick.last_value = 0;
248         }
249
250
251         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
252         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
253
254         if ( joystick.present_mask & 3 )
255                 joy_present = 1;
256         else
257                 joy_present = 0;
258
259         
260         //HH: Main Win32 joystick initialization, incl. reading cal. stuff
261
262         if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
263                 return 0;
264         }
265
266         if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
267                 return 0;
268         }
269
270         joystick.max_timer      = pjc.wPeriodMax;
271         joystick.axis_min[0]    = pjc.wXmin;
272         joystick.axis_min[1]    = pjc.wYmin;
273 //orulz:
274 //        joystick.axis_min[2]    = pjc.wZmin;
275 //        //HH: joystick.axis_min[3]  = pov-stuff
276 //        joystick.axis_min[4]    = pjc.wRmin;
277 //        joystick.axis_min[5]    = pjc.wUmin;
278 //        joystick.axis_min[6]    = pjc.wVmin;
279         joystick.axis_min[2]    = pjc.wRmin;
280         joystick.axis_min[3]    = pjc.wZmin;
281         joystick.axis_min[4]    = pjc.wUmin;
282         joystick.axis_min[5]    = pjc.wVmin;
283
284         joystick.axis_max[0]    = pjc.wXmax;
285         joystick.axis_max[1]    = pjc.wYmax;
286 //orulz:
287 //        joystick.axis_max[2]    = pjc.wZmax;
288 //        //HH: joystick.axis_max[3]  = pov-stuff
289 //        joystick.axis_max[4]    = pjc.wRmax;
290 //        joystick.axis_max[5]    = pjc.wUmax;
291 //        joystick.axis_max[6]    = pjc.wVmax;
292         joystick.axis_max[2]    = pjc.wRmax;
293         joystick.axis_max[3]    = pjc.wZmax;
294         joystick.axis_max[4]    = pjc.wUmax;
295         joystick.axis_max[5]    = pjc.wVmax;
296
297         joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
298         joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
299 //orulz:
300 //        joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
301 //        joystick.axis_center[3] = JOY_POVCENTERED;
302 //        joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
303 //        joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
304 //        joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
305         joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
306         joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
307         joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
308         joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
309
310         joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
311         if (pjc.wCaps & JOYCAPS_HASZ)   joystick.present_mask |= JOY_1_Z_AXIS;
312         joystick.hat_present = (pjc.wCaps & JOYCAPS_HASPOV) > 0;
313         if (pjc.wCaps & JOYCAPS_HASR)   joystick.present_mask |= JOY_1_R_AXIS;
314         if (pjc.wCaps & JOYCAPS_HASU)   joystick.present_mask |= JOY_1_U_AXIS;
315         if (pjc.wCaps & JOYCAPS_HASV)   joystick.present_mask |= JOY_1_V_AXIS;
316
317         return joy_present;
318 }
319
320
321 void joy_close()
322 {
323         if (!joy_installed) return;
324         joy_installed = 0;
325 }
326
327
328 void joy_set_ul()       
329 {
330         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
331         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
332
333         if ( joystick.present_mask & 3 )
334                 joy_present = 1;
335         else
336                 joy_present = 0;
337 }
338
339 void joy_set_lr()       
340 {
341         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
342         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
343
344         if ( joystick.present_mask & 3 )
345                 joy_present = 1;
346         else
347                 joy_present = 0;
348 }
349
350 void joy_set_cen() 
351 {
352         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
353         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
354
355         if ( joystick.present_mask & 3 )
356                 joy_present = 1;
357         else
358                 joy_present = 0;
359 }
360
361 void joy_set_cen_fake(int channel)      
362 { }
363
364
365 int joy_get_scaled_reading( int raw, int axn )  
366 {
367  int x, d;
368
369   // Make sure it's calibrated properly.
370    if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
371     return 0; //HH: had to increase to 128
372    if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
373     return 0; //HH: had to increase to 128
374
375         if (!(joystick.present_mask & (1 << axn)))
376                 return 0; // fixes joy config bug where it'll always set an axis you don't even have. - 2000/01/14 Matt Mueller
377
378   raw -= joystick.axis_center[axn];
379
380    if ( raw < 0 )
381     d = joystick.axis_center[axn]-joystick.axis_min[axn];
382    else
383     d = joystick.axis_max[axn]-joystick.axis_center[axn];
384
385
386    if ( d )
387     x = (raw << 7) / d;
388    else 
389     x = 0;
390
391
392    if ( x < -128 ) x = -128;
393    if ( x > 127 ) x = 127;
394
395 //added on 4/13/99 by Victor Rachels to add deadzone control
396   d =  (joy_deadzone) * 6;
397    if ((x > (-1*d)) && (x < d))
398     x = 0;
399 //end this section addition -VR
400
401         return x;
402 }
403
404 void joy_get_pos( int *x, int *y )      
405 {
406         ubyte flags;
407         int axis[JOY_NUM_AXES];
408
409         if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
410
411         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
412
413         if ( flags & JOY_1_X_AXIS )
414                 *x = joy_get_scaled_reading( axis[0], 0 );
415         else
416                 *x = 0;
417
418         if ( flags & JOY_1_Y_AXIS )
419                 *y = joy_get_scaled_reading( axis[1], 1 );
420         else
421                 *y = 0;
422 }
423
424 ubyte joy_read_stick( ubyte masks, int *axis )  
425 {
426         ubyte flags;
427         int raw_axis[JOY_NUM_AXES];
428
429         if ((!joy_installed)||(!joy_present)) { 
430                 axis[0] = 0; axis[1] = 0;
431                 axis[2] = 0; axis[3] = 0;
432                 axis[4] = 0; axis[5] = 0; 
433                 return 0;  
434         }
435
436         flags=joystick_read_raw_axis( masks, raw_axis );
437
438         if ( flags & JOY_1_X_AXIS )
439                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
440         else
441                 axis[0] = 0;
442
443         if ( flags & JOY_1_Y_AXIS )
444                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
445         else
446                 axis[1] = 0;
447
448         if ( flags & JOY_1_R_AXIS )
449                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
450         else
451                 axis[2] = 0;
452
453         if ( flags & JOY_1_Z_AXIS )
454                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
455         else
456                 axis[3] = 0;
457
458         if ( flags & JOY_1_U_AXIS )
459                 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
460         else
461                 axis[4] = 0;
462
463         if ( flags & JOY_1_V_AXIS )
464                 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
465         else
466                 axis[5] = 0;
467
468
469         return flags;
470 }
471
472 int joy_get_btns()      
473 {
474         if ((!joy_installed)||(!joy_present)) return 0;
475
476         return joy_read_raw_buttons();
477 }
478
479
480 //Begin section modified 3/7/99 - Owen Evans
481
482 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
483 {
484         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
485
486         joy_get_btns();
487
488         *btn0 = joystick.buttons[0].downcount;
489         joystick.buttons[0].downcount = 0;
490         *btn1 = joystick.buttons[1].downcount;
491         joystick.buttons[1].downcount = 0;
492 }
493
494 int joy_get_button_state( int btn )     
495 {    
496         if ((!joy_installed)||(!joy_present)) return 0;
497         if (btn >= JOY_MAX_BUTTONS)
498                 return 0;
499
500         joy_get_btns();
501
502         return joystick.buttons[btn].state;
503 }
504
505 int joy_get_button_up_cnt( int btn ) 
506 {
507         int count;
508
509         if ((!joy_installed)||(!joy_present)) return 0;
510
511         if (btn >= JOY_MAX_BUTTONS)
512                 return 0;
513
514         count = joystick.buttons[btn].upcount;
515         joystick.buttons[btn].upcount = 0;
516
517         return count;
518 }
519
520 int joy_get_button_down_cnt( int btn ) 
521 {
522         int count;
523
524         if ((!joy_installed)||(!joy_present)) return 0;
525         if (btn >= JOY_MAX_BUTTONS)
526                 return 0;
527
528         joy_get_btns();
529
530         count = joystick.buttons[btn].downcount;
531         joystick.buttons[btn].downcount = 0;
532
533         return count;
534 }
535
536 fix joy_get_button_down_time( int btn ) 
537 {
538         fix count;
539
540         if ((!joy_installed)||(!joy_present)) return 0;
541         if (btn >= JOY_MAX_BUTTONS)
542                 return 0;
543
544         joy_get_btns();
545
546         if (joystick.buttons[btn].state) {
547                 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
548                 joystick.buttons[btn].timedown = 0;
549         } else count = 0;
550         
551         return count;
552 }
553
554 //end changed section - OE
555
556
557 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
558 {
559         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
560
561         *btn0 = joystick.buttons[0].upcount;
562         joystick.buttons[0].upcount = 0;
563         *btn1 = joystick.buttons[1].upcount;
564         joystick.buttons[1].upcount = 0;
565 }
566
567 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
568 {
569         joystick.buttons[btn].ignore = 1;
570         joystick.buttons[btn].state = state;
571         joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
572         joystick.buttons[btn].downcount = downcount;
573         joystick.buttons[btn].upcount = upcount;
574 }
575
576 void joy_poll()
577 {
578 }
579