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