newgrf_spritegroup.h

Go to the documentation of this file.
00001 /* $Id: newgrf_spritegroup.h 26172 2013-12-23 18:08:16Z frosch $ */
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 "engine_type.h"
00017 #include "house_type.h"
00018 
00019 #include "newgrf_callbacks.h"
00020 #include "newgrf_generic.h"
00021 #include "newgrf_storage.h"
00022 #include "newgrf_commons.h"
00023 
00030 static inline uint32 GetRegister(uint i)
00031 {
00032   extern TemporaryStorageArray<int32, 0x110> _temp_store;
00033   return _temp_store.GetValue(i);
00034 }
00035 
00041 static inline void ClearRegister(uint i)
00042 {
00043   extern TemporaryStorageArray<int32, 0x110> _temp_store;
00044   _temp_store.StoreValue(i, 0);
00045 }
00046 
00047 /* List of different sprite group types */
00048 enum SpriteGroupType {
00049   SGT_REAL,
00050   SGT_DETERMINISTIC,
00051   SGT_RANDOMIZED,
00052   SGT_CALLBACK,
00053   SGT_RESULT,
00054   SGT_TILELAYOUT,
00055   SGT_INDUSTRY_PRODUCTION,
00056 };
00057 
00058 struct SpriteGroup;
00059 typedef uint32 SpriteGroupID;
00060 struct ResolverObject;
00061 
00062 /* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
00063  * Adding an 'extra' margin would be assuming 64 sprite groups per real
00064  * sprite. 64 = 2^6, so 2^30 should be enough (for now) */
00065 typedef Pool<SpriteGroup, SpriteGroupID, 1024, 1 << 30, PT_DATA> SpriteGroupPool;
00066 extern SpriteGroupPool _spritegroup_pool;
00067 
00068 /* Common wrapper for all the different sprite group types */
00069 struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
00070 protected:
00071   SpriteGroup(SpriteGroupType type) : type(type) {}
00073   virtual const SpriteGroup *Resolve(ResolverObject &object) const { return this; };
00074 
00075 public:
00076   virtual ~SpriteGroup() {}
00077 
00078   SpriteGroupType type;
00079 
00080   virtual SpriteID GetResult() const { return 0; }
00081   virtual byte GetNumResults() const { return 0; }
00082   virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; }
00083 
00084   static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject &object, bool top_level = true);
00085 };
00086 
00087 
00088 /* 'Real' sprite groups contain a list of other result or callback sprite
00089  * groups. */
00090 struct RealSpriteGroup : SpriteGroup {
00091   RealSpriteGroup() : SpriteGroup(SGT_REAL) {}
00092   ~RealSpriteGroup();
00093 
00094   /* Loaded = in motion, loading = not moving
00095    * Each group contains several spritesets, for various loading stages */
00096 
00097   /* XXX: For stations the meaning is different - loaded is for stations
00098    * with small amount of cargo whilst loading is for stations with a lot
00099    * of da stuff. */
00100 
00101   byte num_loaded;       
00102   byte num_loading;      
00103   const SpriteGroup **loaded;  
00104   const SpriteGroup **loading; 
00105 
00106 protected:
00107   const SpriteGroup *Resolve(ResolverObject &object) const;
00108 };
00109 
00110 /* Shared by deterministic and random groups. */
00111 enum VarSpriteGroupScope {
00112   VSG_BEGIN,
00113 
00114   VSG_SCOPE_SELF = VSG_BEGIN, 
00115   VSG_SCOPE_PARENT,           
00116   VSG_SCOPE_RELATIVE,         
00117 
00118   VSG_END
00119 };
00120 DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope)
00121 
00122 enum DeterministicSpriteGroupSize {
00123   DSG_SIZE_BYTE,
00124   DSG_SIZE_WORD,
00125   DSG_SIZE_DWORD,
00126 };
00127 
00128 enum DeterministicSpriteGroupAdjustType {
00129   DSGA_TYPE_NONE,
00130   DSGA_TYPE_DIV,
00131   DSGA_TYPE_MOD,
00132 };
00133 
00134 enum DeterministicSpriteGroupAdjustOperation {
00135   DSGA_OP_ADD,  
00136   DSGA_OP_SUB,  
00137   DSGA_OP_SMIN, 
00138   DSGA_OP_SMAX, 
00139   DSGA_OP_UMIN, 
00140   DSGA_OP_UMAX, 
00141   DSGA_OP_SDIV, 
00142   DSGA_OP_SMOD, 
00143   DSGA_OP_UDIV, 
00144   DSGA_OP_UMOD, 
00145   DSGA_OP_MUL,  
00146   DSGA_OP_AND,  
00147   DSGA_OP_OR,   
00148   DSGA_OP_XOR,  
00149   DSGA_OP_STO,  
00150   DSGA_OP_RST,  
00151   DSGA_OP_STOP, 
00152   DSGA_OP_ROR,  
00153   DSGA_OP_SCMP, 
00154   DSGA_OP_UCMP, 
00155   DSGA_OP_SHL,  
00156   DSGA_OP_SHR,  
00157   DSGA_OP_SAR,  
00158 };
00159 
00160 
00161 struct DeterministicSpriteGroupAdjust {
00162   DeterministicSpriteGroupAdjustOperation operation;
00163   DeterministicSpriteGroupAdjustType type;
00164   byte variable;
00165   byte parameter; 
00166   byte shift_num;
00167   uint32 and_mask;
00168   uint32 add_val;
00169   uint32 divmod_val;
00170   const SpriteGroup *subroutine;
00171 };
00172 
00173 
00174 struct DeterministicSpriteGroupRange {
00175   const SpriteGroup *group;
00176   uint32 low;
00177   uint32 high;
00178 };
00179 
00180 
00181 struct DeterministicSpriteGroup : SpriteGroup {
00182   DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {}
00183   ~DeterministicSpriteGroup();
00184 
00185   VarSpriteGroupScope var_scope;
00186   DeterministicSpriteGroupSize size;
00187   uint num_adjusts;
00188   byte num_ranges;
00189   DeterministicSpriteGroupAdjust *adjusts;
00190   DeterministicSpriteGroupRange *ranges; // Dynamically allocated
00191 
00192   /* Dynamically allocated, this is the sole owner */
00193   const SpriteGroup *default_group;
00194 
00195 protected:
00196   const SpriteGroup *Resolve(ResolverObject &object) const;
00197 };
00198 
00199 enum RandomizedSpriteGroupCompareMode {
00200   RSG_CMP_ANY,
00201   RSG_CMP_ALL,
00202 };
00203 
00204 struct RandomizedSpriteGroup : SpriteGroup {
00205   RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
00206   ~RandomizedSpriteGroup();
00207 
00208   VarSpriteGroupScope var_scope;  
00209 
00210   RandomizedSpriteGroupCompareMode cmp_mode; 
00211   byte triggers;
00212   byte count;
00213 
00214   byte lowest_randbit; 
00215   byte num_groups; 
00216 
00217   const SpriteGroup **groups; 
00218 
00219 protected:
00220   const SpriteGroup *Resolve(ResolverObject &object) const;
00221 };
00222 
00223 
00224 /* This contains a callback result. A failed callback has a value of
00225  * CALLBACK_FAILED */
00226 struct CallbackResultSpriteGroup : SpriteGroup {
00232   CallbackResultSpriteGroup(uint16 value, bool grf_version8) :
00233     SpriteGroup(SGT_CALLBACK),
00234     result(value)
00235   {
00236     /* Old style callback results (only valid for version < 8) have the highest byte 0xFF so signify it is a callback result.
00237      * New style ones only have the highest bit set (allows 15-bit results, instead of just 8) */
00238     if (!grf_version8 && (this->result >> 8) == 0xFF) {
00239       this->result &= ~0xFF00;
00240     } else {
00241       this->result &= ~0x8000;
00242     }
00243   }
00244 
00245   uint16 result;
00246   uint16 GetCallbackResult() const { return this->result; }
00247 };
00248 
00249 
00250 /* A result sprite group returns the first SpriteID and the number of
00251  * sprites in the set */
00252 struct ResultSpriteGroup : SpriteGroup {
00259   ResultSpriteGroup(SpriteID sprite, byte num_sprites) :
00260     SpriteGroup(SGT_RESULT),
00261     sprite(sprite),
00262     num_sprites(num_sprites)
00263   {
00264   }
00265 
00266   SpriteID sprite;
00267   byte num_sprites;
00268   SpriteID GetResult() const { return this->sprite; }
00269   byte GetNumResults() const { return this->num_sprites; }
00270 };
00271 
00275 struct TileLayoutSpriteGroup : SpriteGroup {
00276   TileLayoutSpriteGroup() : SpriteGroup(SGT_TILELAYOUT) {}
00277   ~TileLayoutSpriteGroup() {}
00278 
00279   NewGRFSpriteLayout dts;
00280 
00281   const DrawTileSprites *ProcessRegisters(uint8 *stage) const;
00282 };
00283 
00284 struct IndustryProductionSpriteGroup : SpriteGroup {
00285   IndustryProductionSpriteGroup() : SpriteGroup(SGT_INDUSTRY_PRODUCTION) {}
00286 
00287   uint8 version;
00288   int16 subtract_input[3];  // signed
00289   uint16 add_output[2];     // unsigned
00290   uint8 again;
00291 };
00292 
00299 struct ScopeResolver {
00300   ResolverObject &ro; 
00301 
00302   ScopeResolver(ResolverObject &ro);
00303   virtual ~ScopeResolver();
00304 
00305   virtual uint32 GetRandomBits() const;
00306   virtual uint32 GetTriggers() const;
00307   virtual void SetTriggers(int triggers) const;
00308 
00309   virtual uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
00310   virtual void StorePSA(uint reg, int32 value);
00311 };
00312 
00319 struct ResolverObject {
00320   ResolverObject(const GRFFile *grffile, CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
00321   virtual ~ResolverObject();
00322 
00323   ScopeResolver default_scope; 
00324 
00325   CallbackID callback;        
00326   uint32 callback_param1;     
00327   uint32 callback_param2;     
00328 
00329   byte trigger;
00330 
00331   uint32 last_value;          
00332   uint32 reseed[VSG_END];     
00333 
00334   const GRFFile *grffile;     
00335 
00336   virtual const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
00337 
00338   virtual ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0);
00339 
00345   uint32 GetReseedSum() const
00346   {
00347     uint32 sum = 0;
00348     for (VarSpriteGroupScope vsg = VSG_BEGIN; vsg < VSG_END; vsg++) {
00349       sum |= this->reseed[vsg];
00350     }
00351     return sum;
00352   }
00353 
00358   void ResetState()
00359   {
00360     this->last_value = 0;
00361     this->trigger    = 0;
00362     memset(this->reseed, 0, sizeof(this->reseed));
00363   }
00364 };
00365 
00366 #endif /* NEWGRF_SPRITEGROUP_H */