amd64 fixes
[btb/d2x.git] / 2d / bitmap.c
1 /* $Id: bitmap.c,v 1.9 2005-08-02 06:15:08 chris Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Graphical routines for manipulating grs_bitmaps.
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27
28 #include "u_mem.h"
29
30
31 #include "gr.h"
32 #include "grdef.h"
33 #include "u_dpmi.h"
34 #include "error.h"
35
36 #ifdef OGL
37 #include "ogl_init.h"
38 #endif
39
40 void gr_set_bitmap_data (grs_bitmap *bm, unsigned char *data)
41 {
42 #ifdef OGL
43 //      if (bm->bm_data!=data)
44                 ogl_freebmtexture(bm);
45 #endif
46         bm->bm_data = data;
47 }
48
49 grs_bitmap *gr_create_bitmap(int w, int h )
50 {
51         return gr_create_bitmap_raw (w, h, d_malloc( MAX_BMP_SIZE(w, h) ));
52 }
53
54 grs_bitmap *gr_create_bitmap_raw(int w, int h, unsigned char * raw_data )
55 {
56     grs_bitmap *new;
57
58     new = (grs_bitmap *)d_malloc( sizeof(grs_bitmap) );
59         gr_init_bitmap (new, 0, 0, 0, w, h, w, raw_data);
60
61     return new;
62 }
63
64
65 void gr_init_bitmap( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline, unsigned char * data ) // TODO: virtualize
66 {
67         bm->bm_x = x;
68         bm->bm_y = y;
69         bm->bm_w = w;
70         bm->bm_h = h;
71         bm->bm_flags = 0;
72         bm->bm_type = mode;
73         bm->bm_rowsize = bytesperline;
74
75         bm->bm_data = NULL;
76 #ifdef OGL
77         bm->bm_parent=NULL;bm->gltexture=NULL;
78 #endif
79
80 //      if (data != 0)
81                 gr_set_bitmap_data (bm, data);
82 /*
83         else
84                 gr_set_bitmap_data (bm, d_malloc( MAX_BMP_SIZE(w, h) ));
85 */
86
87 #ifdef BITMAP_SELECTOR
88         bm->bm_selector = 0;
89 #endif
90 }
91
92 void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline)
93 {
94         gr_init_bitmap(bm, mode, x, y, w, h, bytesperline, 0);
95         gr_set_bitmap_data(bm, d_malloc( MAX_BMP_SIZE(w, h) ));
96 }
97
98 void gr_init_bitmap_data (grs_bitmap *bm) // TODO: virtulize
99 {
100         bm->bm_data = NULL;
101 #ifdef OGL
102 //      ogl_freebmtexture(bm);//not what we want here.
103         bm->bm_parent=NULL;bm->gltexture=NULL;
104 #endif
105 }
106
107 grs_bitmap *gr_create_sub_bitmap(grs_bitmap *bm, int x, int y, int w, int h )
108 {
109     grs_bitmap *new;
110
111     new = (grs_bitmap *)d_malloc( sizeof(grs_bitmap) );
112         gr_init_sub_bitmap (new, bm, x, y, w, h);
113
114         return new;
115 }
116
117 void gr_free_bitmap(grs_bitmap *bm )
118 {
119         gr_free_bitmap_data (bm);
120         if (bm!=NULL)
121                 d_free(bm);
122 }
123
124 void gr_free_sub_bitmap(grs_bitmap *bm )
125 {
126         if (bm!=NULL)
127         {
128                 d_free(bm);
129         }
130 }
131
132
133 void gr_free_bitmap_data (grs_bitmap *bm) // TODO: virtulize
134 {
135 #ifdef OGL
136         ogl_freebmtexture(bm);
137 #endif
138         if (bm->bm_data != NULL)
139                 d_free (bm->bm_data);
140         bm->bm_data = NULL;
141 }
142
143 void gr_init_sub_bitmap (grs_bitmap *bm, grs_bitmap *bmParent, int x, int y, int w, int h )     // TODO: virtualize
144 {
145         bm->bm_x = x + bmParent->bm_x;
146         bm->bm_y = y + bmParent->bm_y;
147         bm->bm_w = w;
148         bm->bm_h = h;
149         bm->bm_flags = bmParent->bm_flags;
150         bm->bm_type = bmParent->bm_type;
151         bm->bm_rowsize = bmParent->bm_rowsize;
152
153 #ifdef OGL
154         bm->gltexture=bmParent->gltexture;
155         bm->bm_parent=bmParent;
156 #endif
157         {
158                 bm->bm_data = bmParent->bm_data+(unsigned int)((y*bmParent->bm_rowsize)+x);
159         }
160
161 }
162
163 void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count );
164
165 #if !defined(NO_ASM) && defined(__WATCOMC__)
166
167 #pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \
168 "again_ddn:"                                                    \
169         "xor    eax,eax"                                \
170         "mov    al,[esi]"                       \
171         "inc    dword ptr [ebx+eax*4]"          \
172         "mov    al,[edi+eax]"           \
173         "mov    [esi],al"                       \
174         "inc    esi"                                    \
175         "dec    ecx"                                    \
176         "jne    again_ddn"
177
178 #elif !defined(NO_ASM) && defined(__GNUC__)
179
180 inline void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count ) {
181         int dummy[4];
182    __asm__ __volatile__ (
183     "xorl   %%eax,%%eax;"
184 "0:;"
185     "movb   (%%esi), %%al;"
186     "incl   (%%ebx, %%eax, 4);"
187     "movb   (%%edi, %%eax), %%al;"
188     "movb   %%al, (%%esi);"
189     "incl   %%esi;"
190     "decl   %%ecx;"
191     "jne    0b"
192     : "=S" (dummy[0]), "=c" (dummy[1]), "=D" (dummy[2]), "=b" (dummy[3])
193         : "0" (data), "1" (num_pixels), "2" (colormap), "3" (count)
194         : "%eax");
195 }
196
197 #elif !defined(NO_ASM) && defined(_MSC_VER)
198
199 __inline void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count )
200 {
201   __asm {
202         mov esi,[data]
203         mov ecx,[num_pixels]
204         mov edi,[colormap]
205         mov ebx,[count]
206 again_ddn:
207         xor eax,eax
208         mov al,[esi]
209         inc dword ptr [ebx+eax*4]
210         mov al,[edi+eax]
211         mov [esi],al
212         inc esi
213         dec ecx
214         jne again_ddn
215   }
216 }
217
218 #else // NO_ASM or unknown compiler
219
220 void decode_data_asm(ubyte *data, int num_pixels, ubyte *colormap, int *count)
221 {
222         int i;
223         ubyte mapped;
224
225         for (i = 0; i < num_pixels; i++) {
226                 count[*data]++;
227                 mapped = *data;
228                 *data = colormap[mapped];
229                 data++;
230         }
231 }
232
233 #endif
234
235 void gr_set_bitmap_flags (grs_bitmap *pbm, int flags)
236 {
237         pbm->bm_flags = flags;
238 }
239
240 void gr_set_transparent (grs_bitmap *pbm, int bTransparent)
241 {
242         if (bTransparent)
243         {
244                 gr_set_bitmap_flags (pbm, pbm->bm_flags | BM_FLAG_TRANSPARENT);
245         }
246         else
247         {
248                 gr_set_bitmap_flags (pbm, pbm->bm_flags & ~BM_FLAG_TRANSPARENT);
249         }
250 }
251
252 void gr_set_super_transparent (grs_bitmap *pbm, int bTransparent)
253 {
254         if (bTransparent)
255         {
256                 gr_set_bitmap_flags (pbm, pbm->bm_flags & ~BM_FLAG_SUPER_TRANSPARENT);
257         }
258         else
259         {
260                 gr_set_bitmap_flags (pbm, pbm->bm_flags | BM_FLAG_SUPER_TRANSPARENT);
261         }
262 }
263
264 void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq )
265 {
266         int i, r, g, b;
267
268         for (i=0; i<256; i++ )  {
269                 r = *palette++;
270                 g = *palette++;
271                 b = *palette++;
272                 *colormap++ = gr_find_closest_color( r, g, b );
273                 *freq++ = 0;
274         }
275 }
276
277 void gr_remap_bitmap( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color )
278 {
279         ubyte colormap[256];
280         int freq[256];
281
282         if (bmp->bm_type != BM_LINEAR)
283                 return;  //can't do it
284
285         // This should be build_colormap_asm, but we're not using invert table, so...
286         build_colormap_good( palette, colormap, freq );
287
288         if ( (super_transparent_color>=0) && (super_transparent_color<=255))
289                 colormap[super_transparent_color] = 254;
290
291         if ( (transparent_color>=0) && (transparent_color<=255))
292                 colormap[transparent_color] = TRANSPARENCY_COLOR;
293
294         decode_data_asm(bmp->bm_data, bmp->bm_w * bmp->bm_h, colormap, freq );
295
296         if ( (transparent_color>=0) && (transparent_color<=255) && (freq[transparent_color]>0) )
297                 gr_set_transparent (bmp, 1);
298
299         if ( (super_transparent_color>=0) && (super_transparent_color<=255) && (freq[super_transparent_color]>0) )
300                 gr_set_super_transparent (bmp, 0);
301 }
302
303 void gr_remap_bitmap_good( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color )
304 {
305         ubyte colormap[256];
306         int freq[256];
307         build_colormap_good( palette, colormap, freq );
308
309         if ( (super_transparent_color>=0) && (super_transparent_color<=255))
310                 colormap[super_transparent_color] = 254;
311
312         if ( (transparent_color>=0) && (transparent_color<=255))
313                 colormap[transparent_color] = TRANSPARENCY_COLOR;
314
315         if (bmp->bm_w == bmp->bm_rowsize)
316                 decode_data_asm(bmp->bm_data, bmp->bm_w * bmp->bm_h, colormap, freq );
317         else {
318                 int y;
319                 ubyte *p = bmp->bm_data;
320                 for (y=0;y<bmp->bm_h;y++,p+=bmp->bm_rowsize)
321                         decode_data_asm(p, bmp->bm_w, colormap, freq );
322         }
323
324         if ( (transparent_color>=0) && (transparent_color<=255) && (freq[transparent_color]>0) )
325                 gr_set_transparent (bmp, 1);
326
327         if ( (super_transparent_color>=0) && (super_transparent_color<=255) && (freq[super_transparent_color]>0) )
328                 gr_set_super_transparent (bmp, 1);
329 }
330
331 #ifdef BITMAP_SELECTOR
332 int gr_bitmap_assign_selector( grs_bitmap * bmp )
333 {
334         if (!dpmi_allocate_selector( bmp->bm_data, bmp->bm_w*bmp->bm_h, &bmp->bm_selector )) {
335                 bmp->bm_selector = 0;
336                 return 1;
337         }
338         return 0;
339 }
340 #endif
341
342 void gr_bitmap_check_transparency( grs_bitmap * bmp )
343 {
344         int x, y;
345         ubyte * data;
346
347         data = bmp->bm_data;
348
349         for (y=0; y<bmp->bm_h; y++ )    {
350                 for (x=0; x<bmp->bm_w; x++ )    {
351                         if (*data++ == TRANSPARENCY_COLOR )     {
352                                 gr_set_transparent (bmp, 1);
353                                 return;
354                         }
355                 }
356                 data += bmp->bm_rowsize - bmp->bm_w;
357         }
358
359         bmp->bm_flags = 0;
360
361 }