newgrf_spritegroup.h

Go to the documentation of this file.
00001 /* $Id: newgrf_spritegroup.h 22838 2011-08-25 13:24:32Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef NEWGRF_SPRITEGROUP_H
00013 #define NEWGRF_SPRITEGROUP_H
00014 
00015 #include "town_type.h"
00016 #include "gfx_type.h"
00017 #include "engine_type.h"
00018 #include "core/pool_type.hpp"
00019 #include "house_type.h"
00020 
00021 #include "newgrf_callbacks.h"
00022 #include "newgrf_generic.h"
00023 #include "newgrf_storage.h"
00024 #include "newgrf_commons.h"
00025 
00032 static inline uint32 GetRegister(uint i)
00033 {
00034   extern TemporaryStorageArray<int32, 0x110> _temp_store;
00035   return _temp_store.Get(i);
00036 }
00037 
00043 static inline void ClearRegister(uint i)
00044 {
00045   extern TemporaryStorageArray<int32, 0x110> _temp_store;
00046   _temp_store.Store(i, 0);
00047 }
00048 
00049 /* List of different sprite group types */
00050 enum SpriteGroupType {
00051   SGT_REAL,
00052   SGT_DETERMINISTIC,
00053   SGT_RANDOMIZED,
00054   SGT_CALLBACK,
00055   SGT_RESULT,
00056   SGT_TILELAYOUT,
00057   SGT_INDUSTRY_PRODUCTION,
00058 };
00059 
00060 struct SpriteGroup;
00061 typedef uint32 SpriteGroupID;
00062 
00063 /* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
00064  * Adding an 'extra' margin would be assuming 64 sprite groups per real
00065  * sprite. 64 = 2^6, so 2^30 should be enough (for now) */
00066 typedef Pool<SpriteGroup, SpriteGroupID, 1024, 1 << 30> SpriteGroupPool;
00067 extern SpriteGroupPool _spritegroup_pool;
00068 
00069 /* Common wrapper for all the different sprite group types */
00070 struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
00071 protected:
00072   SpriteGroup(SpriteGroupType type) : type(type) {}
00074   virtual const SpriteGroup *Resolve(struct ResolverObject *object) const { return this; };
00075 
00076 public:
00077   virtual ~SpriteGroup() {}
00078 
00079   SpriteGroupType type;
00080 
00081   virtual SpriteID GetResult() const { return 0; }
00082   virtual byte GetNumResults() const { return 0; }
00083   virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; }
00084 
00094   static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object)
00095   {
00096     return group == NULL ? NULL : group->Resolve(object);
00097   }
00098 };
00099 
00100 
00101 /* 'Real' sprite groups contain a list of other result or callback sprite
00102  * groups. */
00103 struct RealSpriteGroup : SpriteGroup {
00104   RealSpriteGroup() : SpriteGroup(SGT_REAL) {}
00105   ~RealSpriteGroup();
00106 
00107   /* Loaded = in motion, loading = not moving
00108    * Each group contains several spritesets, for various loading stages */
00109 
00110   /* XXX: For stations the meaning is different - loaded is for stations
00111    * with small amount of cargo whilst loading is for stations with a lot
00112    * of da stuff. */
00113 
00114   byte num_loaded;       
00115   byte num_loading;      
00116   const SpriteGroup **loaded;  
00117   const SpriteGroup **loading; 
00118 
00119 protected:
00120   const SpriteGroup *Resolve(ResolverObject *object) const;
00121 };
00122 
00123 /* Shared by deterministic and random groups. */
00124 enum VarSpriteGroupScope {
00125   VSG_BEGIN,
00126 
00127   VSG_SCOPE_SELF = VSG_BEGIN, 
00128   VSG_SCOPE_PARENT,           
00129   VSG_SCOPE_RELATIVE,         
00130 
00131   VSG_END
00132 };
00133 DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope)
00134 
00135 enum DeterministicSpriteGroupSize {
00136   DSG_SIZE_BYTE,
00137   DSG_SIZE_WORD,
00138   DSG_SIZE_DWORD,
00139 };
00140 
00141 enum DeterministicSpriteGroupAdjustType {
00142   DSGA_TYPE_NONE,
00143   DSGA_TYPE_DIV,
00144   DSGA_TYPE_MOD,
00145 };
00146 
00147 enum DeterministicSpriteGroupAdjustOperation {
00148   DSGA_OP_ADD,  
00149   DSGA_OP_SUB,  
00150   DSGA_OP_SMIN, 
00151   DSGA_OP_SMAX, 
00152   DSGA_OP_UMIN, 
00153   DSGA_OP_UMAX, 
00154   DSGA_OP_SDIV, 
00155   DSGA_OP_SMOD, 
00156   DSGA_OP_UDIV, 
00157   DSGA_OP_UMOD, 
00158   DSGA_OP_MUL,  
00159   DSGA_OP_AND,  
00160   DSGA_OP_OR,   
00161   DSGA_OP_XOR,  
00162   DSGA_OP_STO,  
00163   DSGA_OP_RST,  
00164   DSGA_OP_STOP, 
00165   DSGA_OP_ROR,  
00166   DSGA_OP_SCMP, 
00167   DSGA_OP_UCMP, 
00168   DSGA_OP_SHL,  
00169   DSGA_OP_SHR,  
00170   DSGA_OP_SAR,  
00171 };
00172 
00173 
00174 struct DeterministicSpriteGroupAdjust {
00175   DeterministicSpriteGroupAdjustOperation operation;
00176   DeterministicSpriteGroupAdjustType type;
00177   byte variable;
00178   byte parameter; 
00179   byte shift_num;
00180   uint32 and_mask;
00181   uint32 add_val;
00182   uint32 divmod_val;
00183   const SpriteGroup *subroutine;
00184 };
00185 
00186 
00187 struct DeterministicSpriteGroupRange {
00188   const SpriteGroup *group;
00189   uint32 low;
00190   uint32 high;
00191 };
00192 
00193 
00194 struct DeterministicSpriteGroup : SpriteGroup {
00195   DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {}
00196   ~DeterministicSpriteGroup();
00197 
00198   VarSpriteGroupScope var_scope;
00199   DeterministicSpriteGroupSize size;
00200   uint num_adjusts;
00201   byte num_ranges;
00202   DeterministicSpriteGroupAdjust *adjusts;
00203   DeterministicSpriteGroupRange *ranges; // Dynamically allocated
00204 
00205   /* Dynamically allocated, this is the sole owner */
00206   const SpriteGroup *default_group;
00207 
00208 protected:
00209   const SpriteGroup *Resolve(ResolverObject *object) const;
00210 };
00211 
00212 enum RandomizedSpriteGroupCompareMode {
00213   RSG_CMP_ANY,
00214   RSG_CMP_ALL,
00215 };
00216 
00217 struct RandomizedSpriteGroup : SpriteGroup {
00218   RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
00219   ~RandomizedSpriteGroup();
00220 
00221   VarSpriteGroupScope var_scope;  
00222 
00223   RandomizedSpriteGroupCompareMode cmp_mode; 
00224   byte triggers;
00225   byte count;
00226 
00227   byte lowest_randbit; 
00228   byte num_groups; 
00229 
00230   const SpriteGroup **groups; 
00231 
00232 protected:
00233   const SpriteGroup *Resolve(ResolverObject *object) const;
00234 };
00235 
00236 
00237 /* This contains a callback result. A failed callback has a value of
00238  * CALLBACK_FAILED */
00239 struct CallbackResultSpriteGroup : SpriteGroup {
00244   CallbackResultSpriteGroup(uint16 value) :
00245     SpriteGroup(SGT_CALLBACK),
00246     result(value)
00247   {
00248     /* Old style callback results have the highest byte 0xFF so signify it is a callback result
00249      * New style ones only have the highest bit set (allows 15-bit results, instead of just 8) */
00250     if ((this->result >> 8) == 0xFF) {
00251       this->result &= ~0xFF00;
00252     } else {
00253       this->result &= ~0x8000;
00254     }
00255   }
00256 
00257   uint16 result;
00258   uint16 GetCallbackResult() const { return this->result; }
00259 };
00260 
00261 
00262 /* A result sprite group returns the first SpriteID and the number of
00263  * sprites in the set */
00264 struct ResultSpriteGroup : SpriteGroup {
00271   ResultSpriteGroup(SpriteID sprite, byte num_sprites) :
00272     SpriteGroup(SGT_RESULT),
00273     sprite(sprite),
00274     num_sprites(num_sprites)
00275   {
00276   }
00277 
00278   SpriteID sprite;
00279   byte num_sprites;
00280   SpriteID GetResult() const { return this->sprite; }
00281   byte GetNumResults() const { return this->num_sprites; }
00282 };
00283 
00284 struct TileLayoutSpriteGroup : SpriteGroup {
00285   TileLayoutSpriteGroup() : SpriteGroup(SGT_TILELAYOUT) {}
00286   ~TileLayoutSpriteGroup();
00287 
00288   byte num_building_stages;    
00289   struct DrawTileSprites *dts;
00290 
00296   uint GetConstructionStageOffset(uint construction_stage) const
00297   {
00298     uint num_sprites = this->num_building_stages;
00299     assert(num_sprites > 0);
00300     if (num_sprites > 4) num_sprites = 4;
00301     switch (construction_stage) {
00302       case 0: return 0;
00303       case 1: return num_sprites > 2 ? 1 : 0;
00304       case 2: return num_sprites > 2 ? num_sprites - 2 : 0;
00305       case 3: return num_sprites - 1;
00306       default: NOT_REACHED();
00307     }
00308   }
00309 };
00310 
00311 struct IndustryProductionSpriteGroup : SpriteGroup {
00312   IndustryProductionSpriteGroup() : SpriteGroup(SGT_INDUSTRY_PRODUCTION) {}
00313 
00314   uint8 version;
00315   int16 subtract_input[3];  // signed
00316   uint16 add_output[2];     // unsigned
00317   uint8 again;
00318 };
00319 
00320 
00321 struct ResolverObject {
00322   CallbackID callback;
00323   uint32 callback_param1;
00324   uint32 callback_param2;
00325 
00326   byte trigger;
00327 
00328   uint32 last_value;          
00329   uint32 reseed[VSG_END];     
00330 
00331   VarSpriteGroupScope scope;  
00332   byte count;                 
00333 
00334   BaseStorageArray *psa;      
00335 
00336   const GRFFile *grffile;     
00337 
00338   union {
00339     struct {
00340       const struct Vehicle *self;
00341       const struct Vehicle *parent;
00342       EngineID self_type;
00343       bool info_view;                
00344     } vehicle;
00345     struct {
00346       TileIndex tile;
00347     } canal;
00348     struct {
00349       TileIndex tile;
00350       const struct BaseStation *st;
00351       const struct StationSpec *statspec;
00352       CargoID cargo_type;
00353     } station;
00354     struct {
00355       TileIndex tile;
00356       const Town *town;
00357       HouseID house_id;
00358       uint16 initial_random_bits;    
00359       bool not_yet_constructed;      
00360     } house;
00361     struct {
00362       TileIndex tile;
00363       Industry *ind;
00364       IndustryGfx gfx;
00365       IndustryType type;
00366     } industry;
00367     struct {
00368       const struct CargoSpec *cs;
00369     } cargo;
00370     struct {
00371       CargoID cargo_type;
00372       uint8 default_selection;
00373       uint8 src_industry;            
00374       uint8 dst_industry;            
00375       uint8 distance;
00376       AIConstructionEvent event;
00377       uint8 count;
00378       uint8 station_size;
00379     } generic;
00380     struct {
00381       TileIndex tile;                
00382       TileContext context;           
00383     } routes;
00384     struct {
00385       const struct Station *st;      
00386       byte airport_id;               
00387       byte layout;                   
00388       TileIndex tile;                
00389     } airport;
00390     struct {
00391       const struct Object *o;        
00392       TileIndex tile;                
00393       uint8 view;                    
00394     } object;
00395   } u;
00396 
00397   uint32 (*GetRandomBits)(const struct ResolverObject*);
00398   uint32 (*GetTriggers)(const struct ResolverObject*);
00399   void (*SetTriggers)(const struct ResolverObject*, int);
00400   uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*);
00401   const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const RealSpriteGroup*);
00402 
00408   uint32 GetReseedSum() const
00409   {
00410     uint32 sum = 0;
00411     for (VarSpriteGroupScope vsg = VSG_BEGIN; vsg < VSG_END; vsg++) {
00412       sum |= this->reseed[vsg];
00413     }
00414     return sum;
00415   }
00416 
00421   void ResetState()
00422   {
00423     this->last_value = 0;
00424     this->trigger    = 0;
00425     memset(this->reseed, 0, sizeof(this->reseed));
00426   }
00427 };
00428 
00429 #endif /* NEWGRF_SPRITEGROUP_H */