wow
[vg.git] / src / vg / vg_platform.h
1 #ifndef VG_PLATFORM_H
2 #define VG_PLATFORM_H
3
4 #include "vg.h"
5 #include "vg_stdint.h"
6
7 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
8
9 typedef unsigned int uint;
10
11 typedef int v2i[2];
12 typedef int v3i[3];
13 typedef int v4i[4];
14 typedef float v2f[2];
15 typedef float v3f[3];
16 typedef float v4f[4];
17 typedef v2f m2x2f[2];
18 typedef v3f m3x3f[3];
19 typedef v3f m4x3f[4];
20 typedef v4f m4x4f[4];
21 typedef v3f boxf[2];
22
23 // Resource types
24 typedef struct vg_tex2d vg_tex2d;
25
26 struct vg_achievement
27 {
28 int is_set;
29 const char *name;
30 };
31
32 #define vg_static_assert _Static_assert
33 #define vg_list_size( A ) (sizeof(A)/sizeof(A[0]))
34 #define VG_MUST_USE_RESULT __attribute__((warn_unused_result))
35
36 #ifdef _WIN32_NO
37 #include <windows.h>
38
39 #ifdef I_THINK_THIS_IS_WHAT_MSCV_WANTS_BUT_HAVNT_TESTED_IT_YET
40
41 #define VG_DEPRECATED __declspec(deprecated)
42 #define VG_THREAD_LOCAL __declspec( thread )
43
44 #else /* MINGW-64 */
45
46 #define VG_THREAD_LOCAL __thread
47 #define VG_DEPRECATED __attribute__((deprecated))
48
49 #endif
50
51 typedef HANDLE vg_semaphore;
52 typedef HANDLE vg_mutex;
53 typedef u64 vg_timespec;
54
55 #else
56 #include <pthread.h>
57 #include <semaphore.h>
58
59 #define VG_DEPRECATED __attribute__((deprecated))
60 #define VG_THREAD_LOCAL __thread
61
62 typedef sem_t vg_semaphore;
63 typedef pthread_mutex_t vg_mutex;
64 typedef struct timespec vg_timespec;
65
66 #endif
67
68 static void vg_strncpy( const char *src, char *dst, u32 len )
69 {
70 for( u32 i=0; i<len; i++ )
71 {
72 dst[i] = src[i];
73
74 if( !src[i] )
75 break;
76 }
77 }
78
79 #include <stdlib.h>
80
81 #define VG_ZERO_NEW_MEM
82
83 static void vg_fatal_exit_loop( const char *error );
84 static void *vg_alloc( size_t size )
85 {
86 if( size == 0 )
87 return NULL;
88
89 void *ptr = malloc( size );
90
91 if( !ptr )
92 {
93 vg_fatal_exit_loop( "Out of memory" );
94 }
95
96 #ifdef VG_ZERO_NEW_MEM
97 u8 *bytes = ptr;
98 for( u32 i=0; i<size; i++ )
99 {
100 bytes[i] = 0x00;
101 }
102 #endif
103
104 return ptr;
105 }
106
107 static void *vg_realloc( void *orig, size_t size )
108 {
109 void *ptr = realloc( orig, size );
110
111 if( !ptr )
112 {
113 if( size == 0 )
114 return NULL;
115
116 vg_fatal_exit_loop( "Out of memory" );
117 }
118
119 return ptr;
120 }
121
122 /* seems to be a GCC bug when inlining this, its low priority anyway */
123 __attribute__ ((noinline))
124 static void vg_free( void *ptr )
125 {
126 free( ptr );
127 }
128
129 static void vg_required( void *ptr, const char *path )
130 {
131 if( !ptr )
132 {
133 vg_fatal_exit_loop( path );
134 }
135 }
136
137 #define VG_REQUIRED_ASSET( TYPE, DECL, FN, PATH, ... ) \
138 TYPE DECL = FN( PATH,##__VA_ARGS__ ); \
139 vg_required( DECL, "Resource is required but failed to load: '" PATH "'" );
140
141 #if 0
142 VG_DEPRECATED
143 char *strcpy(char* destination, const char* source);
144 VG_DEPRECATED
145 char *strncpy(char *restrict dest, const char *restrict src, size_t n);
146 VG_DEPRECATED
147 char *strcat(char *restrict dest, const char *restrict src);
148 VG_DEPRECATED
149 char *strncat(char *restrict dest, const char *restrict src, size_t n);
150 #endif
151
152 VG_DEPRECATED
153 void *malloc( size_t size );
154
155 VG_DEPRECATED
156 void *realloc( void *orig, size_t size );
157
158 VG_DEPRECATED
159 void free( void *ptr );
160
161 #include <stdio.h>
162 #include <dirent.h>
163 #include <string.h>
164 #include <stdarg.h>
165 #include <ctype.h>
166 #include <math.h>
167 #include <assert.h>
168
169 static int vg_thread_run( void *pfunc, void *data );
170 static void vg_thread_exit(void);
171 static void vg_set_thread_name( const char *name );
172 static int vg_semaphore_init( vg_semaphore *sem, u32 value );
173 static int vg_semaphore_trywait( vg_semaphore *sem );
174 static int vg_semaphore_wait( vg_semaphore *sem );
175 static int vg_semaphore_post( vg_semaphore *sem );
176 static void vg_semaphore_free( vg_semaphore *sem );
177 static int vg_mutex_init( vg_mutex *mutex );
178 static int vg_mutex_lock( vg_mutex *mutex );
179 static int vg_mutex_unlock( vg_mutex *mutex );
180 static void vg_mutex_free( vg_mutex *mutex );
181 static void vg_sleep_ms( long msec );
182 static double vg_time_diff( vg_timespec start, vg_timespec end );
183
184 #ifdef _WIN32_NO
185
186 static int vg_thread_run( void *pfunc, void *data )
187 {
188 HANDLE hThread = CreateThread
189 (
190 NULL, /* Thread attributes */
191 0, /* Stack size (0 = use default) */
192 pfunc, /* Thread start address */
193 data, /* Parameter to pass to the thread */
194 0, /* Creation flags */
195 NULL /* Thread id */
196 );
197
198 if ( hThread == NULL )
199 {
200 /*
201 * Thread creation failed.
202 * More details can be retrieved by calling GetLastError()
203 */
204 return 1;
205 }
206 else
207 {
208 CloseHandle( hThread );
209 return 0;
210 }
211 }
212
213 static void vg_thread_exit(void)
214 {
215 ExitThread(0);
216 }
217
218 static void vg_set_thread_name( const char *name )
219 {
220 /* I believe this is a meaningless concept in windows */
221 }
222
223 static int vg_semaphore_init( vg_semaphore *sem, u32 value );
224 static int vg_semaphore_trywait( vg_semaphore *sem );
225 static int vg_semaphore_wait( vg_semaphore *sem );
226 static int vg_semaphore_post( vg_semaphore *sem );
227 static void vg_semaphore_free( vg_semaphore *sem );
228 static int vg_mutex_init( vg_mutex *mutex );
229 static int vg_mutex_lock( vg_mutex *mutex );
230 static int vg_mutex_unlock( vg_mutex *mutex );
231 static void vg_mutex_free( vg_mutex *mutex );
232 static void vg_sleep_ms( long msec );
233 static double vg_time_diff( vg_timespec start, vg_timespec end );
234
235 #else
236
237 static int vg_thread_run( void *pfunc, void *data )
238 {
239 pthread_t hThread;
240 if( pthread_create( &hThread, NULL, pfunc, data ) )
241 {
242 return 1;
243 }
244 else
245 {
246 pthread_detach( hThread );
247 return 0;
248 }
249 }
250
251
252 static void vg_thread_exit(void)
253 {
254 pthread_exit(NULL);
255 }
256
257 static void vg_set_thread_name( const char *name )
258 {
259 /* not defined but links?? */
260 #if 0
261 pthread_setname_np(pthread_self());
262 #endif
263 }
264
265 static int vg_semaphore_init( vg_semaphore *sem, u32 value )
266 {
267 return !sem_init( sem, 0, value );
268 }
269
270 static int vg_semaphore_trywait( vg_semaphore *sem )
271 {
272 return !sem_trywait( sem );
273 }
274
275 static int vg_semaphore_wait( vg_semaphore *sem )
276 {
277 return !sem_wait( sem );
278 }
279
280 static int vg_semaphore_post( vg_semaphore *sem )
281 {
282 return !sem_post( sem );
283 }
284
285 static void vg_semaphore_free( vg_semaphore *sem )
286 {
287 sem_destroy( sem );
288 }
289
290 static int vg_mutex_init( vg_mutex *mutex )
291 {
292 memset( mutex, 0, sizeof(vg_mutex) );
293 return 1;
294 }
295
296 static int vg_mutex_lock( vg_mutex *mutex )
297 {
298 if( !pthread_mutex_lock( mutex ) )
299 return 1;
300 else
301 return 0;
302 }
303
304 static int vg_mutex_unlock( vg_mutex *mutex )
305 {
306 if( !pthread_mutex_unlock( mutex ) )
307 return 1;
308 else
309 return 0;
310 }
311
312 static void vg_mutex_free( vg_mutex *mutex )
313 {
314
315 }
316
317 static void vg_sleep_ms( long msec )
318 {
319 struct timespec ts;
320
321 ts.tv_sec = msec / 1000;
322 ts.tv_nsec = (msec % 1000) * 1000000;
323 nanosleep( &ts, &ts );
324 }
325
326 /* diff two timespecs in MS */
327 static double vg_time_diff( struct timespec start, struct timespec end )
328 {
329 double elapsed = 1000.0*end.tv_sec + 1e-6*end.tv_nsec
330 - (1000.0*start.tv_sec + 1e-6*start.tv_nsec);
331
332 return elapsed;
333 }
334
335 #endif
336
337 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
338 #define VG_MAX( A, B ) ((A)>(B)?(A):(B))
339
340 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
341 size_t emsize )
342 {
343 if( count+amount > *cap )
344 {
345 *cap = VG_MAX( (*cap)*2, (*cap)+amount );
346 return vg_realloc( buffer, (*cap) * emsize );
347 }
348
349 return buffer;
350 }
351
352 static void *buffer_fix( void *buffer, u32 count, u32 *cap, size_t emsize )
353 {
354 *cap = count;
355 return vg_realloc( buffer, (*cap) * emsize );
356 }
357
358 #endif