-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
243 lines (202 loc) · 6.13 KB
/
main.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
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
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include "game.h"
#include "log.h"
#include "vfs.h"
#include "assets.h"
#include "core.h"
#include "core_argv.h"
#include "core_reload.h"
typedef struct game_settings* (*game_get_settings_fn_t)();
/* Core singleton. */
struct core core_mem = { 0 };
struct core *core_global = &core_mem;
/* VFS singleton. */
struct vfs vfs_mem = { 0 };
struct vfs *vfs_global = &vfs_mem;
/* Input singleton. */
struct input *input_global = NULL;
/* Assets singleton. */
struct assets assets_mem = { 0 };
struct assets *assets = &assets_mem;
void* game_library = 0;
core_init_t game_init_fn = 0;
core_load_t game_assets_load_fn = 0;
core_release_t game_assets_release_fn = 0;
think_func_t game_think_fn = 0;
render_func_t game_render_fn = 0;
input_callback_t game_key_callback_fn = 0;
mousebutton_callback_t game_mousebutton_callback_fn = 0;
fps_func_t game_fps_callback_fn = 0;
core_console_init_t game_console_init_fn = 0;
core_init_memory_t game_init_memory_fn = 0;
game_get_settings_fn_t game_get_settings_fn = NULL;
void* load_shared_library(const char* filename)
{
void* library = 0;
#ifdef _WIN32
library = (void*)LoadLibrary(filename);
#else
library = dlopen(filename, 2);
#endif
if (!library)
{
errorf("Main", "Could not load library %s\n", filename);
}
return library;
}
void* load_function(void* library, const char* function_name)
{
void* function = 0;
#ifdef _WIN32
function = (void*)GetProcAddress((HINSTANCE)library, function_name);
#else
function = dlsym(library, function_name);
#endif
if (!function)
{
errorf("Main", "Could not load function %s\n", function_name);
}
return function;
}
/**
* @return 0 on success, non-zero on failure.
*/
int free_shared_library(void* library)
{
#ifdef _WIN32
return FreeLibrary((HINSTANCE)library) == 0;
#else
return dlclose(library);
#endif
}
void* load_copy(const char* filename, unsigned int size, void* data)
{
char name[256];
char* tmp = strrchr(filename, (int)'/');
if (tmp)
{
tmp++;
int namebegin = strlen(filename) - strlen(tmp);
strcpy(name, filename);
strcpy(&name[namebegin], "runtime_");
strcpy(&name[namebegin + 8], tmp);
}
else
{
strcpy(name, "runtime_");
strcpy(name, filename);
}
FILE *fp;
fp = fopen(name, "wb+");
fwrite(data, sizeof(char), (size_t)size, fp);
fclose(fp);
return load_shared_library(name);
}
int first_load = 1;
void load_game(const char* filename, unsigned int size, void* data, void* userdata)
{
debugf("Main", "Reloading game library %s\n", filename);
if (game_library)
{
free_shared_library(game_library);
debugf("Main", "Freeing old game library %s\n", filename);
game_library = 0;
}
const char* absolute_path = vfs_get_absolute_path(filename);
if (!absolute_path)
{
return;
}
game_library = load_copy(absolute_path, size, data);
debugf("Main", "Load successful %s\n", filename);
if (game_library)
{
game_init_fn = load_function(game_library, "game_init");
game_assets_load_fn = load_function(game_library, "game_assets_load");
game_assets_release_fn = load_function(game_library, "game_assets_release");
game_think_fn = load_function(game_library, "game_think");
game_render_fn = load_function(game_library, "game_render");
game_key_callback_fn = load_function(game_library, "game_key_callback");
game_mousebutton_callback_fn = load_function(game_library, "game_mousebutton_callback");
game_fps_callback_fn = load_function(game_library, "game_fps_callback");
game_console_init_fn = load_function(game_library, "game_console_init");
game_init_memory_fn = load_function(game_library, "game_init_memory");
game_get_settings_fn = load_function(game_library, "game_get_settings");
if (game_init_fn &&
game_assets_load_fn &&
game_assets_release_fn &&
game_think_fn &&
game_render_fn &&
game_key_callback_fn &&
game_mousebutton_callback_fn &&
game_fps_callback_fn &&
game_console_init_fn &&
game_init_memory_fn)
{
core_set_asset_callbacks(core_global, game_assets_load_fn, game_init_fn, game_assets_release_fn);
core_set_key_callback(core_global, game_key_callback_fn);
core_set_mousebutton_callback(core_global, game_mousebutton_callback_fn);
core_set_fps_callback(core_global, game_fps_callback_fn);
core_set_console_init_callback(core_global, game_console_init_fn);
core_set_think_callback(core_global, game_think_fn);
core_set_render_callback(core_global, game_render_fn);
core_set_init_memory_callback(core_global, game_init_memory_fn);
if (!first_load)
{
core_reload(core_global);
}
}
}
}
int main(int argc, char **argv)
{
/* Parse command line arguments. */
struct core_argv args = { 0 };
core_argv_parse(&args, argc, argv);
/* Start the virtual file system */
vfs_init(args.mount);
#ifdef LOAD_SHARED
/* Load game library */
size_t filesize;
void* lib = vfs_get_file(args.game, &filesize);
load_game(args.game, filesize, lib, 0);
first_load = 0;
if (!game_library)
{
return 0;
}
/* Get game settings. */
struct game_settings *settings = game_get_settings_fn();
#else
core_set_think_callback(core_global, &game_think);
core_set_render_callback(core_global, &game_render);
core_set_asset_callbacks(core_global, &game_assets_load, &game_init, &game_assets_release);
core_set_key_callback(core_global, &game_key_callback);
core_set_mousebutton_callback(core_global, &game_mousebutton_callback);
core_set_fps_callback(core_global, &game_fps_callback);
core_set_init_memory_callback(core_global, &game_init_memory);
core_set_console_init_callback(core_global, &game_console_init);
struct game_settings *settings = game_get_settings();
#endif
/* Sound setup */
core_set_up_sound(core_global, &settings->sound_listener, settings->sound_distance_max);
/* Initialize subsystems and run main loop. */
core_setup(core_global, settings->window_title,
settings->view_width, settings->view_height,
settings->window_width, settings->window_height,
args.window_mode, 1000000000);
vfs_run_callbacks();
#ifdef LOAD_SHARED
/* Register game reload callback */
vfs_register_callback(args.game, &load_game, 0);
#endif
core_run(core_global);
vfs_shutdown();
return 0;
}