From 2ea3cfe57be29401f02dffdec6e33c49de4529ba Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Fri, 27 May 2022 17:08:21 -0500 Subject: [PATCH] SDL and GRX back ends working. --- client/client.pro | 5 +- client/src/gui/color.h | 14 ++++ client/src/gui/font.c | 161 ++++++++++++++++++++++++++++++++++++ client/src/gui/font.h | 28 +++++++ client/src/gui/gui.c | 6 ++ client/src/gui/gui.h | 3 + client/src/gui/wmwindow.c | 4 +- client/src/main.c | 5 +- client/src/os.h | 1 - client/src/platform/djgpp.h | 12 +-- client/src/platform/grx.c | 17 ---- client/src/platform/grx.h | 5 -- client/src/platform/sdl2.c | 80 ++++++++++-------- client/src/platform/sdl2.h | 18 +--- 14 files changed, 270 insertions(+), 89 deletions(-) create mode 100644 client/src/gui/color.h create mode 100644 client/src/gui/font.c create mode 100644 client/src/gui/font.h diff --git a/client/client.pro b/client/client.pro index 7b53d5c..962e220 100644 --- a/client/client.pro +++ b/client/client.pro @@ -1,7 +1,7 @@ TEMPLATE = app CONFIG -= app_bundle CONFIG -= qt -CONFIG -= console +CONFIG += console CONFIG += c99 #CONFIG += BACKEND_GRX @@ -23,6 +23,8 @@ HEADERS += \ $$SHARED/stddclmr.h \ $$SHARED/thirdparty/memwatch/memwatch.h \ $$SHARED/thirdparty/stb_ds.h \ + src/gui/color.h \ + src/gui/font.h \ src/gui/gui.h \ src/gui/wmwindow.h \ src/os.h \ @@ -35,6 +37,7 @@ SOURCES += \ $$SHARED/array.c \ $$SHARED/memory.c \ $$SHARED/thirdparty/memwatch/memwatch.c \ + src/gui/font.c \ src/gui/gui.c \ src/gui/wmwindow.c \ src/main.c \ diff --git a/client/src/gui/color.h b/client/src/gui/color.h new file mode 100644 index 0000000..8e439bb --- /dev/null +++ b/client/src/gui/color.h @@ -0,0 +1,14 @@ +#ifndef COLOR_H +#define COLOR_H + + +#include + + +typedef uint32_t ColorT; + + +#define COLOR(r,g,b) (((r) << 24) | ((g) << 16) | ((b) << 8) | 255) + + +#endif // COLOR_H diff --git a/client/src/gui/font.c b/client/src/gui/font.c new file mode 100644 index 0000000..e6ebd1a --- /dev/null +++ b/client/src/gui/font.c @@ -0,0 +1,161 @@ +#include "font.h" +#include "platform/platform.h" + + +FontT *fontFromRAMLoad(uint8_t *pointer) { + FontT *font = NULL; + uint32_t size = 0; + + font = (FontT *)malloc(sizeof(FontT)); + if (!font) { + return NULL; + } + + font->width = pointer[0]; // Width of character in pixels + font->height = pointer[1]; // Height of character in pixels + font->span = pointer[2]; // Width of atlas in characters + font->count = pointer[3]; // Number of characters in atlas - 1 + + font->widthPixels = font->width * font->span; // Width of atlas in pixels + font->heightPixels = font->height * ((font->count + 1) / font->span); // Height of atlas in pixels + size = font->widthPixels * font->heightPixels / 8; // Bits required to store atlas + + font->bits = (uint8_t *)malloc(size); + if (!font->bits) { + DEL(font); + return NULL; + } + + memcpy(font->bits, &pointer[4], size); + + return font; +} + + +uint16_t fontHeightGet(FontT *font) { + return font->height; +} + + +FontT *fontLoad(char *filename) { + FILE *in = NULL; + size_t size = 0; + uint8_t *buffer = NULL; + FontT *font = NULL; + + in = fopen(filename, "rb"); + if (!in) return NULL; + + fseek(in, 0, SEEK_END); + size = ftell(in); + fseek(in, 0, SEEK_SET); + + buffer = (uint8_t *)malloc(size); + if (!buffer) { + fclose(in); + return NULL; + } + + fread(buffer, size, 1, in); + fclose(in); + + font = fontFromRAMLoad(buffer); + + DEL(buffer); + + return font; +} + + +void fontRender(FontT *font, char *string, ColorT foreground, ColorT background, uint16_t x, uint16_t y) { + uint8_t cx; + uint8_t cy; + uint16_t offset; + uint8_t yl; + uint16_t yp; + uint8_t data; + uint8_t character; + uint8_t c; + uint8_t odd; + + //***TODO*** This only handles 4xY and 8xY fonts. + + for (c=0; cspan; + cy = character / font->span; + + // Half byte or full byte font? + if (font->width == 4) { + // Half Byte. + + // Which half of the byte do we want? + odd = ((cx & 1) == 1); + + // Find offset byte based on font bits. + offset = cy * (font->span / 2) * font->height + cx * ((float)font->width / 8.0f); + + for (yl=0; ylheight; yl++) { + // We do 4 pixels unrolled hoping it's fast. + data = font->bits[offset]; + offset += (font->span / 2); + + if (odd) { + videoSurfacePixelSet(x, yp, (data & 0x08) ? foreground : background); + videoSurfacePixelSet(x + 1, yp, (data & 0x04) ? foreground : background); + videoSurfacePixelSet(x + 2, yp, (data & 0x02) ? foreground : background); + videoSurfacePixelSet(x + 3, yp, (data & 0x01) ? foreground : background); + } else { + videoSurfacePixelSet(x, yp, (data & 0x80) ? foreground : background); + videoSurfacePixelSet(x + 1, yp, (data & 0x40) ? foreground : background); + videoSurfacePixelSet(x + 2, yp, (data & 0x20) ? foreground : background); + videoSurfacePixelSet(x + 3, yp, (data & 0x10) ? foreground : background); + } + + yp++; + } + } else { + // Full Byte. + + // Find offset byte based on font bits. + offset = cy * font->span * font->height + cx; + + // Draw out 8 lines. + yp = y; + for (yl=0; ylheight; yl++) { + // We do 8 pixels unrolled hoping it's fast. + data = font->bits[offset]; + offset += font->span; + + videoSurfacePixelSet(x, yp, (data & 0x80) ? foreground : background); + videoSurfacePixelSet(x + 1, yp, (data & 0x40) ? foreground : background); + videoSurfacePixelSet(x + 2, yp, (data & 0x20) ? foreground : background); + videoSurfacePixelSet(x + 3, yp, (data & 0x10) ? foreground : background); + videoSurfacePixelSet(x + 4, yp, (data & 0x08) ? foreground : background); + videoSurfacePixelSet(x + 5, yp, (data & 0x04) ? foreground : background); + videoSurfacePixelSet(x + 6, yp, (data & 0x02) ? foreground : background); + videoSurfacePixelSet(x + 7, yp, (data & 0x01) ? foreground : background); + + yp++; + } + } + + x += font->width; + } +} + + +void fontUnload(FontT **font) { + FontT *f = *font; + + free(f->bits); + free(f); + f = NULL; +} + + +uint16_t fontWidthGet(FontT *font) { + return font->width; +} diff --git a/client/src/gui/font.h b/client/src/gui/font.h new file mode 100644 index 0000000..1cd6df5 --- /dev/null +++ b/client/src/gui/font.h @@ -0,0 +1,28 @@ +#ifndef FONT_H +#define FONT_H + + +#include "os.h" +#include "color.h" + + +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; + + +FontT *fontFromRAMLoad(uint8_t *pointer); +uint16_t fontHeightGet(FontT *font); +FontT *fontLoad(char *filename); +void fontRender(FontT *font, char *string, ColorT foreground, ColorT background, uint16_t x, uint16_t y); +void fontUnload(FontT **font); +uint16_t fontWidthGet(FontT *font); + + +#endif // FONT_H diff --git a/client/src/gui/gui.c b/client/src/gui/gui.c index e297b47..9685abe 100644 --- a/client/src/gui/gui.c +++ b/client/src/gui/gui.c @@ -1,4 +1,5 @@ #include "gui.h" +#include "font.h" #include "wmwindow.h" #include "array.h" @@ -12,6 +13,7 @@ typedef struct WidgetCatalogS { ColorT *__guiBaseColors = NULL; SurfaceT *__guiBackBuffer = NULL; SurfaceT *__guiScreenBuffer = NULL; +FontT *__guiFontVGA8x14 = NULL; static uint8_t _magicCount = 0; @@ -63,6 +65,8 @@ void guiShutdown(void) { wmShutdown(); + fontUnload(&__guiFontVGA8x14); + videoSurfaceDestroy(_mousePointer); videoSurfaceDestroy(__guiBackBuffer); @@ -80,6 +84,8 @@ void guiStartup(int16_t width, int16_t height, int16_t depth) { _mousePointer = imageLoad("mouse.png"); _mouseTransparency = videoSurfacePixelGet(_mousePointer, videoSurfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color. + __guiFontVGA8x14 = fontLoad("vga8x14.dat"); + wmStartup(); guiRegister(windowRegister); diff --git a/client/src/gui/gui.h b/client/src/gui/gui.h index 6c56dd7..214cd04 100644 --- a/client/src/gui/gui.h +++ b/client/src/gui/gui.h @@ -3,6 +3,8 @@ #include "os.h" +#include "platform/platform.h" +#include "font.h" struct WidgetS; @@ -47,6 +49,7 @@ typedef RegisterT *(*WidgetRegisterT)(uint8_t); extern SurfaceT *__guiBackBuffer; extern SurfaceT *__guiScreenBuffer; extern ColorT *__guiBaseColors; +extern FontT *__guiFontVGA8x14; #define GUI_BLACK __guiBaseColors[0] diff --git a/client/src/gui/wmwindow.c b/client/src/gui/wmwindow.c index 8fb24df..b565f5f 100644 --- a/client/src/gui/wmwindow.c +++ b/client/src/gui/wmwindow.c @@ -1,5 +1,6 @@ #include "wmwindow.h" #include "array.h" +#include "font.h" uint8_t __MAGIC_WINDOW = 0; @@ -147,8 +148,7 @@ void windowPaint(struct WidgetS *widget, ...) { if (w->title) { ty1 = w->titlebar.y + 2; tx1 = w->titlebar.x + 2 + (w->titlebar.x2 - w->titlebar.x - 4) * 0.5 - ((strlen(w->title) * 8) * 0.5); - //***TODO*** Does not handle text being clipped. - fontWrite(w->title, tx1, ty1, &FONT_VGA_8x14, GUI_WHITE, titleBackgroundColor); + fontRender(__guiFontVGA8x14, w->title, GUI_WHITE, titleBackgroundColor, tx1, ty1); } } diff --git a/client/src/main.c b/client/src/main.c index ca95020..b593cd9 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -11,10 +11,11 @@ int main(int argc, char *argv[]) { guiStartup(800, 600, 24); - for (i=1; i<4; i++) { + i = 1; + //for (i=1; i<4; i++) { sprintf(title, "Testing %d", i); windowCreate(i * 50, i * 50, 300, 200, title, WIN_CLOSE | WIN_MAXIMIZE | WIN_MINIMIZE | WIN_RESIZE); - } + //} guiRun(); diff --git a/client/src/os.h b/client/src/os.h index a727bb5..8d8b3ee 100644 --- a/client/src/os.h +++ b/client/src/os.h @@ -11,7 +11,6 @@ #include "macros.h" #include "memory.h" -#include "platform/platform.h" #include "stddclmr.h" diff --git a/client/src/platform/djgpp.h b/client/src/platform/djgpp.h index ebcb750..937ead3 100644 --- a/client/src/platform/djgpp.h +++ b/client/src/platform/djgpp.h @@ -5,6 +5,8 @@ #include #include +#include "gui/font.h" + typedef uint32_t ColorT; @@ -30,16 +32,6 @@ typedef struct EventS { 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 diff --git a/client/src/platform/grx.c b/client/src/platform/grx.c index 936366f..0a54851 100644 --- a/client/src/platform/grx.c +++ b/client/src/platform/grx.c @@ -18,23 +18,6 @@ typedef struct VideoModeS { extern struct _GR_mouseInfo _GrMouseInfo; -void fontWrite(char *message, int16_t x, int16_t y, FontT *font, ColorT foreground, ColorT background) { - - GrTextOption textOption; - - textOption.txo_bgcolor.v = background; - textOption.txo_fgcolor.v = foreground; - textOption.txo_chrtype = GR_BYTE_TEXT; - textOption.txo_direct = GR_TEXT_RIGHT; - textOption.txo_font = font; - textOption.txo_xalign = GR_ALIGN_DEFAULT; - textOption.txo_yalign = GR_ALIGN_DEFAULT; - - //***TODO*** Look into GrTextRegion - GrDrawString(message, strlen(message), x, y, &textOption); -} - - SurfaceT *imageLoad(char *filename) { int32_t x; int32_t y; diff --git a/client/src/platform/grx.h b/client/src/platform/grx.h index d2e29c9..32ec655 100644 --- a/client/src/platform/grx.h +++ b/client/src/platform/grx.h @@ -11,7 +11,6 @@ typedef GrColor ColorT; typedef GrContext SurfaceT; typedef GrMouseEvent EventT; -typedef GrFont FontT; #define EVENT_FLAG_KEYPRESS GR_M_KEYPRESS @@ -29,8 +28,6 @@ typedef GrFont FontT; #define KEY_ESC GrKey_Escape -#define FONT_VGA_8x14 GrFont_PC8x14 - #define platformEventGet(p) GrMouseGetEventT(GR_M_EVENT, p, 0) @@ -49,8 +46,6 @@ typedef GrFont FontT; #define videoSurfaceScreenGet GrScreenContext -void fontWrite(char *message, int16_t x, int16_t y, FontT *font, ColorT foreground, ColorT background); - SurfaceT *imageLoad(char *filename); void videoSurfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source); diff --git a/client/src/platform/sdl2.c b/client/src/platform/sdl2.c index f2715e8..be8a739 100644 --- a/client/src/platform/sdl2.c +++ b/client/src/platform/sdl2.c @@ -7,9 +7,6 @@ #define BYTES_PER_PIXEL 4 -FontT *__font8x14 = NULL; - - static SDL_Window *_window = NULL; static SDL_Renderer *_renderer = NULL; static SDL_Surface *_surface = NULL; @@ -24,13 +21,7 @@ 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) { - -} +#define PUTPIXEL(s,x,y,c) s->buffer.bits32[(y) * s->width + (x)] = (c) SurfaceT *imageLoad(char *filename) { @@ -95,10 +86,6 @@ void platformEventGet(EventT *event) { } break; - case SDL_TEXTINPUT: - ASCII = e.text.text[0]; //***TODO*** This is horrifically wrong. - break; - case SDL_KEYUP: ASCII = 0; debounce = 0; @@ -109,8 +96,10 @@ void platformEventGet(EventT *event) { if (e.key.keysym.scancode != 0) { // Not a meta key debounce = 1; - if (e.key.keysym.scancode == SDL_SCANCODE_ESCAPE) ASCII = 27; + ASCII = e.key.keysym.sym; + //if (e.key.keysym.scancode == SDL_SCANCODE_ESCAPE) ASCII = 27; event->key = ASCII; + event->flags |= EVENT_FLAG_KEYPRESS; } } break; @@ -130,8 +119,6 @@ void platformShutdown(void) { free(__guiBaseColors); - SDL_StopTextInput(); - if (_texture) { SDL_DestroyTexture(_texture); _texture = NULL; @@ -154,9 +141,24 @@ void platformShutdown(void) { void platformStartup(int16_t width, int16_t height, int16_t depth) { uint8_t i; - uint8_t red; - uint8_t green; - uint8_t blue; + uint8_t EGA[16][3] = { + { 0, 0, 0 }, /* black */ + { 0, 0, 170 }, /* blue */ + { 0, 170, 0 }, /* green */ + { 0, 170, 170 }, /* cyan */ + { 170, 0, 0 }, /* red */ + { 170, 0, 170 }, /* magenta */ + { 170, 85, 0 }, /* brown */ + { 170, 170, 170 }, /* light gray */ + { 85, 85, 85 }, /* dark gray */ + { 85, 85, 255 }, /* light blue */ + { 85, 255, 85 }, /* light green */ + { 85, 255, 255 }, /* light cyan */ + { 255, 85, 85 }, /* light red */ + { 255, 85, 255 }, /* light magenta */ + { 255, 255, 85 }, /* yellow */ + { 255, 255, 255 } /* white */ + }; (void)depth; @@ -176,14 +178,9 @@ void platformStartup(int16_t width, int16_t height, int16_t depth) { _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); + __guiBaseColors[i] = COLOR(EGA[i][0], EGA[i][1], EGA[i][2]); } } @@ -318,22 +315,37 @@ 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) { - uint16_t x; + int16_t i; size_t offsetTarget; - uint16_t width = x2 - x1; + size_t offsetSource; + uint16_t width; + + if (x1 > x2) { + i = x1; + x1 = x2; + x2 = i; + } + + if (y1 > y2) { + i = y1; + y1 = y2; + y2 = i; + } + + width = (x2 - x1 + 1) * BYTES_PER_PIXEL; // Draw the top line. - for (x=x1; x<=x2; x++) { - PUTPIXEL(_activeSurface, x, 0, c); + for (i=x1; i<=x2; i++) { + PUTPIXEL(_activeSurface, i, y1, 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 * (y1 + 1) + (x1 * BYTES_PER_PIXEL); + offsetSource = _activeSurface->scanline * y1+ (x1 * BYTES_PER_PIXEL); + for (i=y1 + 1; i<=y2; i++) { + memcpy(&_activeSurface->buffer.bits8[offsetTarget], &_activeSurface->buffer.bits8[offsetSource], width); offsetTarget += _activeSurface->scanline; } - } diff --git a/client/src/platform/sdl2.h b/client/src/platform/sdl2.h index 9dc7ff1..f433b7c 100644 --- a/client/src/platform/sdl2.h +++ b/client/src/platform/sdl2.h @@ -7,8 +7,8 @@ #include #include +#include "gui/color.h" -typedef uint32_t ColorT; typedef struct SurfaceS { uint16_t width; @@ -32,16 +32,6 @@ typedef struct EventS { 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 @@ -58,13 +48,7 @@ typedef struct FontS { #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);