mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 14:27:16 +00:00
(svn r3017) -NewGRF: Implement sprite group unreferencing and unloading.
This commit is contained in:
parent
c655e13e92
commit
abe60acbbb
47
engine.c
47
engine.c
@ -294,6 +294,28 @@ static const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, byte overri
|
||||
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_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 */
|
||||
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 */
|
||||
|
||||
|
3
engine.h
3
engine.h
@ -276,4 +276,7 @@ static inline const RoadVehicleInfo* RoadVehInfo(EngineID e)
|
||||
return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
|
||||
}
|
||||
|
||||
void UnloadWagonOverrides(void);
|
||||
void UnloadCustomEngineSprites(void);
|
||||
|
||||
#endif /* ENGINE_H */
|
||||
|
38
newgrf.c
38
newgrf.c
@ -1404,6 +1404,8 @@ static void NewSpriteGroup(byte *buf, int len)
|
||||
}
|
||||
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, int len)
|
||||
}
|
||||
}
|
||||
|
||||
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, int len)
|
||||
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++;
|
||||
}
|
||||
@ -2295,6 +2301,29 @@ static void InitializeGRFSpecial(void)
|
||||
| (_patches.wagon_speed_limits ? (1 << 0x1D) : 0); /* wagonspeedlimits */
|
||||
}
|
||||
|
||||
/**
|
||||
* 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* filename, uint file_index, uint stage)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
70
sprite.c
70
sprite.c
@ -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(const RandomizedSpriteGroup *rsg,
|
||||
|
||||
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);
|
||||
}
|
||||
|
2
sprite.h
2
sprite.h
@ -162,4 +162,6 @@ SpriteGroup *EvalRandomizedSpriteGroup(const RandomizedSpriteGroup *rsg, byte ra
|
||||
* (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 */
|
||||
|
Loading…
Reference in New Issue
Block a user