tron@2186: /* $Id$ */ tron@2186: darkvater@414: #include "stdafx.h" Darkvater@1891: #include "openttd.h" darkvater@414: #include "sprite.h" tron@2153: #include "variables.h" peter1138@2491: #include "debug.h" darkvater@414: darkvater@414: tron@2242: SpriteGroup *EvalDeterministicSpriteGroup(const DeterministicSpriteGroup *dsg, int value) darkvater@414: { darkvater@414: int i; darkvater@414: darkvater@414: value >>= dsg->shift_num; // This should bring us to the byte range. darkvater@414: value &= dsg->and_mask; darkvater@414: darkvater@414: if (dsg->operation != DSG_OP_NONE) darkvater@414: value += (signed char) dsg->add_val; darkvater@414: darkvater@414: switch (dsg->operation) { darkvater@414: case DSG_OP_DIV: darkvater@414: value /= (signed char) dsg->divmod_val; darkvater@414: break; darkvater@414: case DSG_OP_MOD: darkvater@414: value %= (signed char) dsg->divmod_val; darkvater@414: break; darkvater@414: case DSG_OP_NONE: darkvater@414: break; darkvater@414: } darkvater@414: darkvater@414: for (i = 0; i < dsg->num_ranges; i++) { tron@1477: DeterministicSpriteGroupRange *range = &dsg->ranges[i]; darkvater@414: darkvater@414: if (range->low <= value && value <= range->high) peter1138@2488: return range->group; darkvater@414: } darkvater@414: darkvater@414: return dsg->default_group; darkvater@414: } darkvater@414: darkvater@414: int GetDeterministicSpriteValue(byte var) darkvater@414: { darkvater@414: switch (var) { darkvater@414: case 0x00: darkvater@414: return _date; darkvater@414: case 0x01: darkvater@414: return _cur_year; darkvater@414: case 0x02: darkvater@414: return _cur_month; darkvater@414: case 0x03: darkvater@414: return _opt.landscape; darkvater@414: case 0x09: darkvater@414: return _date_fract; darkvater@414: case 0x0A: darkvater@414: return _tick_counter; darkvater@414: case 0x0C: darkvater@414: /* If we got here, it means there was no callback or darkvater@414: * callbacks aren't supported on our callpath. */ darkvater@414: return 0; darkvater@414: default: darkvater@414: return -1; darkvater@414: } darkvater@414: } tron@445: tron@2242: SpriteGroup *EvalRandomizedSpriteGroup(const RandomizedSpriteGroup *rsg, byte random_bits) tron@445: { tron@445: byte mask; tron@445: byte index; tron@445: tron@445: /* Noone likes mangling with bits, but you don't get around it here. tron@445: * Sorry. --pasky */ tron@445: // rsg->num_groups is always power of 2 tron@445: mask = (rsg->num_groups - 1) << rsg->lowest_randbit; tron@445: index = (random_bits & mask) >> rsg->lowest_randbit; tron@445: assert(index < rsg->num_groups); peter1138@2488: return rsg->groups[index]; tron@445: } tron@445: tron@2242: byte RandomizedSpriteGroupTriggeredBits(const RandomizedSpriteGroup *rsg, tron@1477: byte triggers, byte *waiting_triggers) tron@445: { tron@445: byte match = rsg->triggers & (*waiting_triggers | triggers); tron@445: bool res; tron@445: tron@445: if (rsg->cmp_mode == RSG_CMP_ANY) { tron@445: res = (match != 0); tron@445: } else { /* RSG_CMP_ALL */ tron@445: res = (match == rsg->triggers); tron@445: } tron@445: tron@445: if (!res) { tron@445: *waiting_triggers |= triggers; tron@445: return 0; tron@445: } tron@445: tron@445: *waiting_triggers &= ~match; tron@445: tron@445: return (rsg->num_groups - 1) << rsg->lowest_randbit; tron@445: } peter1138@2491: peter1138@2491: /** peter1138@2491: * Traverse a sprite group and release its and its child's memory. peter1138@2491: * A group is only released if its reference count is zero. peter1138@2491: * We pass a pointer to a pointer so that the original reference can be set to NULL. peter1138@2491: * @param group_ptr Pointer to sprite group reference. peter1138@2491: */ peter1138@2491: void UnloadSpriteGroup(SpriteGroup **group_ptr) peter1138@2491: { peter1138@2491: SpriteGroup *group; peter1138@2491: int i; peter1138@2491: peter1138@2491: assert(group_ptr != NULL); peter1138@2491: assert(*group_ptr != NULL); peter1138@2491: peter1138@2491: group = *group_ptr; peter1138@2491: *group_ptr = NULL; // Remove this reference. peter1138@2491: peter1138@2491: group->ref_count--; peter1138@2491: if (group->ref_count > 0) { peter1138@2491: DEBUG(grf, 6)("UnloadSpriteGroup: Group at `%p' (type %d) has %d reference(s) left.", group, group->type, group->ref_count); peter1138@2491: return; // Still some references left, so don't clear up. peter1138@2491: } peter1138@2491: peter1138@2491: DEBUG(grf, 6)("UnloadSpriteGroup: Releasing group at `%p'.", group); peter1138@2491: switch (group->type) { peter1138@2491: case SGT_REAL: peter1138@2491: { peter1138@2491: RealSpriteGroup *rsg = &group->g.real; peter1138@2491: for (i = 0; i < rsg->loading_count; i++) { peter1138@2515: if (rsg->loading[i] != NULL) UnloadSpriteGroup(&rsg->loading[i]); peter1138@2491: } peter1138@2491: for (i = 0; i < rsg->loaded_count; i++) { peter1138@2515: if (rsg->loaded[i] != NULL) UnloadSpriteGroup(&rsg->loaded[i]); peter1138@2491: } peter1138@2491: free(group); peter1138@2491: return; peter1138@2491: } peter1138@2491: peter1138@2491: case SGT_DETERMINISTIC: peter1138@2491: { peter1138@2491: DeterministicSpriteGroup *dsg = &group->g.determ; peter1138@2491: for (i = 0; i < group->g.determ.num_ranges; i++) { peter1138@2515: if (dsg->ranges[i].group != NULL) UnloadSpriteGroup(&dsg->ranges[i].group); peter1138@2491: } peter1138@2515: if (dsg->default_group != NULL) UnloadSpriteGroup(&dsg->default_group); peter1138@2491: free(group->g.determ.ranges); peter1138@2491: free(group); peter1138@2491: return; peter1138@2491: } peter1138@2491: peter1138@2491: case SGT_RANDOMIZED: peter1138@2491: { peter1138@2491: for (i = 0; i < group->g.random.num_groups; i++) { peter1138@2515: if (group->g.random.groups[i] != NULL) UnloadSpriteGroup(&group->g.random.groups[i]); peter1138@2491: } peter1138@2491: free(group->g.random.groups); peter1138@2491: free(group); peter1138@2491: return; peter1138@2491: } peter1138@2491: peter1138@2491: case SGT_CALLBACK: peter1138@2491: case SGT_RESULT: peter1138@2491: free(group); peter1138@2491: return; peter1138@2491: } peter1138@2491: peter1138@2491: DEBUG(grf, 1)("Unable to remove unknown sprite group type `0x%x'.", group->type); peter1138@2491: }