1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * 22 * Based on the original sources 23 * Faery Tale II -- The Halls of the Dead 24 * (c) 1993-1996 The Wyrmkeep Entertainment Co. 25 */ 26 27 #ifndef SAGA2_SPRITE_H 28 #define SAGA2_SPRITE_H 29 30 #include "saga2/rect.h" 31 32 namespace Saga2 { 33 34 class gPort; 35 class gPixelMap; 36 37 /* ===================================================================== * 38 Basic sprite structures 39 * ===================================================================== */ 40 41 // Sprite: A structure representing a single sprite 42 43 struct Sprite { 44 Extent16 size; // size of sprite 45 Point16 offset; // sprite origin point 46 byte *_data; 47 uint32 _dataSize; 48 49 Sprite(Common::SeekableReadStream *stream); 50 ~Sprite(); 51 52 // sprite data follows. 53 }; 54 55 // SpriteSet: A bunch of sprites in a single resource 56 57 struct SpriteSet { 58 uint32 count; // number of images in the range 59 Sprite **_sprites; 60 // (variable-length array) 61 // sprite structures follow table 62 63 SpriteSet(Common::SeekableReadStream *stream); 64 ~SpriteSet(); 65 66 // Member function to return a sprite from the set spriteSpriteSet67 Sprite *sprite(int16 index) { 68 return _sprites[index]; 69 } 70 71 // Sprite &operator[]( int32 index ) 72 // { 73 // return (Sprite *)( (uint8 *)this + offsets[index] ); 74 // } 75 76 }; 77 78 extern SpriteSet *objectSprites, // object sprites 79 *mentalSprites, // intagible object sprites 80 *weaponSprites[], // weapon sprites 81 *missileSprites; // missile sprites 82 83 /* ===================================================================== * 84 Describes the facing directions of actor sprites 85 * ===================================================================== */ 86 87 enum spriteFacingDirections { 88 sprFaceDown = 0, 89 sprFaceDownLeft, 90 sprFaceLeft, 91 sprFaceUpLeft, 92 sprFaceUp 93 }; 94 95 /* ===================================================================== * 96 ActorPose: Describes an element of a choreographed action 97 * ===================================================================== */ 98 99 const int numPoseFacings = 8; 100 101 // Describes a single entry in an actor sequence 102 103 struct ActorPose { 104 105 // Sequence element flags 106 107 enum { 108 // Indicates which of the sprites should be drawn flipped 109 // left-to-right 110 111 actorFlipped = (1 << 0), // actor spr flipped left/right 112 leftObjectFlipped = (1 << 1), // left hand object flipped 113 rightObjectFlipped = (1 << 2), // right hand object flipped 114 115 // Indicates the front-to-back priority of the objects 116 117 leftObjectInFront = (1 << 3), // left object in front of actor 118 rightObjectInFront = (1 << 4), // right object in front of actor 119 leftOverRight = (1 << 5) // left in front of right 120 }; 121 122 uint16 flags; // sequence element flags 123 124 uint8 actorFrameIndex, // actor sprite index 125 actorFrameBank; // which bank actor frame is in 126 uint8 leftObjectIndex, // index of obj in left hand 127 rightObjectIndex; // index of obj in right hand 128 129 Point16 leftObjectOffset, // offset of left-hand obj. 130 rightObjectOffset; // offset of right-hand obj. 131 132 // 14 bytes 133 134 ActorPose(); 135 ActorPose(Common::SeekableReadStream *stream); 136 void load(Common::SeekableReadStream *stream); 137 138 void write(Common::MemoryWriteStreamDynamic *out); 139 }; 140 141 // A choreographed sequence of frames 142 143 struct ActorAnimation { 144 145 // For each facing direction, the offset to the 146 // table of poses for that sequence, and the number of poses 147 // in the sequence. 148 149 uint16 start[numPoseFacings]; 150 uint16 count[numPoseFacings]; 151 152 ActorAnimation(Common::SeekableReadStream *stream); 153 154 // 32 bytes 155 }; 156 157 struct ActorAnimSet { 158 uint32 numAnimations; // number of animations 159 uint32 poseOffset; // offset to poses table 160 161 ActorAnimation **animations; 162 ActorPose **poses; 163 164 uint32 numPoses; 165 }; 166 167 /* ===================================================================== * 168 Sprite color lookup tables 169 * ===================================================================== */ 170 171 typedef uint8 ColorTable[256]; 172 173 // List of color schemes for sprites 174 struct ColorScheme { 175 uint8 bank[11]; 176 uint8 speechColor; 177 char name[32]; 178 ColorSchemeColorScheme179 ColorScheme() {} 180 ColorScheme(Common::SeekableReadStream *stream); 181 }; 182 183 class ColorSchemeList { 184 public: 185 int _count; 186 ColorScheme **_schemes; 187 188 ColorSchemeList(int count, Common::SeekableReadStream *stream); 189 ~ColorSchemeList(); 190 }; 191 192 /* ===================================================================== * 193 Composite sprites (characters made from several component sprites) 194 * ===================================================================== */ 195 196 struct SpriteComponent { 197 Sprite *sp; // the sprite to draw 198 Point16 offset; // offset from given origin 199 uint8 *colorTable; // color lookup table 200 uint8 flipped; // true if horizontally flipped. 201 }; 202 203 enum spriteEffectFlags { 204 sprFXGhosted = (1 << 0), // semi-translucent dither 205 sprFXTerrainMask = (1 << 1), // mask sprite to terrain 206 sprFXGhostIfObscured = (1 << 2) // apply ghosted effect if 207 // obscured by terrain 208 }; 209 210 211 /* ===================================================================== * 212 Object sprite information structure 213 * ===================================================================== */ 214 215 struct ObjectSpriteInfo { 216 Sprite *sp; // object sprite 217 bool flipped; // mirror sprite horizontally 218 }; 219 220 /* ===================================================================== * 221 Actor Appearance 222 * ===================================================================== */ 223 224 // Bits which represent the various "banks" of sprites for 225 // each actor. 226 227 // REM: I think we want more banks than this... 228 229 enum spriteBankNums { 230 sprStandBankNum = 0, 231 sprWalkBankNum, 232 sprRunBankNum, 233 sprKneelBankNum, 234 sprLeapBankNum, 235 sprClimbBankNum, 236 sprTalkBankNum, 237 sprFight1HBankNum, 238 sprFight2HBankNum, 239 sprFireBankNum, 240 sprPassiveBankNum, 241 sprUpStairsBankNum, 242 sprDnStairsBankNum, 243 sprSitBankNum, 244 245 sprBankCount 246 }; 247 248 enum spriteBankBits { 249 sprStandBank = (1 << sprStandBankNum), 250 sprWalkBank = (1 << sprWalkBankNum), 251 sprRunBank = (1 << sprRunBankNum), 252 sprKneelBank = (1 << sprKneelBankNum), 253 sprLeapBank = (1 << sprLeapBankNum), 254 sprClimbBank = (1 << sprClimbBankNum), 255 sprTalkBank = (1 << sprTalkBankNum), 256 sprFight1HBank = (1 << sprFight1HBankNum), 257 sprFight2HBank = (1 << sprFight2HBankNum), 258 sprFireBank = (1 << sprFireBankNum), 259 sprPassiveBank = (1 << sprPassiveBankNum), 260 sprUpStairsBank = (1 << sprUpStairsBankNum), 261 sprDnStairsBank = (1 << sprDnStairsBankNum), 262 sprSitBank = (1 << sprSitBankNum) 263 }; 264 265 // This structure is used to contain all of the items needed 266 // to draw an actor, including sprite set, frame list, and 267 // wielding offsets. 268 // 269 // There is an LRU cache of these structures maintained by 270 // the sprite coordinator. 271 272 class ActorAppearance { 273 public: 274 int16 useCount; // how many actors using this 275 uint32 id; 276 277 ActorAnimSet *poseList; // list of action sequences 278 ColorSchemeList *schemeList; // color remapping info 279 280 SpriteSet *spriteBanks[sprBankCount]; 281 282 void loadSpriteBanks(int16 banksNeeded); 283 284 // Determine if this bank is loaded isBankLoaded(int16 bank)285 bool isBankLoaded(int16 bank) { 286 return spriteBanks[bank] != nullptr; 287 } 288 289 // A request to load a bank. requestBank(int16 bank)290 void requestBank(int16 bank) { 291 // Initiate a load of the sprite bank needed. 292 if (!isBankLoaded(bank)) 293 loadSpriteBanks((int16)(1 << bank)); 294 } 295 animation(int num)296 ActorAnimation *animation(int num) { 297 if (poseList == nullptr) 298 return nullptr; 299 300 if (num >= (int)poseList->numAnimations) { 301 warning("ActorPose:animation(), animation number is too high, %d >= %d", num, poseList->numAnimations); 302 return nullptr; 303 } 304 305 if (poseList) 306 return poseList->animations[num]; 307 308 return nullptr; 309 } 310 pose(ActorAnimation * anim,int dir,int num)311 ActorPose *pose(ActorAnimation *anim, int dir, int num) { 312 if (poseList == nullptr) 313 return nullptr; 314 315 if (num < 0 || num >= anim->count[dir]) 316 num = 0; 317 318 num += anim->start[dir]; 319 320 if (num >= (int)poseList->numPoses) { 321 warning("ActorPose::pose(), pose number is too high, %d >= %d", num, poseList->numPoses); 322 return nullptr; 323 } 324 325 return poseList->poses[num]; 326 } 327 }; 328 329 /* ===================================================================== * 330 Prototypes 331 * ===================================================================== */ 332 333 void initSprites(void); 334 void cleanupSprites(void); 335 336 struct TilePoint; 337 338 // Draw a plain sprite into a gPort, no masking or clipping 339 void DrawSprite(gPort &port, const Point16 &dest, Sprite *sp); 340 341 // Draw a composite sprite with both masking and color mapping 342 void DrawCompositeMaskedSprite( 343 gPort &port, // destination gPort 344 SpriteComponent *scList, // list of components 345 int16 numParts, // number of components 346 const Point16 &destPoint, // where to render to 347 const TilePoint &loc, // location on map 348 int16 effects, // effects flags 349 bool *obscured = NULL); // set if object is obscured by terrain 350 351 // Draw a single sprite with color mapping only 352 void DrawColorMappedSprite( 353 gPort &port, // destination gPort 354 const Point16 &destPoint, // where to render to 355 Sprite *sp, // sprite pointer 356 uint8 *colorTable); // color remapping table 357 358 // Color map a sprite into a gPixelMap. 359 void ExpandColorMappedSprite( 360 gPixelMap &map, // destination gPixelMap 361 Sprite *sp, // sprite pointer 362 uint8 *colorTable); // color remapping table 363 364 // Return a specific pixel from a sprite for mouse hit test 365 uint8 GetSpritePixel( 366 Sprite *sp, // sprite pointer 367 int16 flipped, // true if sprite was flipped 368 const Point16 &testPoint); // where to render to 369 370 // Return the number of visible pixels in a sprite after terrain masking 371 uint16 visiblePixelsInSprite( 372 Sprite *sp, // sprite pointer 373 bool flipped, // is sprite flipped 374 ColorTable colors, // sprite's color table 375 Point16 drawPos, // XY position of sprite 376 TilePoint loc, // UVZ coordinates of sprite 377 uint16 roofID); // ID of ripped roof 378 379 // Assemble a color lookup table 380 void buildColorTable( 381 uint8 *colorTable, // color table to build 382 uint8 *colorOptions, // colors ranges chosen 383 int16 numOptions); 384 385 // Functions to load and release an actor appearance 386 ActorAppearance *LoadActorAppearance(uint32 id, int16 banksNeeded); 387 void ReleaseActorAppearance(ActorAppearance *aa); 388 389 } // end of namespace Saga2 390 391 #endif 392