1; Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. 2; 3; This software is provided AS-IS with no warranty, either express or 4; implied. 5; 6; This software is distributed under license and may not be copied, 7; modified or distributed except as expressly authorized under the terms 8; of the license contained in the file LICENSE in this distribution. 9; 10; For more information about licensing, please refer to 11; http://www.ghostscript.com/licensing/. For information on 12; commercial licensing, go to http://www.artifex.com/licensing/ or 13; contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14; San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 16; $Id: gdevegaa.asm,v 1.4 2002/02/21 22:24:51 giles Exp $ 17; gdevegaasm.asm 18; Assembly code for Ghostscript PC frame buffer driver 19 20gdevegaasm_TEXT SEGMENT BYTE PUBLIC 'CODE' 21 ASSUME CS:gdevegaasm_TEXT 22 23; Note: Turbo C uses si and di for register variables, so 24; we have to preserve them. 25 26; Normal entry and exit. Arguments are relative to bp. 27enterp macro 28 push bp 29 mov bp,sp 30 x = 6 ; offset of arguments, 31 ; large code model 32 endm 33leavep macro 34 pop bp 35 endm 36; Fast entry and exit, for procedures that don't use bx until 37; they've fetched all their arguments. Arguments are relative to ss:bx. 38enterf macro 39 mov bx,sp 40 x = 4 ; offset of arguments, 41 ; large code model 42 endm 43leavef macro 44 endm 45 46; Fast call to VESA set-page routine. 47; void vesa_call_set_page(void (*set_page_proc)(int), int page_no, int win_no) 48 PUBLIC _vesa_call_set_page 49_vesa_call_set_page proc far 50 enterf 51 mov ax,4f05h 52 mov dx,ss:[bx+x+4] ; page_no 53 push ss:[bx+x+2] ; set_page_proc 54 push ss:[bx+x] 55 mov bx,ss:[bx+x+6] ; win_no 56 ret 57_vesa_call_set_page endp 58 59; Structure for operation parameters. 60; Note that this structure is shared with C code. 61; Not all parameters are used for every operation. 62; typedef struct rop_params_s { 63p_dest equ 0 ; fb_ptr dest; /* pointer to frame buffer */ 64p_draster equ 4 ; int draster; /* raster of frame buffer */ 65p_src equ 6 ; const byte far *src; /* pointer to source data */ 66p_sraster equ 10 ; int sraster; /* source raster */ 67p_width equ 12 ; int width; /* width in bytes */ 68p_height equ 14 ; int height; /* height in scan lines */ 69p_shift equ 16 ; int shift; /* amount to right shift source */ 70p_invert equ 18 ; int invert; /* 0 or -1 to invert source */ 71p_data equ 20 ; int data; /* data for fill */ 72; } rop_params; 73 74; void memsetcol(rop_params _ss *rop) 75; { byte far *addr = rop->dest; 76; int yc = rop->height; 77; while ( yc-- ) 78; { byte discard = *addr; 79; *addr = rop->data; 80; addr += rop->draster; 81; } 82; } 83 PUBLIC _memsetcol 84_memsetcol proc far 85 enterf 86 push ds 87 mov ax,ss 88 mov ds,ax 89 mov bx,[bx+x] ; rop 90 mov cx,[bx].p_height 91 jcxz msc0 ; height == 0 92 mov ax,[bx].p_data 93 mov dx,[bx].p_draster 94 lds bx,[bx].p_dest 95; Unroll the loop -- two copies. 96 inc cx ;round up to nearest word. cx>=2 now. 97 shr cx,1 ;make byte count into word count. 98 jnc msc2 ;if it had been odd, do a half word first. 99msc1: mov ah,[bx] 100 mov [bx],al 101 add bx,dx 102msc2: mov ah,[bx] 103 mov [bx],al 104 add bx,dx 105 loop msc1 106 pop ds 107msc0: leavef 108 ret 109_memsetcol ENDP 110 111; void memsetrect(rop_params _ss *rop) 112; { byte far *addr = rop->dest; 113; int yc = rop->height; 114; while ( yc-- ) 115; { int cnt = rop->width; 116; while ( cnt-- ) *addr++ = rop->data; 117; addr += rop->drast - rop->width; 118; } 119; } 120 PUBLIC _memsetrect 121_memsetrect proc far 122 enterf 123 push ds 124 mov ax,ss 125 mov ds,ax 126 mov bx,[bx+x] ; rop 127 mov cx,[bx].p_height 128 jcxz msr0 ; height == 0 129 push si 130 push di 131 mov ax,[bx].p_data 132 les di,[bx].p_dest 133 cld 134 mov dx,[bx].p_draster 135 mov si,cx ; si = height 136 mov cx,[bx].p_width 137 sub dx,cx 138 cmp cx,10 139 ja msrl ; large count, use fast loop 140; Small count, rep stosb is faster. 141msrs: mov cx,[bx].p_width 142 rep stosb 143 add di,dx 144 dec si ; count reps 145 jnz msrs 146 pop di 147 pop si 148msr0: pop ds 149 leavef 150 ret 151; Large count, loop by words rather than bytes. 152msrl: mov ah,al ;we may be storing words... 153msr1: mov cx,[bx].p_width 154 test di,1 ;test for an even address 155 je msr2 ;if even, we can store words. 156 stosb ;otherwise we need to even it out. 157 dec cx ;(cx is at least one here) 158msr2: shr cx,1 ;convert byte count into word count 159 rep stosw ;store them puppies as fast as we can. 160 jnc msr3 ;if an odd number, store it, too. 161 stosb ;(no need to dec cx here). 162msr3: add di,dx 163 dec si ; count reps 164 jnz msr1 165 pop di 166 pop si 167 pop ds 168 leavef 169 ret 170_memsetrect ENDP 171 172; void memrwcol(rop_params _ss *rop) 173; { byte far *dp = rop->dest; 174; const byte far *sp = rop->src; 175; int yc = rop->height; 176; int shift = rop->shift; 177; while ( yc-- ) 178; { byte discard = *dp; 179; *dp = ((*sp >> shift) + (*sp << (8 - shift))) ^ rop->invert; 180; dp += rop->draster, sp += rop->sraster; 181; } 182; } 183 PUBLIC _memrwcol 184_memrwcol proc far 185 enterp 186 push ds 187 mov ax,ss 188 mov ds,ax 189 mov bx,[bp+x] ; rop 190 cmp word ptr [bx].p_height,0 191 jz short mrw0 192 push si 193 push di 194; Register usage: 195; ds:si = sp, es:di = dp, bx = sraster, dx = draster, cl = shift, 196; ch = invert, ah = low byte of yc. 197 push [bx].p_height 198 mov dx,[bx].p_draster 199 mov ax,[bx].p_sraster 200 mov cl,[bx].p_shift 201 mov ch,[bx].p_invert 202 les di,[bx].p_dest 203 lds si,[bx].p_src 204 mov bx,ax 205 mov ah,[bp-8] ; low byte of yc 206 test ah,ah 207 jz mrw2 208mrw1: mov al,[si] 209 ror al,cl 210 xor al,ch 211 xchg es:[di],al 212 add si,bx 213 add di,dx 214 dec ah 215 jnz mrw1 216mrw2: dec byte ptr [bp-7] ; high byte of yc 217 jge mrw1 218 add sp,2 ; pop yc 219 pop di 220 pop si 221mrw0: pop ds 222 leavep 223 ret 224_memrwcol ENDP 225 226; void memrwcol2(rop_params _ss *rop) 227; { byte far *dp = rop->dest; 228; const byte far *sp = rop->src; 229; int yc = rop->height; 230; int shift = rop->shift; 231; while ( yc-- ) 232; { byte discard = *dp; 233; *dp = ((sp[1] >> shift) + (*sp << (8 - shift))) ^ rop->invert; 234; dp += rop->draster, sp += rop->sraster; 235; } 236; } 237 PUBLIC _memrwcol2 238_memrwcol2 proc far 239 enterp 240 push ds 241 mov ax,ss 242 mov ds,ax 243 mov bx,[bp+x] ; rop 244 cmp word ptr [bx].p_height,0 245 jz short mrw20 246 push si 247 push di 248; Register usage: 249; ds:si = sp, es:di = dp, bx = sraster, dx = draster, cl = shift, 250; ch = invert. 251 push [bx].p_height 252 mov dx,[bx].p_draster 253 mov ax,[bx].p_sraster 254 mov cl,[bx].p_shift 255 mov ch,[bx].p_invert 256 les di,[bx].p_dest 257 lds si,[bx].p_src 258 mov bx,ax 259mrw21: mov ax,[si] ; bytes are in wrong order... 260 ror ax,cl 261 xor ah,ch ; ... so result is in ah 262 xchg es:[di],ah 263 add si,bx 264 add di,dx 265 dec word ptr [bp-8] ; yc 266 jg mrw21 267 add sp,2 ; pop yc 268 pop di 269 pop si 270mrw20: pop ds 271 leavep 272 ret 273_memrwcol2 ENDP 274 275gdevegaasm_TEXT ENDS 276 END 277