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_sleep(uint32_t ms)
68{
69#if !defined(_WIN32)
70 struct timespec ts;
71
72 ts.tv_sec = ms / 1000;
73 ts.tv_nsec = (ms % 1000) * 1000000;
74 nanosleep(&ts, NULL);
75#else
76 Sleep((DWORD)ms);
77#endif
78}
79
80void maus_target_fps(Maus* mw, uint32_t fps)
81{
82 uint64_t ns_frame;
83 uint64_t cur_time;
84 uint64_t elapsed;
85 uint64_t sleep;
86
87 if (fps == 0)
88 return;
89
90 ns_frame = 1000000000 / fps; /* max ns a frame can take */
91 cur_time = maus_get_time_ns();
92 elapsed = cur_time - mw->frame_time_last;
93
94 /* if early finish, sleep for the remaining time balance */
95 if (elapsed < ns_frame) {
96 sleep = ns_frame - elapsed;
97 maus_sleep((uint32_t)((sleep + 999999) / 1000000));
98 }
99
100 mw->frame_time_last = maus_get_time_ns();
101}
102