
Somehow it happened that I got a Windows 8 tablet. Not a very successful model - cumbersome as an assistant, rather weak as a workstation, but with a stylus, and most importantly, with a 32-bit Win32 system. Having a certain number of old games from sales of GOG and Steam, I planned to somehow sit down with this tablet and replay everything that can and cannot be. But somehow there was not enough time and mood, and even test launches showed that you need to play with the mouse - the cursor from the touch-screen ran off unknown where, and even a right click with a long press would be frankly inconvenient. The tablet was gathering dust for half a year in a corner before the recent
distribution of Fallout from GOG and this distribution pushed me to action. Friday night began, the tablet got a USB mouse, and I got comfortable on the couch and started on the list from the very top - with Arcanum.
After half an hour of creating a character (and this is a very important and responsible business!), The left hand barely held the device, and the right wrist suspiciously began to pull, hinting about tunnel syndrome and other pleasures of an uncomfortable grip. Remembering
not the good word of the developers of some ergonomic folding mouse, I climbed to look for drivers, patches, or at least something to play with the touchscreen, or at least the stylus.
There were no patches. The only similar driver was paid and without trial mode. It was at this moment that an idiotic (I now understand!) Thought came to my mind - “after all, some WM_TOUCH comes after all and is incorrectly converted to WM_MOUSEMOVE” ... Looking ahead, Arkanum now completely controls my touchscreen, though the weekend is over and more like to sleep than to play.
For impatientThe project is available on
github , there are source codes and a binary. This is a DLL file that should be used as a launcher for playing through rundll32. Pressing with two fingers makes a right click, pressing with three fingers imitates the ESC key - this is enough for Arcanum. Fallout 2 is supported in beta mode, the instruction is in the same place on github. Right-click does not work there, the cursor is occasionally shifted, but this can be corrected by dragging it to the lower left corner of the screen.
Visual studio 6.0

