Metropoli BBS
VIEWER: land.asm MODE: TEXT (ASCII)
;=============================================================================
; land.asm - Landscape fractal demostration.
;                                                    File created:  9/30/93
; Copyright (c) 1993, Carlos Hasan                  Last modified: 10/22/93
;
; Description:
;   This file implements a fractal 3D landscape rotation using the basic
;   plasma routines and 3D rotations. This uses the VGA 320x200x256 mode.
;
; Portability:
;  Requires Turbo Assembler 3.2 or better to be assembled.
;  Dependent on the IBM PC 286 and the VGA graphics card.
;
; Modifications:
;  10/22/93  - Startup Code. Now is an Standalone Program.
;=============================================================================

                .model  small,pascal
                .286

                dosseg                          ; used to link like
                .stack  1024                    ; an standalone program.

                global  DrawPlasma:proc		; in PLASMA.ASM file.
                global  LandScape:proc

;===================== Demo equates and data =================================

TIMEOUT         equ     70 * 10                 ; about 10 sec for timeout.
FADESPEED       equ     6                       ; fade speed.
SCREENWIDTH     equ     320                     ; screen dimensions.
SCREENHEIGHT    equ     200
TRIGSHIFT       equ     6                       ; sin/cos shift factor.
LANDSCAPEX      equ     320                     ; landscape grid dimensions.
LANDSCAPEY      equ     200
WATERLEVEL      equ     128                     ; plasma water level.
PLASMASEED      equ     8945h                   ; plasma random seed.
CENTERX         equ     160                     ; screen grid center
CENTERY         equ     140                     ; position.
GRIDX           equ     32                      ; screen grid dimensions
GRIDY           equ     32                      ; and gaps length.
GRIDDX          equ     6
GRIDDY          equ     6

                .data

                include sincos.inc              ; sinus/cosinus table.

LandSeg         dw      ?                       ; landscape levels.
Pixels          dw      GRIDX * GRIDY dup (?)   ; screen pixels locations.
Palette         db      768 dup (?)             ; hold the color palette.
FromPalette     db      768 dup (?)             ; fading-palettes.
ToPalette       db      768 dup (?)
Timer           dw      ?                       ; timer counter.

;======================= Demo routines =======================================

                .code

;-----------------------------------------------------------------------------
; WaitVRT - Waits the VGA vertical retrace period.
;-----------------------------------------------------------------------------

WaitVRT         proc near

                mov     dx,3DAh
WaitVRT1:       in      al,dx                   ; wait the start of
                test    al,8                    ; vertical retrace.
                jz      WaitVRT1
WaitVRT2:       in      al,dx                   ; wait the end of
                test    al,8                    ; vertical retrace.
                jnz     WaitVRT2
                ret

WaitVRT         endp

;-----------------------------------------------------------------------------
; SetPalette - set the 256 entries of the VGA color palette.
; In:
;   DS:SI - Palette structure address.
;-----------------------------------------------------------------------------

SetPalette      proc near

                mov     cx,768
                mov     dx,3C8h
                xor     al,al
                out     dx,al
                call    WaitVRT
                mov     dx,3C9h
                rep     outsb
                ret

SetPalette      endp

;-----------------------------------------------------------------------------
; FadeTo - Fade palette effect.
; In:
;  FromPalette - Source palette.
;  ToPalette   - Destination palette.
;-----------------------------------------------------------------------------

FadeTo         proc near

FadeLoop:       lea     si,[FromPalette]
                call    SetPalette
                mov     cx,768
                xor     dx,dx
                xor     bx,bx
FadeColor:      mov     al,[FromPalette+bx]
                mov     ah,[ToPalette+bx]
                cmp     al,ah
                je      SkipFade
                ja      FadeOut
FadeIn:         add     al,FADESPEED
                cmp     al,ah
                jl      SetColor
                mov     al,ah
                jmp     SetColor
FadeOut:        sub     al,FADESPEED
                cmp     al,ah
                jg      SetColor
                mov     al,ah
                jmp     SetColor
SetColor:       mov     [FromPalette+bx],al
                inc     dx
SkipFade:       inc     bx
                loop    FadeColor
                test    dx,dx
                jne     FadeLoop
                ret

