1 #include <string.h>
2 #include <ctype.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <unistd.h>
6
7 #ifndef WIN32
8 #include "config.h"
9 #endif
10
11 #include "sprite.h"
12 #include "blit.h"
13 #include "data.h"
14 #include "console.h"
15 #include "cfg.h"
16 #include "error.h"
17
18
19
20 /* allocate memory for screenbuffer */
init_sprites(void)21 void init_sprites(void)
22 {
23 init_blit();
24 }
25
shutdown_sprites(void)26 void shutdown_sprites(void)
27 {
28 shutdown_blit();
29 }
30
31
32 /* write visible window of playing area into screenbuffer */
show_window(int x,int y)33 void show_window(int x,int y)
34 {
35 int a,loffs,roffs;
36 int prec2=y*AREA_X;
37
38 if (x+SCREEN_X<=0)return;
39 if (y+SCREEN_Y<=0)return;
40
41 loffs=x<0?-x:0;
42 roffs=x+SCREEN_X>AREA_X?x+SCREEN_X-AREA_X:0;
43 #ifdef TRI_D
44 switch (tri_d)
45 {
46 case 0: /* normal part */
47 for(a=(y<0?-y:0);a<SCREEN_Y&&(y+a)<AREA_Y;a++)
48 {
49 int prec=a*SCREEN_X;
50 int prec1=a*AREA_X;
51
52 memcpy(screen+prec+loffs,area+loffs+x+prec2+prec1,SCREEN_X-loffs-roffs);
53 memcpy(screen_a+prec+loffs,area_a+loffs+x+prec2+prec1,SCREEN_X-loffs-roffs);
54 }
55 break;
56
57 case 1: /* 3d part */
58 memset(screen2_a,0,SCREEN_X*SCREEN_Y);
59 memset(screen2,0,SCREEN_X*SCREEN_Y);
60 for(a=(y<0?-y:0);a<SCREEN_Y&&(y+a)<AREA_Y;a++)
61 {
62 int b;
63 int prec=a*SCREEN_X;
64 int prec1=a*AREA_X;
65
66 for (b=0;b<SCREEN_X-loffs-roffs;b++)
67 {
68 int offs;
69 int prec4=loffs+x+prec2+prec1+b;
70
71 switch((area_a[prec4])&240)
72 {
73 case TYPE_BACKGROUND:
74 offs=-1;
75 break;
76
77 case TYPE_FOREGROUND:
78 case TYPE_JUMP_FOREGROUND:
79 offs=1;
80 break;
81
82 default:
83 offs=0;
84 break;
85 }
86
87 if (offs!=1&&(!area[prec4]||area[prec4]==' '))continue;
88
89 if ((b+offs+loffs)<0||(loffs+b+offs)>=SCREEN_X)continue;
90 screen2[prec+loffs+b+offs]=area[prec4];
91 screen2_a[prec+loffs+b+offs]=area_a[prec4];
92 }
93 }
94 break;
95 }
96 #else
97 for(a=(y<0?-y:0);a<SCREEN_Y&&(y+a)<AREA_Y;a++)
98 {
99 int prec=a*SCREEN_X;
100 int prec1=a*AREA_X;
101
102 memcpy(screen+prec+loffs,area+loffs+x+prec2+prec1,SCREEN_X-loffs-roffs);
103 memcpy(screen_a+prec+loffs,area_a+loffs+x+prec2+prec1,SCREEN_X-loffs-roffs);
104 }
105 #endif
106 }
107
108
109 /* write one scanline of a bitmap to given memory */
110 #ifdef HAVE_INLINE
111 inline void
112 #else
113 void
114 #endif
put_line(int xs,int ys,unsigned char * scrn,unsigned char * attr,int x,int y,struct line * l,unsigned char type,unsigned char plastic)115 put_line(int xs, int ys,unsigned char *scrn,unsigned char *attr,int x,int y,struct line *l,unsigned char type,unsigned char plastic)
116 {
117 int a,b=xs*y;
118 if (y>=ys||y<0)return;
119 for (a=0;a<l->len&&x+a<xs;a++)
120 {
121 if (!l->attr[a])continue;
122 if ( plastic&&
123 ((attr[x+a+b]&240)==TYPE_FOREGROUND||
124 (attr[x+a+b]&240)==TYPE_JUMP_FOREGROUND)
125 ) continue;
126 if (x+a<0)continue;
127 scrn[x+a+b]=l->bmp[a];
128 attr[x+a+b]=(l->attr[a])|type;
129 }
130 }
131
132 /* put image to given memory */
133 #ifdef HAVE_INLINE
134 inline void
135 #else
136 void
137 #endif
_put_sprite(int xs,int ys,unsigned char * scrn,unsigned char * attr,int x,int y,struct pos * p,unsigned char type,unsigned char plastic)138 _put_sprite(int xs, int ys, unsigned char *scrn,unsigned char *attr,int x,int y,struct pos *p,unsigned char type,unsigned char plastic)
139 {
140 int a;
141 for (a=0;a<p->n;a++)
142 put_line(xs,ys,scrn,attr,x+p->xo,a+y+p->yo,p->lines+a,type,plastic);
143 }
144
145 /* put image into screenbuffer */
146 #ifdef HAVE_INLINE
147 inline void
148 #else
149 void
150 #endif
put_sprite(int x,int y,struct pos * p,unsigned char plastic)151 put_sprite(int x, int y, struct pos *p,unsigned char plastic)
152 {
153 unsigned char *sc,*at;
154 #ifdef TRI_D
155 sc=(TRI_D_ON&&tri_d)?screen2:screen;
156 at=(TRI_D_ON&&tri_d)?screen2_a:screen_a;
157 #else
158 sc=screen;
159 at=screen_a;
160 #endif
161 _put_sprite(SCREEN_X,SCREEN_Y,sc,at,x,y,p,0,plastic);
162 }
163
164
165 /* ancillary function for converting color from file notation to value 0-15 */
_conv_color(int c)166 int _conv_color(int c)
167 {
168 int a=tolower(c);
169 if (a>='a'&&a<='f')return 10+a-'a';
170 if (a>='0'&&a<='9')return a-'0';
171 /* space or other character is blank attr */
172 return 0;
173 }
174
175
176 /* load sprite from a file */
load_sprite(unsigned char * filename,struct sprite * s)177 void load_sprite(unsigned char * filename,struct sprite *s)
178 {
179 #define CURP (s->n_positions-1)
180 #define CURL (s->positions[CURP].n-1)
181 FILE *f;
182 int x,a;
183 static unsigned char buffer[8192];
184 char *p,*q;
185 int step=0; /*0=expecting 'p', 1=expecting 'l', 2=expecting 'a', 3=expecting 'p' or 's' or 'l', 4=expecting end */
186
187 s->positions=DUMMY;
188 s->n_positions=0;
189
190 if (!(f=fopen(filename,"rb")))
191 {
192 chdir(DATA_PATH);
193 }
194 if (!(f=fopen(filename,"rb")))
195 {
196 chdir(DATA_PATH "/../");
197 }
198 if (!(f=fopen(filename,"rb")))
199 {
200 unsigned char msg[256];
201 snprintf(msg,256,"Error opening file \"%s\"!\n",filename);
202 ERROR(msg);
203 EXIT(1);
204 }
205 while(fgets(buffer,8191,f))
206 {
207 x=strlen(buffer);
208 if (buffer[x-1]==10)buffer[x-1]=0;
209 switch(*buffer)
210 {
211 case 0:
212 goto skip;
213
214 case '#': /* comment */
215 break;
216
217 case 'p':
218 if (step!=0&&step!=3)
219 {
220 unsigned char msg[256];
221 snprintf(msg,256,"Syntax error in file \"%s\".\n",filename);
222 ERROR(msg);
223 EXIT(1);
224 }
225 step=1;
226 s->n_positions++;
227 s->positions=mem_realloc(s->positions,s->n_positions*sizeof(struct pos));
228 if (!s->positions)
229 {
230 ERROR("Memory allocation error!\n");
231 EXIT(1);
232 }
233 s->positions[CURP].n=0;
234 s->positions[CURP].lines=0;
235 s->n_steps=0;
236 s->steps=0;
237 s->positions[CURP].xo=strtol(buffer+1,&p,0);
238 s->positions[CURP].yo=strtol(p+1,&q,0);
239 break;
240
241 case 'l':
242 if (step!=1&&step!=3)
243 {
244 unsigned char msg[256];
245 snprintf(msg,256,"Syntax error in file \"%s\".\n",filename);
246 ERROR(msg);
247 EXIT(1);
248 }
249 step=2;
250 if (!(s->positions[CURP].n))s->positions[CURP].lines=DUMMY;
251 s->positions[CURP].n++;
252 s->positions[CURP].lines=mem_realloc(s->positions[CURP].lines,s->positions[CURP].n*sizeof(struct line));
253 if (!s->positions[CURP].lines)
254 {
255 ERROR("Memory allocation error!\n");
256 EXIT(1);
257 }
258 s->positions[CURP].lines[CURL].len=strlen(buffer+1);
259 if (!s->positions[CURP].lines[CURL].len)break; /* empty line, we have nothing to do */
260 s->positions[CURP].lines[CURL].bmp=mem_alloc(s->positions[CURP].lines[CURL].len);
261 if (!s->positions[CURP].lines[CURL].bmp)
262 {
263 ERROR("Memory allocation error!\n");
264 EXIT(1);
265 }
266 memcpy(s->positions[CURP].lines[CURL].bmp,buffer+1,s->positions[CURP].lines[CURL].len);
267 break;
268
269 case 'a':
270 if (step!=2)
271 {
272 unsigned char msg[256];
273 snprintf(msg,256,"Syntax error in file \"%s\".\n",filename);
274 ERROR(msg);
275 EXIT(1);
276 }
277 step=3;
278 /* UGH, co to tady je??????? */
279 if (!s->positions[CURP].lines)
280 {
281 ERROR("Memory allocation error!\n");
282 EXIT(1);
283 }
284 if (!s->positions[CURP].lines[CURL].len)break; /* empty line, we have nothing to do */
285 s->positions[CURP].lines[CURL].attr=mem_alloc(s->positions[CURP].lines[CURL].len);
286 if (!s->positions[CURP].lines[CURL].attr)
287 {
288 ERROR("Memory allocation error!\n");
289 EXIT(1);
290 }
291 x=strlen(buffer+1);
292 if (x>s->positions[CURP].lines[CURL].len)x=s->positions[CURP].lines[CURL].len;
293 for (a=0;a<x;a++)
294 s->positions[CURP].lines[CURL].attr[a]=_conv_color(buffer[1+a]);
295 memset(s->positions[CURP].lines[CURL].attr+x,0,s->positions[CURP].lines[CURL].len-x);
296 break;
297
298 case 's':
299 if (step!=3)
300 {
301 unsigned char msg[256];
302 snprintf(msg,256,"Syntax error in file \"%s\".\n",filename);
303 ERROR(msg);
304 EXIT(1);
305 }
306 step=4;
307 for(q=buffer,p=buffer+1;*q&&*q!=10;*q==','?p=q+1:0)
308 {
309 x=strtol(p,&q,0);
310 if (x<0||x>CURP)
311 {
312 unsigned char txt[256];
313
314 snprintf(txt,256,"Error loading sprite \"%s\". Undefined position %d.\n",filename,x);
315 ERROR(txt);
316 EXIT(1);
317 }
318 if (!(s->n_steps))s->steps=DUMMY;
319 s->n_steps++;
320 s->steps=mem_realloc(s->steps,s->n_steps*sizeof(unsigned short));
321 if (!s->steps)
322 {
323 ERROR("Memory allocation error!\n");
324 EXIT(1);
325 }
326 s->steps[s->n_steps-1]=x;
327 }
328 break;
329
330 default:
331 {
332 unsigned char msg[256];
333 snprintf(msg,256,"Syntax error in file \"%s\"!\n",filename);
334 ERROR(msg);
335 EXIT(1);
336 }
337 }
338 skip: ;
339 }
340 if (step!=4)
341 {
342 unsigned char msg[256];
343 snprintf(msg,256,"Unexpected end of file in \"%s\".\n",filename);
344 ERROR(msg);
345 EXIT(1);
346 }
347 fclose(f);
348 }
349
350
free_line(struct line * line)351 static void free_line(struct line* line)
352 {
353 if(line->len)
354 {
355 mem_free(line->attr);
356 mem_free(line->bmp);
357 }
358 }
359
360
free_pos(struct pos * pos)361 static void free_pos(struct pos *pos)
362 {
363 int a;
364 for (a=0;a<(pos->n);a++)
365 free_line((pos->lines)+a);
366 mem_free(pos->lines);
367 }
368
369
free_sprite(struct sprite * sp)370 void free_sprite(struct sprite*sp)
371 {
372 int a;
373
374 for (a=0;a<(sp->n_positions);a++)
375 free_pos((sp->positions)+a);
376
377 if (sp->n_steps){mem_free(sp->steps);mem_free(sp->positions);}
378 }
379