protonscr

Kernel32::GetSystemPowerStatus Incompatibility with Steam Deck

wineclosed
ValveSoftware/wine#146 · opened 2022-05-07 by KazWolfe · updated 2023-05-17 · 7 comments · github
KKazWolfe 2022-05-07 github

Note: This is an upstream bug reported to Wine as well ([#52831](https://bugs.winehq.org/show_bug.cgi?id=52831)). I am reporting this Issue here as well in hopes of requesting Valve's assistance as this bug affects the Steam Deck particularly. Sample code and possible root cause analysis are both available in the ticket on Wine's side.


Currently, the Steam Deck appears to have an incompatibility with Wine 7.6's implementation of Kernel32's GetSystemPowerStatus API call. The Steam Deck exposes its battery information at BAT1 and its AC line status at ACAD in /sys/class/power_supply:

(deck@okami ~)$ ls /sys/class/power_supply/
ACAD  BAT1

Wine (and Proton, for that matter) only read battery information from /sys/class/power_supply/AC and /sys/class/power_supply/BAT0. This causes requests to GetSystemPowerStatus to return invalid or incomplete data.

Certain games make use of this API to determine if the device is running on battery to display heads-up notifications to users or to change graphical/power settings on-the-fly (e.g. in response to low power events to preserve playtime). While titles that do this still (mostly) work under the Deck, this is a minor compatibility flaw with Wine/Proton that just happens to manifest most severely on the Deck given its battery-driven nature. Games that leverage battery-aware features would benefit from having this state exposed to them, especially on handheld gaming devices.

Aaeikum 2022-05-23 github

Thanks for the report. Do you know of any games that use these APIs, so we can validate a fix?

KKazWolfe 2022-05-23 github

Specific games, unfortunately no other than "they exist" (and speculation that they use this feature for those modes - I haven't actually disassembled games to verify this API's use). This one came up as I was working on modding a game to add a battery life indicator. The following should serve as an MCVE, however:

#include <iostream>
#include <Windows.h>

int main() {
    SYSTEM_POWER_STATUS sps;

    if (!GetSystemPowerStatus(&sps)) return 1;

    std::cout << "== BATTERY STATUS ==" << std::endl;
    std::cout << "Battery Present    : " << (sps.BatteryFlag < 100) << std::endl;
    std::cout << "AC Line Status     : " << ((int) sps.ACLineStatus) << std::endl;
    std::cout << "Battery Flag       : " << ((int) sps.BatteryFlag) << std::endl;
    std::cout << "Battery Charge     : " << ((int) sps.BatteryLifePercent) << "%" << std::endl;
    std::cout << "Battery Life Time  : " << ((int) sps.BatteryLifeTime) << " sec" << std::endl;
    std::cout << "Battery Full Time  : " << ((int) sps.BatteryFullLifeTime) << " sec" << std::endl;

    return 0;
}

If an actual game that uses this feature is required, I know Garry's Mod exposes battery information (though this may be through SteamAPI instead). I've heard that Crysis, GRID 2, Shadow of Mordor, and Football Manager support this behavior (or indicators) as well, but have not been able to verify that they specifically call GetSystemPowerStatus.

SDL, however, will specifically call GetSystemPowerStatus on Windows builds: https://github.com/libsdl-org/SDL/blob/main/src/power/windows/SDL_syspower.c

Aaeikum 2022-05-24 github

Thanks for the info. I've filed an internal bug for a dev to investigate the games you've mentioned. If you do find any games that seem to have bad battery info, please do let us know. We'll keep you updated on what we find.

Aaeikum 2022-05-26 github

Turns out a Wine contributor is already working on this. You could try out his work and provide feedback on his upstream MR, see https://gitlab.winehq.org/wine/wine/-/merge_requests/134

KKazWolfe 2022-06-16 github

I just got word that this was fixed upstream as of commit 89ec378, currently present on their master branch.

I'm unsure how/when/why Valve re-syncs this repo with upstream (so I won't do anything with this ticket), but the code is now there and ready to go. Thank you all for your help with this!

Ggupy1111 2023-05-17 github

GOD BLESS YOU

Kkisak-valve maintainer 2023-05-17 github

Closing as fixed by the upstream commit in Proton 8.0 (https://github.com/ValveSoftware/wine/commit/89ec37871f6093d8336f636dc967d79579607dd3).

Proton versions

Upstream links