Fractalissimo
-------------

	Hello, welcome into the wonderfull world of fractals..

	With this artical, you will easily be able to generate fractals,
	which could be used to make a voxel space, for a sky or only for
	the fun !

	Well, it's really extremely easy, so you can drink a beer (kro..)
all through this article..

	In the begining, our superb fractal will be generated by the shitty
recursivity. Smart for some people, absolutely heavy for others. And me ?
It's very heavy, smart certainly, but especially handy, and it's the most
important here, because we are going to make this in assembly of course !
We also don't generate fractals every VBL, so put the recursivity in da ass..

	Generation is a recursive subdivide of a square zone. Let call our
map W. It have a size of 65536 bytes (strange, he ?). Fill it all with the
0FFh value, and put 03Ch (for example, a random is also good) at W(0,0) and
therefore at W(256,0) , W(0,256) and W(256,256). (cause of 256*256 map..)

	Now we only have to call a little routine, which have the size and the
location of a square in the map, for parameters. We start with a size of 256
4and offset 0, the entire map in fact..

	But, what do this routine do ? (And the police ?). In fact, it uses
corner's values of the zone it has to scan.. On each edge (and if middle value
of the edge is 0FFh), it calculates the average of the two extremes, and add
a noise proportionnal to the square's size. The result is simply put at the
middle of the edge in the map (if the previous value was 0FFh, remember ?).

	The center's square value, is the average of four heights of it, with
also some noise proportionnal to his size. We don't need to now if the
previous was 0FFh or not, we just put the new value in all case..

	The routine calls itself recursively. It divides the zone into 4
quadrants, and it calls itself for each one, until square's size is two.

	Here is the main procedure :


      | RandomSeed  Dd 0
      |
      |         
      |         Xor     Ax,Ax
      |         Int     1Ah     ; Timer interrupt...
      |         Mov     [RandomSeed],Edx
      |
      |         Mov     Es,[Plasma_Seg]
      |         Xor     Di,Di
      |         Stc
      |         Sbb     Eax,Eax
      |         Mov     Cx,4000h
      |         Rep     StosD
      |         Mov     Al,60
      |         StosB           ; we put 03Ch at offset 0
      |         Xor     Bx,Bx   ; Offset 0
      |         Mov     Cx,256  ; Edge size 100h
      |         Call    CalcFractal
      |         



	Here is the recursive fractal procedure :

CalcFractal     PROC NEAR       ; BX=Position (BH=y,BL=x), CX=Edge Size
		Noise2  MACRO
			  Local @@Notnegativ,@@Nottoohigh
			  Push    Ax
			  Pusha
			  Mov     Eax,Dword Ptr [Randomseed]  ; A little random
			  Mov     Ebx,16807
			  Imul    Ebx
			  And     Eax,07FFFFFFFh
			  Mov     Dword Ptr [Randomseed],Eax
			  Popa
			  Mov     Edx,[RandomSeed]
			  Mov     Ax,Cx    ; Proportionnal to the size in CX
			  Shl     Ax,2
			  Imul    Dx
			  Pop     Ax
			  Add     Dx,Ax    ; We add calculated color in DX
			  Or      Dx,Dx
			  Jge     @@Notnegativ  ; DX < 0 ?
			  Xor     Dx,Dx
		  @@Notnegativ:
			  Cmp     Dx,255
			  Jb      @@Nottoohigh  ; DX < 255 ?
			  Mov     Dl,0FEh
		  @@Nottoohigh:
			  Mov     Al,dl
			  Mov     Es:[Di],Al
			  ENDM

		Noise   MACRO
			  Local @@Nonoise
			  Cmp     Byte Ptr Es:[Di],0FFh
			  Jne     @@Nonoise
			  Noise2
		  @@Nonoise:
			  ENDM

	Shr     Cx,1
	jz      @@Endcalc       ; Size <=2 ?

;::::::w(u+l/2,v)=[w(u,v)+w(u+l,v)]/2+noise
;::::::Up Edge
	Xor     Ax,Ax
	Xor     Dx,Dx
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Add     Bl,Cl
	Add     Bl,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,1
	Sub     Bl,Cl
	Mov     Di,Bx
	Noise
	             ; same for others edges..

