shithub: cstory

Download patch

ref: 0c367cecf7ff5236dc8e2005fffae254c400a1fc
parent: e43160825e95651a8b34cb70441504d1c5023845
author: Clownacy <Clownacy@users.noreply.github.com>
date: Thu Sep 3 17:05:14 EDT 2020

Add FIX_MAJOR_BUGS option

This one specifically fixes bugs that either invoke undefined
behaviour or cause memory leaks. Essentially, they affect stability.
Bugs that just affect gameplay will remain covered by FIX_BUGS.

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,6 +14,7 @@
 
 option(JAPANESE "Enable the Japanese-language build (instead of the unofficial Aeon Genesis English translation)" OFF)
 option(FIX_BUGS "Fix various bugs in the game" OFF)
+option(FIX_MAJOR_BUGS "Fix bugs that invoke undefined behaviour or cause memory leaks" OFF)
 option(DEBUG_SAVE "Re-enable the dummied-out 'Debug Save' option, and the ability to drag-and-drop save files onto the window" OFF)
 
 option(LTO "Enable link-time optimisation" OFF)
@@ -167,6 +168,10 @@
 
 if(FIX_BUGS)
 	target_compile_definitions(CSE2 PRIVATE FIX_BUGS)
+endif()
+
+if(FIX_BUGS OR FIX_MAJOR_BUGS)
+	target_compile_definitions(CSE2 PRIVATE FIX_MAJOR_BUGS)
 endif()
 
 if(DEBUG_SAVE)
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,11 @@
 FILENAME ?= $(FILENAME_DEF)
 
 ifeq ($(FIX_BUGS), 1)
-  ALL_CXXFLAGS += -DFIX_BUGS
+  ALL_CXXFLAGS += -DFIX_BUGS -DFIX_MAJOR_BUGS
+else
+  ifeq ($(FIX_MAJOR_BUGS), 1)
+    ALL_CXXFLAGS += -DFIX_MAJOR_BUGS
+  endif
 endif
 
 ifeq ($(DEBUG_SAVE), 1)
--- a/README.md
+++ b/README.md
@@ -82,6 +82,7 @@
 --------|--------
 `-DJAPANESE=ON` | Enable the Japanese-language build (instead of the unofficial Aeon Genesis English translation)
 `-DFIX_BUGS=ON` | Fix various bugs in the game
+`-DFIX_MAJOR_BUGS=ON` | Fix bugs that invoke undefined behaviour or cause memory leaks
 `-DDEBUG_SAVE=ON` | Re-enable [the dummied-out 'Debug Save' option](https://tcrf.net/Cave_Story#Debug_Save), and the ability to drag-and-drop save files onto the window
 `-DLTO=ON` | Enable link-time optimisation
 `-DMSVC_LINK_STATIC_RUNTIME=ON` | Link the static MSVC runtime library, to reduce the number of required DLL files (Visual Studio only)
@@ -108,6 +109,7 @@
 --------|--------
 `JAPANESE=1` | Enable the Japanese-language build (instead of the unofficial Aeon Genesis English translation)
 `FIX_BUGS=1` | Fix various bugs in the game
+`FIX_MAJOR_BUGS=1` | Fix bugs that invoke undefined behaviour or cause memory leaks
 `DEBUG_SAVE=1` | Re-enable [the dummied-out 'Debug Save' option](https://tcrf.net/Cave_Story#Debug_Save), and the ability to drag-and-drop save files onto the window
 `RELEASE=1` | Compile a release build (optimised, stripped, etc.)
 `STATIC=1` | Produce a statically-linked executable (so you don't need to bundle DLL files)
--- a/src/Back.cpp
+++ b/src/Back.cpp
@@ -36,7 +36,7 @@
 	// Check if this is a valid bitmap file
 	if (bmp_header_buffer[0] != 0x4D42)	// 'MB' (we use hex here to prevent a compiler warning)
 	{
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 		// The original game forgets to close fp
 		fclose(fp);
 #endif
--- a/src/Bullet.cpp
+++ b/src/Bullet.cpp
@@ -1644,7 +1644,7 @@
 			if (bul->ani_no > 4)
 			{
 				bul->cond = 0;
-			#ifdef FIX_BUGS
+			#ifdef FIX_MAJOR_BUGS
 				return;	// The code below will use 'ani_no' to access 'rcLeft' and 'rcRight', even though it's now too high
 			#endif
 			}
@@ -2182,7 +2182,7 @@
 	if (bul->ani_no > 2)
 	{
 		bul->cond = 0;
-	#ifdef FIX_BUGS
+	#ifdef FIX_MAJOR_BUGS
 		return;	// Avoid accessing the RECT arrays with an out-of-bounds index
 	#endif
 	}
--- a/src/Caret.cpp
+++ b/src/Caret.cpp
@@ -105,7 +105,7 @@
 		if (++crt->ani_no > 3)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rcLeft' and 'rcRight', even though it's now too high
 		#endif
 		}
@@ -155,7 +155,7 @@
 			if (crt->ani_no > 3)
 			{
 				crt->cond = 0;
-			#ifdef FIX_BUGS
+			#ifdef FIX_MAJOR_BUGS
 				return;	// The code below will use 'ani_no' to access 'rect_left', even though it's now too high
 			#endif
 			}
@@ -173,7 +173,7 @@
 			if (crt->ani_no > 3)
 			{
 				crt->cond = 0;
-			#ifdef FIX_BUGS
+			#ifdef FIX_MAJOR_BUGS
 				return;	// The code below will use 'ani_no' to access 'rect_right', even though it's now too high
 			#endif
 			}
@@ -208,7 +208,7 @@
 		if (++crt->ani_no > 3)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 		#endif
 		}
@@ -242,7 +242,7 @@
 		if (++crt->ani_no > 2)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 		#endif
 		}
@@ -273,7 +273,7 @@
 	if (crt->ani_no > 6)
 	{
 		crt->cond = 0;
-	#ifdef FIX_BUGS
+	#ifdef FIX_MAJOR_BUGS
 		return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 	#endif
 	}
@@ -306,7 +306,7 @@
 		if (++crt->ani_no > 6)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rcLeft', even though it's now too high
 		#endif
 		}
