; COPPER.ASM -- Copper bars

Ideal
Model Tiny
P186
CodeSeg
Org 100h

;**************************** Main Program

Proc        Prog

            mov di,offset Buffer        ;Clear the buffer
            xor ax,ax
            mov cx,500
            rep stosw

            mov di,offset Buffer+400    ;DI = middle of buffer

            mov cx,63                   ;63 shades
Pal1:       stosb                       ;Store color
            inc ax                      ;Next color
            loop Pal1                   ;Loop back

            mov cx,63                   ;63 shades
Pal2:       stosb                       ;Store color
            dec ax                      ;Next color
            loop Pal2                   ;Loop back

            mov si,140                  ;SI, DI, BP = positions
            mov di,140
            mov bp,140

            mov bx,2                    ;BX, CX, DX = speeds
            mov cx,-3
            mov dx,-1

MainLoop:   add si,bx                   ;Advance red value
            jg $+4
            neg bx                      ;Bounce if needed
            cmp si,270
            jl $+4
            neg bx

            add di,cx                   ;Advance green value
            jg $+4
            neg cx                      ;Bounce if needed
            cmp di,270
            jl $+4
            neg cx

            add bp,dx                   ;Advance blue value
            jg $+4
            neg dx                      ;Bounce if needed
            cmp bp,270
            jl $+4
            neg dx

            push si di bp               ;Do the copper effect
            call Copper

            mov ah,1                    ;Loop while no key pressed
            int 16h
            jz MainLoop

            ret                         ;Return

EndP        Prog

;**************************** Copper -- One frame of copper effect

Red         equ bp+8
Green       equ bp+6
Blue        equ bp+4

Proc        Copper

            push bp                     ;Set up stack frame
            mov bp,sp
            pusha                       ;Save all registers
            cli                         ;Disable interrupts

            mov dx,03DAh                ;DX = IS1 port

VRet1:      in al,dx                    ;Wait for active period
            test al,8
            jz VRet1
VRet2:      in al,dx
            test al,8
            jnz VRet2

            mov cx,400                  ;400 lines, BX = buffer
            mov bx,offset Buffer

LineLoop:   mov dx,03DAh                ;DX = IS1 port

HRet1:      in al,dx                    ;Wait for horizontal retrace
            test al,1
            jnz HRet1
HRet2:      in al,dx
            test al,1
            jz HRet2

            mov dx,03C8h                ;Setting color 0
            xor al,al
            out dx,al
            inc dx

            mov si,cx                   ;Set red value
            sub si,[Red]
            mov al,[bx+si+400]
            out dx,al

            mov si,cx                   ;Set green value
            sub si,[Green]
            mov al,[bx+si+400]
            out dx,al

            mov si,cx                   ;Set blue value
            sub si,[Blue]
            mov al,[bx+si+400]
            out dx,al

            loop LineLoop               ;Loop back

            sti                         ;Enable interrupts
            popa                        ;Restore registers
            pop bp                      ;Delete stack frame
            ret 6                       ;Return

EndP        Copper

Buffer:

End Prog
