1 /* $Id: mouse.c,v 1.5 2004-08-28 23:17:45 schaffner Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Functions to access Mouse and Cyberman...
27 #define _BORLAND_DOS_REGS 1
29 _go32_dpmi_registers handler_regs;
47 #define ME_CURSOR_MOVED (1<<0)
48 #define ME_LB_P (1<<1)
49 #define ME_LB_R (1<<2)
50 #define ME_RB_P (1<<3)
51 #define ME_RB_R (1<<4)
52 #define ME_MB_P (1<<5)
53 #define ME_MB_R (1<<6)
54 #define ME_OB_P (1<<7)
55 #define ME_OB_R (1<<8)
57 #define ME_Y_C (1<<10)
58 #define ME_Z_C (1<<11)
59 #define ME_P_C (1<<12)
60 #define ME_B_C (1<<13)
61 #define ME_H_C (1<<14)
62 #define ME_O_C (1<<15)
64 #define MOUSE_MAX_BUTTONS 11
66 typedef struct event_info {
74 ushort device_dependant;
77 typedef struct mouse_info {
81 ubyte pressed[MOUSE_MAX_BUTTONS];
82 fix time_went_down[MOUSE_MAX_BUTTONS];
83 fix time_held_down[MOUSE_MAX_BUTTONS];
84 uint num_downs[MOUSE_MAX_BUTTONS];
85 uint num_ups[MOUSE_MAX_BUTTONS];
90 typedef struct cyberman_info {
97 ubyte pitch_descriptor;
98 ubyte roll_descriptor;
103 static mouse_info Mouse;
105 static int Mouse_installed = 0;
108 #define m_ax r->d.eax
114 void mouse_handler (_go32_dpmi_registers *r)
117 #pragma off (check_stack)
118 void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi)
120 #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
122 Mouse.ctime = timer_get_fixed_secondsX();
124 if (m_ax & ME_LB_P) { // left button pressed
125 if (!Mouse.pressed[MB_LEFT]) {
126 Mouse.pressed[MB_LEFT] = 1;
127 Mouse.time_went_down[MB_LEFT] = Mouse.ctime;
129 Mouse.num_downs[MB_LEFT]++;
130 } else if (m_ax & ME_LB_R ) { // left button released
131 if (Mouse.pressed[MB_LEFT]) {
132 Mouse.pressed[MB_LEFT] = 0;
133 Mouse.time_held_down[MB_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_LEFT];
135 Mouse.num_ups[MB_LEFT]++;
138 if (m_ax & ME_RB_P ) { // right button pressed
139 if (!Mouse.pressed[MB_RIGHT]) {
140 Mouse.pressed[MB_RIGHT] = 1;
141 Mouse.time_went_down[MB_RIGHT] = Mouse.ctime;
143 Mouse.num_downs[MB_RIGHT]++;
144 } else if (m_ax & ME_RB_R ) {// right button released
145 if (Mouse.pressed[MB_RIGHT]) {
146 Mouse.pressed[MB_RIGHT] = 0;
147 Mouse.time_held_down[MB_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_RIGHT];
149 Mouse.num_ups[MB_RIGHT]++;
152 if (m_ax & ME_MB_P ) { // middle button pressed
153 if (!Mouse.pressed[MB_MIDDLE]) {
154 Mouse.pressed[MB_MIDDLE] = 1;
155 Mouse.time_went_down[MB_MIDDLE] = Mouse.ctime;
157 Mouse.num_downs[MB_MIDDLE]++;
158 } else if (m_ax & ME_MB_R ) { // middle button released
159 if (Mouse.pressed[MB_MIDDLE]) {
160 Mouse.pressed[MB_MIDDLE] = 0;
161 Mouse.time_held_down[MB_MIDDLE] += Mouse.ctime-Mouse.time_went_down[MB_MIDDLE];
163 Mouse.num_ups[MB_MIDDLE]++;
166 if (Mouse.cyberman && (m_ax & (ME_Z_C|ME_P_C|ME_B_C|ME_H_C))) {
167 Mouse.x_info = (event_info *)((msi & 0xFFFF) << 4);
169 if (m_ax & ME_Z_C ) { // z axis changed
170 if (Mouse.pressed[MB_Z_UP]) {
172 Mouse.pressed[MB_Z_UP] = 0;
173 Mouse.time_held_down[MB_Z_UP] += Mouse.ctime-Mouse.time_went_down[MB_Z_UP];
174 Mouse.num_ups[MB_Z_UP]++;
175 } else if ( Mouse.x_info->z>0 ) {
177 Mouse.pressed[MB_Z_UP] = 1;
178 Mouse.time_went_down[MB_Z_UP]=Mouse.ctime;
179 Mouse.num_downs[MB_Z_UP]++;
181 if (Mouse.pressed[MB_Z_DOWN]) {
183 Mouse.pressed[MB_Z_DOWN] = 0;
184 Mouse.time_held_down[MB_Z_DOWN] += Mouse.ctime-Mouse.time_went_down[MB_Z_DOWN];
185 Mouse.num_ups[MB_Z_DOWN]++;
186 } else if ( Mouse.x_info->z<0 ) {
188 Mouse.pressed[MB_Z_DOWN] = 1;
189 Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime;
190 Mouse.num_downs[MB_Z_DOWN]++;
193 if (m_ax & ME_P_C ) { // pitch changed
194 if (Mouse.pressed[MB_PITCH_BACKWARD]) {
195 // pitch backward released
196 Mouse.pressed[MB_PITCH_BACKWARD] = 0;
197 Mouse.time_held_down[MB_PITCH_BACKWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_BACKWARD];
198 Mouse.num_ups[MB_PITCH_BACKWARD]++;
199 } else if ( Mouse.x_info->pitch>0 ) {
200 // pitch backward pressed
201 Mouse.pressed[MB_PITCH_BACKWARD] = 1;
202 Mouse.time_went_down[MB_PITCH_BACKWARD]=Mouse.ctime;
203 Mouse.num_downs[MB_PITCH_BACKWARD]++;
205 if (Mouse.pressed[MB_PITCH_FORWARD]) {
206 // pitch forward released
207 Mouse.pressed[MB_PITCH_FORWARD] = 0;
208 Mouse.time_held_down[MB_PITCH_FORWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_FORWARD];
209 Mouse.num_ups[MB_PITCH_FORWARD]++;
210 } else if ( Mouse.x_info->pitch<0 ) {
211 // pitch forward pressed
212 Mouse.pressed[MB_PITCH_FORWARD] = 1;
213 Mouse.time_went_down[MB_PITCH_FORWARD]=Mouse.ctime;
214 Mouse.num_downs[MB_PITCH_FORWARD]++;
218 if (m_ax & ME_B_C ) { // bank changed
219 if (Mouse.pressed[MB_BANK_LEFT]) {
220 // bank left released
221 Mouse.pressed[MB_BANK_LEFT] = 0;
222 Mouse.time_held_down[MB_BANK_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_LEFT];
223 Mouse.num_ups[MB_BANK_LEFT]++;
224 } else if ( Mouse.x_info->bank>0 ) {
226 Mouse.pressed[MB_BANK_LEFT] = 1;
227 Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime;
228 Mouse.num_downs[MB_BANK_LEFT]++;
230 if (Mouse.pressed[MB_BANK_RIGHT]) {
231 // bank right released
232 Mouse.pressed[MB_BANK_RIGHT] = 0;
233 Mouse.time_held_down[MB_BANK_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_RIGHT];
234 Mouse.num_ups[MB_BANK_RIGHT]++;
235 } else if ( Mouse.x_info->bank<0 ) {
236 // bank right pressed
237 Mouse.pressed[MB_BANK_RIGHT] = 1;
238 Mouse.time_went_down[MB_BANK_RIGHT]=Mouse.ctime;
239 Mouse.num_downs[MB_BANK_RIGHT]++;
243 if (m_ax & ME_H_C ) { // heading changed
244 if (Mouse.pressed[MB_HEAD_LEFT]) {
245 // head left released
246 Mouse.pressed[MB_HEAD_LEFT] = 0;
247 Mouse.time_held_down[MB_HEAD_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_LEFT];
248 Mouse.num_ups[MB_HEAD_LEFT]++;
249 } else if ( Mouse.x_info->heading>0 ) {
251 Mouse.pressed[MB_HEAD_LEFT] = 1;
252 Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime;
253 Mouse.num_downs[MB_HEAD_LEFT]++;
255 if (Mouse.pressed[MB_HEAD_RIGHT]) {
256 // head right released
257 Mouse.pressed[MB_HEAD_RIGHT] = 0;
258 Mouse.time_held_down[MB_HEAD_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_RIGHT];
259 Mouse.num_ups[MB_HEAD_RIGHT]++;
260 } else if ( Mouse.x_info->heading<0 ) {
261 // head right pressed
262 Mouse.pressed[MB_HEAD_RIGHT] = 1;
263 Mouse.time_went_down[MB_HEAD_RIGHT]=Mouse.ctime;
264 Mouse.num_downs[MB_HEAD_RIGHT]++;
274 void mouse_handler_end (void) // dummy functions
278 #pragma on (check_stack)
281 //--------------------------------------------------------
282 // returns 0 if no mouse
283 // else number of buttons
284 int mouse_init(int enable_cyberman)
291 union REGS inregs, outregs;
292 ubyte *Mouse_dos_mem;
295 return Mouse.num_buttons;
298 if (_farpeekl(_dos_ds, 0x33 * 4) == 0) {
300 if (_dos_getvect(0x33) == NULL) {
302 // added on 1/13/2000 by Victor Rachels for more info
303 con_printf(CON_NORMAL, "\nNo mouse driver found!\n");
304 // end this section addition - VR
305 // No mouse driver loaded
309 // Reset the mouse driver
310 memset( &inregs, 0, sizeof(inregs) );
312 int386(0x33, &inregs, &outregs);
313 if (outregs.w.ax != 0xffff)
315 // added on 1/13/2000 by Victor Rachels for more info
316 con_printf(CON_NORMAL, "\nUnable to reset mouse!\n");
317 // end this section edit - VR
322 Mouse.num_buttons = outregs.w.bx;
325 // Enable mouse driver
326 // added/edited on 1/15/2000 by Victor Rachels to make this optional - can usually be used w or w/o this reset
327 if(!FindArg("-ihaveabrokenmouse"))
329 memset(&inregs, 0, sizeof(inregs));
330 inregs.w.ax = 0x0020;
331 int386(0x33, &inregs, &outregs);
332 if (outregs.w.ax != 0xffff)
334 // added on 1/13/2000 by Victor Rachels for more info
335 con_printf(CON_NORMAL, "\nUnable to enable mouse! (%x)\n", outregs.w.ax);
336 // end this section edit - VR
340 // end this section edit/addition - VR
342 if ( enable_cyberman ) {
343 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
344 if (Mouse_dos_mem==NULL) {
345 printf( "Unable to allocate DOS buffer in mouse.c\n" );
347 // Check for Cyberman...
348 memset( &rr, 0, sizeof(dpmi_real_regs) );
349 rr.es = DPMI_real_segment(Mouse_dos_mem);
350 rr.edx = DPMI_real_offset(Mouse_dos_mem);
352 dpmi_real_int386x( 0x33, &rr );
354 // SWIFT functions supported
355 ci = (cyberman_info *)Mouse_dos_mem;
356 if (ci->device_type==1) { // Cyberman
358 //printf( "Cyberman mouse detected\n" );
359 Mouse.num_buttons = 11;
365 if (!dpmi_lock_region(&Mouse,sizeof(mouse_info))) {
366 printf( "Unable to lock mouse data region" );
369 if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler)) {
370 printf( "Unable to lock mouse handler" );
374 // Install mouse handler
377 dpmi_real_regs rregs;
378 _go32_dpmi_seginfo info;
379 memset(&rregs, 0, sizeof(rregs));
380 info.pm_offset = (unsigned int)&mouse_handler;
381 if (_go32_dpmi_allocate_real_mode_callback_retf(&info, &handler_regs)) {
382 printf( "Unable allocate mouse handler callback" );
386 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
388 rregs.ecx |= ME_Z_C| ME_P_C| ME_B_C| ME_H_C; // if using a cyberman, also watch z, pitch, bank, heading.
389 rregs.edx = info.rm_offset;
390 rregs.es = info.rm_segment;
391 dpmi_real_int386x( 0x33, &rregs );
394 memset( &inregs, 0, sizeof(inregs));
395 memset( &sregs, 0, sizeof(sregs));
397 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
399 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.
400 inregs.x.edx = FP_OFF(mouse_handler);
401 sregs.es = FP_SEG(mouse_handler);
402 int386x(0x33, &inregs, &outregs, &sregs);
407 atexit( mouse_close );
411 return Mouse.num_buttons;
419 union REGS inregs, outregs;
421 if (Mouse_installed) {
423 // clear mouse handler by setting flags to 0.
424 memset( &inregs, 0, sizeof(inregs));
425 memset( &sregs, 0, sizeof(sregs));
427 inregs.w.cx = 0; // disable event handler by setting to zero.
430 int386x(0x33, &inregs, &outregs, &sregs);
435 void mouse_set_limits( int x1, int y1, int x2, int y2 )
437 union REGS inregs, outregs;
439 if (!Mouse_installed) return;
441 memset( &inregs, 0, sizeof(inregs));
442 inregs.w.ax = 0x7; // Set Horizontal Limits for Pointer
445 int386(0x33, &inregs, &outregs);
447 memset( &inregs, 0, sizeof(inregs));
448 inregs.w.ax = 0x8; // Set Vertical Limits for Pointer
451 int386(0x33, &inregs, &outregs);
454 void mouse_get_pos( int *x, int *y)
456 union REGS inregs, outregs;
458 if (!Mouse_installed) {
462 memset( &inregs, 0, sizeof(inregs));
463 inregs.w.ax = 0x3; // Get Mouse Position and Button Status
464 int386(0x33, &inregs, &outregs);
465 *x = (short)outregs.w.cx;
466 *y = (short)outregs.w.dx;
469 void mouse_get_delta( int *dx, int *dy )
471 union REGS inregs, outregs;
473 if (!Mouse_installed) {
478 memset( &inregs, 0, sizeof(inregs));
479 inregs.w.ax = 0xb; // Read Mouse motion counters
480 int386(0x33, &inregs, &outregs);
481 *dx = (short)outregs.w.cx;
482 *dy = (short)outregs.w.dx;
491 if (!Mouse_installed)
494 for (i=0; i<MOUSE_MAX_BUTTONS; i++ ) {
495 if (Mouse.pressed[i])
502 void mouse_set_pos( int x, int y)
504 union REGS inregs, outregs;
506 if (!Mouse_installed)
509 memset( &inregs, 0, sizeof(inregs));
510 inregs.w.ax = 0x4; // Set Mouse Pointer Position
513 int386(0x33, &inregs, &outregs);
522 if (!Mouse_installed)
527 //Clear the mouse data
528 CurTime =timer_get_fixed_secondsX();
529 for (i=0; i<MOUSE_MAX_BUTTONS; i++ ) {
530 Mouse.pressed[i] = 0;
531 Mouse.time_went_down[i] = CurTime;
532 Mouse.time_held_down[i] = 0;
533 Mouse.num_downs[i]=0;
540 // Returns how many times this button has went down since last call.
541 int mouse_button_down_count(int button)
545 if (!Mouse_installed)
550 count = Mouse.num_downs[button];
551 Mouse.num_downs[button]=0;
558 // Returns 1 if this button is currently down
559 int mouse_button_state(int button)
563 if (!Mouse_installed)
568 state = Mouse.pressed[button];
577 // Returns how long this button has been down since last call.
578 fix mouse_button_down_time(int button)
582 if (!Mouse_installed)
587 if ( !Mouse.pressed[button] ) {
588 time_down = Mouse.time_held_down[button];
589 Mouse.time_held_down[button] = 0;
591 time = timer_get_fixed_secondsX();
592 time_down = time - Mouse.time_went_down[button];
593 Mouse.time_went_down[button] = time;
601 void mouse_get_cyberman_pos( int *x, int *y )
605 ubyte *Mouse_dos_mem;
607 if ( (!Mouse_installed) || (!Mouse.cyberman) ) {
612 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
614 if ( !Mouse_dos_mem ) {
620 memset( &rr, 0, sizeof(dpmi_real_regs) );
621 rr.es = DPMI_real_segment(Mouse_dos_mem);
622 rr.edx = DPMI_real_offset(Mouse_dos_mem);
624 dpmi_real_int386x( 0x33, &rr );
626 ei = (event_info *)Mouse_dos_mem;
628 *x = (((ei->x+8128)*256)/(8064+8128+1)) - 127;
629 *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127;