Metropoli BBS
VIEWER: copper.asm MODE: TEXT (CP437)
;███████████████████████████████████████████████████████████████████████████████
;                    COPPER.COM - 512 bytes copper demo
;███████████████████████████████████████████████████████████████████████████████
model tiny
codeseg
p286
        org     100h
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
;                                   CODE
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

MAIN:   mov     ax,13h
        int     10h

;░░░░░░░░░░ Initialize copper bars
        call    InitBars
        
;░░░░░░░░░░ Set copper palette
        mov     si,offset pal
        mov     cx,3*barheight*barcount
        mov     al,1
        mov     dx,3C8h
        out     dx,al
        inc     dx
        rep     outsb

;░░░░░░░░░░ Save palette for fading
        call    GetPalette

        mov     ax,0A000h
        mov     es,ax

;░░░░░░░░░░ Mainloop
@MainLoop:
        call    CalcBars
        cmp     Frame,MaxFrame
        ja      @Move
        inc     Frame

        call    WaitVREnd
        call    SetPalette
        
@Move:  call    WaitVRStart
        call    DrawBars
        
;░░░░░░░░░░ Repeat until keypressed
        mov     ah,1
        int     16h
        jz      @MainLoop

;░░░░░░░░░░ Fade to black, but keep the bars moving
@MainLoop2:
        call    CalcBars
        call    WaitVREnd
        call    SetPalette
        call    WaitVRStart
        call    DrawBars
        dec     Frame
        jnz     @MainLoop2

;░░░░░░░░░░ Read key pressed and exit
@OUT:   xor     ah,ah
        int     16h
        mov     ax,3
        int     10h

        ret

;▒▒▒▒▒▒▒▒▒▒ GetPalette
;▒▒▒▒▒▒▒▒▒▒ Gets palette for fading
;▒▒▒▒▒▒▒▒▒▒ Assumes:  ES=data
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,bx,cx,dx,di
GetPalette      PROC NEAR
        xor     ax,ax
        mov     bl,MaxFrame
        mov     cx,768
        mov     dx,3C7h
        mov     di,offset palette
        out     dx,al
        inc     dx
        inc     dx
@GetLoop:
        in      al,dx
        shl     ax,8
        div     bl
        stosb
        loop    @GetLoop
        ret
endp

;▒▒▒▒▒▒▒▒▒▒ SetPalette
;▒▒▒▒▒▒▒▒▒▒ Sets whole palette
;▒▒▒▒▒▒▒▒▒▒ Assumes:  DS=data
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,bx,cx,dx,si
SetPalette      PROC NEAR
        xor     ax,ax
        mov     bl,Frame
        mov     cx,768
        mov     dx,3C8h
        mov     si,offset palette
        out     dx,al
        inc     dx
@SetLoop:
        lodsb
        mul     bl
        shr     ax,8
        out     dx,al
        loop    @SetLoop
        ret
endp

;▒▒▒▒▒▒▒▒▒▒ WaitVRStart
;▒▒▒▒▒▒▒▒▒▒ Waits Vertical Retrace to begin
;▒▒▒▒▒▒▒▒▒▒ Assumes:  nothing
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,dx
WaitVRStart     PROC NEAR
        mov     dx,3DAh
@WaitStart:
        in      al,dx
        test    al,8
        jz      @WaitStart
        ret
endp

;▒▒▒▒▒▒▒▒▒▒ WaitVREnd
;▒▒▒▒▒▒▒▒▒▒ Waits Vertical Retrace to end
;▒▒▒▒▒▒▒▒▒▒ Assumes:  Nothing
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,dx
WaitVREnd       PROC NEAR
        mov     dx,3DAh
@WaitEnd:
        in      al,dx
        test    al,8
        jnz     @WaitEnd
        ret
endp

;▒▒▒▒▒▒▒▒▒▒ InitBars
;▒▒▒▒▒▒▒▒▒▒ Initializes copper bars
;▒▒▒▒▒▒▒▒▒▒ Assumes:  nothing
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,bx,cx,si

InitBars        PROC NEAR
        xor     si,si
        mov     cx,barcount
        mov     bx,1
        mov     ax,257                          ; ah=al=1
