(svn r5765) - Codechange: Fully unify the OS-specific FiosGet...List functions into fios.c, as well as FiosGetSavegameList and FiosGetScenarioList functions with the help of some callbacks.
authorDarkvater
Sat, 05 Aug 2006 00:47:32 +0000
changeset 4221 bb06fe8dcce2
parent 4220 86ca889037b3
child 4222 951fbf19b1ad
(svn r5765) - Codechange: Fully unify the OS-specific FiosGet...List functions into fios.c, as well as FiosGetSavegameList and FiosGetScenarioList functions with the help of some callbacks.
fios.c
hal.h
oldloader.c
os2.c
stdafx.h
unix.c
win32.c
--- a/fios.c	Sat Aug 05 00:16:24 2006 +0000
+++ b/fios.c	Sat Aug 05 00:47:32 2006 +0000
@@ -12,6 +12,7 @@
 #include "functions.h"
 #include "table/strings.h"
 #include "hal.h"
+#include "fios.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -26,6 +27,14 @@
 FiosItem *_fios_items;
 int _fios_count, _fios_alloc;
 
+/* OS-specific functions are taken from their respective files (win32/unix/os2 .c) */
+extern bool FiosIsRoot(const char *path);
+extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
+extern void FiosGetDrives(void);
+
+/* get the name of an oldstyle savegame */
+extern void GetOldSaveGameName(char *title, const char *path, const char *file);
+
 /**
  * Allocate a new FiosItem.
  * @return A pointer to the newly allocated FiosItem.
@@ -96,3 +105,193 @@
 {
 	return access(filename, 0) == 0;
 }
+
+typedef byte fios_getlist_callback_proc(int mode, const char *filename, const char *ext, char *title);
+
+/** Create a list of the files in a directory, according to some arbitrary rule.
+ *  @param num Will be filled with the amount of items.
+ *  @param mode The mode we are in. Some modes don't allow 'parent'.
+ *  @param callback The function that is called where you need to do the filtering.
+ *  @return Return the list of files. */
+static FiosItem *FiosGetFileList(int *num, int mode, fios_getlist_callback_proc *callback_proc)
+{
+	struct stat sb;
+	struct dirent *dirent;
+	DIR *dir;
+	FiosItem *fios;
+	int sort_start;
+
+	/* A parent directory link exists if we are not in the root directory */
+	if (!FiosIsRoot(_fios_path) && mode != SLD_NEW_GAME) {
+		fios = FiosAlloc();
+		fios->type = FIOS_TYPE_PARENT;
+		fios->mtime = 0;
+		ttd_strlcpy(fios->name, "..", lengthof(fios->name));
+		ttd_strlcpy(fios->title, ".. (Parent directory)", lengthof(fios->title));
+	}
+
+	/* Show subdirectories */
+	if (mode != SLD_NEW_GAME && (dir = opendir(_fios_path)) != NULL) {
+		while ((dirent = readdir(dir)) != NULL) {
+			/* found file must be directory, but not '.' or '..' */
+			if (FiosIsValidFile(_fios_path, dirent, &sb) && (sb.st_mode & S_IFDIR) &&
+				strcmp(dirent->d_name, ".") != 0 && strcmp(dirent->d_name, "..") != 0) {
+				fios = FiosAlloc();
+				fios->type = FIOS_TYPE_DIR;
+				fios->mtime = 0;
+				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
+				snprintf(fios->title, lengthof(fios->title), "%s" PATHSEP " (Directory)", FS2OTTD(dirent->d_name));
+				str_validate(fios->title);
+			}
+		}
+		closedir(dir);
+	}
+
+	/* Sort the subdirs always by name, ascending, remember user-sorting order */
+	{
+		byte order = _savegame_sort_order;
+		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
+		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
+		_savegame_sort_order = order;
+	}
+
+	/* This is where to start sorting for the filenames */
+	sort_start = _fios_count;
+
+	/* Show files */
+	dir = opendir(_fios_path);
+	if (dir != NULL) {
+		while ((dirent = readdir(dir)) != NULL) {
+			char fios_title[64];
+			char *t;
+			byte type;
+
+			if (!FiosIsValidFile(_fios_path, dirent, &sb) || !(sb.st_mode & S_IFREG)) continue;
+
+			/* File has no extension, skip it */
+			if ((t = strrchr(dirent->d_name, '.')) == NULL) continue;
+			fios_title[0] = '\0'; // reset the title;
+
+			type = callback_proc(mode, dirent->d_name, t, fios_title);
+			if (type != FIOS_TYPE_INVALID) {
+				fios = FiosAlloc();
+				fios->mtime = sb.st_mtime;
+				fios->type = type;
+				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
+
+				/* Some callbacks want to lookup the title of the file. Allow that.
+				 * If we just copy the title from the filename, strip the extension */
+				t = (fios_title[0] == '\0') ? *t = '\0', dirent->d_name : fios_title;
+				ttd_strlcpy(fios->title, FS2OTTD(t), lengthof(fios->title));
+				str_validate(fios->title);
+			}
+		}
+		closedir(dir);
+	}
+
+	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
+
+	/* Show drives */
+	if (mode != SLD_NEW_GAME) FiosGetDrives();
+
+	*num = _fios_count;
+	return _fios_items;
+}
+
+/**
+ * Callback for FiosGetFileList. It tells if a file is a savegame or not.
+ * @param mode Save/load mode.
+ * @param file Name of the file to check.
+ * @param ext A pointer to the extension identifier inside file
+ * @param title Buffer if a callback wants to lookup the title of the file
+ * @return a FIOS_TYPE_* type of the found file, FIOS_TYPE_INVALID if not a savegame
+ * @see FiosGetFileList
+ * @see FiosGetSavegameList
+ */
+static byte FiosGetSavegameListCallback(int mode, const char *file, const char *ext, char *title)
+{
+	/* Show savegame files
+	 * .SAV OpenTTD saved game
+	 * .SS1 Transport Tycoon Deluxe preset game
+	 * .SV1 Transport Tycoon Deluxe (Patch) saved game
+	 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game */
+	if (strcasecmp(ext, ".sav") == 0) return FIOS_TYPE_FILE;
+
+	if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) {
+		if (strcasecmp(ext, ".ss1") == 0 || strcasecmp(ext, ".sv1") == 0 ||
+				strcasecmp(ext, ".sv2") == 0) {
+			GetOldSaveGameName(title, _fios_path, file);
+			return FIOS_TYPE_OLDFILE;
+		}
+	}
+
+	return FIOS_TYPE_INVALID;
+}
+
+/**
+ * Get a list of savegames.
+ * @param mode Save/load mode.
+ * @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
+ * @see FiosGetFileList
+ */
+FiosItem *FiosGetSavegameList(int *num, int mode)
+{
+	static char *_fios_save_path = NULL;
+
+	if (_fios_save_path == NULL) {
+		_fios_save_path = malloc(MAX_PATH);
+		ttd_strlcpy(_fios_save_path, _path.save_dir, MAX_PATH);
+	}
+
+	_fios_path = _fios_save_path;
+
+	return FiosGetFileList(num, mode, &FiosGetSavegameListCallback);
+}
+
+/**
+ * Callback for FiosGetFileList. It tells if a file is a scenario or not.
+ * @param mode Save/load mode.
+ * @param file Name of the file to check.
+ * @param ext A pointer to the extension identifier inside file
+ * @param title Buffer if a callback wants to lookup the title of the file
+ * @return a FIOS_TYPE_* type of the found file, FIOS_TYPE_INVALID if not a scenario
+ * @see FiosGetFileList
+ * @see FiosGetScenarioList
+ */
+static byte FiosGetScenarioListCallback(int mode, const char *file, const char *ext, char *title)
+{
+	/* Show scenario files
+	 * .SCN OpenTTD style scenario file
+	 * .SV0 Transport Tycoon Deluxe (Patch) scenario
+	 * .SS0 Transport Tycoon Deluxe preset scenario */
+	if (strcasecmp(ext, ".scn") == 0) return FIOS_TYPE_SCENARIO;
+
+	if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO || mode == SLD_NEW_GAME) {
+		if (strcasecmp(ext, ".sv0") == 0 || strcasecmp(ext, ".ss0") == 0 ) {
+			GetOldSaveGameName(title, _fios_path, file);
+			return FIOS_TYPE_OLD_SCENARIO;
+		}
+	}
+
+	return FIOS_TYPE_INVALID;
+}
+
+/**
+ * Get a list of scenarios.
+ * @param mode Save/load mode.
+ * @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
+ * @see FiosGetFileList
+ */
+FiosItem *FiosGetScenarioList(int *num, int mode)
+{
+	static char *_fios_scn_path = NULL;
+
+	if (_fios_scn_path == NULL) {
+		_fios_scn_path = malloc(MAX_PATH);
+		ttd_strlcpy(_fios_scn_path, _path.scenario_dir, MAX_PATH);
+	}
+
+	_fios_path = _fios_scn_path;
+
+	return FiosGetFileList(num, mode, &FiosGetScenarioListCallback);
+}
--- a/hal.h	Sat Aug 05 00:16:24 2006 +0000
+++ b/hal.h	Sat Aug 05 00:47:32 2006 +0000
@@ -62,6 +62,7 @@
 	FIOS_TYPE_SCENARIO = 5,
 	FIOS_TYPE_OLD_SCENARIO = 6,
 	FIOS_TYPE_DIRECT = 7,
