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