home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Party 1994: Try This At Home
/
disk_image.bin
/
source
/
fakesrc
/
part10
/
mandel.asm
< prev
next >
Wrap
Assembly Source File
|
1993-10-10
|
16KB
|
489 lines
;=============================================================================
; 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