Changeset - r21576:8f655ba7bab2
[Not reviewed]
master
0 2 0
rubidium - 10 years ago 2014-07-21 18:03:32
rubidium@openttd.org
(svn r26700) -Fix [FS#6066]: incorrect saving of order backups
2 files changed with 11 insertions and 7 deletions:
0 comments (0 inline, 0 general)
src/saveload/order_sl.cpp
Show inline comments
 
@@ -160,159 +160,162 @@ static void Load_ORDR()
 

	
 
			SlArray(orders, len, SLE_UINT32);
 

	
 
			for (size_t i = 0; i < len; ++i) {
 
				new (i) Order(orders[i]);
 
			}
 

	
 
			free(orders);
 
		}
 

	
 
		/* Update all the next pointer */
 
		Order *o;
 
		FOR_ALL_ORDERS(o) {
 
			/* Delete invalid orders */
 
			if (o->IsType(OT_NOTHING)) {
 
				delete o;
 
				continue;
 
			}
 
			/* The orders were built like this:
 
			 * While the order is valid, set the previous will get its next pointer set */
 
			Order *prev = Order::GetIfValid(order_index - 1);
 
			if (prev != NULL) prev->next = o;
 
		}
 
	} else {
 
		int index;
 

	
 
		while ((index = SlIterateArray()) != -1) {
 
			Order *order = new (index) Order();
 
			SlObject(order, GetOrderDescription());
 
			if (IsSavegameVersionBefore(190)) {
 
				order->SetTravelTimetabled(order->GetTravelTime() > 0);
 
				order->SetWaitTimetabled(order->GetWaitTime() > 0);
 
			}
 
		}
 
	}
 
}
 

	
 
static void Ptrs_ORDR()
 
{
 
	/* Orders from old savegames have pointers corrected in Load_ORDR */
 
	if (IsSavegameVersionBefore(5, 2)) return;
 

	
 
	Order *o;
 

	
 
	FOR_ALL_ORDERS(o) {
 
		SlObject(o, GetOrderDescription());
 
	}
 
}
 

	
 
const SaveLoad *GetOrderListDescription()
 
{
 
	static const SaveLoad _orderlist_desc[] = {
 
		SLE_REF(OrderList, first,              REF_ORDER),
 
		SLE_END()
 
	};
 

	
 
	return _orderlist_desc;
 
}
 

	
 
static void Save_ORDL()
 
{
 
	OrderList *list;
 

	
 
	FOR_ALL_ORDER_LISTS(list) {
 
		SlSetArrayIndex(list->index);
 
		SlObject(list, GetOrderListDescription());
 
	}
 
}
 

	
 
static void Load_ORDL()
 
{
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		/* set num_orders to 0 so it's a valid OrderList */
 
		OrderList *list = new (index) OrderList(0);
 
		SlObject(list, GetOrderListDescription());
 
	}
 

	
 
}
 

	
 
static void Ptrs_ORDL()
 
{
 
	OrderList *list;
 

	
 
	FOR_ALL_ORDER_LISTS(list) {
 
		SlObject(list, GetOrderListDescription());
 
	}
 
}
 

	
 
const SaveLoad *GetOrderBackupDescription()
 
{
 
	static const SaveLoad _order_backup_desc[] = {
 
		     SLE_VAR(OrderBackup, user,                     SLE_UINT32),
 
		     SLE_VAR(OrderBackup, tile,                     SLE_UINT32),
 
		     SLE_VAR(OrderBackup, group,                    SLE_UINT16),
 
		     SLE_VAR(OrderBackup, service_interval,         SLE_UINT32),
 
		 SLE_CONDVAR(OrderBackup, service_interval,         SLE_FILE_U32 | SLE_VAR_U16,  0, 191),
 
		 SLE_CONDVAR(OrderBackup, service_interval,         SLE_UINT16,                192, SL_MAX_VERSION),
 
		     SLE_STR(OrderBackup, name,                     SLE_STR, 0),
 
		     SLE_VAR(OrderBackup, clone,                    SLE_UINT16),
 
		SLE_CONDNULL(2,                                                                  0, 191), // clone (2 bytes of pointer, i.e. garbage)
 
		 SLE_CONDREF(OrderBackup, clone,                    REF_VEHICLE,               192, SL_MAX_VERSION),
 
		     SLE_VAR(OrderBackup, cur_real_order_index,     SLE_UINT8),
 
		 SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_UINT8,                 176, SL_MAX_VERSION),
 
		 SLE_CONDVAR(OrderBackup, current_order_time,       SLE_UINT32,                176, SL_MAX_VERSION),
 
		 SLE_CONDVAR(OrderBackup, lateness_counter,         SLE_INT32,                 176, SL_MAX_VERSION),
 
		 SLE_CONDVAR(OrderBackup, timetable_start,          SLE_INT32,                 176, SL_MAX_VERSION),
 
		 SLE_CONDVAR(OrderBackup, vehicle_flags,            SLE_FILE_U8 | SLE_VAR_U16, 176, 179),
 
		 SLE_CONDVAR(OrderBackup, vehicle_flags,            SLE_UINT16,                180, SL_MAX_VERSION),
 
		     SLE_REF(OrderBackup, orders,                   REF_ORDER),
 
		     SLE_END()
 
	};
 

	
 
	return _order_backup_desc;
 
}
 

	
 
