From 96b72f2e336276ff62390c803d8ab62819093c75 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Sat, 12 Apr 2008 21:36:10 +0000
Subject: [PATCH] - Changed the internal Timidity player so that it uses
 timidity_mastervolume   because it has the same sound volume issues as the
 external one. - Replaced use of stdio in Timidity with FileReader and added
 the option to read   from the lump directory. If the main config file is
 inside the lump directory   it will assume that everything else is as well.
 If it is a real file it will be   assumed that the rest is real files as
 well. - Fixed: None of the error returns in Timidity::read_config_file closed
 the file being read.

SVN r906 (trunk)
---
 docs/rh-log.txt                         |   7 ++
 src/files.cpp                           |  31 +++++--
 src/files.h                             |   3 +-
 src/sound/i_musicinterns.h              |   6 ++
 src/sound/music_midistream.cpp          |   9 ++
 src/sound/music_timidity_mididevice.cpp |  17 +++-
 src/timidity/common.cpp                 | 117 ++++++++++++------------
 src/timidity/instrum.cpp                |  38 ++++----
 src/timidity/timidity.cpp               |  82 +++++++++++++----
 src/timidity/timidity.h                 |  18 ++--
 10 files changed, 214 insertions(+), 114 deletions(-)

diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index 096a60e8db..4a67740f1d 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,11 @@
 April 12, 2008 (Changes by Graf Zahl)
+- Changed the internal Timidity player so that it uses timidity_mastervolume
+  because it has the same sound volume issues as the external one.
+- Replaced use of stdio in Timidity with FileReader and added the option to read
+  from the lump directory. If the main config file is inside the lump directory
+  it will assume that everything else is as well. If it is a real file it will be
+  assumed that the rest is real files as well.
+- Fixed: None of the error returns in read_config_file closed the file being read.
 - Added Martin Howe's morph system update.
 - Added support for defining composite textures in HIRESTEX. It is not fully tested
   and right now can't do much more than the old TEXTUREx method.
diff --git a/src/files.cpp b/src/files.cpp
index 80d966acf2..fd017658ee 100644
--- a/src/files.cpp
+++ b/src/files.cpp
@@ -46,7 +46,7 @@
 //==========================================================================
 
 FileReader::FileReader ()
-: File(NULL), Length(0), CloseOnDestruct(false)
+: File(NULL), Length(0), StartPos(0), CloseOnDestruct(false)
 {
 }
 
@@ -59,13 +59,10 @@ FileReader::FileReader (const FileReader &other, long length)
 FileReader::FileReader (const char *filename)
 : File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false)
 {
-	File = fopen (filename, "rb");
-	if (File == NULL)
+	if (!Open(filename))
 	{
 		I_Error ("Could not open %s", filename);
 	}
-	CloseOnDestruct = true;
-	Length = CalcFileLen();
 }
 
 FileReader::FileReader (FILE *file)
@@ -89,6 +86,16 @@ FileReader::~FileReader ()
 	}
 }
 
+bool FileReader::Open (const char *filename)
+{
+	File = fopen (filename, "rb");
+	if (File == NULL) return false;
+	CloseOnDestruct = true;
+	Length = CalcFileLen();
+	return true;
+}
+
+
 void FileReader::ResetFilePtr ()
 {
 	FilePos = ftell (File);
@@ -150,16 +157,26 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len)
 	if (len <= 0) return NULL;
 
 	char *p = strbuf;
-	while (len > 1 && bufptr[FilePos] != 0)
+	while (len > 1)
 	{
+		if (bufptr[FilePos] == 0)
+		{
+			FilePos++;
+			break;
+		}
 		if (bufptr[FilePos] != '\r')
 		{
 			*p++ = bufptr[FilePos];
 			len--;
-			if (bufptr[FilePos] == '\n') break;
+			if (bufptr[FilePos] == '\n') 
+			{
+				FilePos++;
+				break;
+			}
 		}
 		FilePos++;
 	}