+	FIOS_TYPE_INVALID = 255,
 };
 
 
@@ -71,9 +72,7 @@
 int _saveload_mode;
 
 // get the name of an oldstyle savegame
-void GetOldSaveGameName(char *title, const char *file);
-// get the name of an oldstyle scenario
-void GetOldScenarioGameName(char *title, const char *file);
+void GetOldSaveGameName(char *title, const char *path, const char *file);
 
 // Get a list of savegames
 FiosItem *FiosGetSavegameList(int *num, int mode);
--- a/oldloader.c	Sat Aug 05 00:16:24 2006 +0000
+++ b/oldloader.c	Sat Aug 05 00:47:32 2006 +0000
@@ -1571,11 +1571,15 @@
 	return true;
 }
 
-void GetOldSaveGameName(char *title, const char *file)
+void GetOldSaveGameName(char *title, const char *path, const char *file)
 {
-	FILE *f = fopen(file, "rb");
-	title[0] = 0;
-	title[48] = 0;
+	char filename[MAX_PATH];
+	FILE *f;
+
+	snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, file);
+	f = fopen(filename, "rb");
+	title[0] = '\0';
+	title[48] = '\0';
 
 	if (f == NULL) return;
 
@@ -1583,8 +1587,3 @@
 
 	fclose(f);
 }
