Changeset - r26389:b3455045a0d1
[Not reviewed]
master
0 12 0
dP - 21 months ago 2022-09-21 10:42:29
dp@dpointer.org
Change: Make _tick_counter 64bit to avoid wrapping (#10035)
12 files changed with 25 insertions and 14 deletions:
0 comments (0 inline, 0 general)
src/date.cpp
Show inline comments
 
@@ -6,49 +6,49 @@
 
 */
 

	
 
/** @file date.cpp Handling of dates in our native format and transforming them to something human readable. */
 

	
 
#include "stdafx.h"
 
#include "network/network.h"
 
#include "network/network_func.h"
 
#include "currency.h"
 
#include "window_func.h"
 
#include "settings_type.h"
 
#include "date_func.h"
 
#include "vehicle_base.h"
 
#include "rail_gui.h"
 
#include "linkgraph/linkgraph.h"
 
#include "saveload/saveload.h"
 
#include "newgrf_profiling.h"
 
#include "widgets/statusbar_widget.h"
 

	
 
#include "safeguards.h"
 

	
 
Year      _cur_year;   ///< Current year, starting at 0
 
Month     _cur_month;  ///< Current month (0..11)
 
Date      _date;       ///< Current date in days (day counter)
 
DateFract _date_fract; ///< Fractional part of the day.
 
uint16 _tick_counter;  ///< Ever incrementing (and sometimes wrapping) tick counter for setting off various events
 
uint64 _tick_counter;  ///< Ever incrementing tick counter for setting off various events
 

	
 
/**
 
 * Set the date.
 
 * @param date  New date
 
 * @param fract The number of ticks that have passed on this date.
 
 */
 
void SetDate(Date date, DateFract fract)
 
{
 
	assert(fract < DAY_TICKS);
 

	
 
	YearMonthDay ymd;
 

	
 
	_date = date;
 
	_date_fract = fract;
 
	ConvertDateToYMD(date, &ymd);
 
	_cur_year = ymd.year;
 
	_cur_month = ymd.month;
 
}
 

	
 
#define M(a, b) ((a << 5) | b)
 
static const uint16 _month_date_from_year_day[] = {
 
	M( 0, 1), M( 0, 2), M( 0, 3), M( 0, 4), M( 0, 5), M( 0, 6), M( 0, 7), M( 0, 8), M( 0, 9), M( 0, 10), M( 0, 11), M( 0, 12), M( 0, 13), M( 0, 14), M( 0, 15), M( 0, 16), M( 0, 17), M( 0, 18), M( 0, 19), M( 0, 20), M( 0, 21), M( 0, 22), M( 0, 23), M( 0, 24), M( 0, 25), M( 0, 26), M( 0, 27), M( 0, 28), M( 0, 29), M( 0, 30), M( 0, 31),
 
	M( 1, 1), M( 1, 2), M( 1, 3), M( 1, 4), M( 1, 5), M( 1, 6), M( 1, 7), M( 1, 8), M( 1, 9), M( 1, 10), M( 1, 11), M( 1, 12), M( 1, 13), M( 1, 14), M( 1, 15), M( 1, 16), M( 1, 17), M( 1, 18), M( 1, 19), M( 1, 20), M( 1, 21), M( 1, 22), M( 1, 23), M( 1, 24), M( 1, 25), M( 1, 26), M( 1, 27), M( 1, 28), M( 1, 29),
 
	M( 2, 1), M( 2, 2), M( 2, 3), M( 2, 4), M( 2, 5), M( 2, 6), M( 2, 7), M( 2, 8), M( 2, 9), M( 2, 10), M( 2, 11), M( 2, 12), M( 2, 13), M( 2, 14), M( 2, 15), M( 2, 16), M( 2, 17), M( 2, 18), M( 2, 19), M( 2, 20), M( 2, 21), M( 2, 22), M( 2, 23), M( 2, 24), M( 2, 25), M( 2, 26), M( 2, 27), M( 2, 28), M( 2, 29), M( 2, 30), M( 2, 31),
src/date_func.h
Show inline comments
 
/*
 
 * 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 date_func.h Functions related to dates. */
 

	
 
#ifndef DATE_FUNC_H
 
#define DATE_FUNC_H
 

	
 
#include "date_type.h"
 

	
 
extern Year      _cur_year;
 
extern Month     _cur_month;
 
extern Date      _date;
 
extern DateFract _date_fract;
 
extern uint16 _tick_counter;
 
extern uint64 _tick_counter;
 

	
 
void SetDate(Date date, DateFract fract);
 
void ConvertDateToYMD(Date date, YearMonthDay *ymd);
 
Date ConvertYMDToDate(Year year, Month month, Day day);
 

	
 
/**
 
 * Checks whether the given year is a leap year or not.
 
 * @param yr The year to check.
 
 * @return True if \c yr is a leap year, otherwise false.
 
 */
 
static inline bool IsLeapYear(Year yr)
 
{
 
	return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0);
 
}
 

	
 
#endif /* DATE_FUNC_H */
src/gamelog_internal.h
Show inline comments
 
@@ -60,31 +60,31 @@ struct LoggedChange {
 
		} grfparam;
 
		struct {
 
			uint32 grfid;    ///< ID of moved GRF
 
			int32 offset;    ///< offset, positive = move down
 
		} grfmove;
 
		struct {
 
			char *name;      ///< name of the setting
 
			int32 oldval;    ///< old value
 
			int32 newval;    ///< new value
 
		} setting;
 
		struct {
 
			uint64 data;     ///< additional data
 
			uint32 grfid;    ///< ID of problematic GRF
 
			byte bug;        ///< type of bug, @see enum GRFBugs
 
		} grfbug;
 
	};
 
};
 

	
 

	
 
