Maelstrom: Added support for background images

From 17addb4c7b11091c889fea907a014ed0baf1f43a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 8 Apr 2026 12:43:35 -0700
Subject: [PATCH] Added support for background images

---
 game/Maelstrom_Globals.h |  3 +++
 game/game.cpp            | 46 ++++++++++++++++++++++++++--------------
 game/game.h              |  3 +++
 game/init.cpp            |  2 ++
 game/main.cpp            | 10 ++++-----
 game/mods.cpp            |  7 +++++-
 game/steam.h             |  8 +++----
 7 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/game/Maelstrom_Globals.h b/game/Maelstrom_Globals.h
index 90f65a12..a5e3dd41 100644
--- a/game/Maelstrom_Globals.h
+++ b/game/Maelstrom_Globals.h
@@ -53,6 +53,9 @@
 #define PREFERENCES_CONTINUES "Cheat.Continues"
 #define PREFERENCES_MOD_FILE "ModFile"
 
+// The restart event
+#define SDL_EVENT_RESTART_INITIALIZATION	(SDL_EVENT_USER + 0)
+
 // The Font Server :)
 extern FontServ *fontserv;
 
diff --git a/game/game.cpp b/game/game.cpp
index 60398033..545b5645 100644
--- a/game/game.cpp
+++ b/game/game.cpp
@@ -154,6 +154,13 @@ void ContinueGame(void)
 	gShownContinue = 0;
 }
 
+GamePanelDelegate::~GamePanelDelegate()
+{
+	if (m_background) {
+		Free_Texture(screen, m_background);
+	}
+}
+
 bool
 GamePanelDelegate::OnLoad()
 {
@@ -188,6 +195,8 @@ GamePanelDelegate::OnLoad()
 	m_zoomIn = m_panel->GetElement<UIElement>("zoom_in");
 	m_zoomOut = m_panel->GetElement<UIElement>("zoom_out");
 
+	m_background = Load_Image(screen, "background");
+
 	return true;
 }
 
@@ -582,22 +591,27 @@ GamePanelDelegate::OnDraw(DRAWLEVEL drawLevel)
 
 	StartZoomedDrawing();
 
