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