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