Merge branch 'save_ext' into more_cond_orders-sx

# Conflicts:
#	src/lang/english.txt
#	src/order_type.h
This commit is contained in:
Jonathan G Rennison
2019-01-06 22:10:26 +00:00
689 changed files with 36057 additions and 16577 deletions

View File

@@ -154,7 +154,7 @@ static void ConvertTownOwner()
if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HasBit(_m[tile].m3, 7)) {
_m[tile].m3 = OWNER_TOWN;
}
/* FALL THROUGH */
FALLTHROUGH;
case MP_TUNNELBRIDGE:
if (_m[tile].m1 & 0x80) SetTileOwner(tile, OWNER_TOWN);
@@ -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;
}
}
@@ -718,12 +718,14 @@ bool AfterLoadGame()
if (IsSavegameVersionBefore(95)) _settings_game.vehicle.dynamic_engines = 0;
if (IsSavegameVersionBefore(96)) _settings_game.economy.station_noise_level = false;
if (IsSavegameVersionBefore(133)) {
_settings_game.vehicle.roadveh_acceleration_model = 0;
_settings_game.vehicle.train_slope_steepness = 3;
}
if (IsSavegameVersionBefore(134)) _settings_game.economy.feeder_payment_share = 75;
if (IsSavegameVersionBefore(138)) _settings_game.vehicle.plane_crashes = 2;
if (IsSavegameVersionBefore(139)) _settings_game.vehicle.roadveh_slope_steepness = 7;
if (IsSavegameVersionBefore(139)) {
_settings_game.vehicle.roadveh_acceleration_model = 0;
_settings_game.vehicle.roadveh_slope_steepness = 7;
}
if (IsSavegameVersionBefore(143)) _settings_game.economy.allow_town_level_crossings = true;
if (IsSavegameVersionBefore(159)) {
_settings_game.vehicle.max_train_length = 50;
@@ -1212,6 +1214,38 @@ bool AfterLoadGame()
}
}
/* Railtype moved from m3 to m8 in version 200. */
if (IsSavegameVersionBefore(200)) {
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_RAILWAY:
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
break;
case MP_ROAD:
if (IsLevelCrossing(t)) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
case MP_STATION:
if (HasStationRail(t)) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
case MP_TUNNELBRIDGE:
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
default:
break;
}
}
}
/* Elrails got added in rev 24 */
if (IsSavegameVersionBefore(24)) {
RailType min_rail = RAILTYPE_ELECTRIC;
@@ -2155,22 +2189,21 @@ bool AfterLoadGame()
/* Animated tiles would sometimes not be actually animated or
* in case of old savegames duplicate. */
extern TileIndex *_animated_tile_list;
extern uint _animated_tile_count;
extern SmallVector<TileIndex, 256> _animated_tiles;
for (uint i = 0; i < _animated_tile_count; /* Nothing */) {
for (TileIndex *tile = _animated_tiles.Begin(); tile < _animated_tiles.End(); /* Nothing */) {
/* Remove if tile is not animated */
bool remove = _tile_type_procs[GetTileType(_animated_tile_list[i])]->animate_tile_proc == NULL;
bool remove = _tile_type_procs[GetTileType(*tile)]->animate_tile_proc == NULL;
/* and remove if duplicate */
for (uint j = 0; !remove && j < i; j++) {
remove = _animated_tile_list[i] == _animated_tile_list[j];
for (TileIndex *j = _animated_tiles.Begin(); !remove && j < tile; j++) {
remove = *tile == *j;
}
if (remove) {
DeleteAnimatedTile(_animated_tile_list[i]);
DeleteAnimatedTile(*tile);
} else {
i++;
tile++;
}
}
}
@@ -2968,6 +3001,59 @@ bool AfterLoadGame()
#endif
}
if (IsSavegameVersionBefore(198)) {
/* Convert towns growth_rate and grow_counter to ticks */
Town *t;
FOR_ALL_TOWNS(t) {
/* 0x8000 = TOWN_GROWTH_RATE_CUSTOM previously */
if (t->growth_rate & 0x8000) SetBit(t->flags, TOWN_CUSTOM_GROWTH);
if (t->growth_rate != TOWN_GROWTH_RATE_NONE) {
t->growth_rate = TownTicksToGameTicks(t->growth_rate & ~0x8000);
}
/* Add t->index % TOWN_GROWTH_TICKS to spread growth across ticks. */
t->grow_counter = TownTicksToGameTicks(t->grow_counter) + t->index % TOWN_GROWTH_TICKS;
}
}
if (IsSavegameVersionBefore(202)) {
/* Make sure added industry cargo slots are cleared */
Industry *i;
FOR_ALL_INDUSTRIES(i) {
for (size_t ci = 2; ci < lengthof(i->produced_cargo); ci++) {
i->produced_cargo[ci] = CT_INVALID;
i->produced_cargo_waiting[ci] = 0;
i->production_rate[ci] = 0;
i->last_month_production[ci] = 0;
i->last_month_transported[ci] = 0;
i->last_month_pct_transported[ci] = 0;
i->this_month_production[ci] = 0;
i->this_month_transported[ci] = 0;
}
for (size_t ci = 3; ci < lengthof(i->accepts_cargo); ci++) {
i->accepts_cargo[ci] = CT_INVALID;
i->incoming_cargo_waiting[ci] = 0;
}
/* Make sure last_cargo_accepted_at is copied to elements for every valid input cargo.
* The loading routine should put the original singular value into the first array element. */
for (size_t ci = 0; ci < lengthof(i->accepts_cargo); ci++) {
if (i->accepts_cargo[ci] != CT_INVALID) {
i->last_cargo_accepted_at[ci] = i->last_cargo_accepted_at[0];
} else {
i->last_cargo_accepted_at[ci] = 0;
}
}
}
}
if (SlXvIsFeaturePresent(XSLFI_MORE_COND_ORDERS, 1, 1)) {
Order *order;
FOR_ALL_ORDERS(order) {
// Insertion of OCV_MAX_RELIABILITY between OCV_REMAINING_LIFETIME and OCV_CARGO_WAITING
if (order->IsType(OT_CONDITIONAL) && order->GetConditionVariable() > OCV_REMAINING_LIFETIME) {
order->SetConditionVariable(static_cast<OrderConditionVariable>((uint)order->GetConditionVariable() + 1));
}
}
}
/* Station acceptance is some kind of cache */
if (IsSavegameVersionBefore(127)) {

View File

@@ -12,22 +12,21 @@
#include "../stdafx.h"
#include "../tile_type.h"
#include "../core/alloc_func.hpp"
#include "../core/smallvec_type.hpp"
#include "saveload.h"
#include "../safeguards.h"
extern TileIndex *_animated_tile_list;
extern uint _animated_tile_count;
extern uint _animated_tile_allocated;
extern SmallVector<TileIndex, 256> _animated_tiles;
/**
* Save the ANIT chunk.
*/
static void Save_ANIT()
{
SlSetLength(_animated_tile_count * sizeof(*_animated_tile_list));
SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32);
SlSetLength(_animated_tiles.Length() * sizeof(*_animated_tiles.Begin()));
SlArray(_animated_tiles.Begin(), _animated_tiles.Length(), SLE_UINT32);
}
/**
@@ -38,22 +37,20 @@ static void Load_ANIT()
/* Before version 80 we did NOT have a variable length animated tile table */
if (IsSavegameVersionBefore(80)) {
/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
SlArray(_animated_tile_list, 256, IsSavegameVersionBefore(6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
TileIndex anim_list[256];
SlArray(anim_list, 256, IsSavegameVersionBefore(6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) {
if (_animated_tile_list[_animated_tile_count] == 0) break;
for (int i = 0; i < 256; i++) {
if (anim_list[i] == 0) break;
*_animated_tiles.Append() = anim_list[i];
}
return;
}
_animated_tile_count = (uint)SlGetFieldLength() / sizeof(*_animated_tile_list);
/* Determine a nice rounded size for the amount of allocated tiles */
_animated_tile_allocated = 256;
while (_animated_tile_allocated < _animated_tile_count) _animated_tile_allocated *= 2;
_animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated);
SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32);
uint count = (uint)SlGetFieldLength() / sizeof(*_animated_tiles.Begin());
_animated_tiles.Clear();
_animated_tiles.Append(count);
SlArray(_animated_tiles.Begin(), count, SLE_UINT32);
}
/**

View File

@@ -16,6 +16,8 @@
#include "../tunnelbridge_map.h"
#include "../tunnelbridge.h"
#include "../station_base.h"
#include "../strings_func.h"
#include "../settings_func.h"
#include "saveload.h"
@@ -184,7 +186,7 @@ void AfterLoadCompanyStats()
}
}
}
/* FALL THROUGH */
FALLTHROUGH;
case MP_OBJECT:
if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
@@ -243,7 +245,7 @@ static const SaveLoad _company_desc[] = {
SLE_VAR(CompanyProperties, name_1, SLE_STRINGID),
SLE_CONDSTR(CompanyProperties, name, SLE_STR | SLF_ALLOW_CONTROL, 0, 84, SL_MAX_VERSION),
SLE_VAR(CompanyProperties, president_name_1, SLE_UINT16),
SLE_VAR(CompanyProperties, president_name_1, SLE_STRINGID),
SLE_VAR(CompanyProperties, president_name_2, SLE_UINT32),
SLE_CONDSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, 0, 84, SL_MAX_VERSION),
@@ -258,7 +260,7 @@ static const SaveLoad _company_desc[] = {
SLE_VAR(CompanyProperties, colour, SLE_UINT8),
SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
SLE_CONDVAR(CompanyProperties, avail_railtypes, SLE_VAR_I32 | SLE_FILE_I8, 0, 57),
SLE_CONDNULL(1, 0, 57), ///< avail_railtypes
SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
SLE_CONDNULL(2, 0, 93), ///< cargo_types
@@ -349,7 +351,8 @@ static const SaveLoad _company_economy_desc[] = {
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, 2, SL_MAX_VERSION),
SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, 0, 169),
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, 170, SL_MAX_VERSION),
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, 170, 198),
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, 199, SL_MAX_VERSION),
SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32),
SLE_END()
@@ -486,6 +489,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;
}
@@ -496,16 +500,15 @@ static void Check_PLYR()
int index;
while ((index = SlIterateArray()) != -1) {
CompanyProperties *cprops = new CompanyProperties();
memset(cprops, 0, sizeof(*cprops));
SaveLoad_PLYR_common(NULL, cprops);
/* We do not load old custom names */
if (IsSavegameVersionBefore(84)) {
if (GB(cprops->name_1, 11, 5) == 15) {
if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) {
cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
}
if (GB(cprops->president_name_1, 11, 5) == 15) {
if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) {
cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
}
}
@@ -529,7 +532,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},
};