-
-void GetOldScenarioGameName(char *title, const char *file)
-{
-	GetOldSaveGameName(title, file);
-}
--- a/os2.c	Sat Aug 05 00:16:24 2006 +0000
+++ b/os2.c	Sat Aug 05 00:47:32 2006 +0000
@@ -25,273 +25,47 @@
 #include <i86.h>
 
 extern char *_fios_path;
-static char *_fios_save_path;
-static char *_fios_scn_path;
 extern FiosItem *_fios_items;
 extern int _fios_count, _fios_alloc;
 
-static void append_path(char *out, const char *path, const char *file)
+bool FioIsRoot(const char *path)
 {
-	if (path[2] == '\\' && path[3] == '\0') {
-		sprintf(out, "%s%s", path, file);
-	} else {
-		sprintf(out, "%s\\%s", path, file);
-	}
+	return path[3] == '\0';
 }
 
-// Get a list of savegames
-FiosItem *FiosGetSavegameList(int *num, int mode)
+void FiosGetDrives(void)
 {
 	FiosItem *fios;
-	DIR *dir;
-	struct dirent *dirent;
-	struct stat sb;
-	int sort_start;
-	char filename[MAX_PATH];
-
-	if (_fios_save_path == NULL) {
-		_fios_save_path = malloc(MAX_PATH);
-		strcpy(_fios_save_path, _path.save_dir);
-	}
-
-	_fios_path = _fios_save_path;
-
-	// Parent directory, only if not of the type C:\.
-	if (_fios_path[3] != '\0') {
-		fios = FiosAlloc();
-		fios->type = FIOS_TYPE_PARENT;
-		fios->mtime = 0;
-		strcpy(fios->name, "..");
-		strcpy(fios->title, ".. (Parent directory)");
-	}
-
-	// Show subdirectories first
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			append_path(filename, _fios_path, dirent->d_name);
-			if (!stat(filename, &sb) && S_ISDIR(sb.st_mode) &&
-					strcmp(dirent->d_name, ".") != 0 &&
-					strcmp(dirent->d_name, "..") != 0) {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DIR;
-				fios->mtime = 0;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-				snprintf(fios->title, lengthof(fios->title), "%s\\ (Directory)", FS2OTTD(dirent->d_name));
-				str_validate(fios->title);
-			}
-		}
-		closedir(dir);
-	}
+	unsigned disk, disk2, save, total;
 
-	{
-		/* XXX ugly global variables ... */
-		byte order = _savegame_sort_order;
-		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
-		_savegame_sort_order = order;
-	}
-
-	// this is where to start sorting
-	sort_start = _fios_count;
-
-	/* Show savegame files
-	 * .SAV OpenTTD saved game
-	 * .SS1 Transport Tycoon Deluxe preset game
-	 * .SV1 Transport Tycoon Deluxe (Patch) saved game
-	 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game
-	 */
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			char *t;
-
-			append_path(filename, _fios_path, dirent->d_name);
-			if (stat(filename, &sb) || S_ISDIR(sb.st_mode)) continue;
+	_dos_getdrive(&save); // save original drive
 