Somehow it happened that I was sick a dozen years ago by the hooks, patches and injections for Win32 and then with great pleasure I closed this page in my life. And now, dreaming of “half an hour to get to bed and then play,” I took out the old hard drive, wrote off a couple of projects and my favorite tool - VS98, also known as Visual Studio 6.0. Yes, I constantly use VS 2012 for W8 and WP mobile programs, but, I confess, I have no idea what the Platform SDK looks like in it now, and whether something like coding low-level things in C # or C ++ has become fashionable / mandatory / CLI. And then it turned out that VS98, with its weight of 120 megabytes at the same time, works fine under wine on my working machine.
Cleaning up old projects from tin, like IAT's substitution, was dragged out, but after a couple of hours I introduced my module into the game and could track its message flow (subclassing via SetWindowLong and blah blah blah). Spy ++, for obvious reasons, did not want to work with a full-screen game, because I wrote logs and then studied everything that looked like a mouse and a touch. On this Friday night ended and I postponed the continuation in the morning.
WM_TOUCH
In the morning I looked through a couple of articles about working with a touchscreen and sat down to catch WM_TOUCH. An excellent message comes regularly, although it contains in one block a dozen or two taps. It was interesting that the coordinates in the game came correct - they exactly corresponded to the place of pressing on the screen. This did not seem to matter, because I began to generate WM_MOUSEMOVE for each event. The result was surprised - nothing has changed. Nothing at all. Replaced WM_MOUSEMOVE with SetCursorPos and did see the result - crawling the cursor became noticeably less chaotic. It seemed that the matter was in a hat - you
just need
to understand what is going wrong and why the cursor shifts towards each time ... Only when it got dark on the street, I realized that something went wrong :) All logical and non-logical methods formulas, adjustments of coordinates, witchcraft with mouse_event, SendInput, cancellation of certain events - in no case could I get the cursor to move to the place of the click. It seemed to be nonsense or mysticism, but somewhere inside the game there was an own pair of coordinates, which was changed in a way that was not clear to me and was not controlled directly.
')
DirectInput and all-all
On Sunday I woke up demotivated, but still with reliable. Today I wanted to try to repeat everything that comes from a real mouse, but with touchscreen data. I hooked up the rodent and started tracking its actions, and then it turned out that mouse actions do not go through my window procedure at all. Calling myself an ass, not knowing the realities of the games, I dug into Google and found what confused me: Often games get information about the mouse either through DirectInput or in raw form, bypassing the Window Message Queue. Touchscreen and stylus events are the exception - they go through the message queue and somewhere in the depths of DefWindowProc turn into mouse actions. Accordingly, WM_MOUSEMOVE and others like it may be absent altogether (and this is what happens for the mouse) and the attempt to send them, substitution, etc., does not affect the game in any way. Literally, two-thirds of my experiments were simply ignored by the game, and the rest were in conflict with DefWindowProc. Moreover, WM_TOUCH was sent only for compatibility with Windows 7 programs, and the main touch events in Windows 8 are already considered WM_POINTER *.
Accident or fishing?
At this stage, I already knew what I needed and saw the light at the end of the tunnel - I will not allow DefWindowProc to handle touchscreen events at all and will do everything myself. Emotional uplifting did its job, and at some point suddenly the touchscreen began to put the cursor exactly at the place of depression. It was strange, because the interception module was not yet ready. The search for the dichotomy of the desired area (we turn off half the program and look at the behavior, then either return back or turn off half the remaining code) showed that I simultaneously caused
RegisterTouchWindow(hWnd, TWF_WANTPALM)
and
SetProp(hWnd, "MicrosoftTabletPenServiceProperty", (HANDLE)1)
* Despite the idiotic appearance and meaning of the last command, it is quite correct and documented , albeit for the Tablet PC of the 2003 year.Calling these two methods leads to the fact that in WM_TOUCH we get only one coordinate at a time, and the internals of DefWindowProc generate relatively correct coordinates. But the point is that usually WM_TOUCH is not sent immediately when pressed, but accumulates data for the “press and hold” feature. That is characteristic, colleagues already once
faced a similar situation:
At the end of four days of futility, I gave up and did two things. First, I’m looking at what I’m not really using the word although fuck ’.
(...)
Thankfully, my surprise was actually answered by my forum post. I’m on the screen, and I’m not sure what I’ve wanted to write on. TabletPC disables press and hold for your window.
(...)
It has been the case for the TabletPC SDK. Or, “press and hold” was (since it would have been a funeral)
It was still not a complete solution, but still a huge progress! Actually, it was in this mode that Fallout 2 became playable, although it rarely loses the coincidence of virtual and real coordinates - the cursor shifts to the side. This is solved right in the game by dragging the cursor to a place where it can no longer move.
Full implementation
Then everything was a matter of technology - when DefWindowProc stopped interfering and WM_TOUCH / WP_POINTER stopped sticking together, I began to process them and send events via mouse_event; the behavior of the cursor has become predictable. The only thing that could not be solved was the one-time work of the mouse and touchscreen. The mouse does not generate any WM_ messages at all, therefore we cannot find out its exact coordinates, and GetCursorPos only gives what we write there. After intercepting touchscreen events, the values ​​of GetCursorPos stopped changing at all, although the cursor was moving with the mouse and so. For Arcanum, the right button is still critical, so it was hung up by pressing with two fingers. To exit the menu and save, you need ESC, it took root on a gesture of 3 or more fingers. I decided to stop at this today, cleaned up the code, uploaded it on
github and ... instead of playing, sat down to write an article on Habr;)
For skeptics and nostalgic The touchscreen was chosen spell, used, and then with the right "click" out of the caste mode |
The introductory videos are skipped by tap, the character is created and the inventory is also opened with a touchscreen (on the "clean" version it is not possible) |
Bugs and flaws
Support
Anyone wishing to express their gratitude can not bother and say "thank you". You can even out loud and in front of the monitor, do not necessarily write about it. Those who wish to call me necrophilia or something else, I advise you too to say it out loud several times and not to increase the entropy of the world Internet. The project at the same time will not interfere with testing for more old games, solving problems with Fallout,
upgrading to a newer IDE , fixes, a wiki page, etc. I don’t mind the specific game patches. Fork, do, then smogim.
UPD: At lunchtime, I updated the project to VS 2012, added auto-disabling Windows 8 charms, support for the button on the stylus. At the same time I tried to work with ASI Loader, but something did not work out. A strange crash was also captured at startup and a hack fix was made for it.
UPD 2: As it turned out, the library worked incorrectly if the non-default mouse speed was set or “Extended pointer accuracy” was turned on. I do not see a complete solution to this problem yet, because the DLL at startup turns off these items as incompatible with touch controls. If anyone is interested, then “Extended accuracy” is someone's stupid joke, which doubles the mouse offset on any axis, if its value is more than 6 pixels and quadruples if more than 10. That is, By moving the mouse 7 pixels to the left and 12 up, with this mode we will get an offset of 14 pixels to the left and 48 up. I do not see any increased accuracy in this; moreover, limits 6 and 10 were set somewhere inside the system a decade ago and cannot be changed by the user.