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-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Rountines to copy a bitmap on top of another bitmap, but
18 * only copying to pixels that are transparent.
20 * Routines to to inverse bitblitting -- well not really.
21 * We don't inverse bitblt like in the PC, but this code
22 * does set up a structure that blits around the cockpit
24 * d2x uses the "Mac" version for everything except __MSDOS__
32 #ifdef __MSDOS__ //ndef MACINTOSH
50 #define OPCODE_ADD 0x81
51 #define OPCODE_ESI 0xC6 // Followed by a dword (add esi, ????)
52 #define OPCODE_EDI 0xC7 // Followed by a dword (add edi, ????)
53 #define OPCODE_MOV_ECX 0xB9 // Followed by a dword (mov ecx,????)
54 #define OPCODE_MOVSB 0xA4 // movsb
55 #define OPCODE_16BIT 0x66 // movsw
56 #define OPCODE_MOVSD 0xA5 // movsd
57 #define OPCODE_REP 0xF3 // rep
58 #define OPCODE_RET 0xC3 // ret
59 #define OPCODE_MOV_EAX 0xB8 // mov eax, im dword
60 #define OPCODE_MOV_EBX 0xBB // mov ebx, im dword
61 #define OPCODE_CALL_EBX1 0xFF // call
62 #define OPCODE_CALL_EBX2 0xD3 // ebx
63 #define OPCODE_MOV_EDI 0xBF // mov edi, im dword
66 ubyte *Code_pointer = NULL;
68 int ibitblt_svga_page = 0;
74 void count_block( int ecx )
80 case 1: Code_counter++; ecx = 0; break; // MOVSB
81 case 2: Code_counter+=2; ecx = 0; break; // MOVSW
82 case 3: Code_counter+=3; ecx = 0; break; // MOVSW, MOVSB
83 case 4: Code_counter++; ecx = 0; break; // MOVSD
87 Code_counter++; // MOVSD
96 void move_and_count( int dsource, int ddest, int ecx )
114 linear_address += ddest; // Skip to next block
116 p1 = linear_address >> 16; o1 = linear_address & 0xFFFF;
117 p2 = (linear_address+ecx) >> 16;
118 if ( p1 != ibitblt_svga_page ) {
120 // MOV EAX, ?, CALL EBX
122 ibitblt_svga_page = p1;
125 Code_counter += 5; // mov edi, ????
131 nbytes = 0xFFFF-o1+1;
132 count_block( nbytes );
135 Code_counter += 7; // mov eax,???? call ebx
137 ibitblt_svga_page = p2;
139 Code_counter += 5; // mov edi, ????
141 nbytes = ecx - nbytes;
143 count_block( nbytes );
145 linear_address += ecx;
151 void draw_block( int ecx )
160 *Code_pointer++ = OPCODE_MOVSB;
165 *Code_pointer++ = OPCODE_16BIT;
166 *Code_pointer++ = OPCODE_MOVSD;
171 *Code_pointer++ = OPCODE_16BIT;
172 *Code_pointer++ = OPCODE_MOVSD;
173 *Code_pointer++ = OPCODE_MOVSB;
178 *Code_pointer++ = OPCODE_MOVSD;
186 *Code_pointer++ = OPCODE_MOVSD;
189 *Code_pointer++ = OPCODE_MOV_ECX;
190 iptr = (int *)Code_pointer;
192 Code_pointer = (ubyte *)iptr;
194 *Code_pointer++ = OPCODE_REP;
195 *Code_pointer++ = OPCODE_MOVSD;
203 void move_and_draw( int dsource, int ddest, int ecx )
212 *Code_pointer++ = OPCODE_ADD;
213 *Code_pointer++ = OPCODE_ESI;
214 iptr = (int *)Code_pointer;
216 Code_pointer = (ubyte *)iptr;
221 *Code_pointer++ = OPCODE_ADD;
222 *Code_pointer++ = OPCODE_EDI;
223 iptr = (int *)Code_pointer;
225 Code_pointer = (ubyte *)iptr;
233 linear_address += ddest; // Skip to next block
235 p1 = linear_address >> 16; o1 = linear_address & 0xFFFF;
236 p2 = (linear_address+ecx) >> 16;
237 if ( p1 != ibitblt_svga_page ) {
240 *Code_pointer++ = OPCODE_MOV_EAX;
242 memcpy( Code_pointer, &temp, sizeof(int) );
243 Code_pointer += sizeof(int);
245 *Code_pointer++ = OPCODE_CALL_EBX1;
246 *Code_pointer++ = OPCODE_CALL_EBX2;
247 ibitblt_svga_page = p1;
250 temp_offset = 0xA0000 + o1;
251 *Code_pointer++ = OPCODE_MOV_EDI;
252 iptr = (int *)Code_pointer;
253 *iptr++ = temp_offset;
254 Code_pointer = (ubyte *)iptr;
260 nbytes = 0xFFFF-o1+1;
261 draw_block( nbytes );
264 *Code_pointer++ = OPCODE_MOV_EAX;
266 memcpy( Code_pointer, &temp, sizeof(int) );
267 Code_pointer += sizeof(int);
269 *Code_pointer++ = OPCODE_CALL_EBX1;
270 *Code_pointer++ = OPCODE_CALL_EBX2;
271 ibitblt_svga_page = p2;
273 temp_offset = 0xA0000;
274 *Code_pointer++ = OPCODE_MOV_EDI;
275 iptr = (int *)Code_pointer;
276 *iptr++ = temp_offset;
277 Code_pointer = (ubyte *)iptr;
279 nbytes = ecx - nbytes;
281 draw_block( nbytes );
283 linear_address += ecx;
288 //-----------------------------------------------------------------------------------------
289 // Given bitmap, bmp, finds the size of the code
291 int gr_ibitblt_find_code_size_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type )
295 int draw_mode = MODE_NONE;
296 int source_offset = 0;
298 int num_to_draw, draw_start_source, draw_start_dest;
301 Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
305 if ( dest_type == BM_SVGA ) {
306 Code_counter += 1+4; // move ebx, gr_vesa_set_page
307 Code_counter += 1+4; // move eax, 0
308 Code_counter += 2; // call ebx
309 ibitblt_svga_page = 0;
316 esi = source_offset = 0;
317 edi = dest_offset = 0;
318 draw_start_source = draw_start_dest = 0;
320 for ( y=sy; y<sy+sh; y++ ) {
321 for ( x=sx; x<sx+sw; x++ ) {
322 dest_offset = y*mask_bmp->bm_rowsize+x;
323 pixel = mask_bmp->bm_data[dest_offset];
325 switch ( draw_mode) {
327 move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
328 esi = draw_start_source + num_to_draw;
329 edi = draw_start_dest + num_to_draw;
335 draw_mode = MODE_SKIP;
337 switch ( draw_mode) {
340 draw_start_source = source_offset;
341 draw_start_dest = dest_offset;
348 draw_mode = MODE_DRAW;
352 if ( draw_mode == MODE_DRAW ) {
353 move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
354 esi = draw_start_source + num_to_draw;
355 edi = draw_start_dest + num_to_draw;
357 draw_mode = MODE_NONE;
358 source_offset += (srowsize - sw);
360 Code_counter++; // for return
362 //printf( "Code will be %d bytes\n", Code_counter );
364 Code_counter += 16; // for safety was 16
369 int gr_ibitblt_find_code_size( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
371 return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR );
374 int gr_ibitblt_find_code_size_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
376 return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA );
379 //-----------------------------------------------------------------------------------------
380 // Given bitmap, bmp, create code that transfers a bitmap of size sw*sh to position
381 // (sx,sy) on top of bmp, only overwritting transparent pixels of the bitmap.
383 ubyte *gr_ibitblt_create_mask_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type )
387 int draw_mode = MODE_NONE;
388 int source_offset = 0;
390 int num_to_draw, draw_start_source, draw_start_dest;
396 Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
398 if ( dest_type == BM_SVGA )
399 code_size = gr_ibitblt_find_code_size_svga( mask_bmp, sx, sy, sw, sh, srowsize );
401 code_size = gr_ibitblt_find_code_size( mask_bmp, sx, sy, sw, sh, srowsize );
403 code = malloc( code_size );
409 if ( dest_type == BM_SVGA ) {
410 // MOV EBX, gr_vesa_setpage
411 *Code_pointer++ = OPCODE_MOV_EBX;
412 temp = (uint)gr_vesa_setpage;
413 memcpy( Code_pointer, &temp, sizeof(int) );
414 Code_pointer += sizeof(int);
416 *Code_pointer++ = OPCODE_MOV_EAX;
418 memcpy( Code_pointer, &temp, sizeof(int) );
419 Code_pointer += sizeof(int);
421 *Code_pointer++ = OPCODE_CALL_EBX1;
422 *Code_pointer++ = OPCODE_CALL_EBX2;
424 ibitblt_svga_page = 0;
430 esi = source_offset = 0;
431 edi = dest_offset = 0;
432 draw_start_source = draw_start_dest = 0;
434 for ( y=sy; y<sy+sh; y++ ) {
435 for ( x=sx; x<sx+sw; x++ ) {
436 dest_offset = y*mask_bmp->bm_rowsize+x;
437 pixel = mask_bmp->bm_data[dest_offset];
439 switch ( draw_mode) {
441 move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
442 esi = draw_start_source + num_to_draw;
443 edi = draw_start_dest + num_to_draw;
449 draw_mode = MODE_SKIP;
451 switch ( draw_mode) {
454 draw_start_source = source_offset;
455 draw_start_dest = dest_offset;
462 draw_mode = MODE_DRAW;
466 if ( draw_mode == MODE_DRAW ) {
467 move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
468 esi = draw_start_source + num_to_draw;
469 edi = draw_start_dest + num_to_draw;
471 draw_mode = MODE_NONE;
472 source_offset += (srowsize - sw);
474 *Code_pointer++ = OPCODE_RET;
476 if ( Code_pointer >= &code[code_size-1] )
477 Error( "ibitblt overwrote allocated code block\n" );
479 //printf( "Code is %d bytes\n", Code_pointer - code );
484 ubyte *gr_ibitblt_create_mask( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
486 return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR );
489 ubyte *gr_ibitblt_create_mask_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
491 return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA );
495 void gr_ibitblt_do_asm(char *start_si, char *start_di, ubyte * code);
496 #pragma aux gr_ibitblt_do_asm parm [esi] [edi] [eax] modify [ecx edi esi eax] = \
503 void gr_ibitblt(grs_bitmap * source_bmp, grs_bitmap * dest_bmp, ubyte * mask )
506 gr_ibitblt_do_asm( source_bmp->bm_data, dest_bmp->bm_data, mask );
510 void gr_ibitblt_find_hole_size( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy )
515 Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
517 *minx = mask_bmp->bm_w-1;
519 *miny = mask_bmp->bm_h-1;
522 for ( y=0; y<mask_bmp->bm_h; y++ )
523 for ( x=0; x<mask_bmp->bm_w; x++ ) {
524 c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
526 if ( x < *minx ) *minx = x;
527 if ( y < *miny ) *miny = y;
528 if ( x > *maxx ) *maxx = x;
529 if ( y > *maxy ) *maxy = y;
535 Error( "Bitmap for ibitblt doesn't have transparency!\n" );
539 #else /* __MSDOS__ */ // was: /* !MACINTOSH */
542 #include "dxxerror.h"
549 #define MAX_WIDTH 640
550 #define MAX_SCANLINES 480
553 static short start_points[MAX_SCANLINES][MAX_HOLES];
554 static short hole_length[MAX_SCANLINES][MAX_HOLES];
555 static double *scanline = NULL;
557 void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp)
559 int x, y, sw, sh, srowsize, drowsize, dstart, sy;
566 srowsize = src_bmp->bm_rowsize;
567 drowsize = dest_bmp->bm_rowsize;
568 src = src_bmp->bm_data;
569 dest = dest_bmp->bm_data;
572 while (start_points[sy][0] == -1) {
577 Assert(sw <= MAX_WIDTH);
578 Assert(sh <= MAX_SCANLINES);
579 for (y = sy; y < sy + sh; y++) {
580 for (x = 0; x < MAX_HOLES; x++) {
581 if (start_points[y][x] == -1)
583 dstart = start_points[y][x];
584 gr_linear_movsd(&(src[dstart]), &(dest[dstart]), hole_length[y][x]);
591 void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh, int srowsize)
597 Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
599 for (y = 0; y < MAX_SCANLINES; y++) {
600 for (x = 0; x < MAX_HOLES; x++) {
601 start_points[y][x] = -1;
602 hole_length[y][x] = -1;
606 for (y = sy; y < sy+sh; y++) {
609 for (x = sx; x < sx + sw; x++) {
610 if ((mode == FIND_START) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] == TRANSPARENCY_COLOR)) {
611 start_points[y][count] = x;
613 } else if ((mode == FIND_STOP) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] != TRANSPARENCY_COLOR)) {
614 hole_length[y][count] = x - start_points[y][count];
619 if (mode == FIND_STOP) {
620 hole_length[y][count] = x - start_points[y][count];
623 Assert(count <= MAX_HOLES);
627 void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int *maxx, int *maxy)
632 Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
633 Assert( mask_bmp->bm_flags&BM_FLAG_TRANSPARENT );
635 *minx = mask_bmp->bm_w - 1;
637 *miny = mask_bmp->bm_h - 1;
640 if (scanline == NULL)
641 scanline = (double *)malloc(sizeof(double) * (MAX_WIDTH / sizeof(double)));
643 for (y = 0; y < mask_bmp->bm_h; y++) {
644 for (x = 0; x < mask_bmp->bm_w; x++) {
645 c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
646 if (c == TRANSPARENCY_COLOR) { // don't look for transparancy color here.
648 if (x < *minx) *minx = x;
649 if (y < *miny) *miny = y;
650 if (x > *maxx) *maxx = x;
651 if (y > *maxy) *maxy = y;
658 #endif /* __MSDOS__ */ // was: /* !MACINTOSH */