OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [MW_0_8_9PRE7/] [mw/] [src/] [drivers/] [asmplan4.s] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
; Copyright (c) 1999 Greg Haerr <greg@censoft.com>
2
; Copyright (c) 1991 David I. Bell
3
; Permission is granted to use, distribute, or modify this source,
4
; provided that this copyright notice remains intact.
5
;
6
; EGA/VGA Screen Driver 16 color 4 planes, higher speed MASM version
7
;
8
; Note: this file is a replacement for vgaplan4.c, when raw
9
; speed rather than portability is desired
10
;
11
; The algorithms for some of these routines are taken from the book:
12
; Programmer's Guide to PC and PS/2 Video Systems by Richard Wilton.
13
;
14
; Routines to draw pixels and lines for EGA/VGA resolutions.
15
; The drawing mode in the data/rotate register is not changed in this
16
; module, and must be changed as necessary by the callers.
17
;
18
PIXBYTES        = 80            ; number of bytes in scan line
19
 
20
 
21
MSC = 1
22
;__MEDIUM__ = 1
23
        include asm.h
24
        .header
25
 
26
        .cextrn gr_mode,word    ; temp kluge devdraw.c graphics draw mode
27
        .dseg
28
mode_table:
29
        db      00h,18h,10h,08h ; vga draw modes
30
 
31
        .cseg
32
 
33
;
34
; int ega_init(PSD psd)
35
;
36
        .cproc  ega_init
37
        mov     ax,1            ; success
38
        ret
39
        .cendp  ega_init
40
 
41
;
42
; Routine to draw a horizontal line.
43
; Called from C:
44
;       ega_drawhine(x1, x2, y, color);
45
;
46
;       works in the following EGA and VGA modes:
47
;       200 line 16 colors modes
48
;       350 line modes
49
;       640x480 16 color
50
 
51
; argument offsets from bp
52
x1      = arg1          ; first X coordinate
53
x2      = arg1 + 2      ; second X coordinate
54
y       = arg1 + 4      ; second Y coordinate
55
color   = arg1 + 6      ; pixel value
56
 
57
        .cproc  ega_drawhline
58
        push    bp              ; setup stack frame and preserve registers
59
        mov     bp, sp
60
        push    si
61
        push    di
62
        push    es
63
 
64
        ; configure the graphics controller
65
 
66
        mov     dx, 03ceh       ; DX := Graphics Controller port address
67
 
68
        mov     al, #3          ; set data rotate register
69
        lea     bx, mode_table
70
        add     bx, @gr_mode
71
        mov     ah, [bx]
72
        out     dx, ax
73
 
74
        mov     ah, color[bp]   ; pixel value
75
        xor     al, al          ; Set/Reset register number (0)
76
        out     dx, ax
77
 
78
        mov     ax, 0f01h       ; AH := bit plane mask for Enable Set/Reset
79
        out     dx, ax          ; AL := Enable Set/Reset register number
80
 
81
        push    ds              ; preserve DS
82
 
83
        mov     ax, y[bp]
84
        mov     bx, x1[bp]
85
 
86
        ; compute pixel address
87
        mov     dx, offset PIXBYTES     ; AX := [row * PIXBYTES]
88
        mul     dx
89
        mov     cl, bl          ; save low order column bits
90
        shr     bx, 1           ; BX := [col / 8]
91
        shr     bx, 1
92
        shr     bx, 1
93
        add     bx, ax          ; BX := [row * PIXBYTES] + [col / 8]
94
        and     cl, 07h         ; CL := [col % 8]
95
        xor     cl, 07h         ; CL := 7 - [col % 8]
96
        mov     ah, 01h         ; AH := 1 << [7 - [col % 8]]    [mask]
97
        mov     dx, 0a000h      ; ES := EGA buffer segment address
98
        mov     es, dx
99
                                ; AH := bit mask
100
                                ; ES:BX -> video buffer
101
                                ; CL := number bits to shift left
102
        mov     di, bx          ; ES:DI -> buffer
103
        mov     dh, ah          ; DH := unshifted bit mask for left byte
104
 
105
        not     dh
106
        shl     dh, cl          ; DH := reverse bit mask for first byte
107
        not     dh              ; DH := bit mask for first byte
108
 
