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 # remark #2259: non-pointer conversion from ... to ... may lose significant bits
flags="$flags -wd2259" flags="$flags -wd2259"
# Use c++0x mode so static_assert() is available # 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 fi
if [ "$enable_lto" != "0" ]; then 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, # -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) # -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 '...' # warning: unused parameter '...'
flags="$flags -Wno-unused-parameter" flags="$flags -Wno-unused-parameter"
@@ -1352,6 +1357,14 @@ make_compiler_cflags() {
flags="$flags -Wno-unused-variable" flags="$flags -Wno-unused-variable"
fi 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. # rdynamic is used to get useful stack traces from crash reports.
ldflags="$ldflags -rdynamic" ldflags="$ldflags -rdynamic"
else else
@@ -1408,11 +1421,9 @@ make_compiler_cflags() {
flags="$flags -Wnon-virtual-dtor" flags="$flags -Wnon-virtual-dtor"
fi 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. # Use gnu++0x mode so static_assert() is available.
# Don't use c++0x, it breaks mingw (with gcc 4.4.0). # 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" cxxflags="$cxxflags -std=gnu++11"
fi fi
@@ -1429,6 +1440,9 @@ make_compiler_cflags() {
cxxflags="$cxxflags -Wno-narrowing" cxxflags="$cxxflags -Wno-narrowing"
# Disable bogus 'attempt to free a non-heap object' warning # Disable bogus 'attempt to free a non-heap object' warning
flags="$flags -Wno-free-nonheap-object" flags="$flags -Wno-free-nonheap-object"
else
log 1 "configure: error: GCC version is too old: `$1 -dumpversion`, minumum: 4.7"
exit 1
fi fi
if [ $cc_version -ge 409 ]; then if [ $cc_version -ge 409 ]; then

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -48,6 +48,38 @@
/* scriptfile handling */ /* scriptfile handling */
static bool _script_running; ///< Script is running (used to abort execution when #ConReturn is encountered). 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 */ /* console command defines */
#define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[]) #define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
#define DEF_CONSOLE_HOOK(function) static ConsoleHookResult function(bool echo) #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]); char *filename = str_fmt("%s.sav", argv[1]);
IConsolePrint(CC_DEFAULT, "Saving map..."); 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"); IConsolePrint(CC_ERROR, "Saving map failed");
} else { } else {
IConsolePrintF(CC_DEFAULT, "Map successfully saved to %s", filename); IConsolePrintF(CC_DEFAULT, "Map successfully saved to %s", filename);
@@ -317,42 +349,6 @@ DEF_CONSOLE_CMD(ConSaveConfig)
return true; 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) DEF_CONSOLE_CMD(ConLoad)
{ {
if (argc == 0) { if (argc == 0) {
@@ -363,24 +359,21 @@ DEF_CONSOLE_CMD(ConLoad)
if (argc != 2) return false; if (argc != 2) return false;
const char *file = argv[1]; 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 (item != NULL) {
switch (item->type) { if (GetAbstractFileType(item->type) == FT_SAVEGAME) {
case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: { _switch_mode = SM_LOAD_GAME;
_switch_mode = SM_LOAD_GAME; _file_to_saveload.SetMode(item->type);
SetFiosType(item->type); _file_to_saveload.SetName(FiosBrowseTo(item));
_file_to_saveload.SetTitle(item->title);
strecpy(_file_to_saveload.name, FiosBrowseTo(item), lastof(_file_to_saveload.name)); } else {
strecpy(_file_to_saveload.title, item->title, lastof(_file_to_saveload.title)); IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
break;
}
default: IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
} }
} else { } else {
IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file); IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
} }
FiosFreeSavegameList();
return true; return true;
} }
@@ -395,7 +388,8 @@ DEF_CONSOLE_CMD(ConRemove)
if (argc != 2) return false; if (argc != 2) return false;
const char *file = argv[1]; 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 (item != NULL) {
if (!FiosDelete(item->name)) { if (!FiosDelete(item->name)) {
IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file); 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); IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
} }
FiosFreeSavegameList(); _console_file_list.InvalidateFileList();
return true; return true;
} }
@@ -417,13 +411,11 @@ DEF_CONSOLE_CMD(ConListFiles)
return true; return true;
} }
BuildFileList(); _console_file_list.ValidateFileList(true);
for (uint i = 0; i < _console_file_list.Length(); i++) {
for (uint i = 0; i < _fios_items.Length(); i++) { IConsolePrintF(CC_DEFAULT, "%d) %s", i, _console_file_list[i].title);
IConsolePrintF(CC_DEFAULT, "%d) %s", i, _fios_items[i].title);
} }
FiosFreeSavegameList();
return true; return true;
} }
@@ -438,7 +430,8 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
if (argc != 2) return false; if (argc != 2) return false;
const char *file = argv[1]; 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) { if (item != NULL) {
switch (item->type) { switch (item->type) {
case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT: 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); IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
} }
FiosFreeSavegameList(); _console_file_list.InvalidateFileList();
return true; return true;
} }
@@ -464,8 +457,8 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
} }
/* XXX - Workaround for broken file handling */ /* XXX - Workaround for broken file handling */
FiosGetSavegameList(SLD_LOAD_GAME); _console_file_list.ValidateFileList(true);
FiosFreeSavegameList(); _console_file_list.InvalidateFileList();
FiosGetDescText(&path, NULL); FiosGetDescText(&path, NULL);
IConsolePrint(CC_DEFAULT, path); IConsolePrint(CC_DEFAULT, path);

View File

