Merge branch 'save_ext' into jgrpp

# Conflicts:
#	config.lib
#	src/saveload/extended_ver_sl.cpp
#	src/saveload/saveload.cpp
This commit is contained in:
Jonathan G Rennison
2016-09-07 22:02:57 +01:00
39 changed files with 777 additions and 477 deletions

View File

@@ -1291,7 +1291,12 @@ make_compiler_cflags() {
# remark #2259: non-pointer conversion from ... to ... may lose significant bits
flags="$flags -wd2259"
# Use c++0x mode so static_assert() is available
cxxflags="$cxxflags -std=c++0x"
cxxflags="$cxxflags -std=c++11"
fi
if [ $cc_version -lt 140 ]; then
log 1 "configure: error: ICC version is too old: `$1 -dumpversion`, minumum: 14.0"
exit 1
fi
if [ "$enable_lto" != "0" ]; then
@@ -1311,7 +1316,7 @@ make_compiler_cflags() {
# -W alone doesn't enable all warnings enabled by -Wall; on the other hand,
# -Weverything enables too many useless warnings that can't be disabled (as of 3.0)
flags="$flags -Wall -W"
flags="$flags -Wall -W -Wextra"
# warning: unused parameter '...'
flags="$flags -Wno-unused-parameter"
@@ -1352,6 +1357,14 @@ make_compiler_cflags() {
flags="$flags -Wno-unused-variable"
fi
if [ "$cc_version" -ge "33" ]; then
# clang completed C++11 support in version 3.3
flags="$flags -std=c++11"
else
log 1 "configure: error: clang version is too old: `$1 -v 2>&1 | head -n 1`, minumum: 3.3"
exit 1
fi
# rdynamic is used to get useful stack traces from crash reports.
ldflags="$ldflags -rdynamic"
else
@@ -1408,11 +1421,9 @@ make_compiler_cflags() {
flags="$flags -Wnon-virtual-dtor"
fi
if [ $cc_version -ge 403 ] && [ $cc_version -lt 407 ]; then
if [ $cc_version -ge 403 ] && [ $cc_version -lt 600 ]; then
# Use gnu++0x mode so static_assert() is available.
# Don't use c++0x, it breaks mingw (with gcc 4.4.0).
cxxflags="$cxxflags -std=gnu++0x -DDISABLE_OVERRIDE"
elif [ $cc_version -ge 407 ] && [ $cc_version -lt 600 ]; then
cxxflags="$cxxflags -std=gnu++11"
fi
@@ -1429,6 +1440,9 @@ make_compiler_cflags() {
cxxflags="$cxxflags -Wno-narrowing"
# Disable bogus 'attempt to free a non-heap object' warning
flags="$flags -Wno-free-nonheap-object"
else
log 1 "configure: error: GCC version is too old: `$1 -dumpversion`, minumum: 4.7"
exit 1
fi
if [ $cc_version -ge 409 ]; then

View File

@@ -592,6 +592,7 @@
<ClInclude Include="..\src\roadstop_base.h" />
<ClInclude Include="..\src\roadveh.h" />
<ClInclude Include="..\src\safeguards.h" />
<ClInclude Include="..\src\scope.h" />
<ClInclude Include="..\src\screenshot.h" />
<ClInclude Include="..\src\sdl.h" />
<ClInclude Include="..\src\sound\sdl_s.h" />

View File

@@ -1005,6 +1005,9 @@
<ClInclude Include="..\src\safeguards.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\scope.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\screenshot.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@@ -609,6 +609,7 @@
<ClInclude Include="..\src\roadstop_base.h" />
<ClInclude Include="..\src\roadveh.h" />
<ClInclude Include="..\src\safeguards.h" />
<ClInclude Include="..\src\scope.h" />
<ClInclude Include="..\src\screenshot.h" />
<ClInclude Include="..\src\sdl.h" />
<ClInclude Include="..\src\sound\sdl_s.h" />

View File

@@ -1005,6 +1005,9 @@
<ClInclude Include="..\src\safeguards.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\scope.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\screenshot.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@@ -1642,6 +1642,10 @@
RelativePath=".\..\src\safeguards.h"
>
</File>
<File
RelativePath=".\..\src\scope.h"
>
</File>
<File
RelativePath=".\..\src\screenshot.h"
>

View File

@@ -1639,6 +1639,10 @@
RelativePath=".\..\src\safeguards.h"
>
</File>
<File
RelativePath=".\..\src\scope.h"
>
</File>
<File
RelativePath=".\..\src\screenshot.h"
>

View File

@@ -332,6 +332,7 @@ road_type.h
roadstop_base.h
roadveh.h
safeguards.h
scope.h
screenshot.h
sdl.h
sound/sdl_s.h

View File

@@ -48,6 +48,38 @@
/* scriptfile handling */
static bool _script_running; ///< Script is running (used to abort execution when #ConReturn is encountered).
/** File list storage for the console, for caching the last 'ls' command. */
class ConsoleFileList : public FileList {
public:
ConsoleFileList() : FileList()
{
this->file_list_valid = false;
}
/** Declare the file storage cache as being invalid, also clears all stored files. */
void InvalidateFileList()
{
this->Clear();
this->file_list_valid = false;
}
/**
* (Re-)validate the file storage cache. Only makes a change if the storage was invalid, or if \a force_reload.
* @param Always reload the file storage cache.
*/
void ValidateFileList(bool force_reload = false)
{
if (force_reload || !this->file_list_valid) {
this->BuildFileList(FT_SAVEGAME, SLO_LOAD);
this->file_list_valid = true;
}
}
bool file_list_valid; ///< If set, the file list is valid.
};
static ConsoleFileList _console_file_list; ///< File storage cache for the console.
/* console command defines */
#define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
#define DEF_CONSOLE_HOOK(function) static ConsoleHookResult function(bool echo)
@@ -288,7 +320,7 @@ DEF_CONSOLE_CMD(ConSave)
char *filename = str_fmt("%s.sav", argv[1]);
IConsolePrint(CC_DEFAULT, "Saving map...");
if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
if (SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, SAVE_DIR) != SL_OK) {
IConsolePrint(CC_ERROR, "Saving map failed");
} else {
IConsolePrintF(CC_DEFAULT, "Map successfully saved to %s", filename);
@@ -317,42 +349,6 @@ DEF_CONSOLE_CMD(ConSaveConfig)
return true;
}
/**
* Get savegame file informations.
* @param file The savegame filename to return information about. Can be the actual name
* or a numbered entry into the filename list.
* @return FiosItem The information on the file.
*/
static const FiosItem *GetFiosItem(const char *file)
{
_saveload_mode = SLD_LOAD_GAME;
BuildFileList();
for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
if (strcmp(file, item->name) == 0) return item;
if (strcmp(file, item->title) == 0) return item;
}
/* If no name matches, try to parse it as number */
char *endptr;
int i = strtol(file, &endptr, 10);
if (file == endptr || *endptr != '\0') i = -1;
if (IsInsideMM(i, 0, _fios_items.Length())) return _fios_items.Get(i);
/* As a last effort assume it is an OpenTTD savegame and
* that the ".sav" part was not given. */
char long_file[MAX_PATH];
seprintf(long_file, lastof(long_file), "%s.sav", file);
for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
if (strcmp(long_file, item->name) == 0) return item;
if (strcmp(long_file, item->title) == 0) return item;
}
return NULL;
}
DEF_CONSOLE_CMD(ConLoad)
{
if (argc == 0) {
@@ -363,24 +359,21 @@ DEF_CONSOLE_CMD(ConLoad)
if (argc != 2) return false;
const char *file = argv[1];
const FiosItem *item = GetFiosItem(file);
_console_file_list.ValidateFileList();
const FiosItem *item = _console_file_list.FindItem(file);
if (item != NULL) {
switch (item->type) {
case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: {
if (GetAbstractFileType(item->type) == FT_SAVEGAME) {
_switch_mode = SM_LOAD_GAME;
SetFiosType(item->type);
strecpy(_file_to_saveload.name, FiosBrowseTo(item), lastof(_file_to_saveload.name));
strecpy(_file_to_saveload.title, item->title, lastof(_file_to_saveload.title));
break;
}
default: IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
_file_to_saveload.SetMode(item->type);
_file_to_saveload.SetName(FiosBrowseTo(item));
_file_to_saveload.SetTitle(item->title);
} else {
IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
}
} else {
IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
}
FiosFreeSavegameList();
return true;
}
@@ -395,7 +388,8 @@ DEF_CONSOLE_CMD(ConRemove)
if (argc != 2) return false;
const char *file = argv[1];
const FiosItem *item = GetFiosItem(file);
_console_file_list.ValidateFileList();
const FiosItem *item = _console_file_list.FindItem(file);
if (item != NULL) {
if (!FiosDelete(item->name)) {
IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
@@ -404,7 +398,7 @@ DEF_CONSOLE_CMD(ConRemove)
IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
}
FiosFreeSavegameList();
_console_file_list.InvalidateFileList();
return true;
}
@@ -417,13 +411,11 @@ DEF_CONSOLE_CMD(ConListFiles)
return true;
}
BuildFileList();
for (uint i = 0; i < _fios_items.Length(); i++) {
IConsolePrintF(CC_DEFAULT, "%d) %s", i, _fios_items[i].title);
_console_file_list.ValidateFileList(true);
for (uint i = 0; i < _console_file_list.Length(); i++) {
IConsolePrintF(CC_DEFAULT, "%d) %s", i, _console_file_list[i].title);
}
FiosFreeSavegameList();
return true;
}
@@ -438,7 +430,8 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
if (argc != 2) return false;
const char *file = argv[1];
const FiosItem *item = GetFiosItem(file);
_console_file_list.ValidateFileList(true);
const FiosItem *item = _console_file_list.FindItem(file);
if (item != NULL) {
switch (item->type) {
case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
@@ -450,7 +443,7 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
}
FiosFreeSavegameList();
_console_file_list.InvalidateFileList();
return true;
}
@@ -464,8 +457,8 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
}
/* XXX - Workaround for broken file handling */
FiosGetSavegameList(SLD_LOAD_GAME);
FiosFreeSavegameList();
_console_file_list.ValidateFileList(true);
_console_file_list.InvalidateFileList();
FiosGetDescText(&path, NULL);
IConsolePrint(CC_DEFAULT, path);

View File

@@ -256,6 +256,8 @@ public:
/**
* Get the number of items in the list.
*
* @return The number of items in the list.
*/
inline uint Length() const
{

View File

@@ -414,7 +414,7 @@ bool CrashLog::WriteSavegame(char *filename, const char *filename_last) const
seprintf(filename, filename_last, "%scrash.sav", _personal_dir);
/* Don't do a threaded saveload. */
return SaveOrLoad(filename, SL_SAVE, NO_DIRECTORY, false) == SL_OK;
return SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY, false) == SL_OK;
} catch (...) {
return false;
}

View File

@@ -14,6 +14,96 @@
#include "core/enum_type.hpp"
/** The different abstract types of files that the system knows about. */
enum AbstractFileType {
FT_NONE, ///< nothing to do
FT_SAVEGAME, ///< old or new savegame
FT_SCENARIO, ///< old or new scenario
FT_HEIGHTMAP, ///< heightmap file
FT_INVALID = 7, ///< Invalid or unknown file type.
FT_NUMBITS = 3, ///< Number of bits required for storing a #AbstractFileType value.
FT_MASK = (1 << FT_NUMBITS) - 1, ///< Bitmask for extracting an abstract file type.
};
/** Kinds of files in each #AbstractFileType. */
enum DetailedFileType {
/* Save game and scenario files. */
DFT_OLD_GAME_FILE, ///< Old save game or scenario file.
DFT_GAME_FILE, ///< Save game or scenario file.
/* Heightmap files. */
DFT_HEIGHTMAP_BMP, ///< BMP file.
DFT_HEIGHTMAP_PNG, ///< PNG file.
/* fios 'files' */
DFT_FIOS_DRIVE, ///< A drive (letter) entry.
DFT_FIOS_PARENT, ///< A parent directory entry.
DFT_FIOS_DIR, ///< A directory entry.
DFT_FIOS_DIRECT, ///< Direct filename.
DFT_INVALID = 255, ///< Unknown or invalid file.
};
/** Operation performed on the file. */
enum SaveLoadOperation {
SLO_CHECK, ///< Load file for checking and/or preview.
SLO_LOAD, ///< File is being loaded.
SLO_SAVE, ///< File is being saved.
SLO_INVALID, ///< Unknown file operation.
};
/**
* Construct an enum value for #FiosType as a combination of an abstract and a detailed file type.
* @param abstract Abstract file type (one of #AbstractFileType).
* @param detailed Detailed file type (one of #DetailedFileType).
*/
#define MAKE_FIOS_TYPE(abstract, detailed) ((abstract) | ((detailed) << FT_NUMBITS))
/**
* Elements of a file system that are recognized.
* Values are a combination of #AbstractFileType and #DetailedFileType.
* @see GetAbstractFileType GetDetailedFileType
*/
enum FiosType {
FIOS_TYPE_DRIVE = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_DRIVE),
FIOS_TYPE_PARENT = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_PARENT),
FIOS_TYPE_DIR = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_DIR),
FIOS_TYPE_DIRECT = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_DIRECT),
FIOS_TYPE_FILE = MAKE_FIOS_TYPE(FT_SAVEGAME, DFT_GAME_FILE),
FIOS_TYPE_OLDFILE = MAKE_FIOS_TYPE(FT_SAVEGAME, DFT_OLD_GAME_FILE),
FIOS_TYPE_SCENARIO = MAKE_FIOS_TYPE(FT_SCENARIO, DFT_GAME_FILE),
FIOS_TYPE_OLD_SCENARIO = MAKE_FIOS_TYPE(FT_SCENARIO, DFT_OLD_GAME_FILE),
FIOS_TYPE_PNG = MAKE_FIOS_TYPE(FT_HEIGHTMAP, DFT_HEIGHTMAP_PNG),
FIOS_TYPE_BMP = MAKE_FIOS_TYPE(FT_HEIGHTMAP, DFT_HEIGHTMAP_BMP),
FIOS_TYPE_INVALID = MAKE_FIOS_TYPE(FT_INVALID, DFT_INVALID),
};
#undef MAKE_FIOS_TYPE
/**
* Extract the abstract file type from a #FiosType.
* @param fios_type Type to query.
* @return The Abstract file type of the \a fios_type.
*/
inline AbstractFileType GetAbstractFileType(FiosType fios_type)
{
return static_cast<AbstractFileType>(fios_type & FT_MASK);
}
/**
* Extract the detailed file type from a #FiosType.
* @param fios_type Type to query.
* @return The Detailed file type of the \a fios_type.
*/
inline DetailedFileType GetDetailedFileType(FiosType fios_type)
{
return static_cast<DetailedFileType>(fios_type >> FT_NUMBITS);
}
/**
* The different kinds of subdirectories OpenTTD uses
*/

