newgrf_spritegroup.h

Go to the documentation of this file.
00001 /* $Id: newgrf_spritegroup.h 26388 2014-03-03 20:02:31Z 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 
00036 /* List of different sprite group types */
00037 enum SpriteGroupType {
00038   SGT_REAL,
00039   SGT_DETERMINISTIC,
00040   SGT_RANDOMIZED,
00041   SGT_CALLBACK,
00042   SGT_RESULT,
00043   SGT_TILELAYOUT,
00044   SGT_INDUSTRY_PRODUCTION,
00045 };
00046 
00047 struct SpriteGroup;
00048 typedef uint32 SpriteGroupID;
00049 struct ResolverObject;
00050 
00051 /* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
00052  * Adding an 'extra' margin would be assuming 64 sprite groups per real
00053  * sprite. 64 = 2^6, so 2^30 should be enough (for now) */
00054 typedef Pool<SpriteGroup, SpriteGroupID, 1024, 1 << 30, PT_DATA> SpriteGroupPool;
00055 extern SpriteGroupPool _spritegroup_pool;
00056 
00057 /* Common wrapper for all the different sprite group types */
00058 struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
00059 protected:
00060   SpriteGroup(SpriteGroupType type) : type(type) {}
00062   virtual const SpriteGroup *Resolve(ResolverObject &object) const { return this; };
00063 
00064 public:
00065   virtual ~SpriteGroup() {}
00066 
00067   SpriteGroupType type;
00068 
00069   virtual SpriteID GetResult() const { return 0; }
00070   virtual byte GetNumResults() const { return 0; }
00071   virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; }
00072 
00073   static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject &object, bool top_level = true);
00074 };
00075 
00076 
00077 /* 'Real' sprite groups contain a list of other result or callback sprite
00078  * groups. */
00079 struct RealSpriteGroup : SpriteGroup {
00080   RealSpriteGroup() : SpriteGroup(SGT_REAL) {}
00081   ~RealSpriteGroup();
00082 
00083   /* Loaded = in motion, loading = not moving
00084    * Each group contains several spritesets, for various loading stages */
00085 
00086   /* XXX: For stations the meaning is different - loaded is for stations
00087    * with small amount of cargo whilst loading is for stations with a lot
00088    * of da stuff. */
00089 
00090   byte num_loaded;       
00091   byte num_loading;      
00092   const SpriteGroup **loaded;  
00093   const SpriteGroup **loading; 
00094 
00095 protected:
00096   const SpriteGroup *Resolve(ResolverObject &object) const;
00097 };
00098 
00099 /* Shared by deterministic and random groups. */
00100 enum VarSpriteGroupScope {
00101   VSG_BEGIN,
00102 
00103   VSG_SCOPE_SELF = VSG_BEGIN, 
00104   VSG_SCOPE_PARENT,           
00105   VSG_SCOPE_RELATIVE,         
00106 
00107   VSG_END
00108 };
00109 DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope)
00110 
00111 enum DeterministicSpriteGroupSize {
00112   DSG_SIZE_BYTE,
00113   DSG_SIZE_WORD,
00114   DSG_SIZE_DWORD,
00115 };
00116 
00117 enum DeterministicSpriteGroupAdjustType {
00118   DSGA_TYPE_NONE,
00119   DSGA_TYPE_DIV,
00120   DSGA_TYPE_MOD,
00121 };
00122 
00123 enum DeterministicSpriteGroupAdjustOperation {
00124   DSGA_OP_ADD,  
00125   DSGA_OP_SUB,  
00126   DSGA_OP_SMIN, 
00127   DSGA_OP_SMAX, 
00128   DSGA_OP_UMIN, 
00129   DSGA_OP_UMAX, 
00130   DSGA_OP_SDIV, 
00131   DSGA_OP_SMOD, 
00132   DSGA_OP_UDIV, 
00133   DSGA_OP_UMOD, 
00134   DSGA_OP_MUL,  
00135   DSGA_OP_AND,  
00136   DSGA_OP_OR,   
00137   DSGA_OP_XOR,  
00138   DSGA_OP_STO,  
00139   DSGA_OP_RST,  
00140   DSGA_OP_STOP, 
00141   DSGA_OP_ROR,  
00142   DSGA_OP_SCMP, 
00143   DSGA_OP_UCMP, 
00144   DSGA_OP_SHL,  
00145   DSGA_OP_SHR,  
00146   DSGA_OP_SAR,  
00147 };
00148 
00149 
00150 struct DeterministicSpriteGroupAdjust {
00151   DeterministicSpriteGroupAdjustOperation operation;
00152   DeterministicSpriteGroupAdjustType type;
00153   byte variable;
00154   byte parameter; 
00155   byte shift_num;
00156   uint32 and_mask;
00157   uint32 add_val;
00158   uint32 divmod_val;
00159   const SpriteGroup *subroutine;
00160 };
00161 
00162 
00163 struct DeterministicSpriteGroupRange {
00164   const SpriteGroup *group;
00165   uint32 low;
00166   uint32 high;
00167 };
00168 
00169 
00170 struct DeterministicSpriteGroup : SpriteGroup {
00171   DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {}
00172   ~DeterministicSpriteGroup();
00173 
00174   VarSpriteGroupScope var_scope;
00175   DeterministicSpriteGroupSize size;
00176   uint num_adjusts;
00177   byte num_ranges;
00178   DeterministicSpriteGroupAdjust *adjusts;
00179   DeterministicSpriteGroupRange *ranges; // Dynamically allocated
00180 
00181   /* Dynamically allocated, this is the sole owner */
00182   const SpriteGroup *default_group;
00183 
00184 protected:
00185   const SpriteGroup *Resolve(ResolverObject &object) const;
00186 };
00187 
00188 enum RandomizedSpriteGroupCompareMode {
00189   RSG_CMP_ANY,
00190   RSG_CMP_ALL,
00191 };
00192 
00193 struct RandomizedSpriteGroup : SpriteGroup {
00194   RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
00195   ~RandomizedSpriteGroup();
00196 
00197   VarSpriteGroupScope var_scope;  
00198 
00199   RandomizedSpriteGroupCompareMode cmp_mode; 
00200   byte triggers;
00201   byte count;
00202 
00203   byte lowest_randbit; 
00204   byte num_groups; 
00205 
00206   const SpriteGroup **groups; 
00207 
00208 protected:
00209   const SpriteGroup *Resolve(ResolverObject &object) const;
00210 };
00211 
00212 
00213 /* This contains a callback result. A failed callback has a value of
00214  * CALLBACK_FAILED */
00215 struct CallbackResultSpriteGroup : SpriteGroup {
00221   CallbackResultSpriteGroup(uint16 value, bool grf_version8) :
00222     SpriteGroup(SGT_CALLBACK),
00223     result(value)
00224   {
00225     /* Old style callback results (only valid for version < 8) have the highest byte 0xFF so signify it is a callback result.
00226      * New style ones only have the highest bit set (allows 15-bit results, instead of just 8) */
00227     if (!grf_version8 && (this->result >> 8) == 0xFF) {
00228       this->result &= ~0xFF00;
00229     } else {
00230       this->result &= ~0x8000;
00231     }
00232   }
00233 
00234   uint16 result;
00235   uint16 GetCallbackResult() const { return this->result; }
00236 };
00237 
00238 
00239 /* A result sprite group returns the first SpriteID and the number of
00240  * sprites in the set */
00241 struct ResultSpriteGroup : SpriteGroup {
00248   ResultSpriteGroup(SpriteID sprite, byte num_sprites) :
00249     SpriteGroup(SGT_RESULT),
00250     sprite(sprite),
00251     num_sprites(num_sprites)
00252   {
00253   }
00254 
00255   SpriteID sprite;
00256   byte num_sprites;
00257   SpriteID GetResult() const { return this->sprite; }
00258   byte GetNumResults() const { return this->num_sprites; }
00259 };
00260 
00264 struct TileLayoutSpriteGroup : SpriteGroup {
00265   TileLayoutSpriteGroup() : SpriteGroup(SGT_TILELAYOUT) {}
00266   ~TileLayoutSpriteGroup() {}
00267 
00268   NewGRFSpriteLayout dts;
00269 
00270   const DrawTileSprites *ProcessRegisters(uint8 *stage) const;
00271 };
00272 
00273 struct IndustryProductionSpriteGroup : SpriteGroup {
00274   IndustryProductionSpriteGroup() : SpriteGroup(SGT_INDUSTRY_PRODUCTION) {}
00275 
00276   uint8 version;
00277   int16 subtract_input[3];  // signed
00278   uint16 add_output[2];     // unsigned
00279   uint8 again;
00280 };
00281 
00288 struct ScopeResolver {
00289   ResolverObject &ro; 
00290 
00291   ScopeResolver(ResolverObject &ro);
00292   virtual ~ScopeResolver();
00293 
00294   virtual uint32 GetRandomBits() const;
00295   virtual uint32 GetTriggers() const;
00296   virtual void SetTriggers(int triggers) const;
00297 
00298   virtual uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
00299   virtual void StorePSA(uint reg, int32 value);
00300 };
00301 
00308 struct ResolverObject {
00309   ResolverObject(const GRFFile *grffile, CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
00310   virtual ~ResolverObject();
00311 
00312   ScopeResolver default_scope; 
00313 
00314   CallbackID callback;        
00315   uint32 callback_param1;     
00316   uint32 callback_param2;     
00317 
00318   byte trigger;
00319 
00320   uint32 last_value;          
00321   uint32 reseed[VSG_END];     
00322 
00323   const GRFFile *grffile;     
00324   const SpriteGroup *root_spritegroup; 
00325 
00330   const SpriteGroup *Resolve()
00331   {
00332     return SpriteGroup::Resolve(this->root_spritegroup, *this);
00333   }
00334 
00339   uint16 ResolveCallback()
00340   {
00341     const SpriteGroup *result = Resolve();
00342     return result != NULL ? result->GetCallbackResult() : CALLBACK_FAILED;
00343   }
00344 
00345   virtual const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
00346 
00347   virtual ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0);
00348 
00354   uint32 GetReseedSum() const
00355   {
00356     uint32 sum = 0;
00357     for (VarSpriteGroupScope vsg = VSG_BEGIN; vsg < VSG_END; vsg++) {
00358       sum |= this->reseed[vsg];
00359     }
00360     return sum;
00361   }
00362 
00367   void ResetState()
00368   {
00369     this->last_value = 0;
00370     this->trigger    = 0;
00371     memset(this->reseed, 0, sizeof(this->reseed));
00372   }
00373 };
00374 
00375 #endif /* NEWGRF_SPRITEGROUP_H */