************************************************
* Mandelbrot computing routines for Color Computer 3 
* copyright Chris Lomont 2006 www.lomont.org
*
************************************************


************************************************
* MandelbrotZoom - compute zoom internal constants
*    for zooming in on current region 
* REGX x1 coord 0-319 upper left
* REGU x2 coord 0-319 lower right
* REGA y1 coord 0-199 upper left
* REGB y2 coord 0-199 lower right
* REGY iteration count max
* Registers changed: None
************************************************
MandelbrotZoom	
	pshs	u,y,x,b,a 	u:6,s  y:4,s  x:2,s  b:1,s  a:,s
	cmpb	,s		
	bls	>		out of bounds
	cmpu	2,s
	bls	>		out of bounds	
	ldx	#MandelItMx	
	sty	,x		store iteration count

	* compute new x shift
	clra			scale x point
	ldx	2,s		x1 value
	lbsr	MandelbrotScale
	ldx	#MandelTemp
	ldy	#MandelXSh
	lbsr	FPCopy		store new x shift
	
	* compute new y shift
	ldb	,s
	tfr	d,x		y1 value
	inca			scale y point
	lbsr	MandelbrotScale
	ldx	#MandelTemp
	ldy	#MandelYSh
	lbsr	FPCopy		store new y shift
	
	* compute new x scale
	ldx	#MandelDiv319
	ldy	#MandelXSc
	tfr	y,u
	lbsr	FPMul		do in this order to prevent overflow
	ldd	6,s		get x2
	subd	2,s		subtract x1
	ldx	#MandelTemp
	lbsr	FPClear
	std	,x		(x2-x1)/256 as fixed point
	lbsr	FPMul

	* compute new y scale
	ldx	#MandelDiv199
	ldy	#MandelYSc
	tfr	y,u
	lbsr	FPMul		do in this order to prevent overflow
	clra
	ldb	1,s		get y2
	subb	,s		subtract y1
	ldx	#MandelTemp
	lbsr	FPClear
	std	,x		(y2-y1)/256 as fixed point
	lbsr	FPMul
		
!	puls	u,y,x,b,a
	rts

MandelDiv319	fcb	0,205, 113,  39		fixed point value for 256/319
MandelDiv199	fcb	1, 73,  83, 158		fixed point value for 256/199

************************************************
* MandelbrotReset - resets the viewing region
* to the outermost view (standard view)
* Registers changed: None
************************************************
MandelbrotReset
	* mostly just copy over a lot of scaling constants
	pshs	x,y
	ldx	#MandelXScDef
	ldy	#MandelXSc
	lbsr	FPCopy	

	ldx	#MandelYScDef
	ldy	#MandelYSc
	lbsr	FPCopy	

	ldx	#MandelXShDef
	ldy	#MandelXSh
	lbsr	FPCopy	

	ldx	#MandelYShDef
	ldy	#MandelYSh
	lbsr	FPCopy
	puls	x,y	
	rts

* constants that define the outermost view 
MandelXScDef	fcb	2,104,83,118	(3/319)*256 in FP x scale
MandelYScDef	fcb	2,146,167,60	(2/199)*256 in FP y scale
MandelXShDef	fcb	$FE,0,0,0	-2 in FP x shift
MandelYShDef	fcb	$FF,0,0,0	-1 in FP y shift



************************************************
* MandelbrotScale - convert a pixel coord to a
* complex plane coord - todo - REGU is dest makes better routine?
* REGX - value to scale as an integer
* REGA - 0 means scale X, 1 means scale Y
* final value stored in MandelTemp 
* Registers changed: None
************************************************
MandelbrotScale
	pshs	x,y,u,d
	tfr	x,y
	ldx	#MandelTemp	
	lbsr	FPClear		clear it
	sty	MandelTemp	set pixel pos/256
	tfr	x,y		y point to temp
	tsta
	beq	scalex@
	cmpa	#1
	bne	exit@
scaley@	ldx	#MandelYSc	yscale 
	ldu	#MandelTemp
	lbsr	FPMul
	tfr	u,x
	ldy	#MandelYSh	yshift
	lbsr	FPAdd
	bra	exit@
scalex@	ldx	#MandelXSc	xscale 
	ldu	#MandelTemp
	lbsr	FPMul
	tfr	u,x
	ldy	#MandelXSh	xshift
	lbsr	FPAdd
exit@	puls	x,y,u,d
	rts		