View File

@@ -29,17 +29,15 @@
#include "safeguards.h"
/* Variables to display file lists */
SmallVector<FiosItem, 32> _fios_items;
static char *_fios_path;
static const char *_fios_path_last;
SmallFiosItem _file_to_saveload;
SortingBits _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
/* 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 bool FiosIsHiddenFile(const struct dirent *ent);
extern void FiosGetDrives();
extern void FiosGetDrives(FileList &file_list);
extern bool FiosGetDiskFreeSpace(const char *path, uint64 *tot);
/* get the name of an oldstyle savegame */
@@ -65,11 +63,72 @@ int CDECL CompareFiosItems(const FiosItem *da, const FiosItem *db)
return r;
}
/** Free the list of savegames. */
void FiosFreeSavegameList()
FileList::~FileList()
{
_fios_items.Clear();
_fios_items.Compact();
this->Clear();
}
/**
* Construct a file list with the given kind of files, for the stated purpose.
* @param abstract_filetype Kind of files to collect.
* @param fop Purpose of the collection, either #SLO_LOAD or #SLO_SAVE.
*/
void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop)
{
this->Clear();
assert(fop == SLO_LOAD || SLO_SAVE);
switch (abstract_filetype) {
case FT_NONE:
break;
case FT_SAVEGAME:
FiosGetSavegameList(fop, *this);
break;
case FT_SCENARIO:
FiosGetScenarioList(fop, *this);
break;
case FT_HEIGHTMAP:
FiosGetHeightmapList(fop, *this);
break;
default:
NOT_REACHED();
}
}
/**
* Find file information of a file by its name from the file list.
* @param file The filename to return information about. Can be the actual name
* or a numbered entry into the filename list.
* @return The information on the file, or \c NULL if the file is not available.
*/
const FiosItem *FileList::FindItem(const char *file)
{
for (const FiosItem *item = this->Begin(); item != this->End(); item++) {
if (strcmp(file, item->name) == 0) return item;
if (strcmp(file, item->title) == 0) return item;
}
/* If no name matches, try to parse it as number */
char *endptr;
int i = strtol(file, &endptr, 10);
if (file == endptr || *endptr != '\0') i = -1;
if (IsInsideMM(i, 0, this->Length())) return this->Get(i);
/* As a last effort assume it is an OpenTTD savegame and
* that the ".sav" part was not given. */
char long_file[MAX_PATH];
seprintf(long_file, lastof(long_file), "%s.sav", file);
for (const FiosItem *item = this->Begin(); item != this->End(); item++) {
if (strcmp(long_file, item->name) == 0) return item;
if (strcmp(long_file, item->title) == 0) return item;
}
return NULL;
}
/**
@@ -215,23 +274,24 @@ bool FiosDelete(const char *name)
return unlink(filename) == 0;
}
typedef FiosType fios_getlist_callback_proc(SaveLoadDialogMode mode, const char *filename, const char *ext, char *title, const char *last);
typedef FiosType fios_getlist_callback_proc(SaveLoadOperation fop, const char *filename, const char *ext, char *title, const char *last);
/**
* Scanner to scan for a particular type of FIOS file.
*/
class FiosFileScanner : public FileScanner {
SaveLoadDialogMode mode; ///< The mode we want to search for
SaveLoadOperation fop; ///< The kind of file we are looking for.
fios_getlist_callback_proc *callback_proc; ///< Callback to check whether the file may be added
FileList &file_list; ///< Destination of the found files.
public:
/**
* Create the scanner
* @param mode The mode we are in. Some modes don't allow 'parent'.
* @param fop Purpose of collecting the list.
* @param callback_proc The function that is called where you need to do the filtering.
* @param file_list Destination of the found files.
*/
FiosFileScanner(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc) :
mode(mode),
callback_proc(callback_proc)
FiosFileScanner(SaveLoadOperation fop, fios_getlist_callback_proc *callback_proc, FileList &file_list) :
fop(fop), callback_proc(callback_proc), file_list(file_list)
{}
/* virtual */ bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename);
@@ -251,14 +311,14 @@ bool FiosFileScanner::AddFile(const char *filename, size_t basepath_length, cons
char fios_title[64];
fios_title[0] = '\0'; // reset the title;
FiosType type = this->callback_proc(this->mode, filename, ext, fios_title, lastof(fios_title));
FiosType type = this->callback_proc(this->fop, filename, ext, fios_title, lastof(fios_title));
if (type == FIOS_TYPE_INVALID) return false;
for (const FiosItem *fios = _fios_items.Begin(); fios != _fios_items.End(); fios++) {
for (const FiosItem *fios = file_list.Begin(); fios != file_list.End(); fios++) {
if (strcmp(fios->name, filename) == 0) return false;
}
FiosItem *fios = _fios_items.Append();
FiosItem *fios = file_list.Append();
#ifdef WIN32
struct _stat sb;
if (_tstat(OTTD2FS(filename), &sb) == 0) {
@@ -289,11 +349,12 @@ bool FiosFileScanner::AddFile(const char *filename, size_t basepath_length, cons
/**
* Fill the list of the files in a directory, according to some arbitrary rule.
* @param mode The mode we are in. Some modes don't allow 'parent'.
* @param fop Purpose of collecting the list.
* @param callback_proc The function that is called where you need to do the filtering.
* @param subdir The directory from where to start (global) searching.
* @param file_list Destination of the found files.
*/
static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc, Subdirectory subdir)
static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *callback_proc, Subdirectory subdir, FileList &file_list)
{
struct stat sb;
struct dirent *dirent;
@@ -302,11 +363,11 @@ static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc
int sort_start;
char d_name[sizeof(fios->name)];
_fios_items.Clear();
file_list.Clear();
/* A parent directory link exists if we are not in the root directory */
if (!FiosIsRoot(_fios_path)) {
fios = _fios_items.Append();
fios = file_list.Append();
fios->type = FIOS_TYPE_PARENT;
fios->mtime = 0;
strecpy(fios->name, "..", lastof(fios->name));
@@ -322,7 +383,7 @@ static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc
if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
(!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
fios = _fios_items.Append();
fios = file_list.Append();
fios->type = FIOS_TYPE_DIR;
fios->mtime = 0;
strecpy(fios->name, d_name, lastof(fios->name));
@@ -337,27 +398,27 @@ static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc
{
SortingBits order = _savegame_sort_order;
_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
QSortT(_fios_items.Begin(), _fios_items.Length(), CompareFiosItems);
QSortT(file_list.files.Begin(), file_list.files.Length(), CompareFiosItems);
_savegame_sort_order = order;
}
/* This is where to start sorting for the filenames */
sort_start = _fios_items.Length();
sort_start = file_list.Length();
/* Show files */
FiosFileScanner scanner(mode, callback_proc);
FiosFileScanner scanner(fop, callback_proc, file_list);
if (subdir == NO_DIRECTORY) {
scanner.Scan(NULL, _fios_path, false);
} else {
scanner.Scan(NULL, subdir, true, true);
}
QSortT(_fios_items.Get(sort_start), _fios_items.Length() - sort_start, CompareFiosItems);
QSortT(file_list.Get(sort_start), file_list.Length() - sort_start, CompareFiosItems);
/* Show drives */
FiosGetDrives();
FiosGetDrives(file_list);
_fios_items.Compact();
file_list.Compact();
}
/**
@@ -386,7 +447,7 @@ static void GetFileTitle(const char *file, char *title, const char *last, Subdir
/**
* Callback for FiosGetFileList. It tells if a file is a savegame or not.
* @param mode Save/load mode.
* @param fop Purpose of collecting the list.
* @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; NULL to skip the lookup
@@ -395,7 +456,7 @@ static void GetFileTitle(const char *file, char *title, const char *last, Subdir
* @see FiosGetFileList
* @see FiosGetSavegameList
*/
FiosType FiosGetSavegameListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title, const char *last)
FiosType FiosGetSavegameListCallback(SaveLoadOperation fop, const char *file, const char *ext, char *title, const char *last)
{
/* Show savegame files
* .SAV OpenTTD saved game
@@ -411,7 +472,7 @@ FiosType FiosGetSavegameListCallback(SaveLoadDialogMode mode, const char *file,
return FIOS_TYPE_FILE;
}
if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) {
if (fop == SLO_LOAD) {
if (strcasecmp(ext, ".ss1") == 0 || strcasecmp(ext, ".sv1") == 0 ||
strcasecmp(ext, ".sv2") == 0) {
if (title != NULL) GetOldSaveGameName(file, title, last);
@@ -424,10 +485,11 @@ FiosType FiosGetSavegameListCallback(SaveLoadDialogMode mode, const char *file,
/**
* Get a list of savegames.
* @param mode Save/load mode.
* @param fop Purpose of collecting the list.
* @param file_list Destination of the found files.
* @see FiosGetFileList
*/
void FiosGetSavegameList(SaveLoadDialogMode mode)
void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list)
{
static char *fios_save_path = NULL;
static char *fios_save_path_last = NULL;
@@ -441,12 +503,12 @@ void FiosGetSavegameList(SaveLoadDialogMode mode)
_fios_path = fios_save_path;
_fios_path_last = fios_save_path_last;
FiosGetFileList(mode, &FiosGetSavegameListCallback, NO_DIRECTORY);
FiosGetFileList(fop, &FiosGetSavegameListCallback, NO_DIRECTORY, file_list);
}
/**
* Callback for FiosGetFileList. It tells if a file is a scenario or not.
* @param mode Save/load mode.
* @param fop Purpose of collecting the list.
* @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
@@ -455,7 +517,7 @@ void FiosGetSavegameList(SaveLoadDialogMode mode)
* @see FiosGetFileList
* @see FiosGetScenarioList
*/
static FiosType FiosGetScenarioListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title, const char *last)
static FiosType FiosGetScenarioListCallback(SaveLoadOperation fop, const char *file, const char *ext, char *title, const char *last)
{
/* Show scenario files
* .SCN OpenTTD style scenario file
@@ -466,7 +528,7 @@ static FiosType FiosGetScenarioListCallback(SaveLoadDialogMode mode, const char
return FIOS_TYPE_SCENARIO;
}
if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) {
if (fop == SLO_LOAD) {
if (strcasecmp(ext, ".sv0") == 0 || strcasecmp(ext, ".ss0") == 0 ) {
GetOldSaveGameName(file, title, last);
return FIOS_TYPE_OLD_SCENARIO;
@@ -478,10 +540,11 @@ static FiosType FiosGetScenarioListCallback(SaveLoadDialogMode mode, const char
/**
* Get a list of scenarios.
* @param mode Save/load mode.
* @param fop Purpose of collecting the list.
* @param file_list Destination of the found files.
* @see FiosGetFileList
*/
void FiosGetScenarioList(SaveLoadDialogMode mode)
void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list)
{
static char *fios_scn_path = NULL;
static char *fios_scn_path_last = NULL;
@@ -499,10 +562,11 @@ void FiosGetScenarioList(SaveLoadDialogMode mode)
char base_path[MAX_PATH];
FioGetDirectory(base_path, lastof(base_path), SCENARIO_DIR);
FiosGetFileList(mode, &FiosGetScenarioListCallback, (mode == SLD_LOAD_SCENARIO && strcmp(base_path, _fios_path) == 0) ? SCENARIO_DIR : NO_DIRECTORY);
Subdirectory subdir = (fop == SLO_LOAD && strcmp(base_path, _fios_path) == 0) ? SCENARIO_DIR : NO_DIRECTORY;
FiosGetFileList(fop, &FiosGetScenarioListCallback, subdir, file_list);
}
static FiosType FiosGetHeightmapListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title, const char *last)
static FiosType FiosGetHeightmapListCallback(SaveLoadOperation fop, const char *file, const char *ext, char *title, const char *last)
{
/* Show heightmap files
* .PNG PNG Based heightmap files
@@ -548,9 +612,10 @@ static FiosType FiosGetHeightmapListCallback(SaveLoadDialogMode mode, const char
/**
* Get a list of heightmaps.
* @param mode Save/load mode.
* @param fop Purpose of collecting the list.
* @param file_list Destination of the found files.
*/
void FiosGetHeightmapList(SaveLoadDialogMode mode)
void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list)
{
static char *fios_hmap_path = NULL;
static char *fios_hmap_path_last = NULL;
@@ -567,7 +632,8 @@ void FiosGetHeightmapList(SaveLoadDialogMode mode)
char base_path[MAX_PATH];
FioGetDirectory(base_path, lastof(base_path), HEIGHTMAP_DIR);
FiosGetFileList(mode, &FiosGetHeightmapListCallback, strcmp(base_path, _fios_path) == 0 ? HEIGHTMAP_DIR : NO_DIRECTORY);
Subdirectory subdir = strcmp(base_path, _fios_path) == 0 ? HEIGHTMAP_DIR : NO_DIRECTORY;
FiosGetFileList(fop, &FiosGetHeightmapListCallback, subdir, file_list);
}
/**

View File

@@ -99,38 +99,6 @@ enum FileSlots {
MAX_FILE_SLOTS_IN_NETWORK = 63
};
/** Mode of the file dialogue window. */
enum SaveLoadDialogMode {
SLD_LOAD_GAME, ///< Load a game.
SLD_LOAD_SCENARIO, ///< Load a scenario.
SLD_SAVE_GAME, ///< Save a game.
SLD_SAVE_SCENARIO, ///< Save a scenario.
SLD_LOAD_HEIGHTMAP, ///< Load a heightmap.
SLD_SAVE_HEIGHTMAP, ///< Save a heightmap.
};
/** The different types of files that the system knows about. */
enum FileType {
FT_NONE, ///< nothing to do
FT_SAVEGAME, ///< old or new savegame
FT_SCENARIO, ///< old or new scenario
FT_HEIGHTMAP, ///< heightmap file
};
enum FiosType {
FIOS_TYPE_DRIVE,
FIOS_TYPE_PARENT,
FIOS_TYPE_DIR,
FIOS_TYPE_FILE,
FIOS_TYPE_OLDFILE,
FIOS_TYPE_SCENARIO,
FIOS_TYPE_OLD_SCENARIO,
FIOS_TYPE_DIRECT,
FIOS_TYPE_PNG,
FIOS_TYPE_BMP,
FIOS_TYPE_INVALID = 255,
};
/** Deals with finding savegames */
struct FiosItem {
FiosType type;
@@ -139,12 +107,95 @@ struct FiosItem {
char name[MAX_PATH];
};
/** Deals with the type of the savegame, independent of extension */
struct SmallFiosItem {
int mode; ///< savegame/scenario type (old, new)
FileType filetype; ///< what type of file are we dealing with
char name[MAX_PATH]; ///< name
char title[255]; ///< internal name of the game
/** List of file information. */
class FileList {
public:
~FileList();
/**
* Construct a new entry in the file list.
* @return Pointer to the new items to be initialized.
*/
inline FiosItem *Append()
{
return this->files.Append();
}
/**
* Get the number of files in the list.
* @return The number of files stored in the list.
*/
inline uint Length() const
{
return this->files.Length();
}
/**
* Get a pointer to the first file information.
* @return Address of the first file information.
*/
inline const FiosItem *Begin() const
{
return this->files.Begin();
}
/**
* Get a pointer behind the last file information.
* @return Address behind the last file information.
*/
inline const FiosItem *End() const
{
return this->files.End();
}
/**
* Get a pointer to the indicated file information. File information must exist.
* @return Address of the indicated existing file information.
*/
inline const FiosItem *Get(uint index) const
{
return this->files.Get(index);
}
/**
* Get a pointer to the indicated file information. File information must exist.
* @return Address of the indicated existing file information.
*/
inline FiosItem *Get(uint index)
{
return this->files.Get(index);
}
inline const FiosItem &operator[](uint index) const
{
return this->files[index];
}
/**
* Get a reference to the indicated file information. File information must exist.
* @return The requested file information.
*/
inline FiosItem &operator[](uint index)
{
return this->files[index];
}
/** Remove all items from the list. */
inline void Clear()
{
this->files.Clear();
}
/** Compact the list down to the smallest block size boundary. */
inline void Compact()
{
this->files.Compact();
}
void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop);
const FiosItem *FindItem(const char *file);
SmallVector<FiosItem, 32> files; ///< The list of files.
};
enum SortingBits {
@@ -156,18 +207,14 @@ enum SortingBits {
DECLARE_ENUM_AS_BIT_SET(SortingBits)
/* Variables to display file lists */
extern SmallVector<FiosItem, 32> _fios_items;
extern SmallFiosItem _file_to_saveload;
extern SaveLoadDialogMode _saveload_mode;
extern SortingBits _savegame_sort_order;
void ShowSaveLoadDialog(SaveLoadDialogMode mode);
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop);
void FiosGetSavegameList(SaveLoadDialogMode mode);
void FiosGetScenarioList(SaveLoadDialogMode mode);
void FiosGetHeightmapList(SaveLoadDialogMode mode);
void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list);
void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list);
void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list);
void FiosFreeSavegameList();
const char *FiosBrowseTo(const FiosItem *item);
StringID FiosGetDescText(const char **path, uint64 *total_free);
@@ -175,13 +222,8 @@ bool FiosDelete(const char *name);
void FiosMakeHeightmapName(char *buf, const char *name, const char *last);
void FiosMakeSavegameName(char *buf, const char *name, const char *last);
FiosType FiosGetSavegameListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title, const char *last);
FiosType FiosGetSavegameListCallback(SaveLoadOperation fop, const char *file, const char *ext, char *title, const char *last);
int CDECL CompareFiosItems(const FiosItem *a, const FiosItem *b);
extern const TextColour _fios_colours[];
void BuildFileList();
void SetFiosType(const byte fiostype);
#endif /* FIOS_H */

