added pcx_get_dimensions(), other stuff from d2src
[btb/d2x.git] / 2d / bitblt.c
1 /* $Id: bitblt.c,v 1.6 2002-08-17 11:19:56 btb 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 #ifdef HAVE_CONFIG_H
16 #include <conf.h>
17 #endif
18
19 #include <string.h>
20 #include "u_mem.h"
21 #include "gr.h"
22 #include "grdef.h"
23 #include "rle.h"
24 #include "byteswap.h"   // because of rle code that has short for row offsets
25 #include "error.h"
26
27 #ifdef OGL
28 #include "ogl_init.h"
29 #endif
30
31 int gr_bitblt_dest_step_shift = 0;
32 int gr_bitblt_double = 0;
33 ubyte *gr_bitblt_fade_table=NULL;
34
35 void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest);
36 void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest);
37 void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest, int masked);
38
39 void gr_bm_ubitblt01(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest);
40 void gr_bm_ubitblt02(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest);
41
42 #include "linear.h"
43 #include "modex.h"
44 #include "vesa.h"
45
46 #ifdef NO_ASM
47 void gr_linear_movsd( ubyte * source, ubyte * dest, unsigned int nbytes) {
48         memcpy(dest,source,nbytes);
49 }
50
51 void gr_linear_rep_movsdm(ubyte *src, ubyte *dest, int num_pixels) {
52         register ubyte c;
53         while (num_pixels--)
54                 if ((c=*src++)!=255)
55                         *dest++=c;
56                 else    dest++;
57 }
58
59 void gr_linear_rep_movsdm_faded(ubyte * src, ubyte * dest, int num_pixels, ubyte fade_value ) {
60         register ubyte c;
61         while (num_pixels--)
62                 if ((c=*src++)!=255)
63                         *dest++=gr_fade_table[((int)fade_value<<8)|(int)c];
64                 else    dest++;
65 }
66 void gr_linear_rep_movsd_2x(ubyte * source, ubyte * dest, uint nbytes ) {
67         register ubyte c;
68         while (nbytes--) {
69                 if (nbytes&1)
70                         *dest++=*source++;
71                 else {
72                         c=*source++;
73                         *((unsigned short *)dest)++=((short)c<<8)|(short)c;
74                 }
75         }
76 }
77 #endif
78 #ifdef D1XD3D
79 #include "d3dhelp.h"
80 #endif
81
82 void gr_ubitmap00( int x, int y, grs_bitmap *bm )
83 {
84         register int y1;
85         int dest_rowsize;
86
87         unsigned char * dest;
88         unsigned char * src;
89
90         dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift;
91         dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]);
92
93         src = bm->bm_data;
94
95         for (y1=0; y1 < bm->bm_h; y1++ )    {
96                 if (gr_bitblt_double)
97                         gr_linear_rep_movsd_2x( src, dest, bm->bm_w );
98                 else
99                         gr_linear_movsd( src, dest, bm->bm_w );
100                 src += bm->bm_rowsize;
101                 dest+= (int)(dest_rowsize);
102         }
103 }
104
105 void gr_ubitmap00m( int x, int y, grs_bitmap *bm )
106 {
107         register int y1;
108         int dest_rowsize;
109
110         unsigned char * dest;
111         unsigned char * src;
112
113         dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift;
114         dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]);
115
116         src = bm->bm_data;
117
118         if (gr_bitblt_fade_table==NULL) {
119                 for (y1=0; y1 < bm->bm_h; y1++ )    {
120                         gr_linear_rep_movsdm( src, dest, bm->bm_w );
121                         src += bm->bm_rowsize;
122                         dest+= (int)(dest_rowsize);
123                 }
124         } else {
125                 for (y1=0; y1 < bm->bm_h; y1++ )    {
126                         gr_linear_rep_movsdm_faded( src, dest, bm->bm_w, gr_bitblt_fade_table[y1+y] );
127                         src += bm->bm_rowsize;
128                         dest+= (int)(dest_rowsize);
129                 }
130         }
131 }
132
133 //"             jmp     aligned4                                "       
134 //"             mov     eax, edi                                "       
135 //"             and     eax, 11b                                "       
136 //"             jz              aligned4                        "       
137 //"             mov     ebx, 4                                  "       
138 //"             sub     ebx, eax                                "       
139 //"             sub     ecx, ebx                                "       
140 //"alignstart:                                                  "       
141 //"             mov     al, [esi]                               "       
142 //"             add     esi, 4                                  "       
143 //"             mov     [edi], al                               "       
144 //"             inc     edi                                     "       
145 //"             dec     ebx                                     "       
146 //"             jne     alignstart                              "       
147 //"aligned4:                                                    "       
148
149 #ifdef __DJGPP__
150 // From Linear to ModeX
151 void gr_bm_ubitblt01(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
152 {
153         ubyte * dbits;
154         ubyte * sbits;
155         int sstep,dstep;
156         int y,plane;
157         int w1;
158
159         if ( w < 4 ) return;
160
161         sstep = src->bm_rowsize;
162         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
163
164         if (!gr_bitblt_double)  {
165                 for (plane=0; plane<4; plane++ )        {
166                         gr_modex_setplane( (plane+dx)&3 );
167                         sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane;
168                         dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ];
169                         w1 = w >> 2;
170                         if ( (w&3) > plane ) w1++;
171                         for (y=dy; y < dy+h; y++ )              {
172                                 modex_copy_scanline( sbits, dbits, w1 );                
173                                 dbits += dstep;
174                                 sbits += sstep;
175                         }
176                 }
177         } else {
178                 for (plane=0; plane<4; plane++ )        {
179                         gr_modex_setplane( (plane+dx)&3 );
180                         sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane/2;
181                         dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ];
182                         w1 = w >> 2;
183                         if ( (w&3) > plane ) w1++;
184                         for (y=dy; y < dy+h; y++ )              {
185                                 modex_copy_scanline_2x( sbits, dbits, w1 );             
186                                 dbits += dstep;
187                                 sbits += sstep;
188                         }
189                 }
190         }
191 }
192
193
194 // From Linear to ModeX masked
195 void gr_bm_ubitblt01m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
196 {
197         //ubyte * dbits1;
198         //ubyte * sbits1;
199         
200         ubyte * dbits;
201         ubyte * sbits;
202
203         int x;
204 //      int y;
205
206         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
207         dbits =   &gr_video_memory[(dest->bm_rowsize * dy) + dx/4];
208
209         for (x=dx; x < dx+w; x++ )      {       
210                 gr_modex_setplane( x&3 );
211
212                 //sbits1 = sbits;
213                 //dbits1 = dbits;
214                 //for (y=0; y < h; y++ )    {
215                 //      *dbits1 = *sbits1;
216                 //      sbits1 += src_bm_rowsize;
217                 //      dbits1 += dest_bm_rowsize;
218                 //      }
219                 modex_copy_column_m(sbits, dbits, h, src->bm_rowsize, dest->bm_rowsize << gr_bitblt_dest_step_shift );
220
221                 sbits++;
222                 if ( (x&3)==3 )
223                         dbits++;
224         }
225 }
226
227 #endif
228
229
230 void gr_ubitmap012( int x, int y, grs_bitmap *bm )
231 {
232         register int x1, y1;
233         unsigned char * src;
234
235         src = bm->bm_data;
236
237         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
238                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
239                         gr_setcolor( *src++ );
240                         gr_upixel( x1, y1 );
241                 }
242         }
243 }
244
245 void gr_ubitmap012m( int x, int y, grs_bitmap *bm )
246 {
247         register int x1, y1;
248         unsigned char * src;
249
250         src = bm->bm_data;
251
252         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
253                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
254                         if ( *src != 255 )      {
255                                 gr_setcolor( *src );
256                                 gr_upixel( x1, y1 );
257                         }
258                         src++;
259                 }
260         }
261 }
262
263
264 void gr_ubitmapGENERIC(int x, int y, grs_bitmap * bm)
265 {
266         register int x1, y1;
267
268         for (y1=0; y1 < bm->bm_h; y1++ )    {
269                 for (x1=0; x1 < bm->bm_w; x1++ )    {
270                         gr_setcolor( gr_gpixel(bm,x1,y1) );
271                         gr_upixel( x+x1, y+y1 );
272                 }
273         }
274 }
275
276 void gr_ubitmapGENERICm(int x, int y, grs_bitmap * bm)
277 {
278         register int x1, y1;
279         ubyte c;
280
281         for (y1=0; y1 < bm->bm_h; y1++ )    {
282                 for (x1=0; x1 < bm->bm_w; x1++ )    {
283                         c = gr_gpixel(bm,x1,y1);
284                         if ( c != 255 ) {
285                                 gr_setcolor( c );
286                                 gr_upixel( x+x1, y+y1 );
287                         }
288                 }
289         }
290 }
291
292 void gr_ubitmap( int x, int y, grs_bitmap *bm )
293 {   int source, dest;
294
295         source = bm->bm_type;
296         dest = TYPE;
297
298         if (source==BM_LINEAR) {
299                 switch( dest )
300                 {
301                 case BM_LINEAR:
302                         if ( bm->bm_flags & BM_FLAG_RLE )
303                                 gr_bm_ubitblt00_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
304                         else
305                                 gr_ubitmap00( x, y, bm );
306                         return;
307 #ifdef OGL
308                 case BM_OGL:
309                         ogl_ubitmapm(x,y,bm);
310                         return;
311 #endif
312 #ifdef D1XD3D
313                 case BM_DIRECTX:
314                         Assert ((int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_RENDER || (int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_DISPLAY);
315                         Win32_BlitLinearToDirectX_bm(bm, 0, 0, bm->bm_w, bm->bm_h, x, y, 0);
316                         return;
317 #endif
318 #ifdef __DJGPP__
319                 case BM_SVGA:
320                         if ( bm->bm_flags & BM_FLAG_RLE )
321                                 gr_bm_ubitblt0x_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap, 0 );
322                         else
323                                 gr_bm_ubitblt02( bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
324                         return;
325                 case BM_MODEX:
326                         gr_bm_ubitblt01(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap);
327                         return;
328 #endif
329                 default:
330                         gr_ubitmap012( x, y, bm );
331                         return;
332                 }
333         } else  {
334                 gr_ubitmapGENERIC(x, y, bm);
335         }
336 }
337
338 void gr_ubitmapm( int x, int y, grs_bitmap *bm )
339 {   int source, dest;
340
341
342         source = bm->bm_type;
343         dest = TYPE;
344
345         if (source==BM_LINEAR) {
346                 switch( dest )
347                 {
348                 case BM_LINEAR:
349                         if ( bm->bm_flags & BM_FLAG_RLE )
350                                 gr_bm_ubitblt00m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
351                         else
352                                 gr_ubitmap00m( x, y, bm );
353                         return;
354 #ifdef OGL
355                 case BM_OGL:
356                         ogl_ubitmapm(x,y,bm);
357                         return;
358 #endif
359 #ifdef D1XD3D
360                 case BM_DIRECTX:
361                         if (bm->bm_w < 35 && bm->bm_h < 35) {
362                                 // ugly hack needed for reticle
363                                 if ( bm->bm_flags & BM_FLAG_RLE )
364                                         gr_bm_ubitblt0x_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap, 1 );
365                                 else
366                                         gr_ubitmapGENERICm(x, y, bm);
367                                 return;
368                         }
369                         Assert ((int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_RENDER || (int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_DISPLAY);
370                         Win32_BlitLinearToDirectX_bm(bm, 0, 0, bm->bm_w, bm->bm_h, x, y, 1);
371                         return;
372 #endif
373 #ifdef __DJGPP__
374                 case BM_SVGA:
375                         gr_ubitmapGENERICm(x, y, bm);
376                         return;
377                 case BM_MODEX:
378                         gr_bm_ubitblt01m(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap);
379                         return;
380 #endif
381                 default:
382                         gr_ubitmap012m( x, y, bm );
383                         return;
384                 }
385         } else  {
386                 gr_ubitmapGENERICm(x, y, bm);
387         }
388 }
389
390
391 #ifdef __DJGPP__
392 // From linear to SVGA
393 void gr_bm_ubitblt02(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
394 {
395         unsigned char * sbits;
396
397         unsigned int offset, EndingOffset, VideoLocation;
398
399         int sbpr, dbpr, y1, page, BytesToMove;
400
401         sbpr = src->bm_rowsize;
402
403         dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
404
405         VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
406
407         sbits = src->bm_data + ( sbpr*sy ) + sx;
408
409         for (y1=0; y1 < h; y1++ )    {
410
411                 page    = VideoLocation >> 16;
412                 offset  = VideoLocation & 0xFFFF;
413
414                 gr_vesa_setpage( page );
415
416                 EndingOffset = offset+w-1;
417
418                 if ( EndingOffset <= 0xFFFF )
419                 {
420                         if ( gr_bitblt_double )
421                                 gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), w );
422                         else
423                                 gr_linear_movsd( (void *)sbits, (void *)(offset+gr_video_memory), w );
424
425                         VideoLocation += dbpr;
426                         sbits += sbpr;
427                 }
428                 else
429                 {
430                         BytesToMove = 0xFFFF-offset+1;
431
432                         if ( gr_bitblt_double )
433                                 gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), BytesToMove );
434                         else
435                                 gr_linear_movsd( (void *)sbits, (void *)(offset+gr_video_memory), BytesToMove );
436
437                         page++;
438                         gr_vesa_setpage(page);
439
440                         if ( gr_bitblt_double )
441                                 gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)gr_video_memory, EndingOffset - 0xFFFF );
442                         else
443                                 gr_linear_movsd( (void *)(sbits+BytesToMove), (void *)gr_video_memory, EndingOffset - 0xFFFF );
444
445                         VideoLocation += dbpr;
446                         sbits += sbpr;
447                 }
448         }
449 }
450
451 // From SVGA to linear
452 void gr_bm_ubitblt20(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
453 {
454         unsigned char * dbits;
455
456         unsigned int offset, offset1, offset2;
457
458         int sbpr, dbpr, y1, page;
459
460         dbpr = dest->bm_rowsize;
461
462         sbpr = src->bm_rowsize;
463
464         for (y1=0; y1 < h; y1++ )    {
465
466                 offset2 =   (unsigned int)src->bm_data  + (sbpr * (y1+sy)) + sx;
467                 dbits   =   dest->bm_data + (dbpr * (y1+dy)) + dx;
468
469                 page = offset2 >> 16;
470                 offset = offset2 & 0xFFFF;
471                 offset1 = offset+w-1;
472                 gr_vesa_setpage( page );
473
474                 if ( offset1 > 0xFFFF )  {
475                         // Overlaps two pages
476                         while( offset <= 0xFFFF )
477                                 *dbits++ = gr_video_memory[offset++];
478                         offset1 -= (0xFFFF+1);
479                         offset = 0;
480                         page++;
481                         gr_vesa_setpage(page);
482                 }
483                 while( offset <= offset1 )
484                         *dbits++ = gr_video_memory[offset++];
485
486         }
487 }
488 #endif // __DJGPP__
489 //@extern int Interlacing_on;
490
491 // From Linear to Linear
492 void gr_bm_ubitblt00(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
493 {
494         unsigned char * dbits;
495         unsigned char * sbits;
496         //int   src_bm_rowsize_2, dest_bm_rowsize_2;
497         int dstep;
498
499         int i;
500
501         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
502         dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
503
504         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
505
506         // No interlacing, copy the whole buffer.
507         if (gr_bitblt_double)
508             for (i=0; i < h; i++ )    {
509                 gr_linear_rep_movsd_2x( sbits, dbits, w );
510                 sbits += src->bm_rowsize;
511                 dbits += dstep;
512             }
513         else
514             for (i=0; i < h; i++ )    {
515                 gr_linear_movsd( sbits, dbits, w );
516                 //memcpy(dbits, sbits, w);
517                 sbits += src->bm_rowsize;
518                 dbits += dstep;
519             }
520 }
521
522 // From Linear to Linear Masked
523 void gr_bm_ubitblt00m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
524 {
525         unsigned char * dbits;
526         unsigned char * sbits;
527         //int   src_bm_rowsize_2, dest_bm_rowsize_2;
528
529         int i;
530
531         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
532         dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
533
534         // No interlacing, copy the whole buffer.
535
536         if (gr_bitblt_fade_table==NULL) {
537                 for (i=0; i < h; i++ )    {
538                         gr_linear_rep_movsdm( sbits, dbits, w );
539                         sbits += src->bm_rowsize;
540                         dbits += dest->bm_rowsize;
541                 }
542         } else {
543                 for (i=0; i < h; i++ )    {
544                         gr_linear_rep_movsdm_faded( sbits, dbits, w, gr_bitblt_fade_table[dy+i] );
545                         sbits += src->bm_rowsize;
546                         dbits += dest->bm_rowsize;
547                 }
548         }
549 }
550
551
552 void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
553 {
554         int dx1=dx, dx2=dx+dest->bm_w-1;
555         int dy1=dy, dy2=dy+dest->bm_h-1;
556
557         int sx1=sx, sx2=sx+src->bm_w-1;
558         int sy1=sy, sy2=sy+src->bm_h-1;
559
560         if ((dx1 >= dest->bm_w ) || (dx2 < 0)) return;
561         if ((dy1 >= dest->bm_h ) || (dy2 < 0)) return;
562         if ( dx1 < 0 ) { sx1 += -dx1; dx1 = 0; }
563         if ( dy1 < 0 ) { sy1 += -dy1; dy1 = 0; }
564         if ( dx2 >= dest->bm_w )        { dx2 = dest->bm_w-1; }
565         if ( dy2 >= dest->bm_h )        { dy2 = dest->bm_h-1; }
566
567         if ((sx1 >= src->bm_w ) || (sx2 < 0)) return;
568         if ((sy1 >= src->bm_h ) || (sy2 < 0)) return;
569         if ( sx1 < 0 ) { dx1 += -sx1; sx1 = 0; }
570         if ( sy1 < 0 ) { dy1 += -sy1; sy1 = 0; }
571         if ( sx2 >= src->bm_w ) { sx2 = src->bm_w-1; }
572         if ( sy2 >= src->bm_h ) { sy2 = src->bm_h-1; }
573
574         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
575         if ( dx2-dx1+1 < w )
576                 w = dx2-dx1+1;
577         if ( dy2-dy1+1 < h )
578                 h = dy2-dy1+1;
579         if ( sx2-sx1+1 < w )
580                 w = sx2-sx1+1;
581         if ( sy2-sy1+1 < h )
582                 h = sy2-sy1+1;
583
584         gr_bm_ubitblt(w,h, dx1, dy1, sx1, sy1, src, dest );
585 }
586
587 void gr_bm_ubitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
588 {
589         register int x1, y1;
590
591         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR ))
592         {
593                 if ( src->bm_flags & BM_FLAG_RLE )      
594                         gr_bm_ubitblt00_rle( w, h, dx, dy, sx, sy, src, dest );
595                 else
596                         gr_bm_ubitblt00( w, h, dx, dy, sx, sy, src, dest );
597                 return;
598         }
599
600 #ifdef OGL
601         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL ))
602         {
603                 ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest);
604                 return;
605         }
606         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR ))
607         {
608                 ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest);
609                 return;
610         }
611         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL ))
612         {
613                 ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest);
614                 return;
615         }
616 #endif
617
618 #ifdef D1XD3D
619         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX ))
620         {
621                 Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY);
622                 Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 0);
623                 return;
624         }
625         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_LINEAR ))
626         {
627                 return;
628         }
629         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX ))
630         {
631                 return;
632         }
633 #endif
634
635         if ( (src->bm_flags & BM_FLAG_RLE ) && (src->bm_type == BM_LINEAR) )    {
636                 gr_bm_ubitblt0x_rle(w, h, dx, dy, sx, sy, src, dest, 0 );
637                 return;
638         }
639 #ifdef __DJGPP__
640         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_SVGA ))
641         {
642                 gr_bm_ubitblt02( w, h, dx, dy, sx, sy, src, dest );
643                 return;
644         }
645
646         if ( (src->bm_type == BM_SVGA) && (dest->bm_type == BM_LINEAR ))
647         {
648                 gr_bm_ubitblt20( w, h, dx, dy, sx, sy, src, dest );
649                 return;
650         }
651
652         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_MODEX ))
653         {
654                 gr_bm_ubitblt01( w, h, dx+XOFFSET, dy+YOFFSET, sx, sy, src, dest );
655                 return;
656         }
657 #endif
658         for (y1=0; y1 < h; y1++ )    {
659                 for (x1=0; x1 < w; x1++ )    {
660                         gr_bm_pixel( dest, dx+x1, dy+y1, gr_gpixel(src,sx+x1,sy+y1) );
661                 }
662         }
663 }
664
665 // Clipped bitmap ... 
666
667 void gr_bitmap( int x, int y, grs_bitmap *bm )
668 {
669         int dx1=x, dx2=x+bm->bm_w-1;
670         int dy1=y, dy2=y+bm->bm_h-1;
671         int sx=0, sy=0;
672
673         if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return;
674         if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return;
675         if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; }
676         if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; }
677         if ( dx2 >= grd_curcanv->cv_bitmap.bm_w )       { dx2 = grd_curcanv->cv_bitmap.bm_w-1; }
678         if ( dy2 >= grd_curcanv->cv_bitmap.bm_h )       { dy2 = grd_curcanv->cv_bitmap.bm_h-1; }
679                 
680         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
681
682         gr_bm_ubitblt(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
683
684 }
685
686 void gr_bitmapm( int x, int y, grs_bitmap *bm )
687 {
688         int dx1=x, dx2=x+bm->bm_w-1;
689         int dy1=y, dy2=y+bm->bm_h-1;
690         int sx=0, sy=0;
691
692         if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return;
693         if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return;
694         if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; }
695         if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; }
696         if ( dx2 >= grd_curcanv->cv_bitmap.bm_w )       { dx2 = grd_curcanv->cv_bitmap.bm_w-1; }
697         if ( dy2 >= grd_curcanv->cv_bitmap.bm_h )       { dy2 = grd_curcanv->cv_bitmap.bm_h-1; }
698                 
699         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
700
701         if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_LINEAR ))
702         {
703                 if ( bm->bm_flags & BM_FLAG_RLE )       
704                         gr_bm_ubitblt00m_rle(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
705                 else
706                         gr_bm_ubitblt00m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
707                 return;
708         }
709
710         gr_bm_ubitbltm(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
711
712 }
713
714 void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
715 {
716         register int x1, y1;
717         ubyte c;
718
719 #ifdef OGL
720         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL ))
721         {
722                 ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest);
723                 return;
724         }
725         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR ))
726         {
727                 ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest);
728                 return;
729         }
730         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL ))
731         {
732                 ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest);
733                 return;
734         }
735 #endif
736 #ifdef D1XD3D
737         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX ))
738         {
739                 Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY);
740                 Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 1);
741                 return;
742         }
743         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX ))
744         {
745                 Assert ((int)src->bm_data == BM_D3D_RENDER || (int)src->bm_data == BM_D3D_DISPLAY);
746 //              Win32_BlitDirectXToDirectX (w, h, dx, dy, sx, sy, src->bm_data, dest->bm_data, 0);
747                 return;
748         }
749 #endif
750
751
752         for (y1=0; y1 < h; y1++ )    {
753                 for (x1=0; x1 < w; x1++ )    {
754                         if ((c=gr_gpixel(src,sx+x1,sy+y1))!=255)
755                                 gr_bm_pixel( dest, dx+x1, dy+y1,c  );
756                 }
757         }
758
759 }
760
761 //-NOT-used // From linear to SVGA
762 //-NOT-used void gr_bm_ubitblt02_2x(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
763 //-NOT-used {
764 //-NOT-used     unsigned char * sbits;
765 //-NOT-used 
766 //-NOT-used     unsigned int offset, EndingOffset, VideoLocation;
767 //-NOT-used 
768 //-NOT-used     int sbpr, dbpr, y1, page, BytesToMove;
769 //-NOT-used 
770 //-NOT-used     sbpr = src->bm_rowsize;
771 //-NOT-used 
772 //-NOT-used     dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
773 //-NOT-used 
774 //-NOT-used     VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
775 //-NOT-used 
776 //-NOT-used     sbits = src->bm_data + ( sbpr*sy ) + sx;
777 //-NOT-used 
778 //-NOT-used     for (y1=0; y1 < h; y1++ )    {
779 //-NOT-used 
780 //-NOT-used             page    = VideoLocation >> 16;
781 //-NOT-used             offset  = VideoLocation & 0xFFFF;
782 //-NOT-used 
783 //-NOT-used             gr_vesa_setpage( page );
784 //-NOT-used 
785 //-NOT-used             EndingOffset = offset+w-1;
786 //-NOT-used 
787 //-NOT-used             if ( EndingOffset <= 0xFFFF )
788 //-NOT-used             {
789 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), w );
790 //-NOT-used 
791 //-NOT-used                     VideoLocation += dbpr;
792 //-NOT-used                     sbits += sbpr;
793 //-NOT-used             }
794 //-NOT-used             else
795 //-NOT-used             {
796 //-NOT-used                     BytesToMove = 0xFFFF-offset+1;
797 //-NOT-used 
798 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), BytesToMove );
799 //-NOT-used 
800 //-NOT-used                     page++;
801 //-NOT-used                     gr_vesa_setpage(page);
802 //-NOT-used 
803 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)gr_video_memory, EndingOffset - 0xFFFF );
804 //-NOT-used 
805 //-NOT-used                     VideoLocation += dbpr;
806 //-NOT-used                     sbits += sbpr;
807 //-NOT-used             }
808 //-NOT-used 
809 //-NOT-used 
810 //-NOT-used     }
811 //-NOT-used }
812
813
814 //-NOT-used // From Linear to Linear
815 //-NOT-used void gr_bm_ubitblt00_2x(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
816 //-NOT-used {
817 //-NOT-used     unsigned char * dbits;
818 //-NOT-used     unsigned char * sbits;
819 //-NOT-used     //int   src_bm_rowsize_2, dest_bm_rowsize_2;
820 //-NOT-used 
821 //-NOT-used     int i;
822 //-NOT-used 
823 //-NOT-used     sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
824 //-NOT-used     dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
825 //-NOT-used 
826 //-NOT-used     // No interlacing, copy the whole buffer.
827 //-NOT-used     for (i=0; i < h; i++ )    {
828 //-NOT-used             gr_linear_rep_movsd_2x( sbits, dbits, w );
829 //-NOT-used 
830 //-NOT-used             sbits += src->bm_rowsize;
831 //-NOT-used             dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
832 //-NOT-used     }
833 //-NOT-used }
834
835 void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
836 {
837         unsigned char * dbits;
838         unsigned char * sbits;
839         int i, data_offset;
840
841         data_offset = 1;
842         if (src->bm_flags & BM_FLAG_RLE_BIG)
843                 data_offset = 2;
844
845         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
846
847         for (i=0; i<sy; i++ )
848                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
849
850         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
851
852         // No interlacing, copy the whole buffer.
853         for (i=0; i < h; i++ )    {
854                 gr_rle_expand_scanline( dbits, sbits, sx, sx+w-1 );
855                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
856                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
857                 else
858                         sbits += (int)(src->bm_data[4+i+sy]);
859                 dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
860         }
861 }
862
863 void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
864 {
865         unsigned char * dbits;
866         unsigned char * sbits;
867         int i, data_offset;
868
869         data_offset = 1;
870         if (src->bm_flags & BM_FLAG_RLE_BIG)
871                 data_offset = 2;
872
873         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
874         for (i=0; i<sy; i++ )
875                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
876
877         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
878
879         // No interlacing, copy the whole buffer.
880         for (i=0; i < h; i++ )    {
881                 gr_rle_expand_scanline_masked( dbits, sbits, sx, sx+w-1 );
882                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
883                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
884                 else
885                         sbits += (int)(src->bm_data[4+i+sy]);
886                 dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
887         }
888 }
889
890 // in rle.c
891
892 extern void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, 
893         int x1, int x2, int masked );
894
895
896 void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, 
897         grs_bitmap * dest, int masked )
898 {
899         int i, data_offset;
900         register int y1;
901         unsigned char * sbits;
902
903         data_offset = 1;
904         if (src->bm_flags & BM_FLAG_RLE_BIG)
905                 data_offset = 2;
906
907         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
908         for (i=0; i<sy; i++ )
909                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
910
911         for (y1=0; y1 < h; y1++ )    {
912                 gr_rle_expand_scanline_generic( dest, dx, dy+y1,  sbits, sx, sx+w-1, masked  );
913                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
914                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
915                 else
916                         sbits += (int)src->bm_data[4+y1+sy];
917         }
918 }
919
920 // rescalling bitmaps, 10/14/99 Jan Bobrowski jb@wizard.ae.krakow.pl
921
922 inline void scale_line(byte *in, byte *out, int ilen, int olen)
923 {
924         int a = olen/ilen, b = olen%ilen;
925         int c = 0, i;
926         byte *end = out + olen;
927         while(out<end) {
928                 i = a;
929                 c += b;
930                 if(c >= ilen) {
931                         c -= ilen;
932                         goto inside;
933                 }
934                 while(--i>=0) {
935 inside:
936                         *out++ = *in;
937                 }
938                 in++;
939         }
940 }
941
942 void gr_bitmap_scale_to(grs_bitmap *src, grs_bitmap *dst)
943 {
944         byte *s = src->bm_data;
945         byte *d = dst->bm_data;
946         int h = src->bm_h;
947         int a = dst->bm_h/h, b = dst->bm_h%h;
948         int c = 0, i, y;
949
950         for(y=0; y<h; y++) {
951                 i = a;
952                 c += b;
953                 if(c >= h) {
954                         c -= h;
955                         goto inside;
956                 }
957                 while(--i>=0) {
958 inside:
959                         scale_line(s, d, src->bm_w, dst->bm_w);
960                         d += dst->bm_rowsize;
961                 }
962                 s += src->bm_rowsize;
963         }
964 }
965
966 void show_fullscr(grs_bitmap *bm)
967 {
968         grs_bitmap * const scr = &grd_curcanv->cv_bitmap;
969
970 #ifdef OGL
971         if(bm->bm_type == BM_LINEAR && scr->bm_type == BM_OGL) {
972                 ogl_ubitblt_i(scr->bm_w,scr->bm_h,0,0,bm->bm_w,bm->bm_h,0,0,bm,scr);//use opengl to scale, faster and saves ram. -MPM
973                 return;
974         }
975 #endif
976         if(scr->bm_type != BM_LINEAR) {
977                 grs_bitmap *tmp = gr_create_bitmap(scr->bm_w, scr->bm_h);
978                 gr_bitmap_scale_to(bm, tmp);
979                 gr_bitmap(0, 0, tmp);
980                 gr_free_bitmap(tmp);
981                 return;
982         }
983         gr_bitmap_scale_to(bm, scr);
984 }