Beispiel #1
0
	/**
	 * Assign items from other vector.
	 */
	inline void Assign(const SmallMatrix &other)
	{
		if (&other == this) return;

		this->height = other.Height();
		this->width = other.Width();
		uint num_items = this->width * this->height;
		if (num_items > this->capacity) {
			this->capacity = num_items;
			free(this->data);
			this->data = MallocT<T>(num_items);
			MemCpyT(this->data, other[0], num_items);
		} else if (num_items > 0) {
			MemCpyT(this->data, other[0], num_items);
		}
	}
	/** Allocates space for a new tile in the matrix.
	 * @param tile Tile to add.
	 */
	void AllocateStorage(TileIndex tile)
	{
		uint old_left = TileX(this->area.tile) / N;
		uint old_top  = TileY(this->area.tile) / N;
		uint old_w    = this->area.w / N;
		uint old_h    = this->area.h / N;

		/* Add the square the tile is in to the tile area. We do this
		 * by adding top-left and bottom-right of the square. */
		uint grid_x = (TileX(tile) / N) * N;
		uint grid_y = (TileY(tile) / N) * N;
		this->area.Add(TileXY(grid_x, grid_y));
		this->area.Add(TileXY(grid_x + N - 1, grid_y + N - 1));

		/* Allocate new storage. */
		T *new_data = CallocT<T>(this->area.w / N * this->area.h / N);

		if (old_w > 0) {
			/* Copy old data if present. */
			uint offs_x = old_left - TileX(this->area.tile) / N;
			uint offs_y = old_top  - TileY(this->area.tile) / N;

			for (uint row = 0; row < old_h; row++) {
				MemCpyT(&new_data[(row + offs_y) * this->area.w / N + offs_x], &this->data[row * old_w], old_w);
			}
		}

		free(this->data);
		this->data = new_data;
	}
Beispiel #3
0
	/**
	 * Add text to the output buffer.
	 * @param text   Text to store.
	 * @param length Length of the text in bytes.
	 * @return Number of bytes actually stored.
	 */
	int Add(const char *text, int length)
	{
		int store_size = min(length, OUTPUT_BLOCK_SIZE - this->size);
		assert(store_size >= 0);
		assert(store_size <= OUTPUT_BLOCK_SIZE);
		MemCpyT(this->data + this->size, text, store_size);
		this->size += store_size;
		return store_size;
	}
Beispiel #4
0
/**
 * Display an error message in a window.
 * @param summary_msg  General error message showed in first line. Must be valid.
 * @param detailed_msg Detailed error message showed in second line. Can be INVALID_STRING_ID.
 * @param duration     The amount of time to show this error message.
 * @param x            World X position (TileVirtX) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
 * @param y            World Y position (TileVirtY) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
 * @param textref_stack_size Number of uint32 values to put on the #TextRefStack for the error message; 0 if the #TextRefStack shall not be used.
 * @param textref_stack Values to put on the #TextRefStack.
 */
ErrorMessageData::ErrorMessageData(StringID summary_msg, StringID detailed_msg, uint duration, int x, int y, uint textref_stack_size, const uint32 *textref_stack) :
	duration(duration),
	textref_stack_size(textref_stack_size),
	summary_msg(summary_msg),
	detailed_msg(detailed_msg),
	face(INVALID_COMPANY)
{
	this->position.x = x;
	this->position.y = y;

	memset(this->decode_params, 0, sizeof(this->decode_params));
	memset(this->strings, 0, sizeof(this->strings));

	if (textref_stack_size > 0) MemCpyT(this->textref_stack, textref_stack, textref_stack_size);

	assert(summary_msg != INVALID_STRING_ID);
}
Beispiel #5
0
	/**
	 * Display an error message in a window.
	 * @param summary_msg  General error message showed in first line. Must be valid.
	 * @param detailed_msg Detailed error message showed in second line. Can be INVALID_STRING_ID.
	 * @param duration     The amount of time to show this error message.
	 * @param x            World X position (TileVirtX) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
	 * @param y            World Y position (TileVirtY) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
	 * @param textref_stack_size Number of uint32 values to put on the #TextRefStack for the error message; 0 if the #TextRefStack shall not be used.
	 * @param textref_stack Values to put on the #TextRefStack.
	 */
	ErrorMessageData(StringID summary_msg, StringID detailed_msg, uint duration, int x, int y, uint textref_stack_size, const uint32 *textref_stack) :
		duration(duration),
		textref_stack_size(textref_stack_size),
		summary_msg(summary_msg),
		detailed_msg(detailed_msg)
	{
		this->position.x = x;
		this->position.y = y;
		if (textref_stack_size > 0) StartTextRefStackUsage(textref_stack_size, textref_stack);
		CopyOutDParam(this->decode_params, this->strings, detailed_msg == INVALID_STRING_ID ? summary_msg : detailed_msg, lengthof(this->decode_params));
		if (textref_stack_size > 0) {
			StopTextRefStackUsage();
			MemCpyT(this->textref_stack, textref_stack, textref_stack_size);
		}

		CompanyID company = (CompanyID)GetDParamX(this->decode_params, 2);
		this->face = (this->detailed_msg == STR_ERROR_OWNED_BY && company < MAX_COMPANIES) ? company : INVALID_COMPANY;

		assert(summary_msg != INVALID_STRING_ID);
	}
Beispiel #6
0
/**
 * Check the validity of some of the caches.
 * Especially in the sense of desyncs between
 * the cached value and what the value would
 * be when calculated from the 'base' data.
 */
