summaryrefslogtreecommitdiff
path: root/gs/src/gdevegaa.asm
blob: 4cf91d2c3d7de4da628c484ca1b5daf427895282 (plain)
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