forked from sm64pc/sm64ex
-
Notifications
You must be signed in to change notification settings - Fork 1
/
platform.c
144 lines (122 loc) · 3.79 KB
/
platform.c
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
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include "cliopts.h"
#include "fs/fs.h"
/* NULL terminated list of platform specific read-only data paths */
/* priority is top first */
const char *sys_ropaths[] = {
".", // working directory
"!", // executable directory
#if defined(__linux__) || defined(__unix__)
// some common UNIX directories for read only stuff
"/usr/local/share/sm64pc",
"/usr/share/sm64pc",
"/opt/sm64pc",
#endif
NULL,
};
/* these are not available on some platforms, so might as well */
char *sys_strlwr(char *src) {
for (unsigned char *p = (unsigned char *)src; *p; p++)
*p = tolower(*p);
return src;
}
char *sys_strdup(const char *src) {
const unsigned len = strlen(src) + 1;
char *newstr = malloc(len);
if (newstr) memcpy(newstr, src, len);
return newstr;
}
int sys_strcasecmp(const char *s1, const char *s2) {
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
int result;
if (p1 == p2)
return 0;
while ((result = tolower(*p1) - tolower(*p2++)) == 0)
if (*p1++ == '\0')
break;
return result;
}
const char *sys_file_extension(const char *fpath) {
const char *fname = sys_file_name(fpath);
const char *dot = strrchr(fname, '.');
if (!dot || !dot[1]) return NULL; // no dot
if (dot == fname) return NULL; // dot is the first char (e.g. .local)
return dot + 1;
}
const char *sys_file_name(const char *fpath) {
const char *sep1 = strrchr(fpath, '/');
const char *sep2 = strrchr(fpath, '\\');
const char *sep = sep1 > sep2 ? sep1 : sep2;
if (!sep) return fpath;
return sep + 1;
}
/* this calls a platform-specific impl function after forming the error message */
static void sys_fatal_impl(const char *msg) __attribute__ ((noreturn));
void sys_fatal(const char *fmt, ...) {
static char msg[2048];
va_list args;
va_start(args, fmt);
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
fflush(stdout); // push all crap out
sys_fatal_impl(msg);
}
#ifdef HAVE_SDL2
// we can just ask SDL for most of this shit if we have it
#include <SDL2/SDL.h>
const char *sys_user_path(void) {
static char path[SYS_MAX_PATH] = { 0 };
// get it from SDL
char *sdlpath = SDL_GetPrefPath("", "sm64pc");
if (sdlpath) {
const unsigned int len = strlen(sdlpath);
strncpy(path, sdlpath, sizeof(path));
path[sizeof(path)-1] = 0;
SDL_free(sdlpath);
if (path[len-1] == '/' || path[len-1] == '\\')
path[len-1] = 0; // strip the trailing separator
if (!fs_sys_dir_exists(path) && !fs_sys_mkdir(path))
path[0] = 0;
}
return path;
}
const char *sys_exe_path(void) {
static char path[SYS_MAX_PATH] = { 0 };
char *sdlpath = SDL_GetBasePath();
if (sdlpath && sdlpath[0]) {
// use the SDL path if it exists
const unsigned int len = strlen(sdlpath);
strncpy(path, sdlpath, sizeof(path));
path[sizeof(path)-1] = 0;
SDL_free(sdlpath);
if (path[len-1] == '/' || path[len-1] == '\\')
path[len-1] = 0; // strip the trailing separator
}
return path;
}
static void sys_fatal_impl(const char *msg) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR , "Fatal error", msg, NULL);
fprintf(stderr, "FATAL ERROR:\n%s\n", msg);
fflush(stderr);
exit(1);
}
#else
#warning "You might want to implement these functions for your platform"
const char *sys_user_path(void) {
return ".";
}
const char *sys_exe_path(void) {
return ".";
}
static void sys_fatal_impl(const char *msg) {
fprintf(stderr, "FATAL ERROR:\n%s\n", msg);
fflush(stderr);
exit(1);
}
#endif // platform switch