/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit bitmap blitting (written for speed, not readability :-) * * By Michal Mertl. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "blit.inc" #ifdef ALLEGRO_COLOR24 .text /* void _linear_clear_to_color24(BITMAP *bitmap, int color); * Fills a linear bitmap with the specified color. */ FUNC(_linear_clear_to_color24) pushl %ebp movl %esp, %ebp subl $12, %esp /* 12 bytes temp space for local variables */ pushl %edi pushl %ebx pushl %es movl ARG1, %edx /* edx = bmp */ movl BMP_CT(%edx), %ebx /* line to start at */ movl BMP_SEG(%edx), %eax /* select segment */ movl %eax, %es cld movl ARG2, %eax /* pixel color */ movl %eax, -8(%ebp) movl %eax, -5(%ebp) movl %ebx, ARG2 /* line to start at (in ARG2 is line now)*/ movl BMP_CB(%edx), %eax subl %ebx, %eax movl %eax, -12(%ebp) /* line counter */ movl BMP_CR(%edx), %ecx subl BMP_CL(%edx), %ecx /* line length */ _align_ clear_loop: pushl %ecx movl ARG2, %eax movl ARG1, %edx movl BMP_CL(%edx), %edi /* xstart */ WRITE_BANK() /* select bank */ leal (%edi, %edi, 2), %edi /* xstart *= 3 */ addl %eax, %edi /* address = lineoffset+xstart*3 */ movl -8(%ebp), %eax movl -7(%ebp), %ebx movl -6(%ebp), %edx cmpl $4, %ecx jb clear_short_line subl $4, %ecx /* test loop for sign flag */ cld _align_ clear_inner_loop: /* plots 4 pixels an once */ movl %eax, %es:(%edi) movl %ebx, %es:4(%edi) movl %edx, %es:8(%edi) addl $12, %edi subl $4, %ecx jns clear_inner_loop addl $4, %ecx /* add the helper back */ jz clear_normal_line _align_ clear_short_line: movw %ax, %es:(%edi) /* plots remaining pixels (max 3) */ movb %dl, %es:2(%edi) addl $3, %edi decl %ecx jg clear_short_line _align_ clear_normal_line: popl %ecx incl ARG2 /* inc current line */ decl -12(%ebp) /* dec loop counter */ jnz clear_loop /* and loop */ popl %es movl ARG1, %edx UNWRITE_BANK() popl %ebx popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_clear_to_color() */ /* void _linear_blit24(BITMAP *source, BITMAP *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Normal forwards blitting routine for linear bitmaps. */ FUNC(_linear_blit24) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es movl B_DEST_X, %edi leal (%edi, %edi, 2), %edi movl %edi, B_DEST_X movl B_SOURCE_X, %esi leal (%esi, %esi, 2), %esi movl %esi, B_SOURCE_X movl B_WIDTH, %ecx leal (%ecx, %ecx, 2), %ecx movl %ecx, B_WIDTH movl %ds, %ebx /* save data segment selector */ cld /* for forward copy */ _align_ blit_loop_blitter24: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi /* edi = eax+3*edi */ movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi /* esi = eax+3*esi */ movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds shrl $1, %ecx jnc notcarry1 movsb _align_ notcarry1: shrl $1, %ecx jnc notcarry2 movsw _align_ notcarry2: rep ; movsl movl %ebx, %ds /* restore data segment */ incl B_SOURCE_Y incl B_DEST_Y decl B_HEIGHT jg blit_loop_blitter24 /* and loop */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit24() */ /* void _linear_blit_backward24(BITMAP *source, BITMAP *dest, int source_x, * int source_y, int dest_x, dest_y, int width, height); * Reverse blitting routine, for overlapping linear bitmaps. */ FUNC(_linear_blit_backward24) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_HEIGHT, %eax /* y values go from high to low */ decl %eax addl %eax, B_SOURCE_Y addl %eax, B_DEST_Y movl B_WIDTH, %eax /* x values go from high to low */ decl %eax addl %eax, B_SOURCE_X addl %eax, B_DEST_X movl B_DEST_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_DEST_X movl B_SOURCE_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_SOURCE_X movl B_WIDTH, %eax leal (%eax, %eax, 2), %eax movl %eax, B_WIDTH movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es _align_ blit_backwards_loop: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi /* edi = eax+3*esi */ movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi /* esi = eax+3*esi */ movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds std /* backwards */ shrl $1, %ecx jnc not_carry1 movsb _align_ not_carry1: shrl $1, %ecx jnc not_carry2 movsw _align_ not_carry2: rep ; movsl movl %ebx, %ds /* restore data segment */ decl B_SOURCE_Y decl B_DEST_Y decl B_HEIGHT jg blit_backwards_loop /* and loop */ cld /* finished */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit_backward24() */ FUNC(_linear_blit24_end) ret /* void _linear_masked_blit24(BITMAP *source, *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Masked (skipping zero pixels) blitting routine for linear bitmaps. */ FUNC(_linear_masked_blit24) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx movl BMP_SEG(%edx), %eax movl %eax, %es cld movl B_DEST_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_DEST_X movl B_SOURCE_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_SOURCE_X _align_ blit_loop_blitter: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi movl B_SOURCE,%edx movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi movl B_WIDTH, %ecx /* x loop counter */ _align_ inner: lodsl decl %esi andl $0xFFFFFF, %eax cmpl $MASK_COLOR_24, %eax je masked_blit_skip movw %ax, %es:(%edi) shrl $16, %eax movb %al, %es:2(%edi) addl $3, %edi jmp befloop _align_ masked_blit_skip: addl $3, %edi _align_ befloop: loop inner movl %ebx, %ds /* restore data segment */ incl B_SOURCE_Y incl B_DEST_Y decl B_HEIGHT jg blit_loop_blitter /* and loop */ popl %es /* the source must be a memory bitmap, no need for * movl B_SOURCE, %edx * UNREAD_BANK() */ movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_masked_blit24() */ #endif /* ifdef ALLEGRO_COLOR24 */