static void Save_BKOR()
 
{
 
	/* We only save this when we're a network server
 
	 * as we want this information on our clients. For
 
	 * normal games this information isn't needed. */
 
	if (!_networking || !_network_server) return;
 

	
 
	OrderBackup *ob;
 
	FOR_ALL_ORDER_BACKUPS(ob) {
 
		SlSetArrayIndex(ob->index);
 
		SlObject(ob, GetOrderBackupDescription());
 
	}
 
}
 

	
 
void Load_BKOR()
 
{
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		/* set num_orders to 0 so it's a valid OrderList */
 
		OrderBackup *ob = new (index) OrderBackup();
 
		SlObject(ob, GetOrderBackupDescription());
 
	}
 

	
 
	/* Only load order-backups for network clients.
 
	 * If we are a network server or not networking, then we just loaded
 
	 * a previously saved-by-server savegame. There are
 
	 * no clients with a backup anymore, so clear it. */
 
	if (!_networking || _network_server) {
 
	 * If we are a network server or not networking, then we just loaded a previously
 
	 * saved-by-server savegame. There are no clients with a backup, so clear it.
 
	 * Furthermore before savegame version 192 the actual content was always corrupt.
 
	 */
 
	if (!_networking || _network_server || IsSavegameVersionBefore(192)) {
 
		_order_backup_pool.CleanPool();
 
	}
 
}
 

	
 
static void Ptrs_BKOR()
 
{
 
	OrderBackup *ob;
 
	FOR_ALL_ORDER_BACKUPS(ob) {
 
		SlObject(ob, GetOrderBackupDescription());
 
	}
 
}
 

	
 
extern const ChunkHandler _order_chunk_handlers[] = {
 
	{ 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, NULL, CH_ARRAY},
 
	{ 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, NULL, CH_ARRAY},
 
	{ 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, NULL, CH_ARRAY | CH_LAST},
 
};
src/saveload/saveload.cpp
Show inline comments
 
