LAUNCHER: Faux Fullscreen. Never switch monitor resolutions again!

Started by Trapezoid, Thu 16/05/2013 00:08:04

Previous topic - Next topic

Trapezoid

Since AGS's fullscreen mode can look and act wonky on a some screens, I decided to make a sort of faux-fullscreen launcher with AutoHotkey.

What my script does: First, it changes the game to windowed mode in 2x, 3x, or 4x (whatever will fit, depending on your screen's current resolution.)
It then runs the game atop a black background, so Windows or your desktop are not visible under the game. It also disables the title bar and resize-edges of the game's window.
While the game runs, it checks if the game loses focus from alt-tabbing or whatever, to avoid graphical glitches when you bring it back to focus.

To use:

1. You'll have to install AHK, which you should anyway, because it's infinitely useful.

2. Create an .ahk file in the game's folder containing the code below.

Code: AGS

GameWidth = 320
GameHeight = 200
GameExe = Game.exe
GameCfg = acsetup.cfg
 
scrX = %A_ScreenWidth%
scrY = %A_ScreenHeight%
 
IniWrite, 1, %GameCfg%, misc, windowed
 
if (scrX >= GameWidth*4 and scrY >= GameHeight*4) {
  IniWrite, StdScale4, %GameCfg%, misc, gfxfilter
  }
else if (scrX >= GameWidth*3 and scrY >= GameHeight*3) {
  IniWrite, StdScale3, %GameCfg%, misc, gfxfilter 
  }
else if (scrX >= GameWidth*2 and scrY >= GameHeight*2) {
  IniWrite, StdScale2, %GameCfg%, misc, gfxfilter 
  }
else {
  IniWrite, None, %GameCfg%, misc, gfxfilter 
  }
 
WinHide ahk_class Shell_TrayWnd
WinHide Start ahk_class Button 
 
Gui, -Caption +ToolWindow
Gui, Color, 0
Gui, Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE    
 
Run, %GameExe%, , , OutputVarPID
WinWait, ahk_pid %OutputVarPID%
 
WinSet, Style, -0xC00000, ahk_pid %OutputVarPID%
 
Gui, 2: +AlwaysOnTop -Caption +ToolWindow                                        
Gui, 2: Color, 0            
Gui, 2: Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE   
Sleep, 10
Gui, 2:Destroy
 
WinWaitActive, ahk_pid %OutputVarPID%
MouseMove, %GameWidth% / 2, %GameHeight% / 2
checko = 1
 
While Winexist("ahk_pid" . OutputVarPID)
{
  if !WinActive("ahk_pid" . OutputVarPID) and !WinActive("HSHIDE")
  { 
    if (checko=1)
    {
      WinShow ahk_class Shell_TrayWnd
      WinShow Start ahk_class Button
      checko = 0
    }
  }
  if WinActive("ahk_pid" . OutputVarPID) or WinActive("HSHIDE")
  {
    if (checko=0)
    {
      WinHide ahk_class Shell_TrayWnd
      WinHide Start ahk_class Button 
      Gui, -Caption +ToolWindow                                        
      Gui, Color, 0                                                                               
      Gui, Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE      
      Gui, 2: +AlwaysOnTop -Caption +ToolWindow                                        
      Gui, 2: Color, 0                                                                                 
      Gui, 2: Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE
      WinActivate, ahk_pid %OutputVarPID%
      WinWaitActive, ahk_pid %OutputVarPID%
      Gui, 2:Destroy 
      checko = 1
    }
  }
  IfWinActive, HSHIDE
  {
    WinActivate, ahk_pid %OutputVarPID%
  }
  IfWinNotExist, ahk_pid %OutputVarPID%
  {
  WinShow ahk_class Shell_TrayWnd
  WinShow Start ahk_class Button
  ExitApp
  }    
}
 
WinShow ahk_class Shell_TrayWnd
WinShow Start ahk_class Button
ExitApp


3. Alter the first four lines so that they match the game's native resolution and exe/cfg filenames.
If you want to put the game files in a subfolder (might be a good idea so the launcher is the first thing the user sees) you can do something like "GameExe = gamedata/Game.exe" and "GameCfg = gamedata/acsetup.cfg"

3. If this is just for personal use, you can simply double click the .ahk file and it will run.

4. If you want to create a launcher .exe, run Ahk2Exe.exe in your AutohotKey install's Compiler subfolder. Select the ahk, output exe, pick a custom ico, and Convert!

Hooray!

This is my first AutoHotkey script, I've only tested it on my desktop and laptop computers, single monitor setup, in Windows 7. It only changes the "run in a window" and graphics filter settings in the game's setup, so some other settings might conflict.
Please, let me know if it doesn't work or if I goofed it up somehow!

EDIT: Simplified version taking advantage of Custom Resolution Build.


Dave Gilbert

This is very interesting! And will solve a ton of problems I've been having. Just one question:

Quote
1. You'll have to install AHK, which you should anyway, because it's infinitely useful.

Does the player have to have AHK installed? Or just the game's author? If the player needs to have this installed, than it is no good for a commercial developer since you will have to ask the customers to download other software in order to play the game, which is a no no.

Trapezoid

Nope.
QuoteOnce a script is compiled, it becomes a standalone executable; that is, it can be used even on machines where AutoHotkey is not installed (and such EXEs can be distributed or sold with no restrictions). The compilation process compresses and encrypts all of the following: the script, any files it includes, and any files it has incorporated via the FileInstall command.

Sslaxx

AutoHotKey is licensed under the terms of the GPL.
Stuart "Sslaxx" Moore.


Armageddon

It does have a bit off a problem, since I've yet to add an exit button to my game I had to ctrl+alt+delete and cancel the task. Well that works fine, and then the black stays, and you can't remove it. I had to log out and back in before it went away.

Ali

Ooh! This is very interesting, I look forward to testing it.

Trapezoid

Quote from: Armageddon on Mon 20/05/2013 04:38:28
It does have a bit off a problem, since I've yet to add an exit button to my game I had to ctrl+alt+delete and cancel the task. Well that works fine, and then the black stays, and you can't remove it. I had to log out and back in before it went away.
I'm trying killing the game task with ctrl-alt-delete, and the black background clears normally. Not sure why it's not working with you. Both the "While Winexist" loop and the "IfWinNotExist" should be checking for this. Hmm.
(side note, Alt-X is probably a quicker way to abort a game.)

Trapezoid

It does seem like if I mess around enough with alt-tabbing and the task manager, I can quit the game without the script terminating itself (therefore leaving the black border up, sometimes always-on-top, and with the taskbar stuck invisible.)

Here's the code, revised to be a little less buggy, I hope. I ditched the taskbar-hiding, which isn't so bad if yours is set to auto-hide anyway.
Code: AGS
GameWidth = 320
GameHeight = 200
GameExe = Game.exe
GameCfg = acsetup.cfg
 
scrX = %A_ScreenWidth%
scrY = %A_ScreenHeight%
 
IniWrite, 1, %GameCfg%, misc, windowed
 
if (scrX >= GameWidth*4 and scrY >= GameHeight*4) {
  IniWrite, StdScale4, %GameCfg%, misc, gfxfilter
  }
else if (scrX >= GameWidth*3 and scrY >= GameHeight*3) {
  IniWrite, StdScale3, %GameCfg%, misc, gfxfilter 
  }
else if (scrX >= GameWidth*2 and scrY >= GameHeight*2) {
  IniWrite, StdScale2, %GameCfg%, misc, gfxfilter 
  }
else {
  IniWrite, None, %GameCfg%, misc, gfxfilter 
  }
 
Gui, -Caption +ToolWindow
Gui, Color, 0
Gui, Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE    
 
Run, %GameExe%, , , OutputVarPID
WinWait, ahk_pid %OutputVarPID%
 
WinSet, Style, -0xC00000, ahk_pid %OutputVarPID%
 
Gui, 2: +AlwaysOnTop -Caption +ToolWindow                                        
Gui, 2: Color, 0            
Gui, 2: Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE   
Sleep, 10
Gui, 2:Destroy
 
WinWaitActive, ahk_pid %OutputVarPID%
MouseMove, %GameWidth% / 2, %GameHeight% / 2
checko = 1
 
While WinExist("ahk_pid" . OutputVarPID)
{
  if !WinActive("ahk_pid" . OutputVarPID) and !WinActive("HSHIDE")
  { 
    if (checko=1)
    {
      checko = 0
    }
  }
  if WinActive("ahk_pid" . OutputVarPID)
  {
    if (checko=0)
    {
      Gui, -Caption +ToolWindow                                        
      Gui, Color, 0                                                                               
      Gui, Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE      
      Gui, 2: +AlwaysOnTop -Caption +ToolWindow                                        
      Gui, 2: Color, 0                                                                                 
      Gui, 2: Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE
      WinActivate, ahk_pid %OutputVarPID%
      While !WinActive("ahk_pid" . OutputVarPID) and WinExist("ahk_pid" . OutputVarPID) and !WinExist("Adventure Game Studio", "Abort key pressed")
      {
      }
      ;WinWaitActive, ahk_pid %OutputVarPID%
      Gui, 2:Destroy 
      checko = 1
    }
  }
  IfWinActive, HSHIDE
  {
    WinActivate, ahk_pid %OutputVarPID%
  }
  if WinExist("Adventure Game Studio", "Abort key pressed") or !WinExist("ahk_pid" . OutputVarPID)
  {
  ExitApp
  }    
}

ExitApp

Ali

I'm currently trying to achieve a similar thing in-engine: Better Widescreen Borders. It's very specific to my needs at the moment, but it seems it doesn't take much tweaking in the engine to create this effect.

But before I discovered that, I tried modifying Trapezoid's script. Again, it's specific to my needs, but it could be modified. In case it's of interest, here's a script which changes Screen Res to 1280 x 720 then runs an 800 x 600 game:
Code: AGS
ChangeDisplaySettings( cD, sW, sH, rR ) {
  VarSetCapacity(dM,156,0), NumPut(156,2,&dM,36)
  DllCall( "EnumDisplaySettings", UInt,0, UInt,-1, UInt,&dM ), NumPut(0x5c0000,dM,40)
  NumPut(cD,dM,104),  NumPut(sW,dM,108),  NumPut(sH,dM,112),  NumPut(rR,dM,120)
  Return DllCall( "ChangeDisplaySettings", UInt,&dM, UInt,0 )
}

SysGet, Monitor, Monitor

Clipboard=
clipboard := MonitorRight 
OldResWidth := ClipboardAll

Clipboard=
clipboard :=MonitorBottom 
OldResHight := ClipboardAll


cD = 32   ; bits (quality) - you can change to suit your requirments
sW = 1280 ; pixels - you can change to suit your requirments
sH = 720  ; pixels - you can change to suit your requirments
rR = 60   ; Hz (frequency) - you can change to suit your requirments

ChangeDisplaySettings( cD, sW, sH, rR )

cD = 32   	     ; bits (quality) - you can change to suit your requirments
sW = %OldResWidth%   ; pixels - you can change to suit your requirments
sH = %OldResHight%   ; pixels - you can change to suit your requirments
rR = 60   	     ; Hz (frequency) - you can change to suit your requirments
 

GameWidth = 800
GameHeight = 600
GameExe = "Game.exe"
GameCfg = acsetup.cfg
 
scrX = %A_ScreenWidth%
scrY = %A_ScreenHeight%
 
IniWrite, 1, %GameCfg%, misc, windowed
 
if (scrX >= GameWidth*4 and scrY >= GameHeight*4) {
  IniWrite, StdScale4, %GameCfg%, misc, gfxfilter
  }
else if (scrX >= GameWidth*3 and scrY >= GameHeight*3) {
  IniWrite, StdScale3, %GameCfg%, misc, gfxfilter 
  }
else if (scrX >= GameWidth*2 and scrY >= GameHeight*2) {
  IniWrite, StdScale2, %GameCfg%, misc, gfxfilter 
  }
else {
  IniWrite, None, %GameCfg%, misc, gfxfilter 
  }
  
Gui, -Caption +ToolWindow
Gui, Color, 0
Gui, Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE    
 
Run, %GameExe%, , , OutputVarPID
WinWait, ahk_pid %OutputVarPID%
 
WinSet, Style, -0xC00000, ahk_pid %OutputVarPID%
 
Gui, 2: +AlwaysOnTop -Caption +ToolWindow                                        
Gui, 2: Color, 0            
Gui, 2: Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE   
Sleep, 10
Gui, 2:Destroy
 
WinWaitActive, ahk_pid %OutputVarPID%
MouseMove, %GameWidth% / 2, %GameHeight% / 2
checko = 1
 
While WinExist("ahk_pid" . OutputVarPID)
{
  if !WinActive("ahk_pid" . OutputVarPID) and !WinActive("HSHIDE")
  { 
    if (checko=1)
    {
      checko = 0
    }
  }
  if WinActive("ahk_pid" . OutputVarPID)
  {
    if (checko=0)
    {
      Gui, -Caption +ToolWindow                                        
      Gui, Color, 0                                                                               
      Gui, Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE      
      Gui, 2: +AlwaysOnTop -Caption +ToolWindow                                        
      Gui, 2: Color, 0                                                                                 
      Gui, 2: Show, x0 y0 h%A_ScreenHeight% w%A_ScreenWidth%, HSHIDE
      WinActivate, ahk_pid %OutputVarPID%
      While !WinActive("ahk_pid" . OutputVarPID) and WinExist("ahk_pid" . OutputVarPID) and !WinExist("Adventure Game Studio", "Abort key pressed")
      {
      }
      ;WinWaitActive, ahk_pid %OutputVarPID%
      Gui, 2:Destroy 
      checko = 1
    }
  }
  IfWinActive, HSHIDE
  {
    WinActivate, ahk_pid %OutputVarPID%
  }
  if WinExist("Adventure Game Studio", "Abort key pressed") or !WinExist("ahk_pid" . OutputVarPID)
  {
  ChangeDisplaySettings( cD, sW, sH, rR )
  ExitApp
  }    
}
ChangeDisplaySettings( cD, sW, sH, rR )
ExitApp

StillInThe90s

Very creative. Thumbs up!
However...
I'm having problems with this on my win 8 (64) laptop (1366x768). The black background is there but so is the title bar and window edges. My script also fails to pick a  nearest-neighbour mode. Do I need to change anything else apart from game res and name of the game executable? AHK is not my forte.

Trapezoid

Make sure the GameCfg variable is correct too. I'm not sure about AHK's compatibility with Win8, it might have some issue with IniWrite and WinSet. I only have 7, so I can't test it.

StillInThe90s

Got it! I think it was some win 8 security issue. Not sure. It works like a charm now anyway.
Tried to make it work for older games as well (Spooks from 2006 in this case) and I got as far as getting it to pick 640x480 in favour of 320x240, but bar and edges stays in there. Hmmm...

Trapezoid

#14
Hey, if you're using the custom resolution build, I guess there's a new configuration option (renderstyle) that really simplifies this script!

Code: ags
GameWidth = 320
GameHeight = 200
GameExe = Game.exe
GameCfg = acsetup.cfg
 
scrX = %A_ScreenWidth%
scrY = %A_ScreenHeight%
 
IniWrite, 1, %GameCfg%, misc, windowed
IniWrite, center, %GameCfg%, misc, renderstyle
IniWrite, %scrX%, %GameCfg%, misc, screenwidth
IniWrite, %scrY%, %GameCfg%, misc, screenheight
 
if (scrX >= GameWidth*4 and scrY >= GameHeight*4) {
  IniWrite, StdScale4, %GameCfg%, misc, gfxfilter
  }
else if (scrX >= GameWidth*3 and scrY >= GameHeight*3) {
  IniWrite, StdScale3, %GameCfg%, misc, gfxfilter 
  }
else if (scrX >= GameWidth*2 and scrY >= GameHeight*2) {
  IniWrite, StdScale2, %GameCfg%, misc, gfxfilter 
  }
else {
  IniWrite, None, %GameCfg%, misc, gfxfilter 
  }
 
Run, %GameExe%, , , OutputVarPID
WinWait, ahk_pid %OutputVarPID%
 
WinSet, Style, -0xC00000, ahk_pid %OutputVarPID%
  
WinWaitActive, ahk_pid %OutputVarPID%
MouseMove, %GameWidth% / 2, %GameHeight% / 2
 
ExitApp

SMF spam blocked by CleanTalk