109
        mov     cx, x2[bp]
110
        and     cl, 7
111
        xor     cl, 7           ; CL := number of bits to shift left
112
        mov     dl, 0ffh        ; DL := unshifted bit mask for right byte
113
        shl     dl, cl          ; DL := bit mask for last byte
114
 
115
        ; determine byte offset of first and last pixel in the line
116
 
117
        mov     ax, x2[bp]      ; AX := x2
118
        mov     bx, x1[bp]      ; BX := x1
119
 
120
        mov     cl, 3           ; bits to convert pixels to bytes
121
 
122
        shr     ax, cl          ; AX := byte offset of X2
123
        shr     bx, cl          ; BX := byte offset of X1
124
        mov     cx, ax
125
        sub     cx, bx          ; CX := [number of bytes in line] - 1
126
 
127
        ; get Graphics Controller port address into DX
128
 
129
        mov     bx, dx          ; BH := bit mask for first byte
130
                                ; BL := bit mask for last byte
131
        mov     dx, 03ceh       ; DX := Graphics Controller port
132
        mov     al, 8           ; AL := Bit mask Register number
133
 
134
        ; make video buffer addressable through DS:SI
135
 
136
        push    es
137
        pop     ds
138
        mov     si, di          ; DS:SI -> video buffer
139
 
140
        ; set pixels in leftmost byte of the line
141
 
142
        or      bh, bh
143
        js      L43             ; jump if byte-aligned [x1 is leftmost]
144
 
145
        or      cx, cx
146
        jnz     L42             ; jump if more than one byte in the line
147
 
148
        and     bl, bh          ; BL := bit mask for the line
149
        jmp short L44
150
 
151
L42:    mov     ah, bh          ; AH := bit mask for first byte
152
        out     dx, ax          ; update graphics controller
153
 
154
        movsb                   ; update bit planes
155
        dec     cx
156
 
157
        ; use a fast 8086 machine instruction to draw the remainder of the line
158
 
159
L43:    mov     ah, 0ffh        ; AH := bit mask
160
        out     dx, ax          ; update Bit Mask register
161
        rep movsb               ; update all pixels in the line
162
 
163
        ; set pixels in the rightmost byte of the line
164
 
165
L44:    mov     ah, bl          ; AH := bit mask for last byte
166
        out     dx, ax          ; update Graphics Controller
167
        movsb                   ; update bit planes
168
 
169
        pop     ds              ; restore ds
170
 
171
 
172
        ; restore default Graphics Controller state and return to caller
173
        ;;xor   ax, ax          ; AH := 0, AL := 0
174
        ;;out   dx, ax          ; restore Set/Reset register
175
        ;;inc   ax              ; AH := 0, AL := 1
176
        ;;out   dx, ax          ; restore Enable Set/Reset register
177
        ;;mov   ax, 0ff08h      ; AH := 0xff, AL := 0
178
        ;;out   dx, ax          ; restore Bit Mask register
179
 
180
        pop     es
181
        pop     di
182
        pop     si
183
        pop     bp
184
        ret
185
        .cendp  ega_drawhline
186
 
187
 
188
;
189
; Routine to draw a vertical line.
190
; Called from C:
191
;       ega_drawvline(x, y1, y2, color);
192
;
193
;       works in the following EGA and VGA modes:
194
;       200 line 16 colors modes
195
;       350 line modes
196
;       640x480 16 color
197
 
198
; argument offsets from bp
199
x       = arg1          ; first X coordinate
200
y1      = arg1 + 2      ; first Y coordinate
201
y2      = arg1 + 4      ; second Y coordinate
202
color   = arg1 + 6      ; pixel value
203
 
204
        .cproc  ega_drawvline
205
        push    bp              ; setup stack frame and preserve registers
206
        mov     bp, sp
207
        push    ds
208
 
209
        ; configure the graphics controller
210
 
211
        mov     dx, 03ceh       ; DX := Graphics Controller port address
212
 
213
        mov     al, #3          ; set data rotate register
214
        lea     bx, mode_table
215
        add     bx, @gr_mode
216
        mov     ah, [bx]
217
        out     dx, ax
218
 
219
        mov     ah, color[bp]   ; pixel value
220
        xor     al, al          ; Set/Reset register number (0)
221
        out     dx, ax
