shithub: cstory

Download patch

ref: 21cf78b86d1025081e59d3edffc59a8ef5b18148
parent: 3ef9b67b1d9ee27137d51494ee63460e89ec45fb
author: Clownacy <Clownacy@users.noreply.github.com>
date: Mon Jul 15 09:41:19 EDT 2019

Split Draw.cpp into common code and backend code

Should be easy to add the new hardware renderer now

diff: cannot open b/src/Backends//null: file does not exist: 'b/src/Backends//null'
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -155,6 +155,8 @@
 	src/ValueView.cpp
 	src/ValueView.h
 	src/WindowsWrapper.h
+	src/Backends/SDLSoftware.cpp
+	src/Backends/Rendering.h
 )
 
 set(RESOURCES
--- /dev/null
+++ b/src/Backends/Rendering.h
@@ -1,0 +1,23 @@
+#pragma once
+
+#include "SDL.h"
+
+#include "../WindowsWrapper.h"
+
+#include "../Font.h"
+
+struct Backend_Surface;
+
+BOOL Backend_Init(SDL_Window *window);
+void Backend_Deinit(void);
+void Backend_DrawScreen(void);
+Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height);
+void Backend_FreeSurface(Backend_Surface *surface);
+void Backend_LoadPixels(Backend_Surface *surface, const unsigned char *pixels, unsigned int width, unsigned int height, unsigned int pitch);
+void Backend_Blit(const Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key);
+void Backend_BlitToScreen(const Backend_Surface *source_surface, const RECT *rect, long x, long y, BOOL colour_key);
+void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue);
+void Backend_ColourFillToScreen(const RECT *rect, unsigned char red, unsigned char green, unsigned char blue);
+void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect);
+void Backend_DrawText(Backend_Surface *surface, FontObject *font, int x, int y, const char *text, unsigned long colour);
+void Backend_DrawTextToScreen(FontObject *font, int x, int y, const char *text, unsigned long colour);
--- /dev/null
+++ b/src/Backends/SDLSoftware.cpp
@@ -1,0 +1,239 @@
+#include "Rendering.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "SDL.h"
+
+#include "../WindowsWrapper.h"
+
+#include "../Font.h"
+
+struct Backend_Surface
+{
+	unsigned char *pixels;
+	unsigned int width;
+	unsigned int height;
+	unsigned int pitch;
+};
+
+static SDL_Window *window;
+static SDL_Surface *window_surface;
+static SDL_Surface *screen_surface;
+
+static Backend_Surface framebuffer;
+
+BOOL Backend_Init(SDL_Window *p_window)
+{
+	window = p_window;
+
+	window_surface = SDL_GetWindowSurface(window);
+
+	screen_surface = SDL_CreateRGBSurfaceWithFormat(0, window_surface->w, window_surface->h, 0, SDL_PIXELFORMAT_RGB24);
+
+	if (screen_surface == NULL)
+		return FALSE;
+
+	framebuffer.pixels = (unsigned char*)screen_surface->pixels;
+	framebuffer.width = screen_surface->w;
+	framebuffer.height = screen_surface->h;
+	framebuffer.pitch = screen_surface->pitch;
+
+	return TRUE;
+}
+
+void Backend_Deinit(void)
+{
+	SDL_FreeSurface(screen_surface);
+}
+
+void Backend_DrawScreen(void)
+{
+	SDL_BlitSurface(screen_surface, NULL, window_surface, NULL);
+	SDL_UpdateWindowSurface(window);
+}
+
+Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height)
+{
+	Backend_Surface *surface = (Backend_Surface*)malloc(sizeof(Backend_Surface));
+
+	if (surface == NULL)
+		return NULL;
+
+	surface->pixels = (unsigned char*)malloc(width * height * 3);
+
+	if (surface->pixels == NULL)
+	{
+		free(surface);
+		return NULL;
+	}
+
+	surface->width = width;
+	surface->height = height;
+	surface->pitch = width * 3;
+
+	return surface;
+}
+
+void Backend_FreeSurface(Backend_Surface *surface)
+{
+	free(surface->pixels);
+}
+
+void Backend_LoadPixels(Backend_Surface *surface, const unsigned char *pixels, unsigned int width, unsigned int height, unsigned int pitch)
+{
+	for (unsigned int h = 0; h < height; ++h)
+	{
+		const unsigned char *src_row = &pixels[h * pitch];
+		unsigned char *dst_row = &surface->pixels[h * surface->pitch];
+
+		memcpy(dst_row, src_row, width * 3);
+	}
+}
+
+void Backend_Blit(const Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
+{
+	RECT rect_clamped;
+
+	rect_clamped.left = rect->left;
+	rect_clamped.top = rect->top;
+	rect_clamped.right = rect->right;
+	rect_clamped.bottom = rect->bottom;
+
+	// Clamp the rect and coordinates so we don't write outside the pixel buffer
+	long overflow;
+
+	overflow = 0 - x;
+	if (overflow > 0)
+	{
+		rect_clamped.left += overflow;
+		x += overflow;
+	}
+
+	overflow = 0 - y;
+	if (overflow > 0)
+	{
+		rect_clamped.top += overflow;
+		y += overflow;
+	}
+
+	overflow = (x + (rect_clamped.right - rect_clamped.left)) - destination_surface->width;
+	if (overflow > 0)
+	{
+		rect_clamped.right -= overflow;
+	}
+
+	overflow = (y + (rect_clamped.bottom - rect_clamped.top)) - destination_surface->height;
+	if (overflow > 0)
+	{
+		rect_clamped.bottom -= overflow;
+	}
+
+	// Do the actual blitting
+	if (colour_key)
+	{
+		for (long j = 0; j < rect_clamped.bottom - rect_clamped.top; ++j)
+		{
+			unsigned char *source_pointer = &source_surface->pixels[((rect_clamped.top + j) * source_surface->pitch) + (rect_clamped.left * 3)];
+			unsigned char *destination_pointer = &destination_surface->pixels[((y + j) * destination_surface->pitch) + (x * 3)];
+
+			for (long i = 0; i < rect_clamped.right - rect_clamped.left; ++i)
+			{
+				if (source_pointer[0] != 0 || source_pointer[1] != 0 || source_pointer[2] != 0)	// Assumes the colour key will always be #00000000 (black)
+				{
+					destination_pointer[0] = source_pointer[0];
+					destination_pointer[1] = source_pointer[1];
+					destination_pointer[2] = source_pointer[2];
+				}
+
+				source_pointer += 3;
+				destination_pointer += 3;
+			}
+		}
+	}
+	else
+	{
+		for (long j = 0; j < rect_clamped.bottom - rect_clamped.top; ++j)
+		{
+			unsigned char *source_pointer = &source_surface->pixels[((rect_clamped.top + j) * source_surface->pitch) + (rect_clamped.left * 3)];
+			unsigned char *destination_pointer = &destination_surface->pixels[((y + j) * destination_surface->pitch) + (x * 3)];
+
+			memcpy(destination_pointer, source_pointer, (rect_clamped.right - rect_clamped.left) * 3);
+		}
+	}
+}
+
+void Backend_BlitToScreen(const Backend_Surface *source_surface, const RECT *rect, long x, long y, BOOL colour_key)
+{
+	Backend_Blit(source_surface, rect, &framebuffer, x, y, colour_key);
+}
+
+void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
+{
+	RECT rect_clamped;
+
+	rect_clamped.left = rect->left;
+	rect_clamped.top = rect->top;
+	rect_clamped.right = rect->right;
+	rect_clamped.bottom = rect->bottom;
+
+	// Clamp the rect so it doesn't write outside the pixel buffer
+	long overflow;
+
+	overflow = 0 - rect_clamped.left;
+	if (overflow > 0)
+	{
+		rect_clamped.left += overflow;
+	}
+
+	overflow = 0 - rect_clamped.top;
+	if (overflow > 0)
+	{
+		rect_clamped.top += overflow;
+	}
+
+	overflow = rect_clamped.right - surface->width;
+	if (overflow > 0)
+	{
+		rect_clamped.right -= overflow;
+	}
+
+	overflow = rect_clamped.bottom - surface->height;
+	if (overflow > 0)
+	{
+		rect_clamped.bottom -= overflow;
+	}
+
+	for (long j = 0; j < rect_clamped.bottom - rect_clamped.top; ++j)
+	{
+		unsigned char *source_pointer = &surface->pixels[((rect_clamped.top + j) * surface->pitch) + (rect_clamped.left * 3)];
+
+		for (long i = 0; i < rect_clamped.right - rect_clamped.left; ++i)
+		{
+			*source_pointer++ = red;
+			*source_pointer++ = green;
+			*source_pointer++ = blue;
+		}
+	}
+}
+
+void Backend_ColourFillToScreen(const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
+{
+	Backend_ColourFill(&framebuffer, rect, red, green, blue);
+}
+
+void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect)
+{
+	Backend_Blit(&framebuffer, rect, surface, rect->left, rect->top, FALSE);
+}
+
+void Backend_DrawText(Backend_Surface *surface, FontObject *font, int x, int y, const char *text, unsigned long colour)
+{
+	DrawText(font, surface->pixels, surface->pitch, surface->width, surface->height, x, y, colour, text, strlen(text));
+	//surf[surf_no].needs_updating = TRUE;
+}
+
+void Backend_DrawTextToScreen(FontObject *font, int x, int y, const char *text, unsigned long colour)
+{
+	Backend_DrawText(&framebuffer, font, x, y, text, colour);
+}
--- a/src/Draw.cpp
+++ b/src/Draw.cpp
@@ -14,21 +14,17 @@
 #include "Font.h"
 #include "Resource.h"
 #include "Tags.h"
+#include "Backends/Rendering.h"
 
 struct SURFACE
 {
 	BOOL in_use;
-	unsigned char *pixels;
-	unsigned int width;
-	unsigned int height;
-	unsigned int pitch;
+	Backend_Surface *backend;
 };
 
 SDL_Window *gWindow;
-static SDL_Surface *gWindowSurface;
-static SDL_Surface *gSurface;
 
-static SURFACE framebuffer;
+static SDL_PixelFormat *rgb24_pixel_format;	// Needed because SDL2 is stupid
 
 RECT grcGame = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
 RECT grcFull = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
@@ -68,8 +64,7 @@
 		SDL_Delay(1);
 	}
 