-			t = strrchr(dirent->d_name, '.');
-			if (t == NULL) continue;
-
-			if (strcasecmp(t, ".sav") == 0) { // OpenTTD
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_FILE;
-				fios->mtime = sb.st_mtime;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
+	/* get an available drive letter */
+	for (disk = 1;; disk++) {
+		_dos_setdrive(disk, &total);
+		if (disk >= total) return;
+		_dos_getdrive(&disk2);
 
-				*t = '\0'; // strip extension
-				ttd_strlcpy(fios->title, FS2OTTD(dirent->d_name), lengthof(fios->title));
-				str_validate(fios->title);
-			} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) {
-				if (strcasecmp(t, ".ss1") == 0 ||
-						strcasecmp(t, ".sv1") == 0 ||
-						strcasecmp(t, ".sv2") == 0) { // TTDLX(Patch)
-					fios = FiosAlloc();
-					fios->type = FIOS_TYPE_OLDFILE;
-					fios->mtime = sb.st_mtime;
-					ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-					GetOldSaveGameName(fios->title, filename);
-				}
-			}
+		if (disk == disk2) {
+			FiosItem *fios = FiosAlloc();
+			fios->type = FIOS_TYPE_DRIVE;
+			fios->mtime = 0;
+			snprintf(fios->name, lengthof(fios->name),  "%c:", 'A' + disk - 1);
+			ttd_strlcpy(fios->title, fios->name, lengthof(fios->title));
 		}
-		closedir(dir);
 	}
 
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
-
-	// Drives
-	{
-		uint save;
-		uint disk;
-		uint total;
-
-		/* save original drive */
-		_dos_getdrive(&save);
-
-		/* get available drive letters */
-		for (disk = 1; disk < 27; ++disk) {
-			uint disk2;
-
-			_dos_setdrive(disk, &total);
-			_dos_getdrive(&disk2);
-
-			if (disk == disk2) {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DRIVE;
-				sprintf(fios->name, "%c:", 'A' + disk - 1);
-				sprintf(fios->title, "%c:", 'A' + disk - 1);
-			}
-		}
-
-		_dos_setdrive(save, &total);
-	}
-
-	*num = _fios_count;
-	return _fios_items;
+	_dos_setdrive(save, &total); // restore the original drive
 }
 
-// Get a list of scenarios
-FiosItem *FiosGetScenarioList(int *num, int mode)
+bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
 {
-	FiosItem *fios;
-	DIR *dir;
-	struct dirent *dirent;
-	struct stat sb;
-	int sort_start;
 	char filename[MAX_PATH];
 
-	if (_fios_scn_path == NULL) {
-		_fios_scn_path = malloc(MAX_PATH);
-		strcpy(_fios_scn_path, _path.scenario_dir);
-	}
-
-	_fios_path = _fios_scn_path;
-
-	// Parent directory, only if not of the type C:\.
-	if (_fios_path[3] != '\0' && mode != SLD_NEW_GAME) {
-		fios = FiosAlloc();
-		fios->type = FIOS_TYPE_PARENT;
-		fios->mtime = 0;
-		strcpy(fios->title, ".. (Parent directory)");
-	}
-
-	// Show subdirectories first
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			append_path(filename, _fios_path, dirent->d_name);
-			if (!stat(filename, &sb) && S_ISDIR(sb.st_mode) &&
-					strcmp(dirent->d_name, ".") != 0 &&
-					strcmp(dirent->d_name, "..") != 0) {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DIR;
-				fios->mtime = 0;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-				snprintf(fios->title, lengthof(fios->title), "%s\\ (Directory)", FS2OTTD(dirent->d_name));
-				str_validate(fios->title);
-			}
-		}
-		closedir(dir);
-	}
-
-	{
-		/* XXX ugly global variables ... */
-		byte order = _savegame_sort_order;
-		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
-		_savegame_sort_order = order;
-	}
-
-	// this is where to start sorting
-	sort_start = _fios_count;
-
-	/* Show scenario files
-	 * .SCN OpenTTD style scenario file
-	 * .SV0 Transport Tycoon Deluxe (Patch) scenario
-	 * .SS0 Transport Tycoon Deluxe preset scenario
-	 */
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			char *t;
+	snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, ent->d_name);
+	if (stat(filename, sb) != 0) return false;
 
-			append_path(filename, _fios_path, dirent->d_name);
-			if (stat(filename, &sb) || S_ISDIR(sb.st_mode)) continue;
-
-			t = strrchr(dirent->d_name, '.');
-			if (t == NULL) continue;
-
-			if (strcasecmp(t, ".scn") == 0) { // OpenTTD
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_SCENARIO;
-				fios->mtime = sb.st_mtime;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-
-				*t = '\0'; // strip extension
-				ttd_strlcpy(fios->title, FS2OTTD(dirent->d_name), lengthof(fios->title));
-				str_validate(fios->title);
-			} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO ||
-					mode == SLD_NEW_GAME) {
-				if (strcasecmp(t, ".sv0") == 0 ||
-						strcasecmp(t, ".ss0") == 0) { // TTDLX(Patch)
-					fios = FiosAlloc();
-					fios->type = FIOS_TYPE_OLD_SCENARIO;
-					fios->mtime = sb.st_mtime;
-					GetOldScenarioGameName(fios->title, filename);
-					ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-				}
-			}
-		}
-		closedir(dir);
-	}
-
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
-
-	// Drives
-	if (mode != SLD_NEW_GAME) {
-		unsigned save, disk, disk2, total;
-
-		/* save original drive */
-		_dos_getdrive(&save);
-
-		/* get available drive letters */
-
-		for (disk = 1; disk < 27; ++disk) {
-			_dos_setdrive(disk, &total);
-			_dos_getdrive(&disk2);
-
-			if (disk == disk2) {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DRIVE;
-				sprintf(fios->name, "%c:", 'A' + disk - 1);
-				sprintf(fios->title, "%c:", 'A' + disk - 1);
-			}
-		}
-
-		_dos_setdrive(save, &total);
-	}
-
-	*num = _fios_count;
-	return _fios_items;
+	return (ent->d_name[0] != '.'); // hidden file
 }
 
 // Browse to