222
 
223
        mov     ax, 0f01h       ; AH := bit plane mask for Enable Set/Reset
224
        out     dx, ax          ; AL := Enable Set/Reset register number
225
 
226
        ; prepare to draw vertical line
227
 
228
        mov     ax, y1[bp]      ; AX := y1
229
        mov     cx, y2[bp]      ; BX := y2
230
        ;;mov   cx, bx
231
        sub     cx, ax          ; CX := dy
232
        ;;jge   L311            ; jump if dy >= 0
233
        ;;neg   cx              ; force dy >= 0
234
        ;;mov   ax, bx          ; AX := y2
235
 
236
L311:   inc     cx              ; CX := number of pixels to draw
237
        mov     bx, x[bp]       ; BX := x
238
        push    cx              ; save register
239
 
240
        ; compute pixel address
241
        push    dx
242
        mov     dx, offset PIXBYTES     ; AX := [row * PIXBYTES]
243
        mul     dx
244
        mov     cl, bl          ; save low order column bits
245
        shr     bx, 1           ; BX := [col / 8]
246
        shr     bx, 1
247
        shr     bx, 1
248
        add     bx, ax          ; BX := [row * PIXBYTES] + [col / 8]
249
        and     cl, 07h         ; CL := [col % 8]
250
        xor     cl, 07h         ; CL := 7 - [col % 8]
251
        mov     ah, 01h         ; AH := 1 << [7 - [col % 8]]    [mask]
252
        mov     dx, 0a000h      ; DS := EGA buffer segment address
253
        mov     ds, dx
254
        pop     dx
255
                                ; AH := bit mask
256
                                ; DS:BX -> video buffer
257
                                ; CL := number bits to shift left
258
 
259
        ; set up Graphics controller
260
 
261
        shl     ah, cl          ; AH := bit mask in proper position
262
        mov     al, 08h         ; AL := Bit Mask register number
263
        out     dx, ax
264
 
265
        pop     cx              ; restore register
266
 
267
        ; draw the line
268
 
269
        mov     dx, offset PIXBYTES     ; increment for video buffer
270
L1111:  or      [bx], al        ; set pixel
271
        add     bx, dx          ; increment to next line
272
        loop    L1111
273
 
274
        ; restore default Graphics Controller state and return to caller
275
        ;;xor   ax, ax          ; AH := 0, AL := 0
276
        ;;out   dx, ax          ; restore Set/Reset register
277
        ;;inc   ax              ; AH := 0, AL := 1
278
        ;;out   dx, ax          ; restore Enable Set/Reset register
279
        ;;mov   ax, 0ff08h      ; AH := 0xff, AL := 0
280
        ;;out   dx, ax          ; restore Bit Mask register
281
 
282
        pop     ds
283
        pop     bp
284
        ret
285
        .cendp  ega_drawvline
286
 
287
 
288
;
289
; Routine to set an individual pixel value.
290
; Called from C like:
291
;       ega_drawpixel(x, y, color);
292
;
293
 
294
; argument offsets from bp
295
x       = arg1          ; X coordinate
296
y       = arg1+2        ; Y coordinate
297
color   = arg1+4        ; pixel value
298
 
299
        .cproc  ega_drawpixel
300
        push    bp
301
        mov     bp, sp
302
 
303
        mov     dx, 03ceh       ; graphics controller port address
304
        mov     al, #3          ; set data rotate register
305
        lea     bx, mode_table
306
        add     bx, @gr_mode
307
        mov     ah, [bx]
308
        out     dx, ax
309
 
310
        mov     cx, x[bp]               ; ECX := x
311
        mov     ax, y[bp]               ; EAX := y
312
 
313
        mov     dx, offset PIXBYTES     ; AX := [y * PIXBYTES]
314
        mul     dx
315
 
316
        mov     bx, cx          ; BX := [x / 8]
317
        shr     bx, 1
318
        shr     bx, 1
319
        shr     bx, 1
320
 
321
        add     bx, ax          ; BX := [y * PIXBYTES] + [x / 8]
322
 
323
        and     cl, 07h         ; CL := [x % 8]
324
        xor     cl, 07h         ; CL := 7 - [x % 8]
325
        mov     ch, 01h         ; CH := 1 << [7 - [x % 8]]      [mask]
