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.
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)
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)
45 #define MOUSE_MAX_BUTTONS 11
47 typedef struct event_info {
55 ushort device_dependant;
58 typedef struct mouse_info {
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];
71 typedef struct cyberman_info {
78 ubyte pitch_descriptor;
79 ubyte roll_descriptor;
84 static mouse_info Mouse;
86 static int Mouse_installed = 0;
88 #pragma off (check_stack)
89 void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi)
91 #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
93 Mouse.ctime = timer_get_fixed_secondsX();
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;
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];
106 Mouse.num_ups[MB_LEFT]++;
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;
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];
120 Mouse.num_ups[MB_RIGHT]++;
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;
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];
134 Mouse.num_ups[MB_MIDDLE]++;
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);
140 if (m_ax & ME_Z_C ) { // z axis changed
141 if (Mouse.pressed[MB_Z_UP]) {
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 ) {
148 Mouse.pressed[MB_Z_UP] = 1;
149 Mouse.time_went_down[MB_Z_UP]=Mouse.ctime;
150 Mouse.num_downs[MB_Z_UP]++;
152 if (Mouse.pressed[MB_Z_DOWN]) {
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 ) {
159 Mouse.pressed[MB_Z_DOWN] = 1;
160 Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime;
161 Mouse.num_downs[MB_Z_DOWN]++;
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]++;
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]++;
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 ) {
197 Mouse.pressed[MB_BANK_LEFT] = 1;
198 Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime;
199 Mouse.num_downs[MB_BANK_LEFT]++;
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]++;
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 ) {
222 Mouse.pressed[MB_HEAD_LEFT] = 1;
223 Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime;
224 Mouse.num_downs[MB_HEAD_LEFT]++;
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]++;
245 void mouse_handler_end (void) // dummy functions
248 #pragma on (check_stack)
250 //--------------------------------------------------------
251 // returns 0 if no mouse
252 // else number of buttons
253 int mouse_init(int enable_cyberman)
258 union REGS inregs, outregs;
259 ubyte *Mouse_dos_mem;
262 return Mouse.num_buttons;
264 if (_dos_getvect(0x33) == NULL) {
265 // No mouse driver loaded
269 // Reset the mouse driver
270 memset( &inregs, 0, sizeof(inregs) );
272 int386(0x33, &inregs, &outregs);
273 if (outregs.w.ax != 0xffff)
276 Mouse.num_buttons = outregs.w.bx;
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 )
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" );
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);
296 dpmi_real_int386x( 0x33, &rr );
298 // SWIFT functions supported
299 ci = (cyberman_info *)Mouse_dos_mem;
300 if (ci->device_type==1) { // Cyberman
302 //printf( "Cyberman mouse detected\n" );
303 Mouse.num_buttons = 11;
309 if (!dpmi_lock_region(&Mouse,sizeof(mouse_info))) {
310 Error( "Unable to lock mouse data region" );
312 if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler)) {
313 Error( "Unable to lock mouse handler" );
316 // Install mouse handler
317 memset( &inregs, 0, sizeof(inregs));
318 memset( &sregs, 0, sizeof(sregs));
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
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);
329 atexit( mouse_close );
333 return Mouse.num_buttons;
341 union REGS inregs, outregs;
343 if (Mouse_installed) {
345 // clear mouse handler by setting flags to 0.
346 memset( &inregs, 0, sizeof(inregs));
347 memset( &sregs, 0, sizeof(sregs));
349 inregs.w.cx = 0; // disable event handler by setting to zero.
352 int386x(0x33, &inregs, &outregs, &sregs);
357 void mouse_set_limits( int x1, int y1, int x2, int y2 )
359 union REGS inregs, outregs;
361 if (!Mouse_installed) return;
363 memset( &inregs, 0, sizeof(inregs));
364 inregs.w.ax = 0x7; // Set Horizontal Limits for Pointer
367 int386(0x33, &inregs, &outregs);
369 memset( &inregs, 0, sizeof(inregs));
370 inregs.w.ax = 0x8; // Set Vertical Limits for Pointer
373 int386(0x33, &inregs, &outregs);
376 void mouse_get_pos( int *x, int *y)
378 union REGS inregs, outregs;
380 if (!Mouse_installed) {
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;
391 void mouse_get_delta( int *dx, int *dy )
393 union REGS inregs, outregs;
395 if (!Mouse_installed) {
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;
413 if (!Mouse_installed)
416 for (i=0; i<MOUSE_MAX_BUTTONS; i++ ) {
417 if (Mouse.pressed[i])
424 void mouse_set_pos( int x, int y)
426 union REGS inregs, outregs;
428 if (!Mouse_installed)
431 memset( &inregs, 0, sizeof(inregs));
432 inregs.w.ax = 0x4; // Set Mouse Pointer Position
435 int386(0x33, &inregs, &outregs);
444 if (!Mouse_installed)
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;
462 // Returns how many times this button has went down since last call.
463 int mouse_button_down_count(int button)
467 if (!Mouse_installed)
472 count = Mouse.num_downs[button];
473 Mouse.num_downs[button]=0;
480 // Returns 1 if this button is currently down
481 int mouse_button_state(int button)
485 if (!Mouse_installed)
490 state = Mouse.pressed[button];
499 // Returns how long this button has been down since last call.
500 fix mouse_button_down_time(int button)
504 if (!Mouse_installed)
509 if ( !Mouse.pressed[button] ) {
510 time_down = Mouse.time_held_down[button];
511 Mouse.time_held_down[button] = 0;
513 time = timer_get_fixed_secondsX();
514 time_down = time - Mouse.time_went_down[button];
515 Mouse.time_went_down[button] = time;
523 void mouse_get_cyberman_pos( int *x, int *y )
527 ubyte *Mouse_dos_mem;
529 if ( (!Mouse_installed) || (!Mouse.cyberman) ) {
534 Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 );
536 if ( !Mouse_dos_mem ) {
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);
546 dpmi_real_int386x( 0x33, &rr );
548 ei = (event_info *)Mouse_dos_mem;
550 *x = (((ei->x+8128)*256)/(8064+8128+1)) - 127;
551 *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127;