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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [drivers/] [elkplan4.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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