326
        shl     ch, cl
327
 
328
        mov     dx, 03ceh       ; graphics controller port address
329
 
330
        ;;required for old code
331
        ;;mov   ax, 0205h       ; select write mode 2
332
        ;;out   dx, ax          ; [load value 2 into mode register 5]
333
 
334
        ; new code
335
        xor     ax,ax           ; set color register 0
336
        mov     ah,[bp+8]       ; color pixel value
337
        out     dx,ax
338
 
339
        ; original code
340
        mov     al, 08h         ; set the bit mask register
341
        mov     ah, ch          ; [load bit mask into register 8]
342
        out     dx, ax
343
 
344
        push    ds
345
        mov     ax, 0a000h      ; DS := EGA buffer segment address
346
        mov     ds, ax
347
 
348
        ; new code
349
        or      [bx],al         ; quick rmw to set pixel
350
 
351
        ;;the following fails under ELKS without cli/sti
352
        ;;using ES works though.  Code changed to use single
353
        ;;rmw above rather than write mode 2, but the
354
        ;;reason for this failure is still unknown...
355
        ;;cli
356
        ;;mov   al, [bx]        ; dummy read to latch bit planes
357
        ;;mov   al, color[bp]   ; pixel value
358
        ;;mov   [bx], al        ; write pixel back to bit planes
359
        ;;sti
360
 
361
        pop     ds              ; restore registers and return
362
 
363
        mov     ax, 0005h       ; restore default write mode 0
364
        out     dx, ax          ; [load value 0 into mode register 5]
365
        ;;mov   ax, 0ff08h      ; restore default bit mask
366
        ;;out   dx, ax          ; [load value ff into register 8]
367
 
368
        pop     bp
369
        ret
370
        .cendp  ega_drawpixel
371
 
372
;
373
; Routine to read the value of an individual pixel.
374
; Called from C like:
375
;       color = ega_readpixel(x, y);
376
;
377
 
378
; argument offsets from bp
379
x       = arg1                  ; X coordinate
380
y       = arg1+2                ; Y coordinate
381
 
382
        .cproc  ega_readpixel
383
        push    bp
384
        mov     bp, sp
385
        push    si
386
        push    ds
387
 
388
        mov     ax, y[bp]       ; EAX := y
389
        mov     bx, x[bp]       ; EBX := x
390
        mov     dx, offset PIXBYTES     ; AX := [y * PIXBYTES]
391
        mul     dx
392
 
393
        mov     cl, bl          ; save low order column bits
394
        shr     bx, 1           ; BX := [x / 8]
395
        shr     bx, 1
396
        shr     bx, 1
397
 
398
        add     bx, ax          ; BX := [y * PIXBYTES] + [x / 8]
399
 
400
        and     cl, 07h         ; CL := [x % 8]
401
        xor     cl, 07h         ; CL := 7 - [x % 8]
402
 
403
        mov     dx, 0a000h      ; DS := EGA buffer segment address
404
        mov     ds, dx
405
 
406
        mov     ch, 01h         ; CH := 1 << [7 - [col % 8]]  [mask]
407
        shl     ch, cl          ; CH := bit mask in proper position
408
 
409
        mov     si, bx          ; DS:SI -> region buffer byte
410
        xor     bl, bl          ; BL is used to accumulate the pixel value
411
 
412
        mov     dx, 03ceh       ; DX := Graphics Controller port
413
        mov     ax, 0304h       ; AH := initial bit plane number
414
                                ; AL := Read Map Select register number
415
 
416
L112:   out     dx, ax          ; select bit plane
417
        mov     bh, [si]        ; BH := byte from current bit plane
418
        and     bh, ch          ; mask one bit
419
        neg     bh              ; bit 7 of BH := 1 if masked bit = 1
420
                                ; bit 7 of BH := 0 if masked bit = 0
421
        rol     bx, 1           ; bit 0 of BL := next bit from pixel value
422
        dec     ah              ; AH := next bit plane number
423
        jge     L112
424
 
425
        xor     ax, ax          ; AL := pixel value
426
        mov     al, bl
427
 
428
        pop     ds
429
        pop     si
430
        pop     bp
431
        ret
432
        .cendp  ega_readpixel
433
 
434
        .cend
435
        end

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.