+	if (p==strbuf) return NULL;
 	*p++=0;
 	return strbuf;
 }
diff --git a/src/files.h b/src/files.h
index 5786169109..5b9d79433d 100644
--- a/src/files.h
+++ b/src/files.h
@@ -9,9 +9,11 @@
 class FileReader
 {
 public:
+	FileReader ();
 	FileReader (const char *filename);
 	FileReader (FILE *file);
 	FileReader (FILE *file, long length);
+	bool Open (const char *filename);
 	virtual ~FileReader ();
 
 	virtual long Tell () const;
@@ -62,7 +64,6 @@ public:
 
 protected:
 	FileReader (const FileReader &other, long length);
-	FileReader ();
 
 	char *GetsFromBuffer(const char * bufptr, char *strbuf, int len);
 
diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h
index 2a3b24c114..c1f04c3851 100644
--- a/src/sound/i_musicinterns.h
+++ b/src/sound/i_musicinterns.h
@@ -26,6 +26,9 @@ void I_ShutdownMusicWin32 ();
 
 extern float relative_volume;
 
+EXTERN_CVAR (Float, timidity_mastervolume)
+
+
 // The base music class. Everything is derived from this --------------------
 
 class MusInfo
@@ -119,6 +122,7 @@ public:
 	virtual bool Pause(bool paused) = 0;
 	virtual bool NeedThreadedCallback() = 0;
 	virtual void PrecacheInstruments(const WORD *instruments, int count);
+	virtual void TimidityVolumeChanged() {}
 };
 
 // WinMM implementation of a MIDI output device -----------------------------
@@ -237,6 +241,7 @@ public:
 	bool Pause(bool paused);
 	bool NeedThreadedCallback();
 	void PrecacheInstruments(const WORD *instruments, int count);
+	void TimidityVolumeChanged();
 
 protected:
 	static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
@@ -277,6 +282,7 @@ public:
 	~MIDIStreamer();
 
 	void MusicVolumeChanged();
+	void TimidityVolumeChanged();
 	void Play(bool looping);
 	void Pause();
 	void Resume();
diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp
index 8b9bfa8645..3f9d454dfb 100644
--- a/src/sound/music_midistream.cpp
+++ b/src/sound/music_midistream.cpp
@@ -419,6 +419,15 @@ void MIDIStreamer::MusicVolumeChanged()
 	}
 }
 
+void MIDIStreamer::TimidityVolumeChanged()
+{
+	if (MIDI != NULL)
+	{
+		MIDI->TimidityVolumeChanged();
+	}
+}
+
+
 //==========================================================================
 //
 // MIDIStreamer :: OutputVolume