;::::::w(u+l/2,v+l/2)=[w(u+l,v+l)+w(u+l,v)+w(u,v)+w(u,v+l)]/4
;::::::Square center
	Xor     Ax,Ax
	Xor     Dx,Dx
	Add     Bl,Cl
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Sub     Bh,Cl
	Sub     Bh,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Sub     Bl,Cl
	Sub     Bl,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Add     Bh,Cl
	Add     Bh,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,2
	Add     Bl,Cl
	Sub     Bh,Cl
	Mov     Di,Bx
	Noise2          ; a little bit different than edges

	Sub     Bl,Cl   ; recursifs calls..
	Sub     Bh,Cl
	Push    Bx Cx
	Call    Calcfractal     ; 1st quadrant: up & left
	Pop     Cx bx
	Push    Bx Cx
	Add     Bl,Cl
	Call    Calcfractal     ; 2nd quadrant: up & right
	Pop     Cx Bx
	Push    Bx Cx
	Add     Bh,Cl
	Call    Calcfractal     ; 3rd quadrant: down & left
	Pop     Cx bx
	Add     Bl,Cl
	Add     Bh,Cl
	Call    Calcfractal     ; 4th quadrant: down & right
@@Endcalc:
	Ret
CalcFractal     ENDP



	Yeah, that's all now guys !! Have phun ! And don't forget to kall
Equalizer : +33-(0)1-452-519-23 / +33-(0)1-452-511-31


...BaByLooN...ZeN.&.ReVeLaTioN...

-------------------------------------------------------- SOURCE CODE !!! -----

Title Fractal Map

			Dosseg
			.MODEL Large
			.Stack 1000h
			.386

;
;
		.Data
;
;

msg     db 'Kall now : EQUALIZER BBS'
	db '           Syzop: THoRiN / ReVeLaTioN'
	db '           +33-(0)1-452-519-23'
	db '           +33-(0)1-452-511-31'


;
;
		.Code
;
;

	Warpseg         Dw 0
	Psp             Dw 0
	Progsize        Dw 0
	Randomseed      Dd 0


;
Start           Proc Near
;
	Mov     Ax,@Data
	Mov     Ds,Ax

	Mov     [Psp],Es        ; Init Allocation
	Mov     Bx,Ss
	Mov     Cx,Sp
	Shr     Cx,4
	Add     Bx,Cx
	Sub     Bx,[Psp]
	Inc     Bx
	Mov     [Progsize],Bx
Shrinkprog:
	Mov     Ax,4A00h
	Mov     Bx,[Progsize]
	Int     21h

	Mov     Bx,4096
	Mov     Ax,4800h
	Int     21h
	Mov     Warpseg,Ax      ; Allocate memory

	Mov     Ax,0013h
	Int     10h

	Xor     Ax, Ax
	Int     1Ah
	Mov     [Randomseed], Edx

	Xor     Cx,Cx
@Paloop:Mov     Dx,03C8h
	Mov     Ax,Cx
	Out     Dx,Al
	Inc     Dx
	Mov     Ax,Cx
	Shr     Ax,2
	Out     Dx,Al
	Out     Dx,Al
	Out     Dx,Al
	Inc     Cx
	Cmp     Cx,256
	Jne     Short @Paloop

	Call    Calcmap
	Call    Affiche
	Xor     Ah,Ah
	Int     16h

	Mov     Bx,Warpseg
	Mov     Es,Bx
	Xor     Di,Di
	Mov     Ax,4900h
	Int     21h             ; DeAllocate memory

	Mov     Ax,03h
	Int     10h
	Mov     Ah,4Ch
	Int     21h
Start           Endp


;
Affiche         Proc Near
;
	Push    Ds
	Mov     Ds, [Warpseg]
	Mov     Ax,0A000h
	Mov     Es, Ax
	Xor     Si,Si
	Mov     Di, (320-256)/2
	Mov     Bl, 200
@Copytovram:
	Mov     Cx, 256/4
	Rep     Movsd
	Add     Di, (320-256)
	Dec     Bl
	Jnz     Short @Copytovram
	Pop     Ds
	Ret
Affiche         Endp


;
Calcmap         Proc Near
;
	Mov     Es,[Warpseg]
	Xor     Di,Di
	Mov     Cx,4000h
	Stc
	Sbb     Eax,Eax
	Rep     Stosd
	Mov     Al,60
	Stosb
	Xor     Bx,Bx
	Mov     Cx,256
	Call    Calcfractal
	Call    Blurring
	Ret
Calcmap         Endp