View File

@@ -29,7 +29,7 @@ static void Load_PRIC()
/** Cargo payment rates in pre 126 savegames */
static void Load_CAPR()
{
uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO;
uint num_cargo = IsSavegameVersionBefore(55) ? 12 : IsSavegameVersionBefore(199) ? 32 : NUM_CARGO;
int vt = IsSavegameVersionBefore(65) ? SLE_FILE_I32 : SLE_FILE_I64;
SlArray(NULL, num_cargo, vt | SLE_VAR_NULL);
SlArray(NULL, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL);
@@ -102,7 +102,7 @@ static void Ptrs_CAPY()
extern const ChunkHandler _economy_chunk_handlers[] = {
{ 'CAPY', Save_CAPY, Load_CAPY, Ptrs_CAPY, NULL, CH_ARRAY},
{ 'PRIC', NULL, Load_PRIC, NULL, NULL, CH_RIFF | CH_AUTO_LENGTH},
{ 'CAPR', NULL, Load_CAPR, NULL, NULL, CH_RIFF | CH_AUTO_LENGTH},
{ 'PRIC', NULL, Load_PRIC, NULL, NULL, CH_RIFF },
{ 'CAPR', NULL, Load_CAPR, NULL, NULL, CH_RIFF },
{ 'ECMY', Save_ECMY, Load_ECMY, NULL, NULL, CH_RIFF | CH_LAST},
};

View File

@@ -45,7 +45,7 @@ std::vector<uint32> _sl_xv_discardable_chunk_ids; ///< list of chunks
static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk
const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 1, 1, "more_cond_orders", NULL, NULL, NULL },
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 2, 2, "more_cond_orders", NULL, NULL, NULL },
{ XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker
};
@@ -61,6 +61,8 @@ bool SlXvFeatureTest::IsFeaturePresent(uint16 savegame_version, uint16 savegame_
{
bool savegame_version_ok = savegame_version >= savegame_version_from && savegame_version <= savegame_version_to;
if (this->functor) return (*this->functor)(savegame_version, savegame_version_ok);
if (this->feature == XSLFI_NULL) return savegame_version_ok;
bool feature_ok = SlXvIsFeaturePresent(this->feature, this->min_version, this->max_version);
@@ -87,6 +89,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
*/
@@ -94,6 +110,7 @@ void SlXvResetState()
{
_sl_is_ext_version = false;
_sl_is_faked_ext = false;
_sl_xv_discardable_chunk_ids.clear();
memset(_sl_xv_feature_versions, 0, sizeof(_sl_xv_feature_versions));
}
@@ -116,9 +133,7 @@ void SlXvSetCurrentState()
*/
void SlXvCheckSpecialSavegameVersions()
{
extern uint16 _sl_version;
// TODO: check for savegame versions
// Checks for special savegame versions go here
}
/**
@@ -165,7 +180,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 +193,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 +223,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 +232,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) {

View File

@@ -40,11 +40,14 @@ enum SlXvFeatureTestOperator {
* Structure to describe an extended feature version test, and how it combines with a traditional savegame version test
*/
struct SlXvFeatureTest {
using TestFunctorPtr = bool (*)(uint16, bool); ///< Return true if feature present, first parameter is standard savegame version, second is whether standard savegame version is within bounds
private:
uint16 min_version;
uint16 max_version;
SlXvFeatureIndex feature;
SlXvFeatureTestOperator op;
TestFunctorPtr functor = nullptr;
public:
SlXvFeatureTest()
@@ -53,6 +56,9 @@ struct SlXvFeatureTest {
SlXvFeatureTest(SlXvFeatureTestOperator op_, SlXvFeatureIndex feature_, uint16 min_version_ = 1, uint16 max_version_ = 0xFFFF)
: min_version(min_version_), max_version(max_version_), feature(feature_), op(op_) { }
SlXvFeatureTest(TestFunctorPtr functor_)
: min_version(0), max_version(0), feature(XSLFI_NULL), op(XSLFTO_OR), functor(functor_) { }
bool IsFeaturePresent(uint16 savegame_version, uint16 savegame_version_from, uint16 savegame_version_to) const;
};
@@ -66,6 +72,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)

View File

@@ -26,18 +26,28 @@ static const SaveLoad _industry_desc[] = {
SLE_VAR(Industry, location.h, SLE_FILE_U8 | SLE_VAR_U16),
SLE_REF(Industry, town, REF_TOWN),
SLE_CONDNULL( 2, 0, 60), ///< used to be industry's produced_cargo
SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 2, 78, SL_MAX_VERSION),
SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 3, 70, SL_MAX_VERSION),
SLE_ARR(Industry, produced_cargo_waiting, SLE_UINT16, 2),
SLE_ARR(Industry, production_rate, SLE_UINT8, 2),
SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 2, 78, 201),
SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 3, 70, 201),
SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, produced_cargo_waiting, SLE_UINT16, 2, 0, 201),
SLE_CONDARR(Industry, produced_cargo_waiting, SLE_UINT16, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, production_rate, SLE_UINT8, 2, 0, 201),
SLE_CONDARR(Industry, production_rate, SLE_UINT8, 16, 202, SL_MAX_VERSION),
SLE_CONDNULL( 3, 0, 60), ///< used to be industry's accepts_cargo
SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 3, 78, SL_MAX_VERSION),
SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 3, 78, 201),
SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 16, 202, SL_MAX_VERSION),
SLE_VAR(Industry, prod_level, SLE_UINT8),
SLE_ARR(Industry, this_month_production, SLE_UINT16, 2),
SLE_ARR(Industry, this_month_transported, SLE_UINT16, 2),
SLE_ARR(Industry, last_month_pct_transported, SLE_UINT8, 2),
SLE_ARR(Industry, last_month_production, SLE_UINT16, 2),
SLE_ARR(Industry, last_month_transported, SLE_UINT16, 2),
SLE_CONDARR(Industry, this_month_production, SLE_UINT16, 2, 0, 201),
SLE_CONDARR(Industry, this_month_production, SLE_UINT16, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, this_month_transported, SLE_UINT16, 2, 0, 201),
SLE_CONDARR(Industry, this_month_transported, SLE_UINT16, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8, 2, 0, 201),
SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, last_month_production, SLE_UINT16, 2, 0, 201),
SLE_CONDARR(Industry, last_month_production, SLE_UINT16, 16, 202, SL_MAX_VERSION),
SLE_CONDARR(Industry, last_month_transported, SLE_UINT16, 2, 0, 201),
SLE_CONDARR(Industry, last_month_transported, SLE_UINT16, 16, 202, SL_MAX_VERSION),
SLE_VAR(Industry, counter, SLE_UINT16),
@@ -51,13 +61,14 @@ static const SaveLoad _industry_desc[] = {
SLE_CONDVAR(Industry, founder, SLE_UINT8, 70, SL_MAX_VERSION),
SLE_CONDVAR(Industry, construction_date, SLE_INT32, 70, SL_MAX_VERSION),
SLE_CONDVAR(Industry, construction_type, SLE_UINT8, 70, SL_MAX_VERSION),
SLE_CONDVAR(Industry, last_cargo_accepted_at, SLE_INT32, 70, SL_MAX_VERSION),
SLE_CONDVAR(Industry, last_cargo_accepted_at[0], SLE_INT32, 70, 201),
SLE_CONDARR(Industry, last_cargo_accepted_at, SLE_INT32, 16, 202, SL_MAX_VERSION),
SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, 73, SL_MAX_VERSION),
SLEG_CONDARR(_old_ind_persistent_storage.storage, SLE_UINT32, 16, 76, 160),
SLE_CONDREF(Industry, psa, REF_STORAGE, 161, SL_MAX_VERSION),
SLE_CONDVAR(Industry, random_triggers, SLE_UINT8, 82, SL_MAX_VERSION),
SLE_CONDNULL(1, 82, 196), // random_triggers
SLE_CONDVAR(Industry, random, SLE_UINT16, 82, SL_MAX_VERSION),
SLE_CONDNULL(32, 2, 143), // old reserved space
@@ -101,7 +112,7 @@ static void Load_INDY()
/* Store the old persistent storage. The GRFID will be added later. */
assert(PersistentStorage::CanAllocateItem());
i->psa = new PersistentStorage(0, 0, 0);
memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(i->psa->storage));
memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage));
}
Industry::IncIndustryTypeCount(i->type);
}

