Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I've got a few old programs I pulled off an early 90s-era Windows computer and tried to run them on a relatively modern computer. Interestingly enough, they ran at a blazing fast speed - no, not the 60 frames per second kind of fast, rather the oh-my-god-the-character-is-walking-at-the-speed-of-sound kind of fast. I would press an arrow key and the character's sprite would zip across the screen much faster than normal. Time progression in the game was happening much faster than it should. There are even programs made to slow down your CPU so that these games are actually playable.

I've heard that this is related to the game depending on CPU cycles, or something like that. My questions are:

  • Why do older games do this, and how did they get away with it?
  • How do newer games not do this and run independently of the CPU frequency?
share|improve this question
    
This was a while back and I don't recall doing any compatibility trickery, but that's beside the point. There is plenty of information out there on how to fix this, but not so much on why exactly they run that way, which is what I'm asking. –  TreyK Aug 12 '13 at 1:45
9  
Remember the turbo button on older PC's? :D –  Vixen Aug 12 '13 at 7:35
1  
Ah. Makes me remember the 1 sec delay on the ABC80 (Swedish z80-based PC with Basic). FOR F IN 0 TO 1000; NEXT F; –  Macke Aug 12 '13 at 8:18
1  
Just to clarify, "a few old programs I pulled off an early 90s-era Windows computer" are those DOS programs on a Windows machine, or Windows programs where this behaviour happens? I'm used to seeing it on DOS, but not windows, IIRC. –  That Brazilian Guy Aug 12 '13 at 11:09
    
See also CPU or framerate limiting on older games –  BlueRaja Aug 12 '13 at 16:14

4 Answers 4

up vote 46 down vote accepted

I believe they assumed the system clock would run at a specific rate, and tied in their internal timers to that clock rate. Most of these games probably ran on DOS, and were real mode (with complete, direct hardware access) and assumed you were running a iirc 4.77 MHz system for PCs and whatever standard processor that model ran for other systems like the Amiga.

They also took clever shortcuts based on those assumptions including saving a tiny bit of resources by not writing internal timing loops inside the program. They also took up as much processor power as they could – which was a decent idea in the days of slow, often passively cooled chips!

Initially one way to get around differing processor speed was the good old Turbo button (which slowed your system down). Modern applications are in protected mode and the OS tends to manage resources – they wouldn't allow a DOS application (which is running in NTVDM on a 32-bit system anyway) to use up all of the processor in many cases. In short, OSes have gotten smarter, as have APIs.

Heavily based off this guide on Oldskool PC where logic and memory failed me – it's a great read, and probably goes more in depth into the "why".

Stuff like CPUkiller use up as many resources as possible to "slow" down your system, which is inefficient. You'd be better off using DOSBox to manage the clock speed your application sees.

share|improve this answer
14  
Some of these games did not even assume anything, they ran just as fast as they could, which was 'playable' on those CPU's ;-) –  Jan Doggen Aug 12 '13 at 8:41
2  
For information re. "How do newer games not do this and run independently of the CPU frequency?" try searching gamedev.stackexchange.com for something like game loop. There are basically 2 methods. 1) Run as fast as possible and scale movement speeds etc based on how quick the game runs. 2) If you're too fast wait (sleep()) until we're ready for the next 'tick'. –  George Duckett Aug 12 '13 at 8:49
    
I contributed a few code snippets, let me know if they need more explaination! –  Gizmo Aug 12 '13 at 9:01
    
@Gizmo: I think they got rejected while I was away. I do note that since I don't actually code, I'm not sure how I'd have fitted that into my answer. Maybe you could use it to post your own answer with more details? I focused on history and high level implimentation rather than code, anyway. –  Journeyman Geek Aug 12 '13 at 14:18
2  
when I get back from work I'll rewrite my contribution.. ah those rejects.... :/ not even in edit history –  Gizmo Aug 12 '13 at 16:29

As an addition to Journeyman Geek's answer (because my edit got rejected) for the people who are interested in the coding part/developer perspective:

From the programmers perspective, for those who are interested, the DOS times were times where every CPU tick was important so programmers kept the code as fast as possible.

