; Attribute Controller register operations
;
; int char ACread_reg(int register_number);
; void ACset_reg(int register_number, int value);
; void ACset_regm(int reg_num, int value, 
;                 int mask);
;      reg(reg_num)= (!mask & reg(reg_num)) | (mask & value);
;
BMASK   EQU     [BP+0ah]
VALUE   EQU     [BP+8]
REGNO   EQU     [BP+6]
;
AC_TEXT   SEGMENT word public 'CODE'
        ASSUME  cs:AC_TEXT, ds:NOTHING
        PUBLIC  _ACread_reg
        PUBLIC  _ACset_reg
        PUBLIC  _ACset_regm
_ACread_reg     PROC    far
        push    bp
        mov     bp,sp

        mov     ax,40h
        mov     es,ax
        mov     dx,es:[63h]
        add     dl,6            ; get register address

        cli

        in      al,dx   ;reset 3c0 flip/flop
        push    dx
        mov     dl,0c0h
        mov     al,REGNO    ; palette register number
        or      al,20h      ; don't disable display, we're just looking
        out     dx,al

        xor     ax,ax
        inc     dx
        jmp     $+2         ; waste a little more time

        in      al,dx
        mov     bl,al       ; save return in bl for a moment

        pop     dx
        in      al,dx   ;reset 3c0 flip/flop
        mov     dl,0c0h
        mov     al,20h
        out     dx,al   ; return 3c0 to the way we left it

        sti

        xor     ah,ah
        mov     al,bl   ; place return value in al
        pop     bp
        ret             ; return to C

_ACread_reg     ENDP
_ACset_reg      PROC    far
        push    bp
        mov     bp,sp
        mov     ax,40h
        mov     es,ax
        mov     dx,es:[63h]
        add     dl,6                  ;dx=0x03da (color) 0x03ba (mono)
        mov     bl,VALUE              ; save value in a register
        push    dx                    ; save flip/flop reset location
        cli
        in      al,dx                 ;reset 3c0 flip/flop
        mov     dl,0c0h               ; dx=0x03c0
        mov     al,REGNO
        cmp     al,10h                
        jb      outind                ; if a palette register, 
                                      ; disable display
        or      al,20h                ; else don't disable display
outind: out     dx,al                 ; output index to 0x3c0
        mov     al,bl
        jmp     $+2         ; waste a little more time
        out     dx,al                 ; out(0x3c0,VALUE)

        pop     dx
        in      al,dx                 ;reset 3c0 flip/flop
        mov     dl,0c0h
        mov     al,20h
        out     dx,al          ; reenable screen
        sti
        xor     ax,ax
        pop     bp
        ret             ; return to C
_ACset_reg      ENDP
_ACset_regm     PROC  far
        push    bp
        mov     bp,sp
        mov     dl,REGNO
        push    dx
        call    _ACread_reg    ; returns al=reg(reg_num);
        add     sp,2

        mov     bl,BMASK
        not     bl        ; !mask
        and     al,bl     ; al=(!mask&reg(reg_num));
        mov     cl,al     ; save for a microsecond
        mov     al,VALUE
        mov     bl,BMASK
        and     al,bl
        or      al,cl     
        push    ax
        mov     al,REGNO
        push    ax
        call    _ACset_reg
        add     sp,4

        xor     ax,ax
        pop     bp
        ret
_ACset_regm     ENDP
AC_TEXT   ENDS
        END