@@ -256,6 +256,8 @@ public:
/** /**
* Get the number of items in the list. * Get the number of items in the list.
*
* @return The number of items in the list.
*/ */
inline uint Length() const 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); seprintf(filename, filename_last, "%scrash.sav", _personal_dir);
/* Don't do a threaded saveload. */ /* 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 (...) { } catch (...) {
return false; return false;
} }

View File

@@ -14,6 +14,96 @@
#include "core/enum_type.hpp" #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 * The different kinds of subdirectories OpenTTD uses
*/ */

View File

@@ -29,17 +29,15 @@
#include "safeguards.h" #include "safeguards.h"
/* Variables to display file lists */ /* Variables to display file lists */
SmallVector<FiosItem, 32> _fios_items;
static char *_fios_path; static char *_fios_path;
static const char *_fios_path_last; static const char *_fios_path_last;
SmallFiosItem _file_to_saveload;
SortingBits _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING; SortingBits _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
/* OS-specific functions are taken from their respective files (win32/unix/os2 .c) */ /* OS-specific functions are taken from their respective files (win32/unix/os2 .c) */
extern bool FiosIsRoot(const char *path); extern bool FiosIsRoot(const char *path);
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb); extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
extern bool FiosIsHiddenFile(const struct dirent *ent); extern bool FiosIsHiddenFile(const struct dirent *ent);
extern void FiosGetDrives(); extern void FiosGetDrives(FileList &file_list);
extern bool FiosGetDiskFreeSpace(const char *path, uint64 *tot); extern bool FiosGetDiskFreeSpace(const char *path, uint64 *tot);
/* get the name of an oldstyle savegame */ /* get the name of an oldstyle savegame */
@@ -65,11 +63,72 @@ int CDECL CompareFiosItems(const FiosItem *da, const FiosItem *db)
return r; return r;
} }
/** Free the list of savegames. */ FileList::~FileList()
void FiosFreeSavegameList()
{ {
_fios_items.Clear(); this->Clear();
_fios_items.Compact(); }
/**
* 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; 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. * Scanner to scan for a particular type of FIOS file.
*/ */
class FiosFileScanner : public FileScanner { 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 fios_getlist_callback_proc *callback_proc; ///< Callback to check whether the file may be added
FileList &file_list; ///< Destination of the found files.
public: public:
/** /**
* Create the scanner * 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 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) : FiosFileScanner(SaveLoadOperation fop, fios_getlist_callback_proc *callback_proc, FileList &file_list) :
mode(mode), fop(fop), callback_proc(callback_proc), file_list(file_list)
callback_proc(callback_proc)
{} {}
/* virtual */ bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename); /* 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]; char fios_title[64];
fios_title[0] = '\0'; // reset the title; 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; 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; if (strcmp(fios->name, filename) == 0) return false;
} }
FiosItem *fios = _fios_items.Append(); FiosItem *fios = file_list.Append();
#ifdef WIN32 #ifdef WIN32
struct _stat sb; struct _stat sb;
if (_tstat(OTTD2FS(filename), &sb) == 0) { 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. * 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 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 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 stat sb;
struct dirent *dirent; struct dirent *dirent;
@@ -302,11 +363,11 @@ static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc
int sort_start; int sort_start;
char d_name[sizeof(fios->name)]; 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 */ /* A parent directory link exists if we are not in the root directory */
if (!FiosIsRoot(_fios_path)) { if (!FiosIsRoot(_fios_path)) {
fios = _fios_items.Append(); fios = file_list.Append();
fios->type = FIOS_TYPE_PARENT; fios->type = FIOS_TYPE_PARENT;
fios->mtime = 0; fios->mtime = 0;
strecpy(fios->name, "..", lastof(fios->name)); 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) && if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
(!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) && (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
strcmp(d_name, ".") != 0 && strcmp(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->type = FIOS_TYPE_DIR;
fios->mtime = 0; fios->mtime = 0;
strecpy(fios->name, d_name, lastof(fios->name)); 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; SortingBits order = _savegame_sort_order;
_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING; _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; _savegame_sort_order = order;
} }
/* This is where to start sorting for the filenames */ /* This is where to start sorting for the filenames */
sort_start = _fios_items.Length(); sort_start = file_list.Length();
/* Show files */ /* Show files */
FiosFileScanner scanner(mode, callback_proc); FiosFileScanner scanner(fop, callback_proc, file_list);
if (subdir == NO_DIRECTORY) { if (subdir == NO_DIRECTORY) {
scanner.Scan(NULL, _fios_path, false); scanner.Scan(NULL, _fios_path, false);
} else { } else {
scanner.Scan(NULL, subdir, true, true); 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 */ /* 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. * 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 file Name of the file to check.
* @param ext A pointer to the extension identifier inside file * @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 * @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 FiosGetFileList
* @see FiosGetSavegameList * @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 /* Show savegame files
* .SAV OpenTTD saved game * .SAV OpenTTD saved game
@@ -411,7 +472,7 @@ FiosType FiosGetSavegameListCallback(SaveLoadDialogMode mode, const char *file,
return FIOS_TYPE_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 || if (strcasecmp(ext, ".ss1") == 0 || strcasecmp(ext, ".sv1") == 0 ||
strcasecmp(ext, ".sv2") == 0) { strcasecmp(ext, ".sv2") == 0) {
if (title != NULL) GetOldSaveGameName(file, title, last); if (title != NULL) GetOldSaveGameName(file, title, last);
@@ -424,10 +485,11 @@ FiosType FiosGetSavegameListCallback(SaveLoadDialogMode mode, const char *file,
/** /**
* Get a list of savegames. * 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 * @see FiosGetFileList
*/ */
void FiosGetSavegameList(SaveLoadDialogMode mode) void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list)
{ {
static char *fios_save_path = NULL; static char *fios_save_path = NULL;
static char *fios_save_path_last = NULL; static char *fios_save_path_last = NULL;
@@ -441,12 +503,12 @@ void FiosGetSavegameList(SaveLoadDialogMode mode)
_fios_path = fios_save_path; _fios_path = fios_save_path;
_fios_path_last = fios_save_path_last; _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. * 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 file Name of the file to check.
* @param ext A pointer to the extension identifier inside file * @param ext A pointer to the extension identifier inside file
* @param title Buffer if a callback wants to lookup the title of the 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 FiosGetFileList
* @see FiosGetScenarioList * @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 /* Show scenario files
* .SCN OpenTTD style scenario file * .SCN OpenTTD style scenario file
@@ -466,7 +528,7 @@ static FiosType FiosGetScenarioListCallback(SaveLoadDialogMode mode, const char
return FIOS_TYPE_SCENARIO; 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 ) { if (strcasecmp(ext, ".sv0") == 0 || strcasecmp(ext, ".ss0") == 0 ) {
GetOldSaveGameName(file, title, last); GetOldSaveGameName(file, title, last);
return FIOS_TYPE_OLD_SCENARIO; return FIOS_TYPE_OLD_SCENARIO;
@@ -478,10 +540,11 @@ static FiosType FiosGetScenarioListCallback(SaveLoadDialogMode mode, const char
/** /**
* Get a list of scenarios. * 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 * @see FiosGetFileList
*/ */
void FiosGetScenarioList(SaveLoadDialogMode mode) void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list)
{ {
static char *fios_scn_path = NULL; static char *fios_scn_path = NULL;
static char *fios_scn_path_last = NULL; static char *fios_scn_path_last = NULL;
@@ -499,10 +562,11 @@ void FiosGetScenarioList(SaveLoadDialogMode mode)
char base_path[MAX_PATH]; char base_path[MAX_PATH];
FioGetDirectory(base_path, lastof(base_path), SCENARIO_DIR); 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 /* Show heightmap files
* .PNG PNG Based heightmap files * .PNG PNG Based heightmap files
@@ -548,9 +612,10 @@ static FiosType FiosGetHeightmapListCallback(SaveLoadDialogMode mode, const char
/** /**
* Get a list of heightmaps. * 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 = NULL;
static char *fios_hmap_path_last = NULL; static char *fios_hmap_path_last = NULL;
@@ -567,7 +632,8 @@ void FiosGetHeightmapList(SaveLoadDialogMode mode)
char base_path[MAX_PATH]; char base_path[MAX_PATH];
FioGetDirectory(base_path, lastof(base_path), HEIGHTMAP_DIR); 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 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 */ /** Deals with finding savegames */
struct FiosItem { struct FiosItem {
FiosType type; FiosType type;
@@ -139,12 +107,95 @@ struct FiosItem {
char name[MAX_PATH]; char name[MAX_PATH];
}; };
/** Deals with the type of the savegame, independent of extension */ /** List of file information. */
struct SmallFiosItem { class FileList {
int mode; ///< savegame/scenario type (old, new) public:
FileType filetype; ///< what type of file are we dealing with ~FileList();
char name[MAX_PATH]; ///< name
char title[255]; ///< internal name of the game /**
* 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 { enum SortingBits {
@@ -156,18 +207,14 @@ enum SortingBits {
DECLARE_ENUM_AS_BIT_SET(SortingBits) DECLARE_ENUM_AS_BIT_SET(SortingBits)
/* Variables to display file lists */ /* 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; extern SortingBits _savegame_sort_order;
void ShowSaveLoadDialog(SaveLoadDialogMode mode); void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop);
void FiosGetSavegameList(SaveLoadDialogMode mode); void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list);
void FiosGetScenarioList(SaveLoadDialogMode mode); void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list);
void FiosGetHeightmapList(SaveLoadDialogMode mode); void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list);
void FiosFreeSavegameList();
const char *FiosBrowseTo(const FiosItem *item); const char *FiosBrowseTo(const FiosItem *item);
StringID FiosGetDescText(const char **path, uint64 *total_free); 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 FiosMakeHeightmapName(char *buf, const char *name, const char *last);
void FiosMakeSavegameName(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); int CDECL CompareFiosItems(const FiosItem *a, const FiosItem *b);
extern const TextColour _fios_colours[];
void BuildFileList();
void SetFiosType(const byte fiostype);
#endif /* FIOS_H */ #endif /* FIOS_H */

View File

@@ -36,7 +36,6 @@
#include "safeguards.h" #include "safeguards.h"
SaveLoadDialogMode _saveload_mode;
LoadCheckData _load_check_data; ///< Data loaded from save during SL_LOAD_CHECK. LoadCheckData _load_check_data; ///< Data loaded from save during SL_LOAD_CHECK.
static bool _fios_path_changed; static bool _fios_path_changed;
@@ -187,33 +186,24 @@ static const NWidgetPart _nested_save_dialog_widgets[] = {
EndContainer(), EndContainer(),
}; };
/** Colours for fios types, indexed by #FiosType. */ /** Text colours of #DetailedFileType fios entries in the window. */
const TextColour _fios_colours[] = { static const TextColour _fios_colours[] = {
TC_LIGHT_BLUE, TC_DARK_GREEN, TC_DARK_GREEN, TC_ORANGE, TC_LIGHT_BROWN, TC_LIGHT_BROWN, // DFT_OLD_GAME_FILE
TC_ORANGE, TC_LIGHT_BROWN, TC_ORANGE, TC_ORANGE, TC_YELLOW 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: * Sort the collected list save games prior to displaying it in the save/load gui.
case SLD_SAVE_SCENARIO: * @param [inout] file_list List of save game files found in the directory.
FiosGetScenarioList(_saveload_mode); break; */
case SLD_SAVE_HEIGHTMAP: static void SortSaveGameList(FileList &file_list)
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()
{ {
uint sort_start = 0; uint sort_start = 0;
uint sort_end = 0; uint sort_end = 0;
@@ -222,7 +212,7 @@ static void MakeSortedSaveGameList()
* Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE) * Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE)
* Only sort savegames/scenarios, not directories * 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) { switch (item->type) {
case FIOS_TYPE_DIR: sort_start++; break; case FIOS_TYPE_DIR: sort_start++; break;
case FIOS_TYPE_PARENT: 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; uint s_amount = file_list.Length() - sort_start - sort_end;
QSortT(_fios_items.Get(sort_start), s_amount, CompareFiosItems); QSortT(file_list.Get(sort_start), s_amount, CompareFiosItems);
} }
struct SaveLoadWindow : public Window { struct SaveLoadWindow : public Window {
private: private:
QueryString filename_editbox; ///< Filename editbox. 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; FiosItem o_dir;
const FiosItem *selected; const FiosItem *selected; ///< Selected game in #fios_items, or \c NULL.
Scrollbar *vscroll; Scrollbar *vscroll;
public: public:
@@ -250,35 +243,56 @@ public:
this->filename_editbox.text.UpdateSize(); 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[] = { assert(this->fop == SLO_SAVE || this->fop == SLO_LOAD);
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));
/* Use an array to define what will be the current file type being handled /* For saving, construct an initial file name. */
* by current file mode */ if (this->fop == SLO_SAVE) {
switch (mode) { switch (this->abstract_filetype) {
case SLD_SAVE_GAME: this->GenerateFileName(); break; case FT_SAVEGAME:
case SLD_SAVE_HEIGHTMAP: this->GenerateFileName();
case SLD_SAVE_SCENARIO: this->filename_editbox.text.Assign("UNNAMED"); break; break;
default: 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->querystrings[WID_SL_SAVE_OSK_TITLE] = &this->filename_editbox;
this->filename_editbox.ok_button = WID_SL_SAVE_GAME; this->filename_editbox.ok_button = WID_SL_SAVE_GAME;
this->CreateNestedTree(true); this->CreateNestedTree(true);
if (mode == SLD_LOAD_GAME) this->GetWidget<NWidgetStacked>(WID_SL_CONTENT_DOWNLOAD_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL); if (this->fop == SLO_LOAD && this->abstract_filetype == FT_SAVEGAME) {
this->GetWidget<NWidgetCore>(WID_SL_CAPTION)->widget_data = saveload_captions[mode]; this->GetWidget<NWidgetStacked>(WID_SL_CONTENT_DOWNLOAD_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL);
this->vscroll = this->GetScrollbar(WID_SL_SCROLLBAR); }
/* 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->FinishInitNested(0);
this->LowerWidget(WID_SL_DRIVES_DIRECTORIES_LIST); this->LowerWidget(WID_SL_DRIVES_DIRECTORIES_LIST);
@@ -294,20 +308,18 @@ public:
ResetObjectToPlace(); ResetObjectToPlace();
/* Select the initial directory. */
o_dir.type = FIOS_TYPE_DIRECT; o_dir.type = FIOS_TYPE_DIRECT;
switch (_saveload_mode) { switch (this->abstract_filetype) {
case SLD_SAVE_GAME: case FT_SAVEGAME:
case SLD_LOAD_GAME:
FioGetDirectory(o_dir.name, lastof(o_dir.name), SAVE_DIR); FioGetDirectory(o_dir.name, lastof(o_dir.name), SAVE_DIR);
break; break;
case SLD_SAVE_SCENARIO: case FT_SCENARIO:
case SLD_LOAD_SCENARIO:
FioGetDirectory(o_dir.name, lastof(o_dir.name), SCENARIO_DIR); FioGetDirectory(o_dir.name, lastof(o_dir.name), SCENARIO_DIR);
break; break;
case SLD_SAVE_HEIGHTMAP: case FT_HEIGHTMAP:
case SLD_LOAD_HEIGHTMAP:
FioGetDirectory(o_dir.name, lastof(o_dir.name), HEIGHTMAP_DIR); FioGetDirectory(o_dir.name, lastof(o_dir.name), HEIGHTMAP_DIR);
break; break;
@@ -316,9 +328,7 @@ public:
} }
/* Focus the edit box by default in the save windows */ /* 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) { if (this->fop == SLO_SAVE) this->SetFocusedWidget(WID_SL_SAVE_OSK_TITLE);
this->SetFocusedWidget(WID_SL_SAVE_OSK_TITLE);
}
} }
virtual ~SaveLoadWindow() virtual ~SaveLoadWindow()
@@ -327,7 +337,6 @@ public:
if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) { if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
} }
FiosFreeSavegameList();
} }
virtual void DrawWidget(const Rect &r, int widget) const 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); GfxFillRect(r.left + 1, r.top + 1, r.right, r.bottom, PC_BLACK);
uint y = r.top + WD_FRAMERECT_TOP; uint y = r.top + WD_FRAMERECT_TOP;
for (uint pos = this->vscroll->GetPosition(); pos < _fios_items.Length(); pos++) { for (uint pos = this->vscroll->GetPosition(); pos < this->fios_items.Length(); pos++) {
const FiosItem *item = _fios_items.Get(pos); const FiosItem *item = this->fios_items.Get(pos);
if (item == this->selected) { if (item == this->selected) {
GfxFillRect(r.left + 1, y, r.right, y + this->resize.step_height, PC_DARK_BLUE); 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; y += this->resize.step_height;
if (y >= this->vscroll->GetCapacity() * this->resize.step_height + r.top + WD_FRAMERECT_TOP) break; 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; if (y > y_max) break;
/* Hide current date for scenarios */ /* Hide current date for scenarios */
if (_saveload_mode != SLD_LOAD_SCENARIO && _saveload_mode != SLD_SAVE_SCENARIO) { if (this->abstract_filetype != FT_SCENARIO) {
/* Current date */ /* Current date */
SetDParam(0, _load_check_data.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); 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. */ /* 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; y += WD_PAR_VSEP_NORMAL;
if (y > y_max) break; if (y > y_max) break;
@@ -442,7 +451,7 @@ public:
if (y > y_max) break; if (y > y_max) break;
/* Hide the company stuff for scenarios */ /* 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; y += FONT_HEIGHT_NORMAL;
if (y > y_max) break; if (y > y_max) break;
@@ -495,10 +504,10 @@ public:
{ {
if (_savegame_sort_dirty) { if (_savegame_sort_dirty) {
_savegame_sort_dirty = false; _savegame_sort_dirty = false;
MakeSortedSaveGameList(); SortSaveGameList(this->fios_items);
} }
this->vscroll->SetCount(_fios_items.Length()); this->vscroll->SetCount(this->fios_items.Length());
this->DrawWidgets(); this->DrawWidgets();
} }
@@ -527,14 +536,14 @@ public:
case WID_SL_LOAD_BUTTON: case WID_SL_LOAD_BUTTON:
if (this->selected != NULL && !_load_check_data.HasErrors()) { if (this->selected != NULL && !_load_check_data.HasErrors()) {
const char *name = FiosBrowseTo(this->selected); 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)); if (this->abstract_filetype == FT_HEIGHTMAP) {
strecpy(_file_to_saveload.title, this->selected->title, lastof(_file_to_saveload.title));
if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
delete this; delete this;
ShowHeightmapLoad(); ShowHeightmapLoad();
} else if (!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()) { } 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; _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD_GAME;
ClearErrorMessages(); ClearErrorMessages();
@@ -563,7 +572,7 @@ public:
int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WD_FRAMERECT_TOP); int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WD_FRAMERECT_TOP);
if (y == INT_MAX) return; 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); const char *name = FiosBrowseTo(file);
if (name != NULL) { if (name != NULL) {
@@ -572,28 +581,32 @@ public:
this->selected = file; this->selected = file;
_load_check_data.Clear(); _load_check_data.Clear();
if (file->type == FIOS_TYPE_FILE || file->type == FIOS_TYPE_SCENARIO) { if (GetDetailedFileType(file->type) == DFT_GAME_FILE) {
SaveOrLoad(name, SL_LOAD_CHECK, NO_DIRECTORY, false); /* Other detailed file types cannot be checked before. */
SaveOrLoad(name, SLO_CHECK, DFT_GAME_FILE, NO_DIRECTORY, false);
} }
this->InvalidateData(1); 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 */ /* Copy clicked name to editbox */
this->filename_editbox.text.Assign(file->title); this->filename_editbox.text.Assign(file->title);
this->SetWidgetDirty(WID_SL_SAVE_OSK_TITLE); this->SetWidgetDirty(WID_SL_SAVE_OSK_TITLE);
} }
} else if (!_load_check_data.HasErrors()) { } else if (!_load_check_data.HasErrors()) {
this->selected = file; this->selected = file;
if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) { if (this->fop == SLO_LOAD) {
this->OnClick(pt, WID_SL_LOAD_BUTTON, 1); if (this->abstract_filetype == FT_SAVEGAME || this->abstract_filetype == FT_SCENARIO) {
} else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) { this->OnClick(pt, WID_SL_LOAD_BUTTON, 1);
SetFiosType(file->type); } else {
strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name)); assert(this->abstract_filetype == FT_HEIGHTMAP);
strecpy(_file_to_saveload.title, file->title, lastof(_file_to_saveload.title)); _file_to_saveload.SetMode(file->type);
_file_to_saveload.SetName(name);
_file_to_saveload.SetTitle(file->title);
delete this; delete this;
ShowHeightmapLoad(); ShowHeightmapLoad();
}
} }
} }
} else { } else {
@@ -608,10 +621,11 @@ public:
ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR);
} else { } else {
#if defined(ENABLE_NETWORK) #if defined(ENABLE_NETWORK)
switch (_saveload_mode) { assert(this->fop == SLO_LOAD);
switch (this->abstract_filetype) {
default: NOT_REACHED(); default: NOT_REACHED();
case SLD_LOAD_SCENARIO: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_SCENARIO); break; case FT_SCENARIO: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_SCENARIO); break;
case SLD_LOAD_HEIGHTMAP: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_HEIGHTMAP); break; case FT_HEIGHTMAP: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_HEIGHTMAP); break;
} }
#endif #endif
} }
@@ -639,9 +653,8 @@ public:
virtual void OnTimeout() virtual void OnTimeout()
{ {
/* This test protects against using widgets 11 and 12 which are only available /* Widgets WID_SL_DELETE_SELECTION and WID_SL_SAVE_GAME only exist when saving to a file. */
* in those saveload modes. */ if (this->fop != SLO_SAVE) return;
if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP)) return;
if (this->IsWidgetLowered(WID_SL_DELETE_SELECTION)) { // Delete button clicked if (this->IsWidgetLowered(WID_SL_DELETE_SELECTION)) { // Delete button clicked
if (!FiosDelete(this->filename_editbox.text.buf)) { if (!FiosDelete(this->filename_editbox.text.buf)) {
@@ -649,10 +662,10 @@ public:
} else { } else {
this->InvalidateData(); this->InvalidateData();
/* Reset file name to current date on successful delete */ /* 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 } 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; _switch_mode = SM_SAVE_GAME;
FiosMakeSavegameName(_file_to_saveload.name, this->filename_editbox.text.buf, lastof(_file_to_saveload.name)); FiosMakeSavegameName(_file_to_saveload.name, this->filename_editbox.text.buf, lastof(_file_to_saveload.name));
} else { } else {
@@ -683,28 +696,40 @@ public:
this->selected = NULL; this->selected = NULL;
_load_check_data.Clear(); _load_check_data.Clear();
if (!gui_scope) break; 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 */ /* FALL THROUGH */
case 1: case 1:
/* Selection changes */ /* Selection changes */
if (!gui_scope) break; if (!gui_scope) break;
if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
this->SetWidgetDisabledState(WID_SL_LOAD_BUTTON, this->selected == NULL || _load_check_data.HasErrors()); 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;
}
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;
}
default:
NOT_REACHED();
} }
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_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();
break; break;
} }
} }
@@ -734,70 +759,24 @@ static WindowDesc _save_dialog_desc(
_nested_save_dialog_widgets, lengthof(_nested_save_dialog_widgets) _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. * 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); DeleteWindowById(WC_SAVELOAD, 0);
WindowDesc *sld; WindowDesc *sld;
switch (mode) { if (fop == SLO_SAVE) {
case SLD_SAVE_GAME: sld = &_save_dialog_desc;
case SLD_SAVE_SCENARIO: } else {
case SLD_SAVE_HEIGHTMAP: /* Dialogue for loading a file. */
sld = &_save_dialog_desc; break; sld = (abstract_filetype == FT_HEIGHTMAP) ? &_load_heightmap_dialog_desc : &_load_dialog_desc;
case SLD_LOAD_HEIGHTMAP:
sld = &_load_heightmap_dialog_desc; break;
default:
sld = &_load_dialog_desc; break;
} }
_saveload_mode = mode; _file_to_saveload.abstract_ftype = abstract_filetype;
_file_to_saveload.filetype = _file_modetotype[mode];
new SaveLoadWindow(sld, mode); new SaveLoadWindow(sld, abstract_filetype, fop);
}
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;
}
} }

