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