-	SDL_BlitSurface(gSurface, NULL, gWindowSurface, NULL);
-	SDL_UpdateWindowSurface(gWindow);
+	Backend_DrawScreen();
 
 	return TRUE;
 }
@@ -98,18 +93,10 @@
 	}
 
 	// Create renderer
-	gWindowSurface = SDL_GetWindowSurface(gWindow);
-
-	gSurface = SDL_CreateRGBSurfaceWithFormat(0, WINDOW_WIDTH * magnification, WINDOW_HEIGHT * magnification, 0, SDL_PIXELFORMAT_RGB24);
-
-	if (gSurface == NULL)
+	if (!Backend_Init(gWindow))
 		return FALSE;
 
-	framebuffer.in_use = TRUE;
-	framebuffer.pixels = (unsigned char*)gSurface->pixels;
-	framebuffer.width = WINDOW_WIDTH * magnification;
-	framebuffer.height = WINDOW_HEIGHT * magnification;
-	framebuffer.pitch = gSurface->pitch;
+	rgb24_pixel_format = SDL_AllocFormat(SDL_PIXELFORMAT_RGB24);
 
 	return TRUE;
 }
@@ -116,13 +103,13 @@
 
 void EndDirectDraw()
 {
+	SDL_FreeFormat(rgb24_pixel_format);
+
 	// Release all surfaces
 	for (int i = 0; i < SURFACE_ID_MAX; i++)
 		ReleaseSurface(i);
 
-	framebuffer.in_use = FALSE;
-
-	SDL_FreeSurface(gSurface);
+	Backend_Deinit();
 }
 
 static BOOL IsEnableBitmap(SDL_RWops *fp)
