replaced by maths.h
[btb/d2x.git] / unused / bios / 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-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: mouse.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
17 #pragma on (unreferenced)
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <conio.h>
22 #include <dos.h>
23 #include <i86.h>
24 #include <string.h>
25
26 #include "error.h"
27 #include "fix.h"
28 #include "dpmi.h"
29 #include "mouse.h"
30 #include "timer.h"
31
32 #define ME_CURSOR_MOVED (1<<0)
33 #define ME_LB_P                         (1<<1)
34 #define ME_LB_R                         (1<<2)
35 #define ME_RB_P                         (1<<3)
36 #define ME_RB_R                         (1<<4)
37 #define ME_MB_P                         (1<<5)
38 #define ME_MB_R                         (1<<6)
39 #define ME_OB_P                         (1<<7)
40 #define ME_OB_R                         (1<<8)
41 #define ME_X_C                  (1<<9)
42 #define ME_Y_C                  (1<<10)
43 #define ME_Z_C                  (1<<11)
44 #define ME_P_C                  (1<<12)
45 #define ME_B_C                  (1<<13)
46 #define ME_H_C                  (1<<14)
47 #define ME_O_C                  (1<<15)
48
49 #define MOUSE_MAX_BUTTONS       11
50
51 typedef struct event_info {
52         short x;
53         short y;
54         short z;
55         short pitch;
56         short bank;
57         short heading;
58         ushort button_status;
59         ushort device_dependant;
60 } event_info;
61
62 typedef struct mouse_info {
63         fix             ctime;
64         ubyte           cyberman;
65         int             num_buttons;
66         ubyte           pressed[MOUSE_MAX_BUTTONS];
67         fix             time_went_down[MOUSE_MAX_BUTTONS];
68         fix             time_held_down[MOUSE_MAX_BUTTONS];
69         uint            num_downs[MOUSE_MAX_BUTTONS];
70         uint            num_ups[MOUSE_MAX_BUTTONS];
71         event_info *x_info;
72         ushort  button_status;
73 } mouse_info;
74
75 typedef struct cyberman_info {
76         ubyte device_type;
77         ubyte major_version;
78         ubyte minor_version;
79         ubyte x_descriptor;
80         ubyte y_descriptor;
81         ubyte z_descriptor;
82         ubyte pitch_descriptor;
83         ubyte roll_descriptor;
84         ubyte yaw_descriptor;
85         ubyte reserved;
86 } cyberman_info;
87
88 static mouse_info Mouse;
89
90 static int Mouse_installed = 0;
91
92 #pragma off (check_stack)
93 void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi)
94 {
95 #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
96
97         Mouse.ctime = timer_get_fixed_secondsX();
98
99         if (m_ax & ME_LB_P)     {       // left button pressed
100                 if (!Mouse.pressed[MB_LEFT])    {
101                         Mouse.pressed[MB_LEFT] = 1;
102                         Mouse.time_went_down[MB_LEFT] = Mouse.ctime;
103                 }
104                 Mouse.num_downs[MB_LEFT]++;
105         } else if (m_ax & ME_LB_R )     {  // left button released
106                 if (Mouse.pressed[MB_LEFT])     {
107                         Mouse.pressed[MB_LEFT] = 0;
108                         Mouse.time_held_down[MB_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_LEFT];
109                 }
110                 Mouse.num_ups[MB_LEFT]++;
111         }
112
113         if (m_ax & ME_RB_P ) {  // right button pressed
114                 if (!Mouse.pressed[MB_RIGHT])   {
115                         Mouse.pressed[MB_RIGHT] = 1;
116                         Mouse.time_went_down[MB_RIGHT] = Mouse.ctime;
117                 }
118                 Mouse.num_downs[MB_RIGHT]++;
119         } else if (m_ax & ME_RB_R )     {// right button released
120                 if (Mouse.pressed[MB_RIGHT])    {
121                         Mouse.pressed[MB_RIGHT] = 0;
122                         Mouse.time_held_down[MB_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_RIGHT];
123                 }
124                 Mouse.num_ups[MB_RIGHT]++;
125         }
126
127         if (m_ax & ME_MB_P )    { // middle button pressed
128                 if (!Mouse.pressed[MB_MIDDLE])  {
129                         Mouse.pressed[MB_MIDDLE] = 1;
130                         Mouse.time_went_down[MB_MIDDLE] = Mouse.ctime;
131                 }
132                 Mouse.num_downs[MB_MIDDLE]++;
133         } else if (m_ax & ME_MB_R )     { // middle button released
134                 if (Mouse.pressed[MB_MIDDLE])   {
135                         Mouse.pressed[MB_MIDDLE] = 0;
136                         Mouse.time_held_down[MB_MIDDLE] += Mouse.ctime-Mouse.time_went_down[MB_MIDDLE];
137                 }
138                 Mouse.num_ups[MB_MIDDLE]++;
139         }
140
141         if (Mouse.cyberman && (m_ax & (ME_Z_C|ME_P_C|ME_B_C|ME_H_C)))   {
142                 Mouse.x_info = (event_info *)((msi & 0xFFFF) << 4);
143
144                 if (m_ax & ME_Z_C )     { // z axis changed
145                         if (Mouse.pressed[MB_Z_UP])     {
146                                 // z up released
147                                 Mouse.pressed[MB_Z_UP] = 0;
148                                 Mouse.time_held_down[MB_Z_UP] += Mouse.ctime-Mouse.time_went_down[MB_Z_UP];
149                                 Mouse.num_ups[MB_Z_UP]++;
150                         }  else if ( Mouse.x_info->z>0 )        {
151                                 // z up pressed
152                                 Mouse.pressed[MB_Z_UP] = 1;
153                                 Mouse.time_went_down[MB_Z_UP]=Mouse.ctime;
154                                 Mouse.num_downs[MB_Z_UP]++;
155                         }
156                         if (Mouse.pressed[MB_Z_DOWN])   {
157                                 // z down released
158                                 Mouse.pressed[MB_Z_DOWN] = 0;
159                                 Mouse.time_held_down[MB_Z_DOWN] += Mouse.ctime-Mouse.time_went_down[MB_Z_DOWN];
160                                 Mouse.num_ups[MB_Z_DOWN]++;
161                         }  else if ( Mouse.x_info->z<0 )        {
162                                 // z down pressed
163                                 Mouse.pressed[MB_Z_DOWN] = 1;
164                                 Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime;
165                                 Mouse.num_downs[MB_Z_DOWN]++;
166                         }
167                 }
168                 if (m_ax & ME_P_C )     { // pitch changed
169                         if (Mouse.pressed[MB_PITCH_BACKWARD])   {
170                                 // pitch backward released
171                                 Mouse.pressed[MB_PITCH_BACKWARD] = 0;
172                                 Mouse.time_held_down[MB_PITCH_BACKWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_BACKWARD];
173                                 Mouse.num_ups[MB_PITCH_BACKWARD]++;
174                         }  else if ( Mouse.x_info->pitch>0 )    {
175                                 // pitch backward pressed
176                                 Mouse.pressed[MB_PITCH_BACKWARD] = 1;
177                                 Mouse.time_went_down[MB_PITCH_BACKWARD]=Mouse.ctime;
178                                 Mouse.num_downs[MB_PITCH_BACKWARD]++;
179                         }
180                         if (Mouse.pressed[MB_PITCH_FORWARD])    {
181                                 // pitch forward released
182                                 Mouse.pressed[MB_PITCH_FORWARD] = 0;
183                                 Mouse.time_held_down[MB_PITCH_FORWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_FORWARD];
184                                 Mouse.num_ups[MB_PITCH_FORWARD]++;
185                         }  else if ( Mouse.x_info->pitch<0 )    {
186                                 // pitch forward pressed
187                                 Mouse.pressed[MB_PITCH_FORWARD] = 1;
188                                 Mouse.time_went_down[MB_PITCH_FORWARD]=Mouse.ctime;
189                                 Mouse.num_downs[MB_PITCH_FORWARD]++;
190                         }
191                 }
192
193                 if (m_ax & ME_B_C )     { // bank changed
194                         if (Mouse.pressed[MB_BANK_LEFT])        {
195                                 // bank left released
196                                 Mouse.pressed[MB_BANK_LEFT] = 0;
197                                 Mouse.time_held_down[MB_BANK_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_LEFT];
198                                 Mouse.num_ups[MB_BANK_LEFT]++;
199                         }  else if ( Mouse.x_info->bank>0 )     {
200                                 // bank left pressed
201                                 Mouse.pressed[MB_BANK_LEFT] = 1;
202                                 Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime;
203                                 Mouse.num_downs[MB_BANK_LEFT]++;
204                         }
205                         if (Mouse.pressed[MB_BANK_RIGHT])       {
206                                 // bank right released
207                                 Mouse.pressed[MB_BANK_RIGHT] = 0;
208                                 Mouse.time_held_down[MB_BANK_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_RIGHT];
209                                 Mouse.num_ups[MB_BANK_RIGHT]++;
210                         }  else if ( Mouse.x_info->bank<0 )     {
211                                 // bank right pressed
212                                 Mouse.pressed[MB_BANK_RIGHT] = 1;
213                                 Mouse.time_went_down[MB_BANK_RIGHT]=Mouse.ctime;
214                                 Mouse.num_downs[MB_BANK_RIGHT]++;
215                         }
216                 }
217
218                 if (m_ax & ME_H_C )     { // heading changed
219                         if (Mouse.pressed[MB_HEAD_LEFT])        {
220                                 // head left released
221                                 Mouse.pressed[MB_HEAD_LEFT] = 0;
222                                 Mouse.time_held_down[MB_HEAD_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_LEFT];
223                                 Mouse.num_ups[MB_HEAD_LEFT]++;
224                         }  else if ( Mouse.x_info->heading>0 )  {
225                                 // head left pressed
226                                 Mouse.pressed[MB_HEAD_LEFT] = 1;
227                                 Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime;
228                                 Mouse.num_downs[MB_HEAD_LEFT]++;
229                         }
230                         if (Mouse.pressed[MB_HEAD_RIGHT])       {
231                                 // head right released
232                                 Mouse.pressed[MB_HEAD_RIGHT] = 0;
233                                 Mouse.time_held_down[MB_HEAD_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_RIGHT];
234                                 Mouse.num_ups[MB_HEAD_RIGHT]++;
235                         }  else if ( Mouse.x_info->heading<0 )  {
236                                 // head right pressed
237                                 Mouse.pressed[MB_HEAD_RIGHT] = 1;
238                                 Mouse.time_went_down[MB_HEAD_RIGHT]=Mouse.ctime;
239                                 Mouse.num_downs[MB_HEAD_RIGHT]++;
240                         }
241                 }
242         }
243         
244 }
245
246
247
248
249 void mouse_handler_end (void)  // dummy functions
250 {
251 }
252 #pragma on (check_stack)
253
254 //--------------------------------------------------------
255 // returns 0 if no mouse
256 //           else number of buttons
257 int mouse_init(int enable_cyberman)
258 {
259         dpmi_real_regs rr;
260         cyberman_info *ci;
261         struct SREGS sregs;
262         union REGS inregs, outregs;
263         ubyte *Mouse_dos_mem;
264
265         if (Mouse_installed)
266                 return Mouse.num_buttons;
267
268    if (_dos_getvect(0x33) == NULL) {
269       // No mouse driver loaded
270       return 0;
271    }
272
273         // Reset the mouse driver
274         memset( &inregs, 0, sizeof(inregs) );
275         inregs.w.ax = 0;
276         int386(0x33, &inregs, &outregs);
277         if (outregs.w.ax != 0xffff)
278                 return 0;
279
280         Mouse.num_buttons = outregs.w.bx;
281         Mouse.cyberman = 0;
282
283         // Enable mouse driver
284         memset( &inregs, 0, sizeof(inregs) );
285         inregs.w.ax = 0x0020;
286         int386(0x33, &inregs, &outregs);
287         if (outregs.w.ax != 0xffff )
288                 return 0;
289
290         if ( enable_cyberman )  {
291                 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
292                 if (Mouse_dos_mem==NULL)        {
293                         printf( "Unable to allocate DOS buffer in mouse.c\n" );
294                 } else {
295                         // Check for Cyberman...        
296                         memset( &rr, 0, sizeof(dpmi_real_regs) );
297                         rr.es = DPMI_real_segment(Mouse_dos_mem);
298                         rr.edx = DPMI_real_offset(Mouse_dos_mem);
299                         rr.eax = 0x53c1;
300                         dpmi_real_int386x( 0x33, &rr );
301                         if (rr.eax==1)  {
302                                 // SWIFT functions supported
303                                 ci      = (cyberman_info *)Mouse_dos_mem;
304                                 if (ci->device_type==1) {       // Cyberman     
305                                         Mouse.cyberman = 1;
306                                         //printf( "Cyberman mouse detected\n" );
307                                         Mouse.num_buttons = 11;
308                                 }
309                         }
310                 }
311         }
312
313         if (!dpmi_lock_region(&Mouse,sizeof(mouse_info)))       {
314                 Error( "Unable to lock mouse data region" );
315         }
316         if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler))       {
317                 Error( "Unable to lock mouse handler" );
318         }
319
320         // Install mouse handler
321         memset( &inregs, 0, sizeof(inregs));
322         memset( &sregs, 0, sizeof(sregs));
323         inregs.w.ax     = 0xC;
324         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
325         if (Mouse.cyberman)
326                 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.
327         inregs.x.edx    = FP_OFF(mouse_handler);
328         sregs.es                = FP_SEG(mouse_handler);
329         int386x(0x33, &inregs, &outregs, &sregs);
330
331         Mouse_installed = 1;
332
333         atexit( mouse_close );
334
335         mouse_flush();
336
337         return Mouse.num_buttons;
338 }
339
340
341
342 void mouse_close()
343 {
344         struct SREGS sregs;
345         union REGS inregs, outregs;
346
347         if (Mouse_installed)    {
348                 Mouse_installed = 0;
349                 // clear mouse handler by setting flags to 0.
350                 memset( &inregs, 0, sizeof(inregs));
351                 memset( &sregs, 0, sizeof(sregs));
352                 inregs.w.ax     = 0xC;
353                 inregs.w.cx             = 0;            // disable event handler by setting to zero.
354                 inregs.x.edx    = 0;    
355                 sregs.es       = 0;
356                 int386x(0x33, &inregs, &outregs, &sregs);
357         }
358 }
359
360
361 void mouse_set_limits( int x1, int y1, int x2, int y2 )
362 {
363         union REGS inregs, outregs;
364
365         if (!Mouse_installed) return;
366
367         memset( &inregs, 0, sizeof(inregs));
368         inregs.w.ax = 0x7;      // Set Horizontal Limits for Pointer
369         inregs.w.cx = x1;
370         inregs.w.dx = x2;
371         int386(0x33, &inregs, &outregs);
372
373         memset( &inregs, 0, sizeof(inregs));
374         inregs.w.ax = 0x8;      // Set Vertical Limits for Pointer
375         inregs.w.cx = y1;
376         inregs.w.dx = y2;
377         int386(0x33, &inregs, &outregs);
378 }
379
380 void mouse_get_pos( int *x, int *y)
381 {
382         union REGS inregs, outregs;
383
384         if (!Mouse_installed) {
385                 *x = *y = 0;
386                 return;
387         }
388         memset( &inregs, 0, sizeof(inregs));
389         inregs.w.ax = 0x3;      // Get Mouse Position and Button Status
390         int386(0x33, &inregs, &outregs);
391         *x = (short)outregs.w.cx; 
392         *y = (short)outregs.w.dx; 
393 }
394
395 void mouse_get_delta( int *dx, int *dy )
396 {
397         union REGS inregs, outregs;
398
399         if (!Mouse_installed) {
400                 *dx = *dy = 0;
401                 return;
402         }
403
404         memset( &inregs, 0, sizeof(inregs));
405         inregs.w.ax = 0xb;      // Read Mouse motion counters
406         int386(0x33, &inregs, &outregs);
407         *dx = (short)outregs.w.cx; 
408         *dy = (short)outregs.w.dx; 
409 }
410
411 int mouse_get_btns()
412 {
413         int i;
414         uint flag=1;
415         int status = 0;
416
417         if (!Mouse_installed) 
418                 return 0;
419
420         for (i=0; i<MOUSE_MAX_BUTTONS; i++ )    {
421                 if (Mouse.pressed[i])
422                         status |= flag;
423                 flag <<= 1;
424         }
425         return status;
426 }
427
428 void mouse_set_pos( int x, int y)
429 {
430         union REGS inregs, outregs;
431
432         if (!Mouse_installed) 
433                 return;
434
435         memset( &inregs, 0, sizeof(inregs));
436         inregs.w.ax = 0x4;      // Set Mouse Pointer Position
437         inregs.w.cx = x;
438         inregs.w.dx = y;
439         int386(0x33, &inregs, &outregs);
440
441 }
442
443 void mouse_flush()
444 {
445         int i;
446         fix CurTime;
447
448         if (!Mouse_installed) 
449                 return;
450
451         _disable();
452
453         //Clear the mouse data
454         CurTime =timer_get_fixed_secondsX();
455         for (i=0; i<MOUSE_MAX_BUTTONS; i++ )    {
456                 Mouse.pressed[i] = 0;
457                 Mouse.time_went_down[i] = CurTime;
458                 Mouse.time_held_down[i] = 0;
459                 Mouse.num_downs[i]=0;
460                 Mouse.num_ups[i]=0;
461         }
462         _enable();
463 }
464
465
466 // Returns how many times this button has went down since last call.
467 int mouse_button_down_count(int button) 
468 {
469         int count;
470
471         if (!Mouse_installed) 
472                 return 0;
473
474         _disable();
475
476         count = Mouse.num_downs[button];
477         Mouse.num_downs[button]=0;
478
479         _enable();
480
481         return count;
482 }
483
484 // Returns 1 if this button is currently down
485 int mouse_button_state(int button)      
486 {
487         int state;
488
489         if (!Mouse_installed) 
490                 return 0;
491
492         _disable();
493
494         state = Mouse.pressed[button];
495
496         _enable();
497
498         return state;
499 }
500
501
502
503 // Returns how long this button has been down since last call.
504 fix mouse_button_down_time(int button)  
505 {
506         fix time_down, time;
507
508         if (!Mouse_installed) 
509                 return 0;
510
511         _disable();
512
513         if ( !Mouse.pressed[button] )   {
514                 time_down = Mouse.time_held_down[button];
515                 Mouse.time_held_down[button] = 0;
516         } else  {
517                 time = timer_get_fixed_secondsX();
518                 time_down =  time - Mouse.time_went_down[button];
519                 Mouse.time_went_down[button] = time;
520         }
521
522         _enable();
523
524         return time_down;
525 }
526
527 void mouse_get_cyberman_pos( int *x, int *y )
528 {
529         dpmi_real_regs rr;
530         event_info * ei;
531         ubyte *Mouse_dos_mem;
532
533         if ( (!Mouse_installed) || (!Mouse.cyberman) ) {
534                 *x = *y = 0;
535                 return;
536         }
537
538         Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
539
540         if ( !Mouse_dos_mem )   {
541                 *x = *y = 0;
542                 return;
543         }
544
545
546         memset( &rr, 0, sizeof(dpmi_real_regs) );
547         rr.es = DPMI_real_segment(Mouse_dos_mem);
548         rr.edx = DPMI_real_offset(Mouse_dos_mem);
549         rr.eax = 0x5301;
550         dpmi_real_int386x( 0x33, &rr );
551
552         ei = (event_info *)Mouse_dos_mem;
553
554         *x = (((ei->x+8128)*256)/(8064+8128+1)) - 127;
555         *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127;
556
557 }
558