1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 Copyright (C) 2019 Shockolate Project
5 
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 
19 */
20 /*
21  * $Source: n:/project/lib/src/input/RCS/mouse.c $
22  * $Revision: 1.15 $
23  * $Author: mahk $
24  * $Date: 1994/06/21 06:16:42 $
25  *
26  * Mouse handler adapted from Rex Bradford's Freefall mouse code.
27  *
28  * This file is part of the input library.
29  */
30 
31 //    This file only vaguely resembles the freefall mouse code from
32 //    which it descended.  It supports some very-low-level input routines
33 //    for the mouse.  It provides an interrupt-driven event queue, polling,
34 //    and callbacks from the interrupt handler.
35 
36 //	---------------------------------------------------------
37 // 6/21/94 ML Added mouse velocity support in mousevel.h so that we can emulate the mouse
38 // using other devices.
39 //	---------------------------------------------------------
40 // For the Mac version I use a TimeManager task to poll the mouse for mouse
41 // movement callback routines.  Mouse click events will be handled throught the normal
42 // Macintosh event queue.  Most of the stuff in this file will go away.
43 // ¥¥¥Note:  The mouse position will always be returned in *local* coordinates,
44 // that is, local to the main game window.
45 
46 #include <SDL.h>
47 
48 #include "error.h"
49 #include "mouse.h"
50 #include "tickcount.h"
51 
52 typedef struct _mouse_state {
53     short x, y;
54     short butts;
55 } mouse_state;
56 
57 /*
58 #define DEFAULT_XRATE 16  			// Default mouse sensitivity parameters
59 #define DEFAULT_YRATE 8
60 #define DEFAULT_ACCEL 100
61 #define LO_RES_SCREEN_WIDTH 320
62 #define HIRES_XRATE 2
63 #define HIRES_YRATE 2
64 
65 //	These are global for fast access from interrupt routine & others
66 
67 short gMouseCritical;						// in critical region?
68 */
69 #define NUM_MOUSEEVENTS 32
70 short mouseQueueSize = NUM_MOUSEEVENTS;
71 volatile short mouseQueueIn;                // back of event queue
72 volatile short mouseQueueOut;               // front of event queue
73 ss_mouse_event mouseQueue[NUM_MOUSEEVENTS]; // array of events
74 
75 short mouseInstantX; // instantaneous mouse xpos (int-based)
76 short mouseInstantY; // instantaneous mouse ypos (int-based)
77 short mouseInstantButts;
78 /*
79 short mouseButtMask;   					// amt to mask to get buttons.
80 ubyte mouseXshift = 0;  					// Extra bits of mouse resolution
81 ubyte mouseYshift = 1;
82 */
83 ubyte mouseMask = 0xFF; // mask of events to put in the queue.
84 /*
85 uchar  mouseLefty = FALSE; 				// is the user left-handed?
86 */
87 #define NUM_MOUSE_CALLBACKS 16
88 mouse_callfunc mouseCall[NUM_MOUSE_CALLBACKS];
89 void *mouseCallData[NUM_MOUSE_CALLBACKS];
90 short mouseCalls = 0; // current number of mouse calls.
91 short mouseCallSize = sizeof(mouse_callfunc);
92 /*
93 uchar mouse_installed = FALSE;					// was mouse found?
94 
95 ulong default_mouse_ticks = 0;
96 ulong volatile *mouse_ticks = &default_mouse_ticks;  // Place to get mouse timestamps.
97 
98 // MOUSE VELOCITY STUFF
99 
100 int mouseVelX = 0, mouseVelY = 0;
101 int mouseVelXmax = 0x7FFFFFFF;
102 int mouseVelYmax = 0x7FFFFFFF;
103 int mouseVelXmin = 0x80000000;
104 int mouseVelYmin = 0x80000000;
105 
106 //	Macros & defines
107 
108 #define MOUSECRITON() (gMouseCritical++)
109 #define MOUSECRITOFF() (gMouseCritical--)
110 
111 #define INT_MOUSE 0x33		// mouse software interrupt vector
112 
113 #define ERRET 1
114 
115 
116 
117 extern void MouseHandler(void);
118 extern ulong mouseHandlerSize;
119 */
120 
121 // extern short gActiveLeft, gActiveTop;
122 // bool gRBtnWasDown = true;
123 extern uchar pKbdGetKeys[16];
124 
125 //----------------
126 // Internal Prototypes
127 //----------------
128 static void ReadMouseState(mouse_state *pMouseState);
129 
130 #if __profile__
131 #pragma profile off
132 #endif
133 //---------------------------------------------------------------
134 //  The following section is the time manager task for handling mouse movement.
135 //---------------------------------------------------------------
136 #pragma require_prototypes off
137 
138 // KLC - try calling this from the main timer task.
139 //---------------------------------------------------------------
MousePollProc(void)140 void MousePollProc(void) {
141     // TODO: is this even still needed? if so, can it be replaced by setting mouseInstant* in pump_events() ?
142     //       if the callbacks from mouseCall[] are still needed, could they also be called in pump_events() ?
143     //       if not, could they be the only thing called here, while mouseInstant* is still set in pump_events() ?
144 
145     extern ss_mouse_event latestMouseEvent;
146     mouseInstantButts = latestMouseEvent.buttons;
147 
148     if (mouseInstantX != latestMouseEvent.x || mouseInstantY != latestMouseEvent.y) // If different
149     {
150         mouseInstantX = latestMouseEvent.x; // save the position
151         mouseInstantY = latestMouseEvent.y;
152 
153         ss_mouse_event e = latestMouseEvent;
154         e.type = MOUSE_MOTION;
155 
156         for (uint16_t i = 0; i < mouseCalls; i++)
157             if (mouseCall[i] != NULL)
158                 mouseCall[i](&e, mouseCallData[i]);
159 
160         if (mouseMask & MOUSE_MOTION) // Add a mouse-moved event
161         {                             // to the internal queue.
162             short newin = mouseQueueIn, newout = mouseQueueOut;
163             short in = newin;
164             mouseQueue[newin] = e;
165             newin = (newin + 1 < mouseQueueSize) ? newin + 1 : 0;
166             if (newin == mouseQueueOut)
167                 newout = (newout + 1 < mouseQueueSize) ? newout + 1 : 0;
168             mouseQueueOut = newout;
169             mouseQueueIn = newin;
170         }
171     }
172 
173     /*Point					mp;
174     short					i;
175     mouse_event		e;
176 
177     mp = *(Point *)0x830;												// Get mouse location from low
178 memory. mp.h -= gActiveLeft;
179 // Convert to "local" screen coordinates. mp.v -= gActiveTop;
180 
181     GetKeys((UInt32 *)pKbdGetKeys);								// Check keys to see if our
182 simulated
183                                                                                                                                                                     // right button is down.
184     if (Button())																// See if the mouse button is
185 down
186     {
187             mouseInstantButts = 1;
188             if ((pKbdGetKeys[0x3A>>3] >> (0x3A & 7)) & 1)		// If the option key is down also,
189                     mouseInstantButts = 2;										// then it's really a right-button
190 click.
191     }
192     if( ((pKbdGetKeys[0x31>>3] >> (0x31 & 7)) & 1) ||		// If space, enter, or return are down,
193              ((pKbdGetKeys[0x4C>>3] >> (0x4C & 7)) & 1) ||		// then pretend right-button is down.
194              ((pKbdGetKeys[0x24>>3] >> (0x24 & 7)) & 1)  )
195             mouseInstantButts |= 2;
196 
197     if (mouseInstantX != mp.h || mouseInstantY != mp.v)		// If different
198     {
199             mouseInstantX = mp.h;												// save the
200 position mouseInstantY = mp.v;
201 
202             e.x = mp.h;																// and inform the callback
203 routines e.y = mp.v; e.type = MOUSE_MOTION; e.buttons = mouseInstantButts; for (i = 0; i < mouseCalls; i++)
204                     if(mouseCall[i] !=NULL)
205                             mouseCall[i](&e,mouseCallData[i]);
206 
207             if (mouseMask & MOUSE_MOTION)							// Add a mouse-moved
208 event
209             {																			// to the internal
210 queue. short newin = mouseQueueIn, newout = mouseQueueOut; short in = newin; mouseQueue[newin] = e; newin =  (newin + 1
211 < mouseQueueSize) ? newin + 1 : 0; if (newin == mouseQueueOut) newout = (newout + 1 < mouseQueueSize) ? newout + 1 : 0;
212                     mouseQueueOut = newout;
213                     mouseQueueIn  = newin;
214             }
215     }
216 //	PrimeTime((QElemPtr)tmTaskPtr, 50);						// Check 20 times a second.
217 
218 */
219 }
220 
221 #pragma require_prototypes on
222 #if __profile__
223 #pragma profile on
224 #endif
225 
226 //	---------------------------------------------------------
227 //	mouse_shutdown() terminates mouse handler.
228 //	---------------------------------------------------------
229 // For Mac version: do nothing.
230 
mouse_shutdown(void)231 errtype mouse_shutdown(void) {
232     /*	union REGS regs;
233             struct SREGS segregs;
234 
235             Spew(DSRC_MOUSE_Shutdown,("entering mouse_shutdown()\n"));
236 
237 
238             //	Shut down Microsoft mouse driver
239 
240             if (mouse_installed)
241             {
242                     regs.x.eax = 0x000C;
243                     regs.x.ecx = 0;
244                     regs.x.edx = 0;
245                     segregs.es = 0;
246                     segregs.ds = 0;
247                     int386x(INT_MOUSE, &regs, &regs, &segregs);
248 
249                     dpmi_unlock_lin_region(MouseHandler,mouseHandlerSize);
250             } */
251     //	RmvTime((QElemPtr)&pMousePollTask);							// Stop the mouse polling
252     //task 	DisposeRoutineDescriptor(pMousePollPtr);						// Dispose its UPP
253 
254     return OK;
255 }
256 
257 //	---------------------------------------------------------
258 //	mouse_init() initializes mouse handler.  It does the following:
259 //
260 //	1. Microsoft mouse driver initialized
261 //	2. Customizes mouse driver & handler based on display mode
262 //	3. Initializes mouse handler state variables
263 //	---------------------------------------------------------
264 //  For Mac version: ignore sizes (mouse is already set up).
265 
mouse_init(short mone,short mtwo)266 errtype mouse_init(short mone, short mtwo) {
267     mouse_state mstate;
268     /*
269             union REGS regs;
270             struct SREGS segregs;
271             Spew(DSRC_MOUSE_Init,("Entering mouse_init()\n"));
272 
273             //	Initialize Microsoft mouse driver
274 
275             regs.x.eax = 0x0000;
276             int386(INT_MOUSE, &regs, &regs);
277             mouse_installed = (regs.w.ax != 0);
278 
279             //	If mouse found, do more initialization
280 
281             if (mouse_installed)
282             {
283 
284             DBG(DSRC_MOUSE_Init,
285             { if (!mouse_installed)
286                     Warning(("mouse_init(): Mouse not installed\n"));
287             })
288     */
289     //	Initialize mouse state variables
290 
291     extern void sdl_mouse_init(void);
292     sdl_mouse_init();
293 
294     mouseQueueIn = 0;
295     mouseQueueOut = 0;
296 
297     mouseCalls = 0;
298 
299     ReadMouseState(&mstate);
300     mouseInstantX = mstate.x;
301     mouseInstantY = mstate.y;
302     mouseInstantButts = mstate.butts;
303     /*
304             //	Set up mouse interrupt handler
305 
306             dpmi_lock_lin_region(MouseHandler,mouseHandlerSize);
307 
308             regs.x.eax = 0x000C;
309             regs.w.cx = 0xFF;							// take all mouse events
310             regs.x.edx = FP_OFF(MouseHandler);
311             segregs.es = FP_SEG(MouseHandler);
312             segregs.ds = segregs.es;
313             int386x(INT_MOUSE, &regs, &regs, &segregs);
314 
315             // Do the sensitivity scaling thang.
316             mouse_set_screensize(xsize,ysize);
317             }
318 
319             AtExit(mouse_shutdown);
320 
321             //	Return whether or not mouse found
322 
323             return(mouse_installed ? OK : ERR_NODEV);
324     */
325 
326     /*
327             pMousePollPtr = NewTimerProc(MousePollProc);			// Make a UPP for the TM task
328 
329             pMousePollTask.task.tmAddr = pMousePollPtr;				// Insert the mouse polling TM task
330             pMousePollTask.task.tmWakeUp = 0;
331             pMousePollTask.task.tmReserved = 0;
332     #ifndef __powerc
333             pMousePollTask.appA5 = SetCurrentA5();
334     #endif
335             InsTime((QElemPtr)&pMousePollTask);
336             PrimeTime((QElemPtr)&pMousePollTask, 50);				// Check 20 times a second
337     */
338     return (OK);
339 }
340 /*
341 // ---------------------------------------------------------
342 // mouse_set_screensize() sets the screen size, scaling mouse sensitivity.
343 errtype mouse_set_screensize(short x, short y)
344 {
345    short xrate = DEFAULT_XRATE,yrate = DEFAULT_YRATE,t = DEFAULT_ACCEL;
346    if (x > LO_RES_SCREEN_WIDTH)
347    {
348       xrate = HIRES_XRATE;
349       yrate = HIRES_YRATE;
350       mouseXshift = 3;
351       mouseYshift = 3;
352    }
353    else
354    {
355       xrate /= 2;
356       mouseXshift = 1;
357       mouseYshift = 0;
358    }
359    mouse_set_rate(xrate,yrate,t);
360    mouse_constrain_xy(0,0,x-1,y-1);
361    mouse_put_xy(mouseInstantX,mouseInstantY);
362    return OK;
363 }
364 */
365 /*
366 //---------------------------------------------------------
367 // _mouse_update_vel() updates coordinates based on mouse
368 //  velocity.  Generates a motion event if there's any change to position.
369 
370 void _mouse_update_vel(void)
371 {
372    static ulong last_ticks = 0;
373 
374    ulong ticks = *mouse_ticks;
375 
376    if (ticks != last_ticks && (mouseVelX != 0 || mouseVelY != 0))
377    {
378       short newx = mouseInstantX;
379       short newy = mouseInstantY;
380       ulong dt = ticks - last_ticks;
381       short dx = (mouseVelX*dt) >> MOUSE_VEL_UNIT_SHF;
382       short dy = (mouseVelY*dt) >> MOUSE_VEL_UNIT_SHF;
383 
384       mouse_put_xy(newx+dx,newy+dy);
385    }
386    last_ticks = ticks;
387 }
388 */
389 
390 // --------------------------------------------------------
391 // mouse_check_btn checks button state.
392 //   res = ptr to result
393 //   button = button number 0-2
394 //	---------------------------------------------------------
395 //  For Mac version: Basically just return true or false right now.
396 // WH: no use
397 #if 0
398 errtype mouse_check_btn(short button, bool *res) {
399 
400     if (button == 1) {
401         *res = SDL_BUTTON(SDL_BUTTON_LEFT);
402     } else if (button == 2) {
403         *res = SDL_BUTTON(SDL_BUTTON_RIGHT);
404     }
405     /*   if (!mouse_installed)
406        {
407           Warning(("mouse_get_xy(): mouse not installed.\n"));
408           return ERR_NODEV;
409        }
410        *res = (mouseInstantButts >> button) & 1;
411        Spew(DSRC_MOUSE_CheckBtn,("mouse_check_btn(%d,%x) *res = %d\n",button,res,*res)); */
412     return OK;
413 }
414 #endif
415 // ---------------------------------------------------------
416 // mouse_look_next gets the event in front the event queue,
417 // but does not remove the event from the queue.
418 // res = ptr to event to be filled.
419 //	---------------------------------------------------------
420 //  For Mac version: Check the normal Mac event queue for mouse events.  The events
421 //  looked for depend on the 'mouseMask' setting.
422 // WH: no use
423 #if 0
424 errtype mouse_look_next(ss_mouse_event *res) {
425     printf("mouse_look_next not implemented.\n");
426 
427     /*if (OSEventAvail(eventMask, &theEvent))				// If there is an event,
428     {
429             GlobalToLocal(&theEvent.where);
430             res->x = theEvent.where.h;								// fill in the mouse_event
431     record. res->y = theEvent.where.v; res->timestamp = theEvent.when;
432             if (theEvent.modifiers & optionKey)					// If the option keys is down, send back
433     a
434             {																	// right-button
435     event. if (theEvent.what == mouseDown) res->type = MOUSE_RDOWN; else if (theEvent.what == mouseUp) res->type =
436     MOUSE_RUP; res->buttons = 2; res->modifiers = 0;
437             }
438             else																// Otherwise it's a left-button
439     event.
440             {
441                     if (theEvent.what == mouseDown)
442                             res->type = MOUSE_LDOWN;
443                     else if (theEvent.what == mouseUp)
444                             res->type = MOUSE_LUP;
445                     res->buttons = 1;
446                     res->modifiers = (uchar)(theEvent.modifiers >> 8);
447             }
448     }*/
449 
450     // If there's not a mouse click event, check the internal queue for mouse
451     // movement events.
452     /*else if (mouseMask & MOUSE_MOTION)
453     {
454             if (mouseQueueOut == mouseQueueIn)			// If no motion events, return an error.
455                     return ERR_NODEV;
456             else
457                     *res = mouseQueue[mouseQueueOut];		// Return the event.
458     }
459 
460     // If there are no events at all, return an error.
461     else
462             return ERR_NODEV;*/
463 
464     /*
465        Spew(DSRC_MOUSE_LookNext,("entering mouse_look_next()\n"));
466        if (mouseQueueOut == mouseQueueIn)
467           _mouse_update_vel();
468        if (mouseQueueOut == mouseQueueIn)
469        {
470           Spew(DSRC_MOUSE_LookNext,("mouse_look_next(): Queue Underflow.\n"));
471           return ERR_NODEV;
472        }
473       *res = mouseQueue[mouseQueueOut];
474     */
475     return OK;
476 }
477 #endif
478 
479 /*
480 // -------------------------------------------------------
481 //
482 // mouse_generate() adds an event to the back of the
483 //  mouse event queue.  If this overflows the queue,
484 
485 errtype mouse_generate(mouse_event e)
486 {
487    short newin = mouseQueueIn, newout = mouseQueueOut;
488    short in = newin;
489    int i;
490    errtype result = OK;
491    Spew(DSRC_MOUSE_Generate,("Entering mouse_generate()\n"));
492    mouseQueue[newin] = e;
493    newin =  (newin + 1  < mouseQueueSize) ? newin + 1 : 0;
494    if (newin == mouseQueueOut)
495    {
496       newout = (newout + 1 < mouseQueueSize) ? newout + 1 : 0;
497       Spew(DSRC_MOUSE_Generate,("mouse_generate(): Queue Overflow.\n"));
498       result = ERR_DUNDERFLOW;
499    }
500 
501    mouseQueueOut = newout;
502    mouseQueueIn  = newin;
503    mouseInstantX = e.x;
504    mouseInstantY = e.y;
505    mouseInstantButts = e.buttons;
506    for (i = 0; i < mouseCalls; i++)
507       if(mouseCall[i] !=NULL)
508          mouseCall[i](&mouseQueue[in],mouseCallData[i]);
509    return result;
510 }
511 */
512 
513 // ------------------------------------------------------
514 //
515 // mouse_set_callback() registers a callback with the interrupt handler
516 // f = func to be called back.
517 // data = data to be given to the func when called
518 // *id = set to a unique id of the callback.
519 
mouse_set_callback(mouse_callfunc f,void * data,int * id)520 errtype mouse_set_callback(mouse_callfunc f, void *data, int *id) {
521     //   Spew(DSRC_MOUSE_SetCallback,("entering mouse_set_callback(%x,%x,%x)\n",f,data,id));
522     for (*id = 0; *id < mouseCalls; ++*id)
523         if (mouseCall[*id] == NULL)
524             break;
525     if (*id == NUM_MOUSE_CALLBACKS) {
526         //		Spew(DSRC_MOUSE_SetCallback,("mouse_set_callback(): Table Overflow.\n"));
527         return ERR_DOVERFLOW;
528     }
529     if (*id == mouseCalls)
530         mouseCalls++;
531     //	Spew(DSRC_MOUSE_SetCallback,("mouse_set_callback(): *id = %d, mouseCalls = %d\n",*id,mouseCalls));
532     mouseCall[*id] = f;
533     mouseCallData[*id] = data;
534     return OK;
535 }
536 
537 // -------------------------------------------------------
538 //
539 // mouse_unset_callback() un-registers a callback function
540 // id = unique id of function to unset
541 
mouse_unset_callback(int id)542 errtype mouse_unset_callback(int id) {
543     // Spew(DSRC_MOUSE_UnsetCallback,("entering mouse_unset_callback(%d)\n",id));
544     if (id >= mouseCalls || id < 0) {
545         // Spew(DSRC_MOUSE_UnsetCallback,("mouse_unset_callback(): id out of range \n"));
546         return ERR_RANGE;
547     }
548     mouseCall[id] = NULL;
549     while (mouseCalls > 0 && mouseCall[mouseCalls - 1] == NULL)
550         mouseCalls--;
551     return OK;
552 }
553 
554 // --------------------------------------------------------
555 //
556 // mouse_constrain_xy() defines min/max coords
557 //  ¥¥¥ don't do anything for now.  Will need to implement some day.
mouse_constrain_xy(short xl,short yl,short xh,short yh)558 errtype mouse_constrain_xy(short xl, short yl, short xh, short yh) {
559     /*
560        union REGS regs;
561        Spew(DSRC_MOUSE_ConstrainXY,("mouse_constrain_xy(%d,%d,%d,%d)\n",xl,yl,xh,yh));
562        if (!mouse_installed)
563        {
564           Warning(("mouse_constrain_xy(): mouse not installed.\n"));
565           return ERR_NODEV;
566        }
567        regs.x.eax = 0x0007;
568        regs.x.ecx = xl << mouseXshift;
569        regs.x.edx = xh << mouseXshift;
570        int386(INT_MOUSE,&regs,&regs);
571        regs.x.eax = 0x0008;
572        regs.x.ecx = yl << mouseYshift;
573        regs.x.edx = yh << mouseYshift;
574        int386(INT_MOUSE,&regs,&regs);
575     */
576     return OK;
577 }
578 
579 /*
580 // --------------------------------------------------------
581 //
582 // mouse_set_rate() sets mouse rate, doubling threshhold
583 
584 errtype mouse_set_rate(short xr, short yr, short thold)
585 {
586    union REGS regs;
587    Spew(DSRC_MOUSE_SetRate,("mouse_set_rate(%d,%d,%d)\n",xr,yr,thold));
588    if (!mouse_installed)
589    {
590       Warning(("mouse_set_rate(): mouse not installed.\n"));
591       return ERR_NODEV;
592    }
593 //   if (mouseXshift > 0) xr = xr / mouseXshift;  // why are we dividing?  Because shifting is too extreme
594 //   if (mouseYshift > 0) yr = yr / mouseYshift;
595    regs.x.eax = 0x000F;
596    regs.x.ecx = max(1,xr);
597    regs.x.edx = max(1,yr);
598    int386(INT_MOUSE,&regs,&regs);
599    regs.x.eax = 0x0013;
600    regs.x.edx = max(1,thold);
601    int386(INT_MOUSE,&regs,&regs);
602    return OK;
603 }
604 
605 // --------------------------------------------------
606 //
607 // mouse_get_rate() gets current sensitivity values
608 
609 errtype mouse_get_rate(short* xr, short* yr, short* thold)
610 {
611    union REGS regs;
612    regs.x.eax = 0x001B;
613    int386(INT_MOUSE,&regs,&regs);
614    *xr = regs.x.ebx;
615    *yr = regs.x.ecx;
616    *thold = regs.x.edx;
617 //   if (mouseXshift > 0) *xr *= mouseXshift;  // why are we multiplying?  Because shifting is too extreme
618 //   if (mouseYshift > 0) *yr *= mouseYshift;
619    return OK;
620 }
621 
622 
623 // --------------------------------------------------------
624 //
625 // mouse_set_timestamp_register() tells the mouse library where to get
626 // timestamps.
627 
628 errtype mouse_set_timestamp_register(ulong* tstamp)
629 {
630    mouse_ticks = tstamp;
631    return OK;
632 }
633 */
634 
635 // --------------------------------------------------------
636 // mouse_get_time() returns the current mouse timestamp
637 //	--------------------------------------------------------
638 // For Mac version:  Just return TickCount().
639 
mouse_get_time(void)640 uint32_t mouse_get_time(void) {
641     return TickCount();
642 }
643 
644 //	--------------------------------------------------------
645 //	ReadMouseState() reads current state of mouse.
646 //
647 //		pMouseState = ptr to mouse state struct, filled in by routine
648 //	--------------------------------------------------------
649 // For Mac version:  Use Mac routines to get mouse position and state.
650 
ReadMouseState(mouse_state * pMouseState)651 static void ReadMouseState(mouse_state *pMouseState) {
652     int mouse_x;
653     int mouse_y;
654 
655     uint mouse_state = SDL_GetMouseState(&mouse_x, &mouse_y);
656     pMouseState->x = mouse_x;
657     pMouseState->y = mouse_y;
658     pMouseState->butts = 0;
659 
660     if (mouse_state & SDL_BUTTON(SDL_BUTTON_LEFT)) {
661         pMouseState->butts = 1;
662     }
663 
664     if (mouse_state & SDL_BUTTON(SDL_BUTTON_RIGHT)) {
665         pMouseState->butts = 2;
666     }
667 
668     /*	union REGS regs;
669 
670             regs.x.eax = 0x0003;
671             int386(INT_MOUSE, &regs, &regs);
672 
673             pMouseState->x = regs.w.cx;
674             pMouseState->y = regs.w.dx;
675             pMouseState->butts = regs.w.bx; */
676 }
677 
678 /*
679 // ---------------------------------------------------
680 //
681 // mouse_extremes() finds the min and max "virtual" coordinates of the mouse position
682 
683 errtype mouse_extremes( short *xmin, short *ymin, short *xmax, short *ymax )
684 {
685    union REGS regs;
686 
687    regs.x.eax = 0x31;
688    int386( INT_MOUSE, &regs, &regs );
689 
690    *xmin = regs.w.ax >> mouseXshift;
691    *ymin = regs.w.bx >> mouseYshift;
692    *xmax = regs.w.cx >> mouseXshift;
693    *ymax = regs.w.dx >> mouseYshift;
694 
695    Spew( DSRC_MOUSE_Extremes, ("mouse_extremes(): <%d %d> to <%d %d>\n", *xmin, *ymin, *xmax, *ymax ));
696 
697    return OK;
698 }
699 
700 
701 // ------------------------------------------------------
702 //
703 // mouse_set_lefty() sets mouse handedness
704 
705 #define SHIFTDIFF 1
706 
707 static short shifted_button_state(short bstate)
708 {
709    short tmp = (bstate & MOUSE_RBUTTON) >> SHIFTDIFF;
710    tmp |= (bstate & MOUSE_LBUTTON) << SHIFTDIFF;
711    tmp |= bstate & MOUSE_CBUTTON;
712    return tmp;
713 }
714 
715 errtype mouse_set_lefty(uchar lefty)
716 {
717    if (lefty == mouseLefty) return ERR_NOEFFECT;
718    mouseInstantButts = shifted_button_state(mouseInstantButts);
719    mouseLefty = lefty;
720    return OK;
721 }
722 
723 
724 
725 
726 // ---------------------------------------------------
727 //
728 // mouse_set_velocity_range() sets the range of valid mouse pointer velocities.
729 
730 errtype mouse_set_velocity_range(int xl, int yl, int xh, int yh)
731 {
732    mouseVelXmin = xl;
733    mouseVelYmin = yl;
734    mouseVelXmax = xh;
735    mouseVelYmax = yh;
736    return OK;
737 }
738 
739 errtype mouse_set_velocity(int x, int y)
740 {
741    mouseVelX = max(mouseVelXmin,min(x,mouseVelXmax));
742    mouseVelY = max(mouseVelYmin,min(y,mouseVelYmax));
743    if (mouseVelX != x || mouseVelY != y)
744       return ERR_RANGE;
745    return OK;
746 }
747 
748 errtype mouse_add_velocity(int x, int y)
749 {
750    return mouse_set_velocity(mouseVelX + x, mouseVelY + y);
751 }
752 
753 errtype mouse_get_velocity(int* x, int* y)
754 {
755    *x = mouseVelX;
756    *y = mouseVelY;
757    return OK;
758 }
759 */
760