/** Contains information about one logged action that caused at least one logged change */
 
struct LoggedAction {
 
	LoggedChange *change; ///< First logged change in this action
 
	uint32 changes;       ///< Number of changes in this action
 
	GamelogActionType at; ///< Type of action
 
	uint16 tick;          ///< Tick when it happened
 
	uint64 tick;          ///< Tick when it happened
 
};
 

	
 
extern LoggedAction *_gamelog_action;
 
extern uint _gamelog_actions;
 

	
 
#endif /* GAMELOG_INTERNAL_H */
src/newgrf.cpp
Show inline comments
 
@@ -6292,49 +6292,49 @@ bool GetGlobalVariable(byte param, uint3
 
			*value = Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
			return true;
 

	
 
		case 0x02: { // detailed date information: month of year (bit 0-7), day of month (bit 8-12), leap year (bit 15), day of year (bit 16-24)
 
			YearMonthDay ymd;
 
			ConvertDateToYMD(_date, &ymd);
 
			Date start_of_year = ConvertYMDToDate(ymd.year, 0, 1);
 
			*value = ymd.month | (ymd.day - 1) << 8 | (IsLeapYear(ymd.year) ? 1 << 15 : 0) | (_date - start_of_year) << 16;
 
			return true;
 
		}
 

	
 
		case 0x03: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland
 
			*value = _settings_game.game_creation.landscape;
 
			return true;
 

	
 
		case 0x06: // road traffic side, bit 4 clear=left, set=right
 
			*value = _settings_game.vehicle.road_side << 4;
 
			return true;
 

	
 
		case 0x09: // date fraction
 
			*value = _date_fract * 885;
 
			return true;
 

	
 
		case 0x0A: // animation counter
 
			*value = _tick_counter;
 
			*value = GB(_tick_counter, 0, 16);
 
			return true;
 

	
 
		case 0x0B: { // TTDPatch version
 
			uint major    = 2;
 
			uint minor    = 6;
 
			uint revision = 1; // special case: 2.0.1 is 2.0.10
 
			uint build    = 1382;
 
			*value = (major << 24) | (minor << 20) | (revision << 16) | build;
 
			return true;
 
		}
 

	
 
		case 0x0D: // TTD Version, 00=DOS, 01=Windows
 
			*value = _cur.grfconfig->palette & GRFP_USE_MASK;
 
			return true;
 

	
 
		case 0x0E: // Y-offset for train sprites
 
			*value = _cur.grffile->traininfo_vehicle_pitch;
 
			return true;
 

	
 
		case 0x0F: // Rail track type cost factors
 
			*value = 0;
 
			SB(*value, 0, 8, GetRailTypeInfo(RAILTYPE_RAIL)->cost_multiplier); // normal rail
 
			if (_settings_game.vehicle.disable_elrails) {
 
				/* skip elrail multiplier - disabled */
 
@@ -9793,49 +9793,49 @@ static void AfterLoadGRFs()
 

	
 
	SetYearEngineAgingStops();
 

	
 
	FinalisePriceBaseMultipliers();
 

	
 
	/* Deallocate temporary loading data */
 
	free(_gted);
 
	_grm_sprites.clear();
 
}
 

	
 
/**
 
 * Load all the NewGRFs.
 
 * @param load_index The offset for the first sprite to add.
 
 * @param num_baseset Number of NewGRFs at the front of the list to look up in the baseset dir instead of the newgrf dir.
 
 */
 
void LoadNewGRF(uint load_index, uint num_baseset)
 
{
 
	/* In case of networking we need to "sync" the start values
 
	 * so all NewGRFs are loaded equally. For this we use the
 
	 * start date of the game and we set the counters, etc. to
 
	 * 0 so they're the same too. */
 
	Date date            = _date;
 
	Year year            = _cur_year;
 
	DateFract date_fract = _date_fract;
 
	uint16 tick_counter  = _tick_counter;
 
	uint64 tick_counter  = _tick_counter;
 
	byte display_opt     = _display_opt;
 

	
 
	if (_networking) {
 
		_cur_year     = _settings_game.game_creation.starting_year;
 
		_date         = ConvertYMDToDate(_cur_year, 0, 1);
 
		_date_fract   = 0;
 
		_tick_counter = 0;
 
		_display_opt  = 0;
 
	}
 

	
 
	InitializeGRFSpecial();
 

	
 
	ResetNewGRFData();
 

	
 
	/*
 
	 * Reset the status of all files, so we can 'retry' to load them.
 
	 * This is needed when one for example rearranges the NewGRFs in-game
 
	 * and a previously disabled NewGRF becomes usable. If it would not
 
	 * be reset, the NewGRF would remain disabled even though it should
 
	 * have been enabled.
 
	 */
 
	for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
 
		if (c->status != GCS_NOT_FOUND) c->status = GCS_UNKNOWN;
 
	}
src/newgrf_animation_base.h
Show inline comments
 
@@ -32,49 +32,49 @@ struct AnimationBase {
 
	 * @param spec        Specification related to the tile.
 
	 * @param obj         Object related to the tile.
 
	 * @param tile        Tile to animate changes for.
 
	 * @param random_animation Whether to pass random bits to the "next frame" callback.
 
	 * @param extra_data  Custom extra callback data.
 
	 */
 
	static void AnimateTile(const Tspec *spec, Tobj *obj, TileIndex tile, bool random_animation, Textra extra_data = 0)
 
	{
 
		assert(spec != nullptr);
 

	
 
		/* Acquire the animation speed from the NewGRF. */
 
		uint8 animation_speed = spec->animation.speed;
 
		if (HasBit(spec->callback_mask, Tbase::cbm_animation_speed)) {
 
			uint16 callback = GetCallback(Tbase::cb_animation_speed, 0, 0, spec, obj, tile, extra_data);
 
			if (callback != CALLBACK_FAILED) {
 
				if (callback >= 0x100 && spec->grf_prop.grffile->grf_version >= 8) ErrorUnknownCallbackResult(spec->grf_prop.grffile->grfid, Tbase::cb_animation_speed, callback);
 
				animation_speed = Clamp(callback & 0xFF, 0, 16);
 
			}
 
		}
 

	
 
		/* An animation speed of 2 means the animation frame changes 4 ticks, and
 
		 * increasing this value by one doubles the wait. 0 is the minimum value
 
		 * allowed for animation_speed, which corresponds to 30ms, and 16 is the
 
		 * maximum, corresponding to around 33 minutes. */
 
		if (_tick_counter % (1 << animation_speed) != 0) return;
 
		if (_tick_counter % (1ULL << animation_speed) != 0) return;
 

	
 
		uint8 frame      = GetAnimationFrame(tile);
 
		uint8 num_frames = spec->animation.frames;
 

	
 
		bool frame_set_by_callback = false;
 

	
 
		if (HasBit(spec->callback_mask, Tbase::cbm_animation_next_frame)) {
 
			uint16 callback = GetCallback(Tbase::cb_animation_next_frame, random_animation ? Random() : 0, 0, spec, obj, tile, extra_data);
 

	
 
			if (callback != CALLBACK_FAILED) {
 
				frame_set_by_callback = true;
 

	
 
				switch (callback & 0xFF) {
 
					case 0xFF:
 
						DeleteAnimatedTile(tile);
 
						break;
 

	
 
					case 0xFE:
 
						frame_set_by_callback = false;
 
						break;
 

	
 
					default:
 
						frame = callback & 0xFF;
 
						break;
src/newgrf_profiling.cpp
Show inline comments
 
@@ -88,73 +88,73 @@ void NewGRFProfiler::Start()
 
	this->Abort();
 
	this->active = true;
 
	this->start_tick = _tick_counter;
 
}
 

	
 
uint32 NewGRFProfiler::Finish()
 
{
 
	if (!this->active) return 0;
 

	
 
	if (this->calls.empty()) {
 
		IConsolePrint(CC_DEBUG, "Finished profile of NewGRF [{:08X}], no events collected, not writing a file.", BSWAP32(this->grffile->grfid));
 
		return 0;
 
	}
 

	
 
	std::string filename = this->GetOutputFilename();
 
	IConsolePrint(CC_DEBUG, "Finished profile of NewGRF [{:08X}], writing {} events to '{}'.", BSWAP32(this->grffile->grfid), this->calls.size(), filename);
 

	
 
	FILE *f = FioFOpenFile(filename, "wt", Subdirectory::NO_DIRECTORY);
 
	FileCloser fcloser(f);
 

	
 
	uint32 total_microseconds = 0;
 

	
 
	fputs("Tick,Sprite,Feature,Item,CallbackID,Microseconds,Depth,Result\n", f);
 
	for (const Call &c : this->calls) {
 
		fprintf(f, "%u,%u,0x%X,%u,0x%X,%u,%u,%u\n", c.tick, c.root_sprite, c.feat, c.item, (uint)c.cb, c.time, c.subs, c.result);
 
		fprintf(f, OTTD_PRINTF64U ",%u,0x%X,%u,0x%X,%u,%u,%u\n", c.tick, c.root_sprite, c.feat, c.item, (uint)c.cb, c.time, c.subs, c.result);
 
		total_microseconds += c.time;
 
	}
 

	
 
	this->Abort();
 

	
 
	return total_microseconds;
 
}
 

	
 
void NewGRFProfiler::Abort()
 
{
 
	this->active = false;
 
	this->calls.clear();
 
}
 

	
 
/**
 
 * Get name of the file that will be written.
 
 * @return File name of profiling output file.
 
 */
 
std::string NewGRFProfiler::GetOutputFilename() const
 
{
 
	char timestamp[16] = {};
 
	LocalTime::Format(timestamp, lastof(timestamp), "%Y%m%d-%H%M");
 

	
 
	char filepath[MAX_PATH] = {};
 
	seprintf(filepath, lastof(filepath), "%sgrfprofile-%s-%08X.csv", FiosGetScreenshotDir(), timestamp, BSWAP32(this->grffile->grfid));
 

	
 
	return std::string(filepath);
 
}
 

	
 
uint32 NewGRFProfiler::FinishAll()
 
{
 
	int max_ticks = 0;
 
	uint64 max_ticks = 0;
 
	uint32 total_microseconds = 0;
 
	for (NewGRFProfiler &pr : _newgrf_profilers) {
 
		if (pr.active) {
 
			total_microseconds += pr.Finish();
 
			max_ticks = std::max(max_ticks, _tick_counter - pr.start_tick);
 
		}
 
	}
 

	
 
	if (total_microseconds > 0 && max_ticks > 0) {
 
		IConsolePrint(CC_DEBUG, "Total NewGRF callback processing: {} microseconds over {} ticks.", total_microseconds, max_ticks);
 
	}
 

	
 
	_newgrf_profile_end_date = MAX_DAY;
 

	
 
	return total_microseconds;
 
}
src/newgrf_profiling.h
Show inline comments
 
@@ -24,40 +24,40 @@
 
 * Callback profiler for NewGRF development
 
 */
 
struct NewGRFProfiler {
 
	NewGRFProfiler(const GRFFile *grffile);
 
	~NewGRFProfiler();
 

	
 
	void BeginResolve(const ResolverObject &resolver);
 
	void EndResolve(const SpriteGroup *result);
 
	void RecursiveResolve();
 

	
 
	void Start();
 
	uint32 Finish();
 
	void Abort();
 
	std::string GetOutputFilename() const;
 

	
 
	static uint32 FinishAll();
 

	
 
	/** Measurement of a single sprite group resolution */
 
	struct Call {
 
		uint32 root_sprite;  ///< Pseudo-sprite index in GRF file
 
		uint32 item;         ///< Local ID of item being resolved for
 
		uint32 result;       ///< Result of callback
 
		uint32 subs;         ///< Sub-calls to other sprite groups
 
		uint32 time;         ///< Time taken for resolution (microseconds)
 
		uint16 tick;         ///< Game tick
 
		uint64 tick;         ///< Game tick
 
		CallbackID cb;       ///< Callback ID
 
		GrfSpecFeature feat; ///< GRF feature being resolved for
 
	};
 

	
 
	const GRFFile *grffile;  ///< Which GRF is being profiled
 
	bool active;             ///< Is this profiler collecting data
 
	uint16 start_tick;       ///< Tick number this profiler was started on
 
	uint64 start_tick;       ///< Tick number this profiler was started on
 
	Call cur_call;           ///< Data for current call in progress
 
	std::vector<Call> calls; ///< All calls collected so far
 
};
 

	
 
extern std::vector<NewGRFProfiler> _newgrf_profilers;
 
extern Date _newgrf_profile_end_date;
 

	
 
#endif /* NEWGRF_PROFILING_H */
src/saveload/gamelog_sl.cpp
Show inline comments
 
@@ -323,49 +323,50 @@ public:
 

	
 
				SlObject(lc, this->GetLoadDescription());
 
			}
 
			return;
 
		}
 

	
 
		size_t length = SlGetStructListLength(UINT32_MAX);
 
		la->change = ReallocT(la->change, length);
 
		la->changes = (uint32)length;
 

	
 
		for (size_t i = 0; i < length; i++) {
 
			LoggedChange *lc = &la->change[i];
 
			memset(lc, 0, sizeof(*lc));
 

	
 
			lc->ct = (GamelogChangeType)SlReadByte();
 
			SlObject(lc, this->GetLoadDescription());
 
		}
 
	}
 

	
 
	void LoadCheck(LoggedAction *la) const override { this->Load(la); }
 
};
 

	
 
static const SaveLoad _gamelog_desc[] = {
 
	SLE_CONDVAR(LoggedAction, at,            SLE_UINT8,   SLV_RIFF_TO_ARRAY, SL_MAX_VERSION),
 
	SLE_VAR(LoggedAction, tick,              SLE_UINT16),
 
	SLE_CONDVAR(LoggedAction, tick, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER),
 
	SLE_CONDVAR(LoggedAction, tick, SLE_UINT64,                 SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
 
	SLEG_STRUCTLIST("action", SlGamelogAction),
 
};
 

	
 
struct GLOGChunkHandler : ChunkHandler {
 
	GLOGChunkHandler() : ChunkHandler('GLOG', CH_TABLE) {}
 

	
 
	void LoadCommon(LoggedAction *&gamelog_action, uint &gamelog_actions) const
 
	{
 
		assert(gamelog_action == nullptr);
 
		assert(gamelog_actions == 0);
 

	
 
		const std::vector<SaveLoad> slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat);
 

	
 
		if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
 
			byte type;
 
			while ((type = SlReadByte()) != GLAT_NONE) {
 
				if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type");
 

	
 
				gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
 
				LoggedAction *la = &gamelog_action[gamelog_actions++];
 
				memset(la, 0, sizeof(*la));
 

	
 
				la->at = (GamelogActionType)type;
 
				SlObject(la, slt);
src/saveload/misc_sl.cpp
Show inline comments
 
@@ -53,49 +53,50 @@ void ResetViewportAfterLoadGame()
 
	w->viewport->dest_scrollpos_y = _saved_scrollpos_y;
 

	
 
	Viewport *vp = w->viewport;
 
	vp->zoom = std::min(_saved_scrollpos_zoom, ZOOM_LVL_MAX);
 
	vp->virtual_width = ScaleByZoom(vp->width, vp->zoom);
 
	vp->virtual_height = ScaleByZoom(vp->height, vp->zoom);
 

	
 
	/* If zoom_max is ZOOM_LVL_MIN then the setting has not been loaded yet, therefore all levels are allowed. */
 
	if (_settings_client.gui.zoom_max != ZOOM_LVL_MIN) {
 
		/* Ensure zoom level is allowed */
 
		while (vp->zoom < _settings_client.gui.zoom_min) DoZoomInOutWindow(ZOOM_OUT, w);
 
		while (vp->zoom > _settings_client.gui.zoom_max) DoZoomInOutWindow(ZOOM_IN, w);
 
	}
 

	
 
	DoZoomInOutWindow(ZOOM_NONE, w); // update button status
 
	MarkWholeScreenDirty();
 
}
 

	
 
byte _age_cargo_skip_counter; ///< Skip aging of cargo? Used before savegame version 162.
 

	
 
static const SaveLoad _date_desc[] = {
 
	SLEG_CONDVAR("date",                   _date,                   SLE_FILE_U16 | SLE_VAR_I32,  SL_MIN_VERSION,  SLV_31),
 
	SLEG_CONDVAR("date",                   _date,                   SLE_INT32,                  SLV_31, SL_MAX_VERSION),
 
	    SLEG_VAR("date_fract",             _date_fract,             SLE_UINT16),
 
	    SLEG_VAR("tick_counter",         _tick_counter,           SLE_UINT16),
 
	SLEG_CONDVAR("tick_counter",           _tick_counter,           SLE_FILE_U16 | SLE_VAR_U64,  SL_MIN_VERSION, SLV_U64_TICK_COUNTER),
 
	SLEG_CONDVAR("tick_counter",           _tick_counter,           SLE_UINT64,                  SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
 
	SLEG_CONDVAR("age_cargo_skip_counter", _age_cargo_skip_counter, SLE_UINT8,                   SL_MIN_VERSION, SLV_162),
 
	SLEG_CONDVAR("cur_tileloop_tile",      _cur_tileloop_tile,      SLE_FILE_U16 | SLE_VAR_U32,  SL_MIN_VERSION, SLV_6),
 
	SLEG_CONDVAR("cur_tileloop_tile",      _cur_tileloop_tile,      SLE_UINT32,                  SLV_6, SL_MAX_VERSION),
 
	    SLEG_VAR("next_disaster_start",         _disaster_delay,         SLE_UINT16),
 
	    SLEG_VAR("random_state[0]",        _random.state[0],        SLE_UINT32),
 
	    SLEG_VAR("random_state[1]",        _random.state[1],        SLE_UINT32),
 
	    SLEG_VAR("company_tick_counter", _cur_company_tick_index, SLE_FILE_U8  | SLE_VAR_U32),
 
	SLEG_CONDVAR("next_competitor_start",  _next_competitor_start,  SLE_FILE_U16 | SLE_VAR_U32,  SL_MIN_VERSION, SLV_109),
 
	SLEG_CONDVAR("next_competitor_start",  _next_competitor_start,  SLE_UINT32,                SLV_109, SL_MAX_VERSION),
 
	    SLEG_VAR("trees_tick_counter",     _trees_tick_ctr,         SLE_UINT8),
 
	SLEG_CONDVAR("pause_mode",             _pause_mode,             SLE_UINT8,                   SLV_4, SL_MAX_VERSION),
 
};
 

	
 
static const SaveLoad _date_check_desc[] = {
 
	SLEG_CONDVAR("date", _load_check_data.current_date,  SLE_FILE_U16 | SLE_VAR_I32,  SL_MIN_VERSION,  SLV_31),
 
	SLEG_CONDVAR("date", _load_check_data.current_date,  SLE_INT32,                  SLV_31, SL_MAX_VERSION),
 
};
 

	
 
/* Save load date related variables as well as persistent tick counters
 
 * XXX: currently some unrelated stuff is just put here */
 
struct DATEChunkHandler : ChunkHandler {
 
	DATEChunkHandler() : ChunkHandler('DATE', CH_TABLE) {}
 

	
 
	void Save() const override
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -1588,49 +1588,49 @@ static const OldChunks main_chunk[] = {
 
	OCL_ASSERT( OC_TTO, 0x1AC4 ),
 

	
 
	OCL_CCHUNK( OC_TTD, 5000, LoadOldOrder ),
 
	OCL_CCHUNK( OC_TTO, 3000, LoadOldOrder ),
 

	
 
	OCL_ASSERT( OC_TTD, 0x4328 ),
 
	OCL_ASSERT( OC_TTO, 0x3234 ),
 

	
 
	OCL_CHUNK( 1, LoadOldAnimTileList ),
 
	OCL_NULL( 4 ),              ///< old end-of-order-list-pointer, no longer in use
 

	
 
	OCL_ASSERT( OC_TTO, 0x3438 ),
 

	
 
	OCL_CCHUNK( OC_TTD, 255, LoadOldDepot ),
 
	OCL_CCHUNK( OC_TTO, 252, LoadOldDepot ),
 

	
 
	OCL_ASSERT( OC_TTD, 0x4B26 ),
 
	OCL_ASSERT( OC_TTO, 0x3A20 ),
 

	
 
	OCL_NULL( 4 ),              ///< town counter,  no longer in use
 
	OCL_NULL( 2 ),              ///< timer_counter, no longer in use
 
	OCL_NULL( 2 ),              ///< land_code,     no longer in use
 

	
 
	OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_age_cargo_skip_counter ),
 
	OCL_VAR ( OC_UINT16,   1, &_tick_counter ),
 
	OCL_VAR ( OC_FILE_U16 | OC_VAR_U64, 1, &_tick_counter ),
 
	OCL_VAR (   OC_TILE,   1, &_cur_tileloop_tile ),
 

	
 
	OCL_ASSERT( OC_TTO, 0x3A2E ),
 

	
 
	OCL_CNULL( OC_TTO, 48 * 6 ), ///< prices
 
	OCL_CNULL( OC_TTD, 49 * 6 ), ///< prices
 

	
 
	OCL_ASSERT( OC_TTO, 0x3B4E ),
 

	
 
	OCL_CNULL( OC_TTO, 11 * 8 ), ///< cargo payment rates
 
	OCL_CNULL( OC_TTD, 12 * 8 ), ///< cargo payment rates
 

	
 
	OCL_ASSERT( OC_TTD, 0x4CBA ),
 
	OCL_ASSERT( OC_TTO, 0x3BA6 ),
 

	
 
	OCL_CHUNK( 1, LoadOldMapPart1 ),
 

	
 
	OCL_ASSERT( OC_TTD, 0x48CBA ),
 
	OCL_ASSERT( OC_TTO, 0x23BA6 ),
 

	
 
	OCL_CCHUNK( OC_TTD, 250, LoadOldStation ),
 
	OCL_CCHUNK( OC_TTO, 200, LoadOldStation ),
 

	
 
	OCL_ASSERT( OC_TTO, 0x29E16 ),
src/saveload/saveload.h
Show inline comments
 
@@ -319,48 +319,49 @@ enum SaveLoadVersion : uint16 {
 
	 * patchpacks. This way we can present the user with a clean error
 
	 * indicate they are loading a savegame from a patchpack.
 
	 * For future patchpack creators: please follow a system like JGRPP, where
 
	 * the version is masked with 0x8000, and the true version is stored in
 
	 * its own chunk with feature toggles.
 
	 */
 
	SLV_START_PATCHPACKS,                   ///< 220  First known patchpack to use a version just above ours.
 
	SLV_END_PATCHPACKS = 286,               ///< 286  Last known patchpack to use a version just above ours.
 

	
 
	SLV_GS_INDUSTRY_CONTROL,                ///< 287  PR#7912 and PR#8115 GS industry control.
 
	SLV_VEH_MOTION_COUNTER,                 ///< 288  PR#8591 Desync safe motion counter
 
	SLV_INDUSTRY_TEXT,                      ///< 289  PR#8576 v1.11.0-RC1  Additional GS text for industries.
 

	
 
	SLV_MAPGEN_SETTINGS_REVAMP,             ///< 290  PR#8891 v1.11  Revamp of some mapgen settings (snow coverage, desert coverage, heightmap height, custom terrain type).
 
	SLV_GROUP_REPLACE_WAGON_REMOVAL,        ///< 291  PR#7441 Per-group wagon removal flag.
 
	SLV_CUSTOM_SUBSIDY_DURATION,            ///< 292  PR#9081 Configurable subsidy duration.
 
	SLV_SAVELOAD_LIST_LENGTH,               ///< 293  PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST.
 
	SLV_RIFF_TO_ARRAY,                      ///< 294  PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks.
 

	
 
	SLV_TABLE_CHUNKS,                       ///< 295  PR#9322 Introduction of CH_TABLE and CH_SPARSE_TABLE.
 
	SLV_SCRIPT_INT64,                       ///< 296  PR#9415 SQInteger is 64bit but was saved as 32bit.
 
	SLV_LINKGRAPH_TRAVEL_TIME,              ///< 297  PR#9457 v12.0-RC1  Store travel time in the linkgraph.
 
	SLV_DOCK_DOCKINGTILES,                  ///< 298  PR#9578 All tiles around docks may be docking tiles.
 
	SLV_REPAIR_OBJECT_DOCKING_TILES,        ///< 299  PR#9594 v12.0  Fixing issue with docking tiles overlapping objects.
 
	SLV_U64_TICK_COUNTER,                   ///< 300  PR#10035 Make _tick_counter 64bit to avoid wrapping.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
 

	
 
/** Save or load result codes. */
 
enum SaveOrLoadResult {
 
	SL_OK     = 0, ///< completed successfully
 
	SL_ERROR  = 1, ///< error that was caught before internal structures were modified
 
	SL_REINIT = 2, ///< error that was caught in the middle of updating game state, need to clear it. (can only happen during load)
 
};
 

	
 
/** 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).
 
	std::string name;                ///< 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);
 
};
src/stdafx.h
Show inline comments
 
@@ -282,55 +282,63 @@
 
		template <typename T> std::string FS2OTTD(T name) { return name; }
 
		template <typename T> std::string OTTD2FS(T name) { return name; }
 
#	endif /* _WIN32 or WITH_ICONV */
 
#endif /* STRGEN || SETTINGSGEN */
 

	
 
#if defined(_WIN32) || defined(__OS2__) && !defined(__INNOTEK_LIBC__)
 
#	define PATHSEP "\\"
 
#	define PATHSEPCHAR '\\'
 
#else
 
#	define PATHSEP "/"
 
#	define PATHSEPCHAR '/'
 
#endif
 

	
 
#if defined(_MSC_VER) || defined(__WATCOMC__)
 
#	define PACK_N(type_dec, n) __pragma(pack(push, n)) type_dec; __pragma(pack(pop))
 
#elif defined(__MINGW32__)
 
#	define PRAGMA(x) _Pragma(#x)
 
#	define PACK_N(type_dec, n) PRAGMA(pack(push, n)) type_dec; PRAGMA(pack(pop))
 
#else
 
#	define PACK_N(type_dec, n) type_dec __attribute__((__packed__, aligned(n)))
 
#endif
 
#define PACK(type_dec) PACK_N(type_dec, 1)
 

	
 
/* MSVCRT of course has to have a different syntax for long long *sigh* */
 
#if defined(_MSC_VER) || defined(__MINGW32__)
 
#if defined(_MSC_VER)
 
#   define OTTD_PRINTF64 "%I64d"
 
#   define OTTD_PRINTF64U "%I64u"
 
#   define OTTD_PRINTFHEX64 "%I64x"
 
#   define PRINTF_SIZE "%Iu"
 
#   define PRINTF_SIZEX "%IX"
 
#elif defined(__MINGW32__)
 
#   define OTTD_PRINTF64 "%I64d"
 
#   define OTTD_PRINTF64U "%I64llu"
 
#   define OTTD_PRINTFHEX64 "%I64x"
 
#   define PRINTF_SIZE "%Iu"
 
#   define PRINTF_SIZEX "%IX"
 
#else
 
#   define OTTD_PRINTF64 "%lld"
 
#   define OTTD_PRINTF64U "%llu"
 
#   define OTTD_PRINTFHEX64 "%llx"
 
#   define PRINTF_SIZE "%zu"
 
#   define PRINTF_SIZEX "%zX"
 
#endif
 

	
 
typedef unsigned char byte;
 

	
 
/* This is already defined in unix, but not in QNX Neutrino (6.x) or Cygwin. */
 
#if (!defined(UNIX) && !defined(__HAIKU__)) || defined(__QNXNTO__) || defined(__CYGWIN__)
 
	typedef unsigned int uint;
 
#endif
 

	
 
#if defined(TROUBLED_INTS)
 
	/* Haiku's types for uint32/int32/uint64/int64 are different than what
 
	 * they are on other platforms; not in length, but how to print them.
 
	 * So make them more like the other platforms, to make printf() etc a
 
	 * little bit easier. */
 
#	define uint32 uint32_ugly_hack
 
#	define int32 int32_ugly_hack
 
#	define uint64 uint64_ugly_hack
 
#	define int64 int64_ugly_hack
 
	typedef unsigned int uint32_ugly_hack;
 
	typedef signed int int32_ugly_hack;
 
	typedef unsigned __int64 uint64_ugly_hack;
0 comments (0 inline, 0 general)