2012-03-04 13:32:42 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) Sebastian Krzyszkowiak <dos@dosowisko.net>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2017-07-22 18:22:12 +02:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2012-03-04 13:32:42 +01:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2017-07-22 18:22:12 +02:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2012-09-19 01:20:24 +02:00
|
|
|
*
|
|
|
|
* Also, ponies.
|
2012-03-04 13:32:42 +01:00
|
|
|
*/
|
2016-11-06 03:10:43 +01:00
|
|
|
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
|
|
|
#define ALLEGRO_UNSTABLE
|
|
|
|
#endif
|
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
#include "internal.h"
|
2019-03-28 15:33:21 +01:00
|
|
|
#include <getopt.h>
|
2016-07-05 01:30:06 +02:00
|
|
|
#include <libgen.h>
|
2017-09-10 21:35:14 +02:00
|
|
|
#include <locale.h>
|
|
|
|
#include <unistd.h>
|
2016-07-02 23:23:08 +02:00
|
|
|
#ifdef ALLEGRO_MACOSX
|
|
|
|
#include <mach-o/dyld.h>
|
|
|
|
#endif
|
2012-02-15 23:57:06 +01:00
|
|
|
|
2018-10-27 05:18:02 +02:00
|
|
|
static char* GetDefaultWindowWidth(struct Game* game) {
|
|
|
|
char* buf = malloc(sizeof(char) * 255);
|
2019-05-10 23:42:35 +02:00
|
|
|
double aspect = game->_priv.params.aspect ? game->_priv.params.aspect : (game->_priv.params.height ? (game->_priv.params.width / (double)game->_priv.params.height) : 1.0);
|
2018-10-27 05:18:02 +02:00
|
|
|
if (aspect < 1.0) {
|
|
|
|
aspect = 1.0;
|
|
|
|
}
|
|
|
|
snprintf(buf, 255, "%d", (int)(720 * aspect));
|
|
|
|
return AddGarbage(game, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char* GetDefaultWindowHeight(struct Game* game) {
|
|
|
|
char* buf = malloc(sizeof(char) * 255);
|
2019-05-10 23:42:35 +02:00
|
|
|
double aspect = game->_priv.params.aspect ? game->_priv.params.aspect : (game->_priv.params.height ? (game->_priv.params.width / (double)game->_priv.params.height) : 1.0);
|
2018-10-27 05:18:02 +02:00
|
|
|
if (aspect > 1.0) {
|
|
|
|
aspect = 1.0;
|
|
|
|
}
|
|
|
|
snprintf(buf, 255, "%d", (int)(720 / aspect));
|
|
|
|
return AddGarbage(game, buf);
|
|
|
|
}
|
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char* name, struct Params params) {
|
2017-09-10 21:35:14 +02:00
|
|
|
struct Game* game = calloc(1, sizeof(struct Game));
|
2012-08-04 21:58:31 +02:00
|
|
|
|
2019-03-28 15:33:21 +01:00
|
|
|
game->_priv.argc = argc;
|
|
|
|
game->_priv.argv = argv;
|
|
|
|
|
2019-03-28 15:25:37 +01:00
|
|
|
game->_priv.name = strdup(name);
|
2018-12-15 00:59:34 +01:00
|
|
|
game->_priv.params = params;
|
2012-07-03 23:44:03 +02:00
|
|
|
|
2016-07-02 23:23:08 +02:00
|
|
|
#ifdef ALLEGRO_MACOSX
|
2016-09-08 00:32:21 +02:00
|
|
|
getcwd(game->_priv.cwd, MAXPATHLEN);
|
2016-07-02 23:23:08 +02:00
|
|
|
char exe_path[MAXPATHLEN];
|
|
|
|
uint32_t size = sizeof(exe_path);
|
|
|
|
_NSGetExecutablePath(exe_path, &size);
|
2016-07-05 01:30:06 +02:00
|
|
|
chdir(dirname(exe_path));
|
2016-07-02 23:23:08 +02:00
|
|
|
#endif
|
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!al_init()) {
|
2012-09-03 02:25:32 +02:00
|
|
|
fprintf(stderr, "failed to initialize allegro!\n");
|
2017-08-16 01:47:07 +02:00
|
|
|
free(game);
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-09-03 02:25:32 +02:00
|
|
|
}
|
2012-09-03 02:08:12 +02:00
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
InitConfig(game);
|
2012-02-16 12:48:48 +01:00
|
|
|
|
2019-01-13 18:19:44 +01:00
|
|
|
al_set_config_value(al_get_system_config(), "ttf", "cache_text", "0123456789QWERTYUIOPASDFGHJKLZXCVBNMĘÓĄŚŁŻŹĆŃqwertyuiopasdfghjklzxcvbnmęóąśłżźćń.@#$%^&*():\"!?\\[];'{}|,<>/~`-=_+ ");
|
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
game->_priv.fps_count.frames_done = 0;
|
|
|
|
game->_priv.fps_count.fps = 0;
|
|
|
|
game->_priv.fps_count.old_time = 0;
|
2012-12-23 14:29:54 +01:00
|
|
|
|
2017-09-09 00:11:43 +02:00
|
|
|
game->_priv.font_console = NULL;
|
2016-07-03 22:38:36 +02:00
|
|
|
game->_priv.font_bsod = NULL;
|
2017-09-09 00:11:43 +02:00
|
|
|
game->_priv.console_pos = 0;
|
2019-03-29 03:24:36 +01:00
|
|
|
for (size_t i = 0; i < (sizeof(game->_priv.console) / sizeof(game->_priv.console[0])); i++) {
|
2017-09-09 00:11:43 +02:00
|
|
|
game->_priv.console[i][0] = '\0';
|
|
|
|
}
|
2012-12-24 19:41:12 +01:00
|
|
|
|
2016-08-15 04:37:27 +02:00
|
|
|
game->_priv.garbage = NULL;
|
2017-08-07 02:26:36 +02:00
|
|
|
game->_priv.timelines = NULL;
|
2018-05-30 21:11:46 +02:00
|
|
|
game->_priv.shaders = NULL;
|
2019-03-05 03:48:11 +01:00
|
|
|
game->_priv.gamestates = NULL;
|
2016-08-15 04:37:27 +02:00
|
|
|
|
2018-04-16 01:06:58 +02:00
|
|
|
game->_priv.paused = false;
|
2019-03-05 03:48:11 +01:00
|
|
|
game->_priv.started = false;
|
2018-04-16 01:06:58 +02:00
|
|
|
|
2018-06-23 04:44:36 +02:00
|
|
|
game->_priv.texture_sync = false;
|
|
|
|
game->_priv.texture_sync_cond = al_create_cond();
|
|
|
|
game->_priv.texture_sync_mutex = al_create_mutex();
|
|
|
|
|
2018-12-02 00:26:33 +01:00
|
|
|
game->_priv.in_bsod = false;
|
|
|
|
game->_priv.bsod_cond = al_create_cond();
|
|
|
|
game->_priv.bsod_mutex = al_create_mutex();
|
|
|
|
|
2020-04-19 07:40:39 +02:00
|
|
|
game->_priv.speed = 1.0;
|
2019-01-08 04:53:13 +01:00
|
|
|
|
2019-02-26 18:14:19 +01:00
|
|
|
game->_priv.transforms = NULL;
|
|
|
|
game->_priv.transforms_no = 0;
|
|
|
|
|
2019-03-28 16:58:15 +01:00
|
|
|
game->_priv.window_width = 0;
|
|
|
|
game->_priv.window_height = 0;
|
|
|
|
|
2018-12-14 02:18:05 +01:00
|
|
|
game->_priv.mutex = al_create_mutex();
|
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
game->config.fullscreen = strtol(GetConfigOptionDefault(game, "SuperDerpy", "fullscreen", "1"), NULL, 10);
|
|
|
|
game->config.music = strtol(GetConfigOptionDefault(game, "SuperDerpy", "music", "10"), NULL, 10);
|
|
|
|
game->config.voice = strtol(GetConfigOptionDefault(game, "SuperDerpy", "voice", "10"), NULL, 10);
|
|
|
|
game->config.fx = strtol(GetConfigOptionDefault(game, "SuperDerpy", "fx", "10"), NULL, 10);
|
2018-07-26 15:33:02 +02:00
|
|
|
game->config.mute = strtol(GetConfigOptionDefault(game, "SuperDerpy", "mute", "0"), NULL, 10);
|
2019-06-07 20:37:57 +02:00
|
|
|
game->config.samplerate = strtol(GetConfigOptionDefault(game, "SuperDerpy", "samplerate", "0"), NULL, 10);
|
2018-10-27 05:18:02 +02:00
|
|
|
game->config.width = strtol(GetConfigOptionDefault(game, "SuperDerpy", "width", GetDefaultWindowWidth(game)), NULL, 10);
|
|
|
|
if (game->config.width < 100) { game->config.width = 100; }
|
|
|
|
game->config.height = strtol(GetConfigOptionDefault(game, "SuperDerpy", "height", GetDefaultWindowHeight(game)), NULL, 10);
|
|
|
|
if (game->config.height < 100) { game->config.height = 100; }
|
2019-01-08 04:54:53 +01:00
|
|
|
game->config.autopause = strtol(GetConfigOptionDefault(game, "SuperDerpy", "autopause", IS_EMSCRIPTEN ? "1" : "0"), NULL, 10);
|
2012-02-26 12:59:45 +01:00
|
|
|
|
2019-01-08 04:54:53 +01:00
|
|
|
game->config.debug.enabled = strtol(GetConfigOptionDefault(game, "SuperDerpy", "debug", "0"), NULL, 10);
|
2018-12-15 01:09:44 +01:00
|
|
|
game->config.debug.verbose = strtol(GetConfigOptionDefault(game, "debug", "verbose", "0"), NULL, 10);
|
|
|
|
game->config.debug.livereload = strtol(GetConfigOptionDefault(game, "debug", "livereload", "1"), NULL, 10);
|
2018-08-09 00:05:25 +02:00
|
|
|
|
2018-12-22 02:21:46 +01:00
|
|
|
#ifdef __EMSCRIPTEN__
|
2019-01-08 04:54:53 +01:00
|
|
|
game->config.fullscreen = false; // we can't start fullscreen on emscripten
|
2018-12-22 02:21:46 +01:00
|
|
|
#endif
|
|
|
|
|
2019-03-28 15:33:21 +01:00
|
|
|
static struct option long_options[] =
|
|
|
|
{
|
|
|
|
{"debug", no_argument, NULL, 'd'},
|
2019-10-17 03:51:11 +02:00
|
|
|
{"fullscreen", no_argument, NULL, 'f'},
|
|
|
|
{"windowed", no_argument, NULL, 'w'},
|
2019-03-28 15:33:21 +01:00
|
|
|
{NULL, 0, NULL, 0},
|
|
|
|
};
|
|
|
|
|
2020-04-11 00:10:42 +02:00
|
|
|
optind = 1;
|
2020-04-25 19:28:47 +02:00
|
|
|
int opt = 0;
|
2019-10-17 03:51:11 +02:00
|
|
|
while ((opt = getopt_long(argc, argv, "dfw", long_options, NULL)) != -1) {
|
2019-03-28 15:33:21 +01:00
|
|
|
switch (opt) {
|
|
|
|
case 'd':
|
|
|
|
game->config.debug.enabled = true;
|
|
|
|
break;
|
2019-10-17 03:51:11 +02:00
|
|
|
case 'f':
|
|
|
|
if (!game->config.fullscreen) {
|
|
|
|
game->config.fullscreen = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
if (game->config.fullscreen) {
|
|
|
|
game->config.fullscreen = false;
|
|
|
|
}
|
|
|
|
break;
|
2019-03-28 15:33:21 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-11 00:10:42 +02:00
|
|
|
optind = 1;
|
2019-03-28 15:33:21 +01:00
|
|
|
|
2019-12-08 09:23:56 +01:00
|
|
|
game->show_console = game->config.debug.enabled;
|
|
|
|
game->_priv.show_timeline = false;
|
2016-08-16 18:01:12 +02:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!al_init_image_addon()) {
|
2012-02-25 22:26:31 +01:00
|
|
|
fprintf(stderr, "failed to initialize image addon!\n");
|
2012-04-14 22:26:33 +02:00
|
|
|
/*al_show_native_message_box(display, "Error", "Error", "Failed to initialize al_init_image_addon!",
|
2016-07-02 23:23:08 +02:00
|
|
|
NULL, ALLEGRO_MESSAGEBOX_ERROR);*/
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-02-15 23:57:06 +01:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!al_install_audio()) {
|
2017-08-19 01:27:34 +02:00
|
|
|
fprintf(stderr, "failed to initialize audio!\n");
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-02-19 19:17:04 +01:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!al_init_acodec_addon()) {
|
2017-08-19 01:27:34 +02:00
|
|
|
fprintf(stderr, "failed to initialize audio codecs!\n");
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-02-15 23:57:06 +01:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!al_install_keyboard()) {
|
2012-02-25 22:26:31 +01:00
|
|
|
fprintf(stderr, "failed to initialize keyboard!\n");
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-02-15 23:57:06 +01:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!al_init_primitives_addon()) {
|
2012-05-09 10:58:45 +02:00
|
|
|
fprintf(stderr, "failed to initialize primitives!\n");
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-05-09 10:58:45 +02:00
|
|
|
}
|
2016-06-27 21:21:59 +02:00
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
game->input.available.mouse = al_install_mouse();
|
|
|
|
if (!game->input.available.mouse) {
|
2016-07-02 23:23:08 +02:00
|
|
|
fprintf(stderr, "failed to initialize the mouse!\n");
|
|
|
|
}
|
|
|
|
|
2018-04-08 01:33:13 +02:00
|
|
|
if (!al_init_video_addon()) {
|
|
|
|
fprintf(stderr, "failed to initialize the video addon!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-07-03 00:41:57 +02:00
|
|
|
if (!al_init_font_addon() || !al_init_ttf_addon()) {
|
2012-02-25 22:26:31 +01:00
|
|
|
fprintf(stderr, "failed to initialize fonts!\n");
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-02-16 12:48:48 +01:00
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
game->input.available.touch = false;
|
2016-11-08 22:11:10 +01:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!strtol(GetConfigOptionDefault(game, "SuperDerpy", "disableTouch", "0"), NULL, 10)) {
|
2018-12-15 00:59:34 +01:00
|
|
|
game->input.available.touch = al_install_touch_input();
|
2016-11-08 22:11:10 +01:00
|
|
|
}
|
2016-11-06 03:10:43 +01:00
|
|
|
|
|
|
|
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
2020-03-19 02:46:25 +01:00
|
|
|
if (game->input.available.touch) {
|
2016-11-08 17:56:19 +01:00
|
|
|
al_set_mouse_emulation_mode(ALLEGRO_MOUSE_EMULATION_TRANSPARENT);
|
|
|
|
}
|
2016-11-06 03:10:43 +01:00
|
|
|
#endif
|
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
game->input.available.joystick = false;
|
2018-07-03 00:41:57 +02:00
|
|
|
|
|
|
|
if (!strtol(GetConfigOptionDefault(game, "SuperDerpy", "disableJoystick", "0"), NULL, 10)) {
|
2018-12-15 00:59:34 +01:00
|
|
|
game->input.available.joystick = al_install_joystick();
|
2018-07-03 00:41:57 +02:00
|
|
|
}
|
2016-12-05 23:56:41 +01:00
|
|
|
|
2018-07-05 03:28:32 +02:00
|
|
|
#ifdef ALLEGRO_ANDROID
|
2018-12-11 00:26:51 +01:00
|
|
|
int windowMode = ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_FRAMELESS;
|
|
|
|
#elif defined(__EMSCRIPTEN__)
|
|
|
|
int windowMode = ALLEGRO_WINDOWED;
|
|
|
|
#else
|
|
|
|
int windowMode = ALLEGRO_FULLSCREEN_WINDOW;
|
2017-08-22 21:54:58 +02:00
|
|
|
#endif
|
2018-12-11 00:26:51 +01:00
|
|
|
|
2018-09-10 03:18:52 +02:00
|
|
|
if (!game->config.fullscreen) {
|
|
|
|
windowMode = ALLEGRO_WINDOWED;
|
|
|
|
}
|
2019-12-08 09:24:38 +01:00
|
|
|
if (!params.fixed_size) {
|
|
|
|
windowMode |= ALLEGRO_RESIZABLE;
|
|
|
|
}
|
2018-09-10 03:18:52 +02:00
|
|
|
|
|
|
|
al_set_new_display_flags(windowMode | ALLEGRO_OPENGL | ALLEGRO_PROGRAMMABLE_PIPELINE);
|
2017-09-10 21:35:14 +02:00
|
|
|
al_set_new_display_option(ALLEGRO_VSYNC, 2 - strtol(GetConfigOptionDefault(game, "SuperDerpy", "vsync", "1"), NULL, 10), ALLEGRO_SUGGEST);
|
2017-06-26 03:18:54 +02:00
|
|
|
|
|
|
|
#ifdef LIBSUPERDERPY_ORIENTATION_LANDSCAPE
|
2017-07-22 21:01:29 +02:00
|
|
|
al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_LANDSCAPE, ALLEGRO_SUGGEST);
|
2017-06-26 03:18:54 +02:00
|
|
|
#elif defined(LIBSUPERDERPY_ORIENTATION_PORTRAIT)
|
|
|
|
al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_PORTRAIT, ALLEGRO_SUGGEST);
|
|
|
|
#endif
|
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
if (params.depth_buffer) {
|
2018-11-27 03:06:43 +01:00
|
|
|
al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 24, ALLEGRO_SUGGEST);
|
|
|
|
}
|
2018-02-03 03:46:33 +01:00
|
|
|
|
2019-02-01 03:37:15 +01:00
|
|
|
al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, params.samples ? 1 : 0, ALLEGRO_SUGGEST);
|
|
|
|
al_set_new_display_option(ALLEGRO_SAMPLES, params.samples, ALLEGRO_SUGGEST);
|
|
|
|
|
2016-06-27 21:20:02 +02:00
|
|
|
#ifdef ALLEGRO_WINDOWS
|
|
|
|
al_set_new_window_position(20, 40); // workaround nasty Windows bug with window being created off-screen
|
|
|
|
#endif
|
2012-05-10 20:02:22 +02:00
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
al_set_new_window_title(game->_priv.params.window_title ? game->_priv.params.window_title : al_get_app_name());
|
|
|
|
|
2019-10-17 03:50:48 +02:00
|
|
|
#ifdef __EMSCRIPTEN__
|
|
|
|
game->config.width *= emscripten_get_device_pixel_ratio();
|
|
|
|
game->config.height *= emscripten_get_device_pixel_ratio();
|
|
|
|
#endif
|
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
game->display = al_create_display(game->config.width, game->config.height);
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!game->display) {
|
2018-02-03 03:41:11 +01:00
|
|
|
fprintf(stderr, "Failed to create display!\n");
|
2016-07-03 22:38:36 +02:00
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-12-24 19:41:12 +01:00
|
|
|
|
2016-11-06 03:10:43 +01:00
|
|
|
#ifdef ALLEGRO_ANDROID
|
|
|
|
al_android_set_apk_file_interface();
|
|
|
|
al_android_set_apk_fs_interface();
|
|
|
|
#endif
|
|
|
|
|
2019-02-13 22:54:49 +01:00
|
|
|
#if !defined(ALLEGRO_ANDROID) && !defined(ALLEGRO_IPHONE)
|
2018-08-05 01:17:41 +02:00
|
|
|
// We're always using OpenGL which already preserves textures on its own, so avoid
|
|
|
|
// excessive RAM usage by not backuping the bitmaps when not necessary.
|
|
|
|
// Android and iOS can threw out the context, so bitmaps need to be preserved there.
|
|
|
|
al_add_new_bitmap_flag(ALLEGRO_NO_PRESERVE_TEXTURE);
|
|
|
|
#endif
|
|
|
|
|
2018-08-04 18:25:30 +02:00
|
|
|
PrintConsole(game, "libsuperderpy 2 (rev " LIBSUPERDERPY_GIT_REV ")");
|
2019-02-23 13:36:27 +01:00
|
|
|
{
|
|
|
|
uint32_t version = al_get_allegro_version();
|
|
|
|
int major = version >> 24;
|
|
|
|
int minor = (version >> 16) & 255;
|
|
|
|
int revision = (version >> 8) & 255;
|
|
|
|
int release = version & 255;
|
|
|
|
if (release) {
|
|
|
|
PrintConsole(game, "Allegro %d.%d.%d.%d", major, minor, revision, release);
|
|
|
|
} else {
|
|
|
|
PrintConsole(game, "Allegro %d.%d.%d", major, minor, revision);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
uint32_t version = al_get_opengl_version();
|
|
|
|
int major = version >> 24;
|
|
|
|
int minor = (version >> 16) & 255;
|
|
|
|
PrintConsole(game, "OpenGL%s %d.%d", al_get_opengl_variant() == ALLEGRO_OPENGL_ES ? " ES" : "", major, minor);
|
|
|
|
}
|
2018-02-03 03:41:11 +01:00
|
|
|
|
|
|
|
PrintConsole(game, "Max bitmap size: %d", al_get_display_option(game->display, ALLEGRO_MAX_BITMAP_SIZE));
|
|
|
|
PrintConsole(game, "Color buffer bits: %d", al_get_display_option(game->display, ALLEGRO_COLOR_SIZE));
|
|
|
|
PrintConsole(game, "Depth buffer bits: %d", al_get_display_option(game->display, ALLEGRO_DEPTH_SIZE));
|
|
|
|
PrintConsole(game, "Stencil buffer bits: %d", al_get_display_option(game->display, ALLEGRO_STENCIL_SIZE));
|
|
|
|
PrintConsole(game, "NPOT bitmaps: %d", al_get_display_option(game->display, ALLEGRO_SUPPORT_NPOT_BITMAP));
|
|
|
|
PrintConsole(game, "Separate alpha blender: %d", al_get_display_option(game->display, ALLEGRO_SUPPORT_SEPARATE_ALPHA));
|
|
|
|
|
2019-07-25 03:26:08 +02:00
|
|
|
PrintConsole(game, "Connected joysticks:");
|
|
|
|
for (int i = 0; i < al_get_num_joysticks(); i++) {
|
|
|
|
ALLEGRO_JOYSTICK* joystick = al_get_joystick(i);
|
|
|
|
PrintConsole(game, " - %d: %s", i, al_get_joystick_name(joystick));
|
|
|
|
PrintConsole(game, " - buttons: %d", al_get_joystick_num_buttons(joystick));
|
|
|
|
for (int j = 0; j < al_get_joystick_num_sticks(joystick); j++) {
|
|
|
|
PrintConsole(game, " - stick %d: %d axes", j, al_get_joystick_num_axes(joystick, j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-03 03:41:11 +01:00
|
|
|
if (!al_get_display_option(game->display, ALLEGRO_COMPATIBLE_DISPLAY)) {
|
|
|
|
al_destroy_display(game->display);
|
|
|
|
fprintf(stderr, "Created display is Allegro incompatible!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!al_get_display_option(game->display, ALLEGRO_CAN_DRAW_INTO_BITMAP)) {
|
|
|
|
FatalError(game, true, "The created display does not support drawing into bitmaps.");
|
|
|
|
al_destroy_display(game->display);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-03-29 20:54:14 +01:00
|
|
|
const char* iconpath = FindDataFilePath(game, GetGameName(game, "icons/%s.png"));
|
|
|
|
if (iconpath) {
|
|
|
|
ALLEGRO_BITMAP* icon = al_load_bitmap(iconpath);
|
|
|
|
al_set_display_icon(game->display, icon);
|
|
|
|
al_destroy_bitmap(icon);
|
|
|
|
}
|
2012-09-19 01:20:24 +02:00
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
if (game->config.fullscreen) { al_hide_mouse_cursor(game->display); }
|
2016-07-02 23:23:08 +02:00
|
|
|
al_inhibit_screensaver(true);
|
2012-02-29 23:00:59 +01:00
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
SetupViewport(game);
|
2019-03-12 15:16:50 +01:00
|
|
|
ClearScreen(game);
|
2019-02-13 23:00:33 +01:00
|
|
|
al_flip_display();
|
2018-08-04 18:25:30 +02:00
|
|
|
|
2017-09-09 00:11:43 +02:00
|
|
|
al_add_new_bitmap_flag(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
2012-02-29 23:00:59 +01:00
|
|
|
|
2016-08-29 22:47:55 +02:00
|
|
|
al_init_user_event_source(&(game->event_source));
|
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
game->_priv.event_queue = al_create_event_queue();
|
2017-09-10 21:35:14 +02:00
|
|
|
if (!game->_priv.event_queue) {
|
2016-07-03 22:38:36 +02:00
|
|
|
FatalError(game, true, "Failed to create event queue.");
|
|
|
|
al_destroy_display(game->display);
|
|
|
|
return NULL;
|
2012-02-25 22:26:31 +01:00
|
|
|
}
|
2012-02-15 23:57:06 +01:00
|
|
|
|
2019-06-07 20:37:57 +02:00
|
|
|
game->_priv.samplerate = game->config.samplerate;
|
|
|
|
if (!game->_priv.samplerate) {
|
|
|
|
game->_priv.samplerate = params.samplerate;
|
|
|
|
if (!game->_priv.samplerate) {
|
|
|
|
game->_priv.samplerate = 44100;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
game->audio.mixer = al_create_mixer(game->_priv.samplerate, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
|
|
|
game->audio.fx = al_create_mixer(game->_priv.samplerate, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
|
|
|
game->audio.music = al_create_mixer(game->_priv.samplerate, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
|
|
|
game->audio.voice = al_create_mixer(game->_priv.samplerate, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
2016-07-03 22:38:36 +02:00
|
|
|
al_attach_mixer_to_mixer(game->audio.fx, game->audio.mixer);
|
|
|
|
al_attach_mixer_to_mixer(game->audio.music, game->audio.mixer);
|
|
|
|
al_attach_mixer_to_mixer(game->audio.voice, game->audio.mixer);
|
2017-09-10 21:35:14 +02:00
|
|
|
al_set_mixer_gain(game->audio.fx, game->config.fx / 10.0);
|
|
|
|
al_set_mixer_gain(game->audio.music, game->config.music / 10.0);
|
|
|
|
al_set_mixer_gain(game->audio.voice, game->config.voice / 10.0);
|
2018-07-26 16:19:32 +02:00
|
|
|
al_set_mixer_gain(game->audio.mixer, game->config.mute ? 0.0 : 1.0);
|
2019-02-07 04:11:40 +01:00
|
|
|
SetupAudio(game);
|
2018-11-02 06:10:15 +01:00
|
|
|
al_set_default_mixer(game->audio.mixer);
|
2016-07-03 22:38:36 +02:00
|
|
|
|
|
|
|
setlocale(LC_NUMERIC, "C");
|
2016-06-27 21:20:02 +02:00
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
game->data = NULL;
|
2012-05-07 22:44:39 +02:00
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
game->_priv.shutting_down = false;
|
|
|
|
game->_priv.restart = false;
|
2012-12-24 19:41:12 +01:00
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
game->loading.progress = 0;
|
2016-08-20 03:32:32 +02:00
|
|
|
|
2019-05-17 02:31:17 +02:00
|
|
|
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
|
|
|
|
__libsuperderpy_register_gamestate(NULL, NULL, game);
|
|
|
|
#endif
|
|
|
|
|
2019-07-25 03:26:08 +02:00
|
|
|
PrintConsole(game, "Engine initialized.");
|
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
return game;
|
|
|
|
}
|
2012-04-09 16:41:10 +02:00
|
|
|
|
2019-05-17 02:31:17 +02:00
|
|
|
static void ProgressStub(struct Game* game) {}
|
|
|
|
|
2018-09-10 03:18:52 +02:00
|
|
|
SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
|
2016-07-03 22:38:36 +02:00
|
|
|
al_register_event_source(game->_priv.event_queue, al_get_display_event_source(game->display));
|
|
|
|
al_register_event_source(game->_priv.event_queue, al_get_keyboard_event_source());
|
2018-12-15 00:59:34 +01:00
|
|
|
if (game->input.available.mouse) {
|
2018-07-03 00:41:57 +02:00
|
|
|
al_register_event_source(game->_priv.event_queue, al_get_mouse_event_source());
|
|
|
|
}
|
2018-12-15 00:59:34 +01:00
|
|
|
if (game->input.available.joystick) {
|
2018-07-03 00:41:57 +02:00
|
|
|
al_register_event_source(game->_priv.event_queue, al_get_joystick_event_source());
|
|
|
|
}
|
2018-12-15 00:59:34 +01:00
|
|
|
if (game->input.available.touch) {
|
2016-11-08 17:56:19 +01:00
|
|
|
al_register_event_source(game->_priv.event_queue, al_get_touch_input_event_source());
|
2016-11-06 03:10:43 +01:00
|
|
|
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
2016-11-08 17:56:19 +01:00
|
|
|
al_register_event_source(game->_priv.event_queue, al_get_touch_input_mouse_emulation_event_source());
|
2016-11-06 03:10:43 +01:00
|
|
|
#endif
|
2016-11-08 17:56:19 +01:00
|
|
|
}
|
2016-08-29 22:47:55 +02:00
|
|
|
al_register_event_source(game->_priv.event_queue, &(game->event_source));
|
2012-04-09 16:41:10 +02:00
|
|
|
|
2019-02-24 04:20:36 +01:00
|
|
|
// HACK: some backends correct the window size only after the display has been already created.
|
|
|
|
// if we start loading with wrong size, it won't be corrected until the main loop is entered back,
|
|
|
|
// so the loading screen will stay at the wrong size.
|
|
|
|
// Turns out SDL/Wayland needs some help with emitting the resize event before it's too late.
|
|
|
|
ALLEGRO_EVENT event;
|
|
|
|
al_peek_next_event(game->_priv.event_queue, &event);
|
2019-03-12 15:16:50 +01:00
|
|
|
ClearScreen(game);
|
2019-02-24 04:20:36 +01:00
|
|
|
al_flip_display();
|
|
|
|
|
2017-09-10 22:07:02 +02:00
|
|
|
{
|
|
|
|
struct Gamestate* tmp = game->_priv.gamestates;
|
2019-05-17 02:31:17 +02:00
|
|
|
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
|
|
|
|
if (tmp && strcmp(tmp->name, "loading") == 0) {
|
|
|
|
game->_priv.gamestates = tmp->next;
|
|
|
|
game->_priv.loading.gamestate = tmp;
|
|
|
|
tmp = game->_priv.gamestates;
|
|
|
|
}
|
|
|
|
#endif
|
2017-09-10 22:07:02 +02:00
|
|
|
while (tmp) {
|
|
|
|
// don't show loading screen on init if requested
|
2019-06-07 21:35:16 +02:00
|
|
|
if (tmp->pending_load) {
|
|
|
|
tmp->show_loading = game->_priv.params.show_loading_on_launch;
|
|
|
|
}
|
2019-05-17 02:31:17 +02:00
|
|
|
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
|
|
|
|
if (tmp->next && strcmp(tmp->next->name, "loading") == 0) {
|
|
|
|
game->_priv.loading.gamestate = tmp->next;
|
|
|
|
tmp->next = tmp->next->next;
|
|
|
|
}
|
|
|
|
#endif
|
2017-09-10 22:07:02 +02:00
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
2016-07-03 22:38:36 +02:00
|
|
|
}
|
2012-12-24 19:41:12 +01:00
|
|
|
|
2019-05-17 02:31:17 +02:00
|
|
|
if (!game->_priv.loading.gamestate) {
|
|
|
|
game->_priv.loading.gamestate = AllocateGamestate(game, "loading");
|
|
|
|
}
|
2019-03-30 03:34:55 +01:00
|
|
|
if (OpenGamestate(game, game->_priv.loading.gamestate, false) && LinkGamestate(game, game->_priv.loading.gamestate)) {
|
2019-12-05 09:27:06 +01:00
|
|
|
if (game->_priv.params.handlers.compositor) {
|
|
|
|
game->_priv.loading.gamestate->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h);
|
|
|
|
} else {
|
|
|
|
game->_priv.loading.gamestate->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h);
|
|
|
|
}
|
|
|
|
|
2019-05-17 02:31:17 +02:00
|
|
|
game->_priv.loading.gamestate->data = (*game->_priv.loading.gamestate->api->load)(game, ProgressStub);
|
2019-03-30 03:34:55 +01:00
|
|
|
game->_priv.loading.gamestate->loaded = true;
|
|
|
|
PrintConsole(game, "Loading screen registered.");
|
|
|
|
} else {
|
|
|
|
PrintConsole(game, "No loading screen available.");
|
2012-12-28 03:42:59 +01:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:37:32 +01:00
|
|
|
ReloadShaders(game, false);
|
|
|
|
|
2019-03-30 03:34:55 +01:00
|
|
|
if (game->_priv.loading.gamestate->open && game->_priv.loading.gamestate->api->post_load) {
|
2019-02-13 22:59:11 +01:00
|
|
|
(*game->_priv.loading.gamestate->api->post_load)(game, game->_priv.loading.gamestate->data);
|
|
|
|
}
|
|
|
|
|
2018-02-03 03:37:44 +01:00
|
|
|
game->_priv.timestamp = al_get_time();
|
2018-09-10 03:18:52 +02:00
|
|
|
game->_priv.paused = false;
|
2019-03-05 03:48:11 +01:00
|
|
|
game->_priv.started = true;
|
2018-10-11 06:15:07 +02:00
|
|
|
|
2018-11-29 04:37:08 +01:00
|
|
|
#ifdef LIBSUPERDERPY_IMGUI
|
|
|
|
igCreateContext(NULL);
|
|
|
|
ImGui_ImplAllegro5_Init(game->display);
|
|
|
|
igStyleColorsDark(NULL);
|
2018-11-29 21:09:20 +01:00
|
|
|
igGetStyle()->FrameBorderSize = 1.0;
|
2019-04-07 23:26:54 +02:00
|
|
|
ImGuiIO* io = igGetIO();
|
|
|
|
io->FontGlobalScale = strtod(GetConfigOptionDefault(game, "SuperDerpy", "scale", "1"), NULL);
|
2018-11-29 04:37:08 +01:00
|
|
|
#endif
|
|
|
|
|
2019-07-25 03:26:08 +02:00
|
|
|
PrintConsole(game, "Engine started.");
|
|
|
|
|
2017-08-22 21:54:58 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __EMSCRIPTEN__
|
2018-09-10 03:18:52 +02:00
|
|
|
SYMBOL_INTERNAL void libsuperderpy_emscripten_mainloop(void* game) {
|
|
|
|
if (!libsuperderpy_mainloop(game)) {
|
|
|
|
libsuperderpy_destroy(game);
|
|
|
|
printf("Halted.\n");
|
|
|
|
emscripten_cancel_main_loop();
|
|
|
|
}
|
|
|
|
}
|
2019-01-08 04:57:30 +01:00
|
|
|
|
|
|
|
SYMBOL_INTERNAL EM_BOOL libsuperderpy_emscripten_visibility_change(int eventType, const EmscriptenVisibilityChangeEvent* visibilityChangeEvent, void* game) {
|
|
|
|
libsuperderpy_emscripten_mainloop(game);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-22 21:54:58 +02:00
|
|
|
#endif
|
|
|
|
|
2018-09-10 03:18:52 +02:00
|
|
|
SYMBOL_EXPORT int libsuperderpy_run(struct Game* game) {
|
|
|
|
int ret = libsuperderpy_start(game);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
2017-08-22 21:54:58 +02:00
|
|
|
#ifdef __EMSCRIPTEN__
|
2019-01-08 04:57:30 +01:00
|
|
|
emscripten_set_visibilitychange_callback(game, false, libsuperderpy_emscripten_visibility_change);
|
2018-09-10 03:18:52 +02:00
|
|
|
emscripten_set_main_loop_arg(libsuperderpy_emscripten_mainloop, game, 0, true);
|
|
|
|
return 0;
|
2017-09-09 00:42:57 +02:00
|
|
|
#else
|
2019-03-29 03:24:36 +01:00
|
|
|
while (libsuperderpy_mainloop(game)) {}
|
2018-09-10 03:18:52 +02:00
|
|
|
libsuperderpy_destroy(game);
|
2016-07-03 22:38:36 +02:00
|
|
|
return 0;
|
2017-08-22 21:54:58 +02:00
|
|
|
#endif
|
2016-07-03 22:38:36 +02:00
|
|
|
}
|
|
|
|
|
2017-09-10 21:35:14 +02:00
|
|
|
SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
2018-12-15 00:59:34 +01:00
|
|
|
game->_priv.shutting_down = true;
|
2012-12-24 19:41:12 +01:00
|
|
|
|
2018-11-29 04:37:08 +01:00
|
|
|
#ifdef LIBSUPERDERPY_IMGUI
|
|
|
|
ImGui_ImplAllegro5_Shutdown();
|
|
|
|
igDestroyContext(NULL);
|
|
|
|
#endif
|
|
|
|
|
2016-08-16 18:01:12 +02:00
|
|
|
ClearGarbage(game);
|
|
|
|
|
2020-04-25 19:28:47 +02:00
|
|
|
struct Gamestate *tmp = game->_priv.gamestates, *pom = NULL;
|
2012-12-26 13:38:15 +01:00
|
|
|
while (tmp) {
|
|
|
|
if (tmp->started) {
|
2016-07-03 22:38:36 +02:00
|
|
|
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
2016-08-16 18:41:50 +02:00
|
|
|
game->_priv.current_gamestate = tmp;
|
2018-12-16 15:35:53 +01:00
|
|
|
(*tmp->api->stop)(game, tmp->data);
|
2012-12-26 13:38:15 +01:00
|
|
|
tmp->started = false;
|
2018-06-30 00:59:54 +02:00
|
|
|
PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name);
|
2012-12-26 13:38:15 +01:00
|
|
|
}
|
|
|
|
if (tmp->loaded) {
|
2016-07-03 22:38:36 +02:00
|
|
|
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
|
2016-08-16 18:41:50 +02:00
|
|
|
game->_priv.current_gamestate = tmp;
|
2018-12-16 15:35:53 +01:00
|
|
|
(*tmp->api->unload)(game, tmp->data);
|
2012-12-26 13:38:15 +01:00
|
|
|
tmp->loaded = false;
|
2018-06-30 00:59:54 +02:00
|
|
|
PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name);
|
2012-12-26 13:38:15 +01:00
|
|
|
}
|
2017-09-09 00:11:43 +02:00
|
|
|
CloseGamestate(game, tmp);
|
2016-08-16 18:01:12 +02:00
|
|
|
pom = tmp->next;
|
2019-05-11 00:44:45 +02:00
|
|
|
free(tmp->name);
|
2016-08-16 18:01:12 +02:00
|
|
|
free(tmp);
|
2017-09-10 21:35:14 +02:00
|
|
|
tmp = pom;
|
2012-12-26 13:38:15 +01:00
|
|
|
}
|
|
|
|
|
2019-05-17 02:31:17 +02:00
|
|
|
if (game->_priv.loading.gamestate->open && game->_priv.loading.gamestate->api) {
|
2019-03-30 03:34:55 +01:00
|
|
|
(*game->_priv.loading.gamestate->api->unload)(game, game->_priv.loading.gamestate->data);
|
|
|
|
}
|
2019-12-05 09:27:06 +01:00
|
|
|
if (game->_priv.loading.gamestate->fb) {
|
|
|
|
al_destroy_bitmap(game->_priv.loading.gamestate->fb);
|
|
|
|
game->_priv.loading.gamestate->fb = NULL;
|
|
|
|
}
|
2019-05-11 00:05:40 +02:00
|
|
|
CloseGamestate(game, game->_priv.loading.gamestate);
|
2019-05-11 00:44:45 +02:00
|
|
|
free(game->_priv.loading.gamestate->name);
|
2017-09-09 00:11:43 +02:00
|
|
|
free(game->_priv.loading.gamestate);
|
|
|
|
|
2018-12-15 00:59:34 +01:00
|
|
|
if (game->_priv.params.handlers.destroy) {
|
|
|
|
(*game->_priv.params.handlers.destroy)(game);
|
2017-08-22 21:54:58 +02:00
|
|
|
}
|
2018-05-31 20:52:16 +02:00
|
|
|
DestroyShaders(game);
|
2017-08-22 21:54:58 +02:00
|
|
|
|
2016-11-08 10:34:32 +01:00
|
|
|
ClearScreen(game);
|
2017-08-22 21:54:58 +02:00
|
|
|
#ifdef __EMSCRIPTEN__
|
2017-09-09 00:11:43 +02:00
|
|
|
{
|
2017-09-10 21:35:14 +02:00
|
|
|
ALLEGRO_BITMAP* bmp = al_create_bitmap(320, 180);
|
2017-09-09 00:11:43 +02:00
|
|
|
al_set_target_bitmap(bmp);
|
2017-09-10 21:35:14 +02:00
|
|
|
al_clear_to_color(al_map_rgb(0, 0, 0));
|
|
|
|
ALLEGRO_FONT* font = al_create_builtin_font();
|
|
|
|
al_draw_text(font, al_map_rgb(228, 127, 59), 320 / 2, 180 / 2 - 8 - 6, ALLEGRO_ALIGN_CENTER, "It's now safe to turn off");
|
|
|
|
al_draw_text(font, al_map_rgb(228, 127, 59), 320 / 2, 180 / 2 - 8 + 6, ALLEGRO_ALIGN_CENTER, "your browser.");
|
2017-09-09 00:11:43 +02:00
|
|
|
al_set_target_backbuffer(game->display);
|
2017-09-10 21:35:14 +02:00
|
|
|
al_draw_scaled_bitmap(bmp, 0, 0, 320, 180, 0, -game->viewport.height * 0.2, game->viewport.width, game->viewport.height * 1.4, 0);
|
2017-09-09 00:11:43 +02:00
|
|
|
al_flip_display();
|
|
|
|
al_destroy_bitmap(bmp);
|
|
|
|
al_destroy_font(font);
|
|
|
|
}
|
2017-08-22 21:54:58 +02:00
|
|
|
#endif
|
2017-09-09 00:11:43 +02:00
|
|
|
|
2016-07-03 22:38:36 +02:00
|
|
|
PrintConsole(game, "Shutting down...");
|
|
|
|
DrawConsole(game);
|
2012-02-17 13:25:06 +01:00
|
|
|
al_flip_display();
|
2016-08-16 18:01:12 +02:00
|
|
|
while (game->_priv.garbage) {
|
|
|
|
free(game->_priv.garbage->data);
|
|
|
|
game->_priv.garbage = game->_priv.garbage->next;
|
|
|
|
}
|
2019-02-26 18:14:19 +01:00
|
|
|
free(game->_priv.transforms);
|
2016-07-03 22:38:36 +02:00
|
|
|
Console_Unload(game);
|
|
|
|
al_destroy_display(game->display);
|
2016-08-29 22:47:55 +02:00
|
|
|
al_destroy_user_event_source(&(game->event_source));
|
2016-07-03 22:38:36 +02:00
|
|
|
al_destroy_event_queue(game->_priv.event_queue);
|
2019-04-22 01:34:53 +02:00
|
|
|
al_restore_default_mixer();
|
2016-07-03 22:38:36 +02:00
|
|
|
al_destroy_mixer(game->audio.fx);
|
|
|
|
al_destroy_mixer(game->audio.music);
|
2018-12-02 00:24:31 +01:00
|
|
|
al_destroy_mixer(game->audio.voice);
|
2016-07-03 22:38:36 +02:00
|
|
|
al_destroy_mixer(game->audio.mixer);
|
2019-02-07 04:11:40 +01:00
|
|
|
al_set_default_voice(NULL); // destroys game->audio.v voice
|
2018-06-23 04:44:36 +02:00
|
|
|
al_destroy_cond(game->_priv.texture_sync_cond);
|
|
|
|
al_destroy_mutex(game->_priv.texture_sync_mutex);
|
2018-12-02 00:26:33 +01:00
|
|
|
al_destroy_cond(game->_priv.bsod_cond);
|
|
|
|
al_destroy_mutex(game->_priv.bsod_mutex);
|
2018-12-14 02:18:05 +01:00
|
|
|
al_destroy_mutex(game->_priv.mutex);
|
2012-02-25 22:26:31 +01:00
|
|
|
al_uninstall_audio();
|
2016-07-03 22:38:36 +02:00
|
|
|
DeinitConfig(game);
|
2019-05-17 02:31:17 +02:00
|
|
|
#ifndef __EMSCRIPTEN__ // ???
|
2012-12-26 02:25:56 +01:00
|
|
|
al_uninstall_system();
|
2019-05-17 02:31:17 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LIBSUPERDERPY_NO_RESTART
|
2016-07-04 00:06:50 +02:00
|
|
|
char** argv = game->_priv.argv;
|
2018-12-15 00:59:34 +01:00
|
|
|
bool restart = game->_priv.restart;
|
2019-03-28 15:25:37 +01:00
|
|
|
free(game->_priv.name);
|
2016-07-03 22:38:36 +02:00
|
|
|
free(game);
|
2016-08-16 18:01:12 +02:00
|
|
|
if (restart) {
|
2016-09-08 00:32:21 +02:00
|
|
|
#ifdef ALLEGRO_MACOSX
|
|
|
|
chdir(game->_priv.cwd);
|
|
|
|
#endif
|
2018-12-05 02:09:06 +01:00
|
|
|
#ifdef ALLEGRO_WINDOWS
|
|
|
|
wchar_t* wargv[game->_priv.argc];
|
|
|
|
for (int i = 0; i < game->_priv.argc; i++) {
|
|
|
|
size_t size = MultiByteToWideChar(CP_UTF8, 0, argv[i], -1, NULL, 0);
|
2018-12-11 00:26:51 +01:00
|
|
|
wargv[i] = malloc(sizeof(wchar_t) * size);
|
2018-12-05 02:09:06 +01:00
|
|
|
MultiByteToWideChar(CP_UTF8, 0, argv[i], -1, wargv[i], size);
|
|
|
|
}
|
|
|
|
_wexecv(wargv[0], (const wchar_t* const*)wargv);
|
|
|
|
#else
|
2017-08-19 01:26:53 +02:00
|
|
|
execv(argv[0], argv);
|
2018-12-05 02:09:06 +01:00
|
|
|
#endif
|
2012-03-08 22:21:02 +01:00
|
|
|
}
|
2017-08-22 21:54:58 +02:00
|
|
|
#endif
|
2012-02-15 23:57:06 +01:00
|
|
|
}
|