home *** CD-ROM | disk | FTP | other *** search
- ;=============================================================================
- ; mandel.asm - Mandelbrot Set calculation Routines.
- ; File created: 9-22-93
- ; Copyright (C) 1993, Carlos Hasan Last modified: 10-11-93
- ;
- ; Description:
- ; This file implements the Mandelbrot Set fractal using a fast algorithm
- ; based on the Fracint's Boundary trace method. The drawing is optimized
- ; for using with VGA 320x200x256 graphics mode.
- ;
- ; Portability:
- ; Requires Turbo Assembler 3.2 or better to be assembler.
- ; Dependent on the IBM PC 386 or later microprocessor.
- ;=============================================================================
-
- .model small,pascal
- .386
-
- global DrawMandel:proc
-
- ;======================= Mandelbrot Routine ==================================
-
- ;-----------------------------------------------------------------------------
- ; Equates for Mandelbrot Set calculation.
- ;-----------------------------------------------------------------------------
-
- MAXITER equ 150 ; max iterations
- FUDGE equ 24 ; fudge factor
- BAILOUT equ 4 shl FUDGE ; bait out
- PERIODMASK equ 0FFFF0000h ; periodicy mask
-
- ;-----------------------------------------------------------------------------
- ; Miscellaneus Data used for calculation.
- ;-----------------------------------------------------------------------------
-
- .data
-
- SavedAnd dw ?
- SavedIncr dw ?
- SavedMask dd ?
- OldIter dw ?
- LinX dd ?
- LinY dd ?
- SavedX dd ?
- SavedY dd ?
-
- ;-----------------------------------------------------------------------------
- ; CalcMand - Main Mandelbrot Set calculation routine.
- ; In:
- ; ESI - real part of the initial complex value.
- ; EDI - imaginary part of the initial complex value.
- ; Out:
- ; AL - Mandelbrot level.
- ; Modified:
- ; EAX, EBX, ECX, EDX, ESI, EDI, Flags.
- ;-----------------------------------------------------------------------------
-
- .code
-
- CalcMand proc near
-
- mov [SavedAnd],1 ; init periodicy check.
- mov [SavedIncr],1
- mov [SavedMask],1
- mov [SavedX],0FFFFFFFFh ; values impossibles
- mov [SavedY],0FFFFFFFFh ; for x and y.
-
- mov [LinX],esi ; linx = real
- mov [LinY],edi ; liny = imag
-
- xor esi,esi ; x = 0
- xor edi,edi ; y = 0
-
- mov cx,MAXITER ; iter = maxiter
-
- MandLoop: mov eax,esi ; ebx = x*x
- imul esi
- shrd eax,edx,FUDGE
- mov ebx,eax
-
- mov eax,edi ; ebx = y*y
- imul edi
- shrd eax,edx,FUDGE
-
- mov edx,ebx ; edx = x*x + y*y
- add edx,eax
- sub ebx,eax ; ebx = x*x - y*y
-
- cmp edx,BAILOUT ; x*x + y*y > bailout?
- jge MandBreak ; break.
-
- mov eax,edi ; y = 2*x*y + liny
- imul esi
- shrd eax,edx,FUDGE-1
- add eax,[LinY]
- mov edi,eax
-
- add ebx,[LinX] ; x = x*x - y*y + linx
- mov esi,ebx
-
- cmp [OldIter],cx ; check periodicity.
- jle MandContinue
-
- mov eax,esi
- xor eax,[SavedX]
- test eax,PERIODMASK
- jne CheckSave
- mov eax,edi
- xor eax,[SavedY]
- test eax,PERIODMASK
- jne CheckSave
- xor cx,cx
- jmp MandBreak
-
- CheckSave: test cx,[SavedAnd]
- jne MandContinue
- mov [SavedX],esi
- mov [SavedY],edi
- dec [SavedIncr]
- jne MandContinue
- stc
- rcl [SavedAnd],1
- mov [SavedIncr],4
-
- MandContinue: dec cx
- jne MandLoop
-
- MandBreak: mov ax,cx
- mov bx,cx
- sub bx,10
- test cx,cx
- je SetOldIter
- mov bx,MAXITER
- SetOldIter: mov [OldIter],bx
- ret
-
- CalcMand endp
-
-
- ;=================== Boundary Trace Method (BTM) =============================
-
- ;-----------------------------------------------------------------------------
- ; Equates for BTM into a 320x200x256 virtual screen.
- ;-----------------------------------------------------------------------------
-
- MAXWIDTH equ 320 ; Virtual screen dimensions.
- MAXHEIGHT equ 200
- XSTART equ 0 ; Virtual screen drawing
- XSTOP equ 319 ; window coordinates.
- YSTART equ 0
- YSTOP equ 199
- NORTH equ 0 ; Used for BTM algorithm.
- EAST equ 1
- SOUTH equ 2
- WEST equ 3
- MAXINT equ 7FFFh
-
- ;-----------------------------------------------------------------------------
- ; Data used for BTM during plotting.
- ;-----------------------------------------------------------------------------
-
- .data
-
- LeftX dw MAXHEIGHT dup (?) ; array of left and right
- RightX dw MAXHEIGHT dup (?) ; limits for poly filling.
- ComplexX dd MAXWIDTH dup (?) ; translate screen coords
- ComplexY dd MAXHEIGHT dup (?) ; to complex coords.
- FirstX dw ? ; temporary variables used
- FirstY dw ? ; for BTM algorithm.
- Iters dw ?
- Color db ?
- Dir db ?
-
- ;-----------------------------------------------------------------------------
- ; GetPixel - get the pixel color at specified location.
- ; In:
- ; ES - Virtual screen segment.
- ; (SI,DI) - Pixel position.
- ; Out:
- ; AL - Pixel color.
- ; Modified:
- ; BX, Flags.
- ;-----------------------------------------------------------------------------
-
- .code
-
- GetPixel macro
-
- mov bx,di
- imul bx,MAXWIDTH
- add bx,si
- mov al,es:[bx]
-
- endm
-
- ;-----------------------------------------------------------------------------
- ; PutPixel - put the pixel color at specified location.
- ; In:
- ; ES - Virtual screen segment.
- ; (SI,DI) - Pixel position.
- ; AL - Pixel color.
- ; Modified:
- ; BX, Flags.
- ;-----------------------------------------------------------------------------
-
- PutPixel macro
-
- mov bx,di
- imul bx,MAXWIDTH
- add bx,si
- mov es:[bx],al
-
- endm
-
- ;-----------------------------------------------------------------------------
- ; GetColor - get the pixel color using the MandelBrot Set routine or
- ; the virtual screen if already painted.
- ; In:
- ; ES - Virtual screen segment.
- ; (SI,DI) - Pixel position.
- ; Out:
- ; AL - Pixel color.
- ; Modified:
- ; EAX, EBX, ECX, EDX, Flags.
- ;-----------------------------------------------------------------------------
-
- GetColor proc near
-
- GetPixel
- test al,al
- jne ColorNonZero
- push si
- push di
- shl si,2
- shl di,2
- mov esi,[ComplexX+si]
- mov edi,[ComplexY+di]
- call CalcMand
- pop di
- pop si
- inc al
- PutPixel ; don't destroy AL.
- ColorNonZero: ret
-
- GetColor endp
-
- ;-----------------------------------------------------------------------------
- ; BoundTrace - Trace a boundary and fill it.
- ; In:
- ; ES - Virtual screen segment.
- ; (SI,DI) - starting point inside of the boundary.
- ; Modified:
- ; EAX, EBX, ECX, EDX, Flags.
- ;-----------------------------------------------------------------------------
-
- BoundTrace proc near
-
- mov [FirstX],si
- mov [FirstY],di
- call GetColor
- mov [Color],al
- mov [Dir],EAST
- mov [Iters],0
-
- BoundLoop: mov bx,di
- shl bx,1
- cmp si,[LeftX+bx]
- jge NotLess
- mov [LeftX+bx],si
- NotLess: cmp si,[RightX+bx]
- jle NotGreat
- mov [RightX+bx],si
- NotGreat: mov al,[Dir]
- cmp al,NORTH
- je GoNorth
- cmp al,EAST
- je GoEast
- cmp al,SOUTH
- je GoSouth
- cmp al,WEST
- je GoWest
-
- GoNorth: cmp di,[FirstY]
- jle SetEast
- dec di
- call GetColor
- inc di
- cmp al,[Color]
- jne SetEast
- dec di
- cmp si,XSTART
- jle BoundContinue
- dec si
- call GetColor
- inc si
- cmp al,[Color]
- jne BoundContinue
- dec si
- jmp SetWest
-
- GoEast: cmp si,XSTOP
- jge SetSouth
- inc si
- call GetColor
- dec si
- cmp al,[Color]
- jne SetSouth
- inc si
- cmp di,[FirstY]
- jle BoundContinue
- dec di
- call GetColor
- inc di
- cmp al,[Color]
- jne BoundContinue
- dec di
- jmp SetNorth
-
- GoSouth: cmp di,YSTOP
- jge SetWest
- inc di
- call GetColor
- dec di
- cmp al,[Color]
- jne SetWest
- inc di
- cmp si,XSTOP
- jge BoundContinue
- inc si
- call GetColor
- dec si
- cmp al,[Color]
- jne BoundContinue
- inc si
- jmp SetEast
-
- GoWest: cmp si,XSTART
- jle SetNorth
- dec si
- call GetColor
- inc si
- cmp al,[Color]
- jne SetNorth
- dec si
- cmp di,YSTOP
- jge BoundContinue
- inc di
- call GetColor
- dec di
- cmp al,[Color]
- jne BoundContinue
- inc di
- jmp SetSouth
-
- SetNorth: mov [Dir],NORTH
- jmp BoundContinue
-
- SetEast: mov [Dir],EAST
- jmp BoundContinue
-
- SetSouth: mov [Dir],SOUTH
- jmp BoundContinue
-
- SetWest: mov [Dir],WEST
-
- BoundContinue: inc [Iters]
- cmp si,[FirstX]
- jne BoundLoop
- cmp di,[FirstY]
- jne BoundLoop
-
- cmp [Iters],4
- jl BoundExit
-
- mov si,[FirstY]
- cld
- BoundForY: mov bx,si
- shl bx,1
- mov ax,[LeftX+bx]
- mov dx,[RightX+bx]
- mov [LeftX+bx],+MAXINT
- mov [RightX+bx],-MAXINT
- cmp ax,dx
- jg BoundExit
- mov cx,dx
- sub cx,ax
- inc cx
- mov di,si
- imul di,MAXWIDTH
- add di,ax
- mov al,[Color]
- ScanColor: repne scasb
- jne BoundNextY
- jcxz BoundNextY
- FillBlank: mov ah,es:[di]
- test ah,ah
- jne ScanColor
- mov es:[di],al
- inc di
- dec cx
- jne FillBlank
- BoundNextY: inc si
- cmp si,YSTOP
- jle BoundForY
-
- BoundExit: mov si,[FirstX]
- mov di,[FirstY]
- ret
-
- BoundTrace endp
-
- ;-----------------------------------------------------------------------------
- ; DrawMandel - Draw the Mandelbrot Set into a virtual 320x200x256 screen.
- ; In:
- ; (PosX,PosX) - top left corner complex number.
- ; (DeltaX,DeltaY) - complex windows extends.
- ; ScreenSeg - Virtual screen segment.
- ;-----------------------------------------------------------------------------
-
- DrawMandel proc PosX:dword,PosY:dword, \
- DeltaX:dword,DeltaY:dword, ScreenSeg:word
-
- mov ax,ds
- mov es,ax
- cld
-
- mov cx,MAXHEIGHT
- lea di,[LeftX]
- mov ax,+MAXINT
- rep stosw
-
- mov cx,MAXHEIGHT
- lea di,[RightX]
- mov ax,-MAXINT
- rep stosw
-
- mov ecx,XSTOP-XSTART
- mov eax,[DeltaX]
- cdq
- div ecx
- inc cx
- mov edx,eax
- add eax,[PosX]
- add eax,[PosX]
- sar eax,1
- lea di,[ComplexX]
- MakeX: stosd
- add eax,edx
- loop MakeX
-
- mov ecx,YSTOP-YSTART
- mov eax,[DeltaY]
- cdq
- div ecx
- inc cx
- mov edx,eax
- add eax,[PosY]
- add eax,[PosY]
- sar eax,1
- lea di,[ComplexY]
- MakeY: stosd
- add eax,edx
- loop MakeY
-
- mov ax,[ScreenSeg]
- mov es,ax
- mov cx,MAXWIDTH * MAXHEIGHT
- xor di,di
- xor ax,ax
- rep stosb
-
- mov di,YSTART
- ForY: mov si,XSTART
- ForX: GetPixel
- test al,al
- jne NextX
- call BoundTrace
- NextX: inc si
- cmp si,XSTOP
- jle ForX
- NextY: inc di
- cmp di,YSTOP
- jle ForY
- ret
-
- DrawMandel endp
-
- end
-