-	/* -- Draw the star field */
-	for ( i=0; i<MAX_STARS; ++i ) {
-		int x = (gTheStars[i]->xCoord << SPRITE_PRECISION);
-		int y = (gTheStars[i]->yCoord << SPRITE_PRECISION);
-		GetRenderCoordinates(x, y);
-		screen->DrawPoint(x, y, gTheStars[i]->color);
-	}
-
-	for ( i=0; i<MAX_BORDER_STARS; ++i ) {
-		int x = (gBorderStars[i]->xCoord << SPRITE_PRECISION);
-		int y = (gBorderStars[i]->yCoord << SPRITE_PRECISION);
-		GetRenderCoordinates(x, y);
-		if (gZoomGame ||
-		    (x >= SPRITES_WIDTH && x < (GAME_WIDTH - SPRITES_WIDTH) &&
-		     y >= SPRITES_WIDTH && y < (GAME_HEIGHT - SPRITES_WIDTH))) {
-			screen->DrawPoint(x, y, gBorderStars[i]->color);
+	if (m_background) {
+		/* -- Draw the background */
+		m_background->Draw(screen, 0, 0, GAME_WIDTH, GAME_HEIGHT, SDL_ALPHA_OPAQUE);
+	} else {
+		/* -- Draw the star field */
+		for ( i=0; i<MAX_STARS; ++i ) {
+			int x = (gTheStars[i]->xCoord << SPRITE_PRECISION);
+			int y = (gTheStars[i]->yCoord << SPRITE_PRECISION);
+			GetRenderCoordinates(x, y);
+			screen->DrawPoint(x, y, gTheStars[i]->color);
+		}
+
+		for ( i=0; i<MAX_BORDER_STARS; ++i ) {
+			int x = (gBorderStars[i]->xCoord << SPRITE_PRECISION);
+			int y = (gBorderStars[i]->yCoord << SPRITE_PRECISION);
+			GetRenderCoordinates(x, y);
+			if (gZoomGame ||
+				(x >= SPRITES_WIDTH && x < (GAME_WIDTH - SPRITES_WIDTH) &&
+				 y >= SPRITES_WIDTH && y < (GAME_HEIGHT - SPRITES_WIDTH))) {
+				screen->DrawPoint(x, y, gBorderStars[i]->color);
+			}
 		}
 	}
 
diff --git a/game/game.h b/game/game.h
index eebc70db..c7eeb2c7 100644
--- a/game/game.h
+++ b/game/game.h
@@ -31,6 +31,7 @@ class GamePanelDelegate : public UIPanelDelegate
 {
 public:
 	GamePanelDelegate(UIPanel *panel) : UIPanelDelegate(panel) { }
+	virtual ~GamePanelDelegate();
 
 	virtual bool OnLoad();
 	virtual void OnShow();
@@ -97,6 +98,8 @@ class GamePanelDelegate : public UIPanelDelegate
 	UIElement *m_zoomIn;
 	UIElement *m_zoomOut;
 
+	UITexture *m_background;
+
 	enum {
 		STATE_PLAYING,
 		STATE_SHOW_BONUS,
diff --git a/game/init.cpp b/game/init.cpp
index 788e645e..074a83d2 100644
--- a/game/init.cpp
+++ b/game/init.cpp
@@ -959,6 +959,8 @@ bool RestartInitialization()
 		return false;
 	}
 
+	ui->Shutdown();
+
 	ShowLoadingPanel(LOAD_STAGE_STARTING);
 
 	return true;
diff --git a/game/main.cpp b/game/main.cpp
index 687f6996..4496a64a 100644
--- a/game/main.cpp
+++ b/game/main.cpp
@@ -232,6 +232,10 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
 
 SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
 {
+	if (event->type == SDL_EVENT_RESTART_INITIALIZATION) {
+		RestartInitialization();
+	}
+
 	if (event->type == SDL_EVENT_DROP_FILE) {
 		SDL_free(gReplayFile);
 		gReplayFile = SDL_strdup(event->drop.data);
@@ -416,12 +420,6 @@ MainPanelDelegate::OnTick()
 bool
 MainPanelDelegate::HandleEvent(const SDL_Event &event)
 {
-	/* -- Handle file drop requests */
-	if ( event.type == SDL_EVENT_DROP_FILE ) {
-		gReplayFile = SDL_strdup( event.drop.data );
-		return true;
-	}
-
 	return false;
 }
 
diff --git a/game/mods.cpp b/game/mods.cpp
index 82a7df16..1ea5b96e 100644
--- a/game/mods.cpp
+++ b/game/mods.cpp
@@ -130,7 +130,12 @@ ModsDialogDelegate::OnHide()
 		}
 		if (SDL_strcmp(selected_mod, current_mod) != 0) {
 			prefs->SetString(PREFERENCES_MOD_FILE, selected_mod);
-			RestartInitialization();
+
+			// Signal that we should reload the game
+			SDL_Event event;
+			SDL_zero(event);
+			event.type = SDL_EVENT_RESTART_INITIALIZATION;
+			SDL_PushEvent(&event);
 		}
 	}
 }
diff --git a/game/steam.h b/game/steam.h
index 46a36605..c93497ce 100644
--- a/game/steam.h
+++ b/game/steam.h
@@ -22,10 +22,10 @@
 #ifndef _steam_h
 #define _steam_h
 
-#define SDL_EVENT_REMOTE_PLAYERS_CHANGED	(SDL_EVENT_USER + 0)
-#define SDL_EVENT_REMOTE_INPUT				(SDL_EVENT_USER + 1)
-#define SDL_EVENT_OVERLAY_ACTIVATED			(SDL_EVENT_USER + 2)
-#define SDL_EVENT_OVERLAY_DEACTIVATED		(SDL_EVENT_USER + 3)
+#define SDL_EVENT_REMOTE_PLAYERS_CHANGED	(SDL_EVENT_USER + 1000)
+#define SDL_EVENT_REMOTE_INPUT				(SDL_EVENT_USER + 1001)
+#define SDL_EVENT_OVERLAY_ACTIVATED			(SDL_EVENT_USER + 1002)
+#define SDL_EVENT_OVERLAY_DEACTIVATED		(SDL_EVENT_USER + 1003)
 
 enum STEAM_TIMELINE_MODE
 {