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