************************************************
* MandelbrotComputePoint - Mandelbrot point computation
* REGX x coord 0-319
* REGY y coord 0-199
* returns REGD is number of color value 0 on up
* uses internal values to detemine view
* Registers changed: REGD
************************************************
* mandelbrot drawn using current scaling, defaults to [-2,1]x[-1,1]
MandelbrotComputePoint
	pshs	u,y,x		u:4,s  y:2,s  x:,s

*  x = x0 = x co-ordinate of pixel
*  y = y0 = y co-ordinate of pixel
	clra			prepare to position x
	bsr	MandelbrotScale	position x
	ldx	#MandelTemp	copy over
	ldy	#MandelX	
	lbsr	FPCopy
	ldy	#MandelX0
	lbsr	FPCopy

	inca			prepare to position y
	ldx	2,s		get y value
	bsr	MandelbrotScale	position y
	ldx	#MandelTemp	copy over
	ldy	#MandelY	
	lbsr	FPCopy
	ldy	#MandelY0
	lbsr	FPCopy
	
*  x2 = x*x
*  y2 = y*y
	ldx	#MandelX	initialize the squares - todo - compact with below
	tfr	x,y
	ldu	#MandelX2
	lbsr	FPMul
		
	ldx	#MandelY
	tfr	x,y
	ldu	#MandelY2
	lbsr	FPMul

*  iteration = 1
*  maxiteration = uses internal constant

	ldd	#1
	std	MandelIt
*	std	,x 		todo - error?
 
*  while ( x2 + y2 < (2*2)  AND  iteration < maxiteration ) {
mloop	ldx	#MandelX2
	ldy	#MandelY2
	ldu	#MandelTemp
	lbsr	FPAdd		todo - can compare with top byte in MandelTemp >= 4 now :)
	tfr	u,x
	ldy	#FPNegFour	todo - can check this with highest FP byte
	lbsr	FPAdd
	lda	,u		get highest bit, see if positive
	bita	#$80
	beq	mdone		jump out
	ldd	MandelIt
	cmpd	MandelItMx
	bge	mdone		if too many iterations, bail out

*    iteration = iteration + 1
*	incd			todo - remove - this is 6309 only!
*	addb	#1		todo - faster for addd?
*	adca	#0
	addd	#1		
	std	MandelIt
		 
*    y = 2*x*y + y0
	ldx	#MandelX
	ldy	#MandelY
	ldu	#MandelTemp
	lbsr	FPMul
	tfr	u,x
	ldy	#FPTwo
	ldu	#MandelY
	lbsr	FPMul		todo- make a mul by two routine - faster
	tfr	u,x
	ldy	#MandelY0
	lbsr	FPAdd

*    x = x2 - y2 + x0
	ldx	#MandelY2
	lbsr	FPNeg
	ldy	#MandelX2
	ldu	#MandelX
	lbsr	FPAdd
	tfr	u,x
	ldy	#MandelX0
	lbsr	FPAdd	

*    x2 = x*x     
*    y2 = y*y

	ldx	#MandelX
	tfr	x,y
	ldu	#MandelX2
	lbsr	FPMul
		
	ldx	#MandelY
	tfr	x,y
	ldu	#MandelY2
	lbsr	FPMul


   	lbra	mloop
 
 
*  if ( iteration == maxiteration )
*    color = black
*  else
*    color = iteration
mdone	ldd	MandelIt
	cmpd	MandelItMx
	bne	@clrok
	ldd	#0
@clrok	puls	x,y,u
	rts


MandelX		fcb	0,0,0,0		current iterate
MandelY		fcb	0,0,0,0
MandelX2	fcb	0,0,0,0		square of iterate
MandelY2	fcb	0,0,0,0
MandelX0	fcb	0,0,0,0		point to add each pass			
MandelY0	fcb	0,0,0,0
MandelTemp	fcb	0,0,0,0		temp space
MandelIt	fcb	0,0		iteration count
MandelItMx	fcb	0,50		max iter iteration count 50 default

* some constants for computations
MandelXSc	fcb	2,104,83,118	(3/319)*256 in FP x scale
MandelYSc	fcb	2,146,167,60	(2/199)*256 in FP y scale
MandelXSh	fcb	$FE,0,0,0	-2 in FP x shift
MandelYSh	fcb	$FF,0,0,0	-1 in FP y shift


* end - Mandelbrot.asm