static void CheckCaches()
{
	/* Return here so it is easy to add checks that are run
	 * always to aid testing of caches. */
	if (_debug_desync_level <= 1) return;

	/* Check the town caches. */
	SmallVector<TownCache, 4> old_town_caches;
	Town *t;
	FOR_ALL_TOWNS(t) {
		MemCpyT(old_town_caches.Append(), &t->cache);
	}

	extern void RebuildTownCaches();
	RebuildTownCaches();
	RebuildSubsidisedSourceAndDestinationCache();

	uint i = 0;
	FOR_ALL_TOWNS(t) {
		if (MemCmpT(old_town_caches.Get(i), &t->cache) != 0) {
			DEBUG(desync, 2, "town cache mismatch: town %i", (int)t->index);
		}
		i++;
	}

	/* Check company infrastructure cache. */
	SmallVector<CompanyInfrastructure, 4> old_infrastructure;
	Company *c;
	FOR_ALL_COMPANIES(c) MemCpyT(old_infrastructure.Append(), &c->infrastructure);

	extern void AfterLoadCompanyStats();
	AfterLoadCompanyStats();

	i = 0;
	FOR_ALL_COMPANIES(c) {
		if (MemCmpT(old_infrastructure.Get(i), &c->infrastructure) != 0) {
			DEBUG(desync, 2, "infrastructure cache mismatch: company %i", (int)c->index);
		}
		i++;
	}

	/* Strict checking of the road stop cache entries */
	const RoadStop *rs;
	FOR_ALL_ROADSTOPS(rs) {
		if (IsStandardRoadStopTile(rs->xy)) continue;

		assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW));
		rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs);
		rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs);
	}

	Vehicle *v;
	FOR_ALL_VEHICLES(v) {
		extern void FillNewGRFVehicleCache(const Vehicle *v);
		if (v != v->First() || v->vehstatus & VS_CRASHED || !v->IsPrimaryVehicle()) continue;

		uint length = 0;
		for (const Vehicle *u = v; u != NULL; u = u->Next()) length++;

		NewGRFCache        *grf_cache = CallocT<NewGRFCache>(length);
		VehicleCache       *veh_cache = CallocT<VehicleCache>(length);
		GroundVehicleCache *gro_cache = CallocT<GroundVehicleCache>(length);
		TrainCache         *tra_cache = CallocT<TrainCache>(length);

		length = 0;
		for (const Vehicle *u = v; u != NULL; u = u->Next()) {
			FillNewGRFVehicleCache(u);
			grf_cache[length] = u->grf_cache;
			veh_cache[length] = u->vcache;
			switch (u->type) {
				case VEH_TRAIN:
					gro_cache[length] = Train::From(u)->gcache;
					tra_cache[length] = Train::From(u)->tcache;
					break;
				case VEH_ROAD:
					gro_cache[length] = RoadVehicle::From(u)->gcache;
					break;
				default:
					break;
			}
			length++;
		}

		switch (v->type) {
			case VEH_TRAIN:    Train::From(v)->ConsistChanged(CCF_TRACK); break;
			case VEH_ROAD:     RoadVehUpdateCache(RoadVehicle::From(v)); break;
			case VEH_AIRCRAFT: UpdateAircraftCache(Aircraft::From(v));   break;
			case VEH_SHIP:     Ship::From(v)->UpdateCache();             break;
			default: break;
		}

		length = 0;
		for (const Vehicle *u = v; u != NULL; u = u->Next()) {
			FillNewGRFVehicleCache(u);
			if (memcmp(&grf_cache[length], &u->grf_cache, sizeof(NewGRFCache)) != 0) {
				DEBUG(desync, 2, "newgrf cache mismatch: type %i, vehicle %i, company %i, unit number %i, wagon %i", (int)v->type, v->index, (int)v->owner, v->unitnumber, length);
			}
			if (memcmp(&veh_cache[length], &u->vcache, sizeof(VehicleCache)) != 0) {
				DEBUG(desync, 2, "vehicle cache mismatch: type %i, vehicle %i, company %i, unit number %i, wagon %i", (int)v->type, v->index, (int)v->owner, v->unitnumber, length);
			}
			switch (u->type) {
				case VEH_TRAIN:
					if (memcmp(&gro_cache[length], &Train::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
						DEBUG(desync, 2, "train ground vehicle cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
					}
					if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) {
						DEBUG(desync, 2, "train cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
					}
					break;
				case VEH_ROAD:
					if (memcmp(&gro_cache[length], &RoadVehicle::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
						DEBUG(desync, 2, "road vehicle ground vehicle cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
					}
					break;
				default:
					break;
			}
			length++;
		}

		free(grf_cache);
		free(veh_cache);
		free(gro_cache);
		free(tra_cache);
	}

	/* Check whether the caches are still valid */
	FOR_ALL_VEHICLES(v) {
		byte buff[sizeof(VehicleCargoList)];
		memcpy(buff, &v->cargo, sizeof(VehicleCargoList));
		v->cargo.InvalidateCache();
		assert(memcmp(&v->cargo, buff, sizeof(VehicleCargoList)) == 0);
	}

	Station *st;
	FOR_ALL_STATIONS(st) {
		for (CargoID c = 0; c < NUM_CARGO; c++) {
			byte buff[sizeof(StationCargoList)];
			memcpy(buff, &st->goods[c].cargo, sizeof(StationCargoList));
			st->goods[c].cargo.InvalidateCache();
			assert(memcmp(&st->goods[c].cargo, buff, sizeof(StationCargoList)) == 0);
		}
	}
}