View File

@@ -36,7 +36,6 @@
#include "safeguards.h"
SaveLoadDialogMode _saveload_mode;
LoadCheckData _load_check_data; ///< Data loaded from save during SL_LOAD_CHECK.
static bool _fios_path_changed;
@@ -187,33 +186,24 @@ static const NWidgetPart _nested_save_dialog_widgets[] = {
EndContainer(),
};
/** Colours for fios types, indexed by #FiosType. */
const TextColour _fios_colours[] = {
TC_LIGHT_BLUE, TC_DARK_GREEN, TC_DARK_GREEN, TC_ORANGE, TC_LIGHT_BROWN,
TC_ORANGE, TC_LIGHT_BROWN, TC_ORANGE, TC_ORANGE, TC_YELLOW
/** Text colours of #DetailedFileType fios entries in the window. */
static const TextColour _fios_colours[] = {
TC_LIGHT_BROWN, // DFT_OLD_GAME_FILE
TC_ORANGE, // DFT_GAME_FILE
TC_YELLOW, // DFT_HEIGHTMAP_BMP
TC_ORANGE, // DFT_HEIGHTMAP_PNG
TC_LIGHT_BLUE, // DFT_FIOS_DRIVE
TC_DARK_GREEN, // DFT_FIOS_PARENT
TC_DARK_GREEN, // DFT_FIOS_DIR
TC_ORANGE, // DFT_FIOS_DIRECT
};
void BuildFileList()
{
_fios_path_changed = true;
FiosFreeSavegameList();
switch (_saveload_mode) {
case SLD_LOAD_SCENARIO:
case SLD_SAVE_SCENARIO:
FiosGetScenarioList(_saveload_mode); break;
case SLD_SAVE_HEIGHTMAP:
case SLD_LOAD_HEIGHTMAP:
FiosGetHeightmapList(_saveload_mode); break;
default: FiosGetSavegameList(_saveload_mode); break;
}
/* Invalidate saveload window */
InvalidateWindowData(WC_SAVELOAD, 0, 2, true);
}
static void MakeSortedSaveGameList()
/**
* Sort the collected list save games prior to displaying it in the save/load gui.
* @param [inout] file_list List of save game files found in the directory.
*/
static void SortSaveGameList(FileList &file_list)
{
uint sort_start = 0;
uint sort_end = 0;
@@ -222,7 +212,7 @@ static void MakeSortedSaveGameList()
* Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE)
* Only sort savegames/scenarios, not directories
*/
for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
for (const FiosItem *item = file_list.Begin(); item != file_list.End(); item++) {
switch (item->type) {
case FIOS_TYPE_DIR: sort_start++; break;
case FIOS_TYPE_PARENT: sort_start++; break;
@@ -231,15 +221,18 @@ static void MakeSortedSaveGameList()
}
}
uint s_amount = _fios_items.Length() - sort_start - sort_end;
QSortT(_fios_items.Get(sort_start), s_amount, CompareFiosItems);
uint s_amount = file_list.Length() - sort_start - sort_end;
QSortT(file_list.Get(sort_start), s_amount, CompareFiosItems);
}
struct SaveLoadWindow : public Window {
private:
QueryString filename_editbox; ///< Filename editbox.
AbstractFileType abstract_filetype; /// Type of file to select.
SaveLoadOperation fop; ///< File operation to perform.
FileList fios_items; ///< Save game list.
FiosItem o_dir;
const FiosItem *selected;
const FiosItem *selected; ///< Selected game in #fios_items, or \c NULL.
Scrollbar *vscroll;
public:
@@ -250,35 +243,56 @@ public:
this->filename_editbox.text.UpdateSize();
}
SaveLoadWindow(WindowDesc *desc, SaveLoadDialogMode mode) : Window(desc), filename_editbox(64)
SaveLoadWindow(WindowDesc *desc, AbstractFileType abstract_filetype, SaveLoadOperation fop)
: Window(desc), filename_editbox(64), abstract_filetype(abstract_filetype), fop(fop)
{
static const StringID saveload_captions[] = {
STR_SAVELOAD_LOAD_CAPTION,
STR_SAVELOAD_LOAD_SCENARIO,
STR_SAVELOAD_SAVE_CAPTION,
STR_SAVELOAD_SAVE_SCENARIO,
STR_SAVELOAD_LOAD_HEIGHTMAP,
STR_SAVELOAD_SAVE_HEIGHTMAP,
};
assert((uint)mode < lengthof(saveload_captions));
assert(this->fop == SLO_SAVE || this->fop == SLO_LOAD);
/* Use an array to define what will be the current file type being handled
* by current file mode */
switch (mode) {
case SLD_SAVE_GAME: this->GenerateFileName(); break;
case SLD_SAVE_HEIGHTMAP:
case SLD_SAVE_SCENARIO: this->filename_editbox.text.Assign("UNNAMED"); break;
default: break;
/* For saving, construct an initial file name. */
if (this->fop == SLO_SAVE) {
switch (this->abstract_filetype) {
case FT_SAVEGAME:
this->GenerateFileName();
break;
case FT_SCENARIO:
case FT_HEIGHTMAP:
this->filename_editbox.text.Assign("UNNAMED");
break;
default:
NOT_REACHED();
}
}
this->querystrings[WID_SL_SAVE_OSK_TITLE] = &this->filename_editbox;
this->filename_editbox.ok_button = WID_SL_SAVE_GAME;
this->CreateNestedTree(true);
if (mode == SLD_LOAD_GAME) this->GetWidget<NWidgetStacked>(WID_SL_CONTENT_DOWNLOAD_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL);
this->GetWidget<NWidgetCore>(WID_SL_CAPTION)->widget_data = saveload_captions[mode];
this->vscroll = this->GetScrollbar(WID_SL_SCROLLBAR);
if (this->fop == SLO_LOAD && this->abstract_filetype == FT_SAVEGAME) {
this->GetWidget<NWidgetStacked>(WID_SL_CONTENT_DOWNLOAD_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL);
}
/* Select caption string of the window. */
StringID caption_string;
switch (this->abstract_filetype) {
case FT_SAVEGAME:
caption_string = (this->fop == SLO_SAVE) ? STR_SAVELOAD_SAVE_CAPTION : STR_SAVELOAD_LOAD_CAPTION;
break;
case FT_SCENARIO:
caption_string = (this->fop == SLO_SAVE) ? STR_SAVELOAD_SAVE_SCENARIO : STR_SAVELOAD_LOAD_SCENARIO;
break;
case FT_HEIGHTMAP:
caption_string = (this->fop == SLO_SAVE) ? STR_SAVELOAD_SAVE_HEIGHTMAP : STR_SAVELOAD_LOAD_HEIGHTMAP;
break;
default:
NOT_REACHED();
}
this->GetWidget<NWidgetCore>(WID_SL_CAPTION)->widget_data = caption_string;
this->vscroll = this->GetScrollbar(WID_SL_SCROLLBAR);
this->FinishInitNested(0);
this->LowerWidget(WID_SL_DRIVES_DIRECTORIES_LIST);
@@ -294,20 +308,18 @@ public:
ResetObjectToPlace();
/* Select the initial directory. */
o_dir.type = FIOS_TYPE_DIRECT;
switch (_saveload_mode) {
case SLD_SAVE_GAME:
case SLD_LOAD_GAME:
switch (this->abstract_filetype) {
case FT_SAVEGAME:
FioGetDirectory(o_dir.name, lastof(o_dir.name), SAVE_DIR);
break;
case SLD_SAVE_SCENARIO:
case SLD_LOAD_SCENARIO:
case FT_SCENARIO:
FioGetDirectory(o_dir.name, lastof(o_dir.name), SCENARIO_DIR);
break;
case SLD_SAVE_HEIGHTMAP:
case SLD_LOAD_HEIGHTMAP:
case FT_HEIGHTMAP:
FioGetDirectory(o_dir.name, lastof(o_dir.name), HEIGHTMAP_DIR);
break;
@@ -316,9 +328,7 @@ public:
}
/* Focus the edit box by default in the save windows */
if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
this->SetFocusedWidget(WID_SL_SAVE_OSK_TITLE);
}
if (this->fop == SLO_SAVE) this->SetFocusedWidget(WID_SL_SAVE_OSK_TITLE);
}
virtual ~SaveLoadWindow()
@@ -327,7 +337,6 @@ public:
if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
}
FiosFreeSavegameList();
}
virtual void DrawWidget(const Rect &r, int widget) const
@@ -360,13 +369,13 @@ public:
GfxFillRect(r.left + 1, r.top + 1, r.right, r.bottom, PC_BLACK);
uint y = r.top + WD_FRAMERECT_TOP;
for (uint pos = this->vscroll->GetPosition(); pos < _fios_items.Length(); pos++) {
const FiosItem *item = _fios_items.Get(pos);
for (uint pos = this->vscroll->GetPosition(); pos < this->fios_items.Length(); pos++) {
const FiosItem *item = this->fios_items.Get(pos);
if (item == this->selected) {
GfxFillRect(r.left + 1, y, r.right, y + this->resize.step_height, PC_DARK_BLUE);
}
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, item->title, _fios_colours[item->type]);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, item->title, _fios_colours[GetDetailedFileType(item->type)]);
y += this->resize.step_height;
if (y >= this->vscroll->GetCapacity() * this->resize.step_height + r.top + WD_FRAMERECT_TOP) break;
}
@@ -421,7 +430,7 @@ public:
if (y > y_max) break;
/* Hide current date for scenarios */
if (_saveload_mode != SLD_LOAD_SCENARIO && _saveload_mode != SLD_SAVE_SCENARIO) {
if (this->abstract_filetype != FT_SCENARIO) {
/* Current date */
SetDParam(0, _load_check_data.current_date);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CURRENT_DATE);
@@ -429,7 +438,7 @@ public:
}
/* Hide the NewGRF stuff when saving. We also hide the button. */
if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
if (this->fop == SLO_LOAD && (this->abstract_filetype == FT_SAVEGAME || this->abstract_filetype == FT_SCENARIO)) {
y += WD_PAR_VSEP_NORMAL;
if (y > y_max) break;
@@ -442,7 +451,7 @@ public:
if (y > y_max) break;
/* Hide the company stuff for scenarios */
if (_saveload_mode != SLD_LOAD_SCENARIO && _saveload_mode != SLD_SAVE_SCENARIO) {
if (this->abstract_filetype != FT_SCENARIO) {
y += FONT_HEIGHT_NORMAL;
if (y > y_max) break;
@@ -495,10 +504,10 @@ public:
{
if (_savegame_sort_dirty) {
_savegame_sort_dirty = false;
MakeSortedSaveGameList();
SortSaveGameList(this->fios_items);
}
this->vscroll->SetCount(_fios_items.Length());
this->vscroll->SetCount(this->fios_items.Length());
this->DrawWidgets();
}
@@ -527,14 +536,14 @@ public:
case WID_SL_LOAD_BUTTON:
if (this->selected != NULL && !_load_check_data.HasErrors()) {
const char *name = FiosBrowseTo(this->selected);
SetFiosType(this->selected->type);
_file_to_saveload.SetMode(this->selected->type);
_file_to_saveload.SetName(name);
_file_to_saveload.SetTitle(this->selected->title);
strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name));
strecpy(_file_to_saveload.title, this->selected->title, lastof(_file_to_saveload.title));
if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
if (this->abstract_filetype == FT_HEIGHTMAP) {
delete this;
ShowHeightmapLoad();
} else if (!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()) {
_switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD_GAME;
ClearErrorMessages();
@@ -563,7 +572,7 @@ public:
int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WD_FRAMERECT_TOP);
if (y == INT_MAX) return;
const FiosItem *file = _fios_items.Get(y);
const FiosItem *file = this->fios_items.Get(y);
const char *name = FiosBrowseTo(file);
if (name != NULL) {
@@ -572,30 +581,34 @@ public:
this->selected = file;
_load_check_data.Clear();
if (file->type == FIOS_TYPE_FILE || file->type == FIOS_TYPE_SCENARIO) {
SaveOrLoad(name, SL_LOAD_CHECK, NO_DIRECTORY, false);
if (GetDetailedFileType(file->type) == DFT_GAME_FILE) {
/* Other detailed file types cannot be checked before. */
SaveOrLoad(name, SLO_CHECK, DFT_GAME_FILE, NO_DIRECTORY, false);
}
this->InvalidateData(1);
}
if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
if (this->fop == SLO_SAVE) {
/* Copy clicked name to editbox */
this->filename_editbox.text.Assign(file->title);
this->SetWidgetDirty(WID_SL_SAVE_OSK_TITLE);
}
} else if (!_load_check_data.HasErrors()) {
this->selected = file;
if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
if (this->fop == SLO_LOAD) {
if (this->abstract_filetype == FT_SAVEGAME || this->abstract_filetype == FT_SCENARIO) {
this->OnClick(pt, WID_SL_LOAD_BUTTON, 1);
} else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
SetFiosType(file->type);
strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name));
strecpy(_file_to_saveload.title, file->title, lastof(_file_to_saveload.title));
} else {
assert(this->abstract_filetype == FT_HEIGHTMAP);
_file_to_saveload.SetMode(file->type);
_file_to_saveload.SetName(name);
_file_to_saveload.SetTitle(file->title);
delete this;
ShowHeightmapLoad();
}
}
}
} else {
/* Changed directory, need refresh. */
this->InvalidateData();
@@ -608,10 +621,11 @@ public:
ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR);
} else {
#if defined(ENABLE_NETWORK)
switch (_saveload_mode) {
assert(this->fop == SLO_LOAD);
switch (this->abstract_filetype) {
default: NOT_REACHED();
case SLD_LOAD_SCENARIO: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_SCENARIO); break;
case SLD_LOAD_HEIGHTMAP: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_HEIGHTMAP); break;
case FT_SCENARIO: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_SCENARIO); break;
case FT_HEIGHTMAP: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_HEIGHTMAP); break;
}
#endif
}
@@ -639,9 +653,8 @@ public:
virtual void OnTimeout()
{
/* This test protects against using widgets 11 and 12 which are only available
* in those saveload modes. */
if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP)) return;
/* Widgets WID_SL_DELETE_SELECTION and WID_SL_SAVE_GAME only exist when saving to a file. */
if (this->fop != SLO_SAVE) return;
if (this->IsWidgetLowered(WID_SL_DELETE_SELECTION)) { // Delete button clicked
if (!FiosDelete(this->filename_editbox.text.buf)) {
@@ -649,10 +662,10 @@ public:
} else {
this->InvalidateData();
/* Reset file name to current date on successful delete */
if (_saveload_mode == SLD_SAVE_GAME) GenerateFileName();
if (this->abstract_filetype == FT_SAVEGAME) GenerateFileName();
}
} else if (this->IsWidgetLowered(WID_SL_SAVE_GAME)) { // Save button clicked
if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
if (this->abstract_filetype == FT_SAVEGAME || this->abstract_filetype == FT_SCENARIO) {
_switch_mode = SM_SAVE_GAME;
FiosMakeSavegameName(_file_to_saveload.name, this->filename_editbox.text.buf, lastof(_file_to_saveload.name));
} else {
@@ -683,28 +696,40 @@ public:
this->selected = NULL;
_load_check_data.Clear();
if (!gui_scope) break;
BuildFileList();
_fios_path_changed = true;
this->fios_items.BuildFileList(this->abstract_filetype, this->fop);
this->vscroll->SetCount(this->fios_items.Length());
this->selected = NULL;
_load_check_data.Clear();
/* FALL THROUGH */
case 1:
/* Selection changes */
if (!gui_scope) break;
if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
if (this->fop != SLO_LOAD) break;
switch (this->abstract_filetype) {
case FT_HEIGHTMAP:
this->SetWidgetDisabledState(WID_SL_LOAD_BUTTON, this->selected == NULL || _load_check_data.HasErrors());
break;
case FT_SAVEGAME:
case FT_SCENARIO: {
bool disabled = this->selected == NULL || _load_check_data.HasErrors();
if (!_settings_client.gui.UserIsAllowedToChangeNewGRFs()) {
disabled |= _load_check_data.HasNewGrfs() && _load_check_data.grf_compatibility == GLC_NOT_FOUND;
}
if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
this->SetWidgetDisabledState(WID_SL_LOAD_BUTTON,
this->selected == NULL || _load_check_data.HasErrors() || !(!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()));
this->SetWidgetDisabledState(WID_SL_NEWGRF_INFO,
!_load_check_data.HasNewGrfs());
this->SetWidgetDisabledState(WID_SL_LOAD_BUTTON, disabled);
this->SetWidgetDisabledState(WID_SL_NEWGRF_INFO, !_load_check_data.HasNewGrfs());
this->SetWidgetDisabledState(WID_SL_MISSING_NEWGRFS,
!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility == GLC_ALL_GOOD);
}
break;
case 2:
/* _fios_items changed */
this->vscroll->SetCount(_fios_items.Length());
this->selected = NULL;
_load_check_data.Clear();
}
default:
NOT_REACHED();
}
break;
}
}
@@ -734,70 +759,24 @@ static WindowDesc _save_dialog_desc(
_nested_save_dialog_widgets, lengthof(_nested_save_dialog_widgets)
);
/**
* These values are used to convert the file/operations mode into a corresponding file type.
* So each entry, as expressed by the related comment, is based on the enum
*/
static const FileType _file_modetotype[] = {
FT_SAVEGAME, // used for SLD_LOAD_GAME
FT_SCENARIO, // used for SLD_LOAD_SCENARIO
FT_SAVEGAME, // used for SLD_SAVE_GAME
FT_SCENARIO, // used for SLD_SAVE_SCENARIO
FT_HEIGHTMAP, // used for SLD_LOAD_HEIGHTMAP
FT_HEIGHTMAP, // used for SLD_SAVE_HEIGHTMAP
};
/**
* Launch save/load dialog in the given mode.
* @param mode Save/load mode.
* @param abstract_filetype Kind of file to handle.
* @param fop File operation to perform (load or save).
*/
void ShowSaveLoadDialog(SaveLoadDialogMode mode)
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop)
{
DeleteWindowById(WC_SAVELOAD, 0);
WindowDesc *sld;
switch (mode) {
case SLD_SAVE_GAME:
case SLD_SAVE_SCENARIO:
case SLD_SAVE_HEIGHTMAP:
sld = &_save_dialog_desc; break;
case SLD_LOAD_HEIGHTMAP:
sld = &_load_heightmap_dialog_desc; break;
default:
sld = &_load_dialog_desc; break;
if (fop == SLO_SAVE) {
sld = &_save_dialog_desc;
} else {
/* Dialogue for loading a file. */
sld = (abstract_filetype == FT_HEIGHTMAP) ? &_load_heightmap_dialog_desc : &_load_dialog_desc;
}
_saveload_mode = mode;
_file_to_saveload.filetype = _file_modetotype[mode];
_file_to_saveload.abstract_ftype = abstract_filetype;
new SaveLoadWindow(sld, mode);
}
void SetFiosType(const byte fiostype)
{
switch (fiostype) {
case FIOS_TYPE_FILE:
case FIOS_TYPE_SCENARIO:
_file_to_saveload.mode = SL_LOAD;
break;
case FIOS_TYPE_OLDFILE:
case FIOS_TYPE_OLD_SCENARIO:
_file_to_saveload.mode = SL_OLD_LOAD;
break;
#ifdef WITH_PNG
case FIOS_TYPE_PNG:
_file_to_saveload.mode = SL_PNG;
break;
#endif /* WITH_PNG */
case FIOS_TYPE_BMP:
_file_to_saveload.mode = SL_BMP;
break;
default:
_file_to_saveload.mode = SL_INVALID;
break;
}
new SaveLoadWindow(sld, abstract_filetype, fop);
}

View File

@@ -204,7 +204,7 @@ static void _GenerateWorld(void *)
if (_debug_desync_level > 0) {
char name[MAX_PATH];
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR, false);
SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false);
}
} catch (...) {
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_GAMELOOP, true);