diff --git a/src/sound/music_timidity_mididevice.cpp b/src/sound/music_timidity_mididevice.cpp
index 98b7a09076..e20a4ed03c 100644
--- a/src/sound/music_timidity_mididevice.cpp
+++ b/src/sound/music_timidity_mididevice.cpp
@@ -205,7 +205,7 @@ int TimidityMIDIDevice::Resume()
 {
 	if (!Started)
 	{
-		if (Stream->Play(true, 1, false))
+		if (Stream->Play(true, timidity_mastervolume, false))
 		{
 			Started = true;
 			return 0;
@@ -326,6 +326,21 @@ bool TimidityMIDIDevice::NeedThreadedCallback()
 	return false;
 }
 
+
+//==========================================================================
+//
+// TimidityMIDIDevice :: TimidityVolumeChanged
+//
+//==========================================================================
+
+void TimidityMIDIDevice::TimidityVolumeChanged()
+{
+	if (Stream != NULL)
+	{
+		Stream->SetVolume(timidity_mastervolume);
+	}
+}
+
 //==========================================================================
 //
 // TimidityMIDIDevice :: Pause
diff --git a/src/timidity/common.cpp b/src/timidity/common.cpp
index baf74b74a1..f306abfb89 100644
--- a/src/timidity/common.cpp
+++ b/src/timidity/common.cpp
@@ -29,34 +29,32 @@
 #include "zstring.h"
 #include "tarray.h"
 #include "i_system.h"
+#include "w_wad.h"
+#include "files.h"
+#include "cmdlib.h"
 
 namespace Timidity
 {
 
-/* I guess "rb" should be right for any libc */
-#define OPEN_MODE "rb"
-
-FString current_filename;
-
 static TArray<FString> PathList;
 
-/* Try to open a file for reading. */
-static FILE *try_to_open(const char *name, int decompress, int noise_mode)
+FString BuildPath(FString base, const char *name)
 {
-	FILE *fp;
-
-	fp = fopen(name, OPEN_MODE);
-
-	if (!fp)
-		return 0;
-
-	return fp;
+	FString current;
+	if (base.IsNotEmpty())
+	{
+		current = base;
+		if (current[current.Len() - 1] != '/') current += '/';
+	}
+	current += name;
+	return current;
 }
 
 /* This is meant to find and open files for reading. */
-FILE *open_file(const char *name, int decompress, int noise_mode)
+FileReader *open_filereader(const char *name, int open, int *plumpnum)
 {
-	FILE *fp;
+	FileReader *fp;
+	FString current_filename;
 
 	if (!name || !(*name))
 	{
@@ -65,64 +63,56 @@ FILE *open_file(const char *name, int decompress, int noise_mode)
 
 	/* First try the given name */
 	current_filename = name;
+	FixPathSeperator(current_filename);
 
-	if ((fp = try_to_open(current_filename, decompress, noise_mode)))
-		return fp;
+	int lumpnum = Wads.CheckNumForFullName(current_filename);
 
-#ifdef ENOENT
-	if (noise_mode && (errno != ENOENT))
+	if (open != OM_FILE)
 	{
-		return 0;
+		if (lumpnum >= 0)
+		{
+			fp = Wads.ReopenLumpNum(lumpnum);
+			if (plumpnum) *plumpnum = lumpnum;
+			return fp;
+		}
+		if (open == OM_LUMP)	// search the path list when not loading the main config
+		{
+			for (unsigned int plp = PathList.Size(); plp-- != 0; )
+			{ /* Try along the path then */
+				current_filename = BuildPath(PathList[plp], name);
+				lumpnum = Wads.CheckNumForFullName(current_filename);
+				if (lumpnum >= 0)
+				{
+					fp = Wads.ReopenLumpNum(lumpnum);
+					if (plumpnum) *plumpnum = lumpnum;
+					return fp;
+				}
+			}
+			return NULL;
+		}
 	}
-#endif
+	if (plumpnum) *plumpnum = -1;
 
-	if (name[0] != '/'
-#ifdef _WIN32
-		&& name[0] != '\\'
-#endif
-	)
+
+	fp = new FileReader;
+	if (fp->Open(current_filename)) return fp;
+
+	if (name[0] != '/')
 	{
 		for (unsigned int plp = PathList.Size(); plp-- != 0; )
 		{ /* Try along the path then */
-			current_filename = "";
-			if (PathList[plp].IsNotEmpty())
-			{
-				current_filename = PathList[plp];
-				if (current_filename[current_filename.Len() - 1] != '/'
-#ifdef _WIN32
-					&& current_filename[current_filename.Len() - 1] != '\\'
-#endif
-					)
-				{
-					current_filename += '/';
-				}
-			}
-			current_filename += name;
-			if ((fp = try_to_open(current_filename, decompress, noise_mode)))
-				return fp;
-			if (noise_mode && (errno != ENOENT))
-			{
-				return 0;
-			}
+			current_filename = BuildPath(PathList[plp], name);
+			if (fp->Open(current_filename)) return fp;
 		}
 	}
+	delete fp;
 
 	/* Nothing could be opened. */
 	current_filename = "";
-	return 0;
+	return NULL;
 }
 
-/* This closes files opened with open_file */
-void close_file(FILE *fp)
-{
-	fclose(fp);
-}
 
-/* This is meant for skipping a few bytes in a file or fifo. */
-void skip(FILE *fp, size_t len)
-{
-	fseek(fp, (long)len, SEEK_CUR);
-}
 
 /* This'll allocate memory or die. */
 void *safe_malloc(size_t count)
@@ -146,7 +136,14 @@ void *safe_malloc(size_t count)
 /* This adds a directory to the path list */
 void add_to_pathlist(const char *s)
 {
-	PathList.Push(s);
+	FString copy = s;
+	FixPathSeperator(copy);
+	PathList.Push(copy);
+}
+
+void clear_pathlist()
+{
+	PathList.Clear();
 }
 
 }
diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp
index 700ae7b7e9..ee5fdf8689 100644
--- a/src/timidity/instrum.cpp
+++ b/src/timidity/instrum.cpp
@@ -30,6 +30,7 @@
 
 #include "timidity.h"
 #include "m_swap.h"
+#include "files.h"
 
 namespace Timidity
 {
@@ -42,6 +43,7 @@ ToneBank standard_tonebank, standard_drumset;
 
 /* This is only used for tracks that don't specify a program */
 int default_program = DEFAULT_PROGRAM;
+extern int openmode;
 
 
 static void free_instrument(Instrument *ip)
@@ -200,7 +202,7 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
 {
 	InstrumentLayer *lp, *lastlp, *headlp;
 	Instrument *ip;
-	FILE *fp;
+	FileReader *fp;
 	BYTE tmp[239];
 	int i,j;
 	bool noluck = false;
@@ -212,16 +214,16 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
 	if (!name) return 0;
 
 	/* Open patch file */
-	if ((fp = open_file(name, 1, OF_NORMAL)) == NULL)
+	if ((fp = open_filereader(name, openmode, NULL)) == NULL)
 	{
 		/* Try with various extensions */
 		FString tmp = name;
 		tmp += ".pat";
-		if ((fp = open_file(tmp, 1, OF_NORMAL)) == NULL)
+		if ((fp = open_filereader(tmp, openmode, NULL)) == NULL)
 		{
 #ifdef unix			// Windows isn't case-sensitive.
 			tmp.ToUpper();
-			if ((fp = open_file(tmp, 1, OF_NORMAL)) == NULL)
+			if ((fp = open_filereader(tmp, openmode, NULL)) == NULL)
 #endif
 			{
 				noluck = true;
@@ -240,12 +242,13 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
 	/* Read some headers and do cursory sanity checks. There are loads
 	of magic offsets. This could be rewritten... */
 
-	if ((239 != fread(tmp, 1, 239, fp)) ||
+	if ((239 != fp->Read(tmp, 239)) ||
 		(memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
 		memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
 													differences are */
 	{
 		cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
+		delete fp;
 		return 0;
 	}
 
@@ -289,12 +292,14 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
 	if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */
 	{
 		cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]);
+		delete fp;
 		return 0;
 	}
 
 	if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
 	{
 		cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]);
+		delete fp;
 		return 0;
 	}
 
@@ -394,13 +399,13 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
 				BYTE sf2delay;
 
 #define READ_CHAR(thing) \
-	if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \
+	if (1 != fp->Read(&tmpchar,1)) goto fail; \
 	thing = tmpchar;
 #define READ_SHORT(thing) \
-	if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \
+	if (2 != fp->Read(&tmpshort, 2)) goto fail; \
 	thing = LittleShort(tmpshort);
 #define READ_LONG(thing) \
-	if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \
+	if (4 != fp->Read(&tmplong, 4)) goto fail; \
 	thing = LittleLong(tmplong);
 
 				/*
@@ -427,9 +432,9 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
 				* Now: 1 delay
 				* 33	 reserved
 				*/
-				skip(fp, 7); /* Skip the wave name */
+				fp->Seek(7, SEEK_CUR);
 
-				if (1 != fread(&fractions, 1, 1, fp))
+				if (1 != fp->Read(&fractions, 1))
 				{
 fail:
 					cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
@@ -449,6 +454,7 @@ fail:
 					free(ip->left_sample);
 					free(ip);
 					free(lp);
+					delete fp;
 					return 0;
 				}
 
@@ -473,7 +479,7 @@ fail:
 				READ_LONG(sp->low_freq);
 				READ_LONG(sp->high_freq);
 				READ_LONG(sp->root_freq);
-				skip(fp, 2); /* Unused by GUS: Why have a "root frequency" and then "tuning"?? */
+				fp->Seek(2, SEEK_CUR); /* Unused by GUS: Why have a "root frequency" and then "tuning"?? */
 				sp->low_vel = 0;
 				sp->high_vel = 127;
 
@@ -503,7 +509,7 @@ fail:
 				}
 
 				/* envelope, tremolo, and vibrato */
-				if (18 != fread(tmp, 1, 18, fp)) goto fail; 
+				if (18 != fp->Read(tmp, 18)) goto fail; 
 
 				if (!tmp[13] || !tmp[14])
 				{
@@ -551,11 +557,11 @@ fail:
 					READ_SHORT(sample_volume);
 					READ_CHAR(sf2delay);
 					READ_CHAR(sp->exclusiveClass);
-					skip(fp, 32);
+					fp->Seek(32, SEEK_CUR);
 				}
 				else
 				{
-					skip(fp, 36);
+					fp->Seek(36, SEEK_CUR);
 					sample_volume = 0;
 					sf2delay = 0;
 
@@ -658,7 +664,7 @@ fail:
 				}
 				sp->data = (sample_t *)safe_malloc(sp->data_length + 1);
 
-				if (1 != fread(sp->data, sp->data_length, 1, fp))
+				if (sp->data_length != fp->Read(sp->data, sp->data_length))
 					goto fail;
 
 				convert_sample_data(sp, sp->data);
@@ -737,7 +743,7 @@ fail:
 	} /* end of vlayer loop */
 
 
-	close_file(fp);
+	delete fp;
 	return headlp;
 }
 
diff --git a/src/timidity/timidity.cpp b/src/timidity/timidity.cpp
index 51d6c1ebce..cdc6f5472d 100644
--- a/src/timidity/timidity.cpp
+++ b/src/timidity/timidity.cpp
@@ -29,6 +29,7 @@
 #include "cmdlib.h"
 #include "c_cvars.h"
 #include "i_system.h"
+#include "files.h"
 
 CVAR(String, timidity_config, CONFIG_FILE, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
 
@@ -38,17 +39,19 @@ namespace Timidity
 ToneBank *tonebank[MAXBANK], *drumset[MAXBANK];
 
 static FString def_instr_name;
+int openmode = OM_FILEORLUMP;
 
 
 #define MAXWORDS 10
 
-static int read_config_file(const char *name)
+static int read_config_file(const char *name, bool ismain)
 {
-	FILE *fp;
+	FileReader *fp;
 	char tmp[1024], *w[MAXWORDS], *cp;
 	ToneBank *bank = NULL;
 	int i, j, k, line = 0, words;
 	static int rcf_count = 0;
+	int lumpnum;
 
 	if (rcf_count > 50)
 	{
@@ -56,10 +59,25 @@ static int read_config_file(const char *name)
 		return (-1);
 	}
 
-	if (!(fp = open_file(name, 1, OF_VERBOSE)))
+	if (ismain) openmode = OM_FILEORLUMP;
+
+	if (!(fp = open_filereader(name, openmode, &lumpnum)))
 		return -1;
 
-	while (fgets(tmp, sizeof(tmp), fp))
+	if (ismain)
+	{
+		if (lumpnum > 0)
+		{
+			openmode = OM_LUMP;
+			clear_pathlist();	// when reading from a PK3 we won't want to use any external path
+		}
+		else
+		{
+			openmode = OM_FILE;
+		}
+	}
+
+	while (fp->Gets(tmp, sizeof(tmp)))
 	{
 		line++;
 		w[words = 0] = strtok(tmp, " \t\r\n\240");
@@ -177,6 +195,7 @@ static int read_config_file(const char *name)
 			if (words < 2)
 			{
 				Printf("%s: line %d: No directory given\n", name, line);
+				delete fp;
 				return -2;
 			}
 			for (i = 1; i < words; i++)
@@ -192,7 +211,7 @@ static int read_config_file(const char *name)
 			for (i=1; i<words; i++)
 			{
 				rcf_count++;
-				read_config_file(w[i]);
+				read_config_file(w[i], false);
 				rcf_count--;
 			}
 		}
@@ -201,6 +220,7 @@ static int read_config_file(const char *name)
 			if (words != 2)
 			{
 				Printf("%s: line %d: Must specify exactly one patch name\n", name, line);
+				delete fp;
 				return -2;
 			}
 			def_instr_name = w[1];
@@ -210,12 +230,14 @@ static int read_config_file(const char *name)
 			if (words < 2)
 			{
 				Printf("%s: line %d: No drum set number given\n", name, line);
+				delete fp;
 				return -2;
 			}
 			i = atoi(w[1]);
 			if (i < 0 || i > 127)
 			{
 				Printf("%s: line %d: Drum set must be between 0 and 127\n", name, line);
+				delete fp;
 				return -2;
 			}
 			if (drumset[i] == NULL)
@@ -229,12 +251,14 @@ static int read_config_file(const char *name)
 			if (words < 2)
 			{
 				Printf("%s: line %d: No bank number given\n", name, line);
+				delete fp;
 				return -2;
 			}
 			i = atoi(w[1]);
 			if (i < 0 || i > 127)
 			{
 				Printf("%s: line %d: Tone bank must be between 0 and 127\n", name, line);
+				delete fp;
 				return -2;
 			}
 			if (tonebank[i] == NULL)
@@ -248,17 +272,20 @@ static int read_config_file(const char *name)
 			if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
 			{
 				Printf("%s: line %d: syntax error\n", name, line);
+				delete fp;
 				return -2;
 			}
 			i = atoi(w[0]);
 			if (i < 0 || i > 127)
 			{
 				Printf("%s: line %d: Program must be between 0 and 127\n", name, line);
+				delete fp;
 				return -2;
 			}
 			if (bank == NULL)
 			{
 				Printf("%s: line %d: Must specify tone bank or drum set before assignment\n", name, line);
+				delete fp;
 				return -2;
 			}
 			bank->tone[i].name = w[1];
@@ -271,6 +298,7 @@ static int read_config_file(const char *name)
 				if (!(cp=strchr(w[j], '=')))
 				{
 					Printf("%s: line %d: bad patch option %s\n", name, line, w[j]);
+					delete fp;
 					return -2;
 				}
 				*cp++ = 0;
@@ -280,6 +308,7 @@ static int read_config_file(const char *name)
 					if ((k < 0 || k > MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
 					{
 						Printf("%s: line %d: amplification must be between  0 and %d\n", name, line, MAX_AMPLIFICATION);
+						delete fp;
 						return -2;
 					}
 					bank->tone[i].amp = k;
@@ -290,6 +319,7 @@ static int read_config_file(const char *name)
 					if ((k < 0 || k > 127) || (*cp < '0' || *cp > '9'))
 					{
 						Printf("%s: line %d: note must be between 0 and 127\n", name, line);
+						delete fp;
 						return -2;
 					}
 					bank->tone[i].note = k;
@@ -309,6 +339,7 @@ static int read_config_file(const char *name)
 					{
 						Printf("%s: line %d: panning must be left, right, "
 							"center, or between -100 and 100\n", name, line);
+						delete fp;
 						return -2;
 					}
 					bank->tone[i].pan = k;
@@ -322,6 +353,7 @@ static int read_config_file(const char *name)
 					else
 					{
 						Printf("%s: line %d: keep must be env or loop\n", name, line);
+						delete fp;
 						return -2;
 					}
 				}
@@ -336,24 +368,28 @@ static int read_config_file(const char *name)
 					else
 					{
 						Printf("%s: line %d: strip must be env, loop, or tail\n", name, line);
+						delete fp;
 						return -2;
 					}
 				}
 				else
 				{
 					Printf("%s: line %d: bad patch option %s\n", name, line, w[j]);
+					delete fp;
 					return -2;
 				}
 			}
 		}
 	}
+	/*
 	if (ferror(fp))
 	{
 		Printf("Can't read %s: %s\n", name, strerror(errno));
 		close_file(fp);
 		return -2;
 	}
-	close_file(fp);
+	*/
+	delete fp;
 	return 0;
 }
 
@@ -375,22 +411,18 @@ void FreeAll()
 	}
 }
 