FadeTo          endp

;-----------------------------------------------------------------------------
; FlashIn - Flash fade-in effect.
; In:
;  Palette - Source palette.
;-----------------------------------------------------------------------------

FlashIn         proc near

                mov     ax,ds
                mov     es,ax
                cld
                lea     di,[FromPalette]        ; fade from black to white.
                mov     cx,768
                mov     al,00h
                rep     stosb
                lea     di,[ToPalette]
                mov     cx,768
                mov     al,3Fh
                rep     stosb
                call    FadeTo
                lea     di,[FromPalette]        ; fade from white to
                mov     cx,768                  ; destination palette.
                mov     al,3Fh
                rep     stosb
                lea     si,[Palette]
                lea     di,[ToPalette]
                mov     cx,768
                rep     movsb
                call    FadeTo
                ret

FlashIn         endp

;-----------------------------------------------------------------------------
; FlashOut - Flash fade-out effect.
; In:
;  Palette - Source palette.
;-----------------------------------------------------------------------------

FlashOut        proc near

                mov     ax,ds
                mov     es,ax
                cld
                lea     di,[ToPalette]          ; fade from source palette
                mov     cx,768                  ; to white palette.
                mov     al,3Fh
                rep     stosb
                lea     si,[Palette]
                lea     di,[FromPalette]
                mov     cx,768
                rep     movsb
                call    FadeTo
                lea     di,[FromPalette]        ; fade from white to black.
                mov     cx,768
                mov     al,3Fh
                rep     stosb
                lea     di,[ToPalette]
                mov     cx,768
                mov     al,00h
                rep     stosb
                call    FadeTo
                ret

FlashOut        endp

;-----------------------------------------------------------------------------
; GenLandscape - This routines generates the lanscape surface using the
;   plasma routines basically and checks that all the mountain levels
;   are in the right range.
; In:
;  LandSeg - Segment addressing for the landscape.
;-----------------------------------------------------------------------------

GenLandscape    proc near

                mov     ax,[LandSeg]            ; clear landscape area.
                mov     es,ax
                xor     di,di
                xor     ax,ax
                mov     cx,LANDSCAPEX * LANDSCAPEY
                cld
                rep     stosb

                ; draw initial plasma landscape.
                call    DrawPlasma,0,0,LANDSCAPEX-1,LANDSCAPEY-1, \
                                                 PLASMASEED,[LandSeg]

                ; adjust levels for the real landscape.

                mov     ax,[LandSeg]
                mov     es,ax
                xor     di,di
                mov     cx,LANDSCAPEX * LANDSCAPEY
                cld
AdjLoop:        mov     al,es:[di]
                sub     al,WATERLEVEL
                test    al,al
                jge     AdjLevel
                xor     al,al
AdjLevel:       xor     ah,ah
                imul    ax,192
                inc     ah
                mov     es:[di],ah
                inc     di
                loop    AdjLoop
                ret

GenLandscape    endp


;-----------------------------------------------------------------------------
; DrawLandscape - Draws a region of the landscape on the screen starting
;   at the specified position and rotation angles. The clipping support
;   have been removed for speed.
; In:
;   (PosX,PosY) - Landscape starting position.
;   AngleY      - Inclination angle.
;   AngleZ      - Spin angle.
;-----------------------------------------------------------------------------

