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.
15 * $Source: /cvs/cvsroot/d2x/arch/dos/mouse.c,v $
18 * $Date: 2001-10-24 09:25:05 $
20 * Functions to access Mouse and Cyberman...
22 * $Log: not supported by cvs2svn $
23 * Revision 1.3 2001/01/31 14:04:44 bradleyb
24 * Fix compiler warnings
26 * Revision 1.2 2001/01/29 14:03:57 bradleyb
27 * Fixed build, minor fixes
29 * Revision 1.1.1.2 2001/01/19 03:33:52 bradleyb
30 * Import of d2x-0.0.9-pre1
32 * Revision 1.1.1.1 1999/06/14 21:58:38 donut
33 * Import of d1x 1.37 source.
35 * Revision 1.11 1995/02/10 18:52:17 john
36 * Fixed bug with mouse not getting closed.
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.
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
46 * Revision 1.8 1994/12/27 12:38:23 john
47 * Made mouse use temporary dos buffer instead of
52 * Revision 1.7 1994/12/05 23:54:53 john
53 * Fixed bug with mouse_get_delta only returning positive numbers..
55 * Revision 1.6 1994/11/18 23:18:18 john
56 * Changed some shorts to ints.
58 * Revision 1.5 1994/09/13 12:34:02 john
59 * Added functions to get down count and state.
61 * Revision 1.4 1994/08/29 20:52:19 john
62 * Added better cyberman support; also, joystick calibration
63 * value return funcctiionn,
65 * Revision 1.3 1994/08/24 18:54:32 john
66 * *** empty log message ***
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.
72 * Revision 1.1 1994/08/24 13:56:37 john
84 #define _BORLAND_DOS_REGS 1
86 _go32_dpmi_registers handler_regs;
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)
121 #define MOUSE_MAX_BUTTONS 11
123 typedef struct event_info {
130 ushort button_status;
131 ushort device_dependant;
134 typedef struct mouse_info {
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];
144 ushort button_status;
147 typedef struct cyberman_info {
154 ubyte pitch_descriptor;
155 ubyte roll_descriptor;
156 ubyte yaw_descriptor;
160 static mouse_info Mouse;
162 static int Mouse_installed = 0;
165 #define m_ax r->d.eax
171 void mouse_handler (_go32_dpmi_registers *r)
174 #pragma off (check_stack)
175 void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi)
177 #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
179 Mouse.ctime = timer_get_fixed_secondsX();
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;
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];
192 Mouse.num_ups[MB_LEFT]++;
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;
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];
206 Mouse.num_ups[MB_RIGHT]++;
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;
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];
220 Mouse.num_ups[MB_MIDDLE]++;
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);
226 if (m_ax & ME_Z_C ) { // z axis changed
227 if (Mouse.pressed[MB_Z_UP]) {
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 ) {
234 Mouse.pressed[MB_Z_UP] = 1;
235 Mouse.time_went_down[MB_Z_UP]=Mouse.ctime;
236 Mouse.num_downs[MB_Z_UP]++;
238 if (Mouse.pressed[MB_Z_DOWN]) {
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 ) {
245 Mouse.pressed[MB_Z_DOWN] = 1;
246 Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime;
247 Mouse.num_downs[MB_Z_DOWN]++;
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]++;
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]++;
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 ) {
283 Mouse.pressed[MB_BANK_LEFT] = 1;
284 Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime;
285 Mouse.num_downs[MB_BANK_LEFT]++;
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]++;
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 ) {
308 Mouse.pressed[MB_HEAD_LEFT] = 1;
309 Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime;
310 Mouse.num_downs[MB_HEAD_LEFT]++;
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]++;
331 void mouse_handler_end (void) // dummy functions
335 #pragma on (check_stack)
338 //--------------------------------------------------------
339 // returns 0 if no mouse
340 // else number of buttons
341 int mouse_init(int enable_cyberman)
348 union REGS inregs, outregs;
349 ubyte *Mouse_dos_mem;
352 return Mouse.num_buttons;
355 if (_farpeekl(_dos_ds, 0x33 * 4) == 0) {
357 if (_dos_getvect(0x33) == NULL) {
359 // No mouse driver loaded
363 // Reset the mouse driver
364 memset( &inregs, 0, sizeof(inregs) );
366 int386(0x33, &inregs, &outregs);
367 if (outregs.w.ax != 0xffff)
370 Mouse.num_buttons = outregs.w.bx;
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 )
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" );
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);
390 dpmi_real_int386x( 0x33, &rr );
392 // SWIFT functions supported
393 ci = (cyberman_info *)Mouse_dos_mem;
394 if (ci->device_type==1) { // Cyberman
396 //printf( "Cyberman mouse detected\n" );
397 Mouse.num_buttons = 11;
403 if (!dpmi_lock_region(&Mouse,sizeof(mouse_info))) {
404 printf( "Unable to lock mouse data region" );
407 if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler)) {
408 printf( "Unable to lock mouse handler" );
412 // Install mouse handler
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" );
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
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 );
432 memset( &inregs, 0, sizeof(inregs));
433 memset( &sregs, 0, sizeof(sregs));
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
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);
445 atexit( mouse_close );
449 return Mouse.num_buttons;
457 union REGS inregs, outregs;
459 if (Mouse_installed) {
461 // clear mouse handler by setting flags to 0.
462 memset( &inregs, 0, sizeof(inregs));
463 memset( &sregs, 0, sizeof(sregs));
465 inregs.w.cx = 0; // disable event handler by setting to zero.
468 int386x(0x33, &inregs, &outregs, &sregs);
473 void mouse_set_limits( int x1, int y1, int x2, int y2 )
475 union REGS inregs, outregs;
477 if (!Mouse_installed) return;
479 memset( &inregs, 0, sizeof(inregs));
480 inregs.w.ax = 0x7; // Set Horizontal Limits for Pointer
483 int386(0x33, &inregs, &outregs);
485 memset( &inregs, 0, sizeof(inregs));
486 inregs.w.ax = 0x8; // Set Vertical Limits for Pointer
489 int386(0x33, &inregs, &outregs);
492 void mouse_get_pos( int *x, int *y)
494 union REGS inregs, outregs;
496 if (!Mouse_installed) {
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;
507 void mouse_get_delta( int *dx, int *dy )
509 union REGS inregs, outregs;
511 if (!Mouse_installed) {
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;
529 if (!Mouse_installed)
532 for (i=0; i<MOUSE_MAX_BUTTONS; i++ ) {
533 if (Mouse.pressed[i])
540 void mouse_set_pos( int x, int y)
542 union REGS inregs, outregs;
544 if (!Mouse_installed)
547 memset( &inregs, 0, sizeof(inregs));
548 inregs.w.ax = 0x4; // Set Mouse Pointer Position
551 int386(0x33, &inregs, &outregs);
560 if (!Mouse_installed)
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;
578 // Returns how many times this button has went down since last call.
579 int mouse_button_down_count(int button)
583 if (!Mouse_installed)
588 count = Mouse.num_downs[button];
589 Mouse.num_downs[button]=0;
596 // Returns 1 if this button is currently down
597 int mouse_button_state(int button)
601 if (!Mouse_installed)
606 state = Mouse.pressed[button];
615 // Returns how long this button has been down since last call.
616 fix mouse_button_down_time(int button)
620 if (!Mouse_installed)
625 if ( !Mouse.pressed[button] ) {
626 time_down = Mouse.time_held_down[button];
627 Mouse.time_held_down[button] = 0;
629 time = timer_get_fixed_secondsX();
630 time_down = time - Mouse.time_went_down[button];
631 Mouse.time_went_down[button] = time;
639 void mouse_get_cyberman_pos( int *x, int *y )
643 ubyte *Mouse_dos_mem;
645 if ( (!Mouse_installed) || (!Mouse.cyberman) ) {
650 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
652 if ( !Mouse_dos_mem ) {
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);
662 dpmi_real_int386x( 0x33, &rr );
664 ei = (event_info *)Mouse_dos_mem;
666 *x = (((ei->x+8128)*256)/(8064+8128+1)) - 127;
667 *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127;