;-------------------------------
;* FADE.ASM - Clear VGA screen by fading out.
;* Written by Tom Marshall
;* Released into the public domain

                cseg segment
                assume cs:cseg
                org 100h
                .286

PEL_Read_Reg    EQU     03C7h                   ;Palette read access
PEL_Write_Reg   EQU     03C8h                   ;Palette write access
PEL_Data_Reg    EQU     03C9h                   ;Palette data register
O               EQU     OFFSET

Start:          cld                             ;We're moving forward!

                call    SyncVR                  ;Avoid snow
                mov     di,O OrigPalette
                mov     dx,PEL_Read_Reg
                sub     al,al                   ;AL = Color
                out     dx,al                   ;Send color index
                mov     dx,PEL_Data_Reg
                mov     cx,3*256                ;R,G,B per color
                rep insb                        ;Block read color regs

                mov     si,O OrigPalette        ;Copy original palette
                mov     di,O FadePalette        ;  to fade palette
                mov     cx,3*256
                rep movsb

DecPalette:     mov     si,O FadePalette        ;Point to fade values
                mov     cx,3*256                ;Repeat 3 bytes per color
                mov     ah,-1                   ;Done flag = -1 (True)
DecPalLoop:     mov     al,[si]                 ;Get fade value
                test    al,al                   ;Is it zero?
                je      RegZero                 ;If so, skip fade
                dec     BYTE PTR[si]            ;Decrement fade value
                sub     ah,ah                   ;Make flag false
RegZero:        inc     si                      ;Next value
                loop    DecPalLoop
                test    ah,ah                   ;Done yet?
                jnz     ClearScreen             ;Jump if so

                call    SyncVR                  ;Avoid snow
                mov     si,O FadePalette        ;Point to fade values
                mov     dx,PEL_Write_Reg
                sub     al,al                   ;Start with color 0
                out     dx,al                   ;Send color index
                mov     dx,PEL_Data_Reg
                mov     cx,3*256                ;R,G,B per color
                rep outsb                       ;Block write color regs

                push    ds                      ;Simple timer tick delay
                mov     ax,0040h                ;Approx. 1/18.2 sec.
                mov     ds,ax
                mov     bx,06Ch
                mov     al,[bx]
DelayLoop:      cmp     al,[bx]
                je      DelayLoop
                pop     ds

                jmp     DecPalette              ;Continue fading

ClearScreen:    mov     ax,0B800h               ;Set ES to video seg
                mov     es,ax
                mov     ax,0720h                ;Clear text screen
                sub     di,di
                mov     cx,80*25
                rep stosw

                call    SyncVR                  ;Snowplow!
                mov     si,O OrigPalette        ;Point to original palette
                mov     dx,PEL_Write_Reg
                sub     al,al                   ;Start with color 0
                out     dx,al                   ;Send it
                mov     dx,PEL_Data_Reg
                mov     cx,3*256                ;R,G,B per color
                rep outsb

                mov     ax,4C00h                ;Exit to DOS
                int     21h

SyncVR          PROC   NEAR                     ;Sync to start of VR
                mov     dx,03DAh
@@Sync1:        in      al,dx
                test    al,8                    ;Is VR in progress?
                jnz     @@Sync1                 ;If so, wait
@@Sync2:        in      al,dx
                test    al,8                    ;Wait for VR to start
                jz      @@Sync2
                ret
SyncVR          ENDP

OrigPalette     db      3*256 dup (?)           ;Original palette
FadePalette     db      3*256 dup (?)           ;Current fade palette

                cseg    ENDS
                END     Start
