#include #include "internal/engine_internal.h" #include "internal/util/error.h" bool engine_sdl_init_state( engine_sdl_state_t **state, uint32_t window_width, uint32_t window_height, const char window_name[] ) { *state = (engine_sdl_state_t *) malloc(sizeof(engine_sdl_state_t)); if (*state == NULL) { eprintf("failed to initialize engine_sdl_state"); return RCODE_FAILURE; } (*state)->width = window_width; (*state)->height = window_height; strncpy( (*state)->window_name, window_name, WINDOW_NAME_MAX_LENGTH - 1 ); (*state)->window_name[WINDOW_NAME_MAX_LENGTH - 1] = '\0'; return RCODE_SUCCESS; } bool engine_sdl_init_root() { if (!SDL_Init(SDL_INIT_VIDEO)) { eprintf("SDL_Init failed! %s\n", SDL_GetError()); return RCODE_FAILURE; } else { return RCODE_SUCCESS; } } bool engine_sdl_init_window( engine_sdl_state_t* state ) { state->window = SDL_CreateWindow( state->window_name, state->width, state->height, 0 ); if (state->window == NULL) { eprintf("SDL_CreateWindow failed! %s\n", SDL_GetError()); SDL_Quit(); return RCODE_FAILURE; } return RCODE_SUCCESS; } bool engine_sdl_init_renderer( engine_sdl_state_t *state ) { state->renderer = SDL_CreateRenderer(state->window, NULL); if (state->renderer == NULL) { eprintf("SDL_CreateRenderer failed! %s\n", SDL_GetError()); SDL_DestroyWindow(state->window); SDL_Quit(); return RCODE_FAILURE; } // enable VSync if (!SDL_SetRenderVSync(state->renderer, 1)) { eprintf("SDL_SetRenderVSync failed: %s\n", SDL_GetError()); } return RCODE_SUCCESS; } bool engine_sdl_init_texture( engine_sdl_state_t *state ) { state->texture = SDL_CreateTexture( state->renderer, SDL_PIXELFORMAT_XRGB8888, SDL_TEXTUREACCESS_STREAMING, state->width, state->height ); if (state->texture == NULL) { eprintf("SDL_CreateTexture failed! %s\n", SDL_GetError()); SDL_DestroyWindow(state->window); SDL_DestroyRenderer(state->renderer); SDL_Quit(); return RCODE_FAILURE; } return RCODE_SUCCESS; } engine_sdl_state_t* engine_sdl_init( uint32_t window_width, uint32_t window_height, const char window_name[] ) { engine_sdl_state_t *state; if (!engine_sdl_init_state( &state, window_width, window_height, window_name ) || !engine_sdl_init_root() || !engine_sdl_init_window(state) || !engine_sdl_init_renderer(state) || !engine_sdl_init_texture(state) ) { return NULL; } return state; } /** * only call intentinally, not when engine_sdl_init fails * -> it cleans up after itself already */ void engine_sdl_destroy( engine_sdl_state_t *state ) { SDL_DestroyTexture(state->texture); SDL_DestroyRenderer(state->renderer); SDL_DestroyWindow(state->window); SDL_Quit(); free(state); } bool engine_init( uint32_t window_width, uint32_t window_height, const char window_name[], void (*engine_poll_events)(void), void (*engine_update_framebuffer)(void) ) { internal_state = (engine_internal_state_t *) malloc(sizeof(engine_internal_state_t)); if (internal_state == NULL) { return RCODE_FAILURE; } game_state = (game_state_t *) malloc(sizeof(game_state_t)); if (game_state == NULL) { free(internal_state); return RCODE_FAILURE; } game_state->framebuffer = (uint32_t *) malloc(sizeof(uint32_t) * window_width * window_height); if (game_state->framebuffer == NULL) { free(internal_state); free(game_state); return RCODE_FAILURE; } internal_state->engine_poll_events = engine_poll_events; internal_state->engine_update_framebuffer = engine_update_framebuffer; internal_state->sdl_state = engine_sdl_init( window_width, window_height, window_name ); if (internal_state->sdl_state == NULL) { free(internal_state); free(game_state->framebuffer); free(game_state); return RCODE_FAILURE; } game_state->is_running = true; game_state->framebuffer_dirty = true; game_state->dirty_rect = (SDL_Rect) { .x = 0, .y = 0, .w = game_state->width, .h = game_state->height }; game_state->width = internal_state->sdl_state->width; game_state->height = internal_state->sdl_state->height; return RCODE_SUCCESS; }