URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [drivers/] [elkplan4.c] - Rev 174
Compare with Previous | Blame | View Log
/* * Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com> * * Microwindows * ELKS EGA/VGA Screen Driver 16 color 4 planes - 16-bit assembly version * * This file is an adapation of the asmplan4.s MSC asm driver for ELKS */ #include "device.h" #include "vgaplan4.h" /* assumptions for speed: NOTE: psd is ignored in these routines*/ #define SCREENSEG $0a000 #define SCREENBASE MK_FP(0xa000, 0) #define BYTESPERLINE 80 /* extern data*/ extern int gr_mode; /* temp kluge*/ static unsigned char mode_table[MWMODE_MAX + 1] = { 0x00, 0x18, 0x10, 0x08, /* COPY, XOR, AND, OR implemented*/ 0x00, 0x00, 0x00, 0x00, /* no VGA HW for other modes*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; int ega_init(PSD psd) { /* fill in screendevice struct*/ psd->addr = SCREENBASE; psd->linelen = BYTESPERLINE; /* Set up some default values for the VGA Graphics Registers. */ set_enable_sr (0x0f); set_op (0); set_mode (0); return 1; } /* * Routine to draw a horizontal line. * ega_drawhine(psd, x1, x2, y, color); * * works in the following EGA and VGA modes: * 200 line 16 colors modes * 350 line modes * 640x480 16 color */ /* Draw horizontal line from x1,y to x2,y including final point*/ void ega_drawhorzline(PSD psd, int x1, int x2, int y, int color) { #asm push bp ; setup stack frame and preserve registers mov bp, sp push si push di push es ; configure the graphics controller mov dx, #$03ce ; DX := Graphics Controller port address mov al, #3 ; set data rotate register lea bx, _mode_table add bx, _gr_mode mov ah, [bx] out dx, ax mov ah, [bp+12] ; pixel value xor al, al ; Set/Reset register number (0) out dx, ax mov ax, #$0f01 ; AH := bit plane mask for Enable Set/Reset out dx, ax ; AL := Enable Set/Reset register number push ds ; preserve DS mov ax, [bp+10] ; y mov bx, [bp+6] ; x1 ; compute pixel address mov dx, #BYTESPERLINE ; AX := [row * BYTESPERLINE] mul dx mov cl, bl ; save low order column bits shr bx, #1 ; BX := [col / 8] shr bx, #1 shr bx, #1 add bx, ax ; BX := [row * BYTESPERLINE] + [col / 8] and cl, #$07 ; CL := [col % 8] xor cl, #$07 ; CL := 7 - [col % 8] mov ah, #$01 ; AH := 1 << [7 - [col % 8]] [mask] mov dx, #SCREENSEG ; ES := EGA buffer segment address mov es, dx ; AH := bit mask ; ES:BX -> video buffer ; CL := number bits to shift left mov di, bx ; ES:DI -> buffer mov dh, ah ; DH := unshifted bit mask for left byte not dh shl dh, cl ; DH := reverse bit mask for first byte not dh ; DH := bit mask for first byte mov cx, [bp+8] ; x2 and cl, #7 xor cl, #7 ; CL := number of bits to shift left mov dl, #$0ff ; DL := unshifted bit mask for right byte shl dl, cl ; DL := bit mask for last byte ; determine byte offset of first and last pixel in the line mov ax, [bp+8] ; AX := x2 mov bx, [bp+6] ; BX := x1 mov cl, #3 ; bits to convert pixels to bytes shr ax, cl ; AX := byte offset of X2 shr bx, cl ; BX := byte offset of X1 mov cx, ax sub cx, bx ; CX := [number of bytes in line] - 1 ; get Graphics Controller port address into DX mov bx, dx ; BH := bit mask for first byte ; BL := bit mask for last byte mov dx, #$03ce ; DX := Graphics Controller port mov al, #8 ; AL := Bit mask Register number ; make video buffer addressable through DS:SI push es pop ds mov si, di ; DS:SI -> video buffer ; set pixels in leftmost byte of the line or bh, bh js L43 ; jump if byte-aligned [x1 is leftmost] or cx, cx jnz L42 ; jump if more than one byte in the line and bl, bh ; BL := bit mask for the line jmp near L44 L42: mov ah, bh ; AH := bit mask for first byte out dx, ax ; update graphics controller movsb ; update bit planes dec cx ; use a fast 8086 machine instruction to draw the remainder of the line L43: mov ah, #$0ff ; AH := bit mask out dx, ax ; update Bit Mask register rep movsb ; update all pixels in the line ; set pixels in the rightmost byte of the line L44: mov ah, bl ; AH := bit mask for last byte out dx, ax ; update Graphics Controller movsb ; update bit planes pop ds ; restore ds ; restore default Graphics Controller state and return to caller ;;xor ax, ax ; AH := 0, AL := 0 ;;out dx, ax ; restore Set/Reset register ;;inc ax ; AH := 0, AL := 1 ;;out dx, ax ; restore Enable Set/Reset register ;;mov ax, #$0ff08 ; AH := 0xff, AL := 0 ;;out dx, ax ; restore Bit Mask register pop es pop di pop si pop bp #endasm } /* * Routine to draw a vertical line. * Called from C: * ega_drawvline(psd, x, y1, y2, color); * * works in the following EGA and VGA modes: * 200 line 16 colors modes * 350 line modes * 640x480 16 color */ /* Draw a vertical line from x,y1 to x,y2 including final point*/ void ega_drawvertline(PSD psd, int x,int y1, int y2, int color) { #asm push bp ; setup stack frame and preserve registers mov bp, sp push ds ; configure the graphics controller mov dx, #$03ce ; DX := Graphics Controller port address mov al, #3 ; set data rotate register lea bx, _mode_table add bx, _gr_mode mov ah, [bx] out dx, ax mov ah, [bp+12] ; color pixel value xor al, al ; Set/Reset register number (0) out dx, ax mov ax, #$0f01 ; AH := bit plane mask for Enable Set/Reset out dx, ax ; AL := Enable Set/Reset register number ; prepare to draw vertical line mov ax, [bp+8] ; AX := y1 mov cx, [bp+10] ; BX := y2 ;;mov cx, bx sub cx, ax ; CX := dy ;;jge L311 ; jump if dy >= 0 ;;neg cx ; force dy >= 0 ;;mov ax, bx ; AX := y2 L311: inc cx ; CX := number of pixels to draw mov bx, [bp+6] ; BX := x push cx ; save register ; compute pixel address push dx mov dx, #BYTESPERLINE ; AX := [row * BYTESPERLINE] mul dx mov cl, bl ; save low order column bits shr bx, #1 ; BX := [col / 8] shr bx, #1 shr bx, #1 add bx, ax ; BX := [row * BYTESPERLINE] + [col / 8] and cl, #$07 ; CL := [col % 8] xor cl, #$07 ; CL := 7 - [col % 8] mov ah, #$01 ; AH := 1 << [7 - [col % 8]] [mask] mov dx, #SCREENSEG ; DS := EGA buffer segment address mov ds, dx pop dx ; AH := bit mask ; DS:BX -> video buffer ; CL := number bits to shift left ; set up Graphics controller shl ah, cl ; AH := bit mask in proper position mov al, #$08 ; AL := Bit Mask register number out dx, ax pop cx ; restore register ; draw the line mov dx, #BYTESPERLINE ; increment for video buffer L1111: or [bx], al ; set pixel add bx, dx ; increment to next line loop L1111 ; restore default Graphics Controller state and return to caller ;;xor ax, ax ; AH := 0, AL := 0 ;;out dx, ax ; restore Set/Reset register ;;inc ax ; AH := 0, AL := 1 ;;out dx, ax ; restore Enable Set/Reset register ;;mov ax, #$0ff08 ; AH := 0xff, AL := 0 ;;out dx, ax ; restore Bit Mask register pop ds pop bp #endasm } /* * Routine to set an individual pixel value. * Called from C like: * ega_drawpixel(psd, x, y, color); */ void ega_drawpixel(PSD psd, int x, int y, int color) { #asm push bp mov bp, sp mov dx, #$03ce ; graphics controller port address mov al, #3 ; set data rotate register lea bx, _mode_table add bx, _gr_mode mov ah, [bx] out dx, ax mov cx, [bp+6] ; ECX := x mov ax, [bp+8] ; EAX := y mov dx, #BYTESPERLINE ; AX := [y * BYTESPERLINE] mul dx mov bx, cx ; BX := [x / 8] shr bx, #1 shr bx, #1 shr bx, #1 add bx, ax ; BX := [y * BYTESPERLINE] + [x / 8] and cl, #$07 ; CL := [x % 8] xor cl, #$07 ; CL := 7 - [x % 8] mov ch, #$01 ; CH := 1 << [7 - [x % 8]] [mask] shl ch, cl mov dx, #$03ce ; graphics controller port address ;;required for old code mov ax, #$0205 ; select write mode 2 out dx, ax ; [load value 2 into mode register 5] ; new code ;;xor ax,ax ; set color register 0 ;;mov ah,[bp+10] ; color pixel value ;;out dx,ax ; original code mov al, #$08 ; set the bit mask register mov ah, ch ; [load bit mask into register 8] out dx, ax push ds mov ax, #SCREENSEG ; DS := EGA buffer segment address mov ds, ax ; new code ;;or [bx],al ; quick rmw to set pixel ;;the following fails under ELKS without cli/sti ;;using ES works though. Code changed to use single ;;rmw above rather than write mode 2, but the ;;reason for this failure is still unknown... ;;cli mov al, [bx] ; dummy read to latch bit planes mov al, [bp+10] ; pixel value mov [bx], al ; write pixel back to bit planes ;;sti pop ds ; restore registers and return mov ax, #$0005 ; restore default write mode 0 out dx, ax ; [load value 0 into mode register 5] ;;mov ax, #$0ff08 ; restore default bit mask ;;out dx, ax ; [load value ff into register 8] pop bp #endasm } /* * Routine to read the value of an individual pixel. * Called from C like: * color = ega_readpixel(psd, x, y); */ PIXELVAL ega_readpixel(PSD psd, int x, int y) { #asm push bp mov bp, sp push si push ds mov ax, [bp+8] ; EAX := y mov bx, [bp+6] ; EBX := x mov dx, #BYTESPERLINE ; AX := [y * BYTESPERLINE] mul dx mov cl, bl ; save low order column bits shr bx, #1 ; BX := [x / 8] shr bx, #1 shr bx, #1 add bx, ax ; BX := [y * BYTESPERLINE] + [x / 8] and cl, #$07 ; CL := [x % 8] xor cl, #$07 ; CL := 7 - [x % 8] mov dx, #SCREENSEG ; DS := EGA buffer segment address mov ds, dx mov ch, #$01 ; CH := 1 << [7 - [col % 8]] [mask] shl ch, cl ; CH := bit mask in proper position mov si, bx ; DS:SI -> region buffer byte xor bl, bl ; BL is used to accumulate the pixel value mov dx, #$03ce ; DX := Graphics Controller port mov ax, #$0304 ; AH := initial bit plane number ; AL := Read Map Select register number L112: out dx, ax ; select bit plane mov bh, [si] ; BH := byte from current bit plane and bh, ch ; mask one bit neg bh ; bit 7 of BH := 1 if masked bit = 1 ; bit 7 of BH := 0 if masked bit = 0 rol bx, #1 ; bit 0 of BL := next bit from pixel value dec ah ; AH := next bit plane number jge L112 xor ax, ax ; AL := pixel value mov al, bl pop ds pop si pop bp #endasm }