(svn r3626) - Merge the SlGlobVarList (global variables) and SaveLoad (offset in struct, variable determined runtime) structs. The only difference between these two is the last element that either holds the address or the offset in the struct. Which one to take is determined by which function is called; SlObject or SlGlobList.
/* $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);
}