View File

@@ -132,7 +132,7 @@ static const SaveLoad _edge_desc[] = {
/**
* Save/load a link graph.
* @param comp Link graph to be saved or loaded.
* @param lg Link graph to be saved or loaded.
*/
void SaveLoad_LinkGraph(LinkGraph &lg)
{

View File

@@ -272,6 +272,30 @@ static void Save_MAP7()
}
}
static void Load_MAP8()
{
SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
TileIndex size = MapSize();
for (TileIndex i = 0; i != size;) {
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j];
}
}
static void Save_MAP8()
{
SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
TileIndex size = MapSize();
SlSetLength(size * sizeof(uint16));
for (TileIndex i = 0; i != size;) {
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8;
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
}
}
extern const ChunkHandler _map_chunk_handlers[] = {
{ 'MAPS', Save_MAPS, Load_MAPS, NULL, Check_MAPS, CH_RIFF },
{ 'MAPT', Save_MAPT, Load_MAPT, NULL, NULL, CH_RIFF },
@@ -282,5 +306,6 @@ extern const ChunkHandler _map_chunk_handlers[] = {
{ 'M3HI', Save_MAP4, Load_MAP4, NULL, NULL, CH_RIFF },
{ 'MAP5', Save_MAP5, Load_MAP5, NULL, NULL, CH_RIFF },
{ 'MAPE', Save_MAP6, Load_MAP6, NULL, NULL, CH_RIFF },
{ 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL, CH_RIFF | CH_LAST },
{ 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL, CH_RIFF },
{ 'MAP8', Save_MAP8, Load_MAP8, NULL, NULL, CH_RIFF | CH_LAST },
};

View File

@@ -96,8 +96,16 @@ static void Load_NGRF()
{
Load_NGRF_common(_grfconfig);
/* Append static NewGRF configuration, but only if there are some NewGRFs. */
if (_game_mode != GM_MENU || _all_grfs != NULL) AppendStaticGRFConfigs(&_grfconfig);
if (_game_mode == GM_MENU) {
/* Intro game must not have NewGRF. */
if (_grfconfig != NULL) SlErrorCorrupt("The intro game must not use NewGRF");
/* Activate intro NewGRFs (townnames) */
ResetGRFConfig(false);
} else {
/* Append static NewGRF configuration */
AppendStaticGRFConfigs(&_grfconfig);
}
}
static void Check_NGRF()

View File

@@ -265,7 +265,7 @@ static SavegameType DetermineOldSavegameType(FILE *f, char *title, const char *l
case SGT_TTD: title = strecpy(title, "(TTD) ", last); break;
default: title = strecpy(title, "(broken) ", last); break;
}
title = strecpy(title, temp, last);
strecpy(title, temp, last);
}
return type;

