Metropoli BBS
VIEWER: flames.asm MODE: TEXT (ASCII)
;=============================================================================
; flame.asm - Plasma-Like Flames Demo.
;                                                    File created: 11/22/93
; Copyright (c) 1993, Carlos Hasan                  Last modified: 11/22/93
;
; Description:
;  Plasma Like Flames effect based on Vangelis Fire Code.
;
; Portability:
;  Requires Turbo Assembler 3.2 or later to be assembled.
;  Dependant on the IBM PC 286 or better processor.
;=============================================================================

        ideal
        model   small
        jumps
        p286

        dosseg
        stack   1024
        ends

        global  FontFAR:byte            ; FLAMES.FNT linked file.

;=========================== VLA Font Header =================================

struc   FontHeader
  Magic   db   "VGACH"                  ; Font Signature
  First   db   ?                        ; First Char
  Width   db   ?                        ; Font Width
  Height  db   ?                        ; Font Height
  Total   db   ?                        ; Number of Chars
ends    FontHeader

;======================== Equates and Data Segment ===========================

TIMEOUT   equ  70*50                    ; At Least 50 secs
MESGSPEED equ  20                       ; Message Speed in VR Ticks
FLSEED    equ  4                        ; Initial Flames Seed
FLBLANK   equ  100                      ; Ending Flames Seed (Blank Screen)
XDOTS     equ  80                       ; VGA Screen Dimensions
YDOTS     equ  80
HIDDEN    equ  8                        ; Number of Hidden Working Lines

        dataseg

label   Palette byte                    ; Flames RGB Palette:
        I=0                             ; black to blue
        rept 8
        db   0,0,2*I
        I=I+1
        endm
        I=0                             ; blue to darkred
        rept 8
        db   2*I,0,16-2*I
        I=I+1
        endm
        I=0                             ; darkred to lightred
        rept 24
        db   16+47*I/24,0,0
        I=I+1
        endm
        I=0                             ; lighred to yellow
        rept 32
        db   63,31*I/16,0
        I=I+1
        endm
        I=0                             ; yellow to white
        rept 24
        db   63,63,21*I/8
        I=I+1
        endm
        rept 160                        ; white
        db   63,63,63
        endm

Frame        dw   XDOTS*(YDOTS+HIDDEN) dup(?)  ; Flames Frame Buffer
Seed         dw   1234h                 ; Random Seed
FontDataOfs  dw   ?                     ; Font Data Address
FontDataSeg  dw   ?
FontWidths   db   256 dup (?)           ; Font Char Widths
FontFirst    db   ?                     ; Font First Char
FontWidth    db   ?                     ; Font Max Width
FontHeight   db   ?                     ; Font Height
FontSize     dw   ?                     ; Font BitMap Size (=Width*Height)

MesgOff      dw   offset TheMessage     ; Message Offset
TheMessage   db   "     FAKE DEMO  CODED BY PELUSA  MUSIC BY NECROS"
             db   "     GREETS GO TO ALL THE PC DEMO PEOPLE..."
             db   "     THANKS FOR WATCHING THIS LAME THING..."
             db   "     SEEING YA........              "
             db   0


;============================ Code Segment ===================================

        codeseg

;-----------------------------------------------------------------------------
; SetModeX - Sets VGA Tweaked Mode 80x80x256.
;-----------------------------------------------------------------------------

proc    SetModeX
        mov     ax,0013h                ; Set VGA Linear 320x200x256
        int     10h
        mov     dx,3C4h                 ; Disable Chain-Four
        mov     ax,0604h
        out     dx,ax
        mov     dx,3C4h                 ; Enable Write to All Four Planes
        mov     ax,0F02h
        out     dx,ax
        mov     ax,0A000h               ; Clear Display Memory
        mov     es,ax
        xor     di,di
        xor     ax,ax
        mov     cx,8000h
        cld
        rep     stosw
        mov     dx,3D4h                 ; Reprogram CRT Controller:
        mov     ax,00014h               ; turn off dword mode
        out     dx,ax
        mov     ax,0e317h               ; turn on byte mode
        out     dx,ax
        mov     ax,00409h               ; cell height
        out     dx,ax
        ret
endp    SetModeX

