//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// 				Bitmap Fractal Example for Kick Assembler 
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
	.const imCenter = 0
	.const reCenter = 0
	.const zoom = 2        // lower = more zoom

//----------------------------------------------------------------------------
// 				Display the fractal 
//----------------------------------------------------------------------------
	.pc = $0801 "Basic Upstart Program"
	:BasicUpstart($0810)

	.pc = $0810 "Display Program"
	lda #$18
	sta $d018
	lda #$d8
	sta $d016
	lda #$3b
	sta $d011
	
	lda #BLACK
	sta $d021
	sta $d020
	ldx #0
loop:
	.for (var i=0; i<4; i++) {
		lda #GRAY | LIGHT_GRAY<<4 
		sta $0400+$100*i,x
		lda #DARK_GRAY
		sta $d800+$100*i,x
	}
	inx
	bne loop
	jmp *




//----------------------------------------------------------------------------
// 				Calculate the fractal 
//----------------------------------------------------------------------------
	.pc = $2000 "Fractal Image"
	.const colors = List().add(%11,%01,%10,%00)
	.function mandelbrot(re,im) {
		.var zr = 0
		.var zi = 0 
		.var iter=0
		.for(;[zr*zr+zi*zi]<4 && iter<18;iter++) {
			.var newZr = zr*zr-zi*zi + re
			.var newZi = 2*zr*zi + im
			.eval zr = newZr
			.eval zi = newZi
		}
		.return colors.get(iter&3) 
	}
	
	.function map(x, width, targetCenter, targetWidth) {
		.return [targetCenter-targetWidth/2] + targetWidth *[x/[width-1]] 
	}


// Alternative 1: Do it in asm mode - takes lots of memory and lots of time 
/*
.for (var screenY=0; screenY<32; screenY++)
	.for (var screenX=0; screenX<40; screenX++)
		.for (var charY=0; charY<8; charY++) {
			.var byteValue = $00
			.for (var charX=0; charX<4; charX++){
				.var x = charX+screenX*4
				.var y = charY+screenY*8
				.var re = map(x,160,reCenter,zoom)
				.var im = map(y,200,imCenter,zoom)
				.eval byteValue = byteValue | [mandelbrot(re,im)<<[6-charX*2]]			
			}
			.byte byteValue
		}
*/


// Alternative 2: Do it in function mode (using define) - faster and uses less memory
	.define fractalData {
		.var fractalData = List()
		.for (var screenY=0; screenY<25; screenY++)
			.for (var screenX=0; screenX<40; screenX++)
				.for (var charY=0; charY<8; charY++) {
					.var byteValue = $00
					.for (var charX=0; charX<4; charX++){
						.var x = charX+screenX*4
						.var y = charY+screenY*8
						.var re = map(x,160,reCenter,zoom)
						.var im = map(y,200,imCenter,zoom)
						.eval byteValue = byteValue | [mandelbrot(re,im)<<[6-charX*2]]			
					}
					.eval fractalData.add(byteValue)
				}
	}
	.fill 8*25*40,fractalData.get(i)




/*
// Alternative 3: Another way of doing it in function mode
.function calculateFillByte(i) {
	.var charY = i&7
	.var screenX = mod(i>>3,40) 
	.var screenY = floor([i>>3]/40)
	.var y = charY+screenY*8
	.var im = map(y,200,imCenter,zoom)
	.var byteValue = 0
	.for (var charX=0 ; charX<4; charX++ ) {
		.var x = charX+screenX*4
		.var re = map(x,160,reCenter,zoom) 
		.eval byteValue = byteValue | [mandelbrot(re,im)<<[6-charX*2]]		
	}	
	.return byteValue	
}	
.fill 8*25*40,calculateFillByte(i)

*/



