1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
; Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
;
; This file is part of Aladdin Ghostscript.
;
; Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
; or distributor accepts any responsibility for the consequences of using it,
; or for whether it serves any particular purpose or works at all, unless he
; or she says so in writing. Refer to the Aladdin Ghostscript Free Public
; License (the "License") for full details.
;
; Every copy of Aladdin Ghostscript must include a copy of the License,
; normally in a plain ASCII text file named PUBLIC. The License grants you
; the right to copy, modify and redistribute Aladdin Ghostscript, but only
; under certain conditions described in the License. Among other things, the
; License requires that the copyright notice and this notice be preserved on
; all copies.
; Id: gdevegaa.asm
; 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
|