@@ -143,7 +130,7 @@
 	// Release the surface we want to release
 	if (surf[s].in_use)
 	{
-		free(surf[s].pixels);
+		Backend_FreeSurface(surf[s].backend);
 		surf[s].in_use = FALSE;
 	}
 }
@@ -171,14 +158,11 @@
 		else
 		{
 			// Create surface
-			surf[surf_no].pixels = (unsigned char*)malloc((bxsize * magnification) * (bysize * magnification) * 3);
-			surf[surf_no].width = bxsize * magnification;
-			surf[surf_no].height = bysize * magnification;
-			surf[surf_no].pitch = surf[surf_no].width * 3;
+			surf[surf_no].backend = Backend_CreateSurface(bxsize * magnification, bysize * magnification);
 
-			if (surf[surf_no].pixels == NULL)
+			if (surf[surf_no].backend == NULL)
 			{
-				printf("Failed to allocate surface pixel buffer %d\n", surf_no);
+				printf("Failed to create backend surface %d\n", surf_no);
 			}
 			else
 			{
@@ -218,7 +202,7 @@
 				if (create_surface == FALSE || MakeSurface_Generic(surface->w, surface->h, surf_no, FALSE))
 				{
 
-					SDL_Surface *converted_surface = SDL_ConvertSurface(surface, gSurface->format, 0);
+					SDL_Surface *converted_surface = SDL_ConvertSurface(surface, rgb24_pixel_format, 0);
 
 					if (converted_surface == NULL)
 					{
@@ -230,21 +214,17 @@
 						if (magnification == 1)
 						{
 							// Just copy the pixels the way they are
-							for (int h = 0; h < converted_surface->h; ++h)
-							{
-								const unsigned char *src_row = (unsigned char*)converted_surface->pixels + h * converted_surface->pitch;
-								unsigned char *dst_row = surf[surf_no].pixels + h * surf[surf_no].pitch;
-
-								memcpy(dst_row, src_row, converted_surface->w * 3);
-							}
+							Backend_LoadPixels(surf[surf_no].backend, (unsigned char*)converted_surface->pixels, converted_surface->w, converted_surface->h, converted_surface->pitch);
 						}
 						else
 						{
 							// Upscale the bitmap to the game's internal resolution
+							unsigned char *pixels = (unsigned char*)malloc((converted_surface->w * magnification) * (converted_surface->h * magnification) * 3);
+
 							for (int h = 0; h < converted_surface->h; ++h)
 							{
 								const unsigned char *src_row = (unsigned char*)converted_surface->pixels + h * converted_surface->pitch;
-								unsigned char *dst_row = surf[surf_no].pixels + h * surf[surf_no].pitch * magnification;
+								unsigned char *dst_row = pixels + h * (converted_surface->w * magnification * 3) * magnification;
 
 								const unsigned char *src_ptr = src_row;
 								unsigned char *dst_ptr = dst_row;
@@ -262,8 +242,11 @@
 								}
 
 								for (int i = 1; i < magnification; ++i)
-									memcpy(dst_row + i * surf[surf_no].pitch, dst_row, converted_surface->w * magnification * 3);
+									memcpy(dst_row + i * converted_surface->w * magnification * 3, dst_row, converted_surface->w * magnification * 3);
 							}
+
+							Backend_LoadPixels(surf[surf_no].backend, pixels, converted_surface->w * magnification, converted_surface->h * magnification, converted_surface->w * magnification * 3);
+							free(pixels);
 						}
 
 						SDL_FreeSurface(converted_surface);
@@ -390,133 +373,12 @@
 	destination_rect->bottom = source_rect->bottom * magnification;
 }
 
-static void Blit(const SURFACE *source_surface, const RECT *rect, SURFACE *destination_surface, long x, long y, BOOL colour_key)
-{
-	RECT rect_clamped;
-
-	rect_clamped.left = rect->left;
-	rect_clamped.top = rect->top;
-	rect_clamped.right = rect->right;
-	rect_clamped.bottom = rect->bottom;
-
-	// Clamp the rect and coordinates so we don't write outside the pixel buffer
-	long overflow;
-
-	overflow = 0 - x;
-	if (overflow > 0)
-	{
-		rect_clamped.left += overflow;
-		x += overflow;
-	}
-
-	overflow = 0 - y;
-	if (overflow > 0)
-	{
-		rect_clamped.top += overflow;
-		y += overflow;
-	}
-
-	overflow = (x + (rect_clamped.right - rect_clamped.left)) - destination_surface->width;
-	if (overflow > 0)
-	{
-		rect_clamped.right -= overflow;
-	}
-
-	overflow = (y + (rect_clamped.bottom - rect_clamped.top)) - destination_surface->height;
-	if (overflow > 0)
-	{
-		rect_clamped.bottom -= overflow;
-	}
-
-	// Do the actual blitting
-	if (colour_key)
-	{
-		for (long j = 0; j < rect_clamped.bottom - rect_clamped.top; ++j)
-		{
-			unsigned char *source_pointer = &source_surface->pixels[((rect_clamped.top + j) * source_surface->pitch) + (rect_clamped.left * 3)];
-			unsigned char *destination_pointer = &destination_surface->pixels[((y + j) * destination_surface->pitch) + (x * 3)];
-
-			for (long i = 0; i < rect_clamped.right - rect_clamped.left; ++i)
-			{
-				if (source_pointer[0] != 0 || source_pointer[1] != 0 || source_pointer[2] != 0)	// Assumes the colour key will always be #00000000 (black)
-				{
-					destination_pointer[0] = source_pointer[0];
-					destination_pointer[1] = source_pointer[1];
-					destination_pointer[2] = source_pointer[2];
-				}
-
-				source_pointer += 3;
-				destination_pointer += 3;
-			}
-		}
-	}
-	else
-	{
-		for (long j = 0; j < rect_clamped.bottom - rect_clamped.top; ++j)
-		{
-			unsigned char *source_pointer = &source_surface->pixels[((rect_clamped.top + j) * source_surface->pitch) + (rect_clamped.left * 3)];
-			unsigned char *destination_pointer = &destination_surface->pixels[((y + j) * destination_surface->pitch) + (x * 3)];
-
-			memcpy(destination_pointer, source_pointer, (rect_clamped.right - rect_clamped.left) * 3);
-		}
-	}
-}
-
-static void ColourFill(SURFACE *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
-{
-	RECT rect_clamped;
-
-	rect_clamped.left = rect->left;
-	rect_clamped.top = rect->top;
-	rect_clamped.right = rect->right;
-	rect_clamped.bottom = rect->bottom;
-
-	// Clamp the rect so it doesn't write outside the pixel buffer
-	long overflow;
-
-	overflow = 0 - rect_clamped.left;
-	if (overflow > 0)
-	{
-		rect_clamped.left += overflow;
-	}
-
-	overflow = 0 - rect_clamped.top;
-	if (overflow > 0)
-	{
-		rect_clamped.top += overflow;
-	}
-
-	overflow = rect_clamped.right - surface->width;
-	if (overflow > 0)
-	{
-		rect_clamped.right -= overflow;
-	}
-
-	overflow = rect_clamped.bottom - surface->height;
-	if (overflow > 0)
-	{
-		rect_clamped.bottom -= overflow;
-	}
-
-	for (long j = 0; j < rect_clamped.bottom - rect_clamped.top; ++j)
-	{
-		unsigned char *source_pointer = &surface->pixels[((rect_clamped.top + j) * surface->pitch) + (rect_clamped.left * 3)];
-
-		for (long i = 0; i < rect_clamped.right - rect_clamped.left; ++i)
-		{
-			*source_pointer++ = red;
-			*source_pointer++ = green;
-			*source_pointer++ = blue;
-		}
-	}
-}
-
 void BackupSurface(Surface_Ids surf_no, const RECT *rect)
 {
 	RECT frameRect;
 	ScaleRect(rect, &frameRect);
 
-	Blit(&framebuffer, &frameRect, &surf[surf_no], frameRect.left, frameRect.top, FALSE);
+	Backend_ScreenToSurface(surf[surf_no].backend, &frameRect);
 	//surf[surf_no].needs_updating = TRUE;
 }
 
@@ -563,7 +425,7 @@
 	frameRect.bottom *= magnification;
 
 	// Draw to screen
-	Blit(&surf[surf_no], &frameRect, &framebuffer, x * magnification, y * magnification, transparent);
+	Backend_BlitToScreen(surf[surf_no].backend, &frameRect, x * magnification, y * magnification, transparent);
 }
 
 void PutBitmap3(const RECT *rcView, int x, int y, const RECT *rect, Surface_Ids surf_no) // Transparency
@@ -582,7 +444,7 @@
 	RECT frameRect;
 	ScaleRect(rect, &frameRect);
 
-	Blit(&surf[from], &frameRect, &surf[to], x * magnification, y * magnification, TRUE);
+	Backend_Blit(surf[from].backend, &frameRect, surf[to].backend, x * magnification, y * magnification, TRUE);
 	//surf[to].needs_updating = TRUE;
 }
 
@@ -604,7 +466,7 @@
 	const unsigned char col_green = (unsigned char)((col >> 8) & 0xFF);
 	const unsigned char col_blue = (unsigned char)((col >> 16) & 0xFF);
 
-	ColourFill(&framebuffer, &destRect, col_red, col_green, col_blue);
+	Backend_ColourFillToScreen(&destRect, col_red, col_green, col_blue);
 }
 
 void CortBox2(const RECT *rect, unsigned long col, Surface_Ids surf_no)