--- a/stdafx.h	Sat Aug 05 00:16:24 2006 +0000
+++ b/stdafx.h	Sat Aug 05 00:47:32 2006 +0000
@@ -174,8 +174,10 @@
 
 #if defined(UNIX)
 # define PATHSEP "/"
+# define PATHSEPCHAR '/'
 #else
 # define PATHSEP "\\"
+# define PATHSEPCHAR '\\'
 #endif
 
 typedef unsigned char byte;
--- a/unix.c	Sat Aug 05 00:16:24 2006 +0000
+++ b/unix.c	Sat Aug 05 00:47:32 2006 +0000
@@ -49,8 +49,6 @@
 	#endif
 #endif
 extern char *_fios_path;
-static char *_fios_save_path;
-static char *_fios_scn_path;
 extern FiosItem *_fios_items;
 extern int _fios_count, _fios_alloc;
 
@@ -68,208 +66,37 @@
 #define PATHTEMPLATE (__isroot ? "%s:%s" : "%s/%s")
 #endif
 
-// Get a list of savegames
-FiosItem *FiosGetSavegameList(int *num, int mode)
+bool FiosIsRoot(const char *path)
 {
-	FiosItem *fios;
-	DIR *dir;
-	struct dirent *dirent;
-	struct stat sb;
-	int sort_start;
+#if !defined(__MORPHOS__) && !defined(__AMIGAOS__)
+	return path[1] == '\0';
+#else
+	/* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
+	const char *s = strchr(path, ':');
+	return s[1] == '\0';
+#endif
+}
+
+void FiosGetDrives(void)
+{
+	return;
+}
+
+bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
+{
 	char filename[MAX_PATH];
 
-	if (_fios_save_path == NULL) {
-		_fios_save_path = malloc(MAX_PATH);
-		strcpy(_fios_save_path, _path.save_dir);
-	}
-
-	_fios_path = _fios_save_path;
-
-	// Parent directory, only if not in root already.
-	if (!ISROOT(_fios_path)) {
-		fios = FiosAlloc();
-		fios->type = FIOS_TYPE_PARENT;
-		fios->mtime = 0;
-		strcpy(fios->name, "..");
-		strcpy(fios->title, ".. (Parent directory)");
-	}
-
-	// Show subdirectories first
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			snprintf(filename, lengthof(filename), PATHTEMPLATE,
-				_fios_path, dirent->d_name);
-			if (!stat(filename, &sb) && S_ISDIR(sb.st_mode) &&
-					dirent->d_name[0] != '.') {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DIR;
-				fios->mtime = 0;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-				snprintf(fios->title, lengthof(fios->title), "%s/ (Directory)", FS2OTTD(dirent->d_name));
-				str_validate(fios->title);
-			}
-		}
-		closedir(dir);
-	}
-
-	{
-		/* XXX ugly global variables ... */
-		byte order = _savegame_sort_order;
-		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
-		_savegame_sort_order = order;
-	}
-
-	// this is where to start sorting
-	sort_start = _fios_count;
-
-	/* Show savegame files
-	 * .SAV OpenTTD saved game
-	 * .SS1 Transport Tycoon Deluxe preset game
-	 * .SV1 Transport Tycoon Deluxe (Patch) saved game
-	 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game
-	 */
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			char *t;
-
-			snprintf(filename, lengthof(filename), PATHTEMPLATE,
-				_fios_path, dirent->d_name);
-			if (stat(filename, &sb) || S_ISDIR(sb.st_mode)) continue;
-
-			t = strrchr(dirent->d_name, '.');
-			if (t == NULL) continue;
-
-			if (strcasecmp(t, ".sav") == 0) { // OpenTTD
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_FILE;
-				fios->mtime = sb.st_mtime;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-
-				*t = '\0'; // strip extension
-				ttd_strlcpy(fios->title, FS2OTTD(dirent->d_name), lengthof(fios->title));
-				str_validate(fios->title);
-			} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) {
-				if (strcasecmp(t, ".ss1") == 0 ||
-						strcasecmp(t, ".sv1") == 0 ||
-						strcasecmp(t, ".sv2") == 0) { // TTDLX(Patch)
-					fios = FiosAlloc();
-					fios->type = FIOS_TYPE_OLDFILE;
-					fios->mtime = sb.st_mtime;
-					ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-					GetOldSaveGameName(fios->title, filename);
-				}
-			}
-		}
-		closedir(dir);
-	}
-
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
-	*num = _fios_count;
-	return _fios_items;
-}
+#if defined(__MORPHOS__) || defined(__AMIGAOS__)
+	/* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
+	if (FiosIsRoot(path)) {
+		snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name);
+	} else // XXX - only next line!
+#endif
+	snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, ent->d_name);
 
-// Get a list of scenarios
-// FIXME: Gross code duplication with FiosGetSavegameList()
-FiosItem *FiosGetScenarioList(int *num, int mode)
-{
-	FiosItem *fios;
-	DIR *dir;
-	struct dirent *dirent;
-	struct stat sb;
-	int sort_start;
-	char filename[MAX_PATH];
-
-	if (_fios_scn_path == NULL) {
-		_fios_scn_path = malloc(MAX_PATH);
-		strcpy(_fios_scn_path, _path.scenario_dir);
-	}
-
-	_fios_path = _fios_scn_path;
-
-	// Parent directory, only if not of the type C:\.
-	if ((!ISROOT(_fios_path)) && mode != SLD_NEW_GAME) {
-		fios = FiosAlloc();
-		fios->type = FIOS_TYPE_PARENT;
-		fios->mtime = 0;
-		strcpy(fios->title, ".. (Parent directory)");
-	}
-
-	// Show subdirectories first
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			snprintf(filename, lengthof(filename), PATHTEMPLATE,
-				_fios_path, dirent->d_name);
-			if (!stat(filename, &sb) && S_ISDIR(sb.st_mode) &&
-					dirent->d_name[0] != '.') {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DIR;
-				fios->mtime = 0;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-				snprintf(fios->title, lengthof(fios->title), "%s/ (Directory)", FS2OTTD(dirent->d_name));
-				str_validate(fios->title);
-			}
-		}
-		closedir(dir);
-	}
+	if (stat(filename, sb) != 0) return false;
 
-	{
-		/* XXX ugly global variables ... */
-		byte order = _savegame_sort_order;
-		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
-		_savegame_sort_order = order;
-	}
-
-	// this is where to start sorting
-	sort_start = _fios_count;
-
-	/* Show scenario files
-	 * .SCN OpenTTD style scenario file
-	 * .SV0 Transport Tycoon Deluxe (Patch) scenario
-	 * .SS0 Transport Tycoon Deluxe preset scenario
-	 */
-	dir = opendir(_fios_path);
-	if (dir != NULL) {
-		while ((dirent = readdir(dir)) != NULL) {
-			char *t;
-
-			snprintf(filename, lengthof(filename), PATHTEMPLATE, _fios_path, dirent->d_name);
-			if (stat(filename, &sb) || S_ISDIR(sb.st_mode)) continue;
-
-			t = strrchr(dirent->d_name, '.');
-			if (t == NULL) continue;
-
-			if (strcasecmp(t, ".scn") == 0) { // OpenTTD
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_SCENARIO;
-				fios->mtime = sb.st_mtime;
-				ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-
-				*t = '\0'; // strip extension
-				ttd_strlcpy(fios->title, FS2OTTD(dirent->d_name), lengthof(fios->title));
-				str_validate(fios->title);
-			} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO ||
-					mode == SLD_NEW_GAME) {
-				if (strcasecmp(t, ".sv0") == 0 ||
-						strcasecmp(t, ".ss0") == 0) { // TTDLX(Patch)
-					fios = FiosAlloc();
-					fios->type = FIOS_TYPE_OLD_SCENARIO;
-					fios->mtime = sb.st_mtime;
-					GetOldScenarioGameName(fios->title, filename);
-					ttd_strlcpy(fios->name, dirent->d_name, lengthof(fios->name));
-				}
-			}
-		}
-		closedir(dir);
-	}
-
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
-	*num = _fios_count;
-	return _fios_items;
+	return (ent->d_name[0] != '.'); // hidden file
 }
 
 // Browse to
