Changeset - r2491:13bebed6ca4e
[Not reviewed]
master
0 5 0
peter1138 - 19 years ago 2005-10-04 21:42:00
peter1138@openttd.org
(svn r3017) -NewGRF: Implement sprite group unreferencing and unloading.
5 files changed with 157 insertions and 3 deletions:
0 comments (0 inline, 0 general)
engine.c
Show inline comments
 
@@ -294,6 +294,28 @@ static const SpriteGroup *GetWagonOverri
 
	return NULL;
 
}
 

	
 
/**
 
 * Unload all wagon override sprite groups.
 
 */
 
void UnloadWagonOverrides(void)
 
{
 
	WagonOverrides *wos;
 
	WagonOverride *wo;
 
	EngineID engine;
 
	int i;
 

	
 
	for (engine = 0; engine < TOTAL_NUM_ENGINES; engine++) {
 
		wos = &_engine_wagon_overrides[engine];
 
		for (i = 0; i < wos->overrides_count; i++) {
 
			wo = &wos->overrides[i];
 
			UnloadSpriteGroup(&wo->group);
 
			free(wo->train_id);
 
		}
 
		free(wos->overrides);
 
		wos->overrides_count = 0;
 
		wos->overrides = NULL;
 
	}
 
}
 

	
 
// 0 - 28 are cargos, 29 is default, 30 is the advert (purchase list)
 
// (It isn't and shouldn't be like this in the GRF files since new cargo types
 
@@ -303,13 +325,32 @@ static SpriteGroup *engine_custom_sprite
 

	
 
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 */
 
	if (engine_custom_sprites[engine][cargo] != NULL) {
 
		DEBUG(grf, 6)("SetCustomEngineSprites: engine `%d' cargo `%d' already has group -- removing.", engine, cargo);
 
		UnloadSpriteGroup(&engine_custom_sprites[engine][cargo]);
 
	}
 
	engine_custom_sprites[engine][cargo] = group;
 
	group->ref_count++;
 
}
 

	
 
/**
 
 * Unload all engine sprite groups.
 
 */
 
void UnloadCustomEngineSprites(void)
 
{
 
	EngineID engine;
 
	CargoID cargo;
 

	
 
	for (engine = 0; engine < TOTAL_NUM_ENGINES; engine++) {
 
		for (cargo = 0; cargo < NUM_GLOBAL_CID; cargo++) {
 
			if (engine_custom_sprites[engine][cargo] != NULL) {
 
				DEBUG(grf, 6)("UnloadCustomEngineSprites: Unloading group for engine `%d' cargo `%d'.", engine, cargo);
 
				UnloadSpriteGroup(&engine_custom_sprites[engine][cargo]);
 
			}
 
		}
 
	}
 
}
 

	
 
typedef SpriteGroup *(*resolve_callback)(const SpriteGroup *spritegroup,
 
	const Vehicle *veh, uint16 callback_info, void *resolve_func); /* XXX data pointer used as function pointer */
 

	
engine.h
Show inline comments
 
@@ -276,4 +276,7 @@ static inline const RoadVehicleInfo* Roa
 
	return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
 
}
 

	
 
void UnloadWagonOverrides(void);
 
void UnloadCustomEngineSprites(void);
 

	
 
#endif /* ENGINE_H */
newgrf.c
Show inline comments
 
@@ -1404,6 +1404,8 @@ static void NewSpriteGroup(byte *buf, in
 
		}
 
		dg->default_group->ref_count++;
 

	
 
		if (_cur_grffile->spritegroups[setid] != NULL)
 
			UnloadSpriteGroup(&_cur_grffile->spritegroups[setid]);
 
		_cur_grffile->spritegroups[setid] = group;
 
		group->ref_count++;
 
		return;
 
@@ -1454,6 +1456,8 @@ static void NewSpriteGroup(byte *buf, in
 
			}
 
		}
 

	
 
		if (_cur_grffile->spritegroups[setid] != NULL)
 
			UnloadSpriteGroup(&_cur_grffile->spritegroups[setid]);
 
		_cur_grffile->spritegroups[setid] = group;
 
		group->ref_count++;
 
		return;
 
@@ -1519,6 +1523,8 @@ static void NewSpriteGroup(byte *buf, in
 
		DEBUG(grf, 8) ("NewSpriteGroup: + rg->loading[%i] = %u (subset %u)", i, rg->loading[i]->g.result.result, spriteset_id);
 
	}
 

	
 
	if (_cur_grffile->spritegroups[setid] != NULL)
 
		UnloadSpriteGroup(&_cur_grffile->spritegroups[setid]);
 
	_cur_grffile->spritegroups[setid] = group;
 
	group->ref_count++;
 
}
 
@@ -2296,6 +2302,29 @@ static void InitializeGRFSpecial(void)
 
}
 

	
 
/**
 
 * Unload unused sprite groups from the specified GRF file.
 
 * Called after loading each GRF file.
 
 * @param file GRF file
 
 */
 
static void ReleaseSpriteGroups(GRFFile *file)
 