@@ -618,7 +480,7 @@
 	const unsigned char col_green = (unsigned char)((col >> 8) & 0xFF);
 	const unsigned char col_blue = (unsigned char)((col >> 16) & 0xFF);
 
-	ColourFill(&surf[surf_no], &destRect, col_red, col_green, col_blue);
+	Backend_ColourFill(surf[surf_no].backend, &destRect, col_red, col_green, col_blue);
 	//surf[surf_no].needs_updating = TRUE;
 }
 
@@ -723,12 +585,12 @@
 
 void PutText(int x, int y, const char *text, unsigned long color)
 {
-	DrawText(gFont, framebuffer.pixels, framebuffer.pitch, framebuffer.width, framebuffer.height, x * magnification, y * magnification, color, text, strlen(text));
+	Backend_DrawTextToScreen(gFont, x * magnification, y * magnification, text, color);
 }
 
 void PutText2(int x, int y, const char *text, unsigned long color, Surface_Ids surf_no)
 {
-	DrawText(gFont, surf[surf_no].pixels, surf[surf_no].pitch, surf[surf_no].width, surf[surf_no].height, x * magnification, y * magnification, color, text, strlen(text));
+	Backend_DrawText(surf[surf_no].backend, gFont, x * magnification, y * magnification, text, color);
 	//surf[surf_no].needs_updating = TRUE;
 }