peter1138@3595: /* $Id$ */ peter1138@3595: belugas@6674: /** @file newgrf_spritegroup.h */ belugas@6674: peter1138@3595: #ifndef NEWGRF_SPRITEGROUP_H peter1138@3595: #define NEWGRF_SPRITEGROUP_H peter1138@3595: rubidium@6872: #include "town_type.h" rubidium@6872: #include "industry_type.h" rubidium@6872: #include "core/bitmath_func.hpp" rubidium@6872: #include "gfx_type.h" richk@10184: #include "engine_type.h" richk@10184: #include "tile_type.h" richk@10184: richk@10184: #include "newgrf_cargo.h" richk@10184: #include "newgrf_callbacks.h" richk@6878: #include "newgrf_generic.h" richk@10184: #include "newgrf_storage.h" richk@6720: richk@6720: /** richk@6720: * Gets the value of a so-called newgrf "register". richk@6720: * @param i index of the register richk@6720: * @pre i < 0x110 richk@6720: * @return the value of the register richk@6720: */ richk@6720: static inline uint32 GetRegister(uint i) richk@6720: { rubidium@6870: extern TemporaryStorageArray _temp_store; rubidium@6870: return _temp_store.Get(i); richk@6720: } peter1138@3664: rubidium@6574: struct SpriteGroup; peter1138@3664: peter1138@3668: peter1138@3668: /* 'Real' sprite groups contain a list of other result or callback sprite peter1138@3668: * groups. */ rubidium@6574: struct RealSpriteGroup { belugas@6674: /* Loaded = in motion, loading = not moving belugas@6674: * Each group contains several spritesets, for various loading stages */ peter1138@3664: belugas@6674: /* XXX: For stations the meaning is different - loaded is for stations belugas@6674: * with small amount of cargo whilst loading is for stations with a lot belugas@6674: * of da stuff. */ peter1138@3664: peter1138@3668: byte num_loaded; ///< Number of loaded groups peter1138@3668: byte num_loading; ///< Number of loading groups peter1138@4892: const SpriteGroup **loaded; ///< List of loaded groups (can be SpriteIDs or Callback results) peter1138@4892: const SpriteGroup **loading; ///< List of loading groups (can be SpriteIDs or Callback results) rubidium@6574: }; peter1138@3664: peter1138@3664: /* Shared by deterministic and random groups. */ rubidium@6574: enum VarSpriteGroupScope { peter1138@3664: VSG_SCOPE_SELF, belugas@6674: /* Engine of consists for vehicles, city for stations. */ peter1138@3664: VSG_SCOPE_PARENT, richk@10184: /* Any vehicle in the consist (vehicles only) */ richk@10184: VSG_SCOPE_RELATIVE, rubidium@6574: }; peter1138@3664: rubidium@6574: enum DeterministicSpriteGroupSize { peter1138@3668: DSG_SIZE_BYTE, peter1138@3668: DSG_SIZE_WORD, peter1138@3668: DSG_SIZE_DWORD, rubidium@6574: }; peter1138@3664: rubidium@6574: enum DeterministicSpriteGroupAdjustType { peter1138@3668: DSGA_TYPE_NONE, peter1138@3668: DSGA_TYPE_DIV, peter1138@3668: DSGA_TYPE_MOD, rubidium@6574: }; peter1138@3664: rubidium@6574: enum DeterministicSpriteGroupAdjustOperation { belugas@6674: DSGA_OP_ADD, ///< a + b belugas@6674: DSGA_OP_SUB, ///< a - b belugas@6674: DSGA_OP_SMIN, ///< (signed) min(a, b) belugas@6674: DSGA_OP_SMAX, ///< (signed) max(a, b) belugas@6674: DSGA_OP_UMIN, ///< (unsigned) min(a, b) belugas@6674: DSGA_OP_UMAX, ///< (unsigned) max(a, b) belugas@6674: DSGA_OP_SDIV, ///< (signed) a / b belugas@6674: DSGA_OP_SMOD, ///< (signed) a % b belugas@6674: DSGA_OP_UDIV, ///< (unsigned) a / b belugas@6674: DSGA_OP_UMOD, ///< (unsigned) a & b belugas@6674: DSGA_OP_MUL, ///< a * b belugas@6674: DSGA_OP_AND, ///< a & b belugas@6674: DSGA_OP_OR, ///< a | b belugas@6674: DSGA_OP_XOR, ///< a ^ b richk@6719: DSGA_OP_STO, ///< store a into temporary storage, indexed by b. return a richk@6719: DSGA_OP_RST, ///< return b rubidium@6870: DSGA_OP_STOP, ///< store a into persistent storage, indexed by b, return a rubidium@6870: DSGA_OP_ROR, ///< rotate a b positions to the right rubidium@6870: DSGA_OP_SCMP, ///< (signed) comparision (a < b -> 0, a == b = 1, a > b = 2) rubidium@6870: DSGA_OP_UCMP, ///< (unsigned) comparision (a < b -> 0, a == b = 1, a > b = 2) rubidium@6574: }; peter1138@3668: peter1138@3668: rubidium@6574: struct DeterministicSpriteGroupAdjust { peter1138@3668: DeterministicSpriteGroupAdjustOperation operation; peter1138@3668: DeterministicSpriteGroupAdjustType type; peter1138@3668: byte variable; peter1138@3668: byte parameter; ///< Used for variables between 0x60 and 0x7F inclusive. peter1138@3668: byte shift_num; peter1138@3668: uint32 and_mask; peter1138@3668: uint32 add_val; peter1138@3668: uint32 divmod_val; maedhros@5868: const SpriteGroup *subroutine; rubidium@6574: }; peter1138@3668: peter1138@3668: rubidium@6574: struct DeterministicSpriteGroupRange { peter1138@4892: const SpriteGroup *group; peter1138@3668: uint32 low; peter1138@3668: uint32 high; rubidium@6574: }; peter1138@3668: peter1138@3664: rubidium@6574: struct DeterministicSpriteGroup { peter1138@3664: VarSpriteGroupScope var_scope; peter1138@3668: DeterministicSpriteGroupSize size; peter1138@3668: byte num_adjusts; peter1138@3664: byte num_ranges; peter1138@3668: DeterministicSpriteGroupAdjust *adjusts; peter1138@3664: DeterministicSpriteGroupRange *ranges; // Dynamically allocated peter1138@3664: belugas@6674: /* Dynamically allocated, this is the sole owner */ peter1138@4892: const SpriteGroup *default_group; rubidium@6574: }; peter1138@3664: rubidium@6574: enum RandomizedSpriteGroupCompareMode { peter1138@3664: RSG_CMP_ANY, peter1138@3664: RSG_CMP_ALL, rubidium@6574: }; peter1138@3664: rubidium@6574: struct RandomizedSpriteGroup { belugas@6674: VarSpriteGroupScope var_scope; ///< Take this object: peter1138@3664: belugas@6674: RandomizedSpriteGroupCompareMode cmp_mode; ///< Check for these triggers: peter1138@3664: byte triggers; richk@10184: byte count; peter1138@3664: belugas@6674: byte lowest_randbit; ///< Look for this in the per-object randomized bitmask: belugas@6674: byte num_groups; ///< must be power of 2 peter1138@3664: belugas@6674: const SpriteGroup **groups; ///< Take the group with appropriate index: rubidium@6574: }; peter1138@3664: peter1138@3668: peter1138@3668: /* This contains a callback result. A failed callback has a value of peter1138@3668: * CALLBACK_FAILED */ rubidium@6574: struct CallbackResultSpriteGroup { peter1138@3664: uint16 result; rubidium@6574: }; peter1138@3664: peter1138@3668: peter1138@3668: /* A result sprite group returns the first SpriteID and the number of peter1138@3668: * sprites in the set */ rubidium@6574: struct ResultSpriteGroup { peter1138@3668: SpriteID sprite; peter1138@3668: byte num_sprites; rubidium@6574: }; peter1138@3664: maedhros@6658: struct TileLayoutSpriteGroup { belugas@6674: byte num_sprites; ///< Number of sprites in the spriteset, used for loading stages maedhros@6658: struct DrawTileSprites *dts; maedhros@6658: }; maedhros@6658: richk@6720: struct IndustryProductionSpriteGroup { richk@6720: uint8 version; richk@6720: uint16 substract_input[3]; richk@6720: uint16 add_output[2]; richk@6720: uint8 again; richk@6720: }; richk@6720: peter1138@3668: /* List of different sprite group types */ rubidium@6574: enum SpriteGroupType { peter1138@3664: SGT_INVALID, peter1138@3664: SGT_REAL, peter1138@3664: SGT_DETERMINISTIC, peter1138@3664: SGT_RANDOMIZED, peter1138@3664: SGT_CALLBACK, peter1138@3664: SGT_RESULT, maedhros@6658: SGT_TILELAYOUT, richk@6720: SGT_INDUSTRY_PRODUCTION, rubidium@6574: }; peter1138@3664: peter1138@3668: /* Common wrapper for all the different sprite group types */ peter1138@3664: struct SpriteGroup { peter1138@3664: SpriteGroupType type; peter1138@3664: peter1138@3664: union { peter1138@3664: RealSpriteGroup real; peter1138@3664: DeterministicSpriteGroup determ; peter1138@3664: RandomizedSpriteGroup random; peter1138@3664: CallbackResultSpriteGroup callback; peter1138@3664: ResultSpriteGroup result; maedhros@6658: TileLayoutSpriteGroup layout; richk@6720: IndustryProductionSpriteGroup indprod; peter1138@3664: } g; peter1138@3664: }; peter1138@3664: peter1138@3664: rubidium@6573: SpriteGroup *AllocateSpriteGroup(); rubidium@6573: void InitializeSpriteGroupPool(); peter1138@3595: peter1138@3677: rubidium@6574: struct ResolverObject { richk@6743: CallbackID callback; peter1138@3677: uint32 callback_param1; peter1138@3677: uint32 callback_param2; richk@10184: bool procedure_call; ///< true if we are currently resolving a var 0x7E procedure result. peter1138@3677: peter1138@3677: byte trigger; richk@10184: byte count; peter1138@3677: uint32 last_value; peter1138@3677: uint32 reseed; peter1138@3677: VarSpriteGroupScope scope; peter1138@3677: peter1138@4056: bool info_view; ///< Indicates if the item is being drawn in an info window peter1138@4056: rubidium@6870: BaseStorageArray *psa; ///< The persistent storage array of this resolved object. rubidium@6870: peter1138@3677: union { peter1138@3677: struct { peter1138@3677: const struct Vehicle *self; peter1138@3677: const struct Vehicle *parent; peter1138@4057: EngineID self_type; peter1138@3677: } vehicle; peter1138@3677: struct { peter1138@3677: TileIndex tile; richk@6719: } canal; richk@6719: struct { richk@6719: TileIndex tile; peter1138@3677: const struct Station *st; peter1138@3677: const struct StationSpec *statspec; richk@6722: const struct FSMportsSpec *fsmportspec; peter1138@4817: CargoID cargo_type; peter1138@3677: } station; maedhros@6658: struct { maedhros@6658: TileIndex tile; maedhros@6658: Town *town; maedhros@6658: HouseID house_id; maedhros@6658: } house; peter1138@6691: struct { richk@6720: TileIndex tile; richk@6720: Industry *ind; richk@6720: IndustryGfx gfx; rubidium@6872: IndustryType type; richk@6720: } industry; richk@6720: struct { peter1138@6691: const struct CargoSpec *cs; peter1138@6691: } cargo; richk@6878: struct { richk@6878: CargoID cargo_type; richk@6878: uint8 default_selection; richk@6878: IndustryType src_industry; richk@6878: IndustryType dst_industry; richk@6878: uint8 distance; richk@6878: AIConstructionEvent event; richk@6878: uint8 count; richk@6878: uint8 station_size; richk@6878: } generic; peter1138@3720: } u; peter1138@3677: peter1138@3677: uint32 (*GetRandomBits)(const struct ResolverObject*); peter1138@3677: uint32 (*GetTriggers)(const struct ResolverObject*); peter1138@3677: void (*SetTriggers)(const struct ResolverObject*, int); peter1138@3893: uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*); peter1138@3734: const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const SpriteGroup*); richk@10184: richk@10184: ResolverObject() : procedure_call(false) { } rubidium@6574: }; peter1138@3677: peter1138@3677: peter1138@3677: /* Base sprite group resolver */ peter1138@3677: const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object); peter1138@3677: peter1138@3677: peter1138@3595: #endif /* NEWGRF_SPRITEGROUP_H */