The Notebook Review forums were hosted by TechTarget, who shut down them down on January 31, 2022. This static read-only archive was pulled by NBR forum users between January 20 and January 31, 2022, in an effort to make sure that the valuable technical information that had been posted on the forums is preserved. For current discussions, many NBR forum users moved over to NotebookTalk.net after the shutdown.
Problems? See this thread at archive.org.

    Automatically Switch Refresh Rate (AC/Battery) - 60 Hz vs 144 Hz

    Discussion in 'MSI' started by xLima, Apr 1, 2019.

  1. xLima

    xLima Notebook Evangelist

    Reputations:
    132
    Messages:
    567
    Likes Received:
    280
    Trophy Points:
    76
    Credits:

    • U/iRawrz @ Reddit | @iRawrz providing scripts;
    • Patrick Gruenauer @ SID-500.COM for the guide on Code Signing


    This is a guide on how to automate switching between 60 Hz and 144 Hz according to power mode (Battery v. AC)



    Things you will need

    • PowerShell and PowerShell ISE (Preinstalled on Windows 10)
    • Generate a Code Signing Cert and Sign the .ps1 file
    • .ps1 file: This is the power shell command that will detect and automate the switching
    • Task Scheduler: We will run two (2) tasks that will detect and switch according to power source

    Task Scheduler

    1. System_Microsoft-Windows-Kernel-Power_105.xml
      1. Will run PowerShell command to identify if on AC or Battery
    2. State Check.xml
      1. Determine Power profile and trigger refresh rate accordingly.
    3. Open Tash Scheduler and choose IMPORT TASK on the right-hand side
    4. Import the .xml files into task scheduler and modify directories accordingly
      1. The Task Scheduler.xml imports will search C:\ for "check-power-state.ps1"


    Script

    1. Download RefreshRate.ps1 and RENAME to check-power-state.ps1
      1. This step is OPTIONAL, you can place/name it wherever/what ever you like but must match directory in the System_Microsoft-Windows-Kernal-Power_105.xml
        1. Actions Tab > Edit Actions > Add Arguments > -WindowStyle minimized "C:\check-power-state.ps1"
    2. There are additional scripts available (eg. RR+AB) - See README


    Code Signing Cert

    1. Follow the guide here on sid-500.com


    There were attempts to make a script to switch refresh rates, open or close AB to set OC according to power status and turn on and off SteelSeries RGB. The latter was dropped because of difficulty on personalising settings for each particular device (We could only get it to work on 1 device, the timings on the other never matched).



    The RR+AB was abandoned because I found Nvidia Injector easier to use.

    Code:
    Function Set-ScreenResolution {
    
    <#
        .Synopsis
            Sets the Screen Resolution of the primary monitor
        .Description
            Uses Pinvoke and ChangeDisplaySettings Win32API to make the change
        .Example
            Set-ScreenResolution -Width 1024 -Height 768    -Freq 60   
        #>
    param (
    [Parameter(Mandatory=$true,
               Position = 0)]
    [int]
    $Width,
    
    [Parameter(Mandatory=$true,
               Position = 1)]
    [int]
    $Height,
    
    [Parameter(Mandatory=$true,
               Position = 2)]
    [int]
    $Freq
    )
    
    $pinvokeCode = @"
    
    using System;
    using System.Runtime.InteropServices;
    
    namespace Resolution
    {
    
       [StructLayout(LayoutKind.Sequential)]
       public struct DEVMODE1
       {
           [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
           public string dmDeviceName;
           public short dmSpecVersion;
           public short dmDriverVersion;
           public short dmSize;
           public short dmDriverExtra;
           public int dmFields;
    
           public short dmOrientation;
           public short dmPaperSize;
           public short dmPaperLength;
           public short dmPaperWidth;
    
           public short dmScale;
           public short dmCopies;
           public short dmDefaultSource;
           public short dmPrintQuality;
           public short dmColor;
           public short dmDuplex;
           public short dmYResolution;
           public short dmTTOption;
           public short dmCollate;
           [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
           public string dmFormName;
           public short dmLogPixels;
           public short dmBitsPerPel;
           public int dmPelsWidth;
           public int dmPelsHeight;
    
           public int dmDisplayFlags;
           public int dmDisplayFrequency;
    
           public int dmICMMethod;
           public int dmICMIntent;
           public int dmMediaType;
           public int dmDitherType;
           public int dmReserved1;
           public int dmReserved2;
    
           public int dmPanningWidth;
           public int dmPanningHeight;
       };
    
    
    
       class User_32
       {
           [DllImport("user32.dll")]
           public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE1 devMode);
           [DllImport("user32.dll")]
           public static extern int ChangeDisplaySettings(ref DEVMODE1 devMode, int flags);
    
           public const int ENUM_CURRENT_SETTINGS = -1;
           public const int CDS_UPDATEREGISTRY = 0x01;
           public const int CDS_TEST = 0x02;
           public const int DISP_CHANGE_SUCCESSFUL = 0;
           public const int DISP_CHANGE_RESTART = 1;
           public const int DISP_CHANGE_FAILED = -1;
       }
    
    
    
       public class PrmaryScreenResolution
       {
           static public string ChangeResolution(int width, int height, int freq)
           {
    
               DEVMODE1 dm = GetDevMode1();
    
               if (0 != User_32.EnumDisplaySettings(null, User_32.ENUM_CURRENT_SETTINGS, ref dm))
               {
    
                   dm.dmPelsWidth = width;
                   dm.dmPelsHeight = height;
                   dm.dmDisplayFrequency = freq;
    
                   int iRet = User_32.ChangeDisplaySettings(ref dm, User_32.CDS_TEST);
    
                   if (iRet == User_32.DISP_CHANGE_FAILED)
                   {
                       return "Unable to process your request. Sorry for this inconvenience.";
                   }
                   else
                   {
                       iRet = User_32.ChangeDisplaySettings(ref dm, User_32.CDS_UPDATEREGISTRY);
                       switch (iRet)
                       {
                           case User_32.DISP_CHANGE_SUCCESSFUL:
                               {
                                   return "Success";
                               }
                           case User_32.DISP_CHANGE_RESTART:
                               {
                                   return "You need to reboot for the change to happen.\n If you feel any problems after rebooting your machine\nThen try to change resolution in Safe Mode.";
                               }
                           default:
                               {
                                   return "Failed to change the resolution";
                               }
                       }
    
                   }
    
    
               }
               else
               {
                   return "Failed to change the resolution.";
               }
           }
    
           private static DEVMODE1 GetDevMode1()
           {
               DEVMODE1 dm = new DEVMODE1();
               dm.dmDeviceName = new String(new char[32]);
               dm.dmFormName = new String(new char[32]);
               dm.dmSize = (short)Marshal.SizeOf(dm);
               return dm;
           }
       }
    }
    
    "@
    
    Add-Type $pinvokeCode -ErrorAction SilentlyContinue
    [Resolution.PrmaryScreenResolution]::ChangeResolution($width,$height,$freq)
    }
    
    if((Get-WmiObject -Class Win32_Battery -ea 0).BatteryStatus -eq 1) {
    
        Set-ScreenResolution -Width 1920 -Height 1080 -Freq 60
        } else {
    
        Set-ScreenResolution -Width 1920 -Height 1080 -Freq 144
        }
    # SIG # Begin signature block
    # MIIFcQYJKoZIhvcNAQcCoIIFYjCCBV4CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
    # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
    # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUulmi5cgiWqXjonaaIA4q/+/D
    # LFSgggMSMIIDDjCCAfagAwIBAgIQZUSSyB/6wI5MYDhXrRpDcDANBgkqhkiG9w0B
    # AQsFADAUMRIwEAYDVQQDDAlwZm9ydGVzODgwHhcNMTkwMTE5MDc1OTUzWhcNMjAw
    # MTE5MDgxOTUzWjAUMRIwEAYDVQQDDAlwZm9ydGVzODgwggEiMA0GCSqGSIb3DQEB
    # AQUAA4IBDwAwggEKAoIBAQDuGoVJLT8x6Oi9FI/oiGjVhuUFGWcWPom1qzy181Ir
    # EA1UVFIILfl7RTLeV1Dvfd4nTds0Ku4XEsmotnhNlq1eXm5XEtNDEyp/FS8Vli7+
    # MobmMEIyA413stwqYroGF5W9mnr8ATmM6JSc9NRBartEg70YHQ6HWdpBrBXoAeJQ
    # AKCQEUMXIE/UmxFgOSkWeQV0wx24wPKDkG2X3sRSHmJMgIv4523ojsuEfgwaL4EB
    # A7xcfdvfjNSQ26tw6qYxYWt5zlep4LcR7H7dXk1LezPQTFOXCdIY9jwG7SFgqoPt
    # Z3qswbQyPrhXn9aHf2t93UcjJM/2nye9qCHKoBxyn1xlAgMBAAGjXDBaMA4GA1Ud
    # DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAUBgNVHREEDTALgglwZm9y
    # dGVzODgwHQYDVR0OBBYEFC85BuoLzos+GebfI9vfRU4Uoh4cMA0GCSqGSIb3DQEB
    # CwUAA4IBAQCcJWRrLLB+BYr8IrS5/5+51q6fIbeuew4JKVoTxF8k/X7vg0+n0HXT
    # wkLBPAf31SU4AkiN4nJlyZbwZ3WON5+HOVNxSZ5cFPw55dYZ/6YMDYNO5w5i+Z8G
    # YfYALxYJwf/9qXJzcbfrm2N1BxroLarQZ6Njj5QnKay1Th4u+soyXl1Z8PXq09Be
    # wkNCa8ERpDq7iMVKF5BUx9nOw7FXxJ7wgTCnvloBxSECD8NCKl7om3sRolPybfmu
    # hrM61QJRIexJxA0ZU+mMZqVBC54/qRbnnBKoOKR4pgDUKUOI8HP2crZxg5uRHIOq
    # 8N04CN6PSyDRrlw182W3KqUFtvshJKUlMYIByTCCAcUCAQEwKDAUMRIwEAYDVQQD
    # DAlwZm9ydGVzODgCEGVEksgf+sCOTGA4V60aQ3AwCQYFKw4DAhoFAKB4MBgGCisG
    # AQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
    # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFAgi
    # TZn8H45eg34m+4vaTx46CLEmMA0GCSqGSIb3DQEBAQUABIIBAAQbjEz5dGtx3nSL
    # qaKFluK0yB2kpBtoBAfUJQKR4UAi0KPgbUetvXJBaW6YAWkzqDu3oMdV08lm6hAW
    # bh8gKVOgxF+jpd3dgWhFW7FAcYDcqRgj7XKLiJ19hnvBbSEU81PM6P43+ElQkeOc
    # gBslvIoKm9C9wgptZXCUMJ+EqgAAFtF/68r5A5ZbjQKgC9nzg5TUYn2SpB0GgjQP
    # o6raGM5lwmn9mGRqVnkR6bydf/0ckbe4SKTmoxzZtuANmsmfwsGgbon+GVdnrViN
    # SRU+L2QACq34GuUt9eOd8TZLn/Ut/wl8wSwumLhmGnTxcN5aXD2fKUJjvE5EUlWZ
    # 7k8+pXI=
    # SIG # End signature block
    
     
    Kevin@GenTechPC likes this.
  2. hackness

    hackness Notebook Virtuoso

    Reputations:
    1,237
    Messages:
    2,367
    Likes Received:
    427
    Trophy Points:
    101
    Nice.

    What I did was download Qres from here:
    https://www.majorgeeks.com/files/details/qres.html

    Unzip and move Qres.exe to C:\Windows\System32\

    Don't forget to go into Qres.exe's properties and go to compatibility and tick Run this progran as an administrator.

    Next,

    Set up 2 tasks in task scheduler, one named 60Hz, one named 144Hz, all with the highest privilege, trigger set to "On a schedule" and set the time to the past.

    For the 60Hz task, under the Actions tab, add new program, under Settings add C:\Windows\System32\Qres.exe to Program/Script, add /r:60 to Add arguments (Optional).

    For the 144Hz task, under the Actions tab, add new program, under Settings add C:\Windows\System32\Qres.exe to Program/Script, add /r:144 to Add arguments (Optional).

    Remember to untick the "Start the task only if the computer is on AC power".

    Now go to C:\ and create a folder called Qres, go inside and create 2 batch files, one named 60Hz.bat, one named 144Hz.bat

    For 60Hz.bat, put this in the batch file:
    schtasks /run /I /TN "\60Hz"

    For 144Hz.bat, put this in the batch file:
    schtasks /run /I /TN "\144Hz"

    This is to call the task you have just set up in the Task Scheduler.

    Now go to ThrottleStop, go to Options, under the Run program After Profile Change, look for the Profile linked to AC and Battery, select "After", link AC Profile to C:\Qres\144Hz.bat, link Battery Profile to C:\Qres\60Hz.bat, hit OK.

    You are settled.
     
  3. ryzeki

    ryzeki Super Moderator Super Moderator

    Reputations:
    6,552
    Messages:
    6,410
    Likes Received:
    4,087
    Trophy Points:
    431
    Is there a significant boost going from 144hz to 60hz while on battery? Current GS75 lasted me about 5-6 hours watching netflix, not sure if dropping to 60hz would help there. Perhaps while browsing or doing light tasks.
     
    custom90gt likes this.
  4. hackness

    hackness Notebook Virtuoso

    Reputations:
    1,237
    Messages:
    2,367
    Likes Received:
    427
    Trophy Points:
    101
    It lessens the wattage consumption for about 1 watt, prolongs the battery life for about 30 minutes.
     
    ryzeki likes this.
  5. Divinated

    Divinated Notebook Consultant

    Reputations:
    5
    Messages:
    103
    Likes Received:
    30
    Trophy Points:
    41
    Also, if you turn vertical sync on then it limits the graphic card to only render the amount of frames that the screen can display. Correct me if i'm wrong, but that would mean less work for the GPU which ultimately means lower power consumption. Am i correct?
     
  6. hackness

    hackness Notebook Virtuoso

    Reputations:
    1,237
    Messages:
    2,367
    Likes Received:
    427
    Trophy Points:
    101
    That's correct, because you are telling the GPU that you only needed 60 FPS to be rendered.
     
    Kevin@GenTechPC likes this.
  7. ryzeki

    ryzeki Super Moderator Super Moderator

    Reputations:
    6,552
    Messages:
    6,410
    Likes Received:
    4,087
    Trophy Points:
    431
    Thanks! I will consider it, but for the time being, the buttery smooth feeling of 144hz is better than 30 mins more battery, for me :)
     
    ALLurGroceries and hackness like this.