DrawLandscape   proc near PosX:word,PosY:word, AngleY:word,AngleZ:word
                local SinY:word,SinZ:word,CosY:word,CosZ:word, \
                      YIAdd:word,YJAdd:word,ZIAdd:word,ZJAdd:word, \
                      Y0:word,Z0:word,Y:word,Z:word

                mov     bx,[AngleY]             ; compute rotation
                mov     al,[SinTable+bx]        ; parameters.
                cbw
                mov     [SinY],ax
                mov     al,[CosTable+bx]
                cbw
                mov     [CosY],ax

                mov     bx,[AngleZ]
                mov     al,[SinTable+bx]
                cbw
                mov     [SinZ],ax
                mov     al,[CosTable+bx]
                cbw
                mov     [CosZ],ax

                mov     ax,[SinZ]               ; yiadd = griddx * sinz
                imul    ax,GRIDDX
                mov     [YIAdd],ax
                mov     ax,[CosZ]               ; yjadd = griddy * cosz
                imul    ax,GRIDDY
                mov     [YJAdd],ax
                mov     ax,[CosZ]               ; ziadd = griddx * cosz * siny
                mov     dx,[SinY]
                imul    dx
                imul    ax,GRIDDX
                sar     ax,TRIGSHIFT
                mov     [ZIAdd],ax
                mov     ax,[SinZ]               ; zjadd = -griddy * sinz * siny
                mov     dx,[SinY]
                imul    dx
                imul    ax,-GRIDDY
                sar     ax,TRIGSHIFT
                mov     [ZJAdd],ax

                mov     ax,[YIAdd]              ; compute starting grid
                imul    ax,-GRIDX/2             ; corner position.
                mov     dx,[YJAdd]
                imul    dx,-GRIDY/2
                add     ax,dx
                mov     [Y0],ax
                mov     ax,[ZIAdd]
                imul    ax,-GRIDX/2
                mov     dx,[ZJAdd]
                imul    dx,-GRIDY/2
                add     ax,dx
                mov     [Z0],ax

                mov     ax,[LandSeg]            ; es = landscape segment.
                mov     es,ax

                lea     si,[Pixels]             ; ds:si = pixels offsets.

                mov     di,[PosY]               ; store offset
                imul    di,LANDSCAPEX           ; just for speed.
                add     di,[PosX]

                mov     cx,GRIDX
ForI:           push    cx
                mov     ax,[Y0]                 ; y = y0
                mov     [Y],ax
                mov     ax,[Z0]                 ; z = z0
                mov     [Z],ax

                mov     cx,GRIDY
ForJ:           push    es
                mov     ax,0A000h               ; clear old pixel.
                mov     es,ax
                mov     bx,[si]
                mov     byte ptr es:[bx],al
                pop     es

; here the code must be hooked to support clipping, use an "illegal"
; offset to store pixels that are not drawed, and then the routine above
; must erase only "legal" pixels.

                mov     bl,es:[di]              ; bl = landscape(posx,posy)
                mov     al,bl                   ; ax = -centery + (z + bl*cosy)
                xor     ah,ah
                imul    [CosY]
                add     ax,[Z]
                sar     ax,TRIGSHIFT
                sub     ax,CENTERY
                imul    ax,SCREENWIDTH
                mov     dx,[Y]                  ; dx = centery + y
                sar     dx,TRIGSHIFT
                add     dx,CENTERX
                sub     dx,ax
                mov     [si],dx                 ; store pixel offset.

                push    es
                mov     ax,0A000h               ; paint new pixel.
                mov     es,ax
                xchg    dx,bx
                mov     es:[bx],dl
                pop     es

                mov     ax,[YJAdd]              ; y = y + yjadd
                add     [Y],ax
                mov     ax,[ZJAdd]              ; z = z + zjadd
                add     [Z],ax
                inc     di                      ; posy = posy + 1
                add     si,2
                loop    ForJ

                mov     ax,[YIAdd]              ; y0 = y0 + yiadd
                add     [Y0],ax
                mov     ax,[ZIAdd]              ; z0 = z0 + ziadd
                add     [Z0],ax
                add     di,LANDSCAPEX-GRIDY     ; posy = posy - gridy
                pop     cx                      ; posx = posx + 1
                loop    ForI
                ret

DrawLandscape   endp

;-----------------------------------------------------------------------------
; LandScape - Main landscape demo routine. Because this routine was tested
;   using the Borland Pascal high-level interface, the allocation of the
;   memory is done by the caller.
; In:
;  DS     - Data segment.
;  MemSeg - Memory segment of 64K needed for storage.
;-----------------------------------------------------------------------------

LandScape       proc    MemSeg:word
                local   PosX:word,PosY:word,AngleY:word,AngleZ:word

                mov     ax,0013h                ; set VGA 320x200x256 mode.
                int     10h

                mov     ax,[MemSeg]             ; setup landscape
                mov     [LandSeg],ax            ; memory segment.

                lea     di,[Palette]            ; set black palette.
                mov     ax,ds
                mov     es,ax
                mov     cx,768
                xor     ax,ax
                cld
                rep     stosb
                lea     si,[Palette]
                call    SetPalette

