(svn r3014) -NewGRF, Codechange: Make all sprite group references be pointers instead of copying the data around.
authorpeter1138
Tue, 04 Oct 2005 19:52:26 +0000
changeset 2488 cbe3d6b60c27
parent 2487 be510f15d36f
child 2489 88827d8ae517
(svn r3014) -NewGRF, Codechange: Make all sprite group references be pointers instead of copying the data around.
engine.c
newgrf.c
sprite.c
sprite.h
station.h
station_cmd.c
--- a/engine.c	Tue Oct 04 17:34:50 2005 +0000
+++ b/engine.c	Tue Oct 04 19:52:26 2005 +0000
@@ -240,7 +240,7 @@
 typedef struct WagonOverride {
 	byte *train_id;
 	int trains;
-	SpriteGroup group;
+	SpriteGroup *group;
 } WagonOverride;
 
 typedef struct WagonOverrides {
@@ -265,7 +265,7 @@
 	/* FIXME: If we are replacing an override, release original SpriteGroup
 	 * to prevent leaks. But first we need to refcount the SpriteGroup.
 	 * --pasky */
-	wo->group = *group;
+	wo->group = group;
 	wo->trains = trains;
 	wo->train_id = malloc(trains);
 	memcpy(wo->train_id, train_id, trains);
@@ -287,7 +287,7 @@
 
 		for (j = 0; j < wo->trains; j++) {
 			if (wo->train_id[j] == overriding_engine)
-				return &wo->group;
+				return wo->group;
 		}
 	}
 	return NULL;
@@ -298,14 +298,14 @@
 // (It isn't and shouldn't be like this in the GRF files since new cargo types
 // may appear in future - however it's more convenient to store it like this in
 // memory. --pasky)
-static SpriteGroup _engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID];
+static SpriteGroup *engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID];
 
 void SetCustomEngineSprites(EngineID engine, byte cargo, SpriteGroup *group)
 {
 	/* FIXME: If we are replacing an override, release original SpriteGroup
 	 * to prevent leaks. But first we need to refcount the SpriteGroup.
 	 * --pasky */
-	_engine_custom_sprites[engine][cargo] = *group;
+	engine_custom_sprites[engine][cargo] = group;
 }
 
 typedef SpriteGroup *(*resolve_callback)(const SpriteGroup *spritegroup,
@@ -314,6 +314,9 @@
 static const SpriteGroup* ResolveVehicleSpriteGroup(const SpriteGroup *spritegroup,
 	const Vehicle *veh, uint16 callback_info, resolve_callback resolve_func)
 {
+	if (spritegroup == NULL)
+		return NULL;
+
 	//debug("spgt %d", spritegroup->type);
 	switch (spritegroup->type) {
 		case SGT_REAL:
@@ -341,7 +344,7 @@
 					 * That means we should get the first target
 					 * (NOT the default one). */
 					if (dsg->num_ranges > 0) {
-						target = &dsg->ranges[0].group;
+						target = dsg->ranges[0].group;
 					} else {
 						target = dsg->default_group;
 					}
@@ -476,7 +479,7 @@
 				/* Purchase list of something. Show the first one. */
 				assert(rsg->num_groups > 0);
 				//debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type);
-				return resolve_func(&rsg->groups[0], NULL, callback_info, resolve_func);
+				return resolve_func(rsg->groups[0], NULL, callback_info, resolve_func);
 			}
 
 			if (rsg->var_scope == VSG_SCOPE_PARENT) {
@@ -504,7 +507,7 @@
 		assert(cargo != GC_INVALID);
 	}
 
-	group = &_engine_custom_sprites[engine][cargo];
+	group = engine_custom_sprites[engine][cargo];
 
 	if (v != NULL && v->type == VEH_Train) {
 		const SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine);
@@ -539,12 +542,15 @@
 	group = GetVehicleSpriteGroup(engine, v);
 	group = ResolveVehicleSpriteGroup(group, v, 0, (resolve_callback) ResolveVehicleSpriteGroup);
 
-	if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && cargo != GC_DEFAULT) {
+	if (group == NULL && cargo != GC_DEFAULT) {
 		// This group is empty but perhaps there'll be a default one.
-		group = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][GC_DEFAULT], v, 0,
+		group = ResolveVehicleSpriteGroup(engine_custom_sprites[engine][GC_DEFAULT], v, 0,
 		                                (resolve_callback) ResolveVehicleSpriteGroup);
 	}
 
+	if (group == NULL)
+		return 0;
+
 	assert(group->type == SGT_REAL);
 	rsg = &group->g.real;
 
@@ -605,7 +611,7 @@
 	if (v != NULL)
 		cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
 
-	group = &_engine_custom_sprites[engine][cargo];
+	group = engine_custom_sprites[engine][cargo];
 
 	if (v != NULL && v->type == VEH_Train) {
 		const SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine);
@@ -615,13 +621,13 @@
 
 	group = ResolveVehicleSpriteGroup(group, v, callback_info, (resolve_callback) ResolveVehicleSpriteGroup);
 
-	if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && cargo != GC_DEFAULT) {
+	if (group == NULL && cargo != GC_DEFAULT) {
 		// This group is empty but perhaps there'll be a default one.
-		group = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][GC_DEFAULT], v, callback_info,
+		group = ResolveVehicleSpriteGroup(engine_custom_sprites[engine][GC_DEFAULT], v, callback_info,
 		                                (resolve_callback) ResolveVehicleSpriteGroup);
 	}
 
