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