--- a/win32.c	Sat Aug 05 00:16:24 2006 +0000
+++ b/win32.c	Sat Aug 05 00:47:32 2006 +0000
@@ -708,255 +708,39 @@
 }
 
 extern char *_fios_path;
-static char *_fios_save_path;
-static char *_fios_scn_path;
 extern FiosItem *_fios_items;
 extern int _fios_count, _fios_alloc;
 
-static HANDLE MyFindFirstFile(const char *path, const char *file, WIN32_FIND_DATA *fd)
+bool FiosIsRoot(const char *file)
 {
-	UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box
-	HANDLE h;
-	char paths[MAX_PATH];
-	const char *s = strrchr(path, '\\');
-
-	snprintf(paths, sizeof(paths), "%s%s%s", path, (s[1] == '\0') ? "" : "\\", file);
-	h = FindFirstFile(paths, fd);
-
-	SetErrorMode(sem); // restore previous setting
-	return h;
+	return file[3] == '\0'; // C:\...
 }
 
-// Get a list of savegames
-FiosItem *FiosGetSavegameList(int *num, int mode)
+void FiosGetDrives(void)
 {
-	WIN32_FIND_DATA fd;
-	HANDLE h;
-	FiosItem *fios;
-	int sort_start;
-
-	if (_fios_save_path == NULL) {
-		_fios_save_path = malloc(MAX_PATH);
-		strcpy(_fios_save_path, _path.save_dir);
-	}
-
-	_fios_path = _fios_save_path;
-
-	// Parent directory, only if not of the type C:\.
-	if (_fios_path[3] != '\0') {
-		fios = FiosAlloc();
-		fios->type = FIOS_TYPE_PARENT;
-		fios->mtime = 0;
-		strcpy(fios->name, "..");
-		strcpy(fios->title, ".. (Parent directory)");
-	}
-
-	// Show subdirectories first
-	h = MyFindFirstFile(_fios_path, "*.*", &fd);
-	if (h != INVALID_HANDLE_VALUE) {
-		do {
-			if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
-					strcmp(fd.cFileName, ".") != 0 &&
-					strcmp(fd.cFileName, "..") != 0) {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DIR;
-				fios->mtime = 0;
-				ttd_strlcpy(fios->name, fd.cFileName, lengthof(fios->name));
-				snprintf(fios->title, lengthof(fios->title), "%s\\ (Directory)", FS2OTTD(fd.cFileName));
-				str_validate(fios->title);
-			}
-		} while (FindNextFile(h, &fd));
-		FindClose(h);
-	}
-
-	{
-		/* XXX ugly global variables ... */
-		byte order = _savegame_sort_order;
-		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
-		_savegame_sort_order = order;
-	}
-
-	// this is where to start sorting
-	sort_start = _fios_count;
+	char drives[256];
+	const char *s;
 