@@ -432,7 +432,7 @@
 		if (++crt->ani_no > 6)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rcRight', even though it's now too high
 		#endif
 		}
@@ -456,7 +456,7 @@
 		if (++crt->ani_no > 1)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rcLeft', even though it's now too high
 		#endif
 		}
@@ -531,7 +531,7 @@
 		if (++crt->ani_no > 4)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 		#endif
 		}
@@ -557,7 +557,7 @@
 		if (++crt->ani_no > 3)
 		{
 			crt->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rcLeft', even though it's now too high
 		#endif
 		}
--- a/src/Draw.cpp
+++ b/src/Draw.cpp
@@ -273,7 +273,7 @@
 	surf[surf_no]->SetColorKey(DDCKEY_SRCBLT, &ddcolorkey);
 	surf[surf_no]->SetClipper(clipper);
 
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	DeleteObject(handle);
 #endif
 
@@ -414,7 +414,7 @@
 	surf[surf_no]->SetColorKey(DDCKEY_SRCBLT, &ddcolorkey);
 	surf[surf_no]->SetClipper(clipper);
 
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	DeleteObject(handle);
 #endif
 
--- a/src/Ending.cpp
+++ b/src/Ending.cpp
@@ -249,7 +249,7 @@
 	fread(Credit.pData, 1, Credit.size, fp);
 	EncryptionBinaryData2((unsigned char*)Credit.pData, Credit.size);
 
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	// The original game forgot to close the file
 	fclose(fp);
 #endif
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -560,7 +560,7 @@
 			ActBullet();
 			ActCaret();
 			MoveFrame3();
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 			// ActFlash uses frame_x and frame_y uninitialised
 			GetFramePosition(&frame_x, &frame_y);
 #endif
--- a/src/Input.cpp
+++ b/src/Input.cpp
@@ -151,7 +151,7 @@
 	directinput_objects->device = _joystick;
 
 	char string[0x100];
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	sprintf(string, "DeviceGUID = %08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", lpddi->guidInstance.Data1, lpddi->guidInstance.Data2, lpddi->guidInstance.Data3, lpddi->guidInstance.Data4[0], lpddi->guidInstance.Data4[1], lpddi->guidInstance.Data4[2], lpddi->guidInstance.Data4[3], lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]);
 #else
 	sprintf(string, "DeviceGUID = %x\n", lpddi->guidInstance);	// Tries to print a struct as an int
--- a/src/MycParam.cpp
+++ b/src/MycParam.cpp
@@ -110,7 +110,7 @@
 #ifdef FIX_BUGS
 	if (!(g_GameFlags & 2))
 #else
-	// I'm preeeetty sure this is a typo. The Linux port optimised it out.
+	// I'm preeeetty sure this is a typo. The Linux port optimised this entire check out.
 	if (!(g_GameFlags | 2))
 #endif
 		return;
@@ -272,7 +272,7 @@
 
 	int lv = gArmsData[gSelectedArms].level - 1;
 
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	// When the player has no weapons, the default level is 0, which becomes -1.
 	// Catch it, and set it to 0 instead, so the following array-accesses aren't
 	// out-of-bounds.
