Merge branch 'save_ext' into improved_breakdowns
# Conflicts: # src/train_cmd.cpp
This commit is contained in:
@@ -248,7 +248,7 @@ static void InitializeWindowsAndCaches()
|
||||
/* For each company, verify (while loading a scenario) that the inauguration date is the current year and set it
|
||||
* accordingly if it is not the case. No need to set it on companies that are not been used already,
|
||||
* thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */
|
||||
if (_file_to_saveload.filetype == FT_SCENARIO && c->inaugurated_year != MIN_YEAR) {
|
||||
if (_file_to_saveload.abstract_ftype == FT_SCENARIO && c->inaugurated_year != MIN_YEAR) {
|
||||
c->inaugurated_year = _cur_year;
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "../tunnelbridge_map.h"
|
||||
#include "../tunnelbridge.h"
|
||||
#include "../station_base.h"
|
||||
#include "../settings_func.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
@@ -486,6 +487,7 @@ static void Load_PLYR()
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Company *c = new (index) Company();
|
||||
SetDefaultCompanySettings(c->index);
|
||||
SaveLoad_PLYR(c);
|
||||
_company_colours[index] = (Colours)c->colour;
|
||||
}
|
||||
@@ -529,7 +531,25 @@ static void Ptrs_PLYR()
|
||||
}
|
||||
}
|
||||
|
||||
extern void LoadSettingsPlyx(bool skip);
|
||||
extern void SaveSettingsPlyx();
|
||||
|
||||
static void Load_PLYX()
|
||||
{
|
||||
LoadSettingsPlyx(false);
|
||||
}
|
||||
|
||||
static void Check_PLYX()
|
||||
{
|
||||
LoadSettingsPlyx(true);
|
||||
}
|
||||
|
||||
static void Save_PLYX()
|
||||
{
|
||||
SaveSettingsPlyx();
|
||||
}
|
||||
|
||||
extern const ChunkHandler _company_chunk_handlers[] = {
|
||||
{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY | CH_LAST},
|
||||
{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY },
|
||||
{ 'PLYX', Save_PLYX, Load_PLYX, NULL, Check_PLYX, CH_RIFF | CH_LAST},
|
||||
};
|
||||
|
@@ -87,6 +87,20 @@ bool SlXvIsFeaturePresent(SlXvFeatureIndex feature, uint16 min_version, uint16 m
|
||||
return _sl_xv_feature_versions[feature] >= min_version && _sl_xv_feature_versions[feature] <= max_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if @p feature is present and has a version inclusively bounded by @p min_version and @p max_version
|
||||
*/
|
||||
const char *SlXvGetFeatureName(SlXvFeatureIndex feature)
|
||||
{
|
||||
const SlxiSubChunkInfo *info = _sl_xv_sub_chunk_infos;
|
||||
for (; info->index != XSLFI_NULL; ++info) {
|
||||
if (info->index == feature) {
|
||||
return info->name;
|
||||
}
|
||||
}
|
||||
return "(unknown feature)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all extended feature versions to 0
|
||||
*/
|
||||
@@ -116,9 +130,7 @@ void SlXvSetCurrentState()
|
||||
*/
|
||||
void SlXvCheckSpecialSavegameVersions()
|
||||
{
|
||||
extern uint16 _sl_version;
|
||||
|
||||
// TODO: check for savegame versions
|
||||
// Checks for special savegame versions go here
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +177,6 @@ static void Save_SLXI()
|
||||
SlXvSetCurrentState();
|
||||
|
||||
static const SaveLoad _xlsi_sub_chunk_desc[] = {
|
||||
SLE_VAR(SlxiSubChunkInfo, save_version, SLE_UINT16),
|
||||
SLE_STR(SlxiSubChunkInfo, name, SLE_STR, 0),
|
||||
SLE_END()
|
||||
};
|
||||
@@ -179,9 +190,9 @@ static void Save_SLXI()
|
||||
chunk_counts.resize(XSLFI_SIZE);
|
||||
const SlxiSubChunkInfo *info = _sl_xv_sub_chunk_infos;
|
||||
for (; info->index != XSLFI_NULL; ++info) {
|
||||
if (info->save_version > 0) {
|
||||
if (_sl_xv_feature_versions[info->index] > 0) {
|
||||
item_count++;
|
||||
length += 4;
|
||||
length += 6;
|
||||
length += SlCalcObjLength(info, _xlsi_sub_chunk_desc);
|
||||
if (info->save_proc) {
|
||||
uint32 extra_data_length = info->save_proc(info, true);
|
||||
@@ -209,7 +220,8 @@ static void Save_SLXI()
|
||||
// write data
|
||||
info = _sl_xv_sub_chunk_infos;
|
||||
for (; info->index != XSLFI_NULL; ++info) {
|
||||
if (info->save_version > 0) {
|
||||
uint16 save_version = _sl_xv_feature_versions[info->index];
|
||||
if (save_version > 0) {
|
||||
SlxiSubChunkFlags flags = info->flags;
|
||||
assert(!(flags & (XSCF_EXTRA_DATA_PRESENT | XSCF_CHUNK_ID_LIST_PRESENT)));
|
||||
uint32 extra_data_length = extra_data_lengths[info->index];
|
||||
@@ -217,6 +229,7 @@ static void Save_SLXI()
|
||||
if (extra_data_length > 0) flags |= XSCF_EXTRA_DATA_PRESENT;
|
||||
if (chunk_count > 0) flags |= XSCF_CHUNK_ID_LIST_PRESENT;
|
||||
SlWriteUint32(flags);
|
||||
SlWriteUint16(save_version);
|
||||
SlObject(const_cast<SlxiSubChunkInfo *>(info), _xlsi_sub_chunk_desc);
|
||||
|
||||
if (extra_data_length > 0) {
|
||||
|
@@ -66,6 +66,8 @@ inline bool SlXvIsFeatureMissing(SlXvFeatureIndex feature)
|
||||
return !SlXvIsFeaturePresent(feature);
|
||||
}
|
||||
|
||||
const char *SlXvGetFeatureName(SlXvFeatureIndex feature);
|
||||
|
||||
/**
|
||||
* sub chunk flags, this is saved as-is
|
||||
* (XSCF_EXTRA_DATA_PRESENT and XSCF_CHUNK_ID_LIST_PRESENT must only be set by the save code, and read by the load code)
|
||||
|
@@ -1165,7 +1165,7 @@ static const OldChunks vehicle_chunk[] = {
|
||||
|
||||
OCL_SVAR( OC_UINT8, Vehicle, owner ),
|
||||
OCL_SVAR( OC_TILE, Vehicle, tile ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, cur_image ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, sprite_seq.seq[0].sprite ),
|
||||
|
||||
OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
|
||||
|
||||
@@ -1258,7 +1258,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
||||
if (v == NULL) continue;
|
||||
v->refit_cap = v->cargo_cap;
|
||||
|
||||
SpriteID sprite = v->cur_image;
|
||||
SpriteID sprite = v->sprite_seq.seq[0].sprite;
|
||||
/* no need to override other sprites */
|
||||
if (IsInsideMM(sprite, 1460, 1465)) {
|
||||
sprite += 580; // aircraft smoke puff
|
||||
@@ -1269,7 +1269,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
||||
} else if (IsInsideMM(sprite, 2516, 2539)) {
|
||||
sprite += 1385; // rotor or disaster-related vehicles
|
||||
}
|
||||
v->cur_image = sprite;
|
||||
v->sprite_seq.seq[0].sprite = sprite;
|
||||
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: {
|
||||
|
@@ -52,6 +52,7 @@
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
@@ -264,12 +265,14 @@
|
||||
* 191 26646
|
||||
* 192 26700
|
||||
* 193 26802
|
||||
* 194 26881 1.5.x
|
||||
* 194 26881 1.5.x, 1.6.0
|
||||
* 195 27572 1.6.x
|
||||
*/
|
||||
extern const uint16 SAVEGAME_VERSION = 194; ///< Current savegame version of OpenTTD.
|
||||
extern const uint16 SAVEGAME_VERSION = 195; ///< Current savegame version of OpenTTD.
|
||||
const uint16 SAVEGAME_VERSION_EXT = 0x8000; ///< Savegame extension indicator mask
|
||||
|
||||
SavegameType _savegame_type; ///< type of savegame we are loading
|
||||
FileToSaveLoad _file_to_saveload; ///< File to save or load in the openttd loop.
|
||||
|
||||
uint32 _ttdp_version; ///< version of TTDP savegame (if applicable)
|
||||
uint16 _sl_version; ///< the major savegame version identifier
|
||||
@@ -564,7 +567,7 @@ void NORETURN SlError(StringID string, const char *extra_msg, bool already_mallo
|
||||
/**
|
||||
* As SlError, except that it takes a format string and additional parameters
|
||||
*/
|
||||
void CDECL NORETURN SlErrorFmt(StringID string, const char *msg, ...)
|
||||
void NORETURN CDECL SlErrorFmt(StringID string, const char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
@@ -588,7 +591,7 @@ void NORETURN SlErrorCorrupt(const char *msg, bool already_malloced)
|
||||
/**
|
||||
* As SlErrorCorruptFmt, except that it takes a format string and additional parameters
|
||||
*/
|
||||
void CDECL NORETURN SlErrorCorruptFmt(const char *msg, ...)
|
||||
void NORETURN CDECL SlErrorCorruptFmt(const char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
@@ -888,9 +891,20 @@ void SlSetLength(size_t length)
|
||||
case CH_RIFF:
|
||||
/* Ugly encoding of >16M RIFF chunks
|
||||
* The lower 24 bits are normal
|
||||
* The uppermost 4 bits are bits 24:27 */
|
||||
assert(length < (1 << 28));
|
||||
* The uppermost 4 bits are bits 24:27
|
||||
*
|
||||
* If we have more than 28 bits, use an extra uint32 and
|
||||
* signal this using the extended chunk header */
|
||||
assert(length < (1LL << 32));
|
||||
if (length >= (1 << 28)) {
|
||||
/* write out extended chunk header */
|
||||
SlWriteByte(CH_EXT_HDR);
|
||||
SlWriteUint32(static_cast<uint32>(SLCEHF_BIG_RIFF));
|
||||
}
|
||||
SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
|
||||
if (length >= (1 << 28)) {
|
||||
SlWriteUint32(length >> 28);
|
||||
}
|
||||
break;
|
||||
case CH_ARRAY:
|
||||
assert(_sl.last_array_index <= _sl.array_index);
|
||||
@@ -1353,9 +1367,10 @@ static void *IntToReference(size_t index, SLRefType rt)
|
||||
* Return the size in bytes of a list
|
||||
* @param list The std::list to find the size of
|
||||
*/
|
||||
template<typename PtrList>
|
||||
static inline size_t SlCalcListLen(const void *list)
|
||||
{
|
||||
const std::list<void *> *l = (const std::list<void *> *) list;
|
||||
const PtrList *l = (const PtrList *) list;
|
||||
|
||||
int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
|
||||
/* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
|
||||
@@ -1369,23 +1384,23 @@ static inline size_t SlCalcListLen(const void *list)
|
||||
* @param list The list being manipulated
|
||||
* @param conv SLRefType type of the list (Vehicle *, Station *, etc)
|
||||
*/
|
||||
template<typename PtrList>
|
||||
static void SlList(void *list, SLRefType conv)
|
||||
{
|
||||
/* Automatically calculate the length? */
|
||||
if (_sl.need_length != NL_NONE) {
|
||||
SlSetLength(SlCalcListLen(list));
|
||||
SlSetLength(SlCalcListLen<PtrList>(list));
|
||||
/* Determine length only? */
|
||||
if (_sl.need_length == NL_CALCLENGTH) return;
|
||||
}
|
||||
|
||||
typedef std::list<void *> PtrList;
|
||||
PtrList *l = (PtrList *)list;
|
||||
|
||||
switch (_sl.action) {
|
||||
case SLA_SAVE: {
|
||||
SlWriteUint32((uint32)l->size());
|
||||
|
||||
PtrList::iterator iter;
|
||||
typename PtrList::iterator iter;
|
||||
for (iter = l->begin(); iter != l->end(); ++iter) {
|
||||
void *ptr = *iter;
|
||||
SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
|
||||
@@ -1407,7 +1422,7 @@ static void SlList(void *list, SLRefType conv)
|
||||
PtrList temp = *l;
|
||||
|
||||
l->clear();
|
||||
PtrList::iterator iter;
|
||||
typename PtrList::iterator iter;
|
||||
for (iter = temp.begin(); iter != temp.end(); ++iter) {
|
||||
void *ptr = IntToReference((size_t)*iter, conv);
|
||||
l->push_back(ptr);
|
||||
@@ -1473,6 +1488,8 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
|
||||
case SL_ARR:
|
||||
case SL_STR:
|
||||
case SL_LST:
|
||||
case SL_DEQ:
|
||||
case SL_VEC:
|
||||
/* CONDITIONAL saveload types depend on the savegame version */
|
||||
if (!SlIsObjectValidInSavegame(sld)) break;
|
||||
|
||||
@@ -1481,7 +1498,9 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
|
||||
case SL_REF: return SlCalcRefLen();
|
||||
case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
|
||||
case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
|
||||
case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
|
||||
case SL_LST: return SlCalcListLen<std::list<void *>>(GetVariableAddress(object, sld));
|
||||
case SL_DEQ: return SlCalcListLen<std::deque<void *>>(GetVariableAddress(object, sld));
|
||||
case SL_VEC: return SlCalcListLen<std::vector<void *>>(GetVariableAddress(object, sld));
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
@@ -1493,6 +1512,8 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef OTTD_ASSERT
|
||||
|
||||
/**
|
||||
* Check whether the variable size of the variable in the saveload configuration
|
||||
* matches with the actual variable size.
|
||||
@@ -1533,9 +1554,13 @@ static bool IsVariableSizeRight(const SaveLoad *sld)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OTTD_ASSERT */
|
||||
|
||||
bool SlObjectMember(void *ptr, const SaveLoad *sld)
|
||||
{
|
||||
#ifdef OTTD_ASSERT
|
||||
assert(IsVariableSizeRight(sld));
|
||||
#endif
|
||||
|
||||
VarType conv = GB(sld->conv, 0, 8);
|
||||
switch (sld->cmd) {
|
||||
@@ -1544,6 +1569,8 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
|
||||
case SL_ARR:
|
||||
case SL_STR:
|
||||
case SL_LST:
|
||||
case SL_DEQ:
|
||||
case SL_VEC:
|
||||
/* CONDITIONAL saveload types depend on the savegame version */
|
||||
if (!SlIsObjectValidInSavegame(sld)) return false;
|
||||
if (SlSkipVariableOnLoad(sld)) return false;
|
||||
@@ -1570,7 +1597,9 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
|
||||
break;
|
||||
case SL_ARR: SlArray(ptr, sld->length, conv); break;
|
||||
case SL_STR: SlString(ptr, sld->length, sld->conv); break;
|
||||
case SL_LST: SlList(ptr, (SLRefType)conv); break;
|
||||
case SL_LST: SlList<std::list<void *>>(ptr, (SLRefType)conv); break;
|
||||
case SL_DEQ: SlList<std::deque<void *>>(ptr, (SLRefType)conv); break;
|
||||
case SL_VEC: SlList<std::vector<void *>>(ptr, (SLRefType)conv); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
@@ -1661,6 +1690,16 @@ void SlAutolength(AutolengthProc *proc, void *arg)
|
||||
if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
|
||||
}
|
||||
|
||||
/*
|
||||
* Notes on extended chunk header:
|
||||
*
|
||||
* If the chunk type is CH_EXT_HDR (15), then a u32 flags field follows.
|
||||
* This flag field may define additional fields which follow the flags field in future.
|
||||
* The standard chunk header follows, though it my be modified by the flags field.
|
||||
* At present SLCEHF_BIG_RIFF increases the RIFF size limit to a theoretical 60 bits,
|
||||
* by adding a further u32 field for the high bits after the existing RIFF size field.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load a chunk of data (eg vehicles, stations, etc.)
|
||||
* @param ch The chunkhandler that will be used for the operation
|
||||
@@ -1674,6 +1713,15 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
||||
_sl.block_mode = m;
|
||||
_sl.obj_len = 0;
|
||||
|
||||
SaveLoadChunkExtHeaderFlags ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(0);
|
||||
if ((m & 0xF) == CH_EXT_HDR) {
|
||||
ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(SlReadUint32());
|
||||
|
||||
/* read in real header */
|
||||
m = SlReadByte();
|
||||
_sl.block_mode = m;
|
||||
}
|
||||
|
||||
switch (m) {
|
||||
case CH_ARRAY:
|
||||
_sl.array_index = 0;
|
||||
@@ -1689,6 +1737,10 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
||||
/* Read length */
|
||||
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
||||
len += SlReadUint16();
|
||||
if (ext_flags & SLCEHF_BIG_RIFF) {
|
||||
len |= SlReadUint32() << 28;
|
||||
}
|
||||
|
||||
_sl.obj_len = len;
|
||||
endoffs = _sl.reader->GetSize() + len;
|
||||
ch->load_proc();
|
||||
@@ -1714,9 +1766,21 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
||||
_sl.block_mode = m;
|
||||
_sl.obj_len = 0;
|
||||
|
||||
SaveLoadChunkExtHeaderFlags ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(0);
|
||||
if ((m & 0xF) == CH_EXT_HDR) {
|
||||
ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(SlReadUint32());
|
||||
|
||||
/* read in real header */
|
||||
m = SlReadByte();
|
||||
_sl.block_mode = m;
|
||||
}
|
||||
|
||||
switch (m) {
|
||||
case CH_ARRAY:
|
||||
_sl.array_index = 0;
|
||||
if (ext_flags) {
|
||||
SlErrorCorruptFmt("CH_ARRAY does not take chunk header extension flags: 0x%X", ext_flags);
|
||||
}
|
||||
if (ch && ch->load_check_proc) {
|
||||
ch->load_check_proc();
|
||||
} else {
|
||||
@@ -1724,6 +1788,9 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
||||
}
|
||||
break;
|
||||
case CH_SPARSE_ARRAY:
|
||||
if (ext_flags) {
|
||||
SlErrorCorruptFmt("CH_SPARSE_ARRAY does not take chunk header extension flags: 0x%X", ext_flags);
|
||||
}
|
||||
if (ch && ch->load_check_proc) {
|
||||
ch->load_check_proc();
|
||||
} else {
|
||||
@@ -1732,9 +1799,19 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
||||
break;
|
||||
default:
|
||||
if ((m & 0xF) == CH_RIFF) {
|
||||
if (ext_flags != (ext_flags & SLCEHF_BIG_RIFF)) {
|
||||
SlErrorCorruptFmt("Unknown chunk header extension flags for CH_RIFF: 0x%X", ext_flags);
|
||||
}
|
||||
/* Read length */
|
||||
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
||||
len += SlReadUint16();
|
||||
if (ext_flags & SLCEHF_BIG_RIFF) {
|
||||
uint64 full_len = len | (static_cast<uint64>(SlReadUint32()) << 28);
|
||||
if (full_len >= (1LL << 32)) {
|
||||
SlErrorCorrupt("Chunk size too large: " OTTD_PRINTFHEX64, full_len);
|
||||
}
|
||||
len = static_cast<size_t>(full_len);
|
||||
}
|
||||
_sl.obj_len = len;
|
||||
endoffs = _sl.reader->GetSize() + len;
|
||||
if (ch && ch->load_check_proc) {
|
||||
@@ -2478,7 +2555,7 @@ static void SaveFileStart()
|
||||
{
|
||||
_sl.ff_state = _fast_forward;
|
||||
_fast_forward = 0;
|
||||
if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
|
||||
SetMouseCursorBusy(true);
|
||||
|
||||
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START);
|
||||
_sl.saveinprogress = true;
|
||||
@@ -2488,7 +2565,7 @@ static void SaveFileStart()
|
||||
static void SaveFileDone()
|
||||
{
|
||||
if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state;
|
||||
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
|
||||
SetMouseCursorBusy(false);
|
||||
|
||||
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
|
||||
_sl.saveinprogress = false;
|
||||
@@ -2603,7 +2680,7 @@ static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
|
||||
SlSaveChunks();
|
||||
|
||||
SaveFileStart();
|
||||
if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
|
||||
if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread, "ottd:savegame")) {
|
||||
if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
|
||||
|
||||
SaveOrLoadResult result = SaveFileToDisk(false);
|
||||
@@ -2808,10 +2885,10 @@ SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
|
||||
* @param threaded True when threaded saving is allowed
|
||||
* @return Return the result of the action. #SL_OK, #SL_ERROR, or #SL_REINIT ("unload" the game)
|
||||
*/
|
||||
SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded)
|
||||
SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded)
|
||||
{
|
||||
/* An instance of saving is already active, so don't go saving again */
|
||||
if (_sl.saveinprogress && mode == SL_SAVE && threaded) {
|
||||
if (_sl.saveinprogress && fop == SLO_SAVE && dft == DFT_GAME_FILE && threaded) {
|
||||
/* if not an autosave, but a user action, show error message */
|
||||
if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
|
||||
return SL_OK;
|
||||
@@ -2820,7 +2897,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
|
||||
|
||||
try {
|
||||
/* Load a TTDLX or TTDPatch game */
|
||||
if (mode == SL_OLD_LOAD) {
|
||||
if (fop == SLO_LOAD && dft == DFT_OLD_GAME_FILE) {
|
||||
InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
|
||||
|
||||
/* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
|
||||
@@ -2843,25 +2920,35 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
|
||||
return SL_OK;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
|
||||
case SL_LOAD: _sl.action = SLA_LOAD; break;
|
||||
case SL_SAVE: _sl.action = SLA_SAVE; break;
|
||||
assert(dft == DFT_GAME_FILE);
|
||||
switch (fop) {
|
||||
case SLO_CHECK:
|
||||
_sl.action = SLA_LOAD_CHECK;
|
||||
break;
|
||||
|
||||
case SLO_LOAD:
|
||||
_sl.action = SLA_LOAD;
|
||||
break;
|
||||
|
||||
case SLO_SAVE:
|
||||
_sl.action = SLA_SAVE;
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
|
||||
FILE *fh = (fop == SLO_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
|
||||
|
||||
/* Make it a little easier to load savegames from the console */
|
||||
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
|
||||
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
|
||||
if (fh == NULL && mode != SL_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
|
||||
if (fh == NULL && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", SAVE_DIR);
|
||||
if (fh == NULL && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", BASE_DIR);
|
||||
if (fh == NULL && fop != SLO_SAVE) fh = FioFOpenFile(filename, "rb", SCENARIO_DIR);
|
||||
|
||||
if (fh == NULL) {
|
||||
SlError(mode == SL_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
|
||||
SlError(fop == SLO_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
|
||||
}
|
||||
|
||||
if (mode == SL_SAVE) { // SAVE game
|
||||
if (fop == SLO_SAVE) { // SAVE game
|
||||
DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
|
||||
if (_network_server || !_settings_client.gui.threaded_saves) threaded = false;
|
||||
|
||||
@@ -2869,24 +2956,25 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
|
||||
}
|
||||
|
||||
/* LOAD game */
|
||||
assert(mode == SL_LOAD || mode == SL_LOAD_CHECK);
|
||||
assert(fop == SLO_LOAD || fop == SLO_CHECK);
|
||||
DEBUG(desync, 1, "load: %s", filename);
|
||||
return DoLoad(new FileReader(fh), mode == SL_LOAD_CHECK);
|
||||
return DoLoad(new FileReader(fh), fop == SLO_CHECK);
|
||||
} catch (...) {
|
||||
/* This code may be executed both for old and new save games. */
|
||||
ClearSaveLoadState();
|
||||
|
||||
/* Skip the "colour" character */
|
||||
if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
|
||||
if (fop != SLO_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
|
||||
|
||||
/* A saver/loader exception!! reinitialize all variables to prevent crash! */
|
||||
return (mode == SL_LOAD || mode == SL_OLD_LOAD) ? SL_REINIT : SL_ERROR;
|
||||
return (fop == SLO_LOAD) ? SL_REINIT : SL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/** Do a save when exiting the game (_settings_client.gui.autosave_on_exit) */
|
||||
void DoExitSave()
|
||||
{
|
||||
SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
|
||||
SaveOrLoad("exit.sav", SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2924,6 +3012,53 @@ void GenerateDefaultSaveName(char *buf, const char *last)
|
||||
SanitizeFilename(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode and file type of the file to save or load based on the type of file entry at the file system.
|
||||
* @param ft Type of file entry of the file system.
|
||||
*/
|
||||
void FileToSaveLoad::SetMode(FiosType ft)
|
||||
{
|
||||
this->SetMode(SLO_LOAD, GetAbstractFileType(ft), GetDetailedFileType(ft));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode and file type of the file to save or load.
|
||||
* @param fop File operation being performed.
|
||||
* @param aft Abstract file type.
|
||||
* @param dft Detailed file type.
|
||||
*/
|
||||
void FileToSaveLoad::SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft)
|
||||
{
|
||||
if (aft == FT_INVALID || aft == FT_NONE) {
|
||||
this->file_op = SLO_INVALID;
|
||||
this->detail_ftype = DFT_INVALID;
|
||||
this->abstract_ftype = FT_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
this->file_op = fop;
|
||||
this->detail_ftype = dft;
|
||||
this->abstract_ftype = aft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the file.
|
||||
* @param name Name of the file.
|
||||
*/
|
||||
void FileToSaveLoad::SetName(const char *name)
|
||||
{
|
||||
strecpy(this->name, name, lastof(this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title of the file.
|
||||
* @param title Title of the file.
|
||||
*/
|
||||
void FileToSaveLoad::SetTitle(const char *title)
|
||||
{
|
||||
strecpy(this->title, title, lastof(this->title));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Function to get the type of the savegame by looking at the file header.
|
||||
|
@@ -25,15 +25,18 @@ enum SaveOrLoadResult {
|
||||
SL_REINIT = 2, ///< error that was caught in the middle of updating game state, need to clear it. (can only happen during load)
|
||||
};
|
||||
|
||||
/** Save or load mode. @see SaveOrLoad */
|
||||
enum SaveOrLoadMode {
|
||||
SL_INVALID = -1, ///< Invalid mode.
|
||||
SL_LOAD = 0, ///< Load game.
|
||||
SL_SAVE = 1, ///< Save game.
|
||||
SL_OLD_LOAD = 2, ///< Load old game.
|
||||
SL_PNG = 3, ///< Load PNG file (height map).
|
||||
SL_BMP = 4, ///< Load BMP file (height map).
|
||||
SL_LOAD_CHECK = 5, ///< Load for game preview.
|
||||
/** Deals with the type of the savegame, independent of extension */
|
||||
struct FileToSaveLoad {
|
||||
SaveLoadOperation file_op; ///< File operation to perform.
|
||||
DetailedFileType detail_ftype; ///< Concrete file type (PNG, BMP, old save, etc).
|
||||
AbstractFileType abstract_ftype; ///< Abstract type of file (scenario, heightmap, etc).
|
||||
char name[MAX_PATH]; ///< Name of the file.
|
||||
char title[255]; ///< Internal name of the game.
|
||||
|
||||
void SetMode(FiosType ft);
|
||||
void SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft);
|
||||
void SetName(const char *name);
|
||||
void SetTitle(const char *title);
|
||||
};
|
||||
|
||||
/** Types of save games. */
|
||||
@@ -46,10 +49,12 @@ enum SavegameType {
|
||||
SGT_INVALID = 0xFF, ///< broken savegame (used internally)
|
||||
};
|
||||
|
||||
extern FileToSaveLoad _file_to_saveload;
|
||||
|
||||
void GenerateDefaultSaveName(char *buf, const char *last);
|
||||
void SetSaveLoadError(uint16 str);
|
||||
const char *GetSaveLoadErrorString();
|
||||
SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, bool threaded = true);
|
||||
SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded = true);
|
||||
void WaitTillSaved();
|
||||
void ProcessAsyncSaveFinish();
|
||||
void DoExitSave();
|
||||
@@ -99,10 +104,17 @@ enum ChunkType {
|
||||
CH_ARRAY = 1,
|
||||
CH_SPARSE_ARRAY = 2,
|
||||
CH_TYPE_MASK = 3,
|
||||
CH_EXT_HDR = 15, ///< Extended chunk header
|
||||
CH_LAST = 8, ///< Last chunk in this array.
|
||||
CH_AUTO_LENGTH = 16,
|
||||
};
|
||||
|
||||
/** Flags for chunk extended headers */
|
||||
enum SaveLoadChunkExtHeaderFlags {
|
||||
SLCEHF_BIG_RIFF = 1 << 0, ///< This block uses a 60-bit RIFF chunk size
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(SaveLoadChunkExtHeaderFlags)
|
||||
|
||||
/**
|
||||
* VarTypes is the general bitmasked magic type that tells us
|
||||
* certain characteristics about the variable it refers to. For example
|
||||
@@ -193,6 +205,8 @@ enum SaveLoadTypes {
|
||||
SL_ARR = 2, ///< Save/load an array.
|
||||
SL_STR = 3, ///< Save/load a string.
|
||||
SL_LST = 4, ///< Save/load a list.
|
||||
SL_DEQ = 5, ///< Save/load a deque.
|
||||
SL_VEC = 6, ///< Save/load a vector.
|
||||
/* non-normal save-load types */
|
||||
SL_WRITEBYTE = 8,
|
||||
SL_VEH_INCLUDE = 9,
|
||||
@@ -234,7 +248,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @note In general, it is better to use one of the SLE_* macros below.
|
||||
*/
|
||||
#define SLE_GENERAL_X(cmd, base, variable, type, length, from, to, extver) {false, cmd, type, length, from, to, (void*)cpp_offsetof(base, variable), cpp_sizeof(base, variable), extver}
|
||||
#define SLE_GENERAL(cmd, base, variable, type, length, from, to) SLE_GENERAL_X(cmd, base, variable, type, length, from, to, {})
|
||||
#define SLE_GENERAL(cmd, base, variable, type, length, from, to) SLE_GENERAL_X(cmd, base, variable, type, length, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a variable in some savegame versions.
|
||||
@@ -246,7 +260,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDVAR_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_VAR, base, variable, type, 0, from, to, extver)
|
||||
#define SLE_CONDVAR(base, variable, type, from, to) SLE_CONDVAR_X(base, variable, type, from, to, {})
|
||||
#define SLE_CONDVAR(base, variable, type, from, to) SLE_CONDVAR_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a reference in some savegame versions.
|
||||
@@ -258,7 +272,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDREF_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_REF, base, variable, type, 0, from, to, extver)
|
||||
#define SLE_CONDREF(base, variable, type, from, to) SLE_CONDREF_X(base, variable, type, from, to, {})
|
||||
#define SLE_CONDREF(base, variable, type, from, to) SLE_CONDREF_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of an array in some savegame versions.
|
||||
@@ -271,7 +285,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDARR_X(base, variable, type, length, from, to, extver) SLE_GENERAL_X(SL_ARR, base, variable, type, length, from, to, extver)
|
||||
#define SLE_CONDARR(base, variable, type, length, from, to) SLE_CONDARR_X(base, variable, type, length, from, to, {})
|
||||
#define SLE_CONDARR(base, variable, type, length, from, to) SLE_CONDARR_X(base, variable, type, length, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a string in some savegame versions.
|
||||
@@ -284,7 +298,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDSTR_X(base, variable, type, length, from, to, extver) SLE_GENERAL_X(SL_STR, base, variable, type, length, from, to, extver)
|
||||
#define SLE_CONDSTR(base, variable, type, length, from, to) SLE_CONDSTR_X(base, variable, type, length, from, to, {})
|
||||
#define SLE_CONDSTR(base, variable, type, length, from, to) SLE_CONDSTR_X(base, variable, type, length, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a list in some savegame versions.
|
||||
@@ -296,7 +310,31 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDLST_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_LST, base, variable, type, 0, from, to, extver)
|
||||
#define SLE_CONDLST(base, variable, type, from, to) SLE_CONDLST_X(base, variable, type, from, to, {})
|
||||
#define SLE_CONDLST(base, variable, type, from, to) SLE_CONDLST_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a deque in some savegame versions.
|
||||
* @param base Name of the class or struct containing the list.
|
||||
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
* @param from First savegame version that has the list.
|
||||
* @param to Last savegame version that has the list.
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDDEQ_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_DEQ, base, variable, type, 0, from, to, extver)
|
||||
#define SLE_CONDDEQ(base, variable, type, from, to) SLE_CONDDEQ_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a vector in some savegame versions.
|
||||
* @param base Name of the class or struct containing the list.
|
||||
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
* @param from First savegame version that has the list.
|
||||
* @param to Last savegame version that has the list.
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLE_CONDVEC_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_VEC, base, variable, type, 0, from, to, extver)
|
||||
#define SLE_CONDVEC(base, variable, type, from, to) SLE_CONDVEC_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a variable in every version of a savegame.
|
||||
@@ -340,6 +378,22 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
*/
|
||||
#define SLE_LST(base, variable, type) SLE_CONDLST(base, variable, type, 0, SL_MAX_VERSION)
|
||||
|
||||
/**
|
||||
* Storage of a deque in every savegame version.
|
||||
* @param base Name of the class or struct containing the list.
|
||||
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
*/
|
||||
#define SLE_DEQ(base, variable, type) SLE_CONDDEQ(base, variable, type, 0, SL_MAX_VERSION)
|
||||
|
||||
/**
|
||||
* Storage of a vector in every savegame version.
|
||||
* @param base Name of the class or struct containing the list.
|
||||
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
*/
|
||||
#define SLE_VEC(base, variable, type) SLE_CONDVEC(base, variable, type, 0, SL_MAX_VERSION)
|
||||
|
||||
/**
|
||||
* Empty space in every savegame version.
|
||||
* @param length Length of the empty space.
|
||||
@@ -354,16 +408,16 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have empty space
|
||||
*/
|
||||
#define SLE_CONDNULL_X(length, from, to, extver) SLE_CONDARR_X(NullStruct, null, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, extver)
|
||||
#define SLE_CONDNULL(length, from, to) SLE_CONDNULL_X(length, from, to, {})
|
||||
#define SLE_CONDNULL(length, from, to) SLE_CONDNULL_X(length, from, to, SlXvFeatureTest())
|
||||
|
||||
/** Translate values ingame to different values in the savegame and vv. */
|
||||
#define SLE_WRITEBYTE(base, variable, value) SLE_GENERAL(SL_WRITEBYTE, base, variable, 0, 0, value, value)
|
||||
|
||||
#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0, {}}
|
||||
#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0, {}}
|
||||
#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0, SlXvFeatureTest()}
|
||||
#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0, SlXvFeatureTest()}
|
||||
|
||||
/** End marker of a struct/class save or load. */
|
||||
#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL, 0, {}}
|
||||
#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL, 0, SlXvFeatureTest()}
|
||||
|
||||
/**
|
||||
* Storage of global simple variables, references (pointers), and arrays.
|
||||
@@ -376,7 +430,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @note In general, it is better to use one of the SLEG_* macros below.
|
||||
*/
|
||||
#define SLEG_GENERAL_X(cmd, variable, type, length, from, to, extver) {true, cmd, type, length, from, to, (void*)&variable, sizeof(variable), extver}
|
||||
#define SLEG_GENERAL(cmd, variable, type, length, from, to) SLEG_GENERAL_X(cmd, variable, type, length, from, to, {})
|
||||
#define SLEG_GENERAL(cmd, variable, type, length, from, to) SLEG_GENERAL_X(cmd, variable, type, length, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global variable in some savegame versions.
|
||||
@@ -387,7 +441,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDVAR_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_VAR, variable, type, 0, from, to, extver)
|
||||
#define SLEG_CONDVAR(variable, type, from, to) SLEG_CONDVAR_X(variable, type, from, to, {})
|
||||
#define SLEG_CONDVAR(variable, type, from, to) SLEG_CONDVAR_X(variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global reference in some savegame versions.
|
||||
@@ -398,7 +452,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDREF_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_REF, variable, type, 0, from, to, extver)
|
||||
#define SLEG_CONDREF(variable, type, from, to) SLEG_CONDREF_X(variable, type, from, to, {})
|
||||
#define SLEG_CONDREF(variable, type, from, to) SLEG_CONDREF_X(variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global array in some savegame versions.
|
||||
@@ -410,7 +464,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDARR_X(variable, type, length, from, to, extver) SLEG_GENERAL_X(SL_ARR, variable, type, length, from, to, extver)
|
||||
#define SLEG_CONDARR(variable, type, length, from, to) SLEG_CONDARR_X(variable, type, length, from, to, {})
|
||||
#define SLEG_CONDARR(variable, type, length, from, to) SLEG_CONDARR_X(variable, type, length, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global string in some savegame versions.
|
||||
@@ -422,7 +476,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDSTR_X(variable, type, length, from, to, extver) SLEG_GENERAL_X(SL_STR, variable, type, length, from, to, extver)
|
||||
#define SLEG_CONDSTR(variable, type, length, from, to) SLEG_CONDSTR_X(variable, type, length, from, to, {})
|
||||
#define SLEG_CONDSTR(variable, type, length, from, to) SLEG_CONDSTR_X(variable, type, length, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global list in some savegame versions.
|
||||
@@ -433,7 +487,29 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDLST_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_LST, variable, type, 0, from, to, extver)
|
||||
#define SLEG_CONDLST(variable, type, from, to) SLEG_CONDLST_X(variable, type, from, to, {})
|
||||
#define SLEG_CONDLST(variable, type, from, to) SLEG_CONDLST_X(variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global deque in some savegame versions.
|
||||
* @param variable Name of the global variable.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
* @param from First savegame version that has the list.
|
||||
* @param to Last savegame version that has the list.
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDDEQ_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_DEQ, variable, type, 0, from, to, extver)
|
||||
#define SLEG_CONDDEQ(variable, type, from, to) SLEG_CONDDEQ_X(variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global vector in some savegame versions.
|
||||
* @param variable Name of the global variable.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
* @param from First savegame version that has the list.
|
||||
* @param to Last savegame version that has the list.
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||
*/
|
||||
#define SLEG_CONDVEC_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_VEC, variable, type, 0, from, to, extver)
|
||||
#define SLEG_CONDVEC(variable, type, from, to) SLEG_CONDVEC_X(variable, type, from, to, SlXvFeatureTest())
|
||||
|
||||
/**
|
||||
* Storage of a global variable in every savegame version.
|
||||
@@ -470,6 +546,20 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
*/
|
||||
#define SLEG_LST(variable, type) SLEG_CONDLST(variable, type, 0, SL_MAX_VERSION)
|
||||
|
||||
/**
|
||||
* Storage of a global deque in every savegame version.
|
||||
* @param variable Name of the global variable.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
*/
|
||||
#define SLEG_DEQ(variable, type) SLEG_CONDDEQ(variable, type, 0, SL_MAX_VERSION)
|
||||
|
||||
/**
|
||||
* Storage of a global vector in every savegame version.
|
||||
* @param variable Name of the global variable.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
*/
|
||||
#define SLEG_VEC(variable, type) SLEG_CONDVEC(variable, type, 0, SL_MAX_VERSION)
|
||||
|
||||
/**
|
||||
* Empty global space in some savegame versions.
|
||||
* @param length Length of the empty space.
|
||||
@@ -477,10 +567,10 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param to Last savegame version that has the empty space.
|
||||
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have empty space
|
||||
*/
|
||||
#define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, (void*)NULL, {}}
|
||||
#define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, (void*)NULL, SlXvFeatureTest()}
|
||||
|
||||
/** End marker of global variables save or load. */
|
||||
#define SLEG_END() {true, SL_END, 0, 0, 0, 0, NULL, 0, {}}
|
||||
#define SLEG_END() {true, SL_END, 0, 0, 0, 0, NULL, 0, SlXvFeatureTest()}
|
||||
|
||||
/**
|
||||
* Checks whether the savegame is below \a major.\a minor.
|
||||
@@ -624,8 +714,8 @@ void SlObject(void *object, const SaveLoad *sld);
|
||||
bool SlObjectMember(void *object, const SaveLoad *sld);
|
||||
void NORETURN SlError(StringID string, const char *extra_msg = NULL, bool already_malloced = false);
|
||||
void NORETURN SlErrorCorrupt(const char *msg, bool already_malloced = false);
|
||||
void CDECL NORETURN SlErrorFmt(StringID string, const char *msg, ...) WARN_FORMAT(2, 3);
|
||||
void CDECL NORETURN SlErrorCorruptFmt(const char *msg, ...) WARN_FORMAT(1, 2);
|
||||
void NORETURN CDECL SlErrorFmt(StringID string, const char *msg, ...) WARN_FORMAT(2, 3);
|
||||
void NORETURN CDECL SlErrorCorruptFmt(const char *msg, ...) WARN_FORMAT(1, 2);
|
||||
|
||||
bool SaveloadCrashWithMissingNewGRFs();
|
||||
|
||||
|
@@ -60,7 +60,7 @@ static void Load_SIGN()
|
||||
}
|
||||
|
||||
/* Signs placed in scenario editor shall now be OWNER_DEITY */
|
||||
if (IsSavegameVersionBefore(171) && si->owner == OWNER_NONE && _saveload_mode == SLD_LOAD_SCENARIO) {
|
||||
if (IsSavegameVersionBefore(171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) {
|
||||
si->owner = OWNER_DEITY;
|
||||
}
|
||||
}
|
||||
|
@@ -436,21 +436,21 @@ void AfterLoadVehicles(bool part_of_load)
|
||||
|
||||
case VEH_TRAIN:
|
||||
case VEH_SHIP:
|
||||
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
|
||||
break;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
if (Aircraft::From(v)->IsNormalAircraft()) {
|
||||
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
|
||||
|
||||
/* The plane's shadow will have the same image as the plane */
|
||||
/* The plane's shadow will have the same image as the plane, but no colour */
|
||||
Vehicle *shadow = v->Next();
|
||||
shadow->cur_image = v->cur_image;
|
||||
shadow->sprite_seq.CopyWithoutPalette(v->sprite_seq);
|
||||
|
||||
/* In the case of a helicopter we will update the rotor sprites */
|
||||
if (v->subtype == AIR_HELICOPTER) {
|
||||
Vehicle *rotor = shadow->Next();
|
||||
rotor->cur_image = GetRotorImage(Aircraft::From(v), EIT_ON_MAP);
|
||||
GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_seq);
|
||||
}
|
||||
|
||||
UpdateAircraftCache(Aircraft::From(v), true);
|
||||
@@ -800,7 +800,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, 0, 163),
|
||||
SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, 164, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, cur_image, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_VAR(Vehicle, sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_CONDNULL(5, 0, 57),
|
||||
SLE_VAR(Vehicle, progress, SLE_UINT8),
|
||||
SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
|
||||
@@ -840,7 +840,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
SLE_CONDVAR(Vehicle, current_order.dest, SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
|
||||
SLE_CONDVAR(Vehicle, current_order.dest, SLE_UINT16, 5, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, cur_image, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_VAR(Vehicle, sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
|
||||
SLE_CONDVAR(Vehicle, age, SLE_INT32, 31, SL_MAX_VERSION),
|
||||
SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
|
||||
|
Reference in New Issue
Block a user