1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 // sprite with individual 32bit palette
10 /////////////////////////////////////////////////////////////////////////////
11 #include <stdio.h>
12 #include <string.h>
13 #include "types.h"
14 #include "sprite.h"
15 /////////////////////////////////////////////////////////////////////////////
16
17
putsprite_(unsigned * dest,int x,int * linetab,unsigned * palette,int h,int screenwidth)18 static void putsprite_(
19 unsigned *dest, int x, int *linetab, unsigned *palette, int h, int screenwidth
20 ) {
21 for(; h > 0; h--, dest += screenwidth) {
22 register int lx = x;
23 unsigned char *data = ((unsigned char*)linetab) + (*linetab); linetab++;
24 while(lx < screenwidth) {
25 register int count = *data++;
26 if(count == 0xFF) break;
27 lx += count;
28 if(lx >= screenwidth) break;
29 count = *data++;
30 if(!count) continue;
31 if((lx + count) <= 0) { lx += count; data += count; continue; }
32 if(lx < 0) { count += lx; data -= lx; lx = 0; }
33 if((lx + count) > screenwidth) { count = screenwidth - lx; }
34 //for(; count > 0; count--) dest[lx++] = palette[*data++];
35 u32pcpy(dest+lx, data, palette, count);
36 lx+=count;
37 data+=count;
38 }
39 }
40 }
41
putsprite_flip_(unsigned * dest,int x,int * linetab,unsigned * palette,int h,int screenwidth)42 static void putsprite_flip_(
43 unsigned *dest, int x, int *linetab, unsigned* palette, int h, int screenwidth
44 ) {
45 for(; h > 0; h--, dest += screenwidth) {
46 register int lx = x;
47 unsigned char *data = ((unsigned char*)linetab) + (*linetab); linetab++;
48 while(lx > 0) {
49 register int count = *data++;
50 if(count == 0xFF) break;
51 lx -= count;
52 if(lx <= 0) break;
53 count = *data++;
54 if(!count) continue;
55 if((lx - count) >= screenwidth) { lx -= count; data += count; continue; }
56 if(lx > screenwidth) { int diff = (lx - screenwidth); count -= diff; data += diff; lx = screenwidth; }
57 if((lx - count) < 0) { count = lx; }
58 //for(; count > 0; count--) dest[--lx] = palette[*data++];
59 --lx;
60 u32revpcpy(dest+lx, data, palette, count);
61 lx-=count-1;
62 data+=count;
63 }
64 }
65 }
66
67
68 //src high dest low
putsprite_blend_(unsigned * dest,int x,int * linetab,unsigned * palette,int h,int screenwidth,unsigned (* blendfp)(unsigned,unsigned))69 static void putsprite_blend_(
70 unsigned *dest, int x, int *linetab, unsigned* palette, int h, int screenwidth,
71 unsigned (*blendfp)(unsigned, unsigned)
72 ) {
73 for(; h > 0; h--, dest += screenwidth) {
74 register int lx = x;
75 unsigned char *data = ((unsigned char*)linetab) + (*linetab); linetab++;
76 while(lx < screenwidth) {
77 register int count = *data++;
78 if(count == 0xFF) break;
79 lx += count;
80 if(lx >= screenwidth) break;
81 count = *data++;
82 if(!count) continue;
83 if((lx + count) <= 0) { lx += count; data += count; continue; }
84 if(lx < 0) { count += lx; data -= lx; lx = 0; }
85 if((lx + count) > screenwidth) { count = screenwidth - lx; }
86 for(; count > 0; count--, lx++)
87 {
88 dest[lx] = blendfp(palette[*data++], dest[lx]);
89 }
90 }
91 }
92 }
93
putsprite_blend_flip_(unsigned * dest,int x,int * linetab,unsigned * palette,int h,int screenwidth,unsigned (* blendfp)(unsigned,unsigned))94 static void putsprite_blend_flip_(
95 unsigned *dest, int x, int *linetab, unsigned * palette, int h, int screenwidth,
96 unsigned (*blendfp)(unsigned, unsigned)
97 ) {
98 for(; h > 0; h--, dest += screenwidth) {
99 register int lx = x;
100 unsigned char *data = ((unsigned char*)linetab) + (*linetab); linetab++;
101 while(lx > 0) {
102 register int count = *data++;
103 if(count == 0xFF) break;
104 lx -= count;
105 if(lx <= 0) break;
106 count = *data++;
107 if(!count) continue;
108 if((lx - count) >= screenwidth) { lx -= count; data += count; continue; }
109 if(lx > screenwidth) { int diff = (lx - screenwidth); count -= diff; data += diff; lx = screenwidth; }
110 if((lx - count) < 0) { count = lx; }
111 for(; count > 0; count--)
112 { --lx;
113 dest[lx] = blendfp(palette[*data++], dest[lx]);
114 }
115 }
116 }
117 }
118
119 //src high dest low
putsprite_mask_(unsigned * dest,int x,int * linetab,unsigned * palette,int h,int screenwidth,int * masklinetab)120 static void putsprite_mask_(
121 unsigned *dest, int x, int *linetab, unsigned* palette, int h, int screenwidth,
122 int* masklinetab
123 ) {
124 for(; h > 0; h--, dest += screenwidth) {
125 register int lx = x;
126 unsigned char *data = ((unsigned char*)linetab) + (*linetab); linetab++;
127 unsigned char *maskdata = ((unsigned char*)masklinetab) + (*masklinetab); masklinetab++;
128 while(lx < screenwidth) {
129 register int count = *data++; maskdata++;
130 if(count == 0xFF) break;
131 lx += count;
132 if(lx >= screenwidth) break;
133 count = *data++; maskdata++;
134 if(!count) continue;
135 if((lx + count) <= 0) { lx += count; data += count; maskdata += count; continue; }
136 if(lx < 0) { count += lx; data -= lx; maskdata -= lx; lx = 0; }
137 if((lx + count) > screenwidth) { count = screenwidth - lx; }
138 for(; count > 0; count--, lx++)
139 {
140 dest[lx] = blend_channel32(palette[*data++], dest[lx], *maskdata++);
141 }
142 }
143 }
144 }
145
putsprite_mask_flip_(unsigned * dest,int x,int * linetab,unsigned * palette,int h,int screenwidth,int * masklinetab)146 static void putsprite_mask_flip_(
147 unsigned *dest, int x, int *linetab, unsigned * palette, int h, int screenwidth,
148 int *masklinetab
149 ) {
150 for(; h > 0; h--, dest += screenwidth) {
151 register int lx = x;
152 unsigned char *data = ((unsigned char*)linetab) + (*linetab); linetab++;
153 unsigned char *maskdata = ((unsigned char*)masklinetab) + (*masklinetab); masklinetab++;
154 while(lx > 0) {
155 register int count = *data++; maskdata++;
156 if(count == 0xFF) break;
157 lx -= count;
158 if(lx <= 0) break;
159 count = *data++; maskdata++;
160 if(!count) continue;
161 if((lx - count) >= screenwidth) { lx -= count; data += count; maskdata += count; continue; }
162 if(lx > screenwidth) { int diff = (lx - screenwidth); count -= diff; data += diff; maskdata += diff; lx = screenwidth; }
163 if((lx - count) < 0) { count = lx; }
164 for(; count > 0; count--)
165 { --lx;
166 dest[lx] = blend_channel32(palette[*data++], dest[lx], *maskdata++);
167 }
168 }
169 }
170 }
171
172 /////////////////////////////////////////////////////////////////////////////
173
putsprite_x8p32(int x,int y,int is_flip,s_sprite * sprite,s_screen * screen,unsigned * remap,blend32fp blend)174 void putsprite_x8p32(
175 int x, int y, int is_flip, s_sprite *sprite, s_screen *screen,
176 unsigned *remap, blend32fp blend
177 ) {
178 int *linetab, *masklinetab = NULL;
179 int w, h;
180 unsigned *dest;
181 unsigned * m;
182 // Get screen size
183 int screenwidth = screen->width;
184 int screenheight = screen->height;
185 // Adjust coords for centering
186 if(is_flip) x += sprite->centerx;
187 else x -= sprite->centerx;
188 y -= sprite->centery;
189 // Get sprite dimensions
190 w = sprite->width;
191 h = sprite->height;
192 // trivial clip all directions
193 if(is_flip)
194 {
195 if(x-w >= screenwidth) return;
196 if(x <= 0) return;
197 }
198 else
199 {
200 if(x >= screenwidth) return;
201 if((x+w) <= 0) return;
202 }
203 if(y >= screenheight) return;
204 if((y+h) <= 0) return;
205 // Init line table pointer
206 linetab = (int*)(sprite->data);
207 if(sprite->mask) {
208 masklinetab = (int*)(sprite->mask->data);
209 //if(w!=sprite->mask->width) { printf("Wrong mask width. %i %i\n", w, sprite->mask->width); return; }
210 //if(h!=sprite->mask->height) { printf("Wrong mask height. %i %i\n", h, sprite->mask->height); return; }
211 }
212 // clip top
213 if(y < 0) {
214 h += y; // subtract from height
215 linetab -= y; // add to linetab
216 y = 0; // add to y
217 }
218 // clip bottom
219 if((y+h) > screenheight) {
220 h = screenheight - y;
221 }
222 // calculate destination pointer
223 dest = ((unsigned*)(screen->data)) + y*screenwidth;
224 if(remap) m = remap;
225 else m = (unsigned*)sprite->palette;
226 if(sprite->mask) {
227 if(is_flip) putsprite_mask_flip_ (dest, x, linetab, m, h, screenwidth, masklinetab);
228 else putsprite_mask_ (dest, x, linetab, m, h, screenwidth, masklinetab);
229 } else if(blend) {
230 if(is_flip) putsprite_blend_flip_(dest, x, linetab, m , h, screenwidth, blend);
231 else putsprite_blend_ (dest, x , linetab, m , h, screenwidth, blend);
232 } else {
233 if(is_flip) putsprite_flip_ (dest, x, linetab, m , h, screenwidth);
234 else putsprite_ (dest, x , linetab, m , h, screenwidth);
235 }
236 }
237
238 /////////////////////////////////////////////////////////////////////////////
239
240