169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $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);
 | 
						|
}
 |