Important screensaver tip for Windows emulator authors
Moderator: Moderators
Important screensaver tip for Windows emulator authors
This is something I have seen happen over the past, oh I dunno, 10+ years in all sorts of games (many commercial and from very large companies): the games do not inhibit screen savers or monitor blanking (power-off) from occurring while the emulator/game is running.
The solution for this is incredibly simple and takes virtually zero CPU time. Some emulators like Nestopia implement this methodology. I thought I'd document it for those writing Win32-based emulators so that they know how simple it is to do this and what the proper methodology is. I recently had to describe it over on the Steam forums for the recent Angry Video Game Nerd game that came out yesterday:
http://steamcommunity.com/app/237740/di ... 769796832/
I hope this benefits folks here. Please implement this when doing a Windows-based emulator. If your programming language or environment doesn't give you this degree of control, then start hounding on the language or framework authors to provide it. Every Win32 application has a WndProc equivalent, so every Win32 application should be able to accomplish this -- just that many crappy frameworks and abstract garbage don't give you this degree of control, and for no justified reason.
If you need further workarounds I can provide one (it does involve changing the power scheme, I can provide code for such -- but I STRONGLY do not recommend it, as it makes changes to the users' profile without their consent, and if your game/program crashes it can leave the profile indefinitely with no blanking/screen saver configured, which is bad. The method I described in the above URL is indeed the best/proper solution).
HTH.
The solution for this is incredibly simple and takes virtually zero CPU time. Some emulators like Nestopia implement this methodology. I thought I'd document it for those writing Win32-based emulators so that they know how simple it is to do this and what the proper methodology is. I recently had to describe it over on the Steam forums for the recent Angry Video Game Nerd game that came out yesterday:
http://steamcommunity.com/app/237740/di ... 769796832/
I hope this benefits folks here. Please implement this when doing a Windows-based emulator. If your programming language or environment doesn't give you this degree of control, then start hounding on the language or framework authors to provide it. Every Win32 application has a WndProc equivalent, so every Win32 application should be able to accomplish this -- just that many crappy frameworks and abstract garbage don't give you this degree of control, and for no justified reason.
If you need further workarounds I can provide one (it does involve changing the power scheme, I can provide code for such -- but I STRONGLY do not recommend it, as it makes changes to the users' profile without their consent, and if your game/program crashes it can leave the profile indefinitely with no blanking/screen saver configured, which is bad. The method I described in the above URL is indeed the best/proper solution).
HTH.
Re: An important tip for Windows emulator authors
In case that post gets deleted (or paywalled or moved to another URL with no redirect), may I reproduce that post somewhere?
Re: An important tip for Windows emulator authors
Sure thing. I wasn't sure what page on the Wiki would be most relevant for it, sadly. :(
And if needed I can add the code for the power profile adjustment I mentioned (though again, really should not do this).
And if needed I can add the code for the power profile adjustment I mentioned (though again, really should not do this).
Re: An important tip for Windows emulator authors
I really think the problem is that Windows doesn't treat gamepad input like it does keyboard and mouse input. It should also restart the screen saver counter, which would solve this problem for everyone. (And sure, ignore small analog movements since low-quality gamepads can stutter with no actual user input. Or even just ignore analog axes entirely.)
I never like 'solutions' that require every individual piece of software in a given category to implement the 'fix'. We should be putting the pressure on OS vendors to do the right thing as well.
That said, I'll share the Linux equivalent. Here, you want to use XTestFakeKeyEvent, and call it every few seconds. Nothing else is reliable. Sample code:
I never like 'solutions' that require every individual piece of software in a given category to implement the 'fix'. We should be putting the pressure on OS vendors to do the right thing as well.
That said, I'll share the Linux equivalent. Here, you want to use XTestFakeKeyEvent, and call it every few seconds. Nothing else is reliable. Sample code:
Code: Select all
//call this once during each frame
//preferably only if your emulator has window focus
void supressScreenSaver() {
//XSetScreenSaver(timeout = 0) does not work
//XResetScreenSaver() does not work
//XScreenSaverSuspend() does not work
//DPMSDisable() does not work
//XSendEvent(KeyPressMask) does not work
//xdg-screensaver often isn't available
//use XTest extension to send fake keypress every few seconds.
//keycode of 255 does not map to any actual key,
//but it will block screensaver and power management.
Display *display = XOpenDisplay(0);
XTestFakeKeyEvent(display, 255, True, 0);
XTestFakeKeyEvent(display, 255, False, 0);
XCloseDisplay(display);
}
Re: An important tip for Windows emulator authors
Changing a user's settings without asking first, especially something like power settings, is never, ever acceptable IMO. If you include code to adjust these settings, the need to make the behavior opt-in can't be understated.koitsu wrote:And if needed I can add the code for the power profile adjustment I mentioned (though again, really should not do this).
Re: An important tip for Windows emulator authors
In some cases it might be a cross-platform library such as SDL or whatever, so the programmer may not want to normally to include such things (unless the library used already has such a function; even then there ought to be a way to turn off the suppress screen saver function since it isn't always wanted).
(Free Hero Mesh - FOSS puzzle game engine)
- rainwarrior
- Posts: 8735
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: An important tip for Windows emulator authors
SDL has SDL_DisableScreensaver() which does what koitsu suggested for Windows. (I dunno what it does on other platforms.)
Re: An important tip for Windows emulator authors
Good link, i tought about this issue and were going to google it. Thanks!!
ANes
Re: An important tip for Windows emulator authors
There's actually two minor flaws in the sample code you posted on the Steam forums:
1. wParam needs to be ANDed with 0xFFF0 first.
There's also the minor detail that if you've got Windows set to lock the workstation when the screen saver kicks in, it will ignore your program's request to not do so.
1. wParam needs to be ANDed with 0xFFF0 first.
2. The checks should only be done when emulation is actually active, otherwise if you leave emulation paused and walk away it'll never go into power saving mode.MSDN wrote:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
There's also the minor detail that if you've got Windows set to lock the workstation when the screen saver kicks in, it will ignore your program's request to not do so.
Thus, the correct code should probably look something like this (copy/pasted from Nintendulator):MSDN wrote:If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification—even if fails to pass it to DefWindowProc.
Code: Select all
case WM_SYSCOMMAND:
// disallow screen saver while emulating (doesn't work if password protected)
if (running && (((wParam & 0xFFF0) == SC_SCREENSAVE) || ((wParam & 0xFFF0) == SC_MONITORPOWER)))
return 0;
// otherwise, proceed to DefWindowProc
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: Important screensaver tip for Windows emulator authors
The following works even when Windows is set to lock the workstation:
Set a timer somewhere
And in your WindowProc
I suppose there is some risk that your choice of keycode conflicts with some other program that's using it, but I haven't had or heard of any problems so far.
Set a timer somewhere
Code: Select all
SetTimer(hWnd, 0, 30000, NULL);
Code: Select all
case WM_TIMER:
switch (wParam)
{
case 0:
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wVk = 0x88; //Unassigned virtual keycode
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
return 0;
}
get nemulator
http://nemulator.com
http://nemulator.com
Re: Important screensaver tip for Windows emulator authors
So you reset the timer by periodically sending a keypress through the Windows event loop. I can think of a couple improvements. One would be to send the keypress only when the emulator is focused, ensuring that the key code won't conflict. Another would be to send the keypress whenever a button is pressed on the joystick, keeping the screensaver working as expected should the user walk away from a paused game. But then I don't program in Win32 currently; are there problems with my suggestion?
Re: Important screensaver tip for Windows emulator authors
Nope. All of these are fine suggestions.tepples wrote:So you reset the timer by periodically sending a keypress through the Windows event loop. I can think of a couple improvements. One would be to send the keypress only when the emulator is focused, ensuring that the key code won't conflict. Another would be to send the keypress whenever a button is pressed on the joystick, keeping the screensaver working as expected should the user walk away from a paused game. But then I don't program in Win32 currently; are there problems with my suggestion?
re: SendInput focus. I think my concern was with applications that listen to all keyboard events (e.g., hotkey type stuff). Last time I did any testing with this was probably ~8 years ago, so I really have no idea.
get nemulator
http://nemulator.com
http://nemulator.com
Re: Important screensaver tip for Windows emulator authors
Then send something innocent like the down arrow or the spacebar or the X key, as that's what players would already be pressing when playing an NES game with a keyboard.
In any case, Windows Vista didn't exist 8 years ago, and your product requires it or newer.
In any case, Windows Vista didn't exist 8 years ago, and your product requires it or newer.
Re: Important screensaver tip for Windows emulator authors
So every x seconds, the emulator would 'see' you pressing down. How does that make sense?tepples wrote:Then send something innocent like the down arrow or the spacebar or the X key, as that's what players would already be pressing when playing an NES game with a keyboard.
In it's current incarnation, sure. Prior to 2.0, it ran on XP. But I guess you would know better.tepples wrote:In any case, Windows Vista didn't exist 8 years ago, and your product requires it or newer.
get nemulator
http://nemulator.com
http://nemulator.com
Re: Important screensaver tip for Windows emulator authors
The window system would see a key being pressed, but the emulator would ignore it. Perhaps use a key that happens not to be bound to a game button.James wrote:So every x seconds, the emulator would 'see' you pressing down. How does that make sense?tepples wrote:Then send something innocent like the down arrow or the spacebar or the X key, as that's what players would already be pressing when playing an NES game with a keyboard.