VOGONS


Simulating mouse clicks

Topic actions

First post, by pimlottc

User metadata
Rank Newbie
Rank
Newbie

I've recently been play Shadows of Yserbius on innrevival, thanks in no small part to DOSbox. But the game bugs me by requiring the mouse for most actions.

So I have been trying to create a crude "mousekeys" sort of system where I can bind keys to mouse clicks on specific coordinates.

Right now, I'm doing this by using functions from ints/mouse.cpp (Mouse_CursorSet and Mouse_ButtonPressed). I found, though, that if I call Mouse_ButtonPressed followed immediately by Mouse_ButtonReleased, it doesn't register a click. I figure this is because the system needs some time to process the click, otherwise my instantaneous release basically negates the press before the system sees it.

My work around is to bind Mouse_ButtonPressed to the KEYDOWN event and Mouse_ButtonRelease to the KEYUP. Which basically works, but this limits it to keys that generate KEYUP events.

I tried doing the press, forking, sleeping in the child and then doing a release, but that doesn't seem to work at all (the release never seems to happen, the game thinks the mouse button is still held down until I manually click a second time).

So I could use some advice on how to fix my problem. Or maybe I'm going about this the wrong way, and there's a better way I should be looking at to fake mouse events. I'm not that familiar with SDL or DOS programming so I'd appreciate any help more experienced people could offer. Thanks.

Reply 1 of 5, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Maybe rewrite Mouse_AddEvent so it fires the release event after a short
period of time, using PIC_AddEvent (see timer.cpp function PIT0_Event for
an example).

Reply 2 of 5, by pimlottc

User metadata
Rank Newbie
Rank
Newbie

Thanks for the advice, this seems to work very well. The only drawback is that it seems the pic event queue is only processed if there are new keyboard events.

Reply 3 of 5, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

No, that would mean the mouse doesn't work at all.
Which functions did you change?

Reply 4 of 5, by artelius

User metadata
Rank Newbie
Rank
Newbie

From a DOS programming perspective, mouse clicks can be dealt with in two ways:

Poll INT 33,3 (Get mouse position and button status)
Watch the state of the buttons (pressed or released) and where the pointer happens to be. For a click to be registered, this interrupt must indicate the button is down on one call, and up on the next.

Or -
check INT 33,5 and INT 33,6 (Get last press information, and last release information). Programs that use this method will probably work correctly in the situation you describe.

There is also the option of a program installing a custom interrupt routine. That might complicate things.

Anyway, I would guess that this game simply polls INT 33, 3 . So, basically you need INT33_Handler to return a pressed state on one call and a released state on the next.

Some strategies I can think of:
-Delay between setting the pressed and released states - which you've already tried. Perhaps you could schedule an SDL-based callback, see http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fAddTimer

-Have some sort of semaphore/callback system whereby INT33_Handler (under case 0x03) awakens or calls something else to notify that the DOS program has been told about the mouse state.

-It would appear that INT74 is what actually processes the mouse events, and that PIC_ActivateIRQ(MOUSE_IRQ); is what leads to it being called. It looks like MOUSE_UserInt_CB_Handler() causes the IRQ to reinstate itself if the event queue had more than one event in it to start with - so it would follow that having this function somehow schedule activation of the IRQ, rather than doing it immediately, would insert a gap between processing of multiple events. (If just a single event enters the queue this will have no effect.)

If I get any bright ideas I'll make them known.

Reply 5 of 5, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

From dosbox's point of view you can use the upper layers, that is capture/simulate
mouse movement+clicks at the SDL level using state and timing information.