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.
20 #define _BORLAND_DOS_REGS 1
22 _go32_dpmi_registers handler_regs;
40 #define ME_CURSOR_MOVED (1<<0)
41 #define ME_LB_P (1<<1)
42 #define ME_LB_R (1<<2)
43 #define ME_RB_P (1<<3)
44 #define ME_RB_R (1<<4)
45 #define ME_MB_P (1<<5)
46 #define ME_MB_R (1<<6)
47 #define ME_OB_P (1<<7)
48 #define ME_OB_R (1<<8)
50 #define ME_Y_C (1<<10)
51 #define ME_Z_C (1<<11)
52 #define ME_P_C (1<<12)
53 #define ME_B_C (1<<13)
54 #define ME_H_C (1<<14)
55 #define ME_O_C (1<<15)
57 #define MOUSE_MAX_BUTTONS 11
59 typedef struct event_info {
67 ushort device_dependant;
70 typedef struct mouse_info {
74 ubyte pressed[MOUSE_MAX_BUTTONS];
75 fix time_went_down[MOUSE_MAX_BUTTONS];
76 fix time_held_down[MOUSE_MAX_BUTTONS];
77 uint num_downs[MOUSE_MAX_BUTTONS];
78 uint num_ups[MOUSE_MAX_BUTTONS];
83 typedef struct cyberman_info {
90 ubyte pitch_descriptor;
91 ubyte roll_descriptor;
96 static mouse_info Mouse;
98 static int Mouse_installed = 0;
101 #define m_ax r->d.eax
107 void mouse_handler (_go32_dpmi_registers *r)
110 #pragma off (check_stack)
111 void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi)
113 #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
115 Mouse.ctime = timer_get_fixed_secondsX();
117 if (m_ax & ME_LB_P) { // left button pressed
118 if (!Mouse.pressed[MB_LEFT]) {
119 Mouse.pressed[MB_LEFT] = 1;
120 Mouse.time_went_down[MB_LEFT] = Mouse.ctime;
122 Mouse.num_downs[MB_LEFT]++;
123 } else if (m_ax & ME_LB_R ) { // left button released
124 if (Mouse.pressed[MB_LEFT]) {
125 Mouse.pressed[MB_LEFT] = 0;
126 Mouse.time_held_down[MB_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_LEFT];
128 Mouse.num_ups[MB_LEFT]++;
131 if (m_ax & ME_RB_P ) { // right button pressed
132 if (!Mouse.pressed[MB_RIGHT]) {
133 Mouse.pressed[MB_RIGHT] = 1;
134 Mouse.time_went_down[MB_RIGHT] = Mouse.ctime;
136 Mouse.num_downs[MB_RIGHT]++;
137 } else if (m_ax & ME_RB_R ) {// right button released
138 if (Mouse.pressed[MB_RIGHT]) {
139 Mouse.pressed[MB_RIGHT] = 0;
140 Mouse.time_held_down[MB_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_RIGHT];
142 Mouse.num_ups[MB_RIGHT]++;
145 if (m_ax & ME_MB_P ) { // middle button pressed
146 if (!Mouse.pressed[MB_MIDDLE]) {
147 Mouse.pressed[MB_MIDDLE] = 1;
148 Mouse.time_went_down[MB_MIDDLE] = Mouse.ctime;
150 Mouse.num_downs[MB_MIDDLE]++;
151 } else if (m_ax & ME_MB_R ) { // middle button released
152 if (Mouse.pressed[MB_MIDDLE]) {
153 Mouse.pressed[MB_MIDDLE] = 0;
154 Mouse.time_held_down[MB_MIDDLE] += Mouse.ctime-Mouse.time_went_down[MB_MIDDLE];
156 Mouse.num_ups[MB_MIDDLE]++;
159 if (Mouse.cyberman && (m_ax & (ME_Z_C|ME_P_C|ME_B_C|ME_H_C))) {
160 Mouse.x_info = (event_info *)((msi & 0xFFFF) << 4);
162 if (m_ax & ME_Z_C ) { // z axis changed
163 if (Mouse.pressed[MB_Z_UP]) {
165 Mouse.pressed[MB_Z_UP] = 0;
166 Mouse.time_held_down[MB_Z_UP] += Mouse.ctime-Mouse.time_went_down[MB_Z_UP];
167 Mouse.num_ups[MB_Z_UP]++;
168 } else if ( Mouse.x_info->z>0 ) {
170 Mouse.pressed[MB_Z_UP] = 1;
171 Mouse.time_went_down[MB_Z_UP]=Mouse.ctime;
172 Mouse.num_downs[MB_Z_UP]++;
174 if (Mouse.pressed[MB_Z_DOWN]) {
176 Mouse.pressed[MB_Z_DOWN] = 0;
177 Mouse.time_held_down[MB_Z_DOWN] += Mouse.ctime-Mouse.time_went_down[MB_Z_DOWN];
178 Mouse.num_ups[MB_Z_DOWN]++;
179 } else if ( Mouse.x_info->z<0 ) {
181 Mouse.pressed[MB_Z_DOWN] = 1;
182 Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime;
183 Mouse.num_downs[MB_Z_DOWN]++;
186 if (m_ax & ME_P_C ) { // pitch changed
187 if (Mouse.pressed[MB_PITCH_BACKWARD]) {
188 // pitch backward released
189 Mouse.pressed[MB_PITCH_BACKWARD] = 0;
190 Mouse.time_held_down[MB_PITCH_BACKWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_BACKWARD];
191 Mouse.num_ups[MB_PITCH_BACKWARD]++;
192 } else if ( Mouse.x_info->pitch>0 ) {
193 // pitch backward pressed
194 Mouse.pressed[MB_PITCH_BACKWARD] = 1;
195 Mouse.time_went_down[MB_PITCH_BACKWARD]=Mouse.ctime;
196 Mouse.num_downs[MB_PITCH_BACKWARD]++;
198 if (Mouse.pressed[MB_PITCH_FORWARD]) {
199 // pitch forward released
200 Mouse.pressed[MB_PITCH_FORWARD] = 0;
201 Mouse.time_held_down[MB_PITCH_FORWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_FORWARD];
202 Mouse.num_ups[MB_PITCH_FORWARD]++;
203 } else if ( Mouse.x_info->pitch<0 ) {
204 // pitch forward pressed
205 Mouse.pressed[MB_PITCH_FORWARD] = 1;
206 Mouse.time_went_down[MB_PITCH_FORWARD]=Mouse.ctime;
207 Mouse.num_downs[MB_PITCH_FORWARD]++;
211 if (m_ax & ME_B_C ) { // bank changed
212 if (Mouse.pressed[MB_BANK_LEFT]) {
213 // bank left released
214 Mouse.pressed[MB_BANK_LEFT] = 0;
215 Mouse.time_held_down[MB_BANK_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_LEFT];
216 Mouse.num_ups[MB_BANK_LEFT]++;
217 } else if ( Mouse.x_info->bank>0 ) {
219 Mouse.pressed[MB_BANK_LEFT] = 1;
220 Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime;
221 Mouse.num_downs[MB_BANK_LEFT]++;
223 if (Mouse.pressed[MB_BANK_RIGHT]) {
224 // bank right released
225 Mouse.pressed[MB_BANK_RIGHT] = 0;
226 Mouse.time_held_down[MB_BANK_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_RIGHT];
227 Mouse.num_ups[MB_BANK_RIGHT]++;
228 } else if ( Mouse.x_info->bank<0 ) {
229 // bank right pressed
230 Mouse.pressed[MB_BANK_RIGHT] = 1;
231 Mouse.time_went_down[MB_BANK_RIGHT]=Mouse.ctime;
232 Mouse.num_downs[MB_BANK_RIGHT]++;
236 if (m_ax & ME_H_C ) { // heading changed
237 if (Mouse.pressed[MB_HEAD_LEFT]) {
238 // head left released
239 Mouse.pressed[MB_HEAD_LEFT] = 0;
240 Mouse.time_held_down[MB_HEAD_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_LEFT];
241 Mouse.num_ups[MB_HEAD_LEFT]++;
242 } else if ( Mouse.x_info->heading>0 ) {
244 Mouse.pressed[MB_HEAD_LEFT] = 1;
245 Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime;
246 Mouse.num_downs[MB_HEAD_LEFT]++;
248 if (Mouse.pressed[MB_HEAD_RIGHT]) {
249 // head right released
250 Mouse.pressed[MB_HEAD_RIGHT] = 0;
251 Mouse.time_held_down[MB_HEAD_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_RIGHT];
252 Mouse.num_ups[MB_HEAD_RIGHT]++;
253 } else if ( Mouse.x_info->heading<0 ) {
254 // head right pressed
255 Mouse.pressed[MB_HEAD_RIGHT] = 1;
256 Mouse.time_went_down[MB_HEAD_RIGHT]=Mouse.ctime;
257 Mouse.num_downs[MB_HEAD_RIGHT]++;
267 void mouse_handler_end (void) // dummy functions
270 #pragma on (check_stack)
272 //--------------------------------------------------------
273 // returns 0 if no mouse
274 // else number of buttons
275 int mouse_init(int enable_cyberman)
282 union REGS inregs, outregs;
283 ubyte *Mouse_dos_mem;
286 return Mouse.num_buttons;
289 if (_farpeekl(_dos_ds, 0x33 * 4) == 0) {
291 if (_dos_getvect(0x33) == NULL) {
293 // No mouse driver loaded
297 // Reset the mouse driver
298 memset( &inregs, 0, sizeof(inregs) );
300 int386(0x33, &inregs, &outregs);
301 if (outregs.w.ax != 0xffff)
304 Mouse.num_buttons = outregs.w.bx;
307 // Enable mouse driver
308 memset( &inregs, 0, sizeof(inregs) );
309 inregs.w.ax = 0x0020;
310 int386(0x33, &inregs, &outregs);
311 if (outregs.w.ax != 0xffff )
314 if ( enable_cyberman ) {
315 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
316 if (Mouse_dos_mem==NULL) {
317 printf( "Unable to allocate DOS buffer in mouse.c\n" );
319 // Check for Cyberman...
320 memset( &rr, 0, sizeof(dpmi_real_regs) );
321 rr.es = DPMI_real_segment(Mouse_dos_mem);
322 rr.edx = DPMI_real_offset(Mouse_dos_mem);
324 dpmi_real_int386x( 0x33, &rr );
326 // SWIFT functions supported
327 ci = (cyberman_info *)Mouse_dos_mem;
328 if (ci->device_type==1) { // Cyberman
330 //printf( "Cyberman mouse detected\n" );
331 Mouse.num_buttons = 11;
337 if (!dpmi_lock_region(&Mouse,sizeof(mouse_info))) {
338 printf( "Unable to lock mouse data region" );
341 if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler)) {
342 printf( "Unable to lock mouse handler" );
346 // Install mouse handler
349 dpmi_real_regs rregs;
350 _go32_dpmi_seginfo info;
351 memset(&rregs, 0, sizeof(rregs));
352 info.pm_offset = (unsigned int)&mouse_handler;
353 if (_go32_dpmi_allocate_real_mode_callback_retf(&info, &handler_regs)) {
354 printf( "Unable allocate mouse handler callback" );
358 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
360 rregs.ecx |= ME_Z_C| ME_P_C| ME_B_C| ME_H_C; // if using a cyberman, also watch z, pitch, bank, heading.
361 rregs.edx = info.rm_offset;
362 rregs.es = info.rm_segment;
363 dpmi_real_int386x( 0x33, &rregs );
366 memset( &inregs, 0, sizeof(inregs));
367 memset( &sregs, 0, sizeof(sregs));
369 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
371 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.
372 inregs.x.edx = FP_OFF(mouse_handler);
373 sregs.es = FP_SEG(mouse_handler);
374 int386x(0x33, &inregs, &outregs, &sregs);
379 atexit( mouse_close );
383 return Mouse.num_buttons;
391 union REGS inregs, outregs;
393 if (Mouse_installed) {
395 // clear mouse handler by setting flags to 0.
396 memset( &inregs, 0, sizeof(inregs));
397 memset( &sregs, 0, sizeof(sregs));
399 inregs.w.cx = 0; // disable event handler by setting to zero.
402 int386x(0x33, &inregs, &outregs, &sregs);
407 void mouse_set_limits( int x1, int y1, int x2, int y2 )
409 union REGS inregs, outregs;
411 if (!Mouse_installed) return;
413 memset( &inregs, 0, sizeof(inregs));
414 inregs.w.ax = 0x7; // Set Horizontal Limits for Pointer
417 int386(0x33, &inregs, &outregs);
419 memset( &inregs, 0, sizeof(inregs));
420 inregs.w.ax = 0x8; // Set Vertical Limits for Pointer
423 int386(0x33, &inregs, &outregs);
426 void mouse_get_pos( int *x, int *y)
428 union REGS inregs, outregs;
430 if (!Mouse_installed) {
434 memset( &inregs, 0, sizeof(inregs));
435 inregs.w.ax = 0x3; // Get Mouse Position and Button Status
436 int386(0x33, &inregs, &outregs);
437 *x = (short)outregs.w.cx;
438 *y = (short)outregs.w.dx;
441 void mouse_get_delta( int *dx, int *dy )
443 union REGS inregs, outregs;
445 if (!Mouse_installed) {
450 memset( &inregs, 0, sizeof(inregs));
451 inregs.w.ax = 0xb; // Read Mouse motion counters
452 int386(0x33, &inregs, &outregs);
453 *dx = (short)outregs.w.cx;
454 *dy = (short)outregs.w.dx;
463 if (!Mouse_installed)
466 for (i=0; i<MOUSE_MAX_BUTTONS; i++ ) {
467 if (Mouse.pressed[i])
474 void mouse_set_pos( int x, int y)
476 union REGS inregs, outregs;
478 if (!Mouse_installed)
481 memset( &inregs, 0, sizeof(inregs));
482 inregs.w.ax = 0x4; // Set Mouse Pointer Position
485 int386(0x33, &inregs, &outregs);
494 if (!Mouse_installed)
499 //Clear the mouse data
500 CurTime =timer_get_fixed_secondsX();
501 for (i=0; i<MOUSE_MAX_BUTTONS; i++ ) {
502 Mouse.pressed[i] = 0;
503 Mouse.time_went_down[i] = CurTime;
504 Mouse.time_held_down[i] = 0;
505 Mouse.num_downs[i]=0;
512 // Returns how many times this button has went down since last call.
513 int mouse_button_down_count(int button)
517 if (!Mouse_installed)
522 count = Mouse.num_downs[button];
523 Mouse.num_downs[button]=0;
530 // Returns 1 if this button is currently down
531 int mouse_button_state(int button)
535 if (!Mouse_installed)
540 state = Mouse.pressed[button];
549 // Returns how long this button has been down since last call.
550 fix mouse_button_down_time(int button)
554 if (!Mouse_installed)
559 if ( !Mouse.pressed[button] ) {
560 time_down = Mouse.time_held_down[button];
561 Mouse.time_held_down[button] = 0;
563 time = timer_get_fixed_secondsX();
564 time_down = time - Mouse.time_went_down[button];
565 Mouse.time_went_down[button] = time;
573 void mouse_get_cyberman_pos( int *x, int *y )
577 ubyte *Mouse_dos_mem;
579 if ( (!Mouse_installed) || (!Mouse.cyberman) ) {
584 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
586 if ( !Mouse_dos_mem ) {
592 memset( &rr, 0, sizeof(dpmi_real_regs) );
593 rr.es = DPMI_real_segment(Mouse_dos_mem);
594 rr.edx = DPMI_real_offset(Mouse_dos_mem);
596 dpmi_real_int386x( 0x33, &rr );
598 ei = (event_info *)Mouse_dos_mem;
600 *x = (((ei->x+8128)*256)/(8064+8128+1)) - 127;
601 *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127;
604 #endif // __ENV_DJGPP__