diff --git a/src/Attributes.h b/src/Attributes.h index ac0b6b3c..35fcd26f 100644 --- a/src/Attributes.h +++ b/src/Attributes.h @@ -1,5 +1,15 @@ #pragma once +/// Include file for portable usage of __attribute__ + +#ifdef __MINGW32__ +#define ATTRIBUTE_FORMAT_PRINTF(stringIndex, firstToCheck) __attribute__((format(__MINGW_PRINTF_FORMAT, stringIndex, firstToCheck))) +#elif defined(__GNUC__) +#define ATTRIBUTE_FORMAT_PRINTF(stringIndex, firstToCheck) __attribute__((format(printf, stringIndex, firstToCheck))) +#else +#define ATTRIBUTE_FORMAT_PRINTF(stringIndex, firstToCheck) +#endif + #ifdef __GNUC__ #define ATTRIBUTE_HOT __attribute__((hot)) diff --git a/src/Backends/Audio/SDL2.cpp b/src/Backends/Audio/SDL2.cpp index 02921756..74581987 100644 --- a/src/Backends/Audio/SDL2.cpp +++ b/src/Backends/Audio/SDL2.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "SDL.h" @@ -66,7 +67,8 @@ BOOL AudioBackend_Init(void) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { - Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed"); + std::string errorMessage = std::string("'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed : ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", errorMessage.c_str()); return FALSE; } @@ -85,15 +87,16 @@ BOOL AudioBackend_Init(void) SDL_AudioSpec obtained_specification; device_id = SDL_OpenAudioDevice(NULL, 0, &specification, &obtained_specification, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); - output_frequency = obtained_specification.freq; - Mixer_Init(obtained_specification.freq); - if (device_id == 0) { - Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_OpenAudioDevice' failed"); + std::string error_message = std::string("'SDL_OpenAudioDevice' failed : ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", error_message.c_str()); return FALSE; } + output_frequency = obtained_specification.freq; + Mixer_Init(obtained_specification.freq); + SDL_PauseAudioDevice(device_id, 0); printf("Selected SDL2 audio driver: %s\n", SDL_GetCurrentAudioDriver()); diff --git a/src/Backends/GLFW3/Misc.cpp b/src/Backends/GLFW3/Misc.cpp index 44027782..bac11777 100644 --- a/src/Backends/GLFW3/Misc.cpp +++ b/src/Backends/GLFW3/Misc.cpp @@ -1,6 +1,7 @@ #include "../Misc.h" #include +#include #include #include #include @@ -17,6 +18,7 @@ #include "../../Organya.h" #include "../../Profile.h" #include "../../Resource.h" +#include "../../Attributes.h" #define DO_KEY(GLFW_KEY, BACKEND_KEY) \ case GLFW_KEY: \ @@ -290,6 +292,26 @@ void Backend_ShowMessageBox(const char *title, const char *message) printf("ShowMessageBox - '%s' - '%s'\n", title, message); } +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...) +{ + va_list argumentList; + va_start(argumentList, format); + fputs("ERROR: ", stderr); + vfprintf(stderr, format, argumentList); + fputc('\n', stderr); + va_end(argumentList); +} + +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...) +{ + va_list argumentList; + va_start(argumentList, format); + fputs("INFO: ", stdout); + vprintf(format, argumentList); + putchar('\n'); + va_end(argumentList); +} + unsigned long Backend_GetTicks(void) { return (unsigned long)(glfwGetTime() * 1000.0); diff --git a/src/Backends/Misc.h b/src/Backends/Misc.h index adf99783..00ba3e1f 100644 --- a/src/Backends/Misc.h +++ b/src/Backends/Misc.h @@ -1,6 +1,7 @@ #pragma once #include "../WindowsWrapper.h" +#include "../Attributes.h" enum { @@ -96,5 +97,7 @@ void PlaybackBackend_EnableDragAndDrop(void); BOOL Backend_SystemTask(void); void Backend_GetKeyboardState(BOOL *keyboard_state); void Backend_ShowMessageBox(const char *title, const char *message); +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...); +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...); unsigned long Backend_GetTicks(void); void Backend_Delay(unsigned int ticks); diff --git a/src/Backends/Rendering/SDLSurface.cpp b/src/Backends/Rendering/SDLSurface.cpp index 8585c356..e72aa97c 100644 --- a/src/Backends/Rendering/SDLSurface.cpp +++ b/src/Backends/Rendering/SDLSurface.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "SDL.h" @@ -51,28 +52,38 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w if (window != NULL) { if (fullscreen) - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); + { + if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) < 0) + Backend_PrintError("Could not set window to fullscreen: %s", SDL_GetError()); + } window_sdlsurface = SDL_GetWindowSurface(window); - - framebuffer.sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24); - - if (framebuffer.sdlsurface != NULL) + if (!window_sdlsurface) { - Backend_PostWindowCreation(); - - return &framebuffer; + std::string error_message = std::string("Could not get SDL surface of the window: ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", error_message.c_str()); } else { - Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", "Could not create framebuffer surface"); + framebuffer.sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24); + + if (framebuffer.sdlsurface != NULL) + { + Backend_PostWindowCreation(); + + return &framebuffer; + } + + std::string error_message = std::string("Could not create framebuffer surface : ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", error_message.c_str()); } SDL_DestroyWindow(window); } else { - Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", "Could not create window"); + std::string error_message = std::string("Could not create window : ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", error_message.c_str()); } return NULL; @@ -86,8 +97,11 @@ void RenderBackend_Deinit(void) void RenderBackend_DrawScreen(void) { - SDL_BlitSurface(framebuffer.sdlsurface, NULL, window_sdlsurface, NULL); - SDL_UpdateWindowSurface(window); + if (SDL_BlitSurface(framebuffer.sdlsurface, NULL, window_sdlsurface, NULL) < 0) + Backend_PrintError("Couldn't blit framebuffer surface to window surface: %s", SDL_GetError()); + + if (SDL_UpdateWindowSurface(window) < 0) + Backend_PrintError("Couldn't put window surface on screen: %s", SDL_GetError()); } RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height) @@ -162,9 +176,12 @@ void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect, destination_rect.w = source_rect.w; destination_rect.h = source_rect.h; - SDL_SetColorKey(source_surface->sdlsurface, colour_key ? SDL_TRUE : SDL_FALSE, SDL_MapRGB(source_surface->sdlsurface->format, 0, 0, 0)); // Assumes the colour key will always be #000000 (black) + // Assumes the colour key will always be #000000 (black) + if (SDL_SetColorKey(source_surface->sdlsurface, colour_key ? SDL_TRUE : SDL_FALSE, SDL_MapRGB(source_surface->sdlsurface->format, 0, 0, 0)) < 0) + Backend_PrintError("Couldn't set color key of surface: %s", SDL_GetError()); - SDL_BlitSurface(source_surface->sdlsurface, &source_rect, destination_surface->sdlsurface, &destination_rect); + if (SDL_BlitSurface(source_surface->sdlsurface, &source_rect, destination_surface->sdlsurface, &destination_rect) < 0) + Backend_PrintError("Couldn't blit surface: %s", SDL_GetError()); } void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue) @@ -175,7 +192,8 @@ void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, SDL_Rect destination_rect; RectToSDLRect(rect, &destination_rect); - SDL_FillRect(surface->sdlsurface, &destination_rect, SDL_MapRGB(surface->sdlsurface->format, red, green, blue)); + if (SDL_FillRect(surface->sdlsurface, &destination_rect, SDL_MapRGB(surface->sdlsurface->format, red, green, blue)) < 0) + Backend_PrintError("Couldn't fill rectangle with color: %s", SDL_GetError()); } RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch) @@ -189,6 +207,7 @@ RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsign if (glyph->sdlsurface == NULL) { + Backend_PrintError("Couldn't create RBG surface: %s", SDL_GetError()); free(glyph); return NULL; } @@ -240,9 +259,11 @@ void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y) rect.w = glyph->sdlsurface->w; rect.h = glyph->sdlsurface->h; - SDL_SetSurfaceColorMod(glyph->sdlsurface, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]); + if (SDL_SetSurfaceColorMod(glyph->sdlsurface, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]) < 0) + Backend_PrintError("Couldn't set color value: %s", SDL_GetError()); - SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect); + if (SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect) < 0) + Backend_PrintError("Couldn't blit glyph indivual surface to final glyph surface: %s", SDL_GetError()); } void RenderBackend_FlushGlyphs(void) @@ -263,4 +284,7 @@ void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height) // https://wiki.libsdl.org/SDL_GetWindowSurface // We need to fetch a new surface pointer window_sdlsurface = SDL_GetWindowSurface(window); + + if (!window_sdlsurface) + Backend_PrintError("Couldn't get SDL surface for window after resize: %s", SDL_GetError()); } diff --git a/src/Backends/Rendering/SDLTexture.cpp b/src/Backends/Rendering/SDLTexture.cpp index b8aeb0cc..8cc07c7f 100644 --- a/src/Backends/Rendering/SDLTexture.cpp +++ b/src/Backends/Rendering/SDLTexture.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "SDL.h" @@ -73,8 +74,11 @@ static void GlyphBatch_Draw(spritebatch_sprite_t *sprites, int count, int textur // The SDL_Texture side of things uses alpha, not a colour-key, so the bug where the font is blended // with the colour key doesn't occur. - SDL_SetTextureColorMod(texture_atlas, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]); - SDL_SetTextureBlendMode(texture_atlas, SDL_BLENDMODE_BLEND); + if (SDL_SetTextureColorMod(texture_atlas, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]) < 0) + Backend_PrintError("Couldn't set additional color value: %s", SDL_GetError()); + + if (SDL_SetTextureBlendMode(texture_atlas, SDL_BLENDMODE_BLEND) < 0) + Backend_PrintError("Couldn't set texture blend mode: %s", SDL_GetError()); for (int i = 0; i < count; ++i) { @@ -83,7 +87,8 @@ static void GlyphBatch_Draw(spritebatch_sprite_t *sprites, int count, int textur SDL_Rect source_rect = {(int)(texture_w * sprites[i].minx), (int)(texture_h * sprites[i].maxy), (int)glyph->width, (int)glyph->height}; SDL_Rect destination_rect = {(int)sprites[i].x, (int)sprites[i].y, (int)glyph->width, (int)glyph->height}; - SDL_RenderCopy(renderer, texture_atlas, &source_rect, &destination_rect); + if (SDL_RenderCopy(renderer, texture_atlas, &source_rect, &destination_rect) < 0) + Backend_PrintError("Couldn't copy glyph texture portion to renderer: %s", SDL_GetError()); } } @@ -104,7 +109,11 @@ static SPRITEBATCH_U64 GlyphBatch_CreateTexture(void *pixels, int w, int h, void SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, w, h); - SDL_UpdateTexture(texture, NULL, pixels, w * 4); + if (!texture) + Backend_PrintError("Couldn't create texture for renderer: %s", SDL_GetError()); + + if (SDL_UpdateTexture(texture, NULL, pixels, w * 4) < 0) + Backend_PrintError("Couldn't update texture : %s", SDL_GetError()); return (SPRITEBATCH_U64)texture; } @@ -119,13 +128,15 @@ static void GlyphBatch_DestroyTexture(SPRITEBATCH_U64 texture_id, void *udata) RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen) { - puts("Available SDL2 render drivers:"); + Backend_PrintInfo("Available SDL2 render drivers:"); for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i) { SDL_RendererInfo info; - SDL_GetRenderDriverInfo(i, &info); - puts(info.name); + if (SDL_GetRenderDriverInfo(i, &info) < 0) + Backend_PrintError("Couldn't get render driver information : %s", SDL_GetError()); + else + Backend_PrintInfo("%s", info.name); } window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0); @@ -133,7 +144,10 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w if (window != NULL) { if (fullscreen) - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); + { + if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) < 0) + Backend_PrintError("Couldn't set window to fullscreen: %s", SDL_GetError()); + } #if SDL_VERSION_ATLEAST(2,0,10) SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1"); // We never interfere with the renderer, so don't let SDL implicitly disable batching @@ -144,8 +158,10 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w if (renderer != NULL) { SDL_RendererInfo info; - SDL_GetRendererInfo(renderer, &info); - printf("Selected SDL2 render driver: %s\n", info.name); + if (SDL_GetRendererInfo(renderer, &info) < 0) + Backend_PrintError("Couldn't get selected render driver information : %s", SDL_GetError()); + else + Backend_PrintInfo("Selected SDL2 render driver: %s", info.name); framebuffer.texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, screen_width, screen_height); @@ -173,14 +189,16 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w } else { - Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Could not create framebuffer"); + std::string error_message = std::string("Could not create framebuffer: ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", error_message.c_str()); } SDL_DestroyRenderer(renderer); } else { - Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Could not create renderer"); + std::string error_message = std::string("Could not create renderer: ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", error_message.c_str()); } @@ -188,7 +206,8 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w } else { - Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Could not create window"); + std::string error_message = std::string("Could not create window: ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", error_message.c_str()); } return NULL; diff --git a/src/Backends/SDL2/Misc.cpp b/src/Backends/SDL2/Misc.cpp index c3857940..0f2fe232 100644 --- a/src/Backends/SDL2/Misc.cpp +++ b/src/Backends/SDL2/Misc.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "SDL.h" @@ -36,25 +37,30 @@ BOOL Backend_Init(void) { if (SDL_InitSubSystem(SDL_INIT_VIDEO) == 0) { - puts("Available SDL2 video drivers:"); + Backend_PrintInfo("Available SDL2 video drivers:"); for (int i = 0; i < SDL_GetNumVideoDrivers(); ++i) - puts(SDL_GetVideoDriver(i)); + Backend_PrintInfo("%s", SDL_GetVideoDriver(i)); const char *driver = SDL_GetCurrentVideoDriver(); if (driver != NULL) - printf("Selected SDL2 video driver: %s\n", driver); + Backend_PrintInfo("Selected SDL2 video driver: %s", driver); + else + Backend_PrintError("No SDL2 video driver initialized !"); return TRUE; } - Backend_ShowMessageBox("Fatal error", "Could not initialise SDL2 video subsystem"); + std::string error_message = std::string("Could not initialise SDL2 video subsystem: ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error", error_message.c_str()); SDL_Quit(); + return FALSE; } - Backend_ShowMessageBox("Fatal error", "Could not initialise SDL2"); + std::string error_message = std::string("Could not initialise SDL2: ") + SDL_GetError(); + Backend_ShowMessageBox("Fatal error", error_message.c_str()); return FALSE; } @@ -80,6 +86,9 @@ void Backend_PostWindowCreation(void) BOOL Backend_GetBasePath(char *string_buffer) { char *base_path = SDL_GetBasePath(); + if (!base_path) + return FALSE; + // Trim the trailing '/' size_t base_path_length = strlen(base_path); base_path[base_path_length - 1] = '\0'; @@ -103,6 +112,10 @@ void Backend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, SDL_SetWindowIcon(window, surface); SDL_FreeSurface(surface); } + else + { + Backend_PrintError("Couldn't create RGB surface for window icon: %s", SDL_GetError()); + } } void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height) @@ -126,6 +139,10 @@ void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsi } } } + else + { + Backend_PrintError("Failed to allocate memory for cursor surface"); + } } void PlaybackBackend_EnableDragAndDrop(void) @@ -283,8 +300,29 @@ void Backend_GetKeyboardState(BOOL *out_keyboard_state) void Backend_ShowMessageBox(const char *title, const char *message) { - printf("ShowMessageBox - '%s' - '%s'\n", title, message); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, window); + fprintf(stderr, "ShowMessageBox - '%s' - '%s'\n", title, message); + if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, window) != 0) + Backend_PrintError("Was also unable to display a message box containing the error: %s", SDL_GetError()); +} + +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...) +{ + va_list argumentList; + va_start(argumentList, format); + fputs("ERROR: ", stderr); + vfprintf(stderr, format, argumentList); + fputc('\n', stderr); + va_end(argumentList); +} + +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...) +{ + va_list argumentList; + va_start(argumentList, format); + fputs("INFO: ", stdout); + vprintf(format, argumentList); + putchar('\n'); + va_end(argumentList); } unsigned long Backend_GetTicks(void)