
; Rotazione di vectorballs...

****************************************************************************
;			CALCULATE NEW POSITIONS
****************************************************************************
;	Entry :	a0 = Table of original co-ord
;		a1 = Space for new table
;		a2 = Address of angles (Z,Y,X)
;		d7 = No. of points-1

CalcPoints:
	lea	SineTable,a3	; a2=address of sine table

; Calculate current X,Y and Z positions

CalcXYZ:
	move.w	(a0),d2		; d2=xpos
	move.w	2(a0),d3	; d3=ypos
	bsr	CalcNewPos
	move.w	d5,2(a1)	; d5=new ypos
	move.w	d4,d2		; d2=xpos
	move.w	4(a0),d3	; d3=zpos
	bsr	CalcNewPos
	move.w	d4,(a1)		; d4=new xpos
	move.w	d5,d2		; d2=zpos
	move.w	2(a1),d3	; d3=ypos
	bsr	CalcNewPos
	move.w	d4,4(a1)	; d4=new zpos
	move.w	d5,2(a1)	; d5=new ypos
	move.w	6(a0),6(a1)	; Copy colour from orig points to new ones
	addq.l	#8,a0		; a0=address of next original point
	addq.l	#8,a1		; a1=address of next rotated point
	subq.l	#6,a2		; Point a2 back to start of angles
	dbra	d7,CalcXYZ
	rts
CalcNewPos:
	move.w	(a2)+,d0	; Get angle from list
	ext.l	d0		; make it a long word
	lsl.l	d0		; Multiply by 2 (sine table in words)
	move.w	(a3,d0),d1	; d1=sine value for angle

; Cos(X) = Sin (90+X)
; All things added/subtracted are *2 since sine table is in words

	add.l	#180,d0		; Add 90 to angle
	cmp.l	#720,d0		; If angle>359, bring it within 0-359 range
	blt	.ok
	sub.l	#720,d0		; By subtracting 360 from it
.ok	move.w	(a3,d0),d0	; d0=cos value for angle

	move.l	d2,d4		; d4=d2
	move.l	d3,d5		; d5=d3
	muls	d0,d4		; d4=d4 * cos(X)
	muls	d1,d3		; d3=d3 * sin(X)
	sub.l	d3,d4		; Subtract d3 from d4 to get first value
	muls	d0,d5		; d5=d5 * cos(X)
	muls	d1,d2		; d2=d2 * sin(X)
	add.l	d2,d5		; Add d2 to d5 to get second value
	asr.l	#7,d4		; Divide each value by 16384 since each sine
	asr.l	#7,d4		; number was multiplied by this in the first
	asr.l	#7,d5		; place
	asr.l	#7,d5
	rts

****************************************************************************
; 				ROTATION HANDLERS
****************************************************************************

; Bogus handler (just returns a non-zero, ie. lets it rotate)

NoHandler:
	moveq.l	#1,d0		; Rotate
	rts

; Complicated (and the effect isn't that good for it either)

; Variables used:
; 	FLAG	- 0=Normal mode, 1=Firing
;	FALLADD	- If falling, =amount to add to get gravity effect
;	BULLETY	- If falling, =amount bullet has fallen

; Remember that this routine is called when the points have been worked
; out and stored in the table NewPoints, but haven't been sorted or
; displayed

GunHandler:
	tst.w	Flag		; Are we firing a bullet?
	bne	FireGun		; If so, do bullet handler
	clr.l	d0		; d0=counter
	move.w	Counter,d0
	divu	#100,d0		; Start bullet every 100 counts
	swap	d0		; So is remainder 0?
	tst.w	d0
	bne	DoneGun		; Nope?
	move.w	#1,Flag		; If so, time to start firing
FireGun	lea	NewPoints+(Bullet-GunBalls),a1	; a1=address of bullet
				; in Newpoints table
	subq.w	#8,Bullet	; move bullet left 4 (out of barrel)
	tst.w	BulletY		; Are we falling?
	beq	.ok		; Nope
	addq.w	#1,FallAdd	; Fall 1 extra this time
	move.w	FallAdd,d0	; Add FallAdd to BulletY
	lsr.w	d0
	add.w	d0,BulletY
	move.w	BulletY,d0	; d0=BulletY

; This finds out which angle is closest to 90°.  We want to know this because
; the ball should appear to fall slower if it has been fired away from the
; screen.  To decide how far it does fall, the angle furthest from 90° is
; taken as its inclination (only an approximation - no mathematical basis
; for it)

	move.w	#90,d1		; d1=90-XAngle
	move.w	d1,d2		; d2=90-YAngle
	sub.w	XAngle,d1
	sub.w	YAngle,d2
	cmp.w	d1,d2		; If YAngle is closer, use XAngle as angle
	bgt	.UseX
	clr.l	d1		; else use YAngle
	move.w	YAngle,d2
	bra	.ok1
.UseX	clr.l	d1
	move.w	XAngle,d2
.ok1	lsl.l	d1		; Get angle*2 (Sinetable in words)
	lea	SineTable,a0	; d1=sine value
	move.w	(a0,d1),d1

; We want to multiply the Fall (d0) by a number between 0-1, 0 if -90° and
; 1 if +90°.  This is [Sin(X)+1]/2.  However, since sine values in table
; are *16384, it is treated as [Sin(X)+16384]/(16384*2).

	add.l	#16384,d1	; d1=Sin(X)+16384
	mulu	d1,d0		; Multiply Fall Value by d1
	asr.l	#8,d0		; d1=New fall value/16384/2 (>>15)
	asr.l	#7,d0
	add.w	d0,2(a1)	; Add it to current Y value for bullet
	cmp.w	#58,2(a1)	; Off bottom of screen?
	bgt	StopFire	; Yes, put bullet back in barrel, etc.
	bra	GunStop		; No, don't rotate yet
.ok	moveq.l	#2,d0		; Get X²+Y²+Z² and see if its more than 110²
	clr.l	d1		; d1=Total value
.loop	move.w	(a1),d2		; d2=X,Y or Z value
	muls	(a1)+,d2	; Square it
	add.l	d2,d1		; Add it to total value
	dbra	d0,.loop	; Do Y and Z
	cmp.w	#12100,d1	; Is result>110²?
	bge	StartFall	; Yes, start the ball falling.
GunStop:
	addq.w	#1,Counter	; Freeze counter - is subracted by 1 every time
	clr.l	d0		; Don't rotate them next time
	rts
StartFall:
	move.w	#1,BulletY	; Fall by 1
	move.w	#1,FallAdd	; Set fall counter to 1
	bra	GunStop		; Don't rotate
StopFire:
	clr.w	Bullet		; Reset Bullet's X value (only one that's changed)
	clr.w	Flag		; Not firing now
	clr.w	FallAdd		; Not falling now
	clr.w	BulletY		; Not falling now
