t_size MultiWaitAbortable_MsgLoop(const HANDLE * ev, t_size evCount, abort_callback & abort) { pfc::array_t<HANDLE> handles; handles.set_size(evCount + 1); handles[0] = abort.get_abort_event(); pfc::memcpy_t(handles.get_ptr() + 1, ev, evCount); for(;;) { SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(handles.get_count(), handles.get_ptr(), FALSE, INFINITE, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: PFC_ASSERT(!"How did we get here?"); uBugCheck(); case WAIT_OBJECT_0: throw exception_aborted(); case WAIT_FAILED: WIN32_OP_FAIL(); default: { t_size index = (t_size)(status - (WAIT_OBJECT_0 + 1)); if (index == evCount) { ProcessPendingMessages(); } else if (index < evCount) { return index; } else { uBugCheck(); } } } } }
bool WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort, DWORD timeout /*must not be INFINITE*/) { PFC_ASSERT( timeout != INFINITE ); const DWORD entry = GetTickCount(); const HANDLE handles[2] = {ev, abort.get_abort_event()}; for(;;) { const DWORD done = GetTickCount() - entry; if (done >= timeout) return false; SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(2, handles, FALSE, timeout - done, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: return false; case WAIT_OBJECT_0: return true; case WAIT_OBJECT_0 + 1: throw exception_aborted(); case WAIT_OBJECT_0 + 2: ProcessPendingMessages(); break; case WAIT_FAILED: WIN32_OP_FAIL(); default: uBugCheck(); } } }
s32 CALLBACK WinMain(HINSTANCE instance, HINSTANCE, LPSTR, s32) { WNDCLASS WindowClass = {}; WindowClass.style = CS_HREDRAW|CS_VREDRAW; WindowClass.lpfnWndProc = MainWindowCallback; WindowClass.hInstance = instance; WindowClass.lpszClassName = "Win32WindowClass"; WindowClass.hCursor = LoadCursor(0, IDC_ARROW); WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION); if(RegisterClassA(&WindowClass)) { HWND Window = CreateWindowExA( 0, WindowClass.lpszClassName, "Steven's Awesome App", WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0,0,instance,0); if(Window) { HDC DeviceContext = GetDC(Window); HGLRC GLRenderContext = InitializeOpenGL(Window, DeviceContext); GlobalRunning = true; LoadGLFunctions(); SetupTriangle(); glClearColor(0.0f,1.0f,0.0f,1.0f); while(GlobalRunning) { ProcessPendingMessages(); Render(GLRenderContext); SwapBuffers(DeviceContext); } wglMakeCurrent(DeviceContext, 0); wglDeleteContext(GLRenderContext); ReleaseDC(Window, DeviceContext); } } return 0; }
void SleepAbortable_MsgLoop(abort_callback & abort, DWORD timeout /*must not be INFINITE*/) { PFC_ASSERT( timeout != INFINITE ); const DWORD entry = GetTickCount(); const HANDLE handles[1] = {abort.get_abort_event()}; for(;;) { const DWORD done = GetTickCount() - entry; if (done >= timeout) return; SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(1, handles, FALSE, timeout - done, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: return; case WAIT_OBJECT_0: throw exception_aborted(); case WAIT_OBJECT_0 + 1: ProcessPendingMessages(); default: throw exception_win32(GetLastError()); } } }
void WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort) { const HANDLE handles[2] = {ev, abort.get_abort_event()}; for(;;) { SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(2, handles, FALSE, INFINITE, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: PFC_ASSERT(!"How did we get here?"); uBugCheck(); case WAIT_OBJECT_0: return; case WAIT_OBJECT_0 + 1: throw exception_aborted(); case WAIT_OBJECT_0 + 2: ProcessPendingMessages(); break; case WAIT_FAILED: WIN32_OP_FAIL(); default: uBugCheck(); } } }
//Our main loop which should continue running as long as we don't quite the game static void MainLoop() { char DLLFilePath[MAX_PATH]; char *onePastLastSlash; DWORD pathSize = GetModuleFileNameA(NULL, DLLFilePath, sizeof(DLLFilePath)); onePastLastSlash = DLLFilePath; for (char *scan = DLLFilePath; *scan; scan++) { if (*scan == '\\') { onePastLastSlash = scan + 1; } } char DLLFullPath[MAX_PATH]; BuildFileFullPath(&state, "playground game.dll", DLLFullPath, sizeof(DLLFullPath)); char tempDLLFullPath[MAX_PATH]; BuildFileFullPath(&state, "playground game_temp.dll", tempDLLFullPath, sizeof(tempDLLFullPath)); char PDBFullPath[MAX_PATH]; BuildFileFullPath(&state, "playground game.pdb", PDBFullPath, sizeof(PDBFullPath)); char tempPDBFullPath[MAX_PATH]; BuildFileFullPath(&state, "playground game_temp.pdb", tempPDBFullPath, sizeof(tempPDBFullPath)); Input = {}; Input.UP.Button = VK_UP; Input.DOWN.Button = VK_DOWN; Input.RIGHT.Button = VK_RIGHT; Input.LEFT.Button = VK_LEFT; LARGE_INTEGER performanceFrequency; QueryPerformanceFrequency(&performanceFrequency); TicksPerSecond = performanceFrequency.QuadPart; int monitorRefreshHZ = 60; HDC deviceContext = GetDC(Window.Window); int refreshHz = GetDeviceCaps(deviceContext, VREFRESH); ReleaseDC(Window.Window, deviceContext); if (refreshHz > 1) { monitorRefreshHZ = refreshHz; } float gameUpdateHZ = (float)(monitorRefreshHZ); float targetSecondsPerFrame = 1.0f / gameUpdateHZ; UINT desiredSchedulerTime = 1; bool sleepIsSmaller = true;//timeBeginPeriod(desiredSchedulerTime) == TIMERR_NOERROR; LARGE_INTEGER lastTick = GetTicks(); float updateTime = 0; int updates = 0; double frames = 0; double frameTime = 0; while (IsRunning) { /* start_loop = clock(); */ FILETIME newWriteTimeDLL = GetLastWriteTime(DLLFullPath); FILETIME newWriteTimePDB = GetLastWriteTime(PDBFullPath); if (CompareFileTime(&newWriteTimeDLL, &Game.LastWriteTimeDLL) != 0 && CompareFileTime(&newWriteTimeDLL, &Game.LastWriteTimePDB) != 0) { UnloadGameCode(&Game); CopyFile(PDBFullPath, tempPDBFullPath, FALSE); Game = LoadGameCode(DLLFullPath, tempDLLFullPath); Game.Game_Init(Dimensions); } LARGE_INTEGER gameTimerStart = GetTicks(); ProcessPendingMessages(&Keys); ProcessInput(&Input); //Update everything //Update the game Game.Game_Update(&Input); /*NOTE(kai): TEST ONLY*/ //Testing if A button is pressed if (IsKeyDown(&Keys, 'A')) { OutputDebugString("Key: a is pressed\n"); } //Testing if A button is released if (IsKeyUp(&Keys, 'A')) { OutputDebugString("Key: a is released\n"); } //Render everything //Clear the window ClearWindow(); //Render the game Game.Game_Render(); LARGE_INTEGER gameTimerEnd = GetTicks(); frameTime += (double)(1000.0f * GetSecondsElapsed(gameTimerStart, gameTimerEnd)); frames++; //frames += 1000.0f / (double)(1000.0f * GetSecondsElapsed(gameTimerStart, gameTimerEnd)); //PrintTimeElapsed(lastTick, gameTimerEnd); float secondsElapsedForFrame = GetSecondsElapsed(lastTick, GetTicks()); if (secondsElapsedForFrame < targetSecondsPerFrame) { if (sleepIsSmaller) { DWORD sleepTime = (DWORD)(1000.0f * (targetSecondsPerFrame - secondsElapsedForFrame)); if (sleepTime > 0) { Sleep(sleepTime); } } while (secondsElapsedForFrame < targetSecondsPerFrame) { secondsElapsedForFrame = GetSecondsElapsed(lastTick, GetTicks()); } updates++; } updateTime += GetSecondsElapsed(lastTick, GetTicks()); if (updateTime >= 1.0f) { double avgFPS = 1000.0f / ((frameTime) / frames); std::cout << "UPS: " << updates << ", average FPS: " << avgFPS << ", average work/frame: " << (frameTime) / frames << "\n"; frames = 0; frameTime = 0; updates = 0; updateTime = 0; } LARGE_INTEGER endTick = GetTicks(); //PrintTimeElapsed(lastTick, endTick); lastTick = endTick; //Render the window RenderWindow(Window.Window); /* //calc fps calcfps(); static int framecount = 0; framecount++; if (framecount == 10) { framecount = 0; std::cout << "frame per second is : " << (fps) << std::endl; } //QueryPerformanceCounter(&t_current_loop); end_loop = clock(); //float frameticks = (t_current_loop.QuadPart - t_previous_loop.QuadPart) / ((frequency_loop.QuadPart) / 1000.0); float frameticks = ((float)(end_loop - start_loop) / CLOCKS_PER_SEC) * 1000.0f; //print the current fps // std::cout << 1000/frameticks << std::endl; if (1000.0f / max_fps > frameticks){ Sleep(1000.0f / max_fps - frameticks); } */ } //Release resources (if there is any) and destory the window Release(); }