Code Monkey home page Code Monkey logo

sftscrollbugfixer's Introduction

Age of Empires II scrollbug fix

TL;DR

  • Download age2_x1_fixed.tar.gz from the Releases page
  • Unpack it into your age2_x1 folder
  • From now on launch the game with age2_x1_fixed.exe instead of age2_x1.exe
  • No patching of the game binary is required
  • Black magic now removes all of the suffering
  • ?????
  • PROFIT
  • If you want to use the fix with a different version of the game, just modify the .ini file accordingly.

What is the scrollbug?

Sometimes when you tab out of the game, after tabbing back in the game will be stuck in a state where it is constantly scrolling in some direction.

This makes the game unplayable and requires a restart of the game. This is especially annoying in multiplayer games.

The scrollbug happens mostly when running the game in Wine, but has supposedly also been observed on Windows.

How do I reliably reproduce the scrollbug?

  • Use Wine. I don't know if these steps work on Windows.
  • Start a game, e.g. a standard single-player random map game
  • Hold the left-arrow key for 3 seconds
  • Release the left-arrow key
  • Wait for one second
  • Tab out of the game
  • Wait for one second
  • Tab back into the game
  • Congratulations; you now have a scroll bug

Why is there a scrollbug?

Age of Empires II uses the GetKeyboardState() and GetKeyState() Win32 API functions to determine whether one of the scrolling keys is pressed.

In the result of these functions, the key stats are reported as a single byte.

According to the MSDN documentation,

  • Bit 7 of the byte says whether the key is currently pressed
  • Bit 0 of the byte toggles each time the key is pressed
  • All other bits are not documented

Age of Empires II wants to check whether the key is currently pressed. To do this it checks whether the byte value is >= 1 instead of checking if Bit 7 is set (& 0x80).

This works as long as bits 1..6 are zero.

Unfortunately, wine seems to use bit 2 to provide some other metadata, obviously related to tabbing out of the window, so it doesn't guarantee that bits 1..6 are always 0.

Windows also seems to sometimes use some of the other bits.

Which versions of Age of Empires II have the scrollbug?

Every single one, i.e.:

  • AoK
  • AoC
  • Forgotten Empires
  • UserPatch
  • AoE2:HD
  • AoE2:DE

How does this fix work?

This uses the Microsoft Research Detours library to inject replacements of GetKeyState() and GetKeyboardState() into the running Age of Empires II binary.

The replacement functions mask out bits 1..6 in the results.

The fix consists of two binaries:

  • age2_x1_fixed.exe reads the configuration from age2_x1_fixed.ini and calls the exe that is specified in the ini file with the injector dll file that is specified in the ini file.
  • fix_scrollbug32.dll injects fixed versions of GetKeyState() and GetKeyboardState() into any 32-bit Windows executable it is used with.

How do I build this fix?

  • Use Windows (please, somebody port this to winegcc or mingw or something that works on Linux)
  • Install Visual C++ Build Tools 2015
  • Get this source code (duh.)
  • Get detours.lib and detours.h, e.g. by building the Detours library from source by invoking nmake, or by downloading the binaries from this Github repo. Place these two files in a subfolder detours/ of this source code
  • Call build.bat
  • You will now have a whole bunch of garbage files, plus
    • fix_scrollbug32.dll
    • dll_inject.exe
    • dll_inject.ini

How do I use this fix?

dll_inject.exe can be renamed to whatever name. It is recommended to rename it to {name_of_the_exe_you_want_to_fix}_fixed.exe.

When launched, dll_inject.exe will

  • open the .ini file with the same name
  • in that .ini file in the section [dll_inject], read the keys exe_file and dll_file
  • launch the specified exe file and inject the specified dll file
  • wait until the exe file has finished

If you use the pre-compiled and pre-configured age2_x1_fixed.exe, age2_x1_fixed.ini, fix_scrollbug32.dll you can just place them in the age2_x1 folder and launch age2_x1_fixed.exe instead of age2_x1.exe.

Credits

Thanks to Sulix who posted an analysis of the bug on the Steam Forum.

