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