; wander.asm - optimized wandering routine for random fractal

	far	code
	far	data

	public	_wander_asm	; defined here
	public	_setbit
	public	_checkbit

	public	_WritePixel	; needed here
	public	_row
	public	_randoms
	public	_next_random
	public	_hires_rp

_wander_asm:
;	4(sp)	&x	; x and y hold initial values!
;	8(sp)	&y
;wander_asm( retx, rety)
;  int *retx, *rety

	movem.l	d2/d3/a2/a3/a4,-(sp)

	move.l	_next_random,a4	; a4 points to random numbers

	move.l	20+4(sp),a0	; d2 = x
	move.w	(a0),d2		

	move.l	20+8(sp),a0
	move.w	(a0),d0
	ext.l	d0		; get initial row address (from y)
	asl.l	#2,d0
	lea	_row,a2
	adda.l	d0,a2		; a2 = address of row pointer
	move.l	(a2),a3		; a3 = ptr to row

loop	move.w	d2,d0		; is this space occupied?
	asr.w	#3,d0		; calculate byte and bit address
	btst.b	d2,(a3,d0.w)
	bne	loopend		; no

;	bsr	write_pixel	; to show how it is working

; get random number here

	move.b	(a4)+,d0	; d0 = next random number
	bne.s	1$
	move.l	_randoms,a4	; wrap around if needed
1$
	eor.b	d0,d3		; exclusive or it
	move.b	d3,d0		; put in 0..14 range (8 posibilities)
	and.w	#$E,d0
	

; depending on number, go different directions

	move.w	vectors(pc,d0.w),d0
before_jmp
	jmp	(pc,d0.w)

quad0:	addq.w	#1,d2		; x++
	bra.s	loop

quad1:	addq.w	#1,d2		; x++
	move.l	-(a2),a3	; y--
	bra.s	loop

quad2:	move.l	-(a2),a3	; y--
	bra.s	loop

quad3:	subq.w	#1,d2		; x--
	move.l	-(a2),a3	; y--
	bra.s	loop

quad4:	subq.w	#1,d2		; x--
	bra.s	loop

quad5:	subq.w	#1,d2		; x--
	addq.w	#4,a2		; y++
	move.l	(a2),a3
	bra.s	loop

quad6:	addq.w	#4,a2		; y++
	move.l	(a2),a3
	bra.s	loop

quad7:	addq.w	#1,d2		; x++
	addq.w	#4,a2		; y++
	move.l	(a2),a3
	bra.s	loop
	
vectors:
	dc.w	quad0-before_jmp-2
	dc.w	quad1-before_jmp-2
	dc.w	quad2-before_jmp-2
	dc.w	quad3-before_jmp-2
	dc.w	quad4-before_jmp-2
	dc.w	quad5-before_jmp-2
	dc.w	quad6-before_jmp-2
	dc.w	quad7-before_jmp-2

loopend:

	move.l	20+4(sp),a0	; return x
	move.w	d2,(a0)
	move.l	20+8(sp),a0	; return y
	move.l	a2,d0	
	lea	_row,a1
	sub.l	a1,d0
	asr.w	#2,d0	
	move.w	d0,(a0)

	move.l	a4,_next_random	; keep track of random number pointer

	movem.l	(sp)+,d2/d3/a2/a3/a4
	rts

write_pixel:
;	a2 = raw index into row
;	d2 = x

	move.l	a2,d0		; get raw row pointer address
	lea	_row,a1
	sub.l	a1,d0	; subtract off base to get raw index
	asr.l	#2,d0		; 
	move.l	d0,-(sp)

	ext.l	d2
	move.l	d2,-(sp)
	
	move.l	_hires_rp,-(sp)
	jsr	_WritePixel
	lea	12(sp),sp
	rts	


;=========================================================================

_setbit		; setbit( row, x, y )
;	row is the address of an array of pointers to rows
;	x and y are 16 bit
;	This sets the given bit
;	
;	10(sp).w	y
;	8(sp).w		x
;	4(sp).l		address of array of pointers to rows


	move.l	4(sp),a0	; a0 = address of base of array
	move.w	10(sp),d0	; d0 = y
	asl.w	#2,d0
	move.l	(a0,d0.w),a0	; a0 = address of row
	move.w	8(sp),d0	; compute bit address
	move.w	d0,d1		; bit # in d0 (low 3 bits)
	asr.w	#3,d1		; compute byte offset
	bset	d0,(a0,d1.w)	; set it!
	rts

_checkbit		; checkbit( row, x, y )
;	row is the address of an array of pointers to rows
;	x and y are 16 bit
;	This checks the given bit, and returns a 16 bit boolean value
;	
;	10(sp).w	y
;	8(sp).w		x
;	4(sp).l		address of array of pointers to rows


	move.l	4(sp),a0	; a0 = address of base of array
	move.w	10(sp),d0	; d0 = y
	asl.w	#2,d0
	move.l	(a0,d0.w),a0	; a0 = address of row
	move.w	8(sp),d0	; compute bit address
	move.w	d0,d1		; bit # in d0 (low 3 bits)
	asr.w	#3,d1		; compute byte offset
	btst	d0,(a0,d1.w)	; check it!
	sne	d0
	ext.w	d0		; d0.w = bit set
	rts


	end
