Ejemplo n.º 1
0
/**
 * Get the data section size of a GRF.
 * @param f GRF.
 * @return Size of the data section or SIZE_MAX if the file has no separate data section.
 */
size_t GRFGetSizeOfDataSection(FILE *f)
{
	extern const byte _grf_cont_v2_sig[];
	static const uint header_len = 14;

	byte data[header_len];
	if (fread(data, 1, header_len, f) == header_len) {
		if (data[0] == 0 && data[1] == 0 && MemCmpT(data + 2, _grf_cont_v2_sig, 8) == 0) {
			/* Valid container version 2, get data section size. */
			size_t offset = (data[13] << 24) | (data[12] << 16) | (data[11] << 8) | data[10];
			return header_len + offset;
		}
	}

	return SIZE_MAX;
}
Ejemplo n.º 2
0
/**
 * Read the header of a standard MIDI file.
 * The function will consume 14 bytes from the current file pointer position.
 * @param[in] file open file to read from (should be in binary mode)
 * @param[out] header filled with data read
 * @return true if a header in correct format could be read from the file
 */
bool MidiFile::ReadSMFHeader(FILE *file, SMFHeader &header)
{
	/* Try to read header, fixed size */
	byte buffer[14];
	if (fread(buffer, sizeof(buffer), 1, file) != 1) {
		return false;
	}

	/* Check magic, 'MThd' followed by 4 byte length indicator (always = 6 in SMF) */
	const byte magic[] = { 'M', 'T', 'h', 'd', 0x00, 0x00, 0x00, 0x06 };
	if (MemCmpT(buffer, magic, sizeof(magic)) != 0) {
		return false;
	}

	/* Read the parameters of the file */
	header.format = (buffer[8] << 8) | buffer[9];
	header.tracks = (buffer[10] << 8) | buffer[11];
	header.tickdiv = (buffer[12] << 8) | buffer[13];
	return true;
}
Ejemplo n.º 3
0
/**
 * Get the data section size of a GRF.
 * @param f GRF.
 * @return Size of the data section or SIZE_MAX if the file has no separate data section.
 */
size_t GRFGetSizeOfDataSection(FILE *f)
{
	extern const byte _grf_cont_v2_sig[];
	static const uint header_len = 14;

	byte data[header_len];
	if (fread(data, 1, header_len, f) == header_len) {
		if (data[0] == 0 && data[1] == 0 && MemCmpT(data + 2, _grf_cont_v2_sig, 8) == 0) {
			/* Valid container version 2, get data section size. */
			size_t offset = ((size_t)data[13] << 24) | ((size_t)data[12] << 16) | ((size_t)data[11] << 8) | (size_t)data[10];
			if (offset >= 1 * 1024 * 1024 * 1024) {
				DEBUG(grf, 0, "Unexpectedly large offset for NewGRF");
				/* Having more than 1 GiB of data is very implausible. Mostly because then
				 * all pools in OpenTTD are flooded already. Or it's just Action C all over.
				 * In any case, the offsets to graphics will likely not work either. */
				return SIZE_MAX;
			}
			return header_len + offset;
		}
	}

	return SIZE_MAX;
}
Ejemplo n.º 4
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);
		}
	}
}