; NASM or FASM

        ; ax=bx=0, cx=0FFh (doesn't really matter), dx=cs=ds=es, bp=9??h

        org 100h

        mov al,13h
        int 10h                 ; set 320x200 (256 colors) graphical video mode

        add dh,al               ; dx = cs + 1300h
        mov es,dx               ; es = segment behind 64k+ of our code (extra video buffer)

        xchg ax,bp              ; ah = 9 (bp = 13h)
        mov dx,t
        int 21h                 ; output the text

        push es
        pop ds                  ; ds = es

        xchg ax,bx              ; ax = 0 (bx = 9??h)
        dec ch                  ; cx = -1
        rep stosb               ; clear extra video buffer
        dec ax                  ; al = -1
        mov di,0A2D0h           ; set pointer to pixel at 130,80 (col,row)
        mov cl,80
        rep stosw               ; fill 80*2 = 160 pixels by 0FFh color (draw horizontal line)

        mov bx,19A0h            ; set pointer to pixel at 20,160 (col,row)
        mov di,320              ; screen width in pixels
v:      mov [bx],ax             ; draw vertical line...
        add bx,di
        ja v                    ; ...until bottom

        mov dx,3C8h
        mov al,0C0h
        out dx,al               ; start palette set from 0C0h color
        inc dx
p:      outsb                   ; red = 0
        out dx,al               ; green component
        outsb                   ; blue = 0
        inc al                  ; increase color (al mod 64 = 1, 2, 3..63)
        jnz p                   ; set colors 0C0h..0FFh to green gradient (from dark to saturated)

        mov ch,0A0h
        mov ds,cx               ; ds = 0A000h = vedeo segment

l:
        ; bx = pixel pointer, dx = pixel pointer delta value (initial values doesn't matter)
        cmp bh,0FAh
        jae s                   ; jump if current pixel is out of screen
        mov ax,[bx]             ; else get color of pixel (ah = 0 in the most cases - need at the loop end for scan code check and text mode set)
        out 61h,al              ; sound
        cmp al,0C0h
        jbe s                   ; jump if pixel color is out of green gradient range (0C1h..0FFh, excluding 0C0h)

        ; flame effect
        dec ax                  ; else decrase color by 1 (make it darker)
        mov [bx+1],al
        mov [bx-1],al
        mov [bx+di],al          ; di = 320
        mov [bx-320],al         ; and fill pixels around the current by new color

        mov si,-640             ; position delta: 2 lines up
        test dh,dh
        js n                    ; jump if dx is negative (poor pseudorandom boolean check)
        inc si
        inc si                  ; si += 2 (wind effect)
n:      mov [bx+si],al          ; add pixel 2 lines higher than current pixel considering possible wind
s:
        ; restore cross
        mov al,[es:bx]          ; get color from extra video buffer
        or [bx],al              ; replace pixel on screen by 0FFh is al = 0FFh (slow cross redraw)
        add bx,dx               ; increase pixel pointer by (pseudorandom) delta value
        inc dx                  ; increase delta value

        in al,60h               ; read keyboard scan code (also delay on real system)
        dec ax
        jnz l                   ; repeat if Esc key is not pressed

        mov al,3
        int 10h                 ; set text video mode

        ret                     ; return to DOS

t       db      'russkie idut$'
