* SManCP
* By David M. McKinstry.
* This version completed 6/13/89
* This is copyrighted by the author and not to be used in any commerical
* application (excepting Amiga demonstrations) with out his permission.
* However, it may be freely used any duplicated for any non-commercial
* applications.

	INCLUDE	"exec/types.i"	;Needed for SOFFSET macro
	INCLUDE	"graphics/rastport.i"
	INCLUDE	"intuition/intuition.i"


	mc68881

	XDEF	_FuncFind
	XDEF	_ConExt
	
	XREF	_LVOSetAPen
	XREF	_LVOWritePixel


	XREF	_GfxBase
	XREF	_LVOSetAPen
	XREF	_LVOWritePixel


	XREF	_Factor
	XREF	_XCenter
	XREF	_YCenter

	XREF	_xtemp
	XREF	_ytemp
	XREF	_LacMod

	XREF	_IntWindow
	XREF	_CWRast
	XREF	_SWidth
	XREF	_SHeight
	XREF	_S1Width
	XREF	_S1Height
	XREF	_CurCnt
	XREF	_MaxCnt
	

PlotIt:
	move.l	_CurCnt,d0		;Get Mandelbrot count
	cmp.l	#$FFFF,d0	;See if indicated as M.B. It won't be this big
	bne.s	MandOut
	move.l	#15,d0
	bra.s	SetC
MandOut:
	ext.l	d0
	lsr.l	#2,d0
	add.l	#1,d0
SetC:
	move.l	_CWRast,a1
	move.b	d0,rp_FgPen(a1)
	move.l	_ytemp,d1
	cmp.l	#49,d1
	bge.s	OKay		;Use my SetPix if below Menus,
	movem.l	d0-d7/a0-a6,-(a7)	;Otherwise use WritePixel.
	move.l	a1,-(a7)		;Save raster port
	move.l	_GfxBase,a6
	jsr	_LVOSetAPen(a6)
	move.l	_IntWindow,a0
	move.w	wd_MouseY(a0),d0
	cmp.w	#49,d0
	blt.s	IntSet			;Mouse in menu region
	cmp.l	#10,_ytemp		;See if y less than 12
	ble.s	IntSet
	bra.s	MySet
IntSet:	move.l	_xtemp,d0
	move.l	_ytemp,d1
	move.l	(a7)+,a1
	jsr	_LVOWritePixel(a6)
	movem.l	(a7)+,d0-d7/a0-a6
	rts
MySet:	move.l	(a7)+,a1	;Recover Raster port
	movem.l	(a7)+,d0-d7/a0-a6
OKay:	move.l	_xtemp,d0
	bsr	SetOne
	rts

SetOne:
	cmp.w	_SWidth,d0
	bge.s	SetNot
	cmp.w	_SHeight,d1
	bgt.s	SetNot
	tst.l	d1		;See if -
	bmi.s	SetNot
	bsr	SetPix
SetNot:
	rts

*SetPix has inputs of d0.w for x, d1.w for y, and a3 for the video pointer
* Registers affected include d1, d2, and a0. It returns with the address
* of the pixel in a0 and the bit to be set or cleared in d1
SetPix:
	movem.l	d0-d3/a0-a2,-(a7)
	move.b	rp_FgPen(a1),d3		;Get mask for rastport
	move.l	rp_BitMap(a1),a1	;Get pointer to bitmap
	move.l	a1,a2		;Save bit map pointer in a2
	addq.l	#bm_Planes,a1	;Get pointer to planes
	move.w	d1,d2		;See if y is - and get into d2
	bmi.s	SetNo		;Don't set if negative
	cmp.w	(_S1Height+2),d1
	bgt.s	SetNo
	move.w	d1,d2		;y is in d2
	move.w	d0,d1		;See if x is negative
	bmi.s	SetNo		;Don't set if is
	cmp.w	(_S1Width+2),d0
	bgt.s	SetNo		;bcc.s	SetNo		;If no carry then too big
	move.l	d2,d1		;Save y  in d1
	mulu	_SWidth,d1	;Get Screen width times y
	add.l	d0,d1		;Add in x coordinate
	lsr.l	#3,d1		;d1 is x/8
	move.l	d1,d2
	move.w	d0,d1		;d1 is x
	eori.w	#7,d1		;Toggle lowest 3 bits.
	andi.w	#7,d1		;Get 7 - x(mod 8)
	ext.l	d3
	move.l	d3,d0		;Move pen color into d0
	move.b	bm_Depth(a2),d3	;Get depth in d3
