From 0eba7b88698aa961802871709ce347cd3c7c7422 Mon Sep 17 00:00:00 2001 From: Bradley Bell Date: Wed, 4 Sep 2002 22:18:43 +0000 Subject: [PATCH] brought in line with original d2 version --- 2d/ibitblt.c | 790 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 756 insertions(+), 34 deletions(-) diff --git a/2d/ibitblt.c b/2d/ibitblt.c index 87c4e629..ba3bc439 100644 --- a/2d/ibitblt.c +++ b/2d/ibitblt.c @@ -1,4 +1,4 @@ -/* $Id: ibitblt.c,v 1.5 2002-08-27 04:03:50 btb Exp $ */ +/* $Id: ibitblt.c,v 1.6 2002-09-04 22:18:43 btb Exp $ */ /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO @@ -9,13 +9,51 @@ SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. -COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* - * Routines to to inverse bitblitting -- well not really. - * We don't inverse bitblt like in the PC, but this code - * does set up a structure that blits around the cockpit + * + * Mac Version: + * Routines to to inverse bitblitting -- well not really. + * We don't inverse bitblt like in the PC, but this code + * does set up a structure that blits around the cockpit + * + * Old Log: ibitblt.c + * Revision 1.3 1995/09/13 11:43:22 allender + * start on optimizing cockpit copy code + * + * Revision 1.2 1995/09/07 10:16:57 allender + * fixed up cockpit and rearview hole blitting + * + * Revision 1.1 1995/08/18 15:50:48 allender + * Initial revision + * + * PC version: + * Routines to copy a bitmap on top of another bitmap, but + * only copying to pixels that are transparent. + * + * Old Log: + * Revision 1.6 1994/11/28 17:07:29 john + * Took out some unused functions in linear.asm, moved + * gr_linear_movsd from linear.asm to bitblt.c, made sure that + * the code in ibiblt.c sets the direction flags before rep movsing. + * + * Revision 1.5 1994/11/18 22:50:22 john + * Changed shorts to ints in parameters. + * + * Revision 1.4 1994/11/09 16:35:16 john + * First version with working RLE bitmaps. + * + * Revision 1.3 1994/10/03 17:18:05 john + * Fixed bug with edi not getting intialized to zero + * in create_mask. + * + * Revision 1.2 1994/05/31 11:10:55 john + * *** empty log message *** + * + * Revision 1.1 1994/05/30 16:08:27 john + * Initial revision * */ @@ -23,30 +61,622 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include #endif +#ifdef RCS +static char rcsid[] = "$Id: ibitblt.c,v 1.6 2002-09-04 22:18:43 btb Exp $"; +#endif + +#ifdef __MSDOS__ + +#include +#include +#include +#include #include -#include "pstypes.h" + +#include "pa_enabl.h" //$$POLY_ACC +#include "types.h" #include "gr.h" +#include "mem.h" +#include "error.h" +#include "ibitblt.h" #include "grdef.h" + +#if defined(POLY_ACC) +#include "poly_acc.h" +#endif + +#define MODE_NONE 0 +#define MODE_SKIP 1 +#define MODE_DRAW 2 + +#define OPCODE_ADD 0x81 +#define OPCODE_ESI 0xC6 // Followed by a dword (add esi, ????) +#define OPCODE_EDI 0xC7 // Followed by a dword (add edi, ????) +#define OPCODE_MOV_ECX 0xB9 // Followed by a dword (mov ecx,????) +#define OPCODE_MOVSB 0xA4 // movsb +#define OPCODE_16BIT 0x66 // movsw +#define OPCODE_MOVSD 0xA5 // movsd +#define OPCODE_REP 0xF3 // rep +#define OPCODE_RET 0xC3 // ret +#define OPCODE_MOV_EAX 0xB8 // mov eax, im dword +#define OPCODE_MOV_EBX 0xBB // mov ebx, im dword +#define OPCODE_CALL_EBX1 0xFF // call +#define OPCODE_CALL_EBX2 0xD3 // ebx +#define OPCODE_MOV_EDI 0xBF // mov edi, im dword + + +ubyte *Code_pointer = NULL; +int Code_counter = 0; +int ibitblt_svga_page = 0; +int is_svga = 0; +uint linear_address; + + + +void count_block( int ecx ) +{ + int blocks; + + while ( ecx > 0 ) { + switch(ecx) { + case 1: Code_counter++; ecx = 0; break; // MOVSB + case 2: Code_counter+=2; ecx = 0; break; // MOVSW + case 3: Code_counter+=3; ecx = 0; break; // MOVSW, MOVSB + case 4: Code_counter++; ecx = 0; break; // MOVSD + default: + blocks = ecx / 4; + if ( blocks == 1 ) + Code_counter++; // MOVSD + else + Code_counter+=7; + ecx -= blocks*4; + } + } +} + + +void move_and_count( int dsource, int ddest, int ecx ) +{ + if ( ecx <= 0 ) + return; + + if ( dsource > 0 ) { + // ADD ESI, dsource + Code_counter += 6; + } + if ( !is_svga ) { + if ( ddest > 0 ) { + // ADD EDI, ddest + Code_counter += 6; + } + count_block( ecx ); + } else { + int p1, p2, o1; + + linear_address += ddest; // Skip to next block + + p1 = linear_address >> 16; o1 = linear_address & 0xFFFF; + p2 = (linear_address+ecx) >> 16; + if ( p1 != ibitblt_svga_page ) { + // Set page + // MOV EAX, ?, CALL EBX + Code_counter += 7; + ibitblt_svga_page = p1; + } + + Code_counter += 5; // mov edi, ???? + + if ( p1 == p2 ) { + count_block( ecx ); + } else { + int nbytes; + nbytes = 0xFFFF-o1+1; + count_block( nbytes ); + // set page + // MOV EAX, 0 + Code_counter += 7; // mov eax,???? call ebx + + ibitblt_svga_page = p2; + + Code_counter += 5; // mov edi, ???? + + nbytes = ecx - nbytes; + if (nbytes > 0 ) + count_block( nbytes ); + } + linear_address += ecx; + } +} + + + +void draw_block( int ecx ) +{ + int blocks; + int * iptr; + + while ( ecx > 0 ) { + switch( ecx ) { + case 1: + // MOVSB + *Code_pointer++ = OPCODE_MOVSB; + ecx = 0; + break; + case 2: + // MOVSW + *Code_pointer++ = OPCODE_16BIT; + *Code_pointer++ = OPCODE_MOVSD; + ecx = 0; + break; + case 3: + // MOVSW, MOVSB + *Code_pointer++ = OPCODE_16BIT; + *Code_pointer++ = OPCODE_MOVSD; + *Code_pointer++ = OPCODE_MOVSB; + ecx = 0; + break; + case 4: + // MOVSD + *Code_pointer++ = OPCODE_MOVSD; + ecx = 0; + break; + default: + blocks = ecx / 4; + + if ( blocks == 1 ) { + // MOVSD + *Code_pointer++ = OPCODE_MOVSD; + } else { + // MOV ECX, blocks + *Code_pointer++ = OPCODE_MOV_ECX; + iptr = (int *)Code_pointer; + *iptr++ = blocks; + Code_pointer = (ubyte *)iptr; + // REP MOVSD + *Code_pointer++ = OPCODE_REP; + *Code_pointer++ = OPCODE_MOVSD; + } + ecx -= blocks*4; + } + } +} + + +void move_and_draw( int dsource, int ddest, int ecx ) +{ + int * iptr; + + if ( ecx <= 0 ) + return; + + if ( dsource > 0 ) { + // ADD ESI, dsource + *Code_pointer++ = OPCODE_ADD; + *Code_pointer++ = OPCODE_ESI; + iptr = (int *)Code_pointer; + *iptr++ = dsource; + Code_pointer = (ubyte *)iptr; + } + if ( !is_svga ) { + if ( ddest > 0 ) { + // ADD EDI, ddest + *Code_pointer++ = OPCODE_ADD; + *Code_pointer++ = OPCODE_EDI; + iptr = (int *)Code_pointer; + *iptr++ = ddest; + Code_pointer = (ubyte *)iptr; + } + draw_block( ecx ); + } else { + unsigned int temp; + int temp_offset; + int p1, p2, o1; + + linear_address += ddest; // Skip to next block + + p1 = linear_address >> 16; o1 = linear_address & 0xFFFF; + p2 = (linear_address+ecx) >> 16; + if ( p1 != ibitblt_svga_page ) { + // Set page + // MOV EAX, 0 + *Code_pointer++ = OPCODE_MOV_EAX; + temp = p1; + memcpy( Code_pointer, &temp, sizeof(int) ); + Code_pointer += sizeof(int); + // CALL EBX + *Code_pointer++ = OPCODE_CALL_EBX1; + *Code_pointer++ = OPCODE_CALL_EBX2; + ibitblt_svga_page = p1; + } + + temp_offset = 0xA0000 + o1; + *Code_pointer++ = OPCODE_MOV_EDI; + iptr = (int *)Code_pointer; + *iptr++ = temp_offset; + Code_pointer = (ubyte *)iptr; + + if ( p1 == p2 ) { + draw_block( ecx ); + } else { + int nbytes; + nbytes = 0xFFFF-o1+1; + draw_block( nbytes ); + // set page + // MOV EAX, 0 + *Code_pointer++ = OPCODE_MOV_EAX; + temp = p2; + memcpy( Code_pointer, &temp, sizeof(int) ); + Code_pointer += sizeof(int); + // CALL EBX + *Code_pointer++ = OPCODE_CALL_EBX1; + *Code_pointer++ = OPCODE_CALL_EBX2; + ibitblt_svga_page = p2; + + temp_offset = 0xA0000; + *Code_pointer++ = OPCODE_MOV_EDI; + iptr = (int *)Code_pointer; + *iptr++ = temp_offset; + Code_pointer = (ubyte *)iptr; + + nbytes = ecx - nbytes; + if (nbytes > 0 ) + draw_block( nbytes ); + } + linear_address += ecx; + } + +} + +//----------------------------------------------------------------------------------------- +// Given bitmap, bmp, finds the size of the code + +int gr_ibitblt_find_code_size_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type ) +{ + int x,y; + ubyte pixel; + int draw_mode = MODE_NONE; + int source_offset = 0; + int dest_offset = 0; + int num_to_draw, draw_start_source, draw_start_dest; + int esi, edi; + + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); + + Code_counter = 0; + + if ( dest_type == BM_SVGA ) { + Code_counter += 1+4; // move ebx, gr_vesa_set_page + Code_counter += 1+4; // move eax, 0 + Code_counter += 2; // call ebx + ibitblt_svga_page = 0; + linear_address = 0; + is_svga = 1; + } else { + is_svga = 0; + } + + esi = source_offset = 0; + edi = dest_offset = 0; + draw_start_source = draw_start_dest = 0; + + for ( y=sy; ybm_rowsize+x; + pixel = mask_bmp->bm_data[dest_offset]; + if ( pixel!=255 ) { + switch ( draw_mode) { + case MODE_DRAW: + move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw ); + esi = draw_start_source + num_to_draw; + edi = draw_start_dest + num_to_draw; + // fall through!!! + case MODE_NONE: + case MODE_SKIP: + break; + } + draw_mode = MODE_SKIP; + } else { + switch ( draw_mode) { + case MODE_SKIP: + case MODE_NONE: + draw_start_source = source_offset; + draw_start_dest = dest_offset; + num_to_draw = 0; + // fall through + case MODE_DRAW: + num_to_draw++; + break; + } + draw_mode = MODE_DRAW; + } + source_offset++; + } + if ( draw_mode == MODE_DRAW ) { + move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw ); + esi = draw_start_source + num_to_draw; + edi = draw_start_dest + num_to_draw; + } + draw_mode = MODE_NONE; + source_offset += (srowsize - sw); + } + Code_counter++; // for return + + //printf( "Code will be %d bytes\n", Code_counter ); + + Code_counter += 16; // for safety was 16 + + return Code_counter; +} + +int gr_ibitblt_find_code_size( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ) +{ + return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR ); +} + +int gr_ibitblt_find_code_size_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ) +{ + return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA ); +} + +//----------------------------------------------------------------------------------------- +// Given bitmap, bmp, create code that transfers a bitmap of size sw*sh to position +// (sx,sy) on top of bmp, only overwritting transparent pixels of the bitmap. + +ubyte *gr_ibitblt_create_mask_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type ) +{ + int x,y; + ubyte pixel; + int draw_mode = MODE_NONE; + int source_offset = 0; + int dest_offset = 0; + int num_to_draw, draw_start_source, draw_start_dest; + int esi, edi; + int code_size; + ubyte *code; + uint temp; + + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); + + if ( dest_type == BM_SVGA ) + code_size = gr_ibitblt_find_code_size_svga( mask_bmp, sx, sy, sw, sh, srowsize ); + else + code_size = gr_ibitblt_find_code_size( mask_bmp, sx, sy, sw, sh, srowsize ); + + code = malloc( code_size ); + if ( code == NULL ) + return NULL; + + Code_pointer = code; + + if ( dest_type == BM_SVGA ) { + // MOV EBX, gr_vesa_setpage + *Code_pointer++ = OPCODE_MOV_EBX; + temp = (uint)gr_vesa_setpage; + memcpy( Code_pointer, &temp, sizeof(int) ); + Code_pointer += sizeof(int); + // MOV EAX, 0 + *Code_pointer++ = OPCODE_MOV_EAX; + temp = 0; + memcpy( Code_pointer, &temp, sizeof(int) ); + Code_pointer += sizeof(int); + // CALL EBX + *Code_pointer++ = OPCODE_CALL_EBX1; + *Code_pointer++ = OPCODE_CALL_EBX2; + + ibitblt_svga_page = 0; + is_svga = 1; + linear_address = 0; + } else { + is_svga = 0; + } + esi = source_offset = 0; + edi = dest_offset = 0; + draw_start_source = draw_start_dest = 0; + + for ( y=sy; ybm_rowsize+x; + pixel = mask_bmp->bm_data[dest_offset]; + if ( pixel!=255 ) { + switch ( draw_mode) { + case MODE_DRAW: + move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw ); + esi = draw_start_source + num_to_draw; + edi = draw_start_dest + num_to_draw; + // fall through!!! + case MODE_NONE: + case MODE_SKIP: + break; + } + draw_mode = MODE_SKIP; + } else { + switch ( draw_mode) { + case MODE_SKIP: + case MODE_NONE: + draw_start_source = source_offset; + draw_start_dest = dest_offset; + num_to_draw = 0; + // fall through + case MODE_DRAW: + num_to_draw++; + break; + } + draw_mode = MODE_DRAW; + } + source_offset++; + } + if ( draw_mode == MODE_DRAW ) { + move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw ); + esi = draw_start_source + num_to_draw; + edi = draw_start_dest + num_to_draw; + } + draw_mode = MODE_NONE; + source_offset += (srowsize - sw); + } + *Code_pointer++ = OPCODE_RET; + + if ( Code_pointer >= &code[code_size-1] ) + Error( "ibitblt overwrote allocated code block\n" ); + + //printf( "Code is %d bytes\n", Code_pointer - code ); + + return code; +} + +ubyte *gr_ibitblt_create_mask( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ) +{ + return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR ); +} + +#if defined(POLY_ACC) +ulong *pa_emit_blit(int gencode, ulong *buf, int w, int h, int sx, int sy, int dx, int dy) +{ + if(w == 0 || h == 0) + return buf; + + if(gencode) + { + buf[0] = (w << 16) | h; + buf[1] = (sx << 16) | sy; + buf[2] = (dx << 16) | dy; + } + return buf + 3; +} + +ubyte *gr_ibitblt_create_mask_pa( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ) +{ + ulong *ret, *code = 0; + int pass, x, y, n; + ushort *s; + + Assert(mask_bmp->bm_type == BM_LINEAR15); + + srowsize /= PA_BPP; + + pa_flush(); + + // make two passes, first pass gets size of output block, second actually creates data. + for(pass = 0; pass != 2; ++pass) + { + for (y = sy; y < sy + sh; y++ ) + { + // first byte of interest in mask + s = (ushort *)(mask_bmp->bm_data + y * mask_bmp->bm_rowsize + sx * PA_BPP); + for ( x=0; x < sw; ) + { + for(; x != sw && (s[x] & 0x8000); ++x) // while opaque... + ; + for(n = 0; x != sw && !(s[x] & 0x8000); ++n, ++x) // while transparent... + ; + code = pa_emit_blit(pass, code, n, 1, x - n, y - sy, x + sx - n, y); + } + } + if(pass == 0) + { + ret = malloc((int)code + sizeof(ulong)); + ret[0] = (int)code / sizeof(ulong); // store num ulongs in list. + code = ret + 1; + } + } + return (ubyte *)ret; +} + +#else +ubyte *gr_ibitblt_create_mask_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ) +{ + return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA ); +} +#endif + + +void gr_ibitblt_do_asm(char *start_si, char *start_di, ubyte * code); +#pragma aux gr_ibitblt_do_asm parm [esi] [edi] [eax] modify [ecx edi esi eax] = \ + "pusha" \ + "cld" \ + "call eax" \ + "popa" + + +void gr_ibitblt(grs_bitmap * source_bmp, grs_bitmap * dest_bmp, ubyte * mask ) +{ +#if defined(POLY_ACC) + Assert(source_bmp->bm_type == BM_LINEAR15); + pa_ibitblt(source_bmp->bm_data, dest_bmp->bm_data, mask); +#else + if (mask != NULL ) + gr_ibitblt_do_asm( source_bmp->bm_data, dest_bmp->bm_data, mask ); +#endif +} + + +void gr_ibitblt_find_hole_size( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy ) +{ + int x, y, count=0; +#if defined(POLY_ACC) + short c; +#else + ubyte c; +#endif + + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); + +#if defined(POLY_ACC) + Assert(mask_bmp->bm_type == BM_LINEAR15); + pa_flush(); +#endif + + *minx = mask_bmp->bm_w-1; + *maxx = 0; + *miny = mask_bmp->bm_h-1; + *maxy = 0; + + for ( y=0; ybm_h; y++ ) + for ( x=0; xbm_w; x++ ) { +#if defined(POLY_ACC) + c = *(short *)(mask_bmp->bm_data + mask_bmp->bm_rowsize * y + x * PA_BPP); + if (c >= 0) { // hi true means opaque. +#else + c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x]; + if (c == 255 ) { +#endif + if ( x < *minx ) *minx = x; + if ( y < *miny ) *miny = y; + if ( x > *maxx ) *maxx = x; + if ( y > *maxy ) *maxy = y; + count++; + } + } + + if ( count == 0 ) { + Error( "Bitmap for ibitblt doesn't have transparency!\n" ); + } +} + +#else // ifdef __MSDOS__ + +#include "pa_enabl.h" +#include "pstypes.h" +#include "gr.h" #include "ibitblt.h" #include "error.h" -//added 05/17/99 Matt Mueller #include "u_mem.h" -//end addition -MM +#include "grdef.h" + +#if defined(POLY_ACC) +#include "poly_acc.h" +#endif #define FIND_START 1 #define FIND_STOP 2 -#define MAX_WIDTH 1280 -#define MAX_SCANLINES 1024 -#define MAX_HOLES 10 +#define MAX_WIDTH 640 +#define MAX_SCANLINES 480 +#define MAX_HOLES 5 static short start_points[MAX_SCANLINES][MAX_HOLES]; static short hole_length[MAX_SCANLINES][MAX_HOLES]; static double *scanline = NULL; -// adb: gr_linear_movsd assumes c >= 4 -#define gr_linear_movsd(s,d,c) memcpy(d,s,c) - void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double) { int x, y, sw, sh, srowsize, drowsize, dstart, sy, dy; @@ -55,6 +685,11 @@ void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double) // variable setup +#if defined(POLY_ACC) + if ( PAEnabled ) + return; +#endif + sw = src_bmp->bm_w; sh = src_bmp->bm_h; srowsize = src_bmp->bm_rowsize; @@ -67,13 +702,13 @@ void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double) sy++; dest += drowsize; } - + if (pixel_double) { - ubyte *scan = (ubyte *)scanline; // set up for byte processing of scanline - + ubyte *scan = (ubyte *)scanline; // set up for byte processing of scanline + dy = sy; for (y = sy; y < sy + sh; y++) { - gr_linear_rep_movsd_2x(src, scan, sw); + gr_linear_movsd_double(src, scan, sw*2); current_hole = start_points[dy]; current_hole_length = hole_length[dy]; for (x = 0; x < MAX_HOLES; x++) { @@ -116,12 +751,67 @@ void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double) } } +#if defined(POLY_ACC) + +ulong *pa_emit_blit(int gencode, ulong *buf, int w, int h, int sx, int sy, int dx, int dy) +{ + if(w == 0 || h == 0) + return buf; + + if(gencode) + { + buf[0] = (w << 16) | h; + buf[1] = (sx << 16) | sy; + buf[2] = (dx << 16) | dy; + } + return buf + 3; +} + +void gr_ibitblt_create_mask_pa( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ) +{ + ulong *ret, *code = 0; + int pass, x, y, n; + ushort *s; + + Assert(mask_bmp->bm_type == BM_LINEAR15); + + srowsize /= PA_BPP; + + pa_flush(); + + // make two passes, first pass gets size of output block, second actually creates data. + for(pass = 0; pass != 2; ++pass) + { + for (y = sy; y < sy + sh; y++ ) + { + // first byte of interest in mask + s = (ushort *)(mask_bmp->bm_data + y * mask_bmp->bm_rowsize + sx * PA_BPP); + for ( x=0; x < sw; ) + { + for(; x != sw && (s[x] & 0x8000); ++x) // while opaque... + ; + for(n = 0; x != sw && !(s[x] & 0x8000); ++n, ++x) // while transparent... + ; + code = pa_emit_blit(pass, code, n, 1, x - n, y - sy, x + sx - n, y); + } + } + + if(pass == 0) { + ret = malloc((int)code + sizeof(ulong)); + ret[0] = (int)code / sizeof(ulong); // store num ulongs in list. + code = ret + 1; + } + } +// return (ubyte *)ret; +} +#endif + void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh, int srowsize) { int x, y; ubyte mode; int count = 0; - + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); for (y = 0; y < MAX_SCANLINES; y++) { @@ -130,7 +820,7 @@ void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh hole_length[y][x] = -1; } } - + for (y = sy; y < sy+sh; y++) { count = 0; mode = FIND_START; @@ -152,38 +842,68 @@ void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh } } -//added 7/11/99 by adb to prevent memleaks -static void free_scanline(void) +#if defined(POLY_ACC) + +void gr_ibitblt_find_hole_size_pa( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy ) { - if (scanline) d_free(scanline); -} -//end additions - adb + int x, y, count=0; + short c; + + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); + Assert(mask_bmp->bm_type == BM_LINEAR15); + while(!pa_idle()); + + *minx = mask_bmp->bm_w-1; + *maxx = 0; + *miny = mask_bmp->bm_h-1; + *maxy = 0; + + for ( y=0; ybm_h; y++ ) + for ( x=0; xbm_w; x++ ) { + c = *(short *)(mask_bmp->bm_data + mask_bmp->bm_rowsize * y + x * PA_BPP); + if (c >= 0) { // hi true means opaque. + if ( x < *minx ) *minx = x; + if ( y < *miny ) *miny = y; + if ( x > *maxx ) *maxx = x; + if ( y > *maxy ) *maxy = y; + count++; + } + } + + if ( count == 0 ) { + Error( "Bitmap for ibitblt doesn't have transparency!\n" ); + } +} +#endif void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int *maxx, int *maxy) { ubyte c; int x, y, count = 0; - + +#if defined(POLY_ACC) + if ( PAEnabled ) { + gr_ibitblt_find_hole_size_pa( mask_bmp, minx, miny, maxx, maxy ); + return; + } +#endif + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); Assert( mask_bmp->bm_flags&BM_FLAG_TRANSPARENT ); - + *minx = mask_bmp->bm_w - 1; *maxx = 0; *miny = mask_bmp->bm_h - 1; *maxy = 0; - //changed 7/11/99 by adb to prevent memleaks - if (scanline == NULL) { - scanline = (double *)d_malloc(sizeof(double) * (MAX_WIDTH / sizeof(double))); - atexit(free_scanline); - } - //end changes - adb + if (scanline == NULL) + scanline = (double *)malloc(sizeof(double) * (MAX_WIDTH / sizeof(double))); for (y = 0; y < mask_bmp->bm_h; y++) { for (x = 0; x < mask_bmp->bm_w; x++) { c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x]; - if (c == TRANSPARENCY_COLOR) { // don't look for transparency color here. + if (c == TRANSPARENCY_COLOR) { // don't look for transparancy color here. count++; if (x < *minx) *minx = x; if (y < *miny) *miny = y; @@ -194,3 +914,5 @@ void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int * } Assert (count); } + +#endif // ifdef __MSDOS__ -- 2.39.2