/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit sprite drawing (written for speed, not readability :-) * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "sprite.inc" #ifdef ALLEGRO_COLOR16 .text /* void _linear_draw_trans_sprite15(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a translucent sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_sprite15) START_SPRITE_DRAW(trans_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans, %edi) movw (%esi), %ax /* read source pixel */ cmpw $MASK_COLOR_15, %ax jz trans_sprite_skip movw %es:(%ebx, %edi), %dx /* read memory pixel */ pushl GLOBL(_blender_alpha) pushl %edx pushl %eax call *GLOBL(_blender_func15) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ trans_sprite_skip: addl $2, %ebx addl $2, %esi T_SPRITE_END_X(trans) /* no cleanup at end of line */ SPRITE_END_Y(trans) trans_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_trans_sprite15() */ /* void _linear_draw_trans_rgba_sprite15(BITMAP *bmp, sprite, int x, y); * Draws a translucent 32 bit sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_sprite15) START_SPRITE_DRAW(trans_rgba_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans_rgba, %edi) movl (%esi), %eax /* read source pixel */ cmpl $MASK_COLOR_32, %eax jz trans_rgba_sprite_skip movw %es:(%ebx, %edi), %dx /* read memory pixel */ pushl GLOBL(_blender_alpha) pushl %edx pushl %eax call *GLOBL(_blender_func15x) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ trans_rgba_sprite_skip: addl $2, %ebx addl $4, %esi T_SPRITE_END_X(trans_rgba) /* no cleanup at end of line */ SPRITE_END_Y(trans_rgba) trans_rgba_sprite_done: END_SPRITE_DRAW() ret /* end _linear_draw_trans_rgba_sprite15() */ /* void _linear_draw_lit_sprite15(BITMAP *bmp, BITMAP *sprite, int x, y, color); * Draws a lit sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_sprite15) #define ALPHA ARG5 START_SPRITE_DRAW(lit_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl ALPHA, %edi _align_ LT_SPRITE_LOOP(lit_sprite) movw (%esi), %ax /* read pixel */ cmpw $MASK_COLOR_15, %ax jz lit_sprite_skip pushl %edi pushl %eax pushl GLOBL(_blender_col_15) call *GLOBL(_blender_func15) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write pixel */ lit_sprite_skip: addl $2, %esi addl $2, %ebx T_SPRITE_END_X(lit_sprite) SPRITE_END_Y(lit_sprite) lit_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_lit_sprite15() */ /* void _linear_draw_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, int x, y) * Draws an RLE sprite onto a linear bitmap at the specified position. */ FUNC(_linear_draw_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ rep ; movsw /* no special initialisation required */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ shrl $1, %ecx ; \ jnc rle_noclip_no_word ; \ movsw /* copy odd word? */ ; \ rle_noclip_no_word: ; \ jz rle_noclip_x_loop ; \ rep ; movsl /* 32 bit string copy */ /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpw $MASK_COLOR_15, %ax ; \ je done ; \ testw %ax, %ax ; \ js skip /* adds the offset in %eax onto the destination address */ #define ADD_EAX_EDI() \ leal (%edi, %eax, 2), %edi /* zero extend %ax into %eax */ #define RLE_ZEX_EAX() \ movzwl %ax, %eax /* zero extend %ax into %ecx */ #define RLE_ZEX_ECX() \ movzwl %ax, %ecx /* sign extend %ax into %eax */ #define RLE_SEX_EAX() \ movswl %ax, %eax /* do it! */ DO_RLE(rle, 2, w, %ax, $MASK_COLOR_15) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_trans_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rle_run_loop /* do it! */ DO_RLE(rle_trans, 2, w, %ax, $MASK_COLOR_15) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_lit_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y, int color) * Draws a tinted RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl R_COLOR, %ebx ; \ movl %ecx, R_TMP ; \ ; \ lit_rle_clipped_run_loop##n: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_15) ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP ; \ jg lit_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ movl R_COLOR, %ebx /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP ; \ ; \ lit_rle_run_loop: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_15) ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP ; \ jg lit_rle_run_loop /* do it! */ DO_RLE(rle_lit, 2, w, %ax, $MASK_COLOR_15) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #undef TEST_RLE_COMMAND #undef RLE_ZEX_EAX #undef RLE_ZEX_ECX #undef RLE_SEX_EAX /* void _linear_draw_trans_rgba_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent 32 bit RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_run_loop /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpl $MASK_COLOR_32, %eax ; \ je done ; \ testl %eax, %eax ; \ js skip /* no zero or sign extend required */ #define RLE_ZEX_EAX() #define RLE_SEX_EAX() /* this can be a simple copy... */ #define RLE_ZEX_ECX() \ movl %eax, %ecx /* do it! */ DO_RLE(rle_trans_rgba, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #endif /* ifdef ALLEGRO_COLOR16 */