Files @ r3303:1bae0f5399a4
Branch filter:

Location: cpp/openttd-patchpack/source/sprite.c

bjarni
(svn r4060) -Codechange: [OSX] made the release target (in os/macosx/Makefile) easier to use since it gives the release disk image the right name automatically
it now uses REV instead of RELEASE, which means RELEASE is not needed to be set manaully anymore
it also automatically adds "-jaguar" when making a build aimed at OSX 10.2 (codenamed jaguar)
/* $Id$ */

#include "stdafx.h"
#include "openttd.h"
#include "sprite.h"
#include "variables.h"
#include "debug.h"


SpriteGroup *EvalDeterministicSpriteGroup(const DeterministicSpriteGroup *dsg, int value)
{
	int i;

	value >>= dsg->shift_num; // This should bring us to the byte range.
	value &= dsg->and_mask;

	if (dsg->operation != DSG_OP_NONE)
		value += (signed char) dsg->add_val;

	switch (dsg->operation) {
		case DSG_OP_DIV:
			value /= (signed char) dsg->divmod_val;
			break;
		case DSG_OP_MOD:
			value %= (signed char) dsg->divmod_val;
			break;
		case DSG_OP_NONE:
			break;
	}

	for (i = 0; i < dsg->num_ranges; i++) {
		DeterministicSpriteGroupRange *range = &dsg->ranges[i];

		if (range->low <= value && value <= range->high)
			return range->group;
	}

	return dsg->default_group;
}

int GetDeterministicSpriteValue(byte var)
{
	switch (var) {
		case 0x00:
			return _date;
		case 0x01:
			return _cur_year;
		case 0x02:
			return _cur_month;
		case 0x03:
			return _opt.landscape;
		case 0x09:
			return _date_fract;
		case 0x0A:
			return _tick_counter;
		case 0x0C:
			/* If we got here, it means there was no callback or
			 * callbacks aren't supported on our callpath. */
			return 0;
		default:
			return -1;
	}
}

SpriteGroup *EvalRandomizedSpriteGroup(const RandomizedSpriteGroup *rsg, byte random_bits)
{
	byte mask;
	byte index;

	/* Noone likes mangling with bits, but you don't get around it here.
	 * Sorry. --pasky */
	// rsg->num_groups is always power of 2
	mask = (rsg->num_groups - 1) << rsg->lowest_randbit;
	index = (random_bits & mask) >> rsg->lowest_randbit;
	assert(index < rsg->num_groups);
	return rsg->groups[index];
}

byte RandomizedSpriteGroupTriggeredBits(const RandomizedSpriteGroup *rsg,
	byte triggers, byte *waiting_triggers)
{
	byte match = rsg->triggers & (*waiting_triggers | triggers);
	bool res;

	if (rsg->cmp_mode == RSG_CMP_ANY) {
		res = (match != 0);
	} else { /* RSG_CMP_ALL */
		res = (match == rsg->triggers);
	}

	if (!res) {
		*waiting_triggers |= triggers;
		return 0;
	}

	*waiting_triggers &= ~match;

	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++) {
				if (rsg->loading[i] != NULL) UnloadSpriteGroup(&rsg->loading[i]);
			}
			for (i = 0; i < rsg->loaded_count; i++) {
				if (rsg->loaded[i] != NULL) 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++) {
				if (dsg->ranges[i].group != NULL) UnloadSpriteGroup(&dsg->ranges[i].group);
			}
			if (dsg->default_group != NULL) 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++) {
				if (group->g.random.groups[i] != NULL) 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);
}