; Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. ; ; This software is provided AS-IS with no warranty, either express or ; implied. ; ; This software is distributed under license and may not be copied, ; modified or distributed except as expressly authorized under the terms ; of the license contained in the file LICENSE in this distribution. ; ; For more information about licensing, please refer to ; http://www.ghostscript.com/licensing/. For information on ; commercial licensing, go to http://www.artifex.com/licensing/ or ; contact Artifex Software, Inc., 101 Lucas Valley Road #110, ; San Rafael, CA 94903, U.S.A., +1(415)492-9861. ; $Id: gdevegaa.asm,v 1.4 2002/02/21 22:24:51 giles Exp $ ; gdevegaasm.asm ; Assembly code for Ghostscript PC frame buffer driver gdevegaasm_TEXT SEGMENT BYTE PUBLIC 'CODE' ASSUME CS:gdevegaasm_TEXT ; Note: Turbo C uses si and di for register variables, so ; we have to preserve them. ; Normal entry and exit. Arguments are relative to bp. enterp macro push bp mov bp,sp x = 6 ; offset of arguments, ; large code model endm leavep macro pop bp endm ; Fast entry and exit, for procedures that don't use bx until ; they've fetched all their arguments. Arguments are relative to ss:bx. enterf macro mov bx,sp x = 4 ; offset of arguments, ; large code model endm leavef macro endm ; Fast call to VESA set-page routine. ; void vesa_call_set_page(void (*set_page_proc)(int), int page_no, int win_no) PUBLIC _vesa_call_set_page _vesa_call_set_page proc far enterf mov ax,4f05h mov dx,ss:[bx+x+4] ; page_no push ss:[bx+x+2] ; set_page_proc push ss:[bx+x] mov bx,ss:[bx+x+6] ; win_no ret _vesa_call_set_page endp ; Structure for operation parameters. ; Note that this structure is shared with C code. ; Not all parameters are used for every operation. ; typedef struct rop_params_s { p_dest equ 0 ; fb_ptr dest; /* pointer to frame buffer */ p_draster equ 4 ; int draster; /* raster of frame buffer */ p_src equ 6 ; const byte far *src; /* pointer to source data */ p_sraster equ 10 ; int sraster; /* source raster */ p_width equ 12 ; int width; /* width in bytes */ p_height equ 14 ; int height; /* height in scan lines */ p_shift equ 16 ; int shift; /* amount to right shift source */ p_invert equ 18 ; int invert; /* 0 or -1 to invert source */ p_data equ 20 ; int data; /* data for fill */ ; } rop_params; ; void memsetcol(rop_params _ss *rop) ; { byte far *addr = rop->dest; ; int yc = rop->height; ; while ( yc-- ) ; { byte discard = *addr; ; *addr = rop->data; ; addr += rop->draster; ; } ; } PUBLIC _memsetcol _memsetcol proc far enterf push ds mov ax,ss mov ds,ax mov bx,[bx+x] ; rop mov cx,[bx].p_height jcxz msc0 ; height == 0 mov ax,[bx].p_data mov dx,[bx].p_draster lds bx,[bx].p_dest ; Unroll the loop -- two copies. inc cx ;round up to nearest word. cx>=2 now. shr cx,1 ;make byte count into word count. jnc msc2 ;if it had been odd, do a half word first. msc1: mov ah,[bx] mov [bx],al add bx,dx msc2: mov ah,[bx] mov [bx],al add bx,dx loop msc1 pop ds msc0: leavef ret _memsetcol ENDP ; void memsetrect(rop_params _ss *rop) ; { byte far *addr = rop->dest; ; int yc = rop->height; ; while ( yc-- ) ; { int cnt = rop->width; ; while ( cnt-- ) *addr++ = rop->data; ; addr += rop->drast - rop->width; ; } ; } PUBLIC _memsetrect _memsetrect proc far enterf push ds mov ax,ss mov ds,ax mov bx,[bx+x] ; rop mov cx,[bx].p_height jcxz msr0 ; height == 0 push si push di mov ax,[bx].p_data les di,[bx].p_dest cld mov dx,[bx].p_draster mov si,cx ; si = height mov cx,[bx].p_width sub dx,cx cmp cx,10 ja msrl ; large count, use fast loop ; Small count, rep stosb is faster. msrs: mov cx,[bx].p_width rep stosb add di,dx dec si ; count reps jnz msrs pop di pop si msr0: pop ds leavef ret ; Large count, loop by words rather than bytes. msrl: mov ah,al ;we may be storing words... msr1: mov cx,[bx].p_width test di,1 ;test for an even address je msr2 ;if even, we can store words. stosb ;otherwise we need to even it out. dec cx ;(cx is at least one here) msr2: shr cx,1 ;convert byte count into word count rep stosw ;store them puppies as fast as we can. jnc msr3 ;if an odd number, store it, too. stosb ;(no need to dec cx here). msr3: add di,dx dec si ; count reps jnz msr1 pop di pop si pop ds leavef ret _memsetrect ENDP ; void memrwcol(rop_params _ss *rop) ; { byte far *dp = rop->dest; ; const byte far *sp = rop->src; ; int yc = rop->height; ; int shift = rop->shift; ; while ( yc-- ) ; { byte discard = *dp; ; *dp = ((*sp >> shift) + (*sp << (8 - shift))) ^ rop->invert; ; dp += rop->draster, sp += rop->sraster; ; } ; } PUBLIC _memrwcol _memrwcol proc far enterp push ds mov ax,ss mov ds,ax mov bx,[bp+x] ; rop cmp word ptr [bx].p_height,0 jz short mrw0 push si push di ; Register usage: ; ds:si = sp, es:di = dp, bx = sraster, dx = draster, cl = shift, ; ch = invert, ah = low byte of yc. push [bx].p_height mov dx,[bx].p_draster mov ax,[bx].p_sraster mov cl,[bx].p_shift mov ch,[bx].p_invert les di,[bx].p_dest lds si,[bx].p_src mov bx,ax mov ah,[bp-8] ; low byte of yc test ah,ah jz mrw2 mrw1: mov al,[si] ror al,cl xor al,ch xchg es:[di],al add si,bx add di,dx dec ah jnz mrw1 mrw2: dec byte ptr [bp-7] ; high byte of yc jge mrw1 add sp,2 ; pop yc pop di pop si mrw0: pop ds leavep ret _memrwcol ENDP ; void memrwcol2(rop_params _ss *rop) ; { byte far *dp = rop->dest; ; const byte far *sp = rop->src; ; int yc = rop->height; ; int shift = rop->shift; ; while ( yc-- ) ; { byte discard = *dp; ; *dp = ((sp[1] >> shift) + (*sp << (8 - shift))) ^ rop->invert; ; dp += rop->draster, sp += rop->sraster; ; } ; } PUBLIC _memrwcol2 _memrwcol2 proc far enterp push ds mov ax,ss mov ds,ax mov bx,[bp+x] ; rop cmp word ptr [bx].p_height,0 jz short mrw20 push si push di ; Register usage: ; ds:si = sp, es:di = dp, bx = sraster, dx = draster, cl = shift, ; ch = invert. push [bx].p_height mov dx,[bx].p_draster mov ax,[bx].p_sraster mov cl,[bx].p_shift mov ch,[bx].p_invert les di,[bx].p_dest lds si,[bx].p_src mov bx,ax mrw21: mov ax,[si] ; bytes are in wrong order... ror ax,cl xor ah,ch ; ... so result is in ah xchg es:[di],ah add si,bx add di,dx dec word ptr [bp-8] ; yc jg mrw21 add sp,2 ; pop yc pop di pop si mrw20: pop ds leavep ret _memrwcol2 ENDP gdevegaasm_TEXT ENDS END