added new arg and printfs for mouse driver problems (d1x r1.2, r1.2)
[btb/d2x.git] / arch / dos / mouse.c
1 /* $Id: mouse.c,v 1.4 2004-05-21 00:48:14 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-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Functions to access Mouse and Cyberman...
18  *
19  * Old Log:
20  * Revision 1.11  1995/02/10  18:52:17  john
21  * Fixed bug with mouse not getting closed.
22  *
23  * Revision 1.10  1995/02/02  11:10:33  john
24  * Changed a bunch of mouse stuff around to maybe get
25  * around PS/2 mouse hang.
26  *
27  * Revision 1.9  1995/01/14  19:19:52  john
28  * Fixed signed short error cmp with -1 that caused mouse
29  * to break under Watcom 10.0
30  *
31  * Revision 1.8  1994/12/27  12:38:23  john
32  * Made mouse use temporary dos buffer instead of
33  *
34  * allocating its own.
35  *
36  *
37  * Revision 1.7  1994/12/05  23:54:53  john
38  * Fixed bug with mouse_get_delta only returning positive numbers..
39  *
40  * Revision 1.6  1994/11/18  23:18:18  john
41  * Changed some shorts to ints.
42  *
43  * Revision 1.5  1994/09/13  12:34:02  john
44  * Added functions to get down count and state.
45  *
46  * Revision 1.4  1994/08/29  20:52:19  john
47  * Added better cyberman support; also, joystick calibration
48  * value return funcctiionn,
49  *
50  * Revision 1.3  1994/08/24  18:54:32  john
51  * *** empty log message ***
52  *
53  * Revision 1.2  1994/08/24  18:53:46  john
54  * Made Cyberman read like normal mouse; added dpmi module; moved
55  * mouse from assembly to c. Made mouse buttons return time_down.
56  *
57  * Revision 1.1  1994/08/24  13:56:37  john
58  * Initial revision
59  *
60  *
61  */
62
63 #ifdef HAVE_CONFIG_H
64 #include <conf.h>
65 #endif
66
67 #ifdef __DJGPP__
68 #include <dpmi.h>
69 #define _BORLAND_DOS_REGS 1
70 #define near
71 _go32_dpmi_registers handler_regs;
72 #endif
73
74 #include <go32.h>
75
76 #include <stdlib.h>
77 #include <stdio.h>
78 //#include <conio.h>
79 #include <dos.h>
80 //#include <i86.h>
81 #include <string.h>
82
83 #include "error.h"
84 #include "fix.h"
85 #include "u_dpmi.h"
86 #include "mouse.h"
87 #include "timer.h"
88
89 #define ME_CURSOR_MOVED (1<<0)
90 #define ME_LB_P                         (1<<1)
91 #define ME_LB_R                         (1<<2)
92 #define ME_RB_P                         (1<<3)
93 #define ME_RB_R                         (1<<4)
94 #define ME_MB_P                         (1<<5)
95 #define ME_MB_R                         (1<<6)
96 #define ME_OB_P                         (1<<7)
97 #define ME_OB_R                         (1<<8)
98 #define ME_X_C                  (1<<9)
99 #define ME_Y_C                  (1<<10)
100 #define ME_Z_C                  (1<<11)
101 #define ME_P_C                  (1<<12)
102 #define ME_B_C                  (1<<13)
103 #define ME_H_C                  (1<<14)
104 #define ME_O_C                  (1<<15)
105
106 #define MOUSE_MAX_BUTTONS       11
107
108 typedef struct event_info {
109         short x;
110         short y;
111         short z;
112         short pitch;
113         short bank;
114         short heading;
115         ushort button_status;
116         ushort device_dependant;
117 } event_info;
118
119 typedef struct mouse_info {
120         fix             ctime;
121         ubyte           cyberman;
122         int             num_buttons;
123         ubyte           pressed[MOUSE_MAX_BUTTONS];
124         fix             time_went_down[MOUSE_MAX_BUTTONS];
125         fix             time_held_down[MOUSE_MAX_BUTTONS];
126         uint            num_downs[MOUSE_MAX_BUTTONS];
127         uint            num_ups[MOUSE_MAX_BUTTONS];
128         event_info *x_info;
129         ushort  button_status;
130 } mouse_info;
131
132 typedef struct cyberman_info {
133         ubyte device_type;
134         ubyte major_version;
135         ubyte minor_version;
136         ubyte x_descriptor;
137         ubyte y_descriptor;
138         ubyte z_descriptor;
139         ubyte pitch_descriptor;
140         ubyte roll_descriptor;
141         ubyte yaw_descriptor;
142         ubyte reserved;
143 } cyberman_info;
144
145 static mouse_info Mouse;
146
147 static int Mouse_installed = 0;
148
149 #ifdef __DJGPP__
150 #define m_ax r->d.eax
151 #define mbx r->d.ebx
152 #define mcx r->d.ecx
153 #define mdx r->d.edx
154 #define msi r->d.esi
155 #define mdi r->d.edi
156 void mouse_handler (_go32_dpmi_registers *r)
157 {
158 #else
159 #pragma off (check_stack)
160 void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi)
161 {
162 #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
163 #endif
164         Mouse.ctime = timer_get_fixed_secondsX();
165
166         if (m_ax & ME_LB_P)     {       // left button pressed
167                 if (!Mouse.pressed[MB_LEFT])    {
168                         Mouse.pressed[MB_LEFT] = 1;
169                         Mouse.time_went_down[MB_LEFT] = Mouse.ctime;
170                 }
171                 Mouse.num_downs[MB_LEFT]++;
172         } else if (m_ax & ME_LB_R )     {  // left button released
173                 if (Mouse.pressed[MB_LEFT])     {
174                         Mouse.pressed[MB_LEFT] = 0;
175                         Mouse.time_held_down[MB_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_LEFT];
176                 }
177                 Mouse.num_ups[MB_LEFT]++;
178         }
179
180         if (m_ax & ME_RB_P ) {  // right button pressed
181                 if (!Mouse.pressed[MB_RIGHT])   {
182                         Mouse.pressed[MB_RIGHT] = 1;
183                         Mouse.time_went_down[MB_RIGHT] = Mouse.ctime;
184                 }
185                 Mouse.num_downs[MB_RIGHT]++;
186         } else if (m_ax & ME_RB_R )     {// right button released
187                 if (Mouse.pressed[MB_RIGHT])    {
188                         Mouse.pressed[MB_RIGHT] = 0;
189                         Mouse.time_held_down[MB_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_RIGHT];
190                 }
191                 Mouse.num_ups[MB_RIGHT]++;
192         }
193
194         if (m_ax & ME_MB_P )    { // middle button pressed
195                 if (!Mouse.pressed[MB_MIDDLE])  {
196                         Mouse.pressed[MB_MIDDLE] = 1;
197                         Mouse.time_went_down[MB_MIDDLE] = Mouse.ctime;
198                 }
199                 Mouse.num_downs[MB_MIDDLE]++;
200         } else if (m_ax & ME_MB_R )     { // middle button released
201                 if (Mouse.pressed[MB_MIDDLE])   {
202                         Mouse.pressed[MB_MIDDLE] = 0;
203                         Mouse.time_held_down[MB_MIDDLE] += Mouse.ctime-Mouse.time_went_down[MB_MIDDLE];
204                 }
205                 Mouse.num_ups[MB_MIDDLE]++;
206         }
207
208         if (Mouse.cyberman && (m_ax & (ME_Z_C|ME_P_C|ME_B_C|ME_H_C)))   {
209                 Mouse.x_info = (event_info *)((msi & 0xFFFF) << 4);
210
211                 if (m_ax & ME_Z_C )     { // z axis changed
212                         if (Mouse.pressed[MB_Z_UP])     {
213                                 // z up released
214                                 Mouse.pressed[MB_Z_UP] = 0;
215                                 Mouse.time_held_down[MB_Z_UP] += Mouse.ctime-Mouse.time_went_down[MB_Z_UP];
216                                 Mouse.num_ups[MB_Z_UP]++;
217                         }  else if ( Mouse.x_info->z>0 )        {
218                                 // z up pressed
219                                 Mouse.pressed[MB_Z_UP] = 1;
220                                 Mouse.time_went_down[MB_Z_UP]=Mouse.ctime;
221                                 Mouse.num_downs[MB_Z_UP]++;
222                         }
223                         if (Mouse.pressed[MB_Z_DOWN])   {
224                                 // z down released
225                                 Mouse.pressed[MB_Z_DOWN] = 0;
226                                 Mouse.time_held_down[MB_Z_DOWN] += Mouse.ctime-Mouse.time_went_down[MB_Z_DOWN];
227                                 Mouse.num_ups[MB_Z_DOWN]++;
228                         }  else if ( Mouse.x_info->z<0 )        {
229                                 // z down pressed
230                                 Mouse.pressed[MB_Z_DOWN] = 1;
231                                 Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime;
232                                 Mouse.num_downs[MB_Z_DOWN]++;
233                         }
234                 }
235                 if (m_ax & ME_P_C )     { // pitch changed
236                         if (Mouse.pressed[MB_PITCH_BACKWARD])   {
237                                 // pitch backward released
238                                 Mouse.pressed[MB_PITCH_BACKWARD] = 0;
239                                 Mouse.time_held_down[MB_PITCH_BACKWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_BACKWARD];
240                                 Mouse.num_ups[MB_PITCH_BACKWARD]++;
241                         }  else if ( Mouse.x_info->pitch>0 )    {
242                                 // pitch backward pressed
243                                 Mouse.pressed[MB_PITCH_BACKWARD] = 1;
244                                 Mouse.time_went_down[MB_PITCH_BACKWARD]=Mouse.ctime;
245                                 Mouse.num_downs[MB_PITCH_BACKWARD]++;
246                         }
247                         if (Mouse.pressed[MB_PITCH_FORWARD])    {
248                                 // pitch forward released
249                                 Mouse.pressed[MB_PITCH_FORWARD] = 0;
250                                 Mouse.time_held_down[MB_PITCH_FORWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_FORWARD];
251                                 Mouse.num_ups[MB_PITCH_FORWARD]++;
252                         }  else if ( Mouse.x_info->pitch<0 )    {
253                                 // pitch forward pressed
254                                 Mouse.pressed[MB_PITCH_FORWARD] = 1;
255                                 Mouse.time_went_down[MB_PITCH_FORWARD]=Mouse.ctime;
256                                 Mouse.num_downs[MB_PITCH_FORWARD]++;
257                         }
258                 }
259
260                 if (m_ax & ME_B_C )     { // bank changed
261                         if (Mouse.pressed[MB_BANK_LEFT])        {
262                                 // bank left released
263                                 Mouse.pressed[MB_BANK_LEFT] = 0;
264                                 Mouse.time_held_down[MB_BANK_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_LEFT];
265                                 Mouse.num_ups[MB_BANK_LEFT]++;
266                         }  else if ( Mouse.x_info->bank>0 )     {
267                                 // bank left pressed
268                                 Mouse.pressed[MB_BANK_LEFT] = 1;
269                                 Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime;
270                                 Mouse.num_downs[MB_BANK_LEFT]++;
271                         }
272                         if (Mouse.pressed[MB_BANK_RIGHT])       {
273                                 // bank right released
274                                 Mouse.pressed[MB_BANK_RIGHT] = 0;
275                                 Mouse.time_held_down[MB_BANK_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_RIGHT];
276                                 Mouse.num_ups[MB_BANK_RIGHT]++;
277                         }  else if ( Mouse.x_info->bank<0 )     {
278                                 // bank right pressed
279                                 Mouse.pressed[MB_BANK_RIGHT] = 1;
280                                 Mouse.time_went_down[MB_BANK_RIGHT]=Mouse.ctime;
281                                 Mouse.num_downs[MB_BANK_RIGHT]++;
282                         }
283                 }
284
285                 if (m_ax & ME_H_C )     { // heading changed
286                         if (Mouse.pressed[MB_HEAD_LEFT])        {
287                                 // head left released
288                                 Mouse.pressed[MB_HEAD_LEFT] = 0;
289                                 Mouse.time_held_down[MB_HEAD_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_LEFT];
290                                 Mouse.num_ups[MB_HEAD_LEFT]++;
291                         }  else if ( Mouse.x_info->heading>0 )  {
292                                 // head left pressed
293                                 Mouse.pressed[MB_HEAD_LEFT] = 1;
294                                 Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime;
295                                 Mouse.num_downs[MB_HEAD_LEFT]++;
296                         }
297                         if (Mouse.pressed[MB_HEAD_RIGHT])       {
298                                 // head right released
299                                 Mouse.pressed[MB_HEAD_RIGHT] = 0;
300                                 Mouse.time_held_down[MB_HEAD_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_RIGHT];
301                                 Mouse.num_ups[MB_HEAD_RIGHT]++;
302                         }  else if ( Mouse.x_info->heading<0 )  {
303                                 // head right pressed
304                                 Mouse.pressed[MB_HEAD_RIGHT] = 1;
305                                 Mouse.time_went_down[MB_HEAD_RIGHT]=Mouse.ctime;
306                                 Mouse.num_downs[MB_HEAD_RIGHT]++;
307                         }
308                 }
309         }
310         
311 }
312
313
314
315
316 void mouse_handler_end (void)  // dummy functions
317 {
318 }
319 #ifndef __DJGPP__
320 #pragma on (check_stack)
321 #endif
322
323 //--------------------------------------------------------
324 // returns 0 if no mouse
325 //           else number of buttons
326 int mouse_init(int enable_cyberman)
327 {
328         dpmi_real_regs rr;
329         cyberman_info *ci;
330 #ifndef __DJGPP__
331         struct SREGS sregs;
332 #endif
333         union REGS inregs, outregs;
334         ubyte *Mouse_dos_mem;
335
336         if (Mouse_installed)
337                 return Mouse.num_buttons;
338
339 #ifdef __DJGPP__
340        if (_farpeekl(_dos_ds, 0x33 * 4) == 0) {
341 #else
342        if (_dos_getvect(0x33) == NULL) {
343 #endif
344                         // added on 1/13/2000 by Victor Rachels for more info
345                         con_printf(CON_NORMAL, "\nNo mouse driver found!\n");
346                         // end this section addition - VR
347                 // No mouse driver loaded
348                 return 0;
349        }
350
351         // Reset the mouse driver
352         memset( &inregs, 0, sizeof(inregs) );
353         inregs.w.ax = 0;
354         int386(0x33, &inregs, &outregs);
355         if (outregs.w.ax != 0xffff)
356         {
357                 // added on 1/13/2000 by Victor Rachels for more info
358                 con_printf(CON_NORMAL, "\nUnable to reset mouse!\n");
359                 // end this section edit - VR
360
361                 return 0;
362         }
363
364         Mouse.num_buttons = outregs.w.bx;
365         Mouse.cyberman = 0;
366
367         // Enable mouse driver
368         // added/edited on 1/15/2000 by Victor Rachels to make this optional - can usually be used w or w/o this reset
369         if(!FindArg("-ihaveabrokenmouse"))
370         {
371                 memset(&inregs, 0, sizeof(inregs));
372                 inregs.w.ax = 0x0020;
373                 int386(0x33, &inregs, &outregs);
374                 if (outregs.w.ax != 0xffff)
375                 {
376                         // added on 1/13/2000 by Victor Rachels for more info
377                         con_printf(CON_NORMAL, "\nUnable to enable mouse! (%x)\n", outregs.w.ax);
378                         // end this section edit - VR
379                         return 0;
380                 }
381         }
382         // end this section edit/addition - VR
383
384         if ( enable_cyberman )  {
385                 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
386                 if (Mouse_dos_mem==NULL)        {
387                         printf( "Unable to allocate DOS buffer in mouse.c\n" );
388                 } else {
389                         // Check for Cyberman...        
390                         memset( &rr, 0, sizeof(dpmi_real_regs) );
391                         rr.es = DPMI_real_segment(Mouse_dos_mem);
392                         rr.edx = DPMI_real_offset(Mouse_dos_mem);
393                         rr.eax = 0x53c1;
394                         dpmi_real_int386x( 0x33, &rr );
395                         if (rr.eax==1)  {
396                                 // SWIFT functions supported
397                                 ci      = (cyberman_info *)Mouse_dos_mem;
398                                 if (ci->device_type==1) {       // Cyberman     
399                                         Mouse.cyberman = 1;
400                                         //printf( "Cyberman mouse detected\n" );
401                                         Mouse.num_buttons = 11;
402                                 }
403                         }
404                 }
405         }
406
407         if (!dpmi_lock_region(&Mouse,sizeof(mouse_info)))       {
408                 printf( "Unable to lock mouse data region" );
409                 exit(1);
410         }
411         if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler))       {
412                 printf( "Unable to lock mouse handler" );
413                 exit(1);
414         }
415
416         // Install mouse handler
417 #ifdef __DJGPP__
418         {
419          dpmi_real_regs rregs;
420          _go32_dpmi_seginfo info;
421          memset(&rregs, 0, sizeof(rregs));
422          info.pm_offset = (unsigned int)&mouse_handler;
423          if (_go32_dpmi_allocate_real_mode_callback_retf(&info, &handler_regs)) {
424                 printf( "Unable allocate mouse handler callback" );
425                 exit(1);
426          }
427          rregs.eax     = 0xC;
428          rregs.ecx     = ME_LB_P|ME_LB_R|ME_RB_P|ME_RB_R|ME_MB_P|ME_MB_R;      // watch all 3 button ups/downs
429          if (Mouse.cyberman)
430                 rregs.ecx     |= ME_Z_C| ME_P_C| ME_B_C| ME_H_C;      // if using a cyberman, also watch z, pitch, bank, heading.
431          rregs.edx       = info.rm_offset;
432          rregs.es        = info.rm_segment;
433          dpmi_real_int386x( 0x33, &rregs );
434         }
435 #else
436         memset( &inregs, 0, sizeof(inregs));
437         memset( &sregs, 0, sizeof(sregs));
438         inregs.w.ax     = 0xC;
439         inregs.w.cx     = ME_LB_P|ME_LB_R|ME_RB_P|ME_RB_R|ME_MB_P|ME_MB_R;      // watch all 3 button ups/downs
440         if (Mouse.cyberman)
441                 inregs.w.cx     |= ME_Z_C| ME_P_C| ME_B_C| ME_H_C;      // if using a cyberman, also watch z, pitch, bank, heading.
442         inregs.x.edx    = FP_OFF(mouse_handler);
443         sregs.es                = FP_SEG(mouse_handler);
444         int386x(0x33, &inregs, &outregs, &sregs);
445 #endif
446
447         Mouse_installed = 1;
448
449         atexit( mouse_close );
450
451         mouse_flush();
452
453         return Mouse.num_buttons;
454 }
455
456
457
458 void mouse_close()
459 {
460         struct SREGS sregs;
461         union REGS inregs, outregs;
462
463         if (Mouse_installed)    {
464                 Mouse_installed = 0;
465                 // clear mouse handler by setting flags to 0.
466                 memset( &inregs, 0, sizeof(inregs));
467                 memset( &sregs, 0, sizeof(sregs));
468                 inregs.w.ax     = 0xC;
469                 inregs.w.cx             = 0;            // disable event handler by setting to zero.
470                 inregs.x.edx    = 0;    
471                 sregs.es       = 0;
472                 int386x(0x33, &inregs, &outregs, &sregs);
473         }
474 }
475
476
477 void mouse_set_limits( int x1, int y1, int x2, int y2 )
478 {
479         union REGS inregs, outregs;
480
481         if (!Mouse_installed) return;
482
483         memset( &inregs, 0, sizeof(inregs));
484         inregs.w.ax = 0x7;      // Set Horizontal Limits for Pointer
485         inregs.w.cx = x1;
486         inregs.w.dx = x2;
487         int386(0x33, &inregs, &outregs);
488
489         memset( &inregs, 0, sizeof(inregs));
490         inregs.w.ax = 0x8;      // Set Vertical Limits for Pointer
491         inregs.w.cx = y1;
492         inregs.w.dx = y2;
493         int386(0x33, &inregs, &outregs);
494 }
495
496 void mouse_get_pos( int *x, int *y)
497 {
498         union REGS inregs, outregs;
499
500         if (!Mouse_installed) {
501                 *x = *y = 0;
502                 return;
503         }
504         memset( &inregs, 0, sizeof(inregs));
505         inregs.w.ax = 0x3;      // Get Mouse Position and Button Status
506         int386(0x33, &inregs, &outregs);
507         *x = (short)outregs.w.cx; 
508         *y = (short)outregs.w.dx; 
509 }
510
511 void mouse_get_delta( int *dx, int *dy )
512 {
513         union REGS inregs, outregs;
514
515         if (!Mouse_installed) {
516                 *dx = *dy = 0;
517                 return;
518         }
519
520         memset( &inregs, 0, sizeof(inregs));
521         inregs.w.ax = 0xb;      // Read Mouse motion counters
522         int386(0x33, &inregs, &outregs);
523         *dx = (short)outregs.w.cx; 
524         *dy = (short)outregs.w.dx; 
525 }
526
527 int mouse_get_btns()
528 {
529         int i;
530         uint flag=1;
531         int status = 0;
532
533         if (!Mouse_installed) 
534                 return 0;
535
536         for (i=0; i<MOUSE_MAX_BUTTONS; i++ )    {
537                 if (Mouse.pressed[i])
538                         status |= flag;
539                 flag <<= 1;
540         }
541         return status;
542 }
543
544 void mouse_set_pos( int x, int y)
545 {
546         union REGS inregs, outregs;
547
548         if (!Mouse_installed) 
549                 return;
550
551         memset( &inregs, 0, sizeof(inregs));
552         inregs.w.ax = 0x4;      // Set Mouse Pointer Position
553         inregs.w.cx = x;
554         inregs.w.dx = y;
555         int386(0x33, &inregs, &outregs);
556
557 }
558
559 void mouse_flush()
560 {
561         int i;
562         fix CurTime;
563
564         if (!Mouse_installed) 
565                 return;
566
567         _disable();
568
569         //Clear the mouse data
570         CurTime =timer_get_fixed_secondsX();
571         for (i=0; i<MOUSE_MAX_BUTTONS; i++ )    {
572                 Mouse.pressed[i] = 0;
573                 Mouse.time_went_down[i] = CurTime;
574                 Mouse.time_held_down[i] = 0;
575                 Mouse.num_downs[i]=0;
576                 Mouse.num_ups[i]=0;
577         }
578         _enable();
579 }
580
581
582 // Returns how many times this button has went down since last call.
583 int mouse_button_down_count(int button) 
584 {
585         int count;
586
587         if (!Mouse_installed) 
588                 return 0;
589
590         _disable();
591
592         count = Mouse.num_downs[button];
593         Mouse.num_downs[button]=0;
594
595         _enable();
596
597         return count;
598 }
599
600 // Returns 1 if this button is currently down
601 int mouse_button_state(int button)      
602 {
603         int state;
604
605         if (!Mouse_installed) 
606                 return 0;
607
608         _disable();
609
610         state = Mouse.pressed[button];
611
612         _enable();
613
614         return state;
615 }
616
617
618
619 // Returns how long this button has been down since last call.
620 fix mouse_button_down_time(int button)  
621 {
622         fix time_down, time;
623
624         if (!Mouse_installed) 
625                 return 0;
626
627         _disable();
628
629         if ( !Mouse.pressed[button] )   {
630                 time_down = Mouse.time_held_down[button];
631                 Mouse.time_held_down[button] = 0;
632         } else  {
633                 time = timer_get_fixed_secondsX();
634                 time_down =  time - Mouse.time_went_down[button];
635                 Mouse.time_went_down[button] = time;
636         }
637
638         _enable();
639
640         return time_down;
641 }
642
643 void mouse_get_cyberman_pos( int *x, int *y )
644 {
645         dpmi_real_regs rr;
646         event_info * ei;
647         ubyte *Mouse_dos_mem;
648
649         if ( (!Mouse_installed) || (!Mouse.cyberman) ) {
650                 *x = *y = 0;
651                 return;
652         }
653
654         Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
655
656         if ( !Mouse_dos_mem )   {
657                 *x = *y = 0;
658                 return;
659         }
660
661
662         memset( &rr, 0, sizeof(dpmi_real_regs) );
663         rr.es = DPMI_real_segment(Mouse_dos_mem);
664         rr.edx = DPMI_real_offset(Mouse_dos_mem);
665         rr.eax = 0x5301;
666         dpmi_real_int386x( 0x33, &rr );
667
668         ei = (event_info *)Mouse_dos_mem;
669
670         *x = (((ei->x+8128)*256)/(8064+8128+1)) - 127;
671         *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127;
672 }