View File

@@ -27,6 +27,7 @@
#include "town.h"
#include "core/geometry_func.hpp"
#include "core/random_func.hpp"
#include "saveload/saveload.h"
#include "progress.h"
#include "error.h"
@@ -875,7 +876,7 @@ static void _ShowGenerateLandscape(GenerateLandscapeWindowMode mode)
if (mode == GLWM_HEIGHTMAP) {
/* If the function returns negative, it means there was a problem loading the heightmap */
if (!GetHeightmapDimensions(_file_to_saveload.name, &x, &y)) return;
if (!GetHeightmapDimensions(_file_to_saveload.detail_ftype, _file_to_saveload.name, &x, &y)) return;
}
WindowDesc *desc = (mode == GLWM_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc;

View File

@@ -102,7 +102,7 @@ static void ReadHeightmapPNGImageData(byte *map, png_structp png_ptr, png_infop
* If map == NULL only the size of the PNG is read, otherwise a map
* with grayscale pixels is allocated and assigned to *map.
*/
static bool ReadHeightmapPNG(char *filename, uint *x, uint *y, byte **map)
static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, byte **map)
{
FILE *fp;
png_structp png_ptr = NULL;
@@ -232,7 +232,7 @@ static void ReadHeightmapBMPImageData(byte *map, BmpInfo *info, BmpData *data)
* If map == NULL only the size of the BMP is read, otherwise a map
* with grayscale pixels is allocated and assigned to *map.
*/
static bool ReadHeightmapBMP(char *filename, uint *x, uint *y, byte **map)
static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, byte **map)
{
FILE *f;
BmpInfo info;
@@ -444,45 +444,56 @@ void FixSlopes()
}
/**
* Reads the heightmap with the correct file reader
* Reads the heightmap with the correct file reader.
* @param dft Type of image file.
* @param filename Name of the file to load.
* @param [out] x Length of the image.
* @param [out] y Height of the image.
* @param [inout] map If not \c NULL, destination to store the loaded block of image data.
* @return Whether loading was successful.
*/
static bool ReadHeightMap(char *filename, uint *x, uint *y, byte **map)
static bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y, byte **map)
{
switch (_file_to_saveload.mode) {
default: NOT_REACHED();
switch (dft) {
default:
NOT_REACHED();
#ifdef WITH_PNG
case SL_PNG:
case DFT_HEIGHTMAP_PNG:
return ReadHeightmapPNG(filename, x, y, map);
#endif /* WITH_PNG */
case SL_BMP:
case DFT_HEIGHTMAP_BMP:
return ReadHeightmapBMP(filename, x, y, map);
}
}
/**
* Get the dimensions of a heightmap.
* @param dft Type of image file.
* @param filename to query
* @param x dimension x
* @param y dimension y
* @return Returns false if loading of the image failed.
*/
bool GetHeightmapDimensions(char *filename, uint *x, uint *y)
bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y)
{
return ReadHeightMap(filename, x, y, NULL);
return ReadHeightMap(dft, filename, x, y, NULL);
}
/**
* Load a heightmap from file and change the map in his current dimensions
* to a landscape representing the heightmap.
* It converts pixels to height. The brighter, the higher.
* @param dft Type of image file.
* @param filename of the heightmap file to be imported
*/
void LoadHeightmap(char *filename)
void LoadHeightmap(DetailedFileType dft, const char *filename)
{
uint x, y;
byte *map = NULL;
if (!ReadHeightMap(filename, &x, &y, &map)) {
if (!ReadHeightMap(dft, filename, &x, &y, &map)) {
free(map);
return;
}

View File

@@ -12,6 +12,8 @@
#ifndef HEIGHTMAP_H
#define HEIGHTMAP_H
#include "fileio_type.h"
/**
* Order of these enums has to be the same as in lang/english.txt
* Otherwise you will get inconsistent behaviour.
@@ -21,8 +23,8 @@ enum HeightmapRotation {
HM_CLOCKWISE, ///< Rotate the map clockwise 45 degrees
};
bool GetHeightmapDimensions(char *filename, uint *x, uint *y);
void LoadHeightmap(char *filename);
bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y);
void LoadHeightmap(DetailedFileType dft, const char *filename);
void FlatEmptyWorld(byte tile_height);
void FixSlopes();

View File

@@ -111,9 +111,9 @@ struct SelectGameWindow : public Window {
}
break;
case WID_SGI_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
case WID_SGI_PLAY_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
case WID_SGI_PLAY_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
case WID_SGI_LOAD_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
case WID_SGI_PLAY_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_LOAD); break;
case WID_SGI_PLAY_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_LOAD); break;
case WID_SGI_EDIT_SCENARIO: StartScenarioEditor(); break;
case WID_SGI_PLAY_NETWORK:

View File

@@ -31,6 +31,7 @@
#include "object_base.h"
#include "company_func.h"
#include "pathfinder/npf/aystar.h"
#include "saveload/saveload.h"
#include <list>
#include <set>
@@ -1222,7 +1223,7 @@ void GenerateLandscape(byte mode)
if (mode == GWM_HEIGHTMAP) {
SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP);
LoadHeightmap(_file_to_saveload.name);
LoadHeightmap(_file_to_saveload.detail_ftype, _file_to_saveload.name);
IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
} else if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS) {
SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_TERRAGENESIS);

View File

@@ -525,7 +525,7 @@ bool ClientNetworkGameSocketHandler::IsConnected()
* DEF_CLIENT_RECEIVE_COMMAND has parameter: Packet *p
************/
extern bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL);
extern bool SafeLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL);
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p)
{
@@ -841,7 +841,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
/* The map is done downloading, load it */
ClearErrorMessages();
bool load_success = SafeLoad(NULL, SL_LOAD, GM_NORMAL, NO_DIRECTORY, lf);
bool load_success = SafeLoad(NULL, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, lf);
/* Long savegame loads shouldn't affect the lag calculation! */
this->last_packet = _realtime_tick;

View File

@@ -1193,17 +1193,17 @@ struct NetworkStartServerWindow : public Window {
case WID_NSS_LOAD_GAME:
_is_network_server = true;
ShowSaveLoadDialog(SLD_LOAD_GAME);
ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD);
break;
case WID_NSS_PLAY_SCENARIO:
_is_network_server = true;
ShowSaveLoadDialog(SLD_LOAD_SCENARIO);
ShowSaveLoadDialog(FT_SCENARIO, SLO_LOAD);
break;
case WID_NSS_PLAY_HEIGHTMAP:
_is_network_server = true;
ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP);
ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_LOAD);
break;
}
}

