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