;-----------------------------------------------------------------------------
; WaitVR - Waits Vertical Retrace.
;-----------------------------------------------------------------------------

proc    WaitVR
        mov     dx,3DAh
WaitStartVR:
        in      al,dx
        test    al,8
        je      WaitStartVR
WaitEndVR:
        in      al,dx
        test    al,8
        jne     WaitEndVR
        ret
endp    WaitVR

;-----------------------------------------------------------------------------
; LoadFont - Loads the VLA font.
;-----------------------------------------------------------------------------

proc    LoadFont
        mov     ax,SEG FontFAR          ; Load Font File Address
        mov     es,ax
        mov     [FontDataSeg],ax
        mov     [FontDataOfs],Size FontHeader
        mov     al,[es:FontHeader.First] ; Get Font First Char
        mov     [FontFirst],al
        mov     al,[es:FontHeader.Width] ; Get Font Data Size
        mov     ah,[es:FontHeader.Height]
        mov     [FontWidth],al
        mov     [FontHeight],ah
        mul     ah
        mov     [FontSize],ax
        mov     dl,[es:FontHeader.Total]
        xor     dh,dh
        mul     dx
        add     ax,Size FontHeader      ; Copy Font Widths.
        mov     si,ax
        xor     di,di
        mov     cl,[es:FontHeader.Total]
        xor     ch,ch
CopyWidths:
        mov     al,[es:si]
        mov     [FontWidths+di],al
        inc     si
        inc     di
        loop    CopyWidths
        ret
endp    LoadFont

;-----------------------------------------------------------------------------
; DrawChar - Draw a Font Char.
; In:
;  AL = Character Code.
;  ES:DI = Frame Screen Address.
;-----------------------------------------------------------------------------

proc    DrawChar
        sub     al,[FontFirst]          ; Get Char BitMap Offset
        xor     ah,ah
        mov     bx,ax
        mul     [FontSize]
        add     ax,[FontDataOfs]        ; si = char offset
        mov     si,ax
        mov     dl,[FontWidths+bx]      ; dx = char width
        xor     dh,dh
        mov     cl,[FontHeight]         ; cx = char height
        xor     ch,ch
        mov     al,[FontWidth]          ; bp = font max width
        xor     ah,ah
        mov     bp,ax

        mov     ax,XDOTS                ; Draw on Screen Center
        sub     ax,dx
        shr     ax,1
        shl     ax,1
        add     di,XDOTS*(16+YDOTS)
        add     di,ax

        push    ds                      ; ds = font data segment
        mov     ds,[FontDataSeg]
DrawCharLoop:
        push    cx
        push    si
        push    di
        xor     ah,ah
DrawPlane1:
        mov     al,[ds:si]
        test    al,al
        je      SkipColor
        mov     al,0FFh
        mov     [es:di],ax
SkipColor:
        add     si,bp
        add     di,XDOTS*2
        loop    DrawPlane1
        pop     di
        pop     si
        pop     cx
        inc     si
        add     di,2
        dec     dx
        jg      DrawCharLoop
        pop     ds
        ret
endp    DrawChar

;-----------------------------------------------------------------------------
; DrawMesg - Draws the Next Message on the Screen.
;-----------------------------------------------------------------------------

proc    DrawMesg
        pusha
        push    es
        mov     ax,ds                   ; Loads Frame Area Address
        mov     es,ax
        lea     di,[Frame] 
        cld
        mov     si,[MesgOff]
        lodsb
        test    al,al
        stc
        je      DrawMesgExit
        mov     [MesgOff],si
        call    DrawChar
        clc
DrawMesgExit:
        pop     es
        popa
        ret
endp    DrawMesg

;-----------------------------------------------------------------------------
; Random - Returns a random number of 16 bits.
;-----------------------------------------------------------------------------

proc    Random
        mov     ax,[Seed]
        imul    ax,8905h
        inc     ax
        mov     [Seed],ax
        ret
endp    Random

;-----------------------------------------------------------------------------
; Flames - Flames Like Screen Animation.
;-----------------------------------------------------------------------------

