yterm

commit 1ecc26dc058bf273d0b594489333eade04f93217

Author: mesyeti <mesyeti@mesyeti.uk>

software backend working

 source/backend.c | 4 ++
 source/backend.h | 4 ++
 source/backends/glLegacy.c | 6 +++
 source/backends/soft.c | 65 +++++++++++++++++++++++++++++++++------
 source/backends/stub.c | 6 +++
 source/buffer.c | 16 +++++++++
 source/buffer.h | 2 +
 source/screen.c | 2 +


diff --git a/source/backend.c b/source/backend.c
index 76f3f9d00ff9be9198b0eff97fff14e628709d0c..8032163580e267eb658649cc6ffff739cd683faf 100644
--- a/source/backend.c
+++ b/source/backend.c
@@ -30,6 +30,10 @@ void Backend_OnWindowResize(void) {
 	backend.onWindowResize();
 }
 
+void Backend_OnScreenUpdate(void) {
+	backend.onScreenUpdate();
+}
+
 void Backend_Render(void) {
 	backend.render();
 }




diff --git a/source/backend.h b/source/backend.h
index fc69e3fce90219a92a5c6be18ab26ae3d6193460..24f308eb6f688dd333512fcf97389b06491373af 100644
--- a/source/backend.h
+++ b/source/backend.h
@@ -18,12 +18,15 @@
 typedef void Texture;
 
 typedef struct {
+	const char* name;
+
 	void     (*init)(bool beforeWindow);
 	void     (*free)(void);
 	Texture* (*loadTexture)(uint8_t* data, int w, int h, int aW, int aH, int ch);
 	void     (*freeTexture)(Texture* texture);
 	Vec2     (*getTextureSize)(Texture* texture);
 	void     (*onWindowResize)(void);
+	void     (*onScreenUpdate)(void);
 	void     (*render)(void);
 } Backend;
 
@@ -34,6 +37,7 @@ Texture* Backend_LoadTexture(uint8_t* data, int w, int h, int aW, int aH, int ch);
 void     Backend_FreeTexture(Texture* texture);
 Vec2     Backend_GetTextureSize(Texture* texture);
 void     Backend_OnWindowResize(void);
+void     Backend_OnScreenUpdate(void);
 void     Backend_Render(void);
 
 #endif




diff --git a/source/backends/glLegacy.c b/source/backends/glLegacy.c
index 67ccb46c3fefa8f4b716368a9a19a98a37d4cbbc..fbe2fa44f816f7d9bf023818d9bd738ae61bc24b 100644
--- a/source/backends/glLegacy.c
+++ b/source/backends/glLegacy.c
@@ -223,18 +223,24 @@ static void OnWindowResize(void) {
 	
 }
 
+static void OnScreenUpdate(void) {
+	
+}
+
 static void Render(void) {
 	
 }
 
 Backend Backend_GLLegacy(void) {
 	return (Backend) {
+		.name           = "gl 1.1",
 		.init           = &Init,
 		.free           = &Free,
 		.loadTexture    = &LoadTexture,
 		.freeTexture    = &FreeTexture,
 		.getTextureSize = &GetTextureSize,
 		.onWindowResize = &OnWindowResize,
+		.onScreenUpdate = &OnScreenUpdate,
 		.render         = &Render
 	};
 }




diff --git a/source/backends/soft.c b/source/backends/soft.c
index bb7573138c565991bc5596f62c30381e6ea07ab2..d86549c1fbdd90362ceb6b42cd455f76f6f87f22 100644
--- a/source/backends/soft.c
+++ b/source/backends/soft.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <assert.h>
 #include "../log.h"
 #include "../mem.h"
 #include "../font.h"
@@ -22,6 +23,8 @@ 	BTexture  textures[32];
 	uint32_t* buffer;
 	int       bufferW;
 	int       bufferH;
+	bool*     changes;
+	bool      redraw;
 
 	// SDL stuff
 	SDL_Renderer* renderer;
@@ -30,12 +33,27 @@ } State;
 
 static State state;
 
+static uint32_t ColourToPixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
+	return r | (g << 8) | (b << 16) | (a << 24);
+	//return r + (rand() % 20) | (g + (rand() % 20) << 8) | (b + (rand() % 20) << 16) | (a << 24);
+}
+
 static void DrawPixel(int x, int y, uint32_t colour) {
 	if ((x < 0) || (y < 0) || (y >= state.bufferH) || (x >= state.bufferW)) return;
 
 	state.buffer[(y * state.bufferW) + x] = colour;
 }
 
