]> icculus.org git repositories - btb/d2x.git/blob - unused/win95/joyc.c
divide negative window x-coordinates properly, fixing random crashes
[btb/d2x.git] / unused / win95 / joyc.c
1 /* $Id: joyc.c,v 1.2 2005-04-04 09:21:25 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15
16 #pragma off (unreferenced)
17 static char rcsid[] = "$Id: joyc.c,v 1.2 2005-04-04 09:21:25 btb Exp $";
18 #pragma on (unreferenced)
19
20 #define WIN95
21 #define _WIN32
22 #define WIN32_LEAN_AND_MEAN
23
24 #include <windows.h>
25 #include <mmsystem.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <conio.h>
29
30 #include "winapp.h"
31 #include "types.h"
32 #include "mono.h"
33 #include "joy.h"
34 #include "tactile.h"
35 #include "winregs.h"
36
37 #include "args.h"
38
39 //      Controls
40 //#include "win\cyberimp.h"
41 //#include "spw_inp.h"
42
43 #define WIN_TACTILE_ON
44
45 #define JOY_READ_BUTTONS 
46 #define JOY_MAX_BUTTONS 20
47 #define JOY_POLL_RATE   75      // 100 ms.
48
49
50 //      Data Structures ============================================================
51
52 typedef struct Button_info {
53         ubyte           ignore;
54         ubyte           state;
55         ubyte           last_state;
56         unsigned        timedown;
57         ubyte           downcount;
58         ubyte           upcount;
59 } Button_info;
60
61 typedef struct Joy_info {
62         int                     joyid;
63         ubyte                   present_mask;
64         int                     max_timer;
65         int                     read_count;
66         ubyte                   last_value;
67         Button_info buttons[JOY_MAX_BUTTONS];
68         int                     axis_min[7];
69         int                     axis_center[7];
70         int                     axis_max[7];
71         int                     has_pov;
72         int                     threshold;
73         int                     raw_x1, raw_y1, raw_z1, raw_r1, raw_u1, raw_v1, pov;
74 } Joy_info;
75
76 LRESULT joy_handler_win(HWND hWnd, UINT joymsg, UINT wParam, LPARAM lParam);
77
78
79 //      Globals ====================================================================
80
81 Joy_info joystick;
82 int SpecialDevice = 0;
83
84 char SBall_installed = 0;
85 char joy_installed = 0;
86 char joy_present = 0;
87
88
89 //      Extra Controls structures
90 //SPW_Control SBall_Control;                                            // Space Ball Interface
91
92 static JOYCAPS  WinJoyCaps;
93 static BOOL             CHStickHack=0;
94
95
96 //      Functions ==================================================================
97
98 /*      joy_init
99                 Reset joystick information and request joystick notification from
100                 Windows...  Calibration shouldn't be a problem since Windows 95 takes
101                 care of that.  Also attaches a window to the joystick.
102 */
103 int joy_init(int joy, int spjoy)
104 {
105         int i;
106         //int num_devs;
107
108         atexit(joy_close);
109
110 //      Reset Joystick information.
111         joy_flush();
112         memset(&joystick, 0, sizeof(joystick));
113
114         for (i = 0; i < JOY_MAX_BUTTONS; i++)
115                 joystick.buttons[i].last_state = 0;
116
117         if ( !joy_installed )   {
118       joy_present = 0;
119       joy_installed = 1;
120       joystick.max_timer = 65536;
121       joystick.read_count = 0;
122       joystick.last_value = 0;
123         }
124
125         if (spjoy) {
126         // Special joystick interface initialize.
127                 int port;
128
129                 SpecialDevice = 0;
130                 joy_present = 0;
131
132         //      if (FindArg("-CyberImpact")) 
133         //              SpecialDevice = TACTILE_CYBERNET;                       
134
135                 if (i = FindArg("-Iforce")) {
136                         SpecialDevice = TACTILE_IMMERSION;
137                         if (atoi(Args[i+1]) != 0) port = atoi(Args[i+1]);
138                 }
139                         
140                 if (SpecialDevice) 
141                         mprintf((0, "Using Special Joystick!\n"));
142                 
143                 switch(SpecialDevice)
144                 {
145                 #ifdef WIN_TACTILE_ON
146                         case TACTILE_CYBERNET:
147                                 TactileStick = TACTILE_CYBERNET;
148                                 if (!Tactile_open(0)) joy_present = 0;
149                                 else joy_present = 1;
150                                 break;
151
152                         case TACTILE_IMMERSION:
153                                 TactileStick = TACTILE_IMMERSION;
154                                 if (!Tactile_open(port)) joy_present = 0;
155                                 else joy_present = 1;
156                                 break;
157                 #endif
158                 }
159                 if (!joy_present) SpecialDevice = 0;
160         }       
161         else 
162                 joy_present = (char)joyGetNumDevs();
163                 
164
165         return joy_present;
166 }
167
168
169 //      joy_close
170 //              closes to joystick by releasing it from the application window
171
172 void joy_close()
173 {
174         if (joy_installed) {
175         
176                 switch (SpecialDevice)
177                 {
178                         case TACTILE_CYBERNET:
179                                 SpecialDevice = 0;
180                                 break;
181                 
182                         case TACTILE_IMMERSION:
183                                 SpecialDevice = 0;      
184                                 break;
185                 }
186                 joyReleaseCapture(joystick.joyid);
187                 joy_installed = 0;
188         }
189 }
190                 
191
192 //      joy_get/set_cal_vals
193 //              functions that access all of the joystick axis'.  
194 //              An array of at least four elements must be passed to each function
195
196 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
197 {
198    int i;
199
200    for (i=0; i < 7; i++)
201         {
202       axis_min[i] = joystick.axis_min[i];
203       axis_center[i] = joystick.axis_center[i];
204       axis_max[i] = joystick.axis_max[i];
205    }
206 }
207
208
209 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
210 {
211         int i;
212         
213    for (i=0; i < 7; i++)     
214         {
215       joystick.axis_min[i] = axis_min[i];
216       joystick.axis_center[i] = axis_center[i];
217       joystick.axis_max[i] = axis_max[i];
218    }
219 }
220
221
222 //      joy_get_present_mask
223 //              returns the joystick axis' available to be used and accessed
224
225 ubyte joy_get_present_mask()    
226 {
227         return joystick.present_mask;
228 }
229
230
231
232 //      joy_flush
233 //              resets joystick button parameters
234
235 void joy_flush()        
236 {
237    int i;
238
239         for (i = 0; i < JOY_MAX_BUTTONS; i++)
240         {
241       joystick.buttons[i].ignore = 0;
242       joystick.buttons[i].state = 0;
243       joystick.buttons[i].timedown = 0;
244       joystick.buttons[i].downcount = 0;
245       joystick.buttons[i].upcount = 0;
246    }
247 }
248
249
250 //      joy_read_raw_buttons
251 //              returns the status of the buttons at that moment.
252
253 ubyte joy_read_raw_buttons()    
254 {
255         JOYINFOEX       joy;
256         ubyte                   value=0;
257
258         if (!joy_present) { return 0; }
259         
260         memset(&joy, 0, sizeof(joy));
261         joy.dwSize = sizeof(joy);
262         joy.dwFlags = JOY_RETURNBUTTONS | JOY_USEDEADZONE;
263         joyGetPosEx(joystick.joyid, &joy);
264
265 //      For now we support just four buttons
266         value = value | ((ubyte)joy.dwButtons & JOY_BUTTON1);
267         value = value | ((ubyte)joy.dwButtons & JOY_BUTTON2);
268         value = value | ((ubyte)joy.dwButtons & JOY_BUTTON3);
269         value = value | ((ubyte)joy.dwButtons & JOY_BUTTON4);
270         
271         return value;
272 }
273
274
275 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
276 {
277         JOYINFOEX       joy;
278         ubyte read_masks = 0;
279         int i;
280
281         if (!joy_installed) return 0;
282         if (!joy_present) return 0;
283
284         for (i = 0; i < 7; i++)
285                 axis[i] = 0;
286
287         axis[3] = JOY_POVCENTERED;
288
289         switch (SpecialDevice)
290         {
291                 case TACTILE_CYBERNET:
292 //@@                    CyberImpact_ReadRawValues(mask, axis);
293 //@@                    joystick.raw_x1 = axis[0];
294 //@@                    joystick.raw_y1 = axis[1];
295 //@@                    joystick.raw_z1 = axis[2];
296 //@@                    joystick.raw_r1 = axis[4];
297 //@@                    joystick.raw_u1 = axis[5];
298 //@@                    joystick.raw_v1 = axis[6];
299 //@@                    joystick.pov = axis[3];
300 //@@                    break;
301
302                 case TACTILE_IMMERSION:
303                 #ifdef WIN_TACTILE_ON
304                         IForce_ReadRawValues(axis);
305                 #endif
306                         joystick.raw_x1 = axis[0];
307                         joystick.raw_y1 = axis[1];
308                         joystick.raw_z1 = axis[2];
309                         joystick.raw_r1 = axis[4];
310                         joystick.raw_u1 = axis[5];
311                         joystick.raw_v1 = axis[6];
312                         joystick.pov = axis[3];
313                         break;
314
315                 default:
316                         memset(&joy, 0, sizeof(joy));
317                         joy.dwSize = sizeof(joy);
318                         joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE;
319                         joyGetPosEx(joystick.joyid, &joy);
320                         joystick.raw_x1 = joy.dwXpos;
321                         joystick.raw_y1 = joy.dwYpos;
322                         joystick.raw_z1 = joy.dwZpos;
323                         joystick.raw_r1 = joy.dwRpos;
324                         joystick.raw_u1 = joy.dwUpos;
325                         joystick.raw_v1 = joy.dwVpos;
326                         joystick.pov = joy.dwPOV;
327         }
328
329         mask &= joystick.present_mask;
330         if (mask == 0) return 0;                                // Don't read if no stick present
331
332         if (mask & JOY_1_X_AXIS) {
333                 axis[0] = joystick.raw_x1;
334                 read_masks |= JOY_1_X_AXIS;
335         }
336         if (mask & JOY_1_Y_AXIS) {
337                 axis[1] = joystick.raw_y1;
338                 read_masks |= JOY_1_Y_AXIS;
339         }
340         if (mask & JOY_1_Z_AXIS) {
341                 axis[2] = joystick.raw_z1;
342                 read_masks |= JOY_1_Z_AXIS;
343         }
344         if (mask & JOY_1_R_AXIS) {
345                 axis[4] = joystick.raw_r1;
346                 read_masks |= JOY_1_R_AXIS;
347         }
348         if (mask & JOY_1_U_AXIS) {
349                 axis[5] = joystick.raw_u1;
350                 read_masks |= JOY_1_U_AXIS;
351         }
352         if (mask & JOY_1_V_AXIS) {
353                 axis[6] = joystick.raw_v1;
354                 read_masks |= JOY_1_V_AXIS;
355         }
356         if (mask & JOY_1_POV) {
357                 axis[3] = joystick.pov;
358                 read_masks |= JOY_1_POV;
359         }
360
361         return read_masks;
362 }
363
364
365 void joy_set_ul()       
366 {
367         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS+JOY_EXT_AXIS, joystick.axis_min );
368         if ( joystick.present_mask & 3 )
369                 joy_present = 1;
370         else
371                 joy_present = 0;
372 }
373
374
375 void joy_set_lr()       
376 {
377         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS+JOY_EXT_AXIS, joystick.axis_max );
378         if ( joystick.present_mask & 3 )
379                 joy_present = 1;
380         else
381                 joy_present = 0;
382 }
383
384
385 void joy_set_cen() 
386 {
387         switch (SpecialDevice)
388         {
389                 case TACTILE_CYBERNET:
390                 //@@    CyberImpact_CalibCenter();
391                         break;
392         }
393
394         joystick.present_mask = joystick_read_raw_axis( JOY_ALL_AXIS+JOY_EXT_AXIS, joystick.axis_center );
395         if ( joystick.present_mask & 3 )
396                 joy_present = 1;
397         else
398                 joy_present = 0;
399 }
400
401
402 void joy_set_cen_fake(int channel)      
403 {
404 //      Do we need this???
405 }
406
407
408 int joy_get_scaled_reading( int raw, int axn )  
409 {
410         int x, d;
411
412         // Make sure it's calibrated properly.
413         if ( joystick.axis_center[axn] - joystick.axis_min[axn] < 128 ) return 0;
414         if ( joystick.axis_max[axn] - joystick.axis_center[axn] < 128 ) return 0;
415
416         raw -= joystick.axis_center[axn];
417
418         if ( raw < 0 )  {
419                 d = joystick.axis_center[axn]-joystick.axis_min[axn];
420         } else {
421                 d = joystick.axis_max[axn]-joystick.axis_center[axn];
422         }
423
424         if ( d )
425                 x = (raw << 7) / d;
426         else 
427                 x = 0;
428
429         if ( x < -128 ) x = -128;
430         if ( x > 127 ) x = 127;
431
432         return x;
433
434 //@@    int x;
435 //@@
436 //@@    if ((joystick.axis_max[axn] - joystick.axis_min[axn]) == 0) return 0;
437 //@@    if (axn == 3) return raw;
438 //@@    
439 //@@    x = (256 * raw)/(joystick.axis_max[axn]-joystick.axis_min[axn]);
440 //@@    x=x- 128;
441 //@@
442 //@@    return x;
443 }       
444
445
446 void joy_get_pos( int *x, int *y )      
447 {
448         ubyte flags;
449         int axis[4];
450
451
452         if (!joy_installed || !joy_present) { *x = *y = 0; return; }
453
454         flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis );
455
456         if ( flags & JOY_1_X_AXIS )
457                 *x = joy_get_scaled_reading( axis[0], 0 );
458         else
459                 *x = 0;
460
461         if ( flags & JOY_1_Y_AXIS )
462                 *y = joy_get_scaled_reading( axis[1], 1 );
463         else
464                 *y = 0;
465 }
466
467
468 ubyte joy_read_stick( ubyte masks, int *axis )  
469 {
470         ubyte flags;
471         int raw_axis[7];        
472
473
474         if ((!joy_installed)||(!joy_present)) { 
475                 axis[0] = 0; axis[1] = 0;
476                 axis[2] = 0; axis[3] = 0;
477                 axis[4] = 0; axis[5] = 0;
478                 axis[6] = 0; 
479                 return 0;  
480         }
481
482         flags=joystick_read_raw_axis( masks, raw_axis );
483
484         if ( flags & JOY_1_X_AXIS )
485                 axis[0] = joy_get_scaled_reading( raw_axis[0], 0 );
486         else
487                 axis[0] = 0;
488
489         if ( flags & JOY_1_Y_AXIS )
490                 axis[1] = joy_get_scaled_reading( raw_axis[1], 1 );
491         else
492                 axis[1] = 0;
493
494         if ( flags & JOY_1_Z_AXIS )
495                 axis[2] = joy_get_scaled_reading( raw_axis[2], 2 );
496         else
497                 axis[2] = 0;
498
499         if ( flags & JOY_1_R_AXIS )
500                 axis[4] = joy_get_scaled_reading( raw_axis[4], 4 );
501         else
502                 axis[4] = 0;
503
504         if ( flags & JOY_1_U_AXIS )
505                 axis[5] = joy_get_scaled_reading( raw_axis[5], 5 );
506         else
507                 axis[5] = 0;
508
509         if ( flags & JOY_1_V_AXIS )
510                 axis[6] = joy_get_scaled_reading( raw_axis[6], 6 );
511         else
512                 axis[6] = 0;
513
514         if ( flags & JOY_1_POV )
515                 axis[3] = joy_get_scaled_reading( raw_axis[3], 3 );
516         else
517                 axis[3] = 0;
518
519         return flags;
520 }
521
522
523 int joy_get_btns()      
524 {
525         if ((!joy_installed)||(!joy_present)) return 0;
526         return joy_read_raw_buttons();
527 }
528
529
530 void joy_get_btn_down_cnt( int *btn0, int *btn1 ) 
531 {
532         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
533                 
534         *btn0 = joystick.buttons[0].downcount;
535         joystick.buttons[0].downcount = 0;
536         *btn1 = joystick.buttons[1].downcount;
537         joystick.buttons[1].downcount = 0;
538 }
539
540
541 int joy_get_button_state( int btn )     
542 {
543         int count;
544
545         if ((!joy_installed)||(!joy_present)) return 0;
546
547         if (btn >= JOY_MAX_BUTTONS)
548                 return 0;
549
550         count = joystick.buttons[btn].state;
551         
552         return  count;
553 }
554
555
556 int joy_get_button_up_cnt( int btn ) 
557 {
558         int count;
559
560         if ((!joy_installed)||(!joy_present)) return 0;
561
562         if (btn >= JOY_MAX_BUTTONS)
563                 return 0;
564
565         count = joystick.buttons[btn].upcount;
566         joystick.buttons[btn].upcount = 0;
567
568         return count;
569 }
570
571
572 int joy_get_button_down_cnt( int btn ) 
573 {
574         int count;
575
576         if ((!joy_installed)||(!joy_present)) return 0;
577         if (btn >= JOY_MAX_BUTTONS)
578                 return 0;
579
580         count = joystick.buttons[btn].downcount;
581         joystick.buttons[btn].downcount = 0;
582
583         return count;
584 }
585
586         
587 fix joy_get_button_down_time( int btn ) 
588 {
589         fix count;
590
591         if ((!joy_installed)||(!joy_present)) return 0;
592         if (btn >= JOY_MAX_BUTTONS)
593                 return 0;
594
595         count = joystick.buttons[btn].timedown;
596         joystick.buttons[btn].timedown = 0;
597
598         return count;           //fixdiv(count, 1000);
599 }
600
601
602 void joy_get_btn_up_cnt( int *btn0, int *btn1 ) 
603 {
604         if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; }
605         
606         *btn0 = joystick.buttons[0].upcount;
607         joystick.buttons[0].upcount = 0;
608         *btn1 = joystick.buttons[1].upcount;
609         joystick.buttons[1].upcount = 0;
610 }
611
612
613 void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount )
614 {
615         joystick.buttons[btn].ignore = 1;
616         joystick.buttons[btn].state = state;
617         joystick.buttons[btn].timedown = timedown;      //fixmul(timedown,1000);        //convert to miliseconds
618         joystick.buttons[btn].downcount = downcount;
619         joystick.buttons[btn].upcount = upcount;
620 }
621
622
623 //      Windows 95 Custom joystick configuration.
624 //              These are 'low level' routines to get information about a joystick
625 //              in Windows 95.
626 //              Note: spjoy is for 'unique' joysticks.
627
628 int joy95_init_stick(int joy, int spjoy)
629 {
630         UINT                    joyid;
631         MMRESULT        mmresult;
632         char                    joyname[256];
633
634         if (!joy_installed)               
635                 return 0;
636
637         switch (SpecialDevice)
638         {
639                 case TACTILE_CYBERNET:
640                 //@@    joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS | JOY_1_Z_AXIS | JOY_1_POV;
641                 //@@    joystick.has_pov = 1;
642                         break;
643
644                 case TACTILE_IMMERSION:
645                         mprintf((0, "Joystick name= I-Force compatible device.\n"));
646                         break;
647         }
648
649 //      if (spjoy) return 1;
650
651         joystick.joyid = 0;
652
653         if (joy == 1) joystick.joyid = joyid = JOYSTICKID1;
654         else 
655                 return 0;
656
657         mmresult = joyGetDevCaps(joyid, &WinJoyCaps, sizeof(WinJoyCaps));
658         if (mmresult != JOYERR_NOERROR) {
659                 mprintf((1, "Attempt to get Joystick %d caps failed.\n", joy));
660                 return 0;
661         }
662    mprintf ((0,"Joystick name=%s\n",WinJoyCaps.szPname));
663
664 //      Tell our Window App. about this joystick.
665         joySetThreshold(joyid, WinJoyCaps.wXmax/256);
666         mmresult = joySetCapture(GetLibraryWindow(), 
667                                                 joyid, 
668                                                 JOY_POLL_RATE, 
669                                                 FALSE);
670
671         if (mmresult != JOYERR_NOERROR) {
672                 mprintf((1, "Unable to capture joystick %d. Error=%d\n", joy,mmresult));
673                 return 0;
674         }
675
676 //      Get raw axis' min and max.
677         joystick.threshold                      = WinJoyCaps.wXmax/256;
678         joystick.max_timer                      = WinJoyCaps.wPeriodMax;
679
680         joystick.threshold                      = WinJoyCaps.wXmax/256;
681         joystick.max_timer                      = WinJoyCaps.wPeriodMax;
682         joystick.axis_min[0]                    = WinJoyCaps.wXmin;
683         joystick.axis_min[1]                    = WinJoyCaps.wYmin;
684         joystick.axis_min[2]                    = WinJoyCaps.wZmin;
685         joystick.axis_min[4]                    = WinJoyCaps.wRmin;
686         joystick.axis_min[5]                    = WinJoyCaps.wUmin;
687         joystick.axis_min[6]                    = WinJoyCaps.wVmin;
688         joystick.axis_max[0]                    = WinJoyCaps.wXmax;
689         joystick.axis_max[1]                    = WinJoyCaps.wYmax;
690         joystick.axis_max[2]                    = WinJoyCaps.wZmax;
691         joystick.axis_max[4]                    = WinJoyCaps.wRmax;
692         joystick.axis_max[5]                    = WinJoyCaps.wUmax;
693         joystick.axis_max[6]                    = WinJoyCaps.wVmax;
694         joystick.axis_center[0]                 = (WinJoyCaps.wXmax-WinJoyCaps.wXmin)/2;
695         joystick.axis_center[1]                 = (WinJoyCaps.wYmax-WinJoyCaps.wYmin)/2;
696         joystick.axis_center[2]                 = (WinJoyCaps.wZmax-WinJoyCaps.wZmin)/2;
697         joystick.axis_center[4]                 = (WinJoyCaps.wRmax-WinJoyCaps.wRmin)/2;
698         joystick.axis_center[5]                 = (WinJoyCaps.wUmax-WinJoyCaps.wUmin)/2;
699         joystick.axis_center[6]                 = (WinJoyCaps.wVmax-WinJoyCaps.wVmin)/2;
700
701         joystick.present_mask = JOY_1_X_AXIS | JOY_1_Y_AXIS;
702         
703         if (WinJoyCaps.wCaps & JOYCAPS_HASPOV) {
704                 joystick.has_pov = 1;
705                 joystick.present_mask |= JOY_1_POV;
706         }
707         else joystick.has_pov = 0;
708
709         if (WinJoyCaps.wCaps & JOYCAPS_HASZ) 
710                 joystick.present_mask |= JOY_1_Z_AXIS;
711         if (WinJoyCaps.wCaps & JOYCAPS_HASR) 
712                 joystick.present_mask |= JOY_1_R_AXIS;
713         if (WinJoyCaps.wCaps & JOYCAPS_HASU)
714                 joystick.present_mask |= JOY_1_U_AXIS;
715         if (WinJoyCaps.wCaps & JOYCAPS_HASV) 
716                 joystick.present_mask |= JOY_1_V_AXIS;
717
718         joy95_get_name(JOYSTICKID1, joyname, 255);
719         if (!strcmpi(joyname, "CH Flightstick Pro") || FindArg("-ordinaljoy")) {
720                 CHStickHack = 1;
721         }
722         else CHStickHack = 0;
723
724                         
725         return 1;
726 }
727
728 void joy95_get_name(int joyid, char *name, int namesize) 
729 {
730         JOYCAPS jc;
731         MMRESULT res;
732         //HKEY hkey;
733         //long lres;
734         char regpath[256];
735         registry_handle *rhandle;
736         char reglabel[32];
737
738         name[0] = 0;
739
740         switch(SpecialDevice) 
741         {
742                 case TACTILE_IMMERSION:
743                         strcpy(name, "I-Force Force-Feedback");
744                         return;
745         }
746
747         res = joyGetDevCaps(joyid, &jc, sizeof(jc));
748         if (res != JOYERR_NOERROR) {
749                 strcpy(name, "NO JOYSTICK DETECTED");
750                 return;
751         }
752         
753 // we have the reg key!
754         registry_setpath(HKEY_LOCAL_MACHINE);
755         strcpy(regpath, "System\\CurrentControlSet\\control\\MediaResources\\joystick\\");
756         strcat(regpath, jc.szRegKey);
757         strcat(regpath, "\\CurrentJoystickSettings");
758         sprintf(reglabel, "Joystick%dOEMName", joyid+1);
759
760         if ((rhandle = registry_open(regpath))) {
761                 if (!registry_getstring(rhandle, reglabel, name, namesize)) {
762                         registry_close(rhandle);
763                         strcpy(name, "JOYSTICK");
764                         return;
765                 }
766                 registry_close(rhandle);
767         
768         // have reg entry for full name
769                 strcpy(regpath, "System\\CurrentControlSet\\control\\MediaProperties\\PrivateProperties\\Joystick\\OEM\\");
770                 strcat(regpath, name);
771         
772                 if ((rhandle = registry_open(regpath))) {
773                         if (!registry_getstring(rhandle, "OEMName", name, namesize)) {
774                                 registry_close(rhandle);
775                                 strcpy(name, "JOYSTICK");
776                                 return;
777                         }
778                         registry_close(rhandle);
779                 }
780                 else strcpy(name, "JOYSTICK"); 
781         }
782         else strcpy(name, "JOYSTICK");
783 }
784                   
785
786         
787 /*      joy_handler_win
788                 This function takes the place of the joy_handler function for dos.  
789                 The main window procedure will call this function whenever a joystick message
790                 is transmitted.
791 */
792 LRESULT joy_handler_win(HWND hWnd, UINT joymsg, UINT wParam, LPARAM lParam)
793 {
794         DWORD interval_time;
795         DWORD new_time;
796         static DWORD old_time = 0xffffffff;
797         
798         Button_info *button;
799         int state=0;
800         DWORD value=0;
801         int i;
802
803 //      take care of first time initialization
804         if (!joy_installed) return 1;
805         if (old_time == 0xffffffff) {
806                 old_time = timer_get_fixed_seconds();
807                 return 0;
808         }
809
810 //      read and translate buttons 0-3
811         switch (joymsg)
812         {
813                 JOYINFOEX       joy;
814
815                 case MM_JOY1MOVE:
816                 //      For now we support just four buttons
817                         memset(&joy, 0, sizeof(joy));
818                         joy.dwSize = sizeof(joy);
819                         joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;
820                         joyGetPosEx(joystick.joyid, &joy);
821
822                         if (CHStickHack) {
823                                 if (joy.dwPOV == JOY_POVCENTERED && joy.dwButtons > 0) {                  
824                                         value = (1 << (joy.dwButtons-1));
825                                 }
826                                 else value = 0;
827                                 mprintf_at((0, 2, 32, "RAW:%08x OUR:%08x\n", joy.dwButtons, value));
828                         }       
829                         else {
830                                 value = joy.dwButtons;
831                         }
832                         break;
833         }
834
835         new_time = timer_get_fixed_seconds();
836         if (new_time < old_time) old_time = abs(new_time - old_time);
837         interval_time = new_time - old_time;
838
839         for (i = 0; i < JOY_MAX_BUTTONS; i++)
840         {
841         //      Check status of each button and translate information to the button
842         // structure.
843                 button = &joystick.buttons[i];
844                 
845                 if (!button->ignore) {
846                         if (i < (JOY_MAX_BUTTONS - 4))
847                                 state = (value >> i) & 1;
848                         else state = 0;
849
850                         if ( button->last_state == state )      {
851                                 if (state) {
852                                         button->timedown += interval_time;      //interval_ms;
853                                 }
854                         } else {
855                                 if (state)      {
856                                         button->downcount += state;
857                                         button->state = 1;
858                                 } else {        
859                                         button->upcount += button->state;
860                                         button->state = 0;
861                                 }
862                                 button->last_state = state;
863                         }
864                 }
865         }
866
867         old_time = new_time;
868         return 0;
869 }               
870
871
872 void joy_stop_poll()
873 {
874         joyReleaseCapture(joystick.joyid);
875 }
876
877
878 void joy_start_poll()
879 {
880         joySetCapture(GetLibraryWindow(), 
881                                                 joystick.joyid, 
882                                                 JOY_POLL_RATE, 
883                                                 FALSE);
884 }
885
886
887 //      OBSOLETE!!!!
888
889 //      joy_get/set_timer_rate
890 //              these functions are currently implemented for compatability with 
891 //              DOS Descent2, but may be unecessary for now.
892
893 void joy_set_timer_rate(int max_value ) 
894 {
895 //      No real effect, since Joystick runs on its own timer in Windows, for now.
896 }
897
898
899 int joy_get_timer_rate()        
900 {
901         return joystick.max_timer;
902 }
903
904 void joy_handler(int ticks_this_time)   
905 {
906 //      replaced by joy_handler_win for Windows
907 }
908
909 void joy_set_slow_reading(int flag)
910 {
911 //      No need to do this.  In Windows, there are only slow readings.
912 }
913
914 void joy_poll()
915 {
916
917 }
918
919
920