        name    vgc     ; VGA Graphics Controller routines
        ;
        ;  void Select_RPlane(int plane);  
        ;  void Select_Wmode(int mode);    mode ranges 0-3
        ;  int  What_Wmode(void);          
        ;  int  GCread_reg(int reg);
        ;  void GCset_reg(int reg, int value);
        ;  void GCset_regm(int reg, int value, int mask);
        ;
GRAPHICS_CTRL_PORT      EQU     03CEh   ;Graphics controller
GRAPHICS_DATA_PORT      EQU     03CFh   ;Graphics controller data
READ_PLANE_REG          EQU     4
MODE_REG                EQU     5

REGNO    equ     [bp+06]
VALUE    equ     [bp+08]
BMASK    equ     [bp+0ah]

GC_TEXT       segment byte public 'CODE'
        public  _Select_RPlane
        assume  cs:GC_TEXT
_Select_RPlane   proc    far
        push    bp
        mov     bp,sp
        mov     ah,REGNO
        and     ah,3            ; bits 2-7 are reserved/unused
        mov     dx,GRAPHICS_CTRL_PORT
        mov     al,READ_PLANE_REG
        out     dx,ax
        pop     bp
        ret
_Select_RPlane   endp
        public  _Select_Wmode
_Select_Wmode   proc    far
        push    bp
        mov     bp,sp

        mov     cl,REGNO
        and     cl,3
        mov     dx,GRAPHICS_CTRL_PORT
        mov     al,MODE_REG
        out     dx,al
        inc     dx
        in      al,dx
        and     al,0fch
        or      al,cl
        out     dx,al
        pop     bp
        ret
_Select_Wmode   endp
        public  _What_Wmode
        assume  cs:GC_TEXT
_What_Wmode   proc    far
        mov     dx,GRAPHICS_CTRL_PORT
        mov     al,MODE_REG
        out     dx,al
        inc     dx
        in      al,dx
        xor     ah,ah
        ret
_What_Wmode   endp
        public  _GCread_reg
_GCread_reg   proc    far
        push    bp
        mov     bp,sp
        mov     al,REGNO
        mov     dx,GRAPHICS_CTRL_PORT
        out     dx,al
        inc     dx
        in      al,dx
        xor     ah,ah
        pop     bp
        ret
_GCread_reg   endp
        public  _GCset_reg
_GCset_reg   proc    far
        push    bp
        mov     bp,sp

        mov     ah,VALUE
@update:
        mov     al,REGNO
        mov     dx,GRAPHICS_CTRL_PORT
        out     dx,ax

        pop     bp
        ret
_GCset_reg   endp
        public  _GCset_regm
_GCset_regm     PROC  far
        push    bp
        mov     bp,sp

        mov     al,REGNO                ; read old value
        mov     dx,GRAPHICS_CTRL_PORT
        out     dx,al
        inc     dx
        in      al,dx
        xor     ah,ah

        mov     bl,BMASK                ; compute new value
        not     bl        ; !mask
        and     al,bl     ; al=(!mask&reg(reg_num));
        mov     cl,al     ; save for a microsecond
        mov     ah,VALUE
        mov     bl,BMASK
        and     ah,bl
        or      ah,cl     ; leave value in ah for GCset_reg

        jmp     @update   ; already knows REGNO, expects VALUE in ah

_GCset_regm     ENDP
GC_TEXT       ends
        end