A typical scenario where any program will run at the max CPU speed is this simple (pseudo C):

int main()
{
    while(true)
    {

    }
}

this will run forever, now, let's turn this code snippet into a pseudo-DOS-game:

int main()
{
    bool GameRunning = true;
    while(GameRunning)
    {
        ProcessUserMouseAndKeyboardInput();
        ProcessGamePhysics();
        DrawGameOnScreen();

        //close game
        if(Pressed(KEY_ESCAPE))
        {
            GameRunning = false;
        }
    }
}

unless the DrawGameOnScreen functions uses double buffering/V-sync (which was kind of expensive in the days when DOS games were made), the game will run at maximum CPU speed. On a modern day mobile i7 this would run at around 1,000,000 to 5,000,000 times per second (depending on the laptop configuration and current cpu usage).

This would mean that if I could get any DOS game working on my modern CPU in my 64bit windows I could get more than a thousand (1000!) FPS which is too fast for any human to play if the physics processing "assumes" it runs between 50-60 fps.

What current day developers (can) do is:

  1. Enable V-Sync in the game (not available for windowed applications* [a.k.a. only available in full-screen apps])
  2. Measure the time difference between the last update and update the physics according to the time difference which effectively make the game/program run at the same speed regardless of the FPS rate
  3. Limit the framerate programmatically

* depending on the graphics card/driver/os configuration it may be possible.

For point 1 there is no example I will show because it's not really any "programming". It's just using the graphics features.

As for point 2 and 3 I will show the corresponding code snippets and explanations:

2:

int main()
{
    bool GameRunning = true;
    long long LastTick = GetCurrentTime();
    long long TimeDifference;
    while(GameRunning)
    {
        TimeDifference = GetCurrentTime()-LastTick;
        LastTick = GetCurrentTime();

        //process movement based on how many time passed and which keys are pressed
        ProcessUserMouseAndKeyboardInput(TimeDifference);

        //pass the time difference to the physics engine so it can calculate anything time-based
        ProcessGamePhysics(TimeDifference);

        DrawGameOnScreen();

        //close game if escape is pressed
        if(Pressed(KEY_ESCAPE))
        {
            GameRunning = false;
        }
    }
}

Here you can see the user input and physics take the time difference into account, yet you could still get 1000+ FPS on screen because the loop is running as fast as possible. Because the physics engine knows how much time passed, it doesn't have to depend on "no assumptions" or "a certain framerate" so the game will work at the same speed on any cpu.

3:

What developers can do to limit the framerate to, for example, 30 FPS is actually nothing harder, just take a look:

int main()
{
    bool GameRunning = true;
    long long LastTick = GetCurrentTime();
    long long TimeDifference;

    double FPS_WE_WANT = 30;
    //how many milliseconds need to pass before we need to draw again so we get the framerate we want?
    double TimeToPassBeforeNextDraw = 1000.0/FPS_WE_WANT;
    //For the geek programmers: note, this is pseudo code so I don't care for variable types and return types..
    double LastDraw = GetCurrentTime();

    while(GameRunning)
    {
        TimeDifference = GetCurrentTime()-LastTick;
        LastTick = GetCurrentTime();

        //process movement based on how many time passed and which keys are pressed
        ProcessUserMouseAndKeyboardInput(TimeDifference);

        //pass the time difference to the physics engine so it can calculate anything time-based
        ProcessGamePhysics(TimeDifference);

        //if certain amount of milliseconds pass...
        if(LastTick-LastDraw >= TimeToPassBeforeNextDraw)
        {
            //draw our game
            DrawGameOnScreen();

            //and save when we last drawn the game
            LastDraw = LastTick;
        }

        //close game if escape is pressed
        if(Pressed(KEY_ESCAPE))
        {
            GameRunning = false;
        }
    }
}

What happens here is that the program counts how many milliseconds have passed, if a certain amount is reached (33 ms) then it redraws the game screen, effectively applying a frame rate near ~30.

Also, depending on the developer he/she may choose to limit ALL processing to 30 fps with the above code slightly modified to this:

int main()
{
    bool GameRunning = true;
    long long LastTick = GetCurrentTime();
    long long TimeDifference;

    double FPS_WE_WANT = 30;
    //how many miliseconds need to pass before we need to draw again so we get the framerate we want?
    double TimeToPassBeforeNextDraw = 1000.0/FPS_WE_WANT;
    //For the geek programmers: note, this is pseudo code so I don't care for variable types and return types..
    double LastDraw = GetCurrentTime();

    while(GameRunning)
    {

        LastTick = GetCurrentTime();
        TimeDifference = LastTick-LastDraw;

        //if certain amount of miliseconds pass...
        if(TimeDifference >= TimeToPassBeforeNextDraw)
        {
            //process movement based on how many time passed and which keys are pressed
            ProcessUserMouseAndKeyboardInput(TimeDifference);

            //pass the time difference to the physics engine so it can calculate anything time-based
            ProcessGamePhysics(TimeDifference);


            //draw our game
            DrawGameOnScreen();

            //and save when we last drawn the game
            LastDraw = LastTick;

            //close game if escape is pressed
            if(Pressed(KEY_ESCAPE))
            {
                GameRunning = false;
            }
        }
    }
}

There are a few other methods, and some of them I really do hate.

For example, using sleep(<amount of milliseconds>).

I know this is one method to limit the framerate, but what happens when your game processing takes 3 milliseconds or more? And then you execute the sleep...

this will result in a lower framerate than the one which only sleep() should be causing.

Let's for example take a sleep time of 16 ms. this would make the program run at 60 hz. now the processing of the data, input, drawing and all the stuff takes 5 miliseconds. we are at 21 miliseconds for one loop now which results in slightly less than 50 hz, while you could easily still be at 60 hz but because of the sleep it's impossible.

One solution would be to make an adaptive sleep in the form of measuring the processing time and deducting the processing time from the wanted sleep resulting in fixing our "bug":

int main()
{
    bool GameRunning = true;
    long long LastTick = GetCurrentTime();
    long long TimeDifference;
    long long NeededSleep;

    while(GameRunning)
    {
        TimeDifference = GetCurrentTime()-LastTick;
        LastTick = GetCurrentTime();

        //process movement based on how many time passed and which keys are pressed
        ProcessUserMouseAndKeyboardInput(TimeDifference);

        //pass the time difference to the physics engine so it can calculate anything time-based
        ProcessGamePhysics(TimeDifference);


        //draw our game
        DrawGameOnScreen();

        //close game if escape is pressed
        if(Pressed(KEY_ESCAPE))
        {
            GameRunning = false;
        }

        NeededSleep = 33 - (GetCurrentTime()-LastTick);
        if(NeededSleep > 0)
        {
            Sleep(NeededSleep);
        }
    }
}
share|improve this answer

One main cause is using a delay loop which is calibrated when the program starts. They count how many times a loop executes in a known amount of time and divide it for generating smaller delays. This can then be used to implement a sleep() function to pace the game's execution. The problems come when this counter is maxed due to processors being so much faster on the loop that the small delay ends up being way too small. In addition modern processors change speed based on load, sometimes even on a per-core basis, which makes the delay off even more.

For really old PC games they just ran as fast as they could with no regard to trying to pace the game. This was more the case in the IBM PC XT days however where a turbo button existed that slowed the system to match a 4.77mhz processor for this reason.

Modern games and libraries like DirectX have access to high precession timers so don't need to use calibrated code based delay loops.

share|improve this answer

All first PC's ran at the same speed in the beginning, so there was no need to account for difference in speeds.

Also, many games in the beginning had a pretty fixed cpu-load, so it was unlikely that some frames would run faster than others.

Nowadays, with yer kids and yer fancy FPS shooters, you can look at the floor one second, and at the grand canyon the next, load-variation happens more often. :)

(And, few hardware consoles are fast enough to run games at 60 fps constantly. This is mostly due to the fact that console developers opt for 30 Hz and make the pixels twice as shiny...)

share|improve this answer
    
+1 for the pun at the end ;) –  Kwaio Aug 12 '13 at 14:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.