master uint/maus / source / maus.c
 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	va_start(ap, fmt);
26	vlog(stderr, fmt, ap);
27	va_end(ap);
28
29	exit(EXIT_FAILURE);
30}
31
32uint64_t maus_get_time_ns(void)
33{
34#if !defined(_WIN32)
35	struct timespec ts;
36	clock_gettime(CLOCK_MONOTONIC, &ts);
37	return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
38#else
39	static LARGE_INTEGER frequency = {0};
40	if (frequency.QuadPart == 0)
41		QueryPerformanceFrequency(&frequency);
42
43	LARGE_INTEGER counter;
44	QueryPerformanceCounter(&counter);
45
46	uint64_t sec = counter.QuadPart / frequency.QuadPart;
47	uint64_t rem = counter.QuadPart % frequency.QuadPart;
48
49	return (sec * 1000000000ULL) + ((rem * 1000000000ULL) / frequency.QuadPart);
50#endif
51}
52
53void maus_log(FILE* fd, const char* fmt, ...)
54{
55	va_list ap;
56	va_start(ap, fmt);
57	vlog(fd, fmt, ap);
58	fputc('\n', fd);
59	va_end(ap);
60}
61
62void maus_target_fps(Maus* mw, uint32_t fps)
63{
64	if (fps == 0)
65		return;
66
67	uint64_t ns_frame = 1000000000ULL / fps; /* max ns a frame can take */
68	uint64_t cur_time = maus_get_time_ns();
69	uint64_t elapsed = cur_time - mw->frame_time_last;
70
71	/* if early finish, sleep for the remaining time balance */
72	if (elapsed < ns_frame) {
73		uint64_t sleep = ns_frame - elapsed;
74	#if !defined(_WIN32)
75		struct timespec ts;
76		ts.tv_sec = sleep / 1000000000ULL;
77		ts.tv_nsec = sleep % 1000000000ULL;
78		nanosleep(&ts, NULL);
79	#else /* unix */
80		Sleep((DWORD)((sleep + 999999ULL) / 1000000ULL));
81	#endif /* platform */
82	}
83
84	mw->frame_time_last = maus_get_time_ns();
85}
86