@@ -166,194 +166,195 @@
 
 *   96   13226
 
 *   97   13256
 
 *   98   13375
 
 *   99   13838
 
 *  100   13952
 
 *  101   14233
 
 *  102   14332
 
 *  103   14598
 
 *  104   14735
 
 *  105   14803
 
 *  106   14919
 
 *  107   15027
 
 *  108   15045
 
 *  109   15075
 
 *  110   15148
 
 *  111   15190
 
 *  112   15290
 
 *  113   15340
 
 *  114   15601
 
 *  115   15695
 
 *  116   15893   0.7.x
 
 *  117   16037
 
 *  118   16129
 
 *  119   16242
 
 *  120   16439
 
 *  121   16694
 
 *  122   16855
 
 *  123   16909
 
 *  124   16993
 
 *  125   17113
 
 *  126   17433
 
 *  127   17439
 
 *  128   18281
 
 *  129   18292
 
 *  130   18404
 
 *  131   18481
 
 *  132   18522
 
 *  133   18674
 
 *  134   18703
 
 *  135   18719
 
 *  136   18764
 
 *  137   18912
 
 *  138   18942   1.0.x
 
 *  139   19346
 
 *  140   19382
 
 *  141   19799
 
 *  142   20003
 
 *  143   20048
 
 *  144   20334
 
 *  145   20376
 
 *  146   20446
 
 *  147   20621
 
 *  148   20659
 
 *  149   20832
 
 *  150   20857
 
 *  151   20918
 
 *  152   21171
 
 *  153   21263
 
 *  154   21426
 
 *  155   21453
 
 *  156   21728
 
 *  157   21862
 
 *  158   21933
 
 *  159   21962
 
 *  160   21974   1.1.x
 
 *  161   22567
 
 *  162   22713
 
 *  163   22767
 
 *  164   23290
 
 *  165   23304
 
 *  166   23415
 
 *  167   23504
 
 *  168   23637
 
 *  169   23816
 
 *  170   23826
 
 *  171   23835
 
 *  172   23947
 
 *  173   23967   1.2.0-RC1
 
 *  174   23973   1.2.x
 
 *  175   24136
 
 *  176   24446
 
 *  177   24619
 
 *  178   24789
 
 *  179   24810
 
 *  180   24998   1.3.x
 
 *  181   25012
 
 *  182   25296
 
 *  183   25363
 
 *  184   25508
 
 *  185   25620
 
 *  186   25833
 
 *  187   25899
 
 *  188   26169   1.4.x
 
 *  189   26450
 
 *  190   26547
 
 *  191   26646
 
 *  192   26700
 
 */
 
extern const uint16 SAVEGAME_VERSION = 191; ///< Current savegame version of OpenTTD.
 
extern const uint16 SAVEGAME_VERSION = 192; ///< Current savegame version of OpenTTD.
 

	
 
SavegameType _savegame_type; ///< type of savegame we are loading
 

	
 
uint32 _ttdp_version;     ///< version of TTDP savegame (if applicable)
 
uint16 _sl_version;       ///< the major savegame version identifier
 
byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
char _savegame_format[8]; ///< how to compress savegames
 
bool _do_autosave;        ///< are we doing an autosave at the moment?
 

	
 
/** What are we currently doing? */
 
enum SaveLoadAction {
 
	SLA_LOAD,        ///< loading
 
	SLA_SAVE,        ///< saving
 
	SLA_PTRS,        ///< fixing pointers
 
	SLA_NULL,        ///< null all pointers (on loading error)
 
	SLA_LOAD_CHECK,  ///< partial loading into #_load_check_data
 
};
 

	
 
enum NeedLength {
 
	NL_NONE = 0,       ///< not working in NeedLength mode
 
	NL_WANTLENGTH = 1, ///< writing length and data
 
	NL_CALCLENGTH = 2, ///< need to calculate the length
 
};
 

	
 
/** 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)
 
	{
 
	}
 

	
 
	inline byte ReadByte()
 
	{
 
		if (this->bufp == this->bufe) {
 
			size_t len = this->reader->Read(this->buf, lengthof(this->buf));
 
			if (len == 0) SlErrorCorrupt("Unexpected end of chunk");
 

	
 
			this->read += len;
 
			this->bufp = this->buf;
 
			this->bufe = this->buf + len;
 
		}
 

	
 
		return *this->bufp++;
 
	}
 

	
 
	/**
 
	 * Get the size of the memory dump made so far.
 
	 * @return The size.
 
	 */
 
	size_t GetSize() const
 
	{
 
		return this->read - (this->bufe - this->bufp);
 
	}
 
};
 

	
 

	
 
/** Container for dumping the savegame (quickly) to memory. */
 
struct MemoryDumper {
 
	AutoFreeSmallVector<byte *, 16> blocks; ///< Buffer with blocks of allocated memory.
 
	byte *buf;                              ///< Buffer we're going to write to.
 
	byte *bufe;                             ///< End of the buffer we write to.
 

	
 
	/** Initialise our variables. */
 
	MemoryDumper() : buf(NULL), bufe(NULL)
 
	{
 
	}
 

	
 
	/**
 
	 * 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 (this->buf == this->bufe) {
 
			this->buf = CallocT<byte>(MEMORY_CHUNK_SIZE);
 
			*this->blocks.Append() = this->buf;
 
			this->bufe = this->buf + MEMORY_CHUNK_SIZE;
 
		}
 

	
 
		*this->buf++ = b;
 
	}
 

	
 
	/**
0 comments (0 inline, 0 general)