shithub: candycrisis

Download patch

ref: 30c2d82dffe2d90a3f155e6395e0e36961260102
parent: 9acc208ae7427727a736faf0fe971756a34ae019
author: Iliyas Jorio <iliyas@jor.io>
date: Mon Feb 6 15:12:33 EST 2023

In-game widescreen toggle

--- a/src/SDLU.cpp
+++ b/src/SDLU.cpp
@@ -191,6 +191,8 @@
         SDL_PIXELFORMAT_RGB888,
         SDL_TEXTUREACCESS_STREAMING,
         640, 480);
+
+    SDL_RenderSetLogicalSize(g_renderer, 640, widescreen ? 360: 480);
 }
 
 
--- a/src/level.cpp
+++ b/src/level.cpp
@@ -63,12 +63,16 @@
     kTitleItemQuit,
 };
 
-struct {
+struct TitleItemDef
+{
 	const char* name;
 	MRGBColor color1;
 	MRGBColor color2;
 	MRect rect;
-} titleItems[kTitleItems] = {
+};
+
+static const TitleItemDef k_titleItemDefs[kTitleItems] =
+{
 		{ "\x03 Tutorial Mode",     {204, 67,137}, {101, 74,207}, {155, 203, 207, 426} },
 		{ "\x03 One Player Game",   { 35, 31,240}, { 81,237,252}, {225, 179, 281, 451} },
 		{ "\x03 Two Player Game",   {212,194, 48}, {255,196, 56}, {297, 182, 352, 454} },
@@ -82,8 +86,6 @@
 const int kCursorWidth  = 32;
 const int kCursorHeight = 32;
 
-extern MBoolean useNewTitle;
-
 #if USE_CURSOR_SPRITE
 static void InsertCursor( MPoint mouseHere, SDL_Surface* scratch, SDL_Surface* surface )
 {
@@ -124,6 +126,8 @@
 
 void GameStartMenu( void )
 {
+	MBoolean        useNewTitle = widescreen;
+
 	// NOTE: be wary of initializing variables here! This function can run top-to-bottom
 	// multiple times in a row, thanks to "redo". Put initializations after redo.
     SDL_Surface*    gameStartSurface;
@@ -144,6 +148,7 @@
 	SkittlesFontPtr smallFont = GetFont( picFont );
 	SkittlesFontPtr tinyFont = GetFont( picTinyFont );
 	SDL_Rect        meterRect[2] = { { 30, 360, 110, 20 }, { 530, 360, 110, 20 } };
+	TitleItemDef    titleItems[kTitleItems];
     int             titleGlow[kTitleItems];
     int             shouldAddBlob;
     const int       kTitleGlowOff = useNewTitle? 150: 192;
@@ -151,7 +156,9 @@
     
 	const int       kLeftSide = 0, kRightSide = 1, kGlow = 2, kCursor = 3;
 	
+	
 redo:
+	memcpy(titleItems, k_titleItemDefs, sizeof(titleItems));
 
 	combo[0] = combo[1] = 0;
 	comboBright[0] = comboBright[1] = 0;
@@ -192,10 +199,13 @@
 	
 	// make drawing surface
 	gameStartDrawSurface = SDLU_InitSurface( &backdropSDLRect, 32 );
-	if (!useNewTitle) {
+	if (!useNewTitle)
+	{
 		SDLU_BlitSurface(gameStartSurface, &gameStartSurface->clip_rect,
 						 gameStartDrawSurface, &gameStartDrawSurface->clip_rect);
-	} else {
+	}
+	else
+	{
 		// Prepare new title screen
 		SDL_FillRect(gameStartDrawSurface, &gameStartDrawSurface->clip_rect, black);
 
@@ -212,13 +222,15 @@
 		int left = 225;
 		dPoint.h = left;
 		dPoint.v = 215;
-		for (int i = 0; i < kTitleItems; i++) {
+		for (int i = 0; i < kTitleItems; i++)
+		{
 			auto &item = titleItems[i];
 			item.rect.left = dPoint.h;
 			item.rect.top = dPoint.v - 6;
 			item.rect.bottom = dPoint.v + 16 + 6;
 			auto nameLength = strlen(item.name);
-			for (int charNo = 0; charNo < nameLength; charNo++) {
+			for (int charNo = 0; charNo < nameLength; charNo++)
+			{
 				char c = item.name[charNo];
 				float p = charNo / (float) (nameLength - 1);
 				int red = item.color1.red * (1.0f - p) + item.color2.red * p;
@@ -754,14 +766,7 @@
 	
 	// In widescreen mode, move score/gray windows closer to the playfield
 	// so they fit in the cropped screen.
-	if (widescreen) {
-		for (int i = 0; i < 2; i++) {
-			grayMonitorRect[i].top    = playerWindowRect[i].top - 32 - 4;
-			grayMonitorRect[i].bottom = playerWindowRect[i].top - 4;
-			scoreWindowRect[i].top    = playerWindowRect[i].bottom + 4;
-			scoreWindowRect[i].bottom = playerWindowRect[i].bottom + 16 + 4;
-		}
-	}
+	ResetWidescreenLayout();
 	
 	nextWindowVisible[0] = ( player1 == kAutoControl )? false: true;
 	
@@ -780,6 +785,19 @@
 	
 	level = 1;
 	credits = (player2 == kNobodyControl)? 1: 5;
+}
+
+void ResetWidescreenLayout()
+{
+	int miniWindowOffset = widescreen ? 4 : 16;
+
+	for (int i = 0; i < 2; i++)
+	{
+		grayMonitorRect[i].top = playerWindowRect[i].top - 32 - miniWindowOffset;
+		grayMonitorRect[i].bottom = playerWindowRect[i].top - miniWindowOffset;
+		scoreWindowRect[i].top = playerWindowRect[i].bottom + miniWindowOffset;
+		scoreWindowRect[i].bottom = playerWindowRect[i].bottom + 16 + miniWindowOffset;
+	}
 }
 
 MBoolean InitCharacter( int player, int level )
--- a/src/level.h
+++ b/src/level.h
@@ -1,6 +1,7 @@
 // level.h
 
 void InitGame( int player1, int player2 );
+void ResetWidescreenLayout( );
 MBoolean InitCharacter( int player, int level );
 void PrepareStageGraphics( int type );
 void BeginRound( MBoolean changeMusic );
binary files a/src/main.cpp b/src/main.cpp differ
--- a/src/pause.cpp
+++ b/src/pause.cpp
@@ -521,8 +521,8 @@
 // main pause screen (kEndGame is reused in continue and register)
 	kMusic = 0,		kResume,
 	kSound,         kEndGame,
-	kFullscreen,    kControls,
-	kScalingMode,   kWarp,
+	kVideo,         kControls,
+	kWarp,
 
 // continue screen
     kContinue,      
@@ -533,6 +533,12 @@
     k1PDrop,        k2PDrop,
     k1PRotate,      k2PRotate,
     kControlsOK,    kControlsReset,
+
+// video settings screen
+    kFullscreen,
+	kWidescreen,
+    kScalingMode,
+	kVideoOK,
 };
 
 static void DrawContinueContents( int *item, int shade )
@@ -721,37 +727,59 @@
 
 static void DrawPauseContents( int *item, int shade )
 {
-	MPoint dPoint;
-	int index;
-	const char *line[]  = { "\x01 Music",           "\x03 Resume",
-                            "\x01 Sound",           "\x03 End Game",
-                            "\x01 Fullscreen",      "\x03 Controls",
-                            "\x01 Crisp Scaling",
+	const char *line[] =
+	{
+		musicOn ? "\x01 Music" : "\x02 Music",
+		level == kTutorialLevel ? "\x03 Skip Tutorial" : "\x03 Resume",
+		soundOn ? "\x01 Sound" : "\x02 Sound",
+		"\x03 End Game",
+        "\x03 Video",
+		"\x03 Controls",
 	};
 
-    const int itemCount = arrsize(line);
-	
-	if( level == kTutorialLevel ) line[kEndGame] = "\x03 Skip Tutorial";
-	
-	if( !musicOn ) line[kMusic] = "\x02 Music";
-	if( !soundOn ) line[kSound] = "\x02 Sound";
-	if( !fullscreen ) line[kFullscreen] = "\x02 Fullscreen";
-	if( !crispUpscaling ) line[kScalingMode] = "\x02 Crisp Scaling";
-
 	SDLU_AcquireSurface( drawSurface );	
 	
-	for( index=0; index<itemCount; index++ )
+	for( int i = 0; i < arrsize(line); i++ )
 	{	
-		dPoint.h = (index & 1)? 340: 180;
-		dPoint.v = 240 + ((index & ~1) * 15);
+		MPoint dPoint;
+		dPoint.h = (i & 1)? 340: 180;
+		dPoint.v = 240 + ((i & ~1) * 15);
 		
-		DrawRainbowText( smallFont, line[index], dPoint, (0.25 * index) + (0.075 * shade), (*item == index)? kTextBrightRainbow: kTextRainbow );
+		DrawRainbowText( smallFont, line[i], dPoint, (0.25 * i) + (0.075 * shade), (*item == i)? kTextBrightRainbow: kTextRainbow );
 	}
 	
 	SDLU_ReleaseSurface( drawSurface );
 }
 
+static void DrawVideoSettingsContents(int* item, int shade)
+{
+	struct ZoneLabel
+	{
+		int item;
+		const char* text;
+	}
+	labels[] =
+	{
+		{ kFullscreen,		fullscreen ? "\x01 Fullscreen" : "\x02 Fullscreen" },
+		{ kWidescreen,		widescreen ? "\x01 Widescreen" : "\x02 Widescreen" },
+		{ kScalingMode,		crispUpscaling ? "\x01 Crisp upscaling" : "\x02 Crisp upscaling" },
+		{ kVideoOK,			"\x03 OK" },
+	};
 
+	SDLU_AcquireSurface(drawSurface);
+
+	for (int i = 0; i < arrsize(labels); i++)
+	{
+		MPoint dPoint;
+		dPoint.h = 180;
+		dPoint.v = 240 + (i * 30);
+
+		DrawRainbowText(smallFont, labels[i].text, dPoint, (0.25 * i) + (0.075 * shade), (*item == labels[i].item) ? kTextBrightRainbow : kTextRainbow);
+	}
+
+	SDLU_ReleaseSurface(drawSurface);
+}
+
 static MBoolean GetClickedZone( int* item, SDL_Keycode inSDLKey, int numZones, const ClickableZone* zones )
 {
 	if( inSDLKey == SDLK_ESCAPE )
@@ -929,8 +957,8 @@
 	{	
 		{ kMusic,		{ 240, 180, 260, 320 } },		{ kResume,		{ 240, 340, 260, 480 } },
 		{ kSound,		{ 270, 180, 290, 320 } },		{ kEndGame,		{ 270, 340, 290, 480 } },
-		{ kFullscreen,	{ 300, 180, 320, 320 } },		{ kControls,	{ 300, 340, 320, 480 } },
-		{ kScalingMode,	{ 330, 180, 350, 320 } },		{ kWarp,		{ 330, 340, 350, 480 } },
+		{ kVideo,		{ 300, 180, 320, 320 } },		{ kControls,	{ 300, 340, 320, 480 } },
+		{ kWarp,		{ 330, 180, 350, 320 } },
 	};
 
 	static MBoolean lastDown = false;
@@ -973,6 +1001,7 @@
 				case kResume:
 				case kBack:
                 case kControls:
+                case kVideo:
                     PlayMono( kClick );
                     return true;
 
@@ -1000,6 +1029,74 @@
 }
 
 
+
+static MBoolean VideoSettingsSelected( int *item, unsigned char inKey, SDL_Keycode inSDLKey )
+{
+	(void) inSDLKey; // is unused
+	
+	static const ClickableZone zones[] = 
+	{	
+		{ kFullscreen,		{ 240, 180, 260, 320 } },
+		{ kWidescreen,		{ 270, 180, 290, 320 } },
+		{ kScalingMode,		{ 300, 180, 320, 320 } },
+		{ kVideoOK,			{ 330, 180, 350, 320 } },
+	};
+
+	static MBoolean lastDown = false;
+	
+	int trigger = GetClickedZone( item, inSDLKey, arrsize(zones), zones );
+	
+	if( trigger )
+	{
+		if( !lastDown )
+		{
+			lastDown = true;
+			
+			switch( *item )
+			{
+				case kNothing:
+					break;
+
+				case kFullscreen:
+                    fullscreen = !fullscreen;
+                    SetFullscreen( fullscreen );
+                    PlayMono( kClick );
+                    return false;
+
+				case kScalingMode:
+					crispUpscaling = !crispUpscaling;
+					SDLU_CreateRendererTexture();
+					PlayMono(kClick);
+					return false;
+
+				case kWidescreen:
+					widescreen= !widescreen;
+					ResetWidescreenLayout();
+					SDLU_CreateRendererTexture();
+					SetFullscreen(fullscreen);
+					PlayMono(kClick);
+
+					NeedRefresh();
+					//RefreshAll();
+					//RefreshPlayerWindow(0);
+					//RefreshPlayerWindow(1);
+
+					return false;
+
+				default:
+                    PlayMono( kClick );
+                    return true;
+			}
+		}
+	}
+	else
+	{
+		lastDown = false;
+	}
+	
+	return false;
+}
+
 void HandleDialog( int type )
 {	
 	const float    lighten[4] = { 96.0f, 48.0f, 8.0f, 48.0f };
@@ -1093,6 +1190,7 @@
 				HiScoreSelected,
 				ContinueSelected,
 				ControlsSelected,
+				VideoSettingsSelected,
 			};
 			
 			if( DialogSelected[dialogType]( &dialogItem, inASCII, inSDLKey ) )
@@ -1121,6 +1219,7 @@
 				DrawHiScoreContents,
 				DrawContinueContents,
 				DrawControlsContents,
+				DrawVideoSettingsContents,
 			};
 
 			// Refresh screen if necessary
@@ -1136,9 +1235,9 @@
 			dialogShade += skip;
 
 			{
-				const MBoolean dialogHasCandyCrisisLogo[kNumDialogs] = { true, true, true, true };
+				bool dialogHasCandyCrisisLogo = true;
 				
-				if( dialogHasCandyCrisisLogo[dialogType] )
+				if( dialogHasCandyCrisisLogo )
 					DrawDialogLogo( &pauseRect, dialogShade );
 			}
 			
@@ -1195,6 +1294,11 @@
 			
 	switch( dialogItem )
 	{
+		case kVideo:
+			HandleDialog( kVideoDialog );
+			HandleDialog( kPauseDialog );
+			break;
+
 		case kControls:
 			HandleDialog( kControlsDialog );
 			HandleDialog( kPauseDialog );
--- a/src/pause.h
+++ b/src/pause.h
@@ -10,5 +10,6 @@
 	kHiScoreDialog,
 	kContinueDialog,
 	kControlsDialog,
+	kVideoDialog,
 	kNumDialogs
 };
--- a/src/prefs.cpp
+++ b/src/prefs.cpp
@@ -112,35 +112,3 @@
         stream.write((const char*)pref.valuePtr, pref.valueLength);
     }
 }
-
-void ParseCommandLine(int argc, char* argv[])
-{
-    for (int i = 1; i < argc; i++)
-    {
-        const char* arg = argv[i];
-
-        if (!strcmp(arg, "--crisp")) crispUpscaling = true;
-        if (!strcmp(arg, "--fullscreen")) fullscreen = true;
-        if (!strcmp(arg, "--widescreen")) widescreen = true;
-
-        if (!strcmp(arg, "--no-crisp")) crispUpscaling = false;
-        if (!strcmp(arg, "--no-fullscreen")) fullscreen = false;
-        if (!strcmp(arg, "--no-widescreen")) widescreen = false;
-
-        if (!strcmp(arg, "--help") || !strcmp(arg, "-h"))
-        {
-            printf(
-                    "Candy Crisis source port - https://github.com/jorio/candycrisis\n"
-                    "\n"
-                    "    --crisp           pixel-perfect upscaling\n"
-                    "    --no-crisp        upscale with bilinear filtering\n"
-                    "    --fullscreen      run the game fullscreen\n"
-                    "    --no-fullscreen   run the game in a window\n"
-                    "    --widescreen      crop viewport to 16:9 aspect ratio\n"
-                    "    --no-widescreen   use original 4:3 aspect ratio\n"
-                    "\n"
-            );
-            exit(0);
-        }
-    }
-}
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -2,4 +2,3 @@
 
 void LoadPrefs( void );
 void SavePrefs( void );
-void ParseCommandLine(int argc, char* argv[]);