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