View File

@@ -28,6 +28,7 @@
#include "../engine_func.h"
#include "../company_base.h"
#include "../disaster_vehicle.h"
#include "../core/smallvec_type.hpp"
#include "saveload_internal.h"
#include "oldloader.h"
@@ -490,8 +491,7 @@ static inline uint RemapOrderIndex(uint x)
return _savegame_type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2;
}
extern TileIndex *_animated_tile_list;
extern uint _animated_tile_count;
extern SmallVector<TileIndex, 256> _animated_tiles;
extern char *_old_name_array;
static uint32 _old_town_index;
@@ -640,22 +640,18 @@ static bool LoadOldOrder(LoadgameState *ls, int num)
static bool LoadOldAnimTileList(LoadgameState *ls, int num)
{
/* This is slightly hackish - we must load a chunk into an array whose
* address isn't static, but instead pointed to by _animated_tile_list.
* To achieve that, create an OldChunks list on the stack on the fly.
* The list cannot be static because the value of _animated_tile_list
* can change between calls. */
TileIndex anim_list[256];
const OldChunks anim_chunk[] = {
OCL_VAR ( OC_TILE, 256, _animated_tile_list ),
OCL_VAR ( OC_TILE, 256, anim_list ),
OCL_END ()
};
if (!LoadChunk(ls, NULL, anim_chunk)) return false;
/* Update the animated tile counter by counting till the first zero in the array */
for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) {
if (_animated_tile_list[_animated_tile_count] == 0) break;
/* The first zero in the loaded array indicates the end of the list. */
for (int i = 0; i < 256; i++) {
if (anim_list[i] == 0) break;
*_animated_tiles.Append() = anim_list[i];
}
return true;
@@ -950,7 +946,7 @@ static const OldChunks _company_chunk[] = {
OCL_SVAR( OC_UINT8, Company, block_preview ),
OCL_CNULL( OC_TTD, 1 ), // Old AI
OCL_SVAR( OC_TTD | OC_UINT8, Company, avail_railtypes ),
OCL_CNULL( OC_TTD, 1 ), // avail_railtypes
OCL_SVAR( OC_TILE, Company, location_of_HQ ),
OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[0] ),
OCL_SVAR( OC_TTD | OC_UINT8, Company, share_owners[1] ),
@@ -1165,7 +1161,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 +1254,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 +1265,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: {

File diff suppressed because it is too large Load Diff

View File

@@ -25,15 +25,18 @@ enum SaveOrLoadResult {
SL_REINIT = 2, ///< error that was caught in the middle of updating game state, need to clear it. (can only happen during load)
};
/** Save or load mode. @see SaveOrLoad */
enum SaveOrLoadMode {
SL_INVALID = -1, ///< Invalid mode.
SL_LOAD = 0, ///< Load game.
SL_SAVE = 1, ///< Save game.
SL_OLD_LOAD = 2, ///< Load old game.
SL_PNG = 3, ///< Load PNG file (height map).
SL_BMP = 4, ///< Load BMP file (height map).
SL_LOAD_CHECK = 5, ///< Load for game preview.
/** Deals with the type of the savegame, independent of extension */
struct FileToSaveLoad {
SaveLoadOperation file_op; ///< File operation to perform.
DetailedFileType detail_ftype; ///< Concrete file type (PNG, BMP, old save, etc).
AbstractFileType abstract_ftype; ///< Abstract type of file (scenario, heightmap, etc).
char name[MAX_PATH]; ///< Name of the file.
char title[255]; ///< Internal name of the game.
void SetMode(FiosType ft);
void SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft);
void SetName(const char *name);
void SetTitle(const char *title);
};
/** Types of save games. */
@@ -46,10 +49,12 @@ enum SavegameType {
SGT_INVALID = 0xFF, ///< broken savegame (used internally)
};
extern FileToSaveLoad _file_to_saveload;
void GenerateDefaultSaveName(char *buf, const char *last);
void SetSaveLoadError(uint16 str);
void SetSaveLoadError(StringID 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,16 @@ 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
@@ -159,7 +170,7 @@ enum VarTypes {
SLE_INT64 = SLE_FILE_I64 | SLE_VAR_I64,
SLE_UINT64 = SLE_FILE_U64 | SLE_VAR_U64,
SLE_CHAR = SLE_FILE_I8 | SLE_VAR_CHAR,
SLE_STRINGID = SLE_FILE_STRINGID | SLE_VAR_U16,
SLE_STRINGID = SLE_FILE_STRINGID | SLE_VAR_U32,
SLE_STRINGBUF = SLE_FILE_STRING | SLE_VAR_STRB,
SLE_STRINGBQUOTE = SLE_FILE_STRING | SLE_VAR_STRBQ,
SLE_STRING = SLE_FILE_STRING | SLE_VAR_STR,
@@ -193,10 +204,15 @@ 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.
SL_STDSTR = 7, ///< Save/load a std::string.
/* non-normal save-load types */
SL_WRITEBYTE = 8,
SL_VEH_INCLUDE = 9,
SL_ST_INCLUDE = 10,
/* primitive type vector */
SL_VARVEC = 14,
SL_END = 15
};
@@ -286,6 +302,18 @@ typedef SaveLoad SaveLoadGlobVarList;
#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, SlXvFeatureTest())
/**
* Storage of a std::string in some savegame versions.
* @param base Name of the class or struct containing the string.
* @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 string.
* @param to Last savegame version that has the string.
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
*/
#define SLE_CONDSTDSTR_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_STDSTR, base, variable, type, 0, from, to, extver)
#define SLE_CONDSTDSTR(base, variable, type, from, to) SLE_CONDSTDSTR_X(base, variable, type, from, to, SlXvFeatureTest())
/**
* Storage of a list in some savegame versions.
* @param base Name of the class or struct containing the list.
@@ -298,6 +326,42 @@ typedef SaveLoad SaveLoadGlobVarList;
#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, 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 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_CONDVARVEC_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_VARVEC, base, variable, type, 0, from, to, extver)
#define SLE_CONDVARVEC(base, variable, type, from, to) SLE_CONDVARVEC_X(base, variable, type, from, to, SlXvFeatureTest())
/**
* Storage of a variable in every version of a savegame.
* @param base Name of the class or struct containing the variable.
@@ -332,6 +396,14 @@ typedef SaveLoad SaveLoadGlobVarList;
*/
#define SLE_STR(base, variable, type, length) SLE_CONDSTR(base, variable, type, length, 0, SL_MAX_VERSION)
/**
* Storage of a std::string in every savegame version.
* @param base Name of the class or struct containing the string.
* @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_STDSTR(base, variable, type) SLE_CONDSTDSTR(base, variable, type, 0, SL_MAX_VERSION)
/**
* Storage of a list in every savegame version.
* @param base Name of the class or struct containing the list.
@@ -340,6 +412,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.
@@ -435,6 +523,28 @@ typedef SaveLoad SaveLoadGlobVarList;
#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, 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.
* @param variable Name of the global variable.
@@ -461,7 +571,7 @@ typedef SaveLoad SaveLoadGlobVarList;
* @param variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame.
*/
#define SLEG_STR(variable, type) SLEG_CONDSTR(variable, type, lengthof(variable), 0, SL_MAX_VERSION)
#define SLEG_STR(variable, type) SLEG_CONDSTR(variable, type, sizeof(variable), 0, SL_MAX_VERSION)
/**
* Storage of a global list in every savegame version.
@@ -470,6 +580,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.
@@ -514,7 +638,7 @@ static inline bool SlIsObjectCurrentlyValid(uint16 version_from, uint16 version_
* Get the NumberType of a setting. This describes the integer type
* as it is represented in memory
* @param type VarType holding information about the variable-type
* @return return the SLE_VAR_* part of a variable-type description
* @return the SLE_VAR_* part of a variable-type description
*/
static inline VarType GetVarMemType(VarType type)
{
@@ -522,10 +646,10 @@ static inline VarType GetVarMemType(VarType type)
}
/**
* Get the #FileType of a setting. This describes the integer type
* Get the FileType of a setting. This describes the integer type
* as it is represented in a savegame/file
* @param type VarType holding information about the file-type
* @param return the SLE_FILE_* part of a variable-type description
* @return the SLE_FILE_* part of a variable-type description
*/
static inline VarType GetVarFileType(VarType type)
{
@@ -568,52 +692,15 @@ size_t SlCalcObjLength(const void *object, const SaveLoad *sld);
byte SlReadByte();
void SlWriteByte(byte b);
static inline int SlReadUint16()
{
int x = SlReadByte() << 8;
return x | SlReadByte();
}
int SlReadUint16();
uint32 SlReadUint32();
uint64 SlReadUint64();
static inline uint32 SlReadUint32()
{
uint32 x = SlReadUint16() << 16;
return x | SlReadUint16();
}
void SlWriteUint16(uint16 v);
void SlWriteUint32(uint32 v);
void SlWriteUint64(uint64 v);
static inline uint64 SlReadUint64()
{
uint32 x = SlReadUint32();
uint32 y = SlReadUint32();
return (uint64)x << 32 | y;
}
static inline void SlWriteUint16(uint16 v)
{
SlWriteByte(GB(v, 8, 8));
SlWriteByte(GB(v, 0, 8));
}
static inline void SlWriteUint32(uint32 v)
{
SlWriteUint16(GB(v, 16, 16));
SlWriteUint16(GB(v, 0, 16));
}
static inline void SlWriteUint64(uint64 x)
{
SlWriteUint32((uint32)(x >> 32));
SlWriteUint32((uint32)x);
}
/**
* Read in bytes from the file/data structure but don't do
* anything with them, discarding them in effect
* @param length The amount of bytes that is being treated this way
*/
static inline void SlSkipBytes(size_t length)
{
for (; length != 0; length--) SlReadByte();
}
void SlSkipBytes(size_t length);
size_t SlGetBytesRead();
size_t SlGetBytesWritten();
@@ -624,8 +711,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();

View File

@@ -0,0 +1,266 @@
/* $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 saveload_buffer.h Functions/types related to buffers used for saving and loading games. */
#ifndef SAVELOAD_BUFFER_H
#define SAVELOAD_BUFFER_H
#include "../core/alloc_func.hpp"
#include "../core/endian_type.hpp"
#include "../core/endian_func.hpp"
#include "../core/math_func.hpp"
#include <vector>
#include <utility>
struct LoadFilter;
struct SaveFilter;
/** Save in chunks of 128 KiB. */
static const size_t MEMORY_CHUNK_SIZE = 128 * 1024;
/** A buffer for reading (and buffering) savegame data. */
struct ReadBuffer {
byte buf[MEMORY_CHUNK_SIZE]; ///< Buffer we're going to read from.
byte *bufp; ///< Location we're at reading the buffer.
byte *bufe; ///< End of the buffer we can read from.
LoadFilter *reader; ///< The filter used to actually read.
size_t read; ///< The amount of read bytes so far from the filter.
/**
* Initialise our variables.
* @param reader The filter to actually read data.
*/
ReadBuffer(LoadFilter *reader) : bufp(NULL), bufe(NULL), reader(reader), read(0)
{
}
static ReadBuffer *GetCurrent();
void SkipBytesSlowPath(size_t bytes);
void AcquireBytes();
inline void SkipBytes(size_t bytes)
{
byte *b = this->bufp + bytes;
if (likely(b <= this->bufe)) {
this->bufp = b;
} else {
SkipBytesSlowPath(bytes);
}
}
inline byte RawReadByte()
{
return *this->bufp++;
}
inline byte ReadByte()
{
if (unlikely(this->bufp == this->bufe)) {
this->AcquireBytes();
}
return RawReadByte();
}
inline void CheckBytes(size_t bytes)
{
while (unlikely(this->bufp + bytes > this->bufe)) this->AcquireBytes();
}
inline int RawReadUint16()
{
#if OTTD_ALIGNMENT == 0
int x = FROM_BE16(*((const unaligned_uint16*) this->bufp));
this->bufp += 2;
return x;
#else
int x = this->RawReadByte() << 8;
return x | this->RawReadByte();
#endif
}
inline uint32 RawReadUint32()
{
#if OTTD_ALIGNMENT == 0
uint32 x = FROM_BE32(*((const unaligned_uint32*) this->bufp));
this->bufp += 4;
return x;
#else
uint32 x = this->RawReadUint16() << 16;
return x | this->RawReadUint16();
#endif
}
inline uint64 RawReadUint64()
{
#if OTTD_ALIGNMENT == 0
uint64 x = FROM_BE64(*((const unaligned_uint64*) this->bufp));
this->bufp += 8;
return x;
#else
uint32 x = this->RawReadUint32();
uint32 y = this->RawReadUint32();
return (uint64)x << 32 | y;
#endif
}
inline void CopyBytes(byte *ptr, size_t length)
{
while (length) {
if (unlikely(this->bufp == this->bufe)) {
this->AcquireBytes();
}
size_t to_copy = min<size_t>(this->bufe - this->bufp, length);
memcpy(ptr, this->bufp, to_copy);
this->bufp += to_copy;
ptr += to_copy;
length -= to_copy;
}
}
/**
* Get the size of the memory dump made so far.
* @return The size.
*/
inline size_t GetSize() const
{
return this->read - (this->bufe - this->bufp);
}
};
/** Container for dumping the savegame (quickly) to memory. */
struct MemoryDumper {
struct BufferInfo {
byte *data;
size_t size = 0;
BufferInfo(byte *d) : data(d) {}
~BufferInfo() { free(this->data); }
BufferInfo(const BufferInfo &) = delete;
BufferInfo(BufferInfo &&other) : data(other.data), size(other.size) { other.data = nullptr; };
};
std::vector<BufferInfo> blocks; ///< Buffer with blocks of allocated memory.
byte *buf = nullptr; ///< Buffer we're going to write to.
byte *bufe = nullptr; ///< End of the buffer we write to.
size_t completed_block_bytes = 0; ///< Total byte count of completed blocks.
byte *autolen_buf = nullptr;
byte *autolen_buf_end = nullptr;
byte *saved_buf = nullptr;
byte *saved_bufe = nullptr;
MemoryDumper()
{
const size_t size = 8192;
this->autolen_buf = CallocT<byte>(size);
this->autolen_buf_end = this->autolen_buf + size;
}
~MemoryDumper()
{
free(this->autolen_buf);
}
static MemoryDumper *GetCurrent();
void FinaliseBlock();
void AllocateBuffer();
inline void CheckBytes(size_t bytes)
{
if (unlikely(this->buf + bytes > this->bufe)) this->AllocateBuffer();
}
/**
* Write a single byte into the dumper.
* @param b The byte to write.
*/
inline void WriteByte(byte b)
{
/* Are we at the end of this chunk? */
if (unlikely(this->buf == this->bufe)) {
this->AllocateBuffer();
}
*this->buf++ = b;
}
inline void CopyBytes(byte *ptr, size_t length)
{
while (length) {
if (unlikely(this->buf == this->bufe)) {
this->AllocateBuffer();
}
size_t to_copy = min<size_t>(this->bufe - this->buf, length);
memcpy(this->buf, ptr, to_copy);
this->buf += to_copy;
ptr += to_copy;
length -= to_copy;
}
}
inline void RawWriteByte(byte b)
{
*this->buf++ = b;
}
inline void RawWriteUint16(uint16 v)
{
#if OTTD_ALIGNMENT == 0
*((unaligned_uint16 *) this->buf) = TO_BE16(v);
#else
this->buf[0] = GB(v, 8, 8);
this->buf[1] = GB(v, 0, 8);
#endif
this->buf += 2;
}
inline void RawWriteUint32(uint32 v)
{
#if OTTD_ALIGNMENT == 0
*((unaligned_uint32 *) this->buf) = TO_BE32(v);
#else
this->buf[0] = GB(v, 24, 8);
this->buf[1] = GB(v, 16, 8);
this->buf[2] = GB(v, 8, 8);
this->buf[3] = GB(v, 0, 8);
#endif
this->buf += 4;
}
inline void RawWriteUint64(uint64 v)
{
#if OTTD_ALIGNMENT == 0
*((unaligned_uint64 *) this->buf) = TO_BE64(v);
#else
this->buf[0] = GB(v, 56, 8);
this->buf[1] = GB(v, 48, 8);
this->buf[2] = GB(v, 40, 8);
this->buf[3] = GB(v, 32, 8);
this->buf[4] = GB(v, 24, 8);
this->buf[5] = GB(v, 16, 8);
this->buf[6] = GB(v, 8, 8);
this->buf[7] = GB(v, 0, 8);
#endif
this->buf += 8;
}
void Flush(SaveFilter *writer);
size_t GetSize() const;
void StartAutoLength();
std::pair<byte *, size_t> StopAutoLength();
};
#endif

View File

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

View File

@@ -325,6 +325,11 @@ static void SwapPackets(GoodsEntry *ge)
static void Load_STNS()
{
_cargo_source_xy = 0;
_cargo_days = 0;
_cargo_feeder_share = 0;
uint num_cargo = IsSavegameVersionBefore(55) ? 12 : IsSavegameVersionBefore(199) ? 32 : NUM_CARGO;
int index;
while ((index = SlIterateArray()) != -1) {
Station *st = new (index) Station();
@@ -333,7 +338,6 @@ static void Load_STNS()
_waiting_acceptance = 0;
uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO;
for (CargoID i = 0; i < num_cargo; i++) {
GoodsEntry *ge = &st->goods[i];
SlObject(ge, GetGoodsDesc());
@@ -373,10 +377,11 @@ static void Ptrs_STNS()
/* Don't run when savegame version is higher than or equal to 123. */
if (!IsSavegameVersionBefore(123)) return;
uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO;
Station *st;
FOR_ALL_STATIONS(st) {
if (!IsSavegameVersionBefore(68)) {
for (CargoID i = 0; i < NUM_CARGO; i++) {
for (CargoID i = 0; i < num_cargo; i++) {
GoodsEntry *ge = &st->goods[i];
SwapPackets(ge);
SlObject(ge, GetGoodsDesc());
@@ -436,7 +441,8 @@ static const SaveLoad _station_desc[] = {
SLE_VAR(Station, last_vehicle_type, SLE_UINT8),
SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8),
SLE_LST(Station, loading_vehicles, REF_VEHICLE),
SLE_CONDVAR(Station, always_accepted, SLE_UINT32, 127, SL_MAX_VERSION),
SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, 127, 198),
SLE_CONDVAR(Station, always_accepted, SLE_UINT64, 199, SL_MAX_VERSION),
SLE_END()
};
@@ -514,8 +520,10 @@ static void Save_STNN()
static void Load_STNN()
{
int index;
_num_flows = 0;
uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO;
int index;
while ((index = SlIterateArray()) != -1) {
bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
@@ -530,10 +538,10 @@ static void Load_STNN()
/* Store the old persistent storage. The GRFID will be added later. */
assert(PersistentStorage::CanAllocateItem());
st->airport.psa = new PersistentStorage(0, 0, 0);
memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(st->airport.psa->storage));
memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(_old_st_persistent_storage.storage));
}
for (CargoID i = 0; i < NUM_CARGO; i++) {
for (CargoID i = 0; i < num_cargo; i++) {
SlObject(&st->goods[i], GetGoodsDesc());
FlowSaveLoad flow;
FlowStat *fs = NULL;
@@ -575,9 +583,10 @@ static void Ptrs_STNN()
/* Don't run when savegame version lower than 123. */
if (IsSavegameVersionBefore(123)) return;
uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO;
Station *st;
FOR_ALL_STATIONS(st) {
for (CargoID i = 0; i < NUM_CARGO; i++) {
for (CargoID i = 0; i < num_cargo; i++) {
GoodsEntry *ge = &st->goods[i];
if (IsSavegameVersionBefore(183)) {
SwapPackets(ge);

View File

@@ -18,7 +18,8 @@
/** Description of the data to save and load in #PersistentStorage. */
static const SaveLoad _storage_desc[] = {
SLE_CONDVAR(PersistentStorage, grfid, SLE_UINT32, 6, SL_MAX_VERSION),
SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 16, 161, SL_MAX_VERSION),
SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 16, 161, 200),
SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 256, 201, SL_MAX_VERSION),
SLE_END()
};

View File

@@ -11,6 +11,7 @@
#include "../stdafx.h"
#include "../string_func.h"
#include "../strings_func.h"
#include "saveload_internal.h"
#include "table/strings.h"
@@ -60,7 +61,7 @@ char *_old_name_array = NULL;
char *CopyFromOldName(StringID id)
{
/* Is this name an (old) custom name? */
if (GB(id, 11, 5) != 15) return NULL;
if (GetStringTab(id) != TEXT_TAB_OLD_CUSTOM) return NULL;
if (IsSavegameVersionBefore(37)) {
/* Allow for expansion when converted to UTF-8. */

View File

@@ -14,6 +14,7 @@
#include "../town.h"
#include "../landscape.h"
#include "../subsidy_func.h"
#include "../strings_func.h"
#include "saveload.h"
#include "newgrf_sl.h"
@@ -191,7 +192,8 @@ static const SaveLoad _town_desc[] = {
SLE_CONDLST(Town, psa_list, REF_STORAGE, 161, SL_MAX_VERSION),
SLE_CONDVAR(Town, cargo_produced, SLE_UINT32, 166, SL_MAX_VERSION),
SLE_CONDVAR(Town, cargo_produced, SLE_FILE_U32 | SLE_VAR_U64, 166, 198),
SLE_CONDVAR(Town, cargo_produced, SLE_UINT64, 199, SL_MAX_VERSION),
/* reserve extra space in savegame here. (currently 30 bytes) */
SLE_CONDNULL(30, 2, SL_MAX_VERSION),
@@ -273,19 +275,20 @@ static void Save_TOWN()
static void Load_TOWN()
{
int index;
uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO;
while ((index = SlIterateArray()) != -1) {
Town *t = new (index) Town();
SlObject(t, _town_desc);
for (CargoID i = 0; i < NUM_CARGO; i++) {
for (CargoID i = 0; i < num_cargo; i++) {
SlObject(&t->supplied[i], _town_supplied_desc);
}
for (int i = TE_BEGIN; i < TE_END; i++) {
SlObject(&t->received[i], _town_received_desc);
}
if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GB(t->townnametype, 11, 5) != 15) {
if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
SlErrorCorrupt("Invalid town name generator");
}
@@ -294,7 +297,7 @@ static void Load_TOWN()
SlObject(&t->cargo_accepted, GetTileMatrixDesc());
if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
t->cargo_accepted.data = MallocT<uint32>(arr_len);
t->cargo_accepted.data = MallocT<CargoTypes>(arr_len);
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
/* Rebuild total cargo acceptance. */

View File

@@ -375,6 +375,8 @@ void AfterLoadVehicles(bool part_of_load)
FOR_ALL_VEHICLES(v) {
assert(v->first != NULL);
v->trip_occupancy = CalcPercentVehicleFilled(v, NULL);
switch (v->type) {
case VEH_TRAIN: {
Train *t = Train::From(v);
@@ -431,26 +433,26 @@ void AfterLoadVehicles(bool part_of_load)
RoadVehicle *rv = RoadVehicle::From(v);
rv->roadtype = HasBit(EngInfo(v->First()->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
rv->compatible_roadtypes = RoadTypeToRoadTypes(rv->roadtype);
/* FALL THROUGH */
FALLTHROUGH;
}
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);
@@ -459,7 +461,7 @@ void AfterLoadVehicles(bool part_of_load)
default: break;
}
v->UpdateDeltaXY(v->direction);
v->UpdateDeltaXY();
v->coord.left = INVALID_COORD;
v->UpdatePosition();
v->UpdateViewport(false);
@@ -796,7 +798,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),
@@ -836,7 +838,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),