{
 
	int i;
 

	
 
	// Bail out if no spritegroups were defined.
 
	if (file->spritegroups == NULL)
 
		return;
 

	
 
	DEBUG(grf, 6)("ReleaseSpriteGroups: Releasing for `%s'.", file->filename);
 
	for (i = 0; i < file->spritegroups_count; i++) {
 
		if (file->spritegroups[i] != NULL)
 
			UnloadSpriteGroup(&file->spritegroups[i]);
 
	}
 
	free(file->spritegroups);
 
	file->spritegroups = NULL;
 
	file->spritegroups_count = 0;
 
}
 

	
 
/**
 
 * Reset all NewGRF loaded data
 
 * TODO
 
 */
 
@@ -2321,6 +2350,10 @@ static void ResetNewGRFData(void)
 
		}
 
	}
 
	memcpy(&_bridge, &orig_bridge, sizeof(_bridge));
 

	
 
	// Unload sprite group data
 
	UnloadWagonOverrides();
 
	UnloadCustomEngineSprites();
 
}
 

	
 
static void InitNewGRFFile(const char* filename, int sprite_offset)
 
@@ -2493,6 +2526,11 @@ static void LoadNewGRFFile(const char* f
 

	
 
		if (_skip_sprites > 0) _skip_sprites--;
 
	}
 

	
 
	// Release our sprite group references.
 
	// Any groups that are referenced elsewhere will be cleaned up later.
 
	// This removes groups that aren't used. (Perhaps skipped?)
 
	ReleaseSpriteGroups(_cur_grffile);
 
}
 

	
 

	
sprite.c
Show inline comments
 
@@ -4,6 +4,7 @@
 
#include "openttd.h"
 
#include "sprite.h"
 
#include "variables.h"
 
#include "debug.h"
 

	
 

	
 
SpriteGroup *EvalDeterministicSpriteGroup(const DeterministicSpriteGroup *dsg, int value)
 
@@ -96,3 +97,72 @@ byte RandomizedSpriteGroupTriggeredBits(
 

	
 
	return (rsg->num_groups - 1) << rsg->lowest_randbit;
 
}
 

	
 
/**
 
 * Traverse a sprite group and release its and its child's memory.
 
 * A group is only released if its reference count is zero.
 
 * We pass a pointer to a pointer so that the original reference can be set to NULL.
 
 * @param group_ptr Pointer to sprite group reference.
 
 */
 
void UnloadSpriteGroup(SpriteGroup **group_ptr)
 
{
 
	SpriteGroup *group;
 
	int i;
 

	
 
	assert(group_ptr != NULL);
 
	assert(*group_ptr != NULL);
 

	
 
	group = *group_ptr;
 
	*group_ptr = NULL; // Remove this reference.
 

	
 
	group->ref_count--;
 
	if (group->ref_count > 0) {
 
		DEBUG(grf, 6)("UnloadSpriteGroup: Group at `%p' (type %d) has %d reference(s) left.", group, group->type, group->ref_count);
 
		return; // Still some references left, so don't clear up.
 
	}
 

	
 
	DEBUG(grf, 6)("UnloadSpriteGroup: Releasing group at `%p'.", group);
 
	switch (group->type) {
 
		case SGT_REAL:
 
		{
 
			RealSpriteGroup *rsg = &group->g.real;
 
			for (i = 0; i < rsg->loading_count; i++) {
 
				UnloadSpriteGroup(&rsg->loading[i]);
 
			}
 
			for (i = 0; i < rsg->loaded_count; i++) {
 
				UnloadSpriteGroup(&rsg->loaded[i]);
 
			}
 
			free(group);
 
			return;
 
		}
 

	
 
		case SGT_DETERMINISTIC:
 
		{
 
			DeterministicSpriteGroup *dsg = &group->g.determ;
 
			for (i = 0; i < group->g.determ.num_ranges; i++) {
 
				UnloadSpriteGroup(&dsg->ranges[i].group);
 
			}
 
			UnloadSpriteGroup(&dsg->default_group);
 
			free(group->g.determ.ranges);
 
			free(group);
 
			return;
 
		}
 

	
 
		case SGT_RANDOMIZED:
 
		{
 
			for (i = 0; i < group->g.random.num_groups; i++) {
 
				UnloadSpriteGroup(&group->g.random.groups[i]);
 
			}
 
			free(group->g.random.groups);
 
			free(group);
 
			return;
 
		}
 

	
 
		case SGT_CALLBACK:
 
		case SGT_RESULT:
 
			free(group);
 
			return;
 
	}
 

	
 
	DEBUG(grf, 1)("Unable to remove unknown sprite group type `0x%x'.", group->type);
 
}
sprite.h
Show inline comments
 
@@ -162,4 +162,6 @@ SpriteGroup *EvalRandomizedSpriteGroup(c
 
 * (then they are |ed to @waiting_triggers instead). */
 
byte RandomizedSpriteGroupTriggeredBits(const RandomizedSpriteGroup *rsg, byte triggers, byte *waiting_triggers);
 

	
 
void UnloadSpriteGroup(SpriteGroup **group_ptr);
 

	
 
#endif /* SPRITE_H */
0 comments (0 inline, 0 general)