From c15a08f6df5a7f2a4784d6ff946caa70845667c7 Mon Sep 17 00:00:00 2001
From: divverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Mon, 25 Apr 2016 13:01:25 +0000
Subject: [PATCH] Support darkplaces.opt from local files too.

If both are present, flags from both get prepended; the execution order is:
[attached darkplaces.opt] [local darkplaces.opt] [command-line flags]

Also added flags -noopt (don't parse darkplaces.opt) and -noselfpack (don't read attached pack).

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12256 d7cf8633-e32d-0410-b094-e92efae38249
---
 fs.c | 129 +++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 90 insertions(+), 39 deletions(-)

diff --git a/fs.c b/fs.c
index e682f6fa..f5df1f4a 100644
--- a/fs.c
+++ b/fs.c
@@ -1726,55 +1726,78 @@ static void FS_ListGameDirs(void)
 #endif
 */
 
+static void COM_InsertFlags(const char *buf) {
+	const char *p;
+	char *q;
+	const char **new_argv;
+	int i = 0;
+	int args_left = 256;
+	new_argv = (const char **)Mem_Alloc(fs_mempool, sizeof(*com_argv) * (com_argc + args_left + 2));
+	if(com_argc == 0)
+		new_argv[0] = "dummy";  // Can't really happen.
+	else
+		new_argv[0] = com_argv[0];
+	++i;
+	p = buf;
+	while(COM_ParseToken_Console(&p))
+	{
+		size_t sz = strlen(com_token) + 1; // shut up clang
+		if(i > args_left)
+			break;
+		q = (char *)Mem_Alloc(fs_mempool, sz);
+		strlcpy(q, com_token, sz);
+		new_argv[i] = q;
+		++i;
+	}
+	// Now: i <= args_left + 1.
+	if (com_argc >= 1)
+	{
+		memcpy((char *)(&new_argv[i]), &com_argv[1], sizeof(*com_argv) * (com_argc - 1));
+		i += com_argc - 1;
+	}
+	// Now: i <= args_left + (com_argc || 1).
+	new_argv[i] = NULL;
+	com_argv = new_argv;
+	com_argc = i;
+}
+
 /*
 ================
 FS_Init_SelfPack
 ================
 */
+static unsigned char *FS_SysLoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer);
 void FS_Init_SelfPack (void)
 {
 	PK3_OpenLibrary ();
 	fs_mempool = Mem_AllocPool("file management", 0, NULL);
-	if(com_selffd >= 0)
+
+	// Load darkplaces.opt from the FS.
+	if (!COM_CheckParm("-noopt"))
 	{
-		fs_selfpack = FS_LoadPackPK3FromFD(com_argv[0], com_selffd, true);
-		if(fs_selfpack)
+		char *buf = (char *) FS_SysLoadFile("darkplaces.opt", tempmempool, true, NULL);
+		if(buf)
+			COM_InsertFlags(buf);
+		Mem_Free(buf);
+	}
+
+	// Provide the SelfPack.
+	if (!COM_CheckParm("-noselfpack"))
+	{
+		if (com_selffd >= 0)
 		{
-			char *buf, *q;
-			const char *p;
-			FS_AddSelfPack();
-			buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
-			if(buf)
+			fs_selfpack = FS_LoadPackPK3FromFD(com_argv[0], com_selffd, true);
+			if(fs_selfpack)
 			{
-				const char **new_argv;
-				int i = 0;
-				int args_left = 256;
-				new_argv = (const char **)Mem_Alloc(fs_mempool, sizeof(*com_argv) * (com_argc + args_left + 2));
-				if(com_argc == 0)
-				{
-					new_argv[0] = "dummy";
-					com_argc = 1;
-				}
-				else
+				FS_AddSelfPack();
+				if (!COM_CheckParm("-noopt"))
 				{
-					memcpy((char *)(&new_argv[0]), &com_argv[0], sizeof(*com_argv) * com_argc);
+					char *buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
+					if(buf)
+						COM_InsertFlags(buf);
+					Mem_Free(buf);
 				}
-				p = buf;
-				while(COM_ParseToken_Console(&p))
-				{
-					size_t sz = strlen(com_token) + 1; // shut up clang
-					if(i >= args_left)
-						break;
-					q = (char *)Mem_Alloc(fs_mempool, sz);
-					strlcpy(q, com_token, sz);
-					new_argv[com_argc + i] = q;
-					++i;
-				}
-				new_argv[i+com_argc] = NULL;
-				com_argv = new_argv;
-				com_argc = com_argc + i;
 			}
-			Mem_Free(buf);
 		}
 	}
 }
@@ -3228,19 +3251,17 @@ void FS_Purge (qfile_t* file)
 
 /*
 ============
-FS_LoadFile
+FS_LoadAndCloseQFile
 
-Filename are relative to the quake directory.
+Loads full content of a qfile_t and closes it.
 Always appends a 0 byte.
 ============
 */
-unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+static unsigned char *FS_LoadAndCloseQFile (qfile_t *file, const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
 {
-	qfile_t *file;
 	unsigned char *buf = NULL;
 	fs_offset_t filesize = 0;
 
-	file = FS_OpenVirtualFile(path, quiet);
 	if (file)
 	{
 		filesize = file->real_length;
@@ -3265,6 +3286,36 @@ unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, f
 }
 
 
+/*
+============
+FS_LoadFile
+
+Filename are relative to the quake directory.
+Always appends a 0 byte.
+============
+*/
+unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+{
+	qfile_t *file = FS_OpenVirtualFile(path, quiet);
+	return FS_LoadAndCloseQFile(file, path, pool, quiet, filesizepointer);
+}
+
+
+/*
+============
+FS_SysLoadFile
+
+Filename are OS paths.
+Always appends a 0 byte.
+============
+*/
+static unsigned char *FS_SysLoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+{
+	qfile_t *file = FS_SysOpen(path, "rb", false);
+	return FS_LoadAndCloseQFile(file, path, pool, quiet, filesizepointer);
+}
+
+
 /*
 ============
 FS_WriteFile
-- 
2.39.5