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