From e6c514b0eafe69ee73aed62ab781fc8c7eb1c899 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Thu, 26 May 2022 21:22:38 -0500 Subject: [PATCH] Progress on SDL2 backend. Very broken. --- client/client.pro | 9 +- client/client.pro.user | 37 ++- client/src/gui/gui.c | 7 +- client/src/platform/djgpp.c | 121 ++++++++++ client/src/platform/djgpp.h | 83 +++++++ client/src/platform/grx.c | 28 +-- client/src/platform/grx.h | 10 +- client/src/platform/platform.h | 6 +- client/src/platform/sdl2.c | 397 ++++++++++++++++++++++++++++++++- client/src/platform/sdl2.h | 85 +++++++ 10 files changed, 749 insertions(+), 34 deletions(-) diff --git a/client/client.pro b/client/client.pro index 6a1c325..7b53d5c 100644 --- a/client/client.pro +++ b/client/client.pro @@ -4,8 +4,8 @@ CONFIG -= qt CONFIG -= console CONFIG += c99 -CONFIG += BACKEND_GRX -#CONFIG += BACKEND_SDL2 +#CONFIG += BACKEND_GRX +CONFIG += BACKEND_SDL2 #CONFIG += BACKEND_DJGPP SHARED = $$PWD/../shared @@ -57,9 +57,12 @@ BACKEND_GRX { BACKEND_SDL2 { DEFINES += BACKEND_SDL2 + LIBS += \ + -lSDL2 \ + -lSDL2_image } -BACKEND_DJGPP +BACKEND_DJGPP { DEFINES += BACKEND_DJGPP } diff --git a/client/client.pro.user b/client/client.pro.user index 456ecd5..89d7c66 100644 --- a/client/client.pro.user +++ b/client/client.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -56,6 +56,35 @@ true + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + true + Builtin.BuildSystem + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + ProjectExplorer.Project.Target.0 @@ -206,12 +235,14 @@ 2 - ProjectExplorer.CustomExecutableRunConfiguration - + Qt4ProjectManager.Qt4RunConfiguration:/home/scott/code/gui/client/client.pro + /home/scott/code/gui/client/client.pro false true + true false true + /home/scott/code/gui/build-client-Desktop_Qt_5_15_0_GCC_64bit-Debug/bin 1 diff --git a/client/src/gui/gui.c b/client/src/gui/gui.c index b0159f0..e297b47 100644 --- a/client/src/gui/gui.c +++ b/client/src/gui/gui.c @@ -62,24 +62,21 @@ void guiShutdown(void) { hmfree(_widgetCatalog); wmShutdown(); - mouseShutdown(); videoSurfaceDestroy(_mousePointer); videoSurfaceDestroy(__guiBackBuffer); - videoShutdown(); + platformShutdown(); } void guiStartup(int16_t width, int16_t height, int16_t depth) { - videoStartup(width, height, depth); + platformStartup(width, height, depth); __guiScreenBuffer = videoSurfaceScreenGet(); __guiBackBuffer = videoSurfaceCreate(videoDisplayWidthGet(), videoDisplayHeightGet()); - mouseStartup(); - _mousePointer = imageLoad("mouse.png"); _mouseTransparency = videoSurfacePixelGet(_mousePointer, videoSurfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color. diff --git a/client/src/platform/djgpp.c b/client/src/platform/djgpp.c index 2b68df3..6081272 100644 --- a/client/src/platform/djgpp.c +++ b/client/src/platform/djgpp.c @@ -4,4 +4,125 @@ #include "djgpp.h" +FontT *__font8x14 = NULL; + + +void fontWrite(char *message, int16_t x, int16_t y, FontT *font, ColorT foreground, ColorT background) { + +} + + +SurfaceT *imageLoad(char *filename) { + SurfaceT *image = NULL; + + return image; +} + + +void platformEventGet(EventT *event) { + +} + + +void platformShutdown(void) { + +} + + +void platformStartup(int16_t width, int16_t height, int16_t depth) { + +} + +uint16_t videoDisplayHeightGet(void) { + return 0; +} + + +uint16_t videoDisplayWidthGet(void) { + return 0; +} + + +void videoModesShow(void) { + +} + + +void videoSurfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source) { + +} + + +void videoSurfaceBlitWithTransparency(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent) { + +} + + +void videoSurfaceClear(ColorT color) { + +} + + +SurfaceT *videoSurfaceCreate(int16_t width, int16_t height) { + SurfaceT *surface = NULL; + + return surface; +} + + +void videoSurfaceDestroy(SurfaceT *surface) { + +} + + +void videoSurfaceBox(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c) { + +} + + +void videoSurfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c) { + +} + + +int16_t videoSurfaceHeightGet(SurfaceT *surface) { + return surface->height; +} + + +void videoSurfaceLineH(int16_t x1, int16_t y1, int16_t x, ColorT c) { + +} + + +void videoSurfaceLineV(int16_t x, int16_t x2, int16_t y2, ColorT c) { + +} + + +ColorT videoSurfacePixelGet(SurfaceT *surface, int16_t x, int16_t y) { + return 0; +} + + +void videoSurfacePixelSet(int16_t x, int16_t y, ColorT c) { + +} + + +void videoSurfaceSet(SurfaceT *surface) { + +} + + +SurfaceT *videoSurfaceScreenGet(void) { + return NULL; +} + + +int16_t videoSurfaceWidthGet(SurfaceT *surface) { + return surface->width; +} + + #endif // BACKEND_DJGPP diff --git a/client/src/platform/djgpp.h b/client/src/platform/djgpp.h index e15106e..ebcb750 100644 --- a/client/src/platform/djgpp.h +++ b/client/src/platform/djgpp.h @@ -1,4 +1,87 @@ #ifndef DJGPP_H #define DJGPP_H + +#include +#include + + +typedef uint32_t ColorT; + +typedef struct SurfaceS { + uint16_t width; + uint16_t height; + size_t scanline; + size_t bytes; + union { + uint8_t *bits8; + uint16_t *bits16; + uint32_t *bits32; + } buffer; +} SurfaceT; + +typedef struct EventS { + int32_t flags; + int32_t x; + int32_t y; + int32_t buttons; + int32_t key; + int32_t kbstat; + int32_t dtime; +} EventT; + +typedef struct FontS { + uint8_t width; // Width of each character in pixels. + uint8_t height; // Height of each character in pixels. + uint8_t span; // Number of characters per line in font data. + uint8_t count; // Number of characters in font, minus 1. + uint16_t widthPixels; // Width of line of font data in pixels/bits. + uint16_t heightPixels; // Number of lines of font data in pixels/bits. + uint8_t *bits; // Actual font bits. +} FontT; + + +#define EVENT_FLAG_KEYPRESS 1 +#define EVENT_FLAG_LEFT_DOWN 2 +#define EVENT_FLAG_LEFT_UP 4 +#define EVENT_FLAG_RIGHT_DOWN 8 +#define EVENT_FLAG_RIGHT_UP 16 + +#define BUTTON_LEFT 1 +#define BUTTON_RIGHT 2 + +#define META_ALT 1 +#define META_CTRL 2 +#define META_SHIFT 4 + +#define KEY_ESC 27 + +#define FONT_VGA_8x14 __font8x14 + + +extern FontT *__font8x14; + + +void fontWrite(char *message, int16_t x, int16_t y, FontT *font, ColorT foreground, ColorT background); +SurfaceT *imageLoad(char *filename); +void platformEventGet(EventT *event); +uint16_t videoDisplayHeightGet(void); +uint16_t videoDisplayWidthGet(void); +void videoSurfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source); +void videoSurfaceBlitWithTransparency(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent); +void videoSurfaceClear(ColorT color); +SurfaceT *videoSurfaceCreate(int16_t width, int16_t height); +void videoSurfaceDestroy(SurfaceT *surface); +void videoSurfaceBox(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c); +void videoSurfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c); +int16_t videoSurfaceHeightGet(SurfaceT *surface); +void videoSurfaceLineH(int16_t x1, int16_t y1, int16_t x, ColorT c); +void videoSurfaceLineV(int16_t x, int16_t x2, int16_t y2, ColorT c); +ColorT videoSurfacePixelGet(SurfaceT *surface, int16_t x, int16_t y); +void videoSurfacePixelSet(int16_t x, int16_t y, ColorT c); +void videoSurfaceSet(SurfaceT *surface); +SurfaceT *videoSurfaceScreenGet(void); +int16_t videoSurfaceWidthGet(SurfaceT *surface); + + #endif // DJGPP_H diff --git a/client/src/platform/grx.c b/client/src/platform/grx.c index 0862a7b..936366f 100644 --- a/client/src/platform/grx.c +++ b/client/src/platform/grx.c @@ -50,13 +50,22 @@ SurfaceT *imageLoad(char *filename) { } -void mouseShutdown(void) { +void platformShutdown(void) { GrMouseEraseCursor(); GrMouseUnInit(); + + GrSetMode(GR_default_text); } -void mouseStartup(void) { +void platformStartup(int16_t width, int16_t height, int16_t depth) { + // Set up graphics environment. + if (!GrSetMode(GR_width_height_bpp_graphics, width, height, depth)) { + //***TODO*** Die + } + GrSetRGBcolorMode(); + __guiBaseColors = GrAllocEgaColors(); // This does not need released. + // Set up mouse. GrMouseInit(); GrMouseEventEnable(1, 1); @@ -105,21 +114,6 @@ void videoModesShow(void) { } -void videoShutdown(void) { - GrSetMode(GR_default_text); -} - - -void videoStartup(int16_t width, int16_t height, int16_t depth) { - // Set up graphics environment. - if (!GrSetMode(GR_width_height_bpp_graphics, width, height, depth)) { - //***TODO*** Die - } - GrSetRGBcolorMode(); - __guiBaseColors = GrAllocEgaColors(); // This does not need released. -} - - void videoSurfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source) { GrBitBlt(target, targetX, targetY, source, 0, 0, videoSurfaceWidthGet(source) - 1, videoSurfaceHeightGet(source) - 1, GrWRITE); } diff --git a/client/src/platform/grx.h b/client/src/platform/grx.h index b143671..d2e29c9 100644 --- a/client/src/platform/grx.h +++ b/client/src/platform/grx.h @@ -2,7 +2,7 @@ #define GRX_H -#include "stdint.h" +#include #include "grx20.h" #include "grxkeys.h" @@ -16,8 +16,16 @@ typedef GrFont FontT; #define EVENT_FLAG_KEYPRESS GR_M_KEYPRESS #define EVENT_FLAG_LEFT_DOWN GR_M_LEFT_DOWN +#define EVENT_FLAG_LEFT_UP GR_M_LEFT_UP +#define EVENT_FLAG_RIGHT_DOWN GR_M_RIGHT_DOWN +#define EVENT_FLAG_RIGHT_UP GR_M_RIGHT_UP #define BUTTON_LEFT GR_M_LEFT +#define BUTTON_RIGHT GR_M_RIGHT + +#define META_ALT GR_KB_ALT +#define META_CTRL GR_KB_CTRL +#define META_SHIFT GR_KB_SHIFT #define KEY_ESC GrKey_Escape diff --git a/client/src/platform/platform.h b/client/src/platform/platform.h index 5d00e1e..c66f117 100644 --- a/client/src/platform/platform.h +++ b/client/src/platform/platform.h @@ -18,12 +18,10 @@ #endif -void mouseShutdown(void); -void mouseStartup(void); +void platformShutdown(void); +void platformStartup(int16_t width, int16_t height, int16_t depth); void videoModesShow(void); -void videoShutdown(void); -void videoStartup(int16_t width, int16_t height, int16_t depth); #endif // PLATFORM_H diff --git a/client/src/platform/sdl2.c b/client/src/platform/sdl2.c index 5f10d1c..f2715e8 100644 --- a/client/src/platform/sdl2.c +++ b/client/src/platform/sdl2.c @@ -1,7 +1,402 @@ #ifdef BACKEND_SDL2 -#include "linux.h" +#include "sdl2.h" + + +#define BYTES_PER_PIXEL 4 + + +FontT *__font8x14 = NULL; + + +static SDL_Window *_window = NULL; +static SDL_Renderer *_renderer = NULL; +static SDL_Surface *_surface = NULL; +static SDL_Texture *_texture = NULL; +static uint16_t _width = 0; +static uint16_t _height = 0; +static uint8_t _windowScale = 1; +static uint32_t _pixelFormat = SDL_PIXELFORMAT_RGBA8888; +static SurfaceT *_activeSurface = NULL; + + +extern ColorT *__guiBaseColors; + + +#define PUTPIXEL(s,x,y,c) s->buffer.bits32[y*s->width+x]=c +#define COLOR(r,g,b) ((r<<24)|(g<<16)|(b<<8)|255) + + +void fontWrite(char *message, int16_t x, int16_t y, FontT *font, ColorT foreground, ColorT background) { + +} + + +SurfaceT *imageLoad(char *filename) { + SurfaceT *image = NULL; + SDL_Surface *i = NULL; + SDL_Surface *s = IMG_Load(filename); + + if (s) { + i = SDL_ConvertSurfaceFormat(s, _pixelFormat, 0); + if (i) { + image = videoSurfaceCreate(s->w, s->h); + if (image) { + SDL_LockSurface(i); + memcpy(image->buffer.bits8, i->pixels, image->bytes); + SDL_UnlockSurface(i); + } + SDL_FreeSurface(i); + } + SDL_FreeSurface(s); + } + + return image; +} + + +void platformEventGet(EventT *event) { + SDL_Event e; + static uint8_t ASCII = 0; + static uint8_t debounce = 0; + static uint8_t buttons = 0; + static int16_t x = 0; + static int16_t y = 0; + + memset(event, 0, sizeof(EventT)); + + while (SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_MOUSEMOTION: + x = e.motion.x; + y = e.motion.y; + break; + + case SDL_MOUSEBUTTONUP: + if (e.button.button == SDL_BUTTON_LEFT) { + buttons &= ~BUTTON_LEFT; + event->flags |= EVENT_FLAG_LEFT_UP; + } + if (e.button.button == SDL_BUTTON_RIGHT) { + buttons &= ~BUTTON_RIGHT; + event->flags |= EVENT_FLAG_RIGHT_UP; + } + break; + + case SDL_MOUSEBUTTONDOWN: + if (e.button.button == SDL_BUTTON_LEFT) { + buttons |= BUTTON_LEFT; + event->flags |= EVENT_FLAG_LEFT_DOWN; + } + if (e.button.button == SDL_BUTTON_RIGHT) { + buttons |= BUTTON_RIGHT; + event->flags |= EVENT_FLAG_RIGHT_DOWN; + } + break; + + case SDL_TEXTINPUT: + ASCII = e.text.text[0]; //***TODO*** This is horrifically wrong. + break; + + case SDL_KEYUP: + ASCII = 0; + debounce = 0; + break; + + case SDL_KEYDOWN: + if (debounce == 0) { + if (e.key.keysym.scancode != 0) { + // Not a meta key + debounce = 1; + if (e.key.keysym.scancode == SDL_SCANCODE_ESCAPE) ASCII = 27; + event->key = ASCII; + } + } + break; + } + } + + event->x = x; + event->y = y; + event->buttons = buttons; + if ((SDL_GetModState() & KMOD_ALT) != 0) event->kbstat |= META_ALT; + if ((SDL_GetModState() & KMOD_CTRL) != 0) event->kbstat |= META_CTRL; + if ((SDL_GetModState() & KMOD_SHIFT) != 0) event->kbstat |= META_SHIFT; +} + + +void platformShutdown(void) { + + free(__guiBaseColors); + + SDL_StopTextInput(); + + if (_texture) { + SDL_DestroyTexture(_texture); + _texture = NULL; + } + + if (_renderer) { + SDL_DestroyRenderer(_renderer); + _renderer = NULL; + } + + if (_window) { + SDL_DestroyWindow(_window); + _window = NULL; + } + + IMG_Quit(); + SDL_Quit(); +} + + +void platformStartup(int16_t width, int16_t height, int16_t depth) { + uint8_t i; + uint8_t red; + uint8_t green; + uint8_t blue; + + (void)depth; + + SDL_Init(SDL_INIT_EVERYTHING); + IMG_Init(IMG_INIT_PNG); + + _windowScale = 3; + + _window = SDL_CreateWindow("GUI Debug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_ALLOW_HIGHDPI); + _surface = SDL_GetWindowSurface(_window); + _renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED); + _texture = SDL_CreateTexture(_renderer, _pixelFormat, SDL_TEXTUREACCESS_STREAMING, width, height); + + SDL_RenderSetLogicalSize(_renderer, width, height); + SDL_SetWindowSize(_window, width * _windowScale, height * _windowScale); + + _width = width; + _height = height; + + SDL_StartTextInput(); + + __guiBaseColors = (ColorT *)malloc(sizeof(ColorT) * 16); + for (i=0; i<16; i++) { + red = 85 * (((i >> 1) & 2) | ((i >> 5) & 1)); + green = 85 * (( i & 2) | ((i >> 4) & 1)); + blue = 85 * (((i << 1) & 2) | ((i >> 3) & 1)); + __guiBaseColors[i] = COLOR(red, green, blue); + } +} + + +uint16_t videoDisplayHeightGet(void) { + return _height; +} + + +uint16_t videoDisplayWidthGet(void) { + return _width; +} + + +void videoModesShow(void) { + // Nada +} + + +void videoSurfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source) { + uint16_t y1; + size_t offsetTarget; + size_t offsetSource; + void *pixels; + int temp; + + // HACK! Are we copying to the screen? This assumes a full screen update. + if (!target) { + SDL_LockTexture(_texture, NULL, &pixels, &temp); + memcpy(pixels, source->buffer.bits8, source->bytes); + SDL_UnlockTexture(_texture); + SDL_RenderCopy(_renderer, _texture, NULL, NULL); + SDL_RenderPresent(_renderer); + + // Throttle this to some sane frame rate. + SDL_Delay(32); + + return; + } + + if (targetX == 0 && targetY == 0 && target->width == source->width && target->height == source->height) { + // Direct blit of entire surface. + memcpy(target->buffer.bits8, source->buffer.bits8, source->bytes); + } else { + // Blit into larger surface. + offsetTarget = targetY * _activeSurface->scanline + targetX * BYTES_PER_PIXEL; + offsetSource = 0; + for (y1=targetY; y1height; y1++) { + memcpy(&target->buffer.bits8[offsetTarget], &source->buffer.bits8[offsetSource], source->scanline); + offsetTarget += target->scanline; + offsetSource += source->scanline; + } + } +} + + +void videoSurfaceBlitWithTransparency(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent) { + uint16_t x1; + uint16_t y1; + uint16_t x2 = source->width; + uint16_t y2 = source->height; + ColorT pixel; + + // Clip on right and bottom + if (targetX + x2 > target->width) x2 -= targetX + x2 - target->width; + if (targetY + y2 > target->height) y2 -= targetY + y2 - target->height; + + for (y1=0; y1buffer.bits32[y1 * source->width + x1]; + if (transparent != pixel) { + PUTPIXEL(target, targetX + x1, targetY + y1, pixel); + } + } + } + +} + + +void videoSurfaceClear(ColorT color) { + uint16_t x; + size_t offsetTarget; + + // Draw the top line. + for (x=0; x<_activeSurface->width; x++) { + PUTPIXEL(_activeSurface, x, 0, color); + } + + // Copy it to the other lines. + offsetTarget = _activeSurface->scanline; + for (x=1; x<_activeSurface->height; x++) { + memcpy(&_activeSurface->buffer.bits8[offsetTarget], &_activeSurface->buffer.bits8[0], _activeSurface->scanline); + offsetTarget += _activeSurface->scanline; + } +} + + +SurfaceT *videoSurfaceCreate(int16_t width, int16_t height) { + SurfaceT *surface = (SurfaceT *)malloc(sizeof(SurfaceT)); + + if (!surface) return NULL; + + surface->width = width; + surface->height = height; + surface->scanline = width * BYTES_PER_PIXEL; + surface->bytes = surface->scanline * height; + + surface->buffer.bits8 = malloc(surface->bytes); + if (!surface->buffer.bits8) { + free(surface); + return NULL; + } + + memset(surface->buffer.bits8, 0, surface->bytes); + + return surface; +} + + +void videoSurfaceDestroy(SurfaceT *surface) { + free(surface->buffer.bits8); + free(surface); +} + + +void videoSurfaceBox(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c) { + videoSurfaceLineH(x1, x2, y1, c); + videoSurfaceLineH(x1, x2, y2, c); + videoSurfaceLineV(x1, y1, y2, c); + videoSurfaceLineV(x2, y1, y2, c); +} + + +void videoSurfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c) { + uint16_t x; + size_t offsetTarget; + uint16_t width = x2 - x1; + + // Draw the top line. + for (x=x1; x<=x2; x++) { + PUTPIXEL(_activeSurface, x, 0, c); + } + + // Copy it to the other lines. + offsetTarget = _activeSurface->scanline; + for (x=y1; x<=y2; x++) { + memcpy(&_activeSurface->buffer.bits8[offsetTarget], &_activeSurface->buffer.bits8[0], width * BYTES_PER_PIXEL); + offsetTarget += _activeSurface->scanline; + } + +} + + +int16_t videoSurfaceHeightGet(SurfaceT *surface) { + return surface->height; +} + + +void videoSurfaceLineH(int16_t x1, int16_t x2, int16_t y, ColorT c) { + int16_t i; + int16_t t; + + if (x1 > x2) { + t = x2; + x2 = x1; + x1 = t; + } + + for (i=x1; i<=x2; i++) { + PUTPIXEL(_activeSurface, i, y, c); + } +} + + +void videoSurfaceLineV(int16_t x, int16_t y1, int16_t y2, ColorT c) { + int16_t i; + int16_t t; + + if (y1 > y2) { + t = y2; + y2 = y1; + y1 = t; + } + + for (i=y1; i<=y2; i++) { + PUTPIXEL(_activeSurface, x, i, c); + } +} + + +ColorT videoSurfacePixelGet(SurfaceT *surface, int16_t x, int16_t y) { + return surface->buffer.bits32[y * surface->width + x]; +} + + +void videoSurfacePixelSet(int16_t x, int16_t y, ColorT c) { + PUTPIXEL(_activeSurface, x, y, c); +} + + +void videoSurfaceSet(SurfaceT *surface) { + _activeSurface = surface; +} + + +SurfaceT *videoSurfaceScreenGet(void) { + return NULL; +} + + +int16_t videoSurfaceWidthGet(SurfaceT *surface) { + return surface->width; +} #endif // BACKEND_SDL2 diff --git a/client/src/platform/sdl2.h b/client/src/platform/sdl2.h index cd0c52b..9dc7ff1 100644 --- a/client/src/platform/sdl2.h +++ b/client/src/platform/sdl2.h @@ -1,4 +1,89 @@ #ifndef SDL2_H #define SDL2_H + +#include + +#include +#include + + +typedef uint32_t ColorT; + +typedef struct SurfaceS { + uint16_t width; + uint16_t height; + size_t scanline; + size_t bytes; + union { + uint8_t *bits8; + uint16_t *bits16; + uint32_t *bits32; + } buffer; +} SurfaceT; + +typedef struct EventS { + int32_t flags; + int32_t x; + int32_t y; + int32_t buttons; + int32_t key; + int32_t kbstat; + int32_t dtime; +} EventT; + +typedef struct FontS { + uint8_t width; // Width of each character in pixels. + uint8_t height; // Height of each character in pixels. + uint8_t span; // Number of characters per line in font data. + uint8_t count; // Number of characters in font, minus 1. + uint16_t widthPixels; // Width of line of font data in pixels/bits. + uint16_t heightPixels; // Number of lines of font data in pixels/bits. + uint8_t *bits; // Actual font bits. +} FontT; + + +#define EVENT_FLAG_KEYPRESS 1 +#define EVENT_FLAG_LEFT_DOWN 2 +#define EVENT_FLAG_LEFT_UP 4 +#define EVENT_FLAG_RIGHT_DOWN 8 +#define EVENT_FLAG_RIGHT_UP 16 + +#define BUTTON_LEFT 1 +#define BUTTON_RIGHT 2 + +#define META_ALT 1 +#define META_CTRL 2 +#define META_SHIFT 4 + +#define KEY_ESC 27 + +#define FONT_VGA_8x14 (*__font8x14) + + +extern FontT *__font8x14; + + +void fontWrite(char *message, int16_t x, int16_t y, FontT *font, ColorT foreground, ColorT background); +SurfaceT *imageLoad(char *filename); +void platformEventGet(EventT *event); +uint16_t videoDisplayHeightGet(void); +uint16_t videoDisplayWidthGet(void); +void videoSurfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source); +void videoSurfaceBlitWithTransparency(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent); +void videoSurfaceClear(ColorT color); +SurfaceT *videoSurfaceCreate(int16_t width, int16_t height); +void videoSurfaceDestroy(SurfaceT *surface); +void videoSurfaceBox(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c); +void videoSurfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT c); +int16_t videoSurfaceHeightGet(SurfaceT *surface); +void videoSurfaceLineH(int16_t x1, int16_t x2, int16_t y, ColorT c); +void videoSurfaceLineV(int16_t x, int16_t y1, int16_t y2, ColorT c); +ColorT videoSurfacePixelGet(SurfaceT *surface, int16_t x, int16_t y); +void videoSurfacePixelSet(int16_t x, int16_t y, ColorT c); +void videoSurfaceSet(SurfaceT *surface); +SurfaceT *videoSurfaceScreenGet(void); +int16_t videoSurfaceWidthGet(SurfaceT *surface); + + #endif // SDL2_H