DoneGun:
	moveq.l	#1,d0		; Can rotate them next time
	rts
	

****************************************************************************
;			 SINE TABLE (Mark's)
****************************************************************************

SineTable:
	dc.w 0,286,572,857,1143,1428,1713,1997,2280
	dc.w 2563,2845,3126,3406,3686,3964,4240,4516
	dc.w 4790,5063,5334,5604,5872,6138,6402,6664
	dc.w 6924,7182,7438,7692,7943,8192,8438,8682		
	dc.w 8923,9162,9397,9630,9860,10087,10311,10531
	dc.w 10749,10963,11174,11381,11585,11786,11982,12176
	dc.w 12365,12551,12733,12911,13085,13255,13421,13583
	dc.w 13741,13894,14044,14189,14330,14466,14598,14726
	dc.w 14849,14968,15082,15191,15296,15396,15491,15582
	dc.w 15668,15749,15826,15897,15964,16026,16083,16135
	dc.w 16182,16225,16262,16294,16322,16344,16362,16374
	dc.w 16382,16384
	dc.w 16382
	dc.w 16374,16362,16344,16322,16294,16262,16225,16182
	dc.w 16135,16083,16026,15964,15897,15826,15749,15668		
	dc.w 15582,15491,15396,15296,15191,15082,14967,14849
	dc.w 14726,14598,14466,14330,14189,14044,13894,13741		
	dc.w 13583,13421,13255,13085,12911,12733,12551,12365
	dc.w 12176,11982,11786,11585,11381,11174,10963,10749
	dc.w 10531,10311,10087,9860,9630,9397,9162,8923
	dc.w 8682,8438,8192,7943,7692,7438,7182,6924
	dc.w 6664,6402,6138,5872,5604,5334,5063,4790
	dc.w 4516,4240,3964,3686,3406,3126,2845,2563
	dc.w 2280,1997,1713,1428,1143,857,572,286,0
	dc.w -286,-572,-857,-1143,-1428,-1713,-1997,-2280
	dc.w -2563,-2845,-3126,-3406,-3686,-3964,-4240,-4516
	dc.w -4790,-5063,-5334,-5604,-5872,-6138,-6402,-6664
	dc.w -6924,-7182,-7438,-7692,-7943,-8192,-8438,-8682		
	dc.w -8923,-9162,-9397,-9630,-9860,-10087,-10311,-10531
	dc.w -10749,-10963,-11174,-11381,-11585,-11786,-11982,-12176
	dc.w -12365,-12551,-12733,-12911,-13085,-13255,-13421,-13583
	dc.w -13741,-13894,-14044,-14189,-14330,-14466,-14598,-14726
	dc.w -14849,-14968,-15082,-15191,-15296,-15396,-15491,-15582
	dc.w -15668,-15749,-15826,-15897,-15964,-16026,-16083,-16135
	dc.w -16182,-16225,-16262,-16294,-16322,-16344,-16362,-16374
	dc.w -16382,-16384
	dc.w -16382
	dc.w -16374,-16362,-16344,-16322,-16294,-16262,-16225,-16182
	dc.w -16135,-16083,-16026,-15964,-15897,-15826,-15749,-15668		
	dc.w -15582,-15491,-15396,-15296,-15191,-15082,-14967,-14849
	dc.w -14726,-14598,-14466,-14330,-14189,-14044,-13894,-13741		
	dc.w -13583,-13421,-13255,-13085,-12911,-12733,-12551,-12365
	dc.w -12176,-11982,-11786,-11585,-11381,-11174,-10963,-10749
	dc.w -10531,-10311,-10087,-9860,-9630,-9397,-9162,-8923
	dc.w -8682,-8438,-8192,-7943,-7692,-7438,-7182,-6924
	dc.w -6664,-6402,-6138,-5872,-5604,-5334,-5063,-4790
	dc.w -4516,-4240,-3964,-3686,-3406,-3126,-2845,-2563
	dc.w -2280,-1997,-1713,-1428,-1143,-857,-572,-286,0