GenPalette:     lea     di,[Palette]            ; generate color palette.
                mov     ax,3F00h
                mov     [di+0],al               ; background.
                mov     [di+1],al
                mov     [di+2],al
                add     di,3
                mov     [di+0],al               ; blue. (water)
                mov     [di+1],al
                mov     [di+2],ah
                add     di,3
                mov     ax,0000h                ; green to brown.
                mov     bx,3F00h
                mov     dx,0000h
                mov     cx,61
GP0:            mov     [di+0],ah
                mov     [di+1],bh
                mov     [di+2],dh
                add     di,3
                add     ax,0108h
                sub     bx,0086h
                add     dx,0000h
                loop    GP0
                mov     ax,3F00h                ; brown to white.
                mov     bx,2000h                ; (mountain)
                mov     dx,0000h
                mov     cx,48
GP1:            mov     [di+0],ah
                mov     [di+1],bh
                mov     [di+2],dh
                add     di,3
                add     ax,0000h
                add     bx,00AAh
                add     dx,0150h
                loop    GP1
                mov     ax,3F00h                ; white. (snow)
                mov     bx,3F00h
                mov     dx,3F00h
                mov     cx,145
GP2:            mov     [di+0],ah
                mov     [di+1],bh
                mov     [di+2],dh
                add     di,3
                add     ax,0000h
                add     bx,0000h
                add     dx,0000h
                loop    GP2

                call    GenLandscape            ; creates the landscape.

                mov     [AngleY],240            ; inclination angle.
                mov     [AngleZ],0              ; initial spin angle.
                mov     [PosX],0                ; starting landscape
                mov     [PosY],0                ; position.

                ; pixels offset array could be cleaned but not necesary,
                ; because i am using the 64K of video memory ...
                ; i can't overwrite anything! :-)

                ; draw hidden landscape and do flash-in effect.

                call    DrawLandscape,[PosX],[PosY],[AngleY],[AngleZ]
                lea     si,[Palette]
                call    FlashIn

                mov     [Timer],0               ; set timer counter.

                mov     si,1                    ; starting landscape
                mov     di,1                    ; directions.

LandLoop:       call    WaitVRT                 ; wait vertical retrace.

                push    si                      ; draw landscape.
                push    di
                call    DrawLandscape,[PosX],[PosY],[AngleY],[AngleZ]
                pop     di
                pop     si

                inc     byte ptr [AngleZ]       ; increase spin angle.
                add     [PosX],si               ; advance landscape position.
                add     [PosY],di
TestX:          cmp     [PosX],0                ; check for boundaries.
                jl      NegIncX
                cmp     [PosX],LANDSCAPEX-GRIDX
                jl      TestY
NegIncX:        sub     [PosX],si
                neg     si
TestY:          cmp     [PosY],0
                jl      NegIncY
                cmp     [PosY],LANDSCAPEY-GRIDY
                jl      CheckExit
NegIncY:        sub     [PosY],di
                neg     di

CheckExit:      inc     [Timer]                 ; timeout?
                cmp     [Timer],TIMEOUT
                jae     ByeBye

                mov     ah,1                    ; any key pressed?
                int     16h
                jz      LandLoop

ByeBye:         call    FlashOut                ; flash-out!

                mov     ax,03h                  ; set 80x25x16 text mode.
                int     10h
                ret

LandScape       endp


;-----------------------------------------------------------------------------
; Start - Startup code called from DOS.
; In:
;   ES - Program Segment Prefix.
;-----------------------------------------------------------------------------

Start           proc

                mov     ax,@Data
                mov     ds,ax

                mov     ax,ss                   ; shrink memory block.
                mov     bx,es
                sub     ax,bx
                mov     bx,sp
                shr     bx,4
                inc     bx
                add     bx,ax
                mov     ah,4Ah
                int     21h

                mov     ah,48h                  ; allocate 64000 bytes.
                mov     bx,4000
                int     21h
                jc      Exit
                push    ax
                call    LandScape,ax            ; do demostration.
                pop     es
                mov     ah,49h                  ; free 64000 bytes.
                int     21h

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

Start           endp

                end     Start
[ RETURN TO DIRECTORY ]