add caching of weapon inner models, screen shatter effects, robot explosions and...
[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
50 #define my_hwnd g_hWnd // D1X compatibility
51 extern HWND g_hWnd;
52
53 char joy_installed = 0;
54 char joy_present = 0;
55
56 typedef struct Button_info {
57         ubyte           ignore;
58         ubyte           state;
59         ubyte           last_state;
60         int             timedown;
61         ubyte           downcount;
62         ubyte           upcount;
63 } Button_info;
64
65 typedef struct Joy_info {
66         int                     joyid;
67         ubyte                   present_mask;
68         ubyte                   slow_read;
69         int                     max_timer;
70         int                     read_count;
71         ubyte                   last_value;
72         Button_info     buttons[MAX_BUTTONS];
73         int                     axis_min[JOY_NUM_AXES];    //changed 
74         int                     axis_center[JOY_NUM_AXES]; //changed --orulz
75         int                     axis_max[JOY_NUM_AXES];    //changed 
76 } Joy_info;
77
78 Joy_info joystick;
79
80
81 int joy_deadzone = 0;
82
83 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
84 {
85         int i;
86
87         for (i=0; i<JOY_NUM_AXES; i++)             {       //changed - orulz
88                 axis_min[i] = joystick.axis_min[i];
89                 axis_center[i] = joystick.axis_center[i];
90                 axis_max[i] = joystick.axis_max[i];
91         }
92 }
93
94 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
95 {
96         int i;
97
98         for (i=0; i<JOY_NUM_AXES; i++)             {       //changed - orulz
99                 joystick.axis_min[i] = axis_min[i];
100                 joystick.axis_center[i] = axis_center[i];
101                 joystick.axis_max[i] = axis_max[i];
102         }
103 }
104
105 ubyte joy_get_present_mask()    {
106         return joystick.present_mask;
107 }
108
109 void joy_set_timer_rate(int max_value ) {
110         joystick.max_timer = max_value;
111 }
112
113 int joy_get_timer_rate()        {
114         return joystick.max_timer;
115 }
116
117 void joy_flush()        {
118         int i;
119
120         if (!joy_installed) return;
121
122         for (i=0; i<MAX_BUTTONS; i++ )  {
123                 joystick.buttons[i].ignore = 0;
124                 joystick.buttons[i].state = 0;  
125                 joystick.buttons[i].timedown = 0;       
126                 joystick.buttons[i].downcount = 0;      
127                 joystick.buttons[i].upcount = 0;        
128         }
129
130 }
131
132
133 //Repalces joy_handler
134 //Since Windows calls us directly, we have to get our time difference since last time ourselves
135 //while in DOS we got it with the paramter ticks_this_time
136 LRESULT joy_handler32(HWND hWnd, UINT joymsg, UINT wParam, LPARAM lParam)
137 {
138         DWORD time_diff, time_now;
139         static DWORD time_last = 0xffffffff;
140         
141         Button_info *button;
142         int i;
143         int state=0;
144         DWORD value=0;
145
146         if (!joy_installed) return 1;
147         if (time_last == 0xffffffff) {
148                 time_last = timer_get_fixed_seconds();
149                 return 0;
150         }
151
152         if (joymsg==MM_JOY1MOVE)
153         {
154                 JOYINFOEX       joy;
155
156                 memset(&joy, 0, sizeof(joy));
157                 joy.dwSize = sizeof(joy);
158                 joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;
159                 if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
160                         return 1;
161                 }
162                 value = joy.dwButtons;
163         }
164
165         time_now = timer_get_fixed_seconds();
166         if (time_now < time_last) {
167                 time_last = abs(time_now-time_last);
168         }
169         time_diff = time_now - time_last;
170
171         for (i = 0; i < MAX_BUTTONS; i++)
172         {
173                 button = &joystick.buttons[i];
174                 
175                 if (!button->ignore) {
176                         if ( i < (MAX_BUTTONS-4) )
177                                 state = (value >> i) & 1;
178                         else
179                                 state = 0;
180
181                         if ( button->last_state == state )      {
182                                 if (state) {
183                                         button->timedown += time_diff;  //ticks_this_time;
184                                 }
185                         } else {
186                                 if (state)      {
187                                         button->downcount += state;
188                                         button->state = 1;
189                                 } else {        
190                                         button->upcount += button->state;
191                                         button->state = 0;
192                                 }
193                                 button->last_state = state;
194                         }
195                 }
196         }
197
198         time_last = time_now;
199         return 0;
200 }               
201
202
203 //Begin section modified 3/7/99 - Owen Evans
204
205 ubyte joy_read_raw_buttons()
206 {
207         JOYINFOEX joy;
208         int i;
209
210         if (!joy_present)
211                 return 0; 
212         
213         memset(&joy, 0, sizeof(joy));
214         joy.dwSize = sizeof(joy);
215         joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE;
216         
217         if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR)
218                 return 0;
219
220         for (i = 0; i < MAX_BUTTONS; i++) {
221                 joystick.buttons[i].last_state = joystick.buttons[i].state;
222                 joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1;
223                 if (!joystick.buttons[i].last_state && joystick.buttons[i].state) {
224                         joystick.buttons[i].timedown = timer_get_fixed_seconds();
225                         joystick.buttons[i].downcount++;
226                 }
227         }
228
229         /* Hat stuff */
230
231         if (joy.dwPOV != JOY_POVCENTERED)
232          {
233            joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT);
234            joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD);
235            joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT);
236            joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD);
237          }
238
239         return (ubyte)joy.dwButtons;
240 }
241
242 //end changed section - OE
243
244
245 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
246 {
247         JOYINFOEX       joy;
248         ubyte read_masks = 0;
249
250         axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v
251         axis[2] = 0; axis[3] = 0;
252         axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U
253         
254         if (!joy_installed) {
255                 return 0;
256         }
257         
258         memset(&joy, 0, sizeof(joy));
259         joy.dwSize = sizeof(joy);
260         joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
261         if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) {
262                 return 0;
263         }
264                         
265         mask &= joystick.present_mask;                  // Don't read non-present channels
266         if ( mask==0 )  {
267                 return 0;               // Don't read if no stick connected.
268         }
269
270         if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; }
271         if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; }
272 //orulz:
273 //        if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
274 //        if (mask & JOY_1_POV)    { axis[3] = joy.dwPOV;  read_masks |= JOY_1_POV;    }
275 //        if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
276 //        if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; }
277 //        if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; }
278         if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; }
279         if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; }
280         if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; }
281         if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; }
282
283         return read_masks;
284 }
285
286 int hh_average(int val1, int val2)
287 {
288         return abs(val1-val2)/2;
289 }
290
291 int joy_init(int joyid) //HH: added joyid parameter
292 {
293         int i;
294         int temp_axis[JOY_NUM_AXES];       //changed - orulz
295         JOYCAPS pjc;
296
297         atexit(joy_close);      //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :)
298
299         joy_flush();
300         memset(&joystick, 0, sizeof(joystick));
301
302         for (i=0; i<MAX_BUTTONS; i++)
303                 joystick.buttons[i].last_state = 0;
304
305         if ( !joy_installed )   {
306                 joy_present = 0;
307                 joy_installed = 1;
308                 joystick.max_timer = 65536;
309                 joystick.read_count = 0;
310                 joystick.last_value = 0;
311         }
312
313
314         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
315         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, temp_axis );
316
317         if ( joystick.present_mask & 3 )
318                 joy_present = 1;
319         else
320                 joy_present = 0;
321
322         
323         //HH: Main Win32 joystick initialization, incl. reading cal. stuff
324
325         if (joyGetDevCaps(joyid, &pjc, sizeof(pjc))!=JOYERR_NOERROR) {
326                 return 0;
327         }
328
329         if (joySetThreshold(joyid, pjc.wXmax/256)!=JOYERR_NOERROR) {
330                 return 0;
331         }
332         
333         if (joySetCapture(my_hwnd, joyid, JOY_POLL_RATE, FALSE)!=JOYERR_NOERROR) {
334                 return 0;
335         }
336
337         joystick.max_timer      = pjc.wPeriodMax;
338         joystick.axis_min[0]    = pjc.wXmin;
339         joystick.axis_min[1]    = pjc.wYmin;
340 //orulz:
341 //        joystick.axis_min[2]    = pjc.wZmin;
342 //        //HH: joystick.axis_min[3]  = pov-stuff
343 //        joystick.axis_min[4]    = pjc.wRmin;
344 //        joystick.axis_min[5]    = pjc.wUmin;
345 //        joystick.axis_min[6]    = pjc.wVmin;
346         joystick.axis_min[2]    = pjc.wRmin;
347         joystick.axis_min[3]    = pjc.wZmin;
348         joystick.axis_min[4]    = pjc.wUmin;
349         joystick.axis_min[5]    = pjc.wVmin;
350
351         joystick.axis_max[0]    = pjc.wXmax;
352         joystick.axis_max[1]    = pjc.wYmax;
353 //orulz:
354 //        joystick.axis_max[2]    = pjc.wZmax;
355 //        //HH: joystick.axis_max[3]  = pov-stuff
356 //        joystick.axis_max[4]    = pjc.wRmax;
357 //        joystick.axis_max[5]    = pjc.wUmax;
358 //        joystick.axis_max[6]    = pjc.wVmax;
359         joystick.axis_max[2]    = pjc.wRmax;
360         joystick.axis_max[3]    = pjc.wZmax;
361         joystick.axis_max[4]    = pjc.wUmax;
362         joystick.axis_max[5]    = pjc.wVmax;
363
364         joystick.axis_center[0] = hh_average(pjc.wXmax,pjc.wXmin);
365         joystick.axis_center[1] = hh_average(pjc.wYmax,pjc.wYmin);
366 //orulz:
367 //        joystick.axis_center[2] = hh_average(pjc.wZmax,pjc.wZmin);
368 //        joystick.axis_center[3] = JOY_POVCENTERED;
369 //        joystick.axis_center[4] = hh_average(pjc.wRmax,pjc.wRmin);
370 //        joystick.axis_center[5] = hh_average(pjc.wUmax,pjc.wUmin);
371 //        joystick.axis_center[6] = hh_average(pjc.wVmax,pjc.wVmin);
372         joystick.axis_center[2] = hh_average(pjc.wRmax,pjc.wRmin);
373         joystick.axis_center[3] = hh_average(pjc.wZmax,pjc.wZmin);
374         joystick.axis_center[4] = hh_average(pjc.wUmax,pjc.wUmin);
375         joystick.axis_center[5] = hh_average(pjc.wVmax,pjc.wVmin);
376
377         joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
378         if (pjc.wCaps & JOYCAPS_HASZ)   joystick.present_mask |= JOY_1_Z_AXIS;
379 //        if (pjc.wCaps & JOYCAPS_HASPOV) joystick.present_mask |= JOY_1_POV;
380         if (pjc.wCaps & JOYCAPS_HASR)   joystick.present_mask |= JOY_1_R_AXIS;
381         if (pjc.wCaps & JOYCAPS_HASU)   joystick.present_mask |= JOY_1_U_AXIS;
382         if (pjc.wCaps & JOYCAPS_HASV)   joystick.present_mask |= JOY_1_V_AXIS;
383
384         return joy_present;
385 }
386
387
388 void joy_close()
389 {
390         if (!joy_installed) return;
391         joyReleaseCapture(joystick.joyid); //HH: added to release joystick from the application. We ignore errors here
392         joy_installed = 0;
393 }
394
395
396 void joy_set_ul()       
397 {
398         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
399         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_min );
400
401         if ( joystick.present_mask & 3 )
402                 joy_present = 1;
403         else
404                 joy_present = 0;
405 }
406
407 void joy_set_lr()       
408 {
409         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
410         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_max );
411
412         if ( joystick.present_mask & 3 )
413                 joy_present = 1;
414         else
415                 joy_present = 0;
416 }
417
418 void joy_set_cen() 
419 {
420         joystick.present_mask = JOY_ALL_AXIS;           // Assume they're all present
421         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS, joystick.axis_center );
422
423         if ( joystick.present_mask & 3 )
424                 joy_present = 1;
425         else
426                 joy_present = 0;
427 }
428
429 void joy_set_cen_fake(int channel)      
430 { }
431
432
433 int joy_get_scaled_reading( int raw, int axn )  
434 {
435  int x, d;
436
437   // Make sure it's calibrated properly.
438    if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 )
439     return 0; //HH: had to increase to 128
440    if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 )
441     return 0; //HH: had to increase to 128
442
443   raw -= joystick.axis_center[axn];
444
445    if ( raw < 0 )
446     d = joystick.axis_center[axn]-joystick.axis_min[axn];
447    else
448     d = joystick.axis_max[axn]-joystick.axis_center[axn];
449
450
451    if ( d )
452     x = (raw << 7) / d;
453    else 
454     x = 0;
455
456
457    if ( x < -128 ) x = -128;
458    if ( x > 127 ) x = 127;
459
460 //added on 4/13/99 by Victor Rachels to add deadzone control
461   d =  (joy_deadzone) * 6;
462    if ((x > (-1*d)) && (x < d))
463     x = 0;
464 //end this section addition -VR
465
466         return x;
467 }
468
469 void joy_get_pos( int *x, int *y )      
470 {
471         ubyte flags;
472         int axis[JOY_NUM_AXES];
473
474         if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
475
476         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
477
478         if ( flags & JOY_1_X_AXIS )
479                 *x = joy_get_scaled_reading( axis[0], 0 );
480         else
481                 *x = 0;
482
483         if ( flags & JOY_1_Y_AXIS )
484                 *y = joy_get_scaled_reading( axis[1], 1 );
485         else
486                 *y = 0;
487 }
488
489 ubyte joy_read_stick( ubyte masks, int *axis )  
490 {
491         ubyte flags;
492         int raw_axis[JOY_NUM_AXES];
493
494         if ((!joy_installed)||(!joy_present)) { 
495                 axis[0] = 0; axis[1] = 0;
496                 axis[2] = 0; axis[3] = 0;
497                 axis[4] = 0; axis[5] = 0; 
498                 return 0;  
499         }
500
501         flags=joystick_read_raw_axis( masks, raw_axis );
502
503         if ( flags & JOY_1_X_AXIS )
504                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
505         else
506                 axis[0] = 0;
507
508         if ( flags & JOY_1_Y_AXIS )
509                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
510         else
511                 axis[1] = 0;
512
513         if ( flags & JOY_1_R_AXIS )
514                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
515         else
516                 axis[2] = 0;
517
518         if ( flags & JOY_1_Z_AXIS )
519                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
520         else
521                 axis[3] = 0;
522
523         if ( flags & JOY_1_U_AXIS )
524                 axis[4] = joy_get_scaled_reading( raw_axis[4], 4);
525         else
526                 axis[4] = 0;
527
528         if ( flags & JOY_1_V_AXIS )
529                 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
530         else
531                 axis[5] = 0;
532
533
534         return flags;
535 }
536
537 int joy_get_btns()      
538 {
539         if ((!joy_installed)||(!joy_present)) return 0;
540
541         return joy_read_raw_buttons();
542 }
543
544
545 //Begin section modified 3/7/99 - Owen Evans
546
547 void joy_get_btn_down_cnt( int *btn0, int *btn1 )
548 {
549         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
550
551         joy_get_btns();
552
553         *btn0 = joystick.buttons[0].downcount;
554         joystick.buttons[0].downcount = 0;
555         *btn1 = joystick.buttons[1].downcount;
556         joystick.buttons[1].downcount = 0;
557 }
558
559 int joy_get_button_state( int btn )     
560 {    
561         if ((!joy_installed)||(!joy_present)) return 0;
562         if ( btn >= MAX_BUTTONS ) return 0;
563
564         joy_get_btns();
565
566         return joystick.buttons[btn].state;
567 }
568
569 int joy_get_button_up_cnt( int btn ) 
570 {
571         int count;
572
573         if ((!joy_installed)||(!joy_present)) return 0;
574
575         if ( btn >= MAX_BUTTONS ) return 0;
576
577         count = joystick.buttons[btn].upcount;
578         joystick.buttons[btn].upcount = 0;
579
580         return count;
581 }
582
583 int joy_get_button_down_cnt( int btn ) 
584 {
585         int count;
586
587         if ((!joy_installed)||(!joy_present)) return 0;
588         if ( btn >= MAX_BUTTONS ) return 0;
589
590         joy_get_btns();
591
592         count = joystick.buttons[btn].downcount;
593         joystick.buttons[btn].downcount = 0;
594
595         return count;
596 }
597
598 fix joy_get_button_down_time( int btn ) 
599 {
600         fix count;
601
602         if ((!joy_installed)||(!joy_present)) return 0;
603         if ( btn >= MAX_BUTTONS ) return 0;
604
605         joy_get_btns();
606
607         if (joystick.buttons[btn].state) {
608                 count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown;
609                 joystick.buttons[btn].timedown = 0;
610         } else count = 0;
611         
612         return count;
613 }
614
615 //end changed section - OE
616
617
618 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
619 {
620         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
621
622         *btn0 = joystick.buttons[0].upcount;
623         joystick.buttons[0].upcount = 0;
624         *btn1 = joystick.buttons[1].upcount;
625         joystick.buttons[1].upcount = 0;
626 }
627
628 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
629 {
630         joystick.buttons[btn].ignore = 1;
631         joystick.buttons[btn].state = state;
632         joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 );
633         joystick.buttons[btn].downcount = downcount;
634         joystick.buttons[btn].upcount = upcount;
635 }
636
637 void joy_poll()
638 {
639 }
640