--- a/src/NpChar.cpp
+++ b/src/NpChar.cpp
@@ -70,7 +70,7 @@
 	fread(code, 1, 4, fp);
 	if (memcmp(code, gPassPixEve, 3) != 0)
 	{
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 		// The original game forgot to close the file here
 		fclose(fp);
 #endif
--- a/src/NpcAct000.cpp
+++ b/src/NpcAct000.cpp
@@ -59,7 +59,7 @@
 		if (npc->xm < -0x600)
 			npc->xm = -0x600;
 #else
-		// Limit speed (except pixel applied it to the X position)
+		// Limit speed (except Pixel applied it to the X position)
 		if (npc->x < -0x600)
 			npc->x = -0x600;
 #endif
--- a/src/NpcAct120.cpp
+++ b/src/NpcAct120.cpp
@@ -590,7 +590,7 @@
 		if (++npc->ani_no > 2)
 		{
 			npc->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rcH' and 'rcV', even though it's now too high
 		#endif
 		}
@@ -656,7 +656,7 @@
 	if (++npc->ani_no > 4)
 	{
 		npc->cond = 0;
-	#ifdef FIX_BUGS
+	#ifdef FIX_MAJOR_BUGS
 		return;	// The code below will use 'ani_no' to access 'rcLeft' and co., even though it's now too high
 	#endif
 	}
@@ -717,7 +717,7 @@
 		if (++npc->ani_no > 2)
 		{
 			npc->cond = 0;
-		#ifdef FIX_BUGS
+		#ifdef FIX_MAJOR_BUGS
 			return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 		#endif
 		}
--- a/src/NpcAct140.cpp
+++ b/src/NpcAct140.cpp
@@ -753,7 +753,7 @@
 			{
 				SetDestroyNpChar(npc->x, npc->y, 0x1000, 8);
 				npc->cond = 0;
-			#ifdef FIX_BUGS
+			#ifdef FIX_MAJOR_BUGS
 				return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 			#endif
 			}
--- a/src/NpcAct180.cpp
+++ b/src/NpcAct180.cpp
@@ -1429,7 +1429,7 @@
 	if (npc->ani_no > 4)
 	{
 		npc->cond = 0;
-	#ifdef FIX_BUGS
+	#ifdef FIX_MAJOR_BUGS
 		return;	// The code below will use 'ani_no' to access 'rect', even though it's now too high
 	#endif
 	}
--- a/src/Organya.cpp
+++ b/src/Organya.cpp
@@ -212,9 +212,9 @@
 
 			if (hr != DS_OK)
 			{
-#ifdef FIX_BUGS
+			#ifdef FIX_MAJOR_BUGS
 				free(wp);	// The updated Organya source code includes this fix
-#endif
+			#endif
 				return FALSE;
 			}
 
--- a/src/Sound.cpp
+++ b/src/Sound.cpp
@@ -40,10 +40,10 @@
 	if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK)
 	{
 		lpDS = NULL;
-#ifndef FIX_BUGS
+	#ifndef FIX_BUGS
 		// This makes absolutely no sense here
 		StartOrganya(lpDS, "Org\\Wave.dat");
-#endif
+	#endif
 		return FALSE;
 	}
 
@@ -165,7 +165,7 @@
 	for (i = 0; i < 58; i++)
 		fread(&check_box[i], sizeof(char), 1, fp);	// Holy hell, this is inefficient
 
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	// The original code forgets to close 'fp'
 	if (check_box[0] != 'R' || check_box[1] != 'I' || check_box[2] != 'F' || check_box[3] != 'F')
 	{
@@ -186,7 +186,7 @@
 	DWORD *wp;
 	wp = (DWORD*)malloc(file_size);	// ファイルのワークスペースを作る (Create a file workspace)
 
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 	if (wp == NULL)
 	{
 		fclose(fp);
@@ -211,7 +211,7 @@
 
 	if (lpDS->CreateSoundBuffer(&dsbd, &lpSECONDARYBUFFER[no], NULL) != DS_OK)
 	{
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 		free(wp);	// The updated Organya source code includes this fix
 #endif
 		return FALSE;	
@@ -225,7 +225,7 @@
 
 	if (hr != DS_OK)
 	{
-#ifdef FIX_BUGS
+#ifdef FIX_MAJOR_BUGS
 		free(wp);	// The updated Organya source code includes this fix
 #endif
 		return FALSE;
--- a/src/TextScr.cpp
+++ b/src/TextScr.cpp
@@ -678,7 +678,7 @@
 						x = GetTextScriptNo(gTS.p_read + 9);
 
 						gNumberTextScript[0] = x;
-					#ifndef FIX_BUGS
+					#ifndef FIX_MAJOR_BUGS
 						// z is uninitialised. Probably a leftover from copypasting this from elsewhere.
 						gNumberTextScript[1] = z;
 					#endif
@@ -898,7 +898,7 @@
 						x = GetTextScriptNo(gTS.p_read + 4);
 						z = GetTextScriptNo(gTS.p_read + 9);
 
-					#ifdef FIX_BUGS
+					#ifdef FIX_MAJOR_BUGS
 						// Some versions of the Waterway TSC script contain a bug:
 						//  <FLJ850:0111
 						// This command *should* be...
@@ -1007,7 +1007,7 @@
 					}
 					else if (IS_COMMAND('S','P','S'))
 					{
-					#ifdef FIX_BUGS
+					#ifdef FIX_MAJOR_BUGS
 						SetNoise(2, 0);
 					#else
 						// x is not initialised. This bug isn't too bad, since that parameter's not used when the first one is set to 2, but still.