Back to Home

Arcanum and Fallout 2 with touch screen and stylus in Windows 8

games · windows 8 · touch · mouse · touchscreen · visual c ++ · visual studio 6.0

Arcanum and Fallout 2 with touch screen and stylus in Windows 8

    Somehow it turned out that I got a Windows 8 tablet. Not a very successful model - bulky 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 the GOG and Steam sales, I planned to somehow sit down with this tablet and replay everything that is possible and impossible. But somehow there was not enough time and mood, and even trial runs showed that you need to play with the mouse - the cursor from the touch screen was running away to no one knew where, and right-clicking with a long press would be frankly uncomfortable. The tablet dusted for half a year in the corner until the recent Fallout distribution from GOG and this distribution pushed me to action. Friday evening began, the tablet got a USB mouse, and I got comfortable on the couch and started the list from the very top - with Arcanum.
    After half an hour of creating the character (and this is a very important and responsible matter!), The left hand hardly held the device, and the right wrist began to pull suspiciously, hinting at the tunnel syndrome and other joys of an uncomfortable grip. Remembering not a good word for the developers of a certain ergonomic folding mouse, I climbed to look for drivers, patches, or at least something else to play from the touchscreen or at least the stylus.
    No patches were found. The only similar driver was paid and without trial mode. And at that moment an idiotic thought came to my mind (I understand now!) The thought - “after all, some WM_TOUCH will surely come and it will be incorrectly converted to WM_MOUSEMOVE” ... Running ahead, Arcanum now completely controls my touchscreen, however, the weekend is over and more sleepy than play.

    For the impatient
    The project is available on github , there are sources 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 simulates 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-clicking does not work there, the cursor occasionally shifts, but this can be fixed by dragging it to the lower left corner of the screen.


    Visual studio 6.0


    Somehow it turned out that I was sick with hooks, patches and injections under Win32 a dozen years ago and then with great pleasure closed this page in my life. And now, dreaming of a “half an hour to play and then play”, I took out an old hard drive, wrote off a couple of projects and my favorite tool - VS98, aka 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 if 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 and works fine under wine on my working machine.
    Cleaning up old projects from tin like IAT spoofing was delayed, but after a couple of hours I implemented my module into the game and could track its message flow (subclassing through 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. This Friday night ended and I postponed the continuation in the morning.

    WM_TOUCH


    In the morning I ran a couple of articles about working with the touchscreen and sat down to catch WM_TOUCH. An excellent message, it comes regularly, though it contains ten or two clicks in one block. It was interesting that the coordinates came to the game correctly - they exactly corresponded to the place of clicking on the screen. This didn’t seem to matter, because I began to generate WM_MOUSEMOVE with every event. The result surprised me - nothing has changed. Nothing at all. Replaced WM_MOUSEMOVE with SetCursorPos and still saw the result - the crawl of the cursor became noticeably less chaotic. It seemed that the thing was in the hat - it was only necessaryunderstand what is going wrong and why the cursor shifts every time ... Only when it got dark outside, did I understand that something went wrong :) All logical and non-logical methods, formulas, coordinate corrections, witchcraft with mouse_event, SendInput, cancellation of certain events - in no case was I able to make the cursor move to the place of clicking. It seemed nonsense or mysticism, but somewhere inside the game there was a pair of coordinates that changed in a way I did not understand and was not controlled directly.

    DirectInput and all-all-all


    On Sunday, I woke up demotivated, but still reliable. Today I wanted to try to repeat everything that comes from a real mouse, but with touchscreen data. I plugged in a rodent and started tracking its actions, and then it turned out that the mouse actions did not go through my window procedure at all. Calling myself a donkey that does not know the realities of games, I dug into Google and discovered what was confusing for me: often games receive information about the mouse either through DirectInput or in raw form, bypassing the Window Message Queue. Events of the touchscreen and stylus are just an exception - they go through the message queue and somewhere in the bowels of DefWindowProc turn into actions with the mouse. Accordingly, WM_MOUSEMOVE, and others like it, may be absent altogether (and this happens for the mouse) and an attempt to send them, replace them, etc. does not affect the game. 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 WM_POINTER * is already considered the main touch events in Windows 8.

    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 let DefWindowProc process touchscreen events at all and I will do everything myself. The emotional upsurge did its job and at some point, unexpectedly, the touchscreen began to place the cursor exactly at the place of pressing. It was strange, because the interception module was not yet ready. A dichotomy search for the desired area (we turn off half of the program and look at the behavior, then either return it back or turn off half of the remaining code) showed that I simultaneously
    RegisterTouchWindow(hWnd, TWF_WANTPALM)
    and
    SetProp(hWnd, "MicrosoftTabletPenServiceProperty", (HANDLE)1);

    * Despite the idiotic look and meaning of the last command, it is quite correct and documented , albeit for the 2003 Tablet PC.
    Calling these two methods leads to the fact that in WM_TOUCH we get only one coordinate at a time, and the DefWindowProc internals generate relatively correct coordinates. But the fact is that usually WM_TOUCH is not sent immediately when pressed, but accumulates data for the “press and hold” feature. What 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 posted a message on the MSDN forums asking "what the fuck", although I did not actually use the word "fuck" in the post because I thought it might trigger an automatic rejection.
    (...)
    Thankfully, a few days later, to my surprise, someone actually answered my forum post. In it, they referred me to a technical article written in 2003 that showed how to do exactly what I wanted: instead of messing with the TabletPC API at all, you just set a secret global text atom on your window, and poof! TabletPC disables press and hold for your window.
    (...)
    So somehow, in all their COMness, with multiple libraries and hundreds of GUIDs and pages and pages of class documentation, the TabletPC SDK had failed to include a define for, or even a mention of the existence of, this special atom. Or what "press and hold" was (since it would have been really helpful to know that term for searching before I started - I might have been able to find the secret technical article that way).

    This was not a complete solution, but still huge progress! Actually, it was in this mode that Fallout 2 became playable, although it occasionally 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 already a technical matter - when DefWindowProc stopped interfering and WM_TOUCH / WP_POINTER stopped gluing, I began to process them and send events via mouse_event; cursor behavior has become predictable. The only thing that could not be solved was the one-time operation of the mouse and touchscreen. The mouse does not generate WM_ messages at all, therefore we cannot find out its exact coordinates, and GetCursorPos gives only what we ourselves write there. After capturing touchscreen events, the values ​​of GetCursorPos generally ceased to change, although the cursor moved with the mouse and the touch. For Arcanum, the right button is still critical, so I hung it with two fingers. To exit the menu and save, you need ESC, it has taken root on a gesture of 3 or more fingers. On this I decided today and stop, cleaned the code, uploaded to github and ... instead of playing, I sat down to write an article on Habr;)

    For skeptics and nostalgic

    The spell was selected with a touchscreen, used, and then with the right "click" left the cast mode
    Introductory videos are skipped by tap, the character is created and the inventory is also opened with a touchscreen (this is not possible on the “clean” version)



    Bugs and flaws


    • I've already written a couple of times, but I’ll duplicate it: if you move the mouse, the cursor will go astray, you only need to play with the wheelbarrow. The cursor can be pulled into the corner of the screen and then pulled out from there by the touch, this restores the synchronization of coordinates
    • In Fallout 2, intercepting WindowProc crashes the game after a while. I’ll figure it out in future versions, but for now you can play without it: two entry points have been made in the project - with interception of WM messages and without it. Unfortunately, the buttons in the game are small and it’s not convenient to press them with a finger, the stylus works better.
    • The hook for creating new windows works for several seconds while the game starts. If at this time some other program starts, the DLL will be loaded into its address space. As a result, it cannot be deleted until reboot. Not critical, and the DLL can be renamed. During debugging, I accumulated hundreds of one and a half such renamed ones.
    • Windows 8 is rich in wretched fashion gestures, some of which interfere with playing. They can be turned off programmatically, but for this you need to compile in something newer than VS 6.0. In the meantime, you can disable these gestures in the registry:
      [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ImmersiveShell\EdgeUI]
      "DisabledEdges"=dword:0000000f
      - implemented
    • The code was written by a bearded dinosaur in the IDE of '98. Well, please, panov. It can also crash, you know?
    • The DLL turned out to be rather large (48kb), but anyway some antiviruses can do it - there are injections, global hooks and, in general, interference with the system!


    Support


    Everyone who wishes to express their gratitude may not bother and say “thank you”. You can even aloud in front of the monitor, it is not necessary to write about it. If you want to call me a necrophile or something else, I also advise you to say it out loud several times and not increase the entropy of the world’s Internet. The project at the same time will not hurt testing on more old games, solving problems with Fallout, upgrading to a newer IDE , fixes, a wiki page, etc. I don’t mind patches for specific games. Fork, do, then obsess.

    UPD: At lunchtime, I updated the project to VS 2012, added auto-shutdown of Windows 8 charms, button support on the stylus. At the same time I tried to work with ASI Loader, but something did not work out. It also caught a strange crash at startup and made a hack fix for it.

    UPD 2: As it turned out, the library was not working correctly if the mouse had a non-default speed or the "Advanced pointer accuracy" was enabled. I don’t see a full solution to this problem yet, because the DLL turns off these items at startup, as they are not compatible with touch control. If anyone is interested, then “Advanced Precision” is someone’s stupid joke that doubles the mouse offset on any axis if its value is more than 6 pixels and quadruples if it is more than 10. That is by moving the mouse 7 pixels to the left and 12 up, with this mode we get an offset of 14 pixels to the left and 48 up. I do not see any increased accuracy in this, moreover, the limits of 6 and 10 are laid down somewhere inside the system a decade ago and cannot be changed by the user.

    Read Next