sprite.c
changeset 2491 dfe9542f783e
parent 2488 cbe3d6b60c27
child 2515 480538b48b0f
--- a/sprite.c	Tue Oct 04 20:58:10 2005 +0000
+++ b/sprite.c	Tue Oct 04 21:42:00 2005 +0000
@@ -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 @@
 
 	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);
+}