From 3e9e2595aa0ce3992430d1af3850b7e15a7cd118 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 15 Aug 2020 07:15:28 +0300 Subject: [PATCH] add barebones SDL1.2 backends for that sweet Win9x support --- Makefile | 36 ++- src/pc/audio/audio_sdl1.c | 190 ++++++++++++ src/pc/audio/{audio_sdl.c => audio_sdl2.c} | 3 +- src/pc/controller/controller_entry_point.c | 2 + .../{controller_sdl.c => controller_sdl2.c} | 2 +- src/pc/gfx/gfx_opengl.c | 19 +- src/pc/gfx/gfx_opengl_legacy.c | 13 +- src/pc/gfx/gfx_sdl1.c | 280 ++++++++++++++++++ src/pc/pc_main.c | 2 + 9 files changed, 525 insertions(+), 22 deletions(-) create mode 100644 src/pc/audio/audio_sdl1.c rename src/pc/audio/{audio_sdl.c => audio_sdl2.c} (97%) rename src/pc/controller/{controller_sdl.c => controller_sdl2.c} (99%) create mode 100644 src/pc/gfx/gfx_sdl1.c diff --git a/Makefile b/Makefile index bc82c2cb..fc8f8e61 100644 --- a/Makefile +++ b/Makefile @@ -58,9 +58,9 @@ NO_LDIV ?= 0 # Renderers: GL, GL_LEGACY, D3D11, D3D12 RENDER_API ?= GL -# Window managers: SDL2, DXGI (forced if D3D11 or D3D12 in RENDER_API) +# Window managers: SDL1, SDL2, DXGI (forced if D3D11 or D3D12 in RENDER_API) WINDOW_API ?= SDL2 -# Audio backends: SDL2 +# Audio backends: SDL1, SDL2 AUDIO_API ?= SDL2 # Controller backends (can have multiple, space separated): SDL2 CONTROLLER_API ?= SDL2 @@ -481,7 +481,9 @@ SDLCONFIG := $(CROSS)sdl2-config BACKEND_CFLAGS := -DRAPI_$(RENDER_API)=1 -DWAPI_$(WINDOW_API)=1 -DAAPI_$(AUDIO_API)=1 # can have multiple controller APIs BACKEND_CFLAGS += $(foreach capi,$(CONTROLLER_API),-DCAPI_$(capi)=1) -BACKEND_LDFLAGS := +BACKEND_LDFLAG0S := + +SDL1_USED := 0 SDL2_USED := 0 # for now, it's either SDL+GL or DXGI+DirectX, so choose based on WAPI @@ -492,7 +494,7 @@ ifeq ($(WINDOW_API),DXGI) endif BACKEND_LDFLAGS += -ld3dcompiler -ldxgi -ldxguid BACKEND_LDFLAGS += -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -static -else ifeq ($(WINDOW_API),SDL2) +else ifeq ($(findstring SDL,$(WINDOW_API)),SDL) ifeq ($(WINDOWS_BUILD),1) BACKEND_LDFLAGS += -lglew32 -lglu32 -lopengl32 else ifeq ($(TARGET_RPI),1) @@ -502,20 +504,32 @@ else ifeq ($(WINDOW_API),SDL2) else BACKEND_LDFLAGS += -lGL endif - SDL_USED := 2 endif -ifeq ($(AUDIO_API),SDL2) - SDL_USED := 2 +ifneq (,$(findstring SDL2,$(AUDIO_API)$(WINDOW_API)$(CONTROLLER_API))) + SDL2_USED := 1 endif -ifneq (,$(findstring SDL,$(CONTROLLER_API))) - SDL_USED := 2 +ifneq (,$(findstring SDL1,$(AUDIO_API)$(WINDOW_API)$(CONTROLLER_API))) + SDL1_USED := 1 +endif + +ifeq ($(SDL1_USED)$(SDL2_USED),11) + $(error Cannot link both SDL1 and SDL2 at the same time) endif # SDL can be used by different systems, so we consolidate all of that shit into this -ifeq ($(SDL_USED),2) - BACKEND_CFLAGS += -DHAVE_SDL2=1 `$(SDLCONFIG) --cflags` + +ifeq ($(SDL2_USED),1) + SDLCONFIG := $(CROSS)sdl2-config + BACKEND_CFLAGS += -DHAVE_SDL2=1 +else ifeq ($(SDL1_USED),1) + SDLCONFIG := $(CROSS)sdl-config + BACKEND_CFLAGS += -DHAVE_SDL1=1 +endif + +ifneq ($(SDL1_USED)$(SDL2_USED),00) + BACKEND_CFLAGS += `$(SDLCONFIG) --cflags` ifeq ($(WINDOWS_BUILD),1) BACKEND_LDFLAGS += `$(SDLCONFIG) --static-libs` -lsetupapi -luser32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion else diff --git a/src/pc/audio/audio_sdl1.c b/src/pc/audio/audio_sdl1.c new file mode 100644 index 00000000..6cbf5c56 --- /dev/null +++ b/src/pc/audio/audio_sdl1.c @@ -0,0 +1,190 @@ +#ifdef AAPI_SDL1 + +#include +#include +#include +#include + +#include "audio_api.h" + +#define SNDPACKETLEN (8 * 1024) + +// this is basically SDL_dataqueue but slightly less generic + +typedef struct sndpacket { + size_t datalen; /* bytes currently in use in this packet. */ + size_t startpos; /* bytes currently consumed in this packet. */ + struct sndpacket *next; /* next item in linked list. */ + Uint8 data[]; /* packet data */ +} sndpacket_t; + +static sndpacket_t *qhead; +static sndpacket_t *qtail; +static sndpacket_t *qpool; +static size_t queued; + +static SDL_AudioSpec aspec; +static int was_init = 0; + +static void sndqueue_init(const size_t bufsize) { + const size_t wantpackets = (bufsize + (SNDPACKETLEN - 1)) / SNDPACKETLEN; + for (size_t i = 0; i < wantpackets; ++i) { + sndpacket_t *packet = malloc(sizeof(sndpacket_t) + SNDPACKETLEN); + if (packet) { + packet->datalen = 0; + packet->startpos = 0; + packet->next = qpool; + qpool = packet; + } + } +} + +static size_t sndqueue_read(void *buf, size_t len) { + sndpacket_t *packet; + Uint8 *ptr = buf; + + while ((len > 0) && ((packet = qhead) != NULL)) { + const size_t avail = packet->datalen - packet->startpos; + const size_t tx = (len < avail) ? len : avail; + + memcpy(ptr, packet->data + packet->startpos, tx); + packet->startpos += tx; + ptr += tx; + queued -= tx; + len -= tx; + + if (packet->startpos == packet->datalen) { + qhead = packet->next; + packet->next = qpool; + qpool = packet; + } + } + + if (qhead == NULL) + qtail = NULL; + + return (size_t)(ptr - (Uint8*)buf); +} + +static inline sndpacket_t *alloc_sndpacket(void) { + sndpacket_t *packet = qpool; + + if (packet) { + qpool = packet->next; + } else { + packet = malloc(sizeof(sndpacket_t) + SNDPACKETLEN); + if (!packet) return NULL; + } + + packet->datalen = 0; + packet->startpos = 0; + packet->next = NULL; + + if (qtail == NULL) + qhead = packet; + else + qtail->next = packet; + qtail = packet; + + return packet; +} + +static int sndqueue_push(const void *data, size_t len) { + sndpacket_t *orighead = qhead; + sndpacket_t *origtail = qtail; + size_t origlen = origtail ? origtail->datalen : 0; + Uint8 *ptr = data; + + while (len > 0) { + sndpacket_t *packet = qtail; + if (!packet || (packet->datalen >= SNDPACKETLEN)) { + packet = alloc_sndpacket(); + if (!packet) { + // out of memory, fuck everything + return -1; + } + } + + const size_t room = SNDPACKETLEN - packet->datalen; + const size_t datalen = (len < room) ? len : room; + memcpy(packet->data + packet->datalen, ptr, datalen); + ptr += datalen; + len -= datalen; + packet->datalen += datalen; + queued += datalen; + } + + return 0; +} + +static void audio_drain(void *user, Uint8 *buf, int len) { + const size_t tx = sndqueue_read(buf, len); + buf += tx; + len -= (int)tx; + if (len > 0) memset(buf, aspec.silence, len); +} + +static bool audio_sdl_init(void) { + if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { + fprintf(stderr, "SDL init error: %s\n", SDL_GetError()); + return false; + } + + SDL_AudioSpec want, have; + memset(&want, 0, sizeof(want)); + want.freq = 32000; + want.format = AUDIO_S16SYS; + want.channels = 2; + want.samples = 512; + want.callback = audio_drain; + if (SDL_OpenAudio(&want, &have) == -1) { + fprintf(stderr, "SDL_OpenAudio error: %s\n", SDL_GetError()); + return false; + } + + aspec = have; + + was_init = 1; + SDL_PauseAudio(0); + + return true; +} + +static int audio_sdl_buffered(void) { + SDL_LockAudio(); + int len = queued / 4; + SDL_UnlockAudio(); + return len; +} + +static int audio_sdl_get_desired_buffered(void) { + return 1100; +} + +static void audio_sdl_play(const uint8_t *buf, size_t len) { + SDL_LockAudio(); + // Don't fill the audio buffer too much in case this happens + if (queued / 4 < 6000) + sndqueue_push(buf, len); + SDL_UnlockAudio(); +} + +static void audio_sdl_shutdown(void) { + if (SDL_WasInit(SDL_INIT_AUDIO)) { + if (was_init) { + SDL_CloseAudio(); + was_init = 0; + } + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } +} + +struct AudioAPI audio_sdl = { + audio_sdl_init, + audio_sdl_buffered, + audio_sdl_get_desired_buffered, + audio_sdl_play, + audio_sdl_shutdown +}; + +#endif diff --git a/src/pc/audio/audio_sdl.c b/src/pc/audio/audio_sdl2.c similarity index 97% rename from src/pc/audio/audio_sdl.c rename to src/pc/audio/audio_sdl2.c index 0701b037..b0abea7a 100644 --- a/src/pc/audio/audio_sdl.c +++ b/src/pc/audio/audio_sdl2.c @@ -11,10 +11,11 @@ static bool audio_sdl_init(void) { fprintf(stderr, "SDL init error: %s\n", SDL_GetError()); return false; } + SDL_AudioSpec want, have; SDL_zero(want); want.freq = 32000; - want.format = AUDIO_S16; + want.format = AUDIO_S16SYS; want.channels = 2; want.samples = 512; want.callback = NULL; diff --git a/src/pc/controller/controller_entry_point.c b/src/pc/controller/controller_entry_point.c index c2e5207a..e5ff3eb8 100644 --- a/src/pc/controller/controller_entry_point.c +++ b/src/pc/controller/controller_entry_point.c @@ -13,7 +13,9 @@ static struct ControllerAPI *controller_implementations[] = { &controller_recorded_tas, + #ifdef CAPI_SDL2 &controller_sdl, + #endif &controller_keyboard, }; diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl2.c similarity index 99% rename from src/pc/controller/controller_sdl.c rename to src/pc/controller/controller_sdl2.c index a71a82eb..a45a55de 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl2.c @@ -13,7 +13,7 @@ #include #include "controller_api.h" -#include "controller_sdl.h" +#include "controller_sdl2.h" #include "../configfile.h" #include "../platform.h" #include "../fs/fs.h" diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index b3d090b0..324f082e 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -19,13 +19,20 @@ # include #endif -#include - #define GL_GLEXT_PROTOTYPES 1 -#ifdef USE_GLES -# include -#else -# include + +#ifdef WAPI_SDL2 +# include +# ifdef USE_GLES +# include +# else +# include +# endif +#elif defined(WAPI_SDL1) +# include +# ifndef GLEW_STATIC +# include +# endif #endif #include "../platform.h" diff --git a/src/pc/gfx/gfx_opengl_legacy.c b/src/pc/gfx/gfx_opengl_legacy.c index 5f7c7daa..4547b305 100644 --- a/src/pc/gfx/gfx_opengl_legacy.c +++ b/src/pc/gfx/gfx_opengl_legacy.c @@ -15,15 +15,22 @@ # define FOR_WINDOWS 0 #endif -#include - #if FOR_WINDOWS || defined(OSX_BUILD) # define GLEW_STATIC # include #endif #define GL_GLEXT_PROTOTYPES 1 -#include + +#ifdef WAPI_SDL2 +# include +# include +#elif defined(WAPI_SDL1) +# include +# ifndef GLEW_STATIC +# include +# endif +#endif // redefine this if using a different GL loader #define mglGetProcAddress(name) SDL_GL_GetProcAddress(name) diff --git a/src/pc/gfx/gfx_sdl1.c b/src/pc/gfx/gfx_sdl1.c new file mode 100644 index 00000000..e8c6fa4e --- /dev/null +++ b/src/pc/gfx/gfx_sdl1.c @@ -0,0 +1,280 @@ +#ifdef WAPI_SDL1 + +#ifdef __MINGW32__ +#define FOR_WINDOWS 1 +#else +#define FOR_WINDOWS 0 +#endif + +#include + +#include +#include + +#include "gfx_window_manager_api.h" +#include "gfx_screen_config.h" +#include "../pc_main.h" +#include "../configfile.h" +#include "../cliopts.h" +#include "../platform.h" + +#include "src/pc/controller/controller_keyboard.h" + +// TODO: figure out if this shit even works +#ifdef VERSION_EU +# define FRAMERATE 25 +#else +# define FRAMERATE 30 +#endif + +static int inverted_scancode_table[512]; + +static kb_callback_t kb_key_down = NULL; +static kb_callback_t kb_key_up = NULL; +static void (*kb_all_keys_up)(void) = NULL; + +// time between consequtive game frames +static const int frame_time = 1000 / FRAMERATE; + +static int desktop_w = 640; +static int desktop_h = 480; +static int desktop_bpp = 24; + +static int window_w = 0; +static int window_h = 0; + +const SDLKey windows_scancode_table[] = { + /* 0 1 2 3 4 5 6 7 */ + /* 8 9 A B C D E F */ + SDLK_UNKNOWN, SDLK_ESCAPE, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, /* 0 */ + SDLK_7, SDLK_8, SDLK_9, SDLK_0, SDLK_MINUS, SDLK_EQUALS, SDLK_BACKSPACE, SDLK_TAB, /* 0 */ + + SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i, /* 1 */ + SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, SDLK_RETURN, SDLK_LCTRL, SDLK_a, SDLK_s, /* 1 */ + + SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, SDLK_SEMICOLON, /* 2 */ + SDLK_UNKNOWN, SDLK_BACKQUOTE, SDLK_LSHIFT, SDLK_BACKSLASH, SDLK_z, SDLK_x, SDLK_c, SDLK_v, /* 2 */ + + SDLK_b, SDLK_n, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_RSHIFT, SDLK_PRINT, /* 3 */ + SDLK_LALT, SDLK_SPACE, SDLK_CAPSLOCK, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, /* 3 */ + + SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_NUMLOCK, SDLK_SCROLLOCK, SDLK_HOME, /* 4 */ + SDLK_UP, SDLK_PAGEUP, SDLK_KP_MINUS, SDLK_LEFT, SDLK_KP5, SDLK_RIGHT, SDLK_KP_PLUS, SDLK_END, /* 4 */ + + SDLK_DOWN, SDLK_PAGEDOWN, SDLK_INSERT, SDLK_DELETE, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_F11, /* 5 */ + SDLK_F12, SDLK_PAUSE, SDLK_UNKNOWN, SDLK_LSUPER, SDLK_RSUPER, SDLK_MODE, SDLK_UNKNOWN, SDLK_UNKNOWN, /* 5 */ + + SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_F13, SDLK_F14, SDLK_F15, SDLK_UNKNOWN, /* 6 */ + SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, /* 6 */ + + SDLK_WORLD_2, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_WORLD_1, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, SDLK_UNKNOWN, /* 7 */ + SDLK_UNKNOWN, SDLK_WORLD_4, SDLK_UNKNOWN, SDLK_WORLD_5, SDLK_UNKNOWN, SDLK_WORLD_3, SDLK_UNKNOWN, SDLK_UNKNOWN /* 7 */ +}; + +const SDLKey scancode_rmapping_extended[][2] = { + { SDLK_KP_ENTER, SDLK_RETURN }, + { SDLK_RALT, SDLK_LALT }, + { SDLK_RCTRL, SDLK_LCTRL }, + { SDLK_KP_DIVIDE, SDLK_SLASH }, + //{ SDLK_KPPLUS, SDLK_CAPSLOCK } +}; + +const SDLKey scancode_rmapping_nonextended[][2] = { + { SDLK_KP7, SDLK_HOME }, + { SDLK_KP8, SDLK_UP }, + { SDLK_KP9, SDLK_PAGEUP }, + { SDLK_KP4, SDLK_LEFT }, + { SDLK_KP6, SDLK_RIGHT }, + { SDLK_KP1, SDLK_END }, + { SDLK_KP2, SDLK_DOWN }, + { SDLK_KP3, SDLK_PAGEDOWN }, + { SDLK_KP0, SDLK_INSERT }, + { SDLK_KP_PERIOD, SDLK_DELETE }, + { SDLK_KP_MULTIPLY, SDLK_PRINT } +}; + +static void gfx_sdl_set_mode(void) { + if (configWindow.exiting_fullscreen) + configWindow.exiting_fullscreen = false; + + if (configWindow.reset) { + configWindow.fullscreen = false; + configWindow.x = WAPI_WIN_CENTERPOS; + configWindow.y = WAPI_WIN_CENTERPOS; + configWindow.w = DESIRED_SCREEN_WIDTH; + configWindow.h = DESIRED_SCREEN_HEIGHT; + configWindow.reset = false; + } + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + uint32_t flags = SDL_OPENGL; + if (configWindow.fullscreen) + flags |= SDL_FULLSCREEN; + else + flags |= SDL_RESIZABLE; + + if (!SDL_VideoModeOK(configWindow.w, configWindow.h, desktop_bpp, flags)) { + printf( + "video mode [%dx%d fullscreen %d] not available, falling back to default\n", + configWindow.w, configWindow.h, configWindow.fullscreen + ); + configWindow.w = DESIRED_SCREEN_WIDTH; + configWindow.h = DESIRED_SCREEN_HEIGHT; + configWindow.fullscreen = false; + flags = SDL_OPENGL | SDL_RESIZABLE; + } + + if (!SDL_SetVideoMode(configWindow.w, configWindow.h, desktop_bpp, flags)) { + sys_fatal( + "could not set video mode [%dx%d fullscreen %d]: %s\n", + configWindow.w, configWindow.h, configWindow.fullscreen, SDL_GetError() + ); + } + + window_w = configWindow.w; + window_h = configWindow.h; +} + +static void gfx_sdl_init(const char *window_title) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) + sys_fatal("Could not init SDL1 video: %s\n", SDL_GetError()); + + const SDL_VideoInfo *vinfo = SDL_GetVideoInfo(); + desktop_w = vinfo->current_w; + desktop_h = vinfo->current_h; + desktop_bpp = vinfo->vfmt->BitsPerPixel; + + SDL_WM_SetCaption(window_title, NULL); + + // set actual desired video mode + + gfx_sdl_set_mode(); + + SDL_ShowCursor(0); + + for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDLKey); i++) { + inverted_scancode_table[windows_scancode_table[i]] = i; + } + + for (size_t i = 0; i < sizeof(scancode_rmapping_extended) / sizeof(scancode_rmapping_extended[0]); i++) { + inverted_scancode_table[scancode_rmapping_extended[i][0]] = inverted_scancode_table[scancode_rmapping_extended[i][1]] + 0x100; + } + + for (size_t i = 0; i < sizeof(scancode_rmapping_nonextended) / sizeof(scancode_rmapping_nonextended[0]); i++) { + inverted_scancode_table[scancode_rmapping_nonextended[i][0]] = inverted_scancode_table[scancode_rmapping_nonextended[i][1]]; + inverted_scancode_table[scancode_rmapping_nonextended[i][1]] += 0x100; + } +} + +static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) { + run_one_game_iter(); +} + +static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) { + if (width) *width = window_w; + if (height) *height = window_h; +} + +static int translate_scancode(int scancode) { + if (scancode < 512) { + return inverted_scancode_table[scancode]; + } else { + return 0; + } +} + +static void gfx_sdl_onkeydown(int scancode) { + if (kb_key_down) + kb_key_down(translate_scancode(scancode)); +} + +static void gfx_sdl_onkeyup(int scancode) { + if (kb_key_up) + kb_key_up(translate_scancode(scancode)); +} + +static void gfx_sdl_handle_events(void) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { +#ifndef TARGET_WEB + // Scancodes are broken in Emscripten SDL2: https://bugzilla.libsdl.org/show_bug.cgi?id=3259 + case SDL_KEYDOWN: + gfx_sdl_onkeydown(event.key.keysym.sym); + // ALT+F4 in case the OS doesn't do it (SDL1 doesn't seem to do it on my machine) + if (event.key.keysym.sym == SDLK_F4 && (event.key.keysym.mod & (KMOD_LALT | KMOD_RALT))) + game_exit(); + break; + case SDL_KEYUP: + gfx_sdl_onkeyup(event.key.keysym.sym); + break; +#endif + case SDL_VIDEORESIZE: + window_w = configWindow.w = event.resize.w; + window_h = configWindow.h = event.resize.h; + break; + case SDL_QUIT: + game_exit(); + break; + } + } +} + +static void gfx_sdl_set_keyboard_callbacks(kb_callback_t on_key_down, kb_callback_t on_key_up, void (*on_all_keys_up)(void)) { + kb_key_down = on_key_down; + kb_key_up = on_key_up; + kb_all_keys_up = on_all_keys_up; +} + +static bool gfx_sdl_start_frame(void) { + return true; +} + +static inline void sync_framerate_with_timer(void) { + static Uint32 last_time = 0; + // get base timestamp on the first frame (might be different from 0) + if (last_time == 0) last_time = SDL_GetTicks(); + const int elapsed = SDL_GetTicks() - last_time; + if (elapsed < frame_time) + SDL_Delay(frame_time - elapsed); + last_time += frame_time; +} + +static void gfx_sdl_swap_buffers_begin(void) { + sync_framerate_with_timer(); + SDL_GL_SwapBuffers(); +} + +static void gfx_sdl_swap_buffers_end(void) { +} + +static double gfx_sdl_get_time(void) { + return 0.0; +} + + +static void gfx_sdl_shutdown(void) { + if (SDL_WasInit(0)) + SDL_Quit(); +} + +struct GfxWindowManagerAPI gfx_sdl = { + gfx_sdl_init, + gfx_sdl_set_keyboard_callbacks, + gfx_sdl_main_loop, + gfx_sdl_get_dimensions, + gfx_sdl_handle_events, + gfx_sdl_start_frame, + gfx_sdl_swap_buffers_begin, + gfx_sdl_swap_buffers_end, + gfx_sdl_get_time, + gfx_sdl_shutdown +}; + +#endif // BACKEND_WM diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index ed6ee746..ada661f1 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -222,8 +222,10 @@ void main_func(void) { gfx_init(wm_api, rendering_api, window_title); wm_api->set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up); + #if defined(AAPI_SDL1) || defined(AAPI_SDL2) if (audio_api == NULL && audio_sdl.init()) audio_api = &audio_sdl; + #endif if (audio_api == NULL) { audio_api = &audio_null;