+static uint8_t Component(uint32_t colour, uint8_t comp) {
+	switch (comp) {
+		case 0:  return  colour & 0x000000FF;        // red
+		case 1:  return (colour & 0x0000FF00) >> 8;  // green
+		case 2:  return (colour & 0x00FF0000) >> 16; // blue
+		case 3:  return (colour & 0xFF000000) >> 24; // alpha
+		default: assert(0);
+	}
+}
+
 static void Init(bool beforeWindow) {
 	if (beforeWindow) return;
 
@@ -64,6 +82,8 @@
 	state.buffer  = SafeMalloc(video.windows[0].width * video.windows[0].height * sizeof(uint32_t));
 	state.bufferW = video.windows[0].width;
 	state.bufferH = video.windows[0].height;
+
+	state.changes = NULL;
 }
 
 static void Free(void) {
@@ -77,11 +97,6 @@ 	free(state.buffer);
 
 	SDL_DestroyTexture(state.texture);
 	SDL_DestroyRenderer(state.renderer);
-}
-
-static uint32_t ColourToPixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
-	return r | (g << 8) | (b << 16) | (a << 24);
-	//return r + (rand() % 20) | (g + (rand() % 20) << 8) | (b + (rand() % 20) << 16) | (a << 24);
 }
 
 static Texture* LoadTexture(uint8_t* data, int w, int h, int aW, int aH, int ch) {
@@ -122,6 +137,18 @@ static void OnWindowResize(void) {
 	
 }
 
+static void OnScreenUpdate(void) {
+	if (!state.changes) {
+		free(state.changes);
+	}
+
+	size_t size = screen.buffer.width * screen.buffer.height * sizeof(bool);
+	state.changes = SafeMalloc(size);
+	memset(state.changes, 0, size);
+
+	state.redraw = true;
+}
+
 static void FillRect(int x, int y, int w, int h, Colour colour) {
 	for (int iy = 0; iy < h; ++ iy) {
 		for (int ix = 0; ix < w; ++ ix) {
@@ -140,15 +167,21 @@
 			int sx = ix + src.x;
 			int sy = iy + src.y;
 
-			// DrawPixel(ix + x, iy + y, texture->pixels[(sy * texture->width) + sx]);
-			DrawPixel(ix + x, iy + y, texture->pixels[(sy * texture->width) + sx]);
+			uint32_t srcPix = texture->pixels[(sy * texture->aWidth) + sx];
+			uint8_t  alpha  = Component(srcPix, 3);
+
+			if (alpha == 0) continue;
+
+			DrawPixel(ix + x, iy + y, srcPix);
 		}
 	}
 }
 
 static void Render(void) {
-	for (int i = 0; i < state.bufferW * state.bufferH; ++ i) {
-		state.buffer[i] = ColourToPixel(theme.bg.r, theme.bg.g, theme.bg.b, 255);
+	if (state.redraw) {
+		for (int i = 0; i < state.bufferW * state.bufferH; ++ i) {
+			state.buffer[i] = ColourToPixel(theme.bg.r, theme.bg.g, theme.bg.b, 255);
+		}
 	}
 
 	int cw;
@@ -157,6 +190,10 @@ 	Font_CharSize(&screen.font, &cw, &ch);
 
 	for (int y = 0; y < screen.buffer.height; ++ y) {
 		for (int x = 0; x < screen.buffer.width; ++ x) {
+			if (!state.changes[(y * screen.buffer.width) + x] && !state.redraw) continue;
+
+			state.changes[(y * screen.buffer.width) + x] = false;
+
 			int cx = x * cw;
 			int cy = y * ch;
 
@@ -166,10 +203,12 @@ 			ColourRGB fg = Screen_GetColour(true,  cell->fgMode, cell->fg);
 			ColourRGB bg = Screen_GetColour(false, cell->bgMode, cell->bg);
 
 			FillRect(cx, cy, cw, ch, (Colour) {bg.r, bg.g, bg.b, 255});
+
+			if ((cell->ch == ' ') || (cell->ch == 0)) continue;
 
 			Rect src;
-			src.x = ((int) (ch % 16)) * cw;
-			src.y = ((int) (ch / 16)) * ch;
+			src.x = ((int) (cell->ch % 16)) * cw;
+			src.y = ((int) (cell->ch / 16)) * ch;
 			src.w = cw;
 			src.h = ch;
 
@@ -177,6 +216,8 @@ 			Blit((BTexture*) screen.font.v.bm.texture, cx, cy, src, (Colour) {fg.r, fg.g, fg.b, 255});
 		}
 	}
 
+	state.redraw = false;
+
 	SDL_RenderClear(state.renderer);
 	SDL_UpdateTexture(state.texture, NULL, state.buffer, state.bufferW * 4);
 	SDL_RenderCopy(state.renderer, state.texture, NULL, NULL);
@@ -185,12 +226,14 @@ }
 
 Backend Backend_Soft(void) {
 	return (Backend) {
+		.name           = "soft",
 		.init           = &Init,
 		.free           = &Free,
 		.loadTexture    = &LoadTexture,
 		.freeTexture    = &FreeTexture,
 		.getTextureSize = &GetTextureSize,
 		.onWindowResize = &OnWindowResize,
+		.onScreenUpdate = &OnScreenUpdate,
 		.render         = &Render
 	};
 }




diff --git a/source/backends/stub.c b/source/backends/stub.c
index 6d7dfe19e8f2b7b5174ed71d944f0d5eec673443..c8d879b1779adaf28cd4bcda1032f4f7c126fd54 100644
--- a/source/backends/stub.c
+++ b/source/backends/stub.c
@@ -33,18 +33,24 @@ static void OnWindowResize(void) {
 	
 }
 
+static void OnScreenUpdate(void) {
+	
+}
+
 static void Render(void) {
 	
 }
 
 Backend Backend_Stub(void) {
 	return (Backend) {
+		.name           = "stub",
 		.init           = &Init,
 		.free           = &Free,
 		.loadTexture    = &LoadTexture,
 		.freeTexture    = &FreeTexture,
 		.getTextureSize = &GetTextureSize,
 		.onWindowResize = &OnWindowResize,
+		.onScreenUpdate = &OnScreenUpdate,
 		.render         = &Render
 	};
 }




diff --git a/source/buffer.c b/source/buffer.c
index 1fc8b68cc668162f9601bf50683997a6bad6d475..c6c1619e38bc0833c636f912368ce6735eec1caf 100644
--- a/source/buffer.c
+++ b/source/buffer.c
@@ -16,7 +16,7 @@ 	Buffer ret;
 	ret.buf = SafeMalloc(width * height * sizeof(BufCell));
 
 	for (int i = 0; i < width * height; ++ i) {
-		ret.buf[i] = FromChar('a');
+		ret.buf[i] = FromChar(0);
 	}
 
 	ret.width  = width;
@@ -39,3 +39,17 @@ 	if ((x < 0) || (y < 0) || (x >= buf->width) || (y >= buf->height)) return NULL;
 
 	return &buf->buf[(y * buf->width) + x];
 }
+
+void Buffer_Blit(Buffer* dest, Buffer* src, int x, int y, Rect clip) {
+	for (int iy = 0; iy < clip.h; ++ iy) {
+		for (int ix = 0; ix < clip.w; ++ ix) {
+			if ((clip.x + ix >= src->width) || (clip.y + iy >= src->height)) continue;
+
+			int sx = ix + clip.x;
+			int sy = iy + clip.y;
+
+			BufCell* cell = Buffer_Get(src, sx, sy);
+			*Buffer_Get(dest, x + ix, y + iy) = *cell;
+		}
+	}
+}




diff --git a/source/buffer.h b/source/buffer.h
index 6ef2d01260d3b857d75017dbfd9e00d19bb1b2e7..7ae1a1806cc0970c593c5c536a19d8d3b07a29c4 100644
--- a/source/buffer.h
+++ b/source/buffer.h
@@ -2,6 +2,7 @@ #ifndef YT_BUFFER_H
 #define YT_BUFFER_H
 
 #include "char.h"
+#include "types.h"
 #include "video.h"
 
 enum {
@@ -34,5 +35,6 @@ Buffer   Buffer_New(int width, int height);
 void     Buffer_Free(Buffer* buf);
 void     Buffer_WriteChar(Buffer* buf, UChar ch, int x, int y);
 BufCell* Buffer_Get(Buffer* buf, int x, int y);
+void     Buffer_Blit(Buffer* dest, Buffer* src, int x, int y, Rect clip);
 
 #endif




diff --git a/source/screen.c b/source/screen.c
index 91ff0e30648f3712ead9f7bf7521dd38c23617a7..271ac94133b21efb3794d6b992d1b265c83a392f 100644
--- a/source/screen.c
+++ b/source/screen.c
@@ -25,6 +25,8 @@ 	int ch;
 	Font_CharSize(&screen.font, &cw, &ch);
 
 	screen.buffer = Buffer_New(video.windows[0].width / cw, video.windows[0].height / ch);
+
+	Backend_OnScreenUpdate();
 }
 
 void Screen_Free(void) {