View File

@@ -359,7 +359,7 @@ static void LoadIntroGame(bool load_newgrfs = true)
SetupColoursAndInitialWindow();
/* Load the default opening screen savegame */
if (SaveOrLoad("opntitle.dat", SL_LOAD, BASESET_DIR) != SL_OK) {
if (SaveOrLoad("opntitle.dat", SLO_LOAD, DFT_GAME_FILE, BASESET_DIR) != SL_OK) {
GenerateWorld(GWM_EMPTY, 64, 64); // if failed loading, make empty world.
WaitTillGeneratedWorld();
SetLocalCompany(COMPANY_SPECTATOR);
@@ -650,15 +650,16 @@ int openttd_main(int argc, char *argv[])
case 'e': _switch_mode = (_switch_mode == SM_LOAD_GAME || _switch_mode == SM_LOAD_SCENARIO ? SM_LOAD_SCENARIO : SM_EDITOR); break;
case 'g':
if (mgo.opt != NULL) {
strecpy(_file_to_saveload.name, mgo.opt, lastof(_file_to_saveload.name));
_switch_mode = (_switch_mode == SM_EDITOR || _switch_mode == SM_LOAD_SCENARIO ? SM_LOAD_SCENARIO : SM_LOAD_GAME);
_file_to_saveload.mode = SL_LOAD;
_file_to_saveload.SetName(mgo.opt);
bool is_scenario = _switch_mode == SM_EDITOR || _switch_mode == SM_LOAD_SCENARIO;
_switch_mode = is_scenario ? SM_LOAD_SCENARIO : SM_LOAD_GAME;
_file_to_saveload.SetMode(SLO_LOAD, is_scenario ? FT_SCENARIO : FT_SAVEGAME, DFT_GAME_FILE);
/* if the file doesn't exist or it is not a valid savegame, let the saveload code show an error */
const char *t = strrchr(_file_to_saveload.name, '.');
if (t != NULL) {
FiosType ft = FiosGetSavegameListCallback(SLD_LOAD_GAME, _file_to_saveload.name, t, NULL, NULL);
if (ft != FIOS_TYPE_INVALID) SetFiosType(ft);
FiosType ft = FiosGetSavegameListCallback(SLO_LOAD, _file_to_saveload.name, t, NULL, NULL);
if (ft != FIOS_TYPE_INVALID) _file_to_saveload.SetMode(ft);
}
break;
@@ -679,10 +680,10 @@ int openttd_main(int argc, char *argv[])
char title[80];
title[0] = '\0';
FiosGetSavegameListCallback(SLD_LOAD_GAME, mgo.opt, strrchr(mgo.opt, '.'), title, lastof(title));
FiosGetSavegameListCallback(SLO_LOAD, mgo.opt, strrchr(mgo.opt, '.'), title, lastof(title));
_load_check_data.Clear();
SaveOrLoadResult res = SaveOrLoad(mgo.opt, SL_LOAD_CHECK, SAVE_DIR, false);
SaveOrLoadResult res = SaveOrLoad(mgo.opt, SLO_CHECK, DFT_GAME_FILE, SAVE_DIR, false);
if (res != SL_OK || _load_check_data.HasErrors()) {
fprintf(stderr, "Failed to open savegame\n");
if (_load_check_data.HasErrors()) {
@@ -1056,14 +1057,15 @@ static void MakeNewEditorWorld()
* @param subdir default directory to look for filename, set to 0 if not needed
* @param lf Load filter to use, if NULL: use filename + subdir.
*/
bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL)
bool SafeLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL)
{
assert(mode == SL_LOAD || (lf == NULL && mode == SL_OLD_LOAD));
assert(fop == SLO_LOAD);
assert(dft == DFT_GAME_FILE || (lf == NULL && dft == DFT_OLD_GAME_FILE));
GameMode ogm = _game_mode;
_game_mode = newgm;
switch (lf == NULL ? SaveOrLoad(filename, mode, subdir) : LoadWithFilter(lf)) {
switch (lf == NULL ? SaveOrLoad(filename, fop, dft, subdir) : LoadWithFilter(lf)) {
case SL_OK: return true;
case SL_REINIT:
@@ -1152,11 +1154,11 @@ void SwitchToMode(SwitchMode new_mode)
ResetGRFConfig(true);
ResetWindowSystem();
if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL, NO_DIRECTORY)) {
if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, NO_DIRECTORY)) {
SetDParamStr(0, GetSaveLoadErrorString());
ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
} else {
if (_saveload_mode == SLD_LOAD_SCENARIO) {
if (_file_to_saveload.abstract_ftype == FT_SCENARIO) {
/* Reset engine pool to simplify changing engine NewGRFs in scenario editor. */
EngineOverrideManager::ResetToCurrentNewGRFConfig();
}
@@ -1197,7 +1199,7 @@ void SwitchToMode(SwitchMode new_mode)
break;
case SM_LOAD_SCENARIO: { // Load scenario from scenario editor
if (SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR, NO_DIRECTORY)) {
if (SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_EDITOR, NO_DIRECTORY)) {
SetLocalCompany(OWNER_NONE);
_settings_newgame.game_creation.starting_year = _cur_year;
/* Cancel the saveload pausing */
@@ -1219,7 +1221,7 @@ void SwitchToMode(SwitchMode new_mode)
case SM_SAVE_GAME: // Save game.
/* Make network saved games on pause compatible to singleplayer */
if (SaveOrLoad(_file_to_saveload.name, SL_SAVE, NO_DIRECTORY) != SL_OK) {
if (SaveOrLoad(_file_to_saveload.name, SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY) != SL_OK) {
SetDParamStr(0, GetSaveLoadErrorString());
ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
} else {
@@ -1514,7 +1516,7 @@ void StateGameLoop()
/* Save the desync savegame if needed. */
char name[MAX_PATH];
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR, false);
SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false);
}
CheckCaches(false);
@@ -1578,7 +1580,7 @@ static void DoAutosave()
}
DEBUG(sl, 2, "Autosaving to '%s'", buf);
if (SaveOrLoad(buf, SL_SAVE, AUTOSAVE_DIR) != SL_OK) {
if (SaveOrLoad(buf, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR) != SL_OK) {
ShowErrorMessage(STR_ERROR_AUTOSAVE_FAILED, INVALID_STRING_ID, WL_ERROR);
}
}

View File

@@ -45,7 +45,7 @@ bool FiosIsRoot(const char *file)
return file[3] == '\0';
}
void FiosGetDrives()
void FiosGetDrives(FileList &file_list)
{
uint disk, disk2, save, total;
@@ -75,7 +75,7 @@ void FiosGetDrives()
#endif
if (disk == disk2) {
FiosItem *fios = _fios_items.Append();
FiosItem *fios = file_list.Append();
fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0;
#ifndef __INNOTEK_LIBC__

View File

@@ -16,6 +16,7 @@
#include "../../core/random_func.hpp"
#include "../../debug.h"
#include "../../string_func.h"
#include "../../fios.h"
#include <dirent.h>
@@ -77,7 +78,7 @@ bool FiosIsRoot(const char *path)
#endif
}
void FiosGetDrives()
void FiosGetDrives(FileList &file_list)
{
return;
}

View File

@@ -208,11 +208,11 @@ bool FiosIsRoot(const char *file)
return file[3] == '\0'; // C:\...
}
void FiosGetDrives()
void FiosGetDrives(FileList &file_list)
{
#if defined(WINCE)
/* WinCE only knows one drive: / */
FiosItem *fios = _fios_items.Append();
FiosItem *fios = file_list.Append();
fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0;
seprintf(fios->name, lastof(fios->name), PATHSEP "");
@@ -223,7 +223,7 @@ void FiosGetDrives()
GetLogicalDriveStrings(lengthof(drives), drives);
for (s = drives; *s != '\0';) {
FiosItem *fios = _fios_items.Append();
FiosItem *fios = file_list.Append();
fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0;
seprintf(fios->name, lastof(fios->name), "%c:", s[0] & 0xFF);

View File

@@ -250,7 +250,7 @@ static void InitializeWindowsAndCaches()
/* For each company, verify (while loading a scenario) that the inauguration date is the current year and set it
* accordingly if it is not the case. No need to set it on companies that are not been used already,
* thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */
if (_file_to_saveload.filetype == FT_SCENARIO && c->inaugurated_year != MIN_YEAR) {
if (_file_to_saveload.abstract_ftype == FT_SCENARIO && c->inaugurated_year != MIN_YEAR) {
c->inaugurated_year = _cur_year;
}
}

View File

@@ -143,6 +143,7 @@ void SlXvSetCurrentState()
*/
void SlXvCheckSpecialSavegameVersions()
{
// Checks for special savegame versions go here
extern uint16 _sl_version;
if (_sl_version == 2000) {

View File

@@ -273,6 +273,7 @@ extern const uint16 SAVEGAME_VERSION = 195; ///< Current savegame version of Ope
const uint16 SAVEGAME_VERSION_EXT = 0x8000; ///< Savegame extension indicator mask
SavegameType _savegame_type; ///< type of savegame we are loading
FileToSaveLoad _file_to_saveload; ///< File to save or load in the openttd loop.
uint32 _ttdp_version; ///< version of TTDP savegame (if applicable)
uint16 _sl_version; ///< the major savegame version identifier
@@ -2866,10 +2867,10 @@ SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
* @param threaded True when threaded saving is allowed
* @return Return the result of the action. #SL_OK, #SL_ERROR, or #SL_REINIT ("unload" the game)
*/
SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded)
{
/* An instance of saving is already active, so don't go saving again */
if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
if (_sl.saveinprogress && fop == SLO_SAVE && dft == DFT_GAME_FILE && threaded) {
/* if not an autosave, but a user action, show error message */
if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
return SL_OK;
@@ -2878,7 +2879,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
try {
/* Load a TTDLX or TTDPatch game */
if (mode == SL_OLD_LOAD) {
if (fop == SLO_LOAD && dft == DFT_OLD_GAME_FILE) {
InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
/* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
@@ -2901,25 +2902,35 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
return SL_OK;
}
switch (mode) {
case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
case SL_LOAD: _sl.action = SLA_LOAD; break;
case SL_SAVE: _sl.action = SLA_SAVE; break;
assert(dft == DFT_GAME_FILE);
switch (fop) {
case SLO_CHECK:
_sl.action = SLA_LOAD_CHECK;
break;
case SLO_LOAD:
_sl.action = SLA_LOAD;
break;
case SLO_SAVE:
_sl.action = SLA_SAVE;
break;
default: NOT_REACHED();
}
FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
FILE *fh = (fop == SLO_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
/* Make it a little easier to load savegames from the console */
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
if (fh == NULL && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
if (fh == NULL && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
if (fh == NULL && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
if (fh == NULL) {
SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
SlError(fop == SLO_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
}
if (mode == SL_SAVE) { // SAVE game
if (fop == SLO_SAVE) { // SAVE game
DEBUG(desync, 1, "save: %08x; %02x; %02X; %s", _date, _date_fract, _tick_skip_counter, filename);
if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
@@ -2927,24 +2938,25 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
}
/* LOAD game */
assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
assert(fop == SLO_LOAD || fop == SLO_CHECK);
DEBUG(desync, 1, "load: %s", filename);
return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
return DoLoad(new FileReader(fh), fop == SLO_CHECK);
} catch (...) {
/* This code may be executed both for old and new save games. */
ClearSaveLoadState();
/* Skip the "colour" character */
if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
if (fop != SLO_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
/* A saver/loader exception!! reinitialize all variables to prevent crash! */
return (mode == SL_LOAD || mode == SL_OLD_LOAD) ? SL_REINIT : SL_ERROR;
return (fop == SLO_LOAD) ? SL_REINIT : SL_ERROR;
}
}
/** Do a save when exiting the game (_settings_client.gui.autosave_on_exit) */
void DoExitSave()
{
SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
SaveOrLoad("exit.sav", SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR);
}
/**
@@ -2982,6 +2994,53 @@ void GenerateDefaultSaveName(char *buf, const char *last)
SanitizeFilename(buf);
}
/**
* Set the mode and file type of the file to save or load based on the type of file entry at the file system.
* @param ft Type of file entry of the file system.
*/
void FileToSaveLoad::SetMode(FiosType ft)
{
this->SetMode(SLO_LOAD, GetAbstractFileType(ft), GetDetailedFileType(ft));
}
/**
* Set the mode and file type of the file to save or load.
* @param fop File operation being performed.
* @param aft Abstract file type.
* @param dft Detailed file type.
*/
void FileToSaveLoad::SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft)
{
if (aft == FT_INVALID || aft == FT_NONE) {
this->file_op = SLO_INVALID;
this->detail_ftype = DFT_INVALID;
this->abstract_ftype = FT_INVALID;
return;
}
this->file_op = fop;
this->detail_ftype = dft;
this->abstract_ftype = aft;
}
/**
* Set the name of the file.
* @param name Name of the file.
*/
void FileToSaveLoad::SetName(const char *name)
{
strecpy(this->name, name, lastof(this->name));
}
/**
* Set the title of the file.
* @param title Title of the file.
*/
void FileToSaveLoad::SetTitle(const char *title)
{
strecpy(this->title, title, lastof(this->title));
}
#if 0
/**
* Function to get the type of the savegame by looking at the file header.

View File

@@ -25,15 +25,18 @@ enum SaveOrLoadResult {
SL_REINIT = 2, ///< error that was caught in the middle of updating game state, need to clear it. (can only happen during load)
};
/** Save or load mode. @see SaveOrLoad */
enum SaveOrLoadMode {
SL_INVALID = -1, ///< Invalid mode.
SL_LOAD = 0, ///< Load game.
SL_SAVE = 1, ///< Save game.
SL_OLD_LOAD = 2, ///< Load old game.
SL_PNG = 3, ///< Load PNG file (height map).
SL_BMP = 4, ///< Load BMP file (height map).
SL_LOAD_CHECK = 5, ///< Load for game preview.
/** Deals with the type of the savegame, independent of extension */
struct FileToSaveLoad {
SaveLoadOperation file_op; ///< File operation to perform.
DetailedFileType detail_ftype; ///< Concrete file type (PNG, BMP, old save, etc).
AbstractFileType abstract_ftype; ///< Abstract type of file (scenario, heightmap, etc).
char name[MAX_PATH]; ///< Name of the file.
char title[255]; ///< Internal name of the game.
void SetMode(FiosType ft);
void SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft);
void SetName(const char *name);
void SetTitle(const char *title);
};
/** Types of save games. */
@@ -46,10 +49,12 @@ enum SavegameType {
SGT_INVALID = 0xFF, ///< broken savegame (used internally)
};
extern FileToSaveLoad _file_to_saveload;
void GenerateDefaultSaveName(char *buf, const char *last);
void SetSaveLoadError(uint16 str);
const char *GetSaveLoadErrorString();
SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded = true);
SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded = true);
void WaitTillSaved();
void ProcessAsyncSaveFinish();
void DoExitSave();

View File

@@ -60,7 +60,7 @@ static void Load_SIGN()
}
/* Signs placed in scenario editor shall now be OWNER_DEITY */
if (IsSavegameVersionBefore(171) && si->owner == OWNER_NONE && _saveload_mode == SLD_LOAD_SCENARIO) {
if (IsSavegameVersionBefore(171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) {
si->owner = OWNER_DEITY;
}
}

53
src/scope.h Normal file
View File

@@ -0,0 +1,53 @@
/* $Id$ */
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file scope.h Simple scope guard... */
#ifndef SCOPE_H
#define SCOPE_H
template <typename T>
class scope_exit_obj {
T f;
bool shouldexec;
public:
scope_exit_obj(T &&func)
: f(std::move(func)), shouldexec(true) { }
scope_exit_obj(const scope_exit_obj &copysrc) = delete;
scope_exit_obj(scope_exit_obj &&movesrc)
: f(std::move(movesrc.f)), shouldexec(movesrc.shouldexec) {
movesrc.shouldexec = false;
}
~scope_exit_obj() {
exec();
}
void exec() {
if (shouldexec) {
f();
shouldexec = false;
}
}
void cancel() {
shouldexec = false;
}
};
template <typename T>
scope_exit_obj<typename std::decay<T>::type> scope_guard(T &&func) {
return scope_exit_obj<typename std::decay<T>::type>(std::forward<T>(func));
}
#endif /* SCOPE_H */

View File

@@ -2340,18 +2340,6 @@ static void SaveSettings(const SettingDesc *sd, void *object)
/** Sorted list of PATX settings, generated by MakeSettingsPatxList */
static std::vector<const SettingDesc *> _sorted_patx_settings;
/**
* Internal structure used in LoadSettingsPatx()
* placed outside for legacy compiler compatibility
* this makes me miss lambdas :/
*/
struct StringSorter {
bool operator()(const SettingDesc *a, const SettingDesc *b)
{
return strcmp(a->patx_name, b->patx_name) < 0;
}
};
/**
* Prepare a sorted list of settings to be potentially be loaded out of the PATX chunk
* This is to enable efficient lookup of settings by name
@@ -2370,28 +2358,11 @@ static void MakeSettingsPatxList(const SettingDesc *sd)
_sorted_patx_settings.push_back(desc);
}
std::sort(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), StringSorter());
std::sort(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), [](const SettingDesc *a, const SettingDesc *b) {
return strcmp(a->patx_name, b->patx_name) < 0;
});
}
/**
* Internal structure used in LoadSettingsPatx()
* placed outside for legacy compiler compatibility
* this is effectively a reference capture lambda
*/
struct StringSearcher {
bool &m_exact_match;
StringSearcher(bool &exact_match)
: m_exact_match(exact_match) { }
bool operator()(const SettingDesc *a, const char *b)
{
int result = strcmp(a->patx_name, b);
if (result == 0) m_exact_match = true;
return result < 0;
}
};
/**
* Internal structure used in LoadSettingsPatx() and LoadSettingsPlyx()
*/
@@ -2447,9 +2418,13 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
// flags are not in use yet, reserve for future expansion
if (current_setting.flags != 0) SlErrorCorruptFmt("PATX chunk: unknown setting header flags: 0x%X", current_setting.flags);
// now try to find corresponding setting, this would be much easier with C++11 support...
// now try to find corresponding setting
bool exact_match = false;
std::vector<const SettingDesc *>::iterator iter = std::lower_bound(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), current_setting.name, StringSearcher(exact_match));
auto iter = std::lower_bound(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), current_setting.name, [&](const SettingDesc *a, const char *b) {
int result = strcmp(a->patx_name, b);
if (result == 0) exact_match = true;
return result < 0;
});
if (exact_match) {
assert(iter != _sorted_patx_settings.end());
@@ -2469,15 +2444,6 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
}
}
/**
* Internal structure used in SaveSettingsPatx()
* placed outside for legacy compiler compatibility
*/
struct SettingToAdd {
const SettingDesc *setting;
uint32 setting_length;
};
/**
* Save handler for settings which go in the PATX chunk
* @param sd SettingDesc struct containing all information
@@ -2488,6 +2454,10 @@ static void SaveSettingsPatx(const SettingDesc *sd, void *object)
{
SettingsExtSave current_setting;
struct SettingToAdd {
const SettingDesc *setting;
uint32 setting_length;
};
std::vector<SettingToAdd> settings_to_add;
size_t length = 8;

View File

@@ -361,21 +361,8 @@ typedef unsigned char byte;
#define PERSONAL_DIR ""
#endif
/* Compile time assertions. Prefer c++0x static_assert().
* Older compilers cannot evaluate some expressions at compile time,
* typically when templates are involved, try assert_tcompile() in those cases. */
#if defined(__STDCXX_VERSION__) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(static_assert)
/* __STDCXX_VERSION__ is c++0x feature macro, __GXX_EXPERIMENTAL_CXX0X__ is used by gcc, __GXX_EXPERIMENTAL_CPP0X__ by icc */
#define assert_compile(expr) static_assert(expr, #expr )
#define assert_tcompile(expr) assert_compile(expr)
#elif defined(__OS2__)
/* Disabled for OS/2 */
#define assert_compile(expr)
#define assert_tcompile(expr) assert_compile(expr)
#else
#define assert_compile(expr) typedef int __ct_assert__[1 - 2 * !(expr)]
#define assert_tcompile(expr) assert(expr)
#endif
#define assert_compile(expr) static_assert(expr, #expr )
#define assert_tcompile(expr) assert_compile(expr)
/* Check if the types have the bitsizes like we are using them */
assert_compile(sizeof(uint64) == 8);

View File

@@ -17,7 +17,7 @@
#define NIP_END() { NULL, 0, 0, 0, 0 }
/* Helper for filling callback tables */
#define NIC(cb_id, base, variable, bit) { #cb_id, cpp_offsetof(base, variable), cpp_sizeof(base, variable), bit, cb_id }
#define NIC(cb_id, base, variable, bit) { #cb_id, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), bit, cb_id }
#define NIC_END() { NULL, 0, 0, 0, 0 }
/* Helper for filling variable tables */

View File

@@ -11,6 +11,10 @@
#include "../core/enum_type.hpp"
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
static const char * const _name_original_english_1[] = {
"Great ",
"Little ",

View File

@@ -437,17 +437,17 @@ static CallBackFunction MenuClickSaveLoad(int index = 0)
{
if (_game_mode == GM_EDITOR) {
switch (index) {
case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(SLD_SAVE_SCENARIO); break;
case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(SLD_SAVE_HEIGHTMAP); break;
case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_SAVE); break;
case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_LOAD); break;
case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_SAVE); break;
case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_LOAD); break;
case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break;
case SLEME_EXIT_GAME: HandleExitGameRequest(); break;
}
} else {
switch (index) {
case SLNME_SAVE_GAME: ShowSaveLoadDialog(SLD_SAVE_GAME); break;
case SLNME_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
case SLNME_SAVE_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_SAVE); break;
case SLNME_LOAD_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break;
case SLNME_EXIT_GAME: HandleExitGameRequest(); break;
}
@@ -1726,7 +1726,7 @@ struct MainToolbarWindow : Window {
case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
case MTHK_SETTINGS: ShowGameOptions(); break;
case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
case MTHK_LOADGAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
case MTHK_LOADGAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
case MTHK_SMALLMAP: ShowSmallMap(); break;
case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
case MTHK_SUBSIDIES: ShowSubsidiesList(); break;

View File

@@ -142,7 +142,7 @@ static void *_dedicated_video_mem;
/* Whether a fork has been done. */
bool _dedicated_forks;
extern bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL);
extern bool SafeLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL);
static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
@@ -286,7 +286,7 @@ void VideoDriver_Dedicated::MainLoop()
_switch_mode = SM_NONE;
/* First we need to test if the savegame can be loaded, else we will end up playing the
* intro game... */
if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL, BASE_DIR)) {
if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, BASE_DIR)) {
/* Loading failed, pop out.. */
DEBUG(net, 0, "Loading requested map failed, aborting");
_networking = false;