@Init1: mov     [si+TheBars.Y],bx               ; save Y
        mov     [si+TheBars.C],ax               ; set color
        mov     [si+TheBars.Dir],al             ; going up
        mov     [si+TheBars.NewDI],64000        ; old position

        add     si,(size bar)                   ; next bar
        add     bx,barheight*2
        add     al,barheight
        add     ah,barheight
        loop    @Init1
        ret
endp

;▒▒▒▒▒▒▒▒▒▒ CalcBars
;▒▒▒▒▒▒▒▒▒▒ Calculates next positions for bars
;▒▒▒▒▒▒▒▒▒▒ Assumes:  nothing
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,bx,cx,dx,si
CalcBars        PROC NEAR
        xor     si,si
        mov     cx,barcount                     ; process all bars
@CalcLoop:
        mov     ax,[si+TheBars.Y]               ; load Y
        mov     dx,[si+TheBars.NewDI]           ; load previous position
        mov     bl,[si+TheBars.Dir]             ; test for direction
        or      bl,bl
        jz      @GoingDown

@GoingUp:
        add     dx,320*barheight
        dec     ax
        jnz     @BarOK
        mov     [si+TheBars.Dir],0              ; if on top then change dir
        jmp     @BarOK

@GoingDown:
        inc     ax
        cmp     ax,200-barheight                ; on bottom?
        jb      @BarOK
        mov     [si+TheBars.Dir],1              ; if on bottom then change dir

@BarOK: mov     [si+TheBars.Y],ax               ; set new Y
        shl     ax,6
        mov     di,ax
        shl     ax,2
        add     di,ax
        mov     [si+TheBars.OldDI],dx           ; save previous position
        mov     [si+TheBars.NewDI],di           ; save new position

        add     si,(size bar)                   ; next bar
        loop    @CalcLoop
        ret
endp

;▒▒▒▒▒▒▒▒▒▒ DrawBars
;▒▒▒▒▒▒▒▒▒▒ Draws copper bars
;▒▒▒▒▒▒▒▒▒▒ Assumes:  ES=A000
;▒▒▒▒▒▒▒▒▒▒ Destroys: ax,bx,cx,dx,si,di
DrawBars        PROC NEAR
        xor     si,si
        mov     bx,barcount                     ; process all bars
@MoveLoop:
        mov     di,[si+TheBars.OldDI]

        mov     cx,160                          ; erase one line behind
        xor     ax,ax
        rep     stosw

        mov     di,[si+TheBars.NewDI]
        mov     dx,barheight
        mov     ax,[si+TheBars.C]
@DrawLoop:                                      ; draw bar into new position
        mov     cx,160
        rep     stosw
        add     ax,257                          ; increase ah and al
        dec     dx
        jnz     @DrawLoop

        add     si,(size bar)                   ; next bar
        dec     bx
        jnz     @MoveLoop
        ret
endp

;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
;                                   DATA
;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

;▒▒▒▒▒▒▒▒▒▒ Copper bar structure
bar      struc
Y        dw ?                   ; Y - coordinate
OldDI    dw ?                   ; Old position
NewDI    dw ?                   ; New position
C        dw ?                   ; Base color for bar
Dir      db ?                   ; 0=down, anything else=up
ends

;░░░░░░░░░░░░░░░░░░░░░░░░░░░░ INITIALIZED DATA ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

barheight equ 11                ; height of the bar
barcount  equ 5                 ; count of bars
MaxFrame  equ 100               ; frames for fading

;▒▒▒▒▒▒▒▒▒▒ Copper bars palette
Pal:
include Copper.Pal              ; Include palette

Frame   db  0                   ; Current frame in fading

;░░░░░░░░░░░░░░░░░░░░░░░ ZERO DATA - TO BE REMOVED ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
db      0FFh                    ; End of file -Marker

TheBars bar barcount dup (?)
Palette:                        ; Palette for fading
db 768 dup (?)

end     MAIN
;███████████████████████████████████████████████████████████████████████████████
                                    END
;███████████████████████████████████████████████████████████████████████████████
[ RETURN TO DIRECTORY ]