1#if !defined(BACKEND_WIN)
2#define _POSIX_C_SOURCE 199309L
3#else
4#include <windows.h>
5#endif
6
7#include <stdarg.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <time.h>
11
12#include "maus.h"
13
14static void vlog(FILE* fd, const char* fmt, va_list ap);
15
16static void vlog(FILE* fd, const char* fmt, va_list ap)
17{
18 fprintf(fd, "maus: ");
19 vfprintf(fd, fmt, ap);
20}
21
22void maus_die(const char* fmt, ...)
23{
24 va_list ap;
25
26 va_start(ap, fmt);
27 vlog(stderr, fmt, ap);
28 va_end(ap);
29
30 exit(EXIT_FAILURE);
31}
32
33uint64_t maus_get_time_ns(void)
34{
35#if !defined(_WIN32)
36 struct timespec ts;
37 clock_gettime(CLOCK_MONOTONIC, &ts);
38 return ts.tv_sec * 1000000000 + ts.tv_nsec;
39#else
40 static LARGE_INTEGER frequency = {0};
41 LARGE_INTEGER counter;
42 uint64_t sec;
43 uint64_t rem;
44
45 if (frequency.QuadPart == 0)
46 QueryPerformanceFrequency(&frequency);
47
48 QueryPerformanceCounter(&counter);
49
50 sec = counter.QuadPart / frequency.QuadPart;
51 rem = counter.QuadPart % frequency.QuadPart;
52
53 return (sec * 1000000000) + ((rem * 1000000000) / frequency.QuadPart);
54#endif
55}
56
57void maus_log(FILE* fd, const char* fmt, ...)
58{
59 va_list ap;
60
61 va_start(ap, fmt);
62 vlog(fd, fmt, ap);
63 fputc('\n', fd);
64 va_end(ap);
65}
66
67void maus_target_fps(Maus* mw, uint32_t fps)
68{
69 uint64_t ns_frame;
70 uint64_t cur_time;
71 uint64_t elapsed;
72 uint64_t sleep;
73
74 #if !defined(_WIN32)
75 struct timespec ts;
76 #endif
77
78 if (fps == 0)
79 return;
80
81 ns_frame = 1000000000 / fps; /* max ns a frame can take */
82 cur_time = maus_get_time_ns();
83 elapsed = cur_time - mw->frame_time_last;
84
85 /* if early finish, sleep for the remaining time balance */
86 if (elapsed < ns_frame) {
87 sleep = ns_frame - elapsed;
88 #if !defined(_WIN32)
89 ts.tv_sec = sleep / 1000000000;
90 ts.tv_nsec = sleep % 1000000000;
91 nanosleep(&ts, NULL);
92 #else
93 Sleep((DWORD)((sleep + 999999) / 1000000));
94 #endif
95 }
96
97 mw->frame_time_last = maus_get_time_ns();
98}
99