-int LoadConfig()
+int LoadConfig(const char *filename)
 {
-	static bool set_initial_path = false;
-
-	if (!set_initial_path)
-	{
+	clear_pathlist();
 #ifdef _WIN32
-		add_to_pathlist("\\TIMIDITY");
-		add_to_pathlist(progdir);
+	add_to_pathlist("C:\\TIMIDITY");
+	add_to_pathlist("\\TIMIDITY");
+	add_to_pathlist(progdir);
 #else
-		add_to_pathlist("/usr/local/lib/timidity");
-		add_to_pathlist("/etc/timidity");
-		add_to_pathlist("/etc");
+	add_to_pathlist("/usr/local/lib/timidity");
+	add_to_pathlist("/etc/timidity");
+	add_to_pathlist("/etc");
 #endif
-		set_initial_path = true;
-	}
 
 	/* Some functions get aggravated if not even the standard banks are available. */
 	if (tonebank[0] == NULL)
@@ -399,7 +431,12 @@ int LoadConfig()
 		drumset[0] = new ToneBank;
 	}
 
-	return read_config_file(timidity_config);
+	return read_config_file(filename, true);
+}
+
+int LoadConfig()
+{
+	return LoadConfig(timidity_config);
 }
 
 Renderer::Renderer(float sample_rate)