Thanks to Microsoft Research for the Detours library and the excellent accompanying samples. dll_inject.cpp was derived directly from the withdll example, and fix_scrollbug.cpp was derived by modifying one of the other examples.

sftscrollbugfixer's People

Contributors

mic-e avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sftscrollbugfixer's Issues

not working with AoE2DE_s.exe (Age of Empires II: Definitive Edition

Hello,

I tried your fix with AoE2DE and it won't work.

Steps made to make it work with Steam:
Working folder: ~/.steam/steam/steamapps/common/AoE2DE
Rename AoE2DE_s.exe to AoE2DE_s-ORIG.exe
Rename age2_x1_fixed.exe and .ini to AoE2DE_s.exe and <...>.ini
Adjust exe_file=AoE2DE_s-ORIG.exe inside AoE2DE_s.ini
Go to Steam Library, and set launch options for Age of Empires II: Definitive Edition:
/c ~/.steam/steam/steamapps/common/AoE2DE/AoE2DE_s.exe
(that way, steam won't try to update the game because of changed exe file).
It runs your executable and then starts the game. But the bug is still there.

Wine Debbuger says:

ini file Z:\home\thiago.steam\steam\steamapps\common\AoE2DE\AoE2D
E_s.ini
exe file AoE2DE_s-ORIG.exe
dll file fix_scrollbug32.dll
start command AoE2DE_s-ORIG.exe /c /home/thiago/.steam/steam/steamapps/
common/AoE2DE/AoE2DE_s.exe
start cwd Z:\home\thiago.steam\steam\steamapps\common\AoE2DE
dll file [full path] Z:\home\thiago.steam\steam\steamapps\common\AoE2DE\fix_s
crollbug32.dll
exe file [full path] Z:\home\thiago.steam\steam\steamapps\common\AoE2DE\AoE2D
E_s-ORIG.exe
Unable to read VR Path Registry from C:\users\steamuser\Local Settings\Applicati
on Data\openvr\openvrpaths.vrpath
Setting breakpad minidump AppID = 813780
Steam_SetMinidumpSteamID: Caching Steam ID: 76561198003414423 [API loaded no]
Unable to read VR Path Registry from C:\users\steamuser\Local Settings\Applicati
on Data\openvr\openvrpaths.vrpath
Unable to read VR Path Registry from C:\users\steamuser\Local Settings\Applicati
on Data\openvr\openvrpaths.vrpath
2020/03/29 22:57:20 : inf - BT! - SockInit: SOCK_FD_SET_SIZE = 8192
2020/03/29 22:57:20 : inf - WRN - SockConnect: failed (error 10013 - ATLAS_NOTINTABLE: Undefined error.).
Process of pid=006f has terminated
No process loaded, cannot execute 'echo Modules:'
Cannot get info on module while no process is loaded
No process loaded, cannot execute 'echo Threads:'
process tid prio (all id:s are in hex)
00000008 steam.exe
0000002a 0
00000009 0
0000000c services.exe
00000026 0
00000020 0
00000018 0
00000011 0
0000000e 0
0000000d 0
0000000f plugplay.exe
00000015 0
00000014 0
00000010 0
00000016 winedevice.exe
0000001d 0
0000001c 0
0000001b 0
0000001a 0
00000019 0
00000017 0
0000001e winedevice.exe
00000023 0
00000022 0
00000021 0
0000001f 0
00000024 winedevice.exe
00000029 0
00000028 0
00000027 0
00000025 0
0000002b explorer.exe
00000031 0
00000030 0
0000002d 0
0000002c 0
00000034 AoE2DE_s.exe
00000035 0
00000036 wineconsole.exe
00000037 0
00000038 AoE2DE_s-ORIG.exe
00000075 0
00000071 0
0000006e 0
0000006d 0
0000006c 0
0000006b 0
0000005e 0
0000005d 0
0000005c 0
0000005b 0
0000005a -2
00000059 -2
00000058 -2
00000057 -2
00000056 -2
00000055 0
00000054 0
00000053 0
00000049 0
00000048 0
00000047 0
00000046 0
00000045 0
00000044 0
00000043 0
00000040 0
0000003f 0
0000003e 0
0000003d 0
0000003c 0
00000039 0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.