;
Calcfractal     Proc Near       ; BX=Position (BH=y,BL=x), CX=Edge Size
;
	Noise2  Macro
		Local @@Notnegativ,@@Nottoohigh
		Push    Ax
		Pusha
		Mov     Eax,Dword Ptr [Randomseed]      ; a little random
		Mov     Ebx,16807
		Imul    Ebx
		And     Eax,07FFFFFFFh
		Mov     Dword Ptr [Randomseed],Eax
		Popa
		Mov     Edx,[Randomseed]
		Mov     Ax,Cx
		Shl     Ax,2
		Imul    Dx
		Pop     Ax
		Add     Dx,Ax
		Or      Dx,Dx
		Jge     @@Notnegativ
		Xor     Dx,Dx
		@@Notnegativ:
		Cmp     Dx,255
		Jb      @@Nottoohigh
		Mov     Dl,0FEh
		@@Nottoohigh:
		Mov     Al,Dl
		Mov     Es:[Di],Al
		Endm
	Noise   Macro
		Local @@Nonoise
		Cmp     Byte Ptr Es:[Di],0FFh
		Jne     @@Nonoise
		Noise2
		@@Nonoise:
		Endm
	Shr     Cx,1
	Jz      @@Endcalc
;:::::::::::::::::::::w(u+l/2,v)=[w(u,v)+w(u+l,v)]/2+noise...
	Xor     Ax,Ax
	Xor     Dx,Dx
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Add     Bl,Cl
	Add     Bl,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,1

	Sub     Bl,Cl
	Mov     Di,Bx
	Noise
;:::::::::::::::::::::w(u,v+l/2)=[w(u,v)+w(u,v+l)]/2
	Xor     Ax,Ax
	Xor     Dx,Dx
	Sub     Bl,Cl
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Add     Bh,Cl
	Add     Bh,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,1
	Sub     Bh,Cl
	Mov     Di,Bx
	Noise
;:::::::::::::::::::::w(u+l,v+l/2)=[w(u+l,v)+w(u+l,v+l)]/2
	Xor     Ax,Ax
	Xor     Dx,Dx
	Sub     Bh,Cl
	Add     Bl,Cl
	Add     Bl,Cl
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Add     Bh,Cl
	Add     Bh,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,1
	Sub     Bh,Cl
	Mov     Di,Bx
	Noise
;:::::::::::::::::::::w(u+l/2,v+l)=[w(u,v+l)+w(u+l,v+l)]/2
	Xor     Ax,Ax
	Xor     Dx,Dx
	Add     Bh,Cl
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Sub     Bl,Cl
	Sub     Bl,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,1
	Add     Bl,Cl
	Mov     Di,Bx
	Noise
;:::::::::::::::::::::w(u+l/2,v+l/2)=[w(u+l,v+l)+w(u+l,v)+w(u,v)+w(u,v+l)}/4
	Xor     Ax,Ax
	Xor     Dx,Dx
	Add     Bl,Cl
	Mov     Di,Bx
	Mov     Al,Es:[Di]
	Sub     Bh,Cl
	Sub     Bh,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Sub     Bl,Cl
	Sub     Bl,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Add     Bh,Cl
	Add     Bh,Cl
	Mov     Di,Bx
	Mov     Dl,Es:[Di]
	Add     Ax,Dx
	Shr     Ax,2
	Add     Bl,Cl
	Sub     Bh,Cl
	Mov     Di,Bx
	Noise2

	Sub     Bl,Cl
	Sub     Bh,Cl
	Push    Bx Cx
	Call    Calcfractal
	Pop     Cx Bx
	Push    Bx Cx
	Add     Bl,Cl
	Call    Calcfractal
	Pop     Cx Bx
	Push    Bx Cx
	Add     Bh,Cl
	Call    Calcfractal
	Pop     Cx Bx
	Add     Bl,Cl
	Add     Bh,Cl
	Call    Calcfractal
@@Endcalc:
	Ret
Calcfractal             Endp


;
Blurring        Proc Near
;
	Xor     Di,Di
	Mov     Es,Warpseg
	Mov     Ecx,256*256
@@Blurrloop:
	Xor     Ax,Ax
	Xor     Dx,Dx
	Mov     Al,Es:[Di-255]
	Mov     Dl,Es:[Di-257]
	Add     Ax,Dx
	Mov     Dl,Es:[Di+255]
	Add     Ax,Dx
	Mov     Dl,Es:[Di+257]
	Add     Ax,Dx
	Mov     Dl,Es:[Di+256]
	Add     Ax,Dx
	Mov     Dl,Es:[Di-256]
	Add     Ax,Dx
	Mov     Dl,Es:[Di-1]
	Add     Ax,Dx
	Mov     Dl,Es:[Di+1]
	Add     Ax,Dx
	Shr     Ax,3
	Mov     Es:[Di],Al
	Inc     Di
	Dec     Ecx
	Jnz     @@Blurrloop
	Ret
Blurring        Endp


;
;
		End Start
;
;

