1 /*------------------------------------------------------------------------.
2 | Copyright 2000  Alexandre Duret-Lutz <duret_g@epita.fr>                 |
3 |                                                                         |
4 | This file is part of Heroes.                                            |
5 |                                                                         |
6 | Heroes is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License version 2 as published by   |
8 | the Free Software Foundation.                                           |
9 |                                                                         |
10 | Heroes is distributed in the hope that it will be useful, but WITHOUT   |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   |
12 | FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   |
13 | for more details.                                                       |
14 |                                                                         |
15 | You should have received a copy of the GNU General Public License along |
16 | with this program; if not, write to the Free Software Foundation, Inc., |
17 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                   |
18 `------------------------------------------------------------------------*/
19 
20 #ifndef HEROES__SPRITES__H
21 #define HEROES__SPRITES__H
22 
23 /*-------------------------------------------------------------------.
24 | This file define an abstraction for sprites, i.e., small blocks of |
25 | pixels that can be pasted in memory (but you knew that).           |
26 `-------------------------------------------------------------------*/
27 
28 #include "video.h"
29 
30 /* Different kind of sprites, they are not all used yet.  These values
31    should be used *internally* by the sprite handling functions.  */
32 enum sprite_kind {
33   S_OPAQUE,			/* opaque (yes!) */
34   S_RLE,			/* transparant */
35   S_RLE_SHADE,			/* transparant, using one line of glenz */
36   S_RLE_ZCOL,			/* transparant, using a kind of
37   				   color-based z-buffer, for explosions */
38   S_RLE_GLENZ,			/* transparant,
39 				   using uniform glenz for the rest */
40   S_RLE_UNIC_SHADE,		/* transparant, using a UNIque opaque Color,
41 				   and one line of glenz */
42   S_RLE_GLENZ_AUTO,		/* transparant, using glenz for some
43 				   known colors (this is slow) */
44   S_PROG,			/* a list of sprites, to draw all at once */
45   S_PROG_WAV			/* like S_PROG but also wave */
46 };
47 
48 typedef union sprite_s a_sprite;
49 
50 typedef void (*sprite_draw_func) (const a_sprite *sprite, a_pixel *dest);
51 
52 /*-------------------------------------------------------------------.
53 | Because the various flavor of sprites are not drawn the same way,  |
54 | there exist various drawing functions.  There is one drawing       |
55 | function for each kind of sprite.                                  |
56 |                                                                    |
57 | Each sprite contains a pointer to its drawing function.  Therefore |
58 | the DRAW_SPRITE macro below is the generic way to draw a sprite.   |
59 | It is more efficient, however, to call the right drawing function  |
60 | if you know it at compile time.                                    |
61 `-------------------------------------------------------------------*/
62 
63 #define DRAW_SPRITE(s,dest) ((s)->draw ((s), (dest)))
64 
65 #define SPRITE_FIRST_MEMBER			\
66   sprite_draw_func	draw
67 
68 
69 #define SPRITE_COMMON_MEMBERS				\
70   SPRITE_FIRST_MEMBER;					\
71   enum sprite_kind	kind	/* kind of sprite */
72 
73 struct sprite_common_s {
74   SPRITE_COMMON_MEMBERS;
75 };
76 
77 typedef struct sprite_prog_list_s a_sprite_prog_list; /* see sprprog.c */
78 
79 struct sprite_prog_s {
80   SPRITE_COMMON_MEMBERS;
81   a_sprite_prog_list *list;
82 };
83 
84 #define SPRITE_RLE_MEMBERS						\
85   SPRITE_COMMON_MEMBERS;						\
86 									\
87   /* The code of an rle-sprite is a sequence of				\
88        1 a_u8: number m of transparent pixels to skip			\
89        1 a_u8: number n of bytes to write				\
90        n a_u8: actual bytes to write					\
91      The end of a line can be announced using m=0 and n=0,		\
92      and the code MUST terminate by m=0 and n=0.			\
93   */									\
94   a_u8*		code;							\
95 									\
96   /* a pointer the byte right after the end of code,			\
97      in order to known where to stop. */				\
98   a_u8*		end_code;						\
99 									\
100   /* the number of byte to skip to from the end of a line to the	\
101      beginning of the next one */					\
102   unsigned int	line_skip
103 
104 struct sprite_rle_s {
105   SPRITE_RLE_MEMBERS;
106 };
107 
108 struct sprite_rle_shade_s {
109   /* shaded sprites reuse the member of RLE, but the code used
110      is extended.  The code of a shaded sprite is a sequence of
111        1 a_u8: number m of transparent pixels to skip
112        1 a_u8: number n of bytes to write
113        n a_u8: actual bytes to write
114        1 a_u8: number s of glenz pixels to draw right after
115      The end of a line can be announced using m=0, n=0, and s=0,
116      and the code MUST terminate by m=0, n=0, and s=0.
117   */
118   SPRITE_RLE_MEMBERS;
119   a_pixel*	glenz;
120 };
121 
122 struct sprite_rle_glenz_s {
123   /* glenz sprites reuse the member of RLE, but the code used
124      is extended.  The code of a shaded sprite is a sequence of
125        1 a_u8: number m of transparent pixels to skip
126        1 a_u8: number n of glenz pixels to write
127      The end of a line can be announced using m=0, and n=0,
128      and the code MUST terminate by m=0, and n=0.
129   */
130   SPRITE_RLE_MEMBERS;
131   a_pixel*	glenz;
132 };
133 
134 struct sprite_rle_unic_shade_s {
135   /* shaded sprites reuse the member of RLE, but the code used
136      is extended.  The code of a shaded sprite is a sequence of
137        1 a_u8: number m of transparent pixels to skip
138        1 a_u8: number n of bytes to write
139        1 a_u8: number s of glenz pixels to draw right after
140      The end of a line can be announced using m=0, n=0, and s=0,
141      and the code MUST terminate by m=0, n=0, and s=0.
142   */
143   SPRITE_RLE_MEMBERS;
144   a_pixel*	glenz;
145   a_pixel	color;		/* used to draw opaque pixels */
146 };
147 
148 struct sprite_opaque_s {
149   SPRITE_COMMON_MEMBERS;
150   a_pixel*	data;		/* data to write (concatenated) */
151   a_pixel*	end_data;	/* pointer the pixel right after the last
152 				   in data */
153   int		width;		/* number of data to write per line */
154   int		line_skip;	/* byte to skip at the end of a line, to
155 				   jump to the next one. */
156 };
157 
158 union sprite_s {
159   SPRITE_FIRST_MEMBER;
160   struct sprite_common_s	all;
161   struct sprite_prog_s		prog;
162   struct sprite_rle_s		rle;
163   struct sprite_rle_shade_s	shade;
164   struct sprite_rle_glenz_s	glenz;
165   struct sprite_opaque_s	opaq;
166   struct sprite_rle_unic_shade_s unish;
167 };
168 
169 /* generic sprite freeing function, this will dispatch to the right
170    freeing function */
171 void free_sprite (a_sprite *sprite);
172 
173 #define FREE_SPRITE0(x)				\
174   do {						\
175     if (x) {					\
176       free_sprite (x);				\
177       x = 0;					\
178     }						\
179   } while (0)
180 
181 #endif /* HEROES__SPRITES__H */
182