hannesmann / vanillafixes

Client modification for WoW 1.12.1 to eliminate stutter and animation lag
MIT License
132 stars 15 forks source link

Feature request: Override option for default resolutions and refresh rates #27

Open Thorsten42 opened 10 months ago

Thorsten42 commented 10 months ago

Hi,

The 1.12.1 (and Turtle) WoW client sometimes fails to correctly detect the available resolutions and refresh rates. Certain conditions that appear to trigger this behavior include multi-monitor setups or situations where the monitor is not turned on before booting Windows. I'm not entirely sure about the root cause, but I found an explanation on the Turtle WoW Discord that might shed some light on this:

The issue seems to be related to having multiple displays of different resolutions, and when you start your PC, windows will choose one of your displays to be the "first" display in it's list of displays. This "first" display is not related to "make this my main display" in windows and will not change after windows has started, even if turned off. When WoW launches, it checks the available resolutions for the "first" display slot and for some reason, somehow incorrectly cross references them with your actual main display leading to a strange list of very old very small resolutions for me at least.

The primary symptoms of this problem are limited default resolutions (e.g., 800x600, 1024x768, 1280x1024, 1600x120) with a fixed refresh rate of 60Hz. This issue also leads to the overwriting of saved settings and the loss of addon interface positions. If you search for these resolutions (for example in the turtle wow discord), you'll find numerous instances of people encountering this problem, but with no tangible solution.

In my case, turning on the monitor before booting the PC seems to bypass this problem. I genuinely appreciate your efforts in addressing the shortcomings of the 1.12.1 client. I'd be grateful if you could explore the possibility of adding an option for overriding the default resolutions and refresh rates. This would allow the default entry to be something like 3840x2160@144Hz instead of 800x600@60Hz.

Many thanks in advance!

hannesmann commented 9 months ago

Hmm, I don't think overriding the default entry is a good idea. Instead the bug should be fixed properly so that WoW isn't incorrectly comparing two displays.

I've never had this issue myself (and I don't play WoW anymore) but if someone wants to look into fixing the bug it shouldn't be too hard to override the display WoW is looking at. It's probably getting the primary monitor from MonitorFromWindow or MonitorFromPoint and the "incorrect" display would be from EnumDisplayMonitors.

Thorsten42 commented 9 months ago

Thanks for your reply and your ideas to fix the problem. Do you happen to have some tutorials on developing such hooks which closely match the way vanillafixes works? Could you also possibly provide me with a brief description of the necessary steps? I know a little bit C and would try to investigate it.

hannesmann commented 9 months ago

VanillaFixes uses MinHook. Hooks are created in src/dll/dll.c. You can use MH_CreateHook to hook functions in the game and MH_CreateHookApi to hook Windows API functions.

Example:

static BOOL (WINAPI *orig_EnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM) = NULL;

// This needs to match the definition of EnumDisplayMonitors 
// All Windows API functions use the WINAPI calling convention
BOOL WINAPI VfEnumDisplayMonitors(HDC hdc, LPCRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData) 
{
    // Do something here...
    return orig_EnumDisplayMonitors(hdc, lprcClip, lpfnEnum, dwData);
}

...

MH_CreateHookApi(L"user32.dll", "EnumDisplayMonitors", &VfEnumDisplayMonitors, &orig_EnumDisplayMonitors);

The first step would probably be to hook the various display functions (MonitorFromWindow, MonitorFromPoint, EnumDisplayMonitors, IDirect3DDevice9::GetDisplayMode, ...) and see which ones are used by WoW. If the theory is correct that WoW is getting the wrong display from EnumDisplayMonitors, the easiest solution would be to hook that function and return the primary display as the first entry. It could also be useful to launch WoW in OpenGL mode (WoW.exe -opengl) and see if it has the same issue.