SetPln:	move.l	(a1)+,a0	;Get pointer to bit plane
	adda.l	d2,a0		;Add in offset	
	btst	#0,d0		;See if 1st color
	beq.s	NoOne
	bset	d1,(a0)		;Set bit 7-x(mod8)
	bra.s	PlnOne
NoOne:	bclr	d1,(a0)
PlnOne:	asr.l	#1,d0		;Move next bit in color down.
	sub.b	#1,d3		;See if all planes done.
	bne.s	SetPln
SetNo:	movem.l	(a7)+,d0-d3/a0-a2
	rts


* Convert relevant double precision values from main to extended precision.
_ConExt:
	fmove.x	fp0,-(a7)
	fmove.d	_Factor,fp0
	fmove.x	fp0,Factor
	move.l	#2,d0
	fmove.l	d0,fp0
	fmove.x	fp0,Two
	fmove.x	Factor,fp0
	fmul.x	Two,fp0
	fmul.x	fp0,fp0
	fmove.x	fp0,Limit
	fmove.d	_XCenter,fp0
	fmove.x	fp0,XCenter
	fmove.d	_YCenter,fp0
	fmove.x	fp0,YCenter
	fmove.x	(a7)+,fp0
	rts
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lea	Limit,a0	
_FuncFind:
	bsr	FncFnd
	move.l	d7,_CurCnt
	bsr	PlotIt
	rts

FncFnd:
	fmove.x	Two,fp7
	fmove.x	Factor,fp6
	move.l	_xtemp,d0
	move.l	_ytemp,d1
	tst.w	_LacMod
	bne.s	IsLace
	lsl.l	#1,d1		;If non-interlace, double y.
IsLace:	fmove.l	d0,fp0
	fmove.l	d1,fp1
	fsub.x	XCenter,fp0
	fsub.x	YCenter,fp1
	bsr	Mand
	rts

Mand:	move.l	#0,d7		;Initialize counter
	fmove.l	d7,fp2		;Place 0 in Zr
	fmove.x	fp2,fp3		;Same for Zi
ZConv:	bsr.s	ZFind		;Get next value for Zr and Zi
	cmp.l	_MaxCnt,d7	;See if to be assumed within Mandelbrot set
	bgt.s	LimCnt
	bra.s	ZConv
LimCnt:	move.l	#$FFFF,d7	;Indicate it is part of Mandelbrot
NotMand:
	rts

ZFind:	fmove.x	fp2,fp4		;Get current Zr into temporary
	fmove.x	fp3,fp5		;Do same for Zi
	fmul.x	fp4,fp4		;Find Zr^2
	fmul.x	fp5,fp5		;Find Zi^2
	fmove.x	fp5,-(a7)	;Save Zi^2 on stack
	fadd.x	fp4,fp5		;Find z-squared
	fcmp.x	Limit,fp5	;See if > 2^2 (i.e. is |Z|>2?)
	fbgt	TooBig		;If so extablish count to failure
	fmove.x	(a7)+,fp5	;Recover Zi^2
	fsub.x	fp5,fp4		;Find Zr^2 - Zi^2
	fdiv.x	fp6,fp4		;Divide by factor to get part of new Zr
	fadd.x	fp0,fp4		;Find New Zr
	fmul.x	fp2,fp3		;Find original Zi*Zr
	fmul.x	fp7,fp3		;Find 2*Zi*Ze
	fdiv.x	fp6,fp3		;Divide by Factor
	fadd.x	fp1,fp3		;Add in original Zi to get new Zi
	fmove.x	fp4,fp2		;and get new Zr into fp2
	addq.l	#1,d7		;Increment counter
	rts
TooBig:	fmove.x	(a7)+,fp5	;Recover fp5 to balance stack
	fmove.x	fp2,fp5		;See if fp5 really needed
	addq.l	#4,a7		;Balance stack for return from ZFind
	bra.s	NotMand		;Back to Main


	dseg

Limit:	ds.l	3
Factor:	ds.l	3
Two:	ds.l	3
XCenter:
	ds.l	3
YCenter:
	ds.l	3

	END
