Stabilized main loop.

Cherry picked timeBeginPeriod.
Ref PR #85.
This commit is contained in:
Muzychenko Andrey 2021-11-11 18:03:23 +03:00
parent c29acb12d0
commit ec13bca129
4 changed files with 64 additions and 59 deletions

View File

@ -225,12 +225,15 @@ void pb::ballset(int x, int y)
ball->Speed = maths::normalize_2d(&ball->Acceleration); ball->Speed = maths::normalize_2d(&ball->Acceleration);
} }
int pb::frame(int time) void pb::frame(int time)
{ {
static int frameTime = 0; static int frameTime = 0;
if (time > 100) if (time > 100)
time = 100; time = 100;
if (time <= 0)
return;
float timeMul = time * 0.001f; float timeMul = time * 0.001f;
if (!mode_countdown(time)) if (!mode_countdown(time))
{ {
@ -284,7 +287,6 @@ int pb::frame(int time)
MainTable->tilt(time_now); MainTable->tilt(time_now);
} }
} }
return 1;
} }
void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)

View File

@ -26,7 +26,7 @@ public:
static void toggle_demo(); static void toggle_demo();
static void replay_level(int demoMode); static void replay_level(int demoMode);
static void ballset(int x, int y); static void ballset(int x, int y);
static int frame(int time); static void frame(int time);
static void timed_frame(float timeNow, float timeDelta, bool drawBalls); static void timed_frame(float timeNow, float timeDelta, bool drawBalls);
static void window_size(int* width, int* height); static void window_size(int* width, int* height);
static void pause_continue(); static void pause_continue();

View File

@ -12,6 +12,8 @@
#include "splash.h" #include "splash.h"
#include "render.h" #include "render.h"
const int TargetFrameTime = 8;
HINSTANCE winmain::hinst = nullptr; HINSTANCE winmain::hinst = nullptr;
HWND winmain::hwnd_frame = nullptr; HWND winmain::hwnd_frame = nullptr;
HCURSOR winmain::mouse_hsave; HCURSOR winmain::mouse_hsave;
@ -28,8 +30,6 @@ int winmain::last_mouse_y;
int winmain::mouse_down; int winmain::mouse_down;
int winmain::no_time_loss; int winmain::no_time_loss;
DWORD winmain::then;
DWORD winmain::now;
UINT winmain::iFrostUniqueMsg; UINT winmain::iFrostUniqueMsg;
bool winmain::restart = false; bool winmain::restart = false;
@ -51,6 +51,10 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
options::ReadOptions(); options::ReadOptions();
auto regSpaceCadet = pinball::get_rc_string(166, 0); auto regSpaceCadet = pinball::get_rc_string(166, 0);
// Needed for sub 16ms sleep
if (timeBeginPeriod(1) == TIMERR_NOERROR)
atexit(ResetTimer);
if (options::get_int(regSpaceCadet, "Table Version", 1) <= 1) if (options::get_int(regSpaceCadet, "Table Version", 1) <= 1)
{ {
auto tmpBuf = memory::allocate(0x1F4u); auto tmpBuf = memory::allocate(0x1F4u);
@ -221,7 +225,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
pb::replay_level(0); pb::replay_level(0);
DWORD someTimeCounter = 300u, prevTime = 0u; DWORD someTimeCounter = 300u, prevTime = 0u;
then = timeGetTime(); int sleepRemainder = 0, frameDuration = TargetFrameTime;
while (true) while (true)
{ {
if (!someTimeCounter) if (!someTimeCounter)
@ -259,38 +263,26 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
if (has_focus) if (has_focus)
{ {
if (mouse_down) if (mouse_down && frameDuration >= 2)
{
now = timeGetTime();
if (now - then >= 2)
{ {
/*last_mouse_n is in client coordinates*/ /*last_mouse_n is in client coordinates*/
POINT Point; POINT Point;
GetCursorPos(&Point); GetCursorPos(&Point);
ScreenToClient(hwnd_frame, &Point); ScreenToClient(hwnd_frame, &Point);
pb::ballset(last_mouse_x - Point.x, Point.y - last_mouse_y); pb::ballset(last_mouse_x - Point.x, Point.y - last_mouse_y);
Point = POINT{last_mouse_x, last_mouse_y}; Point = POINT{ last_mouse_x, last_mouse_y };
ClientToScreen(hwnd_frame, &Point); ClientToScreen(hwnd_frame, &Point);
SetCursorPos(Point.x, Point.y); SetCursorPos(Point.x, Point.y);
} }
}
if (!single_step) if (!single_step)
{ {
now = timeGetTime(); auto frameStart = timeGetTime();
if (no_time_loss) auto dt = frameDuration;
{ if (!no_time_loss)
then = now;
no_time_loss = 0;
}
if (now == then)
{
Sleep(8u);
}
else
{
auto dt = now - then;
pb::frame(dt); pb::frame(dt);
else
no_time_loss = 0;
if (DispGRhistory) if (DispGRhistory)
{ {
@ -303,7 +295,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
gdrv::ScrollBitmapHorizontal(&gfr_display, -1); gdrv::ScrollBitmapHorizontal(&gfr_display, -1);
auto target = 8.0f; float target = TargetFrameTime;
auto scale = height / target / 2; auto scale = height / target / 2;
gdrv::fill_bitmap(&gfr_display, 1, height, width - 1, 0, 0); // Background gdrv::fill_bitmap(&gfr_display, 1, height, width - 1, 0, 0); // Background
@ -318,9 +310,17 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
gdrv::blit(&gfr_display, 0, 0, render::vscreen.Width - width, 0, width, height); gdrv::blit(&gfr_display, 0, 0, render::vscreen.Width - width, 0, width, height);
} }
auto updateEnd = timeGetTime();
auto sleepDuration = TargetFrameTime - (int)(updateEnd - frameStart) - sleepRemainder;
if (sleepDuration > 0)
Sleep(sleepDuration);
auto frameEnd = timeGetTime();
sleepRemainder = (frameEnd - updateEnd) - sleepDuration;
frameDuration = min(frameEnd - frameStart, TargetFrameTime * 2);
--someTimeCounter; --someTimeCounter;
then = now;
}
} }
} }
} }

View File

@ -26,11 +26,14 @@ public:
private: private:
static int return_value, bQuit, DispFrameRate, DispGRhistory, activated; static int return_value, bQuit, DispFrameRate, DispGRhistory, activated;
static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss; static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss;
static DWORD then, now;
static UINT iFrostUniqueMsg; static UINT iFrostUniqueMsg;
static gdrv_bitmap8 gfr_display; static gdrv_bitmap8 gfr_display;
static HCURSOR mouse_hsave; static HCURSOR mouse_hsave;
static bool restart; static bool restart;
static HDC _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); static HDC _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
static void ResetTimer()
{
timeEndPeriod(1u);
}
}; };