-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathglobal.h
329 lines (284 loc) · 10.9 KB
/
global.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#pragma once
#include "host.h"
#ifdef _WIN32
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
# define NTDDI_VERSION NTDDI_VISTA
# elif _WIN32_WINNT < 0x0600
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0502//0x0501 excludes SetDllDirectory, so I need to put it at 0x0502
# define NTDDI_VERSION NTDDI_WS03 // actually NTDDI_WINXPSP2, but MinGW sddkddkver.h gets angry about that
# endif
# define _WIN32_IE 0x0600
//the namespace pollution this causes is massive, but without it, there's a bunch of functions that
// just tail call kernel32.dll. With it, they can be inlined.
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef interface // screw that, I'm not interested in COM shittery
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE //strdup, realpath, asprintf
#endif
#define _strdup strdup //and windows is being windows as usual
#define __STDC_LIMIT_MACROS //how many of these stupid things exist
#define __STDC_FORMAT_MACROS//if I include a header, it's because I want to use its contents
#define __STDC_CONSTANT_MACROS
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include "function.h"
typedef void(*funcptr)();
//Note to anyone interested in reusing these objects:
//Many, if not most, of them will likely change their interface, likely quite fundamentally, in the future.
//No attempt is made to keep any kind of backwards or forwards compatibility.
//#include "function.h"
//#ifndef NO_ANON_UNION_STRUCT//For crappy compilers.
//Mandatory because there's a pile of unions in struct config.
#define UNION_BEGIN union {
#define UNION_END };
#define STRUCT_BEGIN struct {
#define STRUCT_END };
//#else
//#define UNION_BEGIN
//#define UNION_END
//#define STRUCT_BEGIN
//#define STRUCT_END
//#endif
#define with(obj) for(bool FIRST=true;FIRST;FIRST=false)for(obj;FIRST;FIRST=false)
#define JOIN_(x, y) x ## y
#define JOIN(x, y) JOIN_(x, y)
//some magic stolen from http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx
//C++ can be so messy sometimes...
template<typename T, size_t N> char(&ARRAY_SIZE_CORE(T(&x)[N]))[N];
#define ARRAY_SIZE(x) (sizeof(ARRAY_SIZE_CORE(x)))
//requirements:
//- static_assert(false) throws something at compile time
//- multiple static_assert(true) works
//- does not require unique names for each assertion
//- zero traces left in the object files, assuming no debug info
//- zero warnings under any compiler
//- static_assert(2+2 < 5); works at the global scope
//- static_assert(2+2 < 5); works as a class member
//- static_assert(2+2 < 5); works inside a function
//- static_assert(2+2 < 5); works in all of the above when templates are involved
//- works on all compilers
//optional:
//- (FAILED) works if compiled as C (can fix with an ifdef, but I'm lazy)
//- can name assertions, if desired
#ifdef __GNUC__
#define MAYBE_UNUSED __attribute__((__unused__)) // shut up, stupid warnings
#define TYPENAME_IF_GCC typename
#else
#define MAYBE_UNUSED
#define TYPENAME_IF_GCC
#endif
template<bool x> struct static_assert_t;
template<> struct static_assert_t<true> { struct STATIC_ASSERTION_FAILED {}; };
template<> struct static_assert_t<false> {};
//#define static_assert(expr)
// typedef TYPENAME_IF_NEEDED static_assert_t<(bool)(expr)>::STATIC_ASSERTION_FAILED
// JOIN(static_assertion_, __COUNTER__) MAYBE_UNUSED;
#define static_assert(expr) \
enum { \
JOIN(static_assertion_, __COUNTER__) = \
sizeof(TYPENAME_IF_GCC static_assert_t<(bool)(expr)>::STATIC_ASSERTION_FAILED) \
} MAYBE_UNUSED
#ifdef __GNUC__
#define ALIGN(n) __attribute__((aligned(n)))
#endif
#ifdef _MSC_VER
#define ALIGN(n) __declspec(align(n))
#endif
#ifdef __cplusplus
class anyptr {
void* data;
public:
template<typename T> anyptr(T* data_) { data=(void*)data_; }
template<typename T> operator T*() { return (T*)data; }
template<typename T> operator const T*() const { return (const T*)data; }
};
#else
typedef void* anyptr;
#endif
#include <stdlib.h> // needed because otherwise I get errors from malloc_check being redeclared.
anyptr malloc_check(size_t size);
anyptr try_malloc(size_t size);
#define malloc malloc_check
anyptr realloc_check(anyptr ptr, size_t size);
anyptr try_realloc(anyptr ptr, size_t size);
#define realloc realloc_check
anyptr calloc_check(size_t size, size_t count);
anyptr try_calloc(size_t size, size_t count);
#define calloc calloc_check
//if I cast it to void, that means I do not care, so shut the hell up about warn_unused_result.
template<typename T> static inline void ignore(T t) {}
//too reliant on non-ancient compilers
////some SFINAE shenanigans to call T::create if it exists, otherwise new() - took an eternity to google up
////don't use this template yourself, use generic_create/destroy instead
//template<typename T> class generic_create_core {
// template<int G> class int_eater {};
//public:
// template<typename T2> static T* create(T2*, int_eater<sizeof(&T2::create)>*) { return T::create(); }
// static T* create(T*, ...) { return new T(); }
//
// template<typename T2> static void destroy(T* obj, T2*, int_eater<sizeof(&T2::release)>*) { obj->release(); }
// static void destroy(T* obj, T*, ...) { delete obj; }
//};
//template<typename T> T* generic_create() { return generic_create_core<T>::create((T*)NULL, NULL); }
//template<typename T> void generic_delete(T* obj) { generic_create_core<T>::destroy(obj, (T*)NULL, NULL); }
template<typename T> T* generic_create() { return T::create(); }
template<typename T> T* generic_new() { return new T; }
template<typename T> void generic_delete(T* obj) { delete obj; }
template<typename T> void generic_release(T* obj) { obj->release(); }
template<typename T> void* generic_create_void() { return (void*)generic_create<T>(); }
template<typename T> void* generic_new_void() { return (void*)generic_new<T>(); }
template<typename T> void generic_delete_void(void* obj) { generic_delete((T*)obj); }
template<typename T> void generic_release_void(void* obj) { generic_release((T*)obj); }
class nocopy {
protected:
nocopy() {}
~nocopy() {}
//#ifdef HAVE_MOVE
// nocopy(nocopy&&) = default;
// const nocopy& operator=(nocopy&&) = default;
//#endif
private:
nocopy(const nocopy&);
const nocopy& operator=(const nocopy&);
};
/*
template<typename T> class autoptr : nocopy {
T* obj;
#ifdef HAVE_MOVE
public:
autoptr(T* obj) : obj(obj) {}
autoptr(map&& other) : obj(other.obj) { other.obj=NULL; }
~map() { delete obj; }
#else
unsigned int* refcount;
public:
autoptr(T* obj) : obj(obj)
{
this->refcount=new unsigned int;
this->refcount[0]=1;
}
autoptr(const autoptr& other) : obj(other.obj)
{
this->refcount=other.refcount;
this->refcount[0]++;
}
~autoptr()
{
this->refcount[0]--;
if (this->refcount[0]==0)
{
delete this->refcount;
delete this->obj;
}
}
#endif
T& operator*() { return *obj; }
T* operator->() { return obj; }
};
*/
#ifdef HAVE_MOVE
#define autoref nocopy
#else
template<typename T> class autoref {
unsigned int* refcount;
public:
autoref()
{
this->refcount=new unsigned int;
this->refcount[0]=1;
}
autoref(const autoref& other)
{
this->refcount=other.refcount;
this->refcount[0]++;
}
~autoref()
{
this->refcount[0]--;
if (this->refcount[0]==0)
{
((T*)this) -> release();
}
}
};
#endif
template<typename T> class autoptr : autoref<T> {
T* obj;
public:
autoptr(T* obj) : obj(obj) {}
void release() { delete obj; }
T& operator*() { return *obj; }
T* operator->() { return obj; }
};
#ifndef HAVE_ASPRINTF
void asprintf(char * * ptr, const char * fmt, ...);
#else
#define asprintf(...) ignore(asprintf(__VA_ARGS__))
#endif
//msvc:
//typedef unsigned long uint32_t;
//typedef unsigned __int64 uint64_t;
//typedef unsigned int size_t;
template<typename T> static inline T bitround(T in)
{
in--;
in|=in>>1;
in|=in>>2;
in|=in>>4;
in|=in>>8;
if (sizeof(T)>2) in|=in>>8>>8;
if (sizeof(T)>4) in|=in>>8>>8>>8>>8;
in++;
return in;
}
//If any interface defines a callback, free() is banned while inside this callback; other functions
// are allowed, unless otherwise specified. Other instances of the same interface may be used and
// freed, and other interfaces may be called.
//If an interface defines a function to set some state, and a callback for when this state changes,
// calling that function will not trigger the state callback.
//Unless otherwise specified, an interface may only be used from its owner thread (the creator).
// However, it is safe for any thread to create an interface, including having different threads
// use multiple instances of the same interface.
//Don't depend on any pointer being unique; for example, the None interfaces are static. However,
// even if they are (potentially) non-unique, following the instructed method to free them is safe;
// either they're owned by the one one giving them to you, or their free() handlers are empty, or
// they could even be refcounted.
//If a pointer is valid until anything from a set of functions is called (including if the set
// contains only one listed function), free() will also invalidate that pointer.
//"Implementation" means the implementation of the interfaces; the blocks of code that are called
// when a function is called on an interface.
//"User" means the one using the interfaces. Some interface implementations are users of other
// interfaces; for example, an implementation of libretro is also the user of a dylib.
//An implementation may, at its sole discretion, choose to define any implementation of undefined
// behaviour. After all, any result, including something well defined, is a valid interpretation of
// undefined behaviour. The user may, of course, not rely on that.
//Any function that starts with an underscore may only be called by the module that implements that
// function. ("Module" is defined as "anything whose compilation is controlled by the same #ifdef,
// or the file implementing an interface, whichever makes sense"; for example, window-win32-* is the
// same module.) The arguments and return values of these private functions may change meaning
// between modules, and the functions are not guaranteed to exist at all, or closely correspond to
// their name. For example, _window_init_misc on GTK+ instead initializes a component needed by the
// listboxes.
//This file, and many other parts of minir, uses a weird mix between Windows- and Linux-style
// filenames and paths. This is intentional; the author prefers Linux-style paths and directory
// structures, but Windows file extensions. .exe is less ambigous than no extension, and Windows'
// insistence on overloading the escape character is irritating. Since this excludes following
// any single OS, the rest is personal preference.
//This one doesn't really belong here, but it's used by both image.h and minir.h (and io.h, but image.h uses that).
//If minir.h grows a dependency on image.h or io.h, move this to image.h.
enum videoformat {
//these three are same values and order as in libretro - do not change
fmt_xrgb1555,
fmt_xrgb8888,
fmt_rgb565,
//these are used only in minir
fmt_none,//this should be 0, but libretro compatibility means I can't do that
fmt_rgb888,
fmt_argb1555,
fmt_argb8888,
};