-	/* Show savegame files
-	 * .SAV OpenTTD saved game
-	 * .SS1 Transport Tycoon Deluxe preset game
-	 * .SV1 Transport Tycoon Deluxe (Patch) saved game
-	 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game
-	 */
-	h = MyFindFirstFile(_fios_path, "*.*", &fd);
-	if (h != INVALID_HANDLE_VALUE) {
-		do {
-			char *t;
-
-			if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
-
-			t = strrchr(fd.cFileName, '.');
-			if (t == NULL) continue;
-
-			if (strcasecmp(t, ".sav") == 0) { // OpenTTD
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_FILE;
-				fios->mtime = *(uint64*)&fd.ftLastWriteTime;
-				ttd_strlcpy(fios->name, fd.cFileName, lengthof(fios->name));
-
-				*t = '\0'; // strip extension
-				ttd_strlcpy(fios->title, FS2OTTD(fd.cFileName), lengthof(fios->title));
-				str_validate(fios->title);
-			} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) {
-				if (strcasecmp(t, ".ss1") == 0 ||
-						strcasecmp(t, ".sv1") == 0 ||
-						strcasecmp(t, ".sv2") == 0) { // TTDLX(Patch)
-					char buf[MAX_PATH];
-
-					fios = FiosAlloc();
-					fios->type = FIOS_TYPE_OLDFILE;
-					fios->mtime = *(uint64*)&fd.ftLastWriteTime;
-					ttd_strlcpy(fios->name, fd.cFileName, lengthof(fios->name));
-					sprintf(buf, "%s\\%s", _fios_path, fd.cFileName);
-					GetOldSaveGameName(fios->title, buf);
-				}
-			}
-		} while (FindNextFile(h, &fd));
-		FindClose(h);
+	GetLogicalDriveStrings(sizeof(drives), drives);
+	for (s = drives; *s != '\0';) {
+		FiosItem *fios = FiosAlloc();
+		fios->type = FIOS_TYPE_DRIVE;
+		fios->mtime = 0;
+		snprintf(fios->name,  lengthof(fios->name),  "%c:", s[0]);
+		ttd_strlcpy(fios->title, fios->name, lengthof(fios->title));
+		while (*s++ != '\0');
 	}
-
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
-
-	// Drives
-	{
-		char drives[256];
-		const char *s;
-
-		GetLogicalDriveStrings(sizeof(drives), drives);
-		for (s = drives; *s != '\0';) {
-			fios = FiosAlloc();
-			fios->type = FIOS_TYPE_DRIVE;
-			sprintf(fios->name, "%c:", s[0]);
-			sprintf(fios->title, "%c:", s[0]);
-			while (*s++ != '\0') {}
-		}
-	}
-
-	*num = _fios_count;
-	return _fios_items;
 }
 