proc    Flames
        pusha
        push    ds
        push    es

        call    SetModeX                ; Sets VGA 80x80x256 graphics mode

        call    LoadFont
        mov     [MesgOff],offset TheMessage

        call    WaitVR
        lea     si,[Palette]            ; Sets Color Palette
        mov     cx,768
        mov     dx,3C8h
        xor     al,al
        out     dx,al
        inc     dx
        cld
        rep     outsb
        mov     ax,ds                   ; Clears Frame Buffer
        mov     es,ax
        lea     di,[Frame]
        mov     cx,XDOTS*(YDOTS+HIDDEN)
        xor     ax,ax
        rep     stosw
        mov     ax,0A000h               ; Set Display Memory Segment
        mov     es,ax
        mov     bx,FLSEED               ; Loads Flames Seed Factor
        xor     bp,bp                   ; Start Timer Counter
         
FlamesLoop:
        inc     bp                      ; Increase Timer
        call    WaitVR                  ; Wait Vertical Retrace
        lea     si,[Frame]              ; Write Frame to the Screen
        xor     di,di
        mov     cx,XDOTS*YDOTS/2
WriteFrameLoop:
        lodsw
        mov     dl,al
        lodsw
        mov     dh,al
        mov     ax,dx
        stosw
        loop    WriteFrameLoop

        cmp     bp,TIMEOUT              ; Don't Draw Message while
        jae     DontDrawMesg            ; Fading out the Flames.
        mov     ax,bp
        xor     dx,dx
        mov     cx,MESGSPEED
        div     cx
        test    dx,dx                   ; Draws Messages...
        jne     DontDrawMesg
        call    DrawMesg
        jnc     DontDrawMesg            ; If no more message text,
        mov     bp,TIMEOUT              ; Start fading out...
DontDrawMesg:

        mov     cx,XDOTS*(YDOTS+HIDDEN-2) ; Transform Upper Frame Lines
        lea     si,[Frame+2*XDOTS]
FlamesTransform:
        mov     ax,[ds:si-2]            ; Sets Pixel at (X,Y) like
        add     ax,[ds:si+0]            ; the average of the near four
        add     ax,[ds:si+2]            ; pixels below it:
        add     ax,[ds:si+2*XDOTS]      ; P(X,Y) = (P(X-1,Y+1)+P(X,Y+1)+
        sub     ax,bx                   ;   P(X+1,Y+1)+P(X,Y+2)-Seed)/4
        sar     ax,2
        jge     FlameNotTooLow
        xor     ax,ax
FlameNotTooLow:
        mov     [ds:si-2*XDOTS],ax
        add     si,2
        loop    FlamesTransform

        ; Sets New Random Bottom Flames with Colors from 0 to 127.
        lea     si,[Frame+2*XDOTS*(YDOTS+HIDDEN-2)]
        mov     cx,XDOTS
        xor     dx,dx
RandomFlames:
        call    Random                  ; Use Random to Create a New
        test    ax,ax                   ; Flames Bottom Lines
        js      NotNewColor
        call    Random
        mov     dl,al
        and     dl,7Fh
NotNewColor:
        mov     [ds:si],dx
        mov     [ds:si+2*XDOTS],dx
        add     si,2
        loop    RandomFlames
        mov     ah,1                    ; or Any Key Pressed?
        int     16h                     
        je      CheckTimer
        mov     ah,0
        int     16h
        mov     bp,TIMEOUT
CheckTimer:
        cmp     bp,TIMEOUT              ; Timeout?
        jb      FlamesLoop
DecreaseFlames:
        inc     bx                      ; Increase Flames Seed
        cmp     bx,FLBLANK              ; (makes flames more low)
        jbe     FlamesLoop
FlamesExit:
        mov     ax,0003h                ; Set Text Mode 80x25x16
        int     10h
        pop     es
        pop     ds
        popa
        ret
endp    Flames

;-----------------------------------------------------------------------------
; Start - Startup code called from DOS.
;-----------------------------------------------------------------------------

proc    Start
        mov     ax,@Data                ; Set DS Segment
        mov     ds,ax
        mov     bx,ss                   ; Shrink Program Segment
        mov     ax,es
        sub     bx,ax
        mov     ax,sp
        shr     ax,4
        inc     ax
        add     bx,ax
        mov     ah,4Ah
        call    Flames                  ; Do Flames Demo
        mov     ax,4C00h
        int     21h                     ; Exit to DOS.
endp    Start

        end     Start
[ RETURN TO DIRECTORY ]