Limit FPS with injected clr app menu

User Tag List

Results 1 to 14 of 14
  1. #1
    Corthezz's Avatar Elite User Authenticator enabled
    Reputation
    386
    Join Date
    Nov 2011
    Posts
    325
    Thanks G/R
    183/98
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Limit FPS with injected clr app

    First of all: Yes nowdays you can use CVar maxfpsbk to limit the framerate in WoW however Im not really interested in capping the FPS for a purpose but rather want to find out the best technique to do it.

    Right now I got an injected clr executable running in WoW.
    Obviously one EndScene call means one frame. So FPS depends on how often EndScene can get executed in a second.
    If we want to cap at 60 FPS:
    1000/60 = 16,66666666666667 => Time between each rendered frame should be around 16666666ns

    Logic is easy:
    If the time passing by between the last rendered frame and the current frame takes less than 16 ms we sleep til we reach 16 ms.
    Now I redirected EndScene to a c# function which will do the logic:

    Code:
    private static int LastFrameTick = 0;
    private static int TimeBetweenFrame = 0;
    private static int WaitTilNextFrame = 0;
    
    private static int EndSceneHook(IntPtr parDevice)
    {
    	int ret = (int)_endSceneHook.CallOriginal(parDevice);
    	if (LastFrameTick != 0)
    	{
    		TimeBetweenFrame = (Environment.TickCount - LastFrameTick);
    		if (TimeBetweenFrame < 15)
    		{
    			WaitTilNextFrame = Environment.TickCount + (15 - TimeBetweenFrame);
    			while (Environment.TickCount < WaitTilNextFrame) ;
    		}
    	}
    	LastFrameTick = Environment.TickCount;
    	return ret;
    }
    Well I am pretty happy with the result but I am wondering if there are ways to be more accurate. Since .net cant work with ns (atleast I read it cant) we cant really work with 16,66666666666667 so we have to decide between 16ms (62.5 fps) and 17ms (58.8 fps) not accounting that the detour itself also affects the outcome.

    Can someone recommend a better way to be more accurate?
    Last edited by Corthezz; 11-03-2015 at 03:28 PM.
    Check my blog: https://zzuks.blogspot.com

    Limit FPS with injected clr app
  2. Thanks HI5 (1 members gave Thanks to Corthezz for this useful post)
  3. #2
    danwins's Avatar Contributor
    Reputation
    189
    Join Date
    Mar 2013
    Posts
    143
    Thanks G/R
    6/62
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Correct me if I'm wrong, but i was under the impression that dx9 endscene isnt *always* called once per frame, but in some cases multiple times per rendered frame.

  4. #3
    Corthezz's Avatar Elite User Authenticator enabled
    Reputation
    386
    Join Date
    Nov 2011
    Posts
    325
    Thanks G/R
    183/98
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by danwins View Post
    Correct me if I'm wrong, but i was under the impression that dx9 endscene isnt *always* called once per frame, but in some cases multiple times per rendered frame.
    Atleast in 1.12.1 WoW EndScene is called once each mainthread loop. Im not to experienced with DirectX .
    Check my blog: https://zzuks.blogspot.com

  5. #4
    danwins's Avatar Contributor
    Reputation
    189
    Join Date
    Mar 2013
    Posts
    143
    Thanks G/R
    6/62
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I didn't mean wow but rather, in general. its just something I've stumbled upon in other games.

    it generally causes issues with things like ESP drawing,

  6. #5
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry for derailing.. it's just a related topic and people posting here know more than I do about it.
    Can anyone explain to me as some one newer to this stuff what the obsession is with hooking EndScene and running their code in each frame?

    Outside of visual tools that render things to the screen like radar's and esp, is it really needed or even ideal? I really prefer to run as much code as I possible can on my end, just so my code is the least dependent on other factors I don't control as possible.

    For code I desire to be called frequently at specified interval, I use this class mostly:
    https://github.com/lolp1/MemorySharp...ols/Updater.cs

    Then, to actually run any code that interacting with game functions that I want thread-safety from, I use the code Jadd posted and just invoke it when ever.
    ntoskrnl | Hooking Threads without Detours or Patches
    If you're curious about the blog like I was, here is an example easier to look at than a single-page blog:
    https://github.com/lolp1/MemorySharp/tree/master/Hooks

    Is there anything wrong with this, or am I totally missing something that explains why there is one million topics and discussions about hooking endscene at the ultimate end-all?
    Last edited by lolp1; 11-03-2015 at 06:52 PM.

  7. #6
    Frosttall's Avatar Active Member
    Reputation
    64
    Join Date
    Feb 2011
    Posts
    261
    Thanks G/R
    16/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by lolp1 View Post
    Sorry for derailing.. it's just a related topic and people posting here know more than I do about it.
    Can anyone explain to me as some one newer to this stuff what the obsession is with hooking EndScene and running their code in each frame?

    Outside of visual tools that render things to the screen like radar's and esp, is it really needed or even ideal? I really prefer to run as much code as I possible can on my end, just so my code is the least dependent on other factors I don't control as possible.

    For code I desire to be called frequently at specified interval, I use this class mostly:
    https://github.com/lolp1/MemorySharp...ols/Updater.cs

    Then, to actually run any code that interacting with game functions that I want thread-safety from, I use the code Jadd posted and just invoke it when ever.
    ntoskrnl | Hooking Threads without Detours or Patches
    If you're curious about the blog like I was, here is an example easier to look at than a single-page blog:
    https://github.com/lolp1/MemorySharp/tree/master/Hooks

    Is there anything wrong with this, or am I totally missing something that explains why there is one million topics and discussions about hooking endscene at the ultimate end-all?
    Imagine following situation:

    You're hooking a function (not EndScene) because it gets called way more often, right? Now what happens if a function, which generates the underlying object geometry for e.g. TraceLine calls exactly this function during the generation? You would have an incomplete, or in worst case a corrupt, state. An incomplete list is not always a matter, but could result in inconsistent behaviour like detecting objects upon the first call, even though they're not "there" during the first call because this object has not been processed yet.

    To sum it up: EndScene guarantees a finite state, because it gets called as soon as every single background-task to process the changed data (because of movement, time, server-packets, events etc...) between each frame.has been finished.

    A programmer should generally prefer consistency over speed: Calling some code a little bit faster may be great, but speed should not be the point which decides whether your program works or not. A consistent state on the other hand is very important: You will always have to debug errors and thus spend a lot of time to find out reasons your code is crashing or behaving in a strange manner. Now imagine you're spending 12 hours in a row just to find out that the function you're hooking corrupts the state of the data you're accessing.
    EndScene will "never" leave data in a corrupt state and you will avoid a lot of possible problems.

  8. #7
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    (....)To sum it up: EndScene guarantees a finite state, because it gets called as soon as every single background-task to process the changed data (because of movement, time, server-packets, events etc...) between each frame.has been finished.
    This I understand. What I don't understand is why hooking EndScene is a solution for this. If you're not rendering stuff like a radar, the EndScene hook seems like massive overkill to provide safety. I'm fairly sure the example Jadd posted in his blog that I linked above provides 100% thread safety just as EndScene does.

    For example, in my project I apply the WndProc hook, which runs on the same thread as EndScene. Then, when I want to execute code or access any data/function I assume to be not thread-safe, I have my 'tick' event fire a PostMessage with WM_USER+1 as the message and then intercept that message in the hook call back and it's handled there. This seems to let me execute code inside the main thread on any tick event I desire, and still be safe.

    A programmer should generally prefer consistency over speed.
    I think so too, especially when using something like C#. I'm not really sure how speed is hurt by using methods other than hooking EndScene to run misc code.

  9. #8
    Jadd's Avatar 🐸 Premium Seller
    Reputation
    1511
    Join Date
    May 2008
    Posts
    2,432
    Thanks G/R
    81/333
    Trade Feedback
    1 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by danwins View Post
    Correct me if I'm wrong, but i was under the impression that dx9 endscene isnt *always* called once per frame, but in some cases multiple times per rendered frame.
    EndScene finalizes the scene and occurs once per frame, so yes, EndScene is a viable place to count frames.


    Originally Posted by danwins View Post
    I didn't mean wow but rather, in general. its just something I've stumbled upon in other games.

    it generally causes issues with things like ESP drawing,
    The issue is most likely that a different device or swap-chain is calling EndScene, in which case you should compare the device and/or swap-chain to a list you're maintaining. That way you can get your framerate for all outputs.


    Originally Posted by Frosttall View Post
    Imagine following situation:

    You're hooking a function (not EndScene) because it gets called way more often, right? Now what happens if a function, which generates the underlying object geometry for e.g. TraceLine calls exactly this function during the generation? You would have an incomplete, or in worst case a corrupt, state. An incomplete list is not always a matter, but could result in inconsistent behaviour like detecting objects upon the first call, even though they're not "there" during the first call because this object has not been processed yet.
    What in the name of **** are you talking about? Use a timer? Use a WndProc callback for a custom window message?


    Originally Posted by Frosttall View Post
    To sum it up: EndScene guarantees a finite state, because it gets called as soon as every single background-task to process the changed data (because of movement, time, server-packets, events etc...) between each frame.has been finished.
    EndScene isn't all that reliable. What happens when you minimize your game? You have no choice but to wait for the game to be shown again. And what happens when we're running on one computer at 500fps and on another at 5fps? It's inconsistent, not to mention slower.


    Edit: Sorry OP, totally ignored your question. P/Invoke QueryPerformanceCounter if you want to do timing in microseconds. I believe System.Diagnostics.Stopwatch also uses QPC for timing so it's also quite precise if you would prefer to use that.
    Last edited by Jadd; 11-04-2015 at 03:37 AM.

  10. Thanks HI5 (1 members gave Thanks to Jadd for this useful post)
  11. #9
    Corthezz's Avatar Elite User Authenticator enabled
    Reputation
    386
    Join Date
    Nov 2011
    Posts
    325
    Thanks G/R
    183/98
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Adding up to Jadds post this guy is pretty interesting.

    Edit: Actually pretty funny. In the start post published snippet provides a cap at 64 FPS while the example below caps at 160 FPS while it technically should do the same:

    Code:
    private static double LastFrameTick = 0;
    private static double TimeBetweenFrame = 0;
    private static double WaitTilNextFrame = 0;
    private static double CapAt = 16.66;
    
    private static int EndSceneHook(IntPtr parDevice)
    {
    	int ret = (int)_endSceneHook.CallOriginal(parDevice);
    	if (LastFrameTick != 0)
    	{
    		TimeBetweenFrame = (QueryPerformanceCounter() - LastFrameTick);
    		if (TimeBetweenFrame < CapAt)
    		{
    			WaitTilNextFrame = QueryPerformanceCounter() + (CapAt - TimeBetweenFrame);
    			while (QueryPerformanceCounter() <= WaitTilNextFrame) ;
    		}
    	}
    	LastFrameTick = QueryPerformanceCounter();
    	return ret;
    }
    
    private static double QueryPerformanceCounter()
    {
    	long tmp;
    	WinImports.QueryPerformanceCounter(out tmp);
    	return tmp / (double)1000;
    }
    Last edited by Corthezz; 11-04-2015 at 05:51 AM.
    Check my blog: https://zzuks.blogspot.com

  12. #10
    Master674's Avatar Elite User
    Reputation
    487
    Join Date
    May 2008
    Posts
    578
    Thanks G/R
    2/23
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Jadd View Post
    EndScene finalizes the scene and occurs once per frame, so yes, EndScene is a viable place to count frames.
    Actually it's perfectly valid to have multiple BeginScene/EndScene calls per frame. Its almost always better to use Present instead of EndScene.

    For example my injected UI framework hooks Present and calls a new BeginScene/EndScene pair.
    This would obviously mess with anyone elses hooks on EndScene because he'd see multiple calls as soon as mine is loaded.

  13. #11
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Out of curiosity Corthezz, what exactly is the need of having such precise timing for fps in a game?

  14. #12
    Corthezz's Avatar Elite User Authenticator enabled
    Reputation
    386
    Join Date
    Nov 2011
    Posts
    325
    Thanks G/R
    183/98
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by lolp1 View Post
    Out of curiosity Corthezz, what exactly is the need of having such precise timing for fps in a game?
    In vanilla WoW click2move is affected by the framerate. If you have a framerate which is above 80 it will just initial a never ending walk in the direction your character is facing.
    When I was using my bot privately this wasnt a problem since my monitor is 60hz anyway and I can easily cap the FPS using vSync but now since its public it should also support 120 hz monitors

    The timing is not that important. I am just curious if it possible to create an external framecapper that can limit FPS to the exact value specified.
    Oh and btw: I am really curious if it is possible to fix CTM for FPS higher than 80 but havnt found the time to really look into it ... probably another "fun" exercise with no real benefit.
    Check my blog: https://zzuks.blogspot.com

  15. #13
    andy012345's Avatar Active Member
    Reputation
    59
    Join Date
    Oct 2007
    Posts
    124
    Thanks G/R
    0/7
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Might be my 11pm rambling but calling EndScene then looping seems like it steals processing time from the next frame.

    Also use Present.

  16. #14
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Corthezz View Post
    Adding up to Jadds post this guy is pretty interesting.

    Edit: Actually pretty funny. In the start post published snippet provides a cap at 64 FPS while the example below caps at 160 FPS while it technically should do the same:

    Code:
    private static double LastFrameTick = 0;
    private static double TimeBetweenFrame = 0;
    private static double WaitTilNextFrame = 0;
    private static double CapAt = 16.66;
    
    private static int EndSceneHook(IntPtr parDevice)
    {
        int ret = (int)_endSceneHook.CallOriginal(parDevice);
        if (LastFrameTick != 0)
        {
            TimeBetweenFrame = (QueryPerformanceCounter() - LastFrameTick);
            if (TimeBetweenFrame < CapAt)
            {
                WaitTilNextFrame = QueryPerformanceCounter() + (CapAt - TimeBetweenFrame);
                while (QueryPerformanceCounter() <= WaitTilNextFrame) ;
            }
        }
        LastFrameTick = QueryPerformanceCounter();
        return ret;
    }
    
    private static double QueryPerformanceCounter()
    {
        long tmp;
        WinImports.QueryPerformanceCounter(out tmp);
        return tmp / (double)1000;
    }
    You are not taking the frequency of the timer into account in this snippet. QPC has way higher precision than milliseconds on modern PCs.

    If you want to control the FPS more precisely you can accumulate the errors and correct for the error in future ticks. This will allow you to achieve a perfect average FPS in the long run.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

Similar Threads

  1. Character Model Swapping With Injection?
    By Jackalhead in forum Diablo 3 Memory Editing
    Replies: 8
    Last Post: 04-15-2012, 01:43 PM
  2. Replies: 1
    Last Post: 01-19-2012, 03:14 AM
  3. C# Lua Wrapper (No ASM, Requires injected CLR)
    By Apoc in forum WoW Memory Editing
    Replies: 29
    Last Post: 02-04-2011, 02:52 PM
  4. Need help with VB console apps
    By Sm00gel in forum Programming
    Replies: 12
    Last Post: 03-19-2010, 10:29 AM
  5. How to increase your fps[with video]!
    By feliz in forum World of Warcraft Guides
    Replies: 31
    Last Post: 07-12-2008, 10:30 AM
All times are GMT -5. The time now is 04:10 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search