-// Get a list of scenarios
-FiosItem *FiosGetScenarioList(int *num, int mode)
+bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
 {
-	FiosItem *fios;
-	WIN32_FIND_DATA fd;
-	HANDLE h;
-	int sort_start;
-
-	if (_fios_scn_path == NULL) {
-		_fios_scn_path = malloc(MAX_PATH);
-		strcpy(_fios_scn_path, _path.scenario_dir);
-	}
-
-	_fios_path = _fios_scn_path;
-
-	// Parent directory, only if not of the type C:\.
-	if (_fios_path[3] != '\0' && mode != SLD_NEW_GAME) {
-		fios = FiosAlloc();
-		fios->type = FIOS_TYPE_PARENT;
-		fios->mtime = 0;
-		strcpy(fios->title, ".. (Parent directory)");
-	}
-
-	// Show subdirectories first
-	h = MyFindFirstFile(_fios_scn_path, "*.*", &fd);
-	if (h != INVALID_HANDLE_VALUE && mode != SLD_NEW_GAME) {
-		do {
-			if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
-					strcmp(fd.cFileName, ".") != 0 &&
-					strcmp(fd.cFileName, "..") != 0) {
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_DIR;
-				fios->mtime = 0;
-				ttd_strlcpy(fios->name, fd.cFileName, lengthof(fios->name));
-				snprintf(fios->title, lengthof(fios->title), "%s\\ (Directory)", FS2OTTD(fd.cFileName));
-				str_validate(fios->title);
-			}
-		} while (FindNextFile(h, &fd));
-		FindClose(h);
-	}
-
-	{
-		/* XXX ugly global variables ... */
-		byte order = _savegame_sort_order;
-		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
-		_savegame_sort_order = order;
-	}
-
-	// this is where to start sorting
-	sort_start = _fios_count;
+	const WIN32_FIND_DATA *fd = &ent->dir->fd;
+	if ((fd->dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0) return false;
 
-	/* Show scenario files
-	 * .SCN OpenTTD style scenario file
-	 * .SV0 Transport Tycoon Deluxe (Patch) scenario
-	 * .SS0 Transport Tycoon Deluxe preset scenario
-	 */
-	h = MyFindFirstFile(_fios_scn_path, "*.*", &fd);
-	if (h != INVALID_HANDLE_VALUE) {
-		do {
-			char *t;
-
-			if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;
-
-			t = strrchr(fd.cFileName, '.');
-			if (t == NULL) continue;
-
-			if (strcasecmp(t, ".scn") == 0) { // OpenTTD
-				fios = FiosAlloc();
-				fios->type = FIOS_TYPE_SCENARIO;
-				fios->mtime = *(uint64*)&fd.ftLastWriteTime;
-				ttd_strlcpy(fios->name, fd.cFileName, lengthof(fios->name));
-
-				*t = '\0'; // strip extension
-				ttd_strlcpy(fios->title, FS2OTTD(fd.cFileName), lengthof(fios->title));
-				str_validate(fios->title);
-			} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO ||
-					mode == SLD_NEW_GAME) {
-				if (strcasecmp(t, ".sv0") == 0 ||
-						strcasecmp(t, ".ss0") == 0) { // TTDLX(Patch)
-					char buf[MAX_PATH];
-
-					fios = FiosAlloc();
-					fios->type = FIOS_TYPE_OLD_SCENARIO;
-					fios->mtime = *(uint64*)&fd.ftLastWriteTime;
-					sprintf(buf, "%s\\%s", _fios_path, fd.cFileName);
-					GetOldScenarioGameName(fios->title, buf);
-					ttd_strlcpy(fios->name, fd.cFileName, lengthof(fios->name));
-				}
-			}
-		} while (FindNextFile(h, &fd));
-		FindClose(h);
-	}
-
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
-
-	// Drives
-	if (mode != SLD_NEW_GAME) {
-		char drives[256];
-		const char *s;
-
-		GetLogicalDriveStrings(sizeof(drives), drives);
-		for (s = drives; *s != '\0';) {
-			fios = FiosAlloc();
-			fios->type = FIOS_TYPE_DRIVE;
-			sprintf(fios->name, "%c:", s[0]);
-			sprintf(fios->title, "%c:", s[0]);
-			while (*s++ != '\0') {}
-		}
-	}
-
-	*num = _fios_count;
-	return _fios_items;
+	sb->st_size  = (fd->nFileSizeHigh * MAXDWORD+1) + fd->nFileSizeLow;
+	sb->st_mtime = (fd->ftLastWriteTime.dwHighDateTime * MAXDWORD+1) + fd->ftLastWriteTime.dwLowDateTime;
+	sb->st_mode  = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG;
+	return true;
 }
 
 // Browse to