@@ -508,10 +545,15 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
 
 void cmsg(int type, int verbosity_level, const char *fmt, ...)
 {
+	/*
+	va_list args;
+	va_start(args, fmt);
+	VPrintf(PRINT_HIGH, fmt, args);
+	msg.VFormat(fmt, args);
+	*/
 #ifdef _WIN32
 	char buf[1024];
 	va_list args;
-
 	va_start(args, fmt);
 	vsprintf(buf, fmt, args);
 	va_end(args);
diff --git a/src/timidity/timidity.h b/src/timidity/timidity.h
index 2a18aab66c..3470b656c0 100644
--- a/src/timidity/timidity.h
+++ b/src/timidity/timidity.h
@@ -23,6 +23,8 @@
 #include "doomtype.h"
 #include "zstring.h"
 
+class FileReader;
+
 namespace Timidity
 {
 
@@ -172,19 +174,16 @@ extern __inline__ double pow_x87_inline(double x,double y)
 common.h
 */
 
-extern FString current_filename;
+#define OM_FILEORLUMP 0
+#define OM_LUMP 1
+#define OM_FILE 2
 
-/* Noise modes for open_file */
-#define OF_SILENT	0
-#define OF_NORMAL	1
-#define OF_VERBOSE	2
-
-extern FILE *open_file(const char *name, int decompress, int noise_mode);
 extern void add_to_pathlist(const char *s);
-extern void close_file(FILE *fp);
-extern void skip(FILE *fp, size_t len);
+extern void clear_pathlist();
 extern void *safe_malloc(size_t count);
 
+FileReader *open_filereader(const char *name, int open, int *plumpnum);
+
 /*
 controls.h
 */
@@ -510,6 +509,7 @@ tables.h
 timidity.h
 */
 struct DLS_Data;
+int LoadConfig(const char *filename);
 extern int LoadConfig();
 extern void FreeAll();