View File

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

View File

@@ -27,6 +27,7 @@
#include "town.h" #include "town.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "core/random_func.hpp" #include "core/random_func.hpp"
#include "saveload/saveload.h"
#include "progress.h" #include "progress.h"
#include "error.h" #include "error.h"
@@ -875,7 +876,7 @@ static void _ShowGenerateLandscape(GenerateLandscapeWindowMode mode)
if (mode == GLWM_HEIGHTMAP) { if (mode == GLWM_HEIGHTMAP) {
/* If the function returns negative, it means there was a problem loading the 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; 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 * If map == NULL only the size of the PNG is read, otherwise a map
* with grayscale pixels is allocated and assigned to *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; FILE *fp;
png_structp png_ptr = NULL; 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 * If map == NULL only the size of the BMP is read, otherwise a map
* with grayscale pixels is allocated and assigned to *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; FILE *f;
BmpInfo info; 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) { switch (dft) {
default: NOT_REACHED(); default:
NOT_REACHED();
#ifdef WITH_PNG #ifdef WITH_PNG
case SL_PNG: case DFT_HEIGHTMAP_PNG:
return ReadHeightmapPNG(filename, x, y, map); return ReadHeightmapPNG(filename, x, y, map);
#endif /* WITH_PNG */ #endif /* WITH_PNG */
case SL_BMP:
case DFT_HEIGHTMAP_BMP:
return ReadHeightmapBMP(filename, x, y, map); return ReadHeightmapBMP(filename, x, y, map);
} }
} }
/** /**
* Get the dimensions of a heightmap. * Get the dimensions of a heightmap.
* @param dft Type of image file.
* @param filename to query * @param filename to query
* @param x dimension x * @param x dimension x
* @param y dimension y * @param y dimension y
* @return Returns false if loading of the image failed. * @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 * Load a heightmap from file and change the map in his current dimensions
* to a landscape representing the heightmap. * to a landscape representing the heightmap.
* It converts pixels to height. The brighter, the higher. * It converts pixels to height. The brighter, the higher.
* @param dft Type of image file.
* @param filename of the heightmap file to be imported * @param filename of the heightmap file to be imported
*/ */
void LoadHeightmap(char *filename) void LoadHeightmap(DetailedFileType dft, const char *filename)
{ {
uint x, y; uint x, y;
byte *map = NULL; byte *map = NULL;
if (!ReadHeightMap(filename, &x, &y, &map)) { if (!ReadHeightMap(dft, filename, &x, &y, &map)) {
free(map); free(map);
return; return;
} }

View File

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

View File

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

View File

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

View File

@@ -525,7 +525,7 @@ bool ClientNetworkGameSocketHandler::IsConnected()
* DEF_CLIENT_RECEIVE_COMMAND has parameter: Packet *p * 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) 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 */ /* The map is done downloading, load it */
ClearErrorMessages(); 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! */ /* Long savegame loads shouldn't affect the lag calculation! */
this->last_packet = _realtime_tick; this->last_packet = _realtime_tick;

View File

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

View File

@@ -359,7 +359,7 @@ static void LoadIntroGame(bool load_newgrfs = true)
SetupColoursAndInitialWindow(); SetupColoursAndInitialWindow();
/* Load the default opening screen savegame */ /* 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. GenerateWorld(GWM_EMPTY, 64, 64); // if failed loading, make empty world.
WaitTillGeneratedWorld(); WaitTillGeneratedWorld();
SetLocalCompany(COMPANY_SPECTATOR); 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 'e': _switch_mode = (_switch_mode == SM_LOAD_GAME || _switch_mode == SM_LOAD_SCENARIO ? SM_LOAD_SCENARIO : SM_EDITOR); break;
case 'g': case 'g':
if (mgo.opt != NULL) { if (mgo.opt != NULL) {
strecpy(_file_to_saveload.name, mgo.opt, lastof(_file_to_saveload.name)); _file_to_saveload.SetName(mgo.opt);
_switch_mode = (_switch_mode == SM_EDITOR || _switch_mode == SM_LOAD_SCENARIO ? SM_LOAD_SCENARIO : SM_LOAD_GAME); bool is_scenario = _switch_mode == SM_EDITOR || _switch_mode == SM_LOAD_SCENARIO;
_file_to_saveload.mode = SL_LOAD; _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 */ /* 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, '.'); const char *t = strrchr(_file_to_saveload.name, '.');
if (t != NULL) { if (t != NULL) {
FiosType ft = FiosGetSavegameListCallback(SLD_LOAD_GAME, _file_to_saveload.name, t, NULL, NULL); FiosType ft = FiosGetSavegameListCallback(SLO_LOAD, _file_to_saveload.name, t, NULL, NULL);
if (ft != FIOS_TYPE_INVALID) SetFiosType(ft); if (ft != FIOS_TYPE_INVALID) _file_to_saveload.SetMode(ft);
} }
break; break;
@@ -679,10 +680,10 @@ int openttd_main(int argc, char *argv[])
char title[80]; char title[80];
title[0] = '\0'; 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(); _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()) { if (res != SL_OK || _load_check_data.HasErrors()) {
fprintf(stderr, "Failed to open savegame\n"); fprintf(stderr, "Failed to open savegame\n");
if (_load_check_data.HasErrors()) { 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 subdir default directory to look for filename, set to 0 if not needed
* @param lf Load filter to use, if NULL: use filename + subdir. * @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; GameMode ogm = _game_mode;
_game_mode = newgm; _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_OK: return true;
case SL_REINIT: case SL_REINIT:
@@ -1152,11 +1154,11 @@ void SwitchToMode(SwitchMode new_mode)
ResetGRFConfig(true); ResetGRFConfig(true);
ResetWindowSystem(); 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()); SetDParamStr(0, GetSaveLoadErrorString());
ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
} else { } 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. */ /* Reset engine pool to simplify changing engine NewGRFs in scenario editor. */
EngineOverrideManager::ResetToCurrentNewGRFConfig(); EngineOverrideManager::ResetToCurrentNewGRFConfig();
} }
@@ -1197,7 +1199,7 @@ void SwitchToMode(SwitchMode new_mode)
break; break;
case SM_LOAD_SCENARIO: { // Load scenario from scenario editor 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); SetLocalCompany(OWNER_NONE);
_settings_newgame.game_creation.starting_year = _cur_year; _settings_newgame.game_creation.starting_year = _cur_year;
/* Cancel the saveload pausing */ /* Cancel the saveload pausing */
@@ -1219,7 +1221,7 @@ void SwitchToMode(SwitchMode new_mode)
case SM_SAVE_GAME: // Save game. case SM_SAVE_GAME: // Save game.
/* Make network saved games on pause compatible to singleplayer */ /* 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()); SetDParamStr(0, GetSaveLoadErrorString());
ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
} else { } else {
@@ -1514,7 +1516,7 @@ void StateGameLoop()
/* Save the desync savegame if needed. */ /* Save the desync savegame if needed. */
char name[MAX_PATH]; char name[MAX_PATH];
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date); 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); CheckCaches(false);
@@ -1578,7 +1580,7 @@ static void DoAutosave()
} }
DEBUG(sl, 2, "Autosaving to '%s'", buf); 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); 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'; return file[3] == '\0';
} }
void FiosGetDrives() void FiosGetDrives(FileList &file_list)
{ {
uint disk, disk2, save, total; uint disk, disk2, save, total;
@@ -75,7 +75,7 @@ void FiosGetDrives()
#endif #endif
if (disk == disk2) { if (disk == disk2) {
FiosItem *fios = _fios_items.Append(); FiosItem *fios = file_list.Append();
fios->type = FIOS_TYPE_DRIVE; fios->type = FIOS_TYPE_DRIVE;
fios->mtime = 0; fios->mtime = 0;
#ifndef __INNOTEK_LIBC__ #ifndef __INNOTEK_LIBC__

View File

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

View File

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

View File

@@ -143,6 +143,7 @@ void SlXvSetCurrentState()
*/ */
void SlXvCheckSpecialSavegameVersions() void SlXvCheckSpecialSavegameVersions()
{ {
// Checks for special savegame versions go here
extern uint16 _sl_version; extern uint16 _sl_version;
if (_sl_version == 2000) { 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 const uint16 SAVEGAME_VERSION_EXT = 0x8000; ///< Savegame extension indicator mask
SavegameType _savegame_type; ///< type of savegame we are loading 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) uint32 _ttdp_version; ///< version of TTDP savegame (if applicable)
uint16 _sl_version; ///< the major savegame version identifier uint16 _sl_version; ///< the major savegame version identifier
@@ -2866,10 +2867,10 @@ SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
* @param threaded True when threaded saving is allowed * @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) * @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 */ /* 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 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); if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
return SL_OK; return SL_OK;
@@ -2878,7 +2879,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
try { try {
/* Load a TTDLX or TTDPatch game */ /* 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 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 /* 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; return SL_OK;
} }
switch (mode) { assert(dft == DFT_GAME_FILE);
case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break; switch (fop) {
case SL_LOAD: _sl.action = SLA_LOAD; break; case SLO_CHECK:
case SL_SAVE: _sl.action = SLA_SAVE; break; _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(); 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 */ /* 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 && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR); if (fh == NULL && fop != SLO_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", SCENARIO_DIR);
if (fh == NULL) { 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); 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; 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 */ /* LOAD game */
assert(mode == SL_LOAD || mode == SL_LOAD_CHECK); assert(fop == SLO_LOAD || fop == SLO_CHECK);
DEBUG(desync, 1, "load: %s", filename); DEBUG(desync, 1, "load: %s", filename);
return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK); return DoLoad(new FileReader(fh), fop == SLO_CHECK);
} catch (...) { } catch (...) {
/* This code may be executed both for old and new save games. */
ClearSaveLoadState(); ClearSaveLoadState();
/* Skip the "colour" character */ /* 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! */ /* 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) */ /** Do a save when exiting the game (_settings_client.gui.autosave_on_exit) */
void DoExitSave() 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); 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 #if 0
/** /**
* Function to get the type of the savegame by looking at the file header. * 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) 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 */ /** Deals with the type of the savegame, independent of extension */
enum SaveOrLoadMode { struct FileToSaveLoad {
SL_INVALID = -1, ///< Invalid mode. SaveLoadOperation file_op; ///< File operation to perform.
SL_LOAD = 0, ///< Load game. DetailedFileType detail_ftype; ///< Concrete file type (PNG, BMP, old save, etc).
SL_SAVE = 1, ///< Save game. AbstractFileType abstract_ftype; ///< Abstract type of file (scenario, heightmap, etc).
SL_OLD_LOAD = 2, ///< Load old game. char name[MAX_PATH]; ///< Name of the file.
SL_PNG = 3, ///< Load PNG file (height map). char title[255]; ///< Internal name of the game.
SL_BMP = 4, ///< Load BMP file (height map).
SL_LOAD_CHECK = 5, ///< Load for game preview. 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. */ /** Types of save games. */
@@ -46,10 +49,12 @@ enum SavegameType {
SGT_INVALID = 0xFF, ///< broken savegame (used internally) SGT_INVALID = 0xFF, ///< broken savegame (used internally)
}; };
extern FileToSaveLoad _file_to_saveload;
void GenerateDefaultSaveName(char *buf, const char *last); void GenerateDefaultSaveName(char *buf, const char *last);
void SetSaveLoadError(uint16 str); void SetSaveLoadError(uint16 str);
const char *GetSaveLoadErrorString(); 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 WaitTillSaved();
void ProcessAsyncSaveFinish(); void ProcessAsyncSaveFinish();
void DoExitSave(); void DoExitSave();

View File

@@ -60,7 +60,7 @@ static void Load_SIGN()
} }
/* Signs placed in scenario editor shall now be OWNER_DEITY */ /* 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; 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 */ /** Sorted list of PATX settings, generated by MakeSettingsPatxList */
static std::vector<const SettingDesc *> _sorted_patx_settings; 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 * 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 * 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); _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() * 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 // 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); 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; 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) { if (exact_match) {
assert(iter != _sorted_patx_settings.end()); 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 * Save handler for settings which go in the PATX chunk
* @param sd SettingDesc struct containing all information * @param sd SettingDesc struct containing all information
@@ -2488,6 +2454,10 @@ static void SaveSettingsPatx(const SettingDesc *sd, void *object)
{ {
SettingsExtSave current_setting; SettingsExtSave current_setting;
struct SettingToAdd {
const SettingDesc *setting;
uint32 setting_length;
};
std::vector<SettingToAdd> settings_to_add; std::vector<SettingToAdd> settings_to_add;
size_t length = 8; size_t length = 8;

View File

@@ -361,21 +361,8 @@ typedef unsigned char byte;
#define PERSONAL_DIR "" #define PERSONAL_DIR ""
#endif #endif
/* Compile time assertions. Prefer c++0x static_assert(). #define assert_compile(expr) static_assert(expr, #expr )
* Older compilers cannot evaluate some expressions at compile time, #define assert_tcompile(expr) assert_compile(expr)
* 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
/* Check if the types have the bitsizes like we are using them */ /* Check if the types have the bitsizes like we are using them */
assert_compile(sizeof(uint64) == 8); assert_compile(sizeof(uint64) == 8);

View File

@@ -17,7 +17,7 @@
#define NIP_END() { NULL, 0, 0, 0, 0 } #define NIP_END() { NULL, 0, 0, 0, 0 }
/* Helper for filling callback tables */ /* 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 } #define NIC_END() { NULL, 0, 0, 0, 0 }
/* Helper for filling variable tables */ /* Helper for filling variable tables */

View File

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

View File

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

View File

@@ -142,7 +142,7 @@ static void *_dedicated_video_mem;
/* Whether a fork has been done. */ /* Whether a fork has been done. */
bool _dedicated_forks; 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; static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
@@ -286,7 +286,7 @@ void VideoDriver_Dedicated::MainLoop()
_switch_mode = SM_NONE; _switch_mode = SM_NONE;
/* First we need to test if the savegame can be loaded, else we will end up playing the /* First we need to test if the savegame can be loaded, else we will end up playing the
* intro game... */ * 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.. */ /* Loading failed, pop out.. */
DEBUG(net, 0, "Loading requested map failed, aborting"); DEBUG(net, 0, "Loading requested map failed, aborting");
_networking = false; _networking = false;