-	if (group->type != SGT_CALLBACK)
+	if (group == NULL || group->type != SGT_CALLBACK)
 		return CALLBACK_FAILED;
 
 	return group->g.callback.result;
@@ -637,6 +643,9 @@
 static const SpriteGroup *TriggerVehicleSpriteGroup(const SpriteGroup *spritegroup,
 	Vehicle *veh, uint16 callback_info, resolve_callback resolve_func)
 {
+	if (spritegroup == NULL)
+		return NULL;
+
 	if (spritegroup->type == SGT_RANDOMIZED) {
 		_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(
 			&spritegroup->g.random,
@@ -659,12 +668,15 @@
 	group = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh, 0,
 	                                  (resolve_callback) TriggerVehicleSpriteGroup);
 
-	if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && veh->cargo_type != GC_DEFAULT) {
+	if (group == NULL && veh->cargo_type != GC_DEFAULT) {
 		// This group turned out to be empty but perhaps there'll be a default one.
-		group = TriggerVehicleSpriteGroup(&_engine_custom_sprites[veh->engine_type][GC_DEFAULT], veh, 0,
+		group = TriggerVehicleSpriteGroup(engine_custom_sprites[veh->engine_type][GC_DEFAULT], veh, 0,
 		                                  (resolve_callback) TriggerVehicleSpriteGroup);
 	}
 
+	if (group == NULL)
+		return;
+
 	assert(group->type == SGT_REAL);
 	rsg = &group->g.real;
 
--- a/newgrf.c	Tue Oct 04 17:34:50 2005 +0000
+++ b/newgrf.c	Tue Oct 04 19:52:26 2005 +0000
@@ -1210,11 +1210,11 @@
  * @param value The value that was used to represent this callback result
  * @return A spritegroup representing that callback result
  */
-SpriteGroup NewCallBackResult(uint16 value)
+SpriteGroup *NewCallBackResultSpriteGroup(uint16 value)
 {
-	SpriteGroup group;
+	SpriteGroup *group = calloc(1, sizeof(*group));
 
-	group.type = SGT_CALLBACK;
+	group->type = SGT_CALLBACK;
 
 	// Old style callback results have the highest byte 0xFF so signify it is a callback result
 	// New style ones only have the highest bit set (allows 15-bit results, instead of just 8)
@@ -1223,7 +1223,7 @@
 	else
 		value &= ~0x8000;
 
-	group.g.callback.result = value;
+	group->g.callback.result = value;
 
 	return group;
 }
@@ -1308,8 +1308,11 @@
 	numloading = buf[4];
 
 	if (setid >= _cur_grffile->spritegroups_count) {
-		_cur_grffile->spritegroups_count = setid + 1;
-		_cur_grffile->spritegroups = realloc(_cur_grffile->spritegroups, _cur_grffile->spritegroups_count * sizeof(*_cur_grffile->spritegroups));
+		// Allocate memory for new sprite group references.
+		_cur_grffile->spritegroups = realloc(_cur_grffile->spritegroups, (setid + 1) * sizeof(*_cur_grffile->spritegroups));
+		// Initialise new space to NULL
+		for (; _cur_grffile->spritegroups_count < (setid + 1); _cur_grffile->spritegroups_count++)
+			_cur_grffile->spritegroups[_cur_grffile->spritegroups_count] = NULL;
 	}
 
 	if (numloaded == 0x81 || numloaded == 0x82) {
@@ -1354,8 +1357,8 @@
 		dg->ranges = calloc(dg->num_ranges, sizeof(*dg->ranges));
 		for (i = 0; i < dg->num_ranges; i++) {
 			groupid = grf_load_word(&buf);
-			if (groupid & 0x8000) {
-				dg->ranges[i].group = NewCallBackResult(groupid);
+			if (HASBIT(groupid, 15)) {
+				dg->ranges[i].group = NewCallBackResultSpriteGroup(groupid);
 			} else if (groupid >= _cur_grffile->spritegroups_count) {
 				/* This doesn't exist for us. */
 				grf_load_word(&buf); // skip range
@@ -1364,7 +1367,7 @@
 			} else {
 			/* XXX: If multiple surreal sets attach a surreal
 			 * set this way, we are in trouble. */
-				dg->ranges[i].group = *_cur_grffile->spritegroups[groupid];
+				dg->ranges[i].group = _cur_grffile->spritegroups[groupid];
 			}
 
 			dg->ranges[i].low = grf_load_byte(&buf);
@@ -1372,17 +1375,15 @@
 		}
 
 		groupid = grf_load_word(&buf);
-		if (groupid & 0x8000) {
-			dg->default_group = malloc(sizeof(*dg->default_group));
-			*dg->default_group = NewCallBackResult(groupid);
+		if (HASBIT(groupid, 15)) {
+			dg->default_group = NewCallBackResultSpriteGroup(groupid);
 		} else if (groupid >= _cur_grffile->spritegroups_count) {
 			/* This spritegroup stinks. */
 			free(dg->ranges), dg->ranges = NULL;
 			grfmsg(GMS_WARN, "NewSpriteGroup(%02x:0x%x): Default groupid %04x is cargo callback or unknown, ignoring spritegroup.", setid, numloaded, groupid);
 			return;
 		} else {
-			dg->default_group = malloc(sizeof(*dg->default_group));
-			memcpy(dg->default_group, _cur_grffile->spritegroups[groupid], sizeof(*dg->default_group));
+			dg->default_group = _cur_grffile->spritegroups[groupid];
 		}
 
 		_cur_grffile->spritegroups[setid] = group;
@@ -1428,7 +1429,7 @@
 			}
 			/* XXX: If multiple surreal sets attach a surreal
 			 * set this way, we are in trouble. */
-			rg->groups[i] = *_cur_grffile->spritegroups[groupid];
+			rg->groups[i] = _cur_grffile->spritegroups[groupid];
 		}
 
 		_cur_grffile->spritegroups[setid] = group;
@@ -1556,7 +1557,7 @@
 					continue;
 				}
 
-				stat->spritegroup[1] = *_cur_grffile->spritegroups[groupid];
+				stat->spritegroup[1] = _cur_grffile->spritegroups[groupid];
 			}
 		}
 
@@ -1574,7 +1575,7 @@
 				uint8 stid = buf[3 + i];
 				StationSpec *stat = &_cur_grffile->stations[stid];
 
-				stat->spritegroup[0] = *_cur_grffile->spritegroups[groupid];
+				stat->spritegroup[0] = _cur_grffile->spritegroups[groupid];
 				stat->grfid = _cur_grffile->grfid;
 				SetCustomStation(stid, stat);
 				stat->sclass = STAT_CLASS_NONE;
--- a/sprite.c	Tue Oct 04 17:34:50 2005 +0000
+++ b/sprite.c	Tue Oct 04 19:52:26 2005 +0000
@@ -31,7 +31,7 @@
 		DeterministicSpriteGroupRange *range = &dsg->ranges[i];
 
 		if (range->low <= value && value <= range->high)
-			return &range->group;
+			return range->group;
 	}
 
 	return dsg->default_group;
@@ -72,7 +72,7 @@
 	mask = (rsg->num_groups - 1) << rsg->lowest_randbit;
 	index = (random_bits & mask) >> rsg->lowest_randbit;
 	assert(index < rsg->num_groups);
-	return &rsg->groups[index];
+	return rsg->groups[index];
 }
 
 byte RandomizedSpriteGroupTriggeredBits(const RandomizedSpriteGroup *rsg,
--- a/sprite.h	Tue Oct 04 17:34:50 2005 +0000
+++ b/sprite.h	Tue Oct 04 19:52:26 2005 +0000
@@ -107,7 +107,7 @@
 	byte num_groups; // must be power of 2
 
 	// Take the group with appropriate index:
-	SpriteGroup *groups;
+	SpriteGroup **groups;
 } RandomizedSpriteGroup;
 
 typedef struct CallbackResultSpriteGroup {
@@ -133,7 +133,7 @@
 };
 
 struct DeterministicSpriteGroupRange {
-	SpriteGroup group;
+	SpriteGroup *group;
 	byte low;
 	byte high;
 };
--- a/station.h	Tue Oct 04 17:34:50 2005 +0000
+++ b/station.h	Tue Oct 04 19:52:26 2005 +0000
@@ -253,7 +253,7 @@
 
 	/* Sprite offsets for renderdata->seq->image. spritegroup[0] is default
 	 * whilst spritegroup[1] is "GC_PURCHASE". */
-	SpriteGroup spritegroup[2];
+	SpriteGroup *spritegroup[2];
 } StationSpec;
 
 /* Here, @stid is local per-GRFFile station index. If spec->localidx is not yet
--- a/station_cmd.c	Tue Oct 04 17:34:50 2005 +0000
+++ b/station_cmd.c	Tue Oct 04 19:52:26 2005 +0000
@@ -1286,7 +1286,7 @@
 					 * That means we should get the first target
 					 * (NOT the default one). */
 					if (dsg->num_ranges > 0) {
-						target = &dsg->ranges[0].group;
+						target = dsg->ranges[0].group;
 					} else {
 						target = dsg->default_group;
 					}
@@ -1346,7 +1346,7 @@
 
 uint32 GetCustomStationRelocation(const StationSpec *spec, const Station *st, byte ctype)
 {
-	const RealSpriteGroup *rsg = ResolveStationSpriteGroup(&spec->spritegroup[ctype], st);
+	const RealSpriteGroup *rsg = ResolveStationSpriteGroup(spec->spritegroup[ctype], st);
 
 	if (rsg->sprites_per_set != 0) {
 		if (rsg->loading_count != 0) return rsg->loading[0];