1 /*
2 * OpenBOR - http://www.chronocrash.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2014 OpenBOR Team
7 */
8
9 // sprite with individual 32bit palette
10 /////////////////////////////////////////////////////////////////////////////
11 #include <stdio.h>
12 #include <string.h>
13 #include "globals.h"
14 #include "types.h"
15 #include "sprite.h"
16 /////////////////////////////////////////////////////////////////////////////
17
18
putsprite_(unsigned * dest,int x,int xmin,int xmax,int * linetab,unsigned * palette,int h,int screenwidth)19 static void putsprite_(
20 unsigned *dest, int x, int xmin, int xmax, int *linetab, unsigned *palette, int h, int screenwidth
21 )
22 {
23 for(; h > 0; h--, dest += screenwidth)
24 {
25 register int lx = x;
26 unsigned char *data = ((unsigned char *)linetab) + (*linetab);
27 linetab++;
28 while(lx < xmax)
29 {
30 register int count = *data++;
31 if(count == 0xFF)
32 {
33 break;
34 }
35 lx += count;
36 if(lx >= xmax)
37 {
38 break;
39 }
40 count = *data++;
41 if(!count)
42 {
43 continue;
44 }
45 if((lx + count) <= xmin)
46 {
47 lx += count;
48 data += count;
49 continue;
50 }
51 if(lx < xmin)
52 {
53 int diff = lx - xmin;
54 count += diff;
55 data -= diff;
56 lx = xmin;
57 }
58 if((lx + count) > xmax)
59 {
60 count = xmax - lx;
61 }
62 for(; count > 0; count--)
63 {
64 dest[lx++] = palette[*data++];
65 }
66 //u32pcpy(dest+lx, data, palette, count);
67 //lx+=count;
68 //data+=count;
69 }
70 }
71 }
72
putsprite_flip_(unsigned * dest,int x,int xmin,int xmax,int * linetab,unsigned * palette,int h,int screenwidth)73 static void putsprite_flip_(
74 unsigned *dest, int x, int xmin, int xmax, int *linetab, unsigned *palette, int h, int screenwidth
75 )
76 {
77 for(; h > 0; h--, dest += screenwidth)
78 {
79 register int lx = x;
80 unsigned char *data = ((unsigned char *)linetab) + (*linetab);
81 linetab++;
82 while(lx > xmin)
83 {
84 register int count = *data++;
85 if(count == 0xFF)
86 {
87 break;
88 }
89 lx -= count;
90 if(lx <= xmin)
91 {
92 break;
93 }
94 count = *data++;
95 if(!count)
96 {
97 continue;
98 }
99 if((lx - count) >= xmax)
100 {
101 lx -= count;
102 data += count;
103 continue;
104 }
105 if(lx > xmax)
106 {
107 int diff = (lx - xmax);
108 count -= diff;
109 data += diff;
110 lx = xmax;
111 }
112 if((lx - count) < xmin)
113 {
114 count = lx - xmin;
115 }
116 for(; count > 0; count--)
117 {
118 dest[--lx] = palette[*data++];
119 }
120 //--lx;
121 //u32revpcpy(dest+lx, data, palette, count);
122 //lx-=count-1;
123 //data+=count;
124 }
125 }
126 }
127
128
129 //src high dest low
putsprite_blend_(unsigned * dest,int x,int xmin,int xmax,int * linetab,unsigned * palette,int h,int screenwidth,unsigned (* blendfp)(unsigned,unsigned))130 static void putsprite_blend_(
131 unsigned *dest, int x, int xmin, int xmax, int *linetab, unsigned *palette, int h, int screenwidth,
132 unsigned (*blendfp)(unsigned, unsigned)
133 )
134 {
135 for(; h > 0; h--, dest += screenwidth)
136 {
137 register int lx = x;
138 unsigned char *data = ((unsigned char *)linetab) + (*linetab);
139 linetab++;
140 while(lx < xmax)
141 {
142 register int count = *data++;
143 if(count == 0xFF)
144 {
145 break;
146 }
147 lx += count;
148 if(lx >= xmax)
149 {
150 break;
151 }
152 count = *data++;
153 if(!count)
154 {
155 continue;
156 }
157 if((lx + count) <= xmin)
158 {
159 lx += count;
160 data += count;
161 continue;
162 }
163 if(lx < xmin)
164 {
165 int diff = lx - xmin;
166 count += diff;
167 data -= diff;
168 lx = xmin;
169 }
170 if((lx + count) > xmax)
171 {
172 count = xmax - lx;
173 }
174 for(; count > 0; count--, lx++)
175 {
176 dest[lx] = blendfp(palette[*data++], dest[lx]);
177 }
178 }
179 }
180 }
181
putsprite_blend_flip_(unsigned * dest,int x,int xmin,int xmax,int * linetab,unsigned * palette,int h,int screenwidth,unsigned (* blendfp)(unsigned,unsigned))182 static void putsprite_blend_flip_(
183 unsigned *dest, int x, int xmin, int xmax, int *linetab, unsigned *palette, int h, int screenwidth,
184 unsigned (*blendfp)(unsigned, unsigned)
185 )
186 {
187 for(; h > 0; h--, dest += screenwidth)
188 {
189 register int lx = x;
190 unsigned char *data = ((unsigned char *)linetab) + (*linetab);
191 linetab++;
192 while(lx > xmin)
193 {
194 register int count = *data++;
195 if(count == 0xFF)
196 {
197 break;
198 }
199 lx -= count;
200 if(lx <= xmin)
201 {
202 break;
203 }
204 count = *data++;
205 if(!count)
206 {
207 continue;
208 }
209 if((lx - count) >= xmax)
210 {
211 lx -= count;
212 data += count;
213 continue;
214 }
215 if(lx > xmax)
216 {
217 int diff = (lx - xmax);
218 count -= diff;
219 data += diff;
220 lx = xmax;
221 }
222 if((lx - count) < xmin)
223 {
224 count = lx - xmin;
225 }
226 for(; count > 0; count--)
227 {
228 --lx;
229 dest[lx] = blendfp(palette[*data++], dest[lx]);
230 }
231 }
232 }
233 }
234
235 //src high dest low
putsprite_mask_(unsigned * dest,int x,int xmin,int xmax,int * linetab,unsigned * palette,int h,int screenwidth,int * masklinetab)236 static void putsprite_mask_(
237 unsigned *dest, int x, int xmin, int xmax, int *linetab, unsigned *palette, int h, int screenwidth,
238 int *masklinetab
239 )
240 {
241 for(; h > 0; h--, dest += screenwidth)
242 {
243 register int lx = x;
244 unsigned char *data = ((unsigned char *)linetab) + (*linetab);
245 linetab++;
246 unsigned char *maskdata = ((unsigned char *)masklinetab) + (*masklinetab);
247 masklinetab++;
248 while(lx < xmax)
249 {
250 register int count = *data++;
251 maskdata++;
252 if(count == 0xFF)
253 {
254 break;
255 }
256 lx += count;
257 if(lx >= xmax)
258 {
259 break;
260 }
261 count = *data++;
262 maskdata++;
263 if(!count)
264 {
265 continue;
266 }
267 if((lx + count) <= xmin)
268 {
269 lx += count;
270 data += count;
271 maskdata += count;
272 continue;
273 }
274 if(lx < xmin)
275 {
276 int diff = lx - xmin;
277 count += diff;
278 data -= diff;
279 maskdata -= diff;
280 lx = xmin;
281 }
282 if((lx + count) > xmax)
283 {
284 count = xmax - lx;
285 }
286 for(; count > 0; count--, lx++)
287 {
288 dest[lx] = blend_channel32(palette[*data++], dest[lx], *maskdata++);
289 }
290 }
291 }
292 }
293
putsprite_mask_flip_(unsigned * dest,int x,int xmin,int xmax,int * linetab,unsigned * palette,int h,int screenwidth,int * masklinetab)294 static void putsprite_mask_flip_(
295 unsigned *dest, int x, int xmin, int xmax, int *linetab, unsigned *palette, int h, int screenwidth,
296 int *masklinetab
297 )
298 {
299 for(; h > 0; h--, dest += screenwidth)
300 {
301 register int lx = x;
302 unsigned char *data = ((unsigned char *)linetab) + (*linetab);
303 linetab++;
304 unsigned char *maskdata = ((unsigned char *)masklinetab) + (*masklinetab);
305 masklinetab++;
306 while(lx > xmin)
307 {
308 register int count = *data++;
309 maskdata++;
310 if(count == 0xFF)
311 {
312 break;
313 }
314 lx -= count;
315 if(lx <= xmin)
316 {
317 break;
318 }
319 count = *data++;
320 maskdata++;
321 if(!count)
322 {
323 continue;
324 }
325 if((lx - count) >= xmax)
326 {
327 lx -= count;
328 data += count;
329 maskdata += count;
330 continue;
331 }
332 if(lx > xmax)
333 {
334 int diff = (lx - xmax);
335 count -= diff;
336 data += diff;
337 maskdata += diff;
338 lx = xmax;
339 }
340 if((lx - count) < xmin)
341 {
342 count = lx - xmin;
343 }
344 for(; count > 0; count--)
345 {
346 --lx;
347 dest[lx] = blend_channel32(palette[*data++], dest[lx], *maskdata++);
348 }
349 }
350 }
351 }
352
353 /////////////////////////////////////////////////////////////////////////////
354
putsprite_x8p32(int x,int y,int is_flip,s_sprite * sprite,s_screen * screen,unsigned * remap,blend32fp blend)355 void putsprite_x8p32(
356 int x, int y, int is_flip, s_sprite *sprite, s_screen *screen,
357 unsigned *remap, blend32fp blend
358 )
359 {
360 int *linetab, *masklinetab = NULL;
361 int w, h;
362 unsigned *dest;
363 unsigned *m;
364 // Get screen size
365 int screenwidth = screen->width;
366 int xmin = useclip ? MAX(clipx1, 0) : 0,
367 xmax = useclip ? MIN(clipx2, screen->width) : screen->width,
368 ymin = useclip ? MAX(clipy1, 0) : 0,
369 ymax = useclip ? MIN(clipy2, screen->height) : screen->height;
370 // Adjust coords for centering
371 if(is_flip)
372 {
373 x += sprite->centerx;
374 }
375 else
376 {
377 x -= sprite->centerx;
378 }
379 y -= sprite->centery;
380 // Get sprite dimensions
381 w = sprite->width;
382 h = sprite->height;
383 // trivial clip all directions
384 if(is_flip)
385 {
386 if(x - w >= xmax)
387 {
388 return;
389 }
390 if(x <= xmin)
391 {
392 return;
393 }
394 }
395 else
396 {
397 if(x >= xmax)
398 {
399 return;
400 }
401 if((x + w) <= xmin)
402 {
403 return;
404 }
405 }
406 if(y >= ymax)
407 {
408 return;
409 }
410 if((y + h) <= ymin)
411 {
412 return;
413 }
414 // Init line table pointer
415 linetab = (int *)(sprite->data);
416 if(sprite->mask)
417 {
418 masklinetab = (int *)(sprite->mask->data);
419 //if(w!=sprite->mask->width) { printf("Wrong mask width. %i %i\n", w, sprite->mask->width); return; }
420 //if(h!=sprite->mask->height) { printf("Wrong mask height. %i %i\n", h, sprite->mask->height); return; }
421 }
422 // clip top
423 if(y < ymin)
424 {
425 int diff = y - ymin;
426 h += diff; // subtract from height
427 linetab -= diff; // add to linetab
428 masklinetab -= diff;
429 y = ymin; // add to y
430 }
431 // clip bottom
432 if((y + h) > ymax)
433 {
434 h = ymax - y;
435 }
436 // calculate destination pointer
437 dest = ((unsigned *)(screen->data)) + y * screenwidth;
438 if(remap)
439 {
440 m = remap;
441 }
442 else
443 {
444 m = (unsigned *)sprite->palette;
445 }
446 if(sprite->mask)
447 {
448 if(is_flip)
449 {
450 putsprite_mask_flip_ (dest, x, xmin, xmax, linetab, m, h, screenwidth, masklinetab);
451 }
452 else
453 {
454 putsprite_mask_ (dest, x, xmin, xmax, linetab, m, h, screenwidth, masklinetab);
455 }
456 }
457 else if(blend)
458 {
459 if(is_flip)
460 {
461 putsprite_blend_flip_(dest, x, xmin, xmax, linetab, m , h, screenwidth, blend);
462 }
463 else
464 {
465 putsprite_blend_ (dest, x, xmin, xmax , linetab, m , h, screenwidth, blend);
466 }
467 }
468 else
469 {
470 if(is_flip)
471 {
472 putsprite_flip_ (dest, x, xmin, xmax, linetab, m , h, screenwidth);
473 }
474 else
475 {
476 putsprite_ (dest, x, xmin, xmax , linetab, m , h, screenwidth);
477 }
478 }
479 }
480
481 /////////////////////////////////////////////////////////////////////////////
482
483