;*======================================================================*
;*                TITLE:                  ROTATE.S                      *
;*                Function:               misc. rotation routines	*
;*                                                                      *
;*                Project #:              JAGUAR                        *
;*                Programmer:             Andrew J Burgess              *
;*                                                                      *
;*              COPYRIGHT 1992 Atari Computer Corporation               *
;*          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
;*          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
;*        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
;*                            ALL RIGHTS RESERVED.                      *
;*                                                                      *
;*======================================================================*
;*
;* NOTES:
;*
;*======================================================================*

BASE	EQU	$00D00000	;* 68000 register base address
BAR_ON	EQU	1

;*======================================================================*
;*	INCLUDE FILES
;*======================================================================*

	include "jaguar.inc"
	include "blit.inc"
	include "gpu.inc"
	include "joydefs.inc"
	include "defs.inc"

;*======================================================================*
;*	USEFUL DEFINES
;*======================================================================*
INPUT6		EQU	G_ENDRAM-$4	; pointer to parameter 6 for GPU
INPUT5		EQU	INPUT6-$4	; pointer to parameter 5 for GPU
INPUT4		EQU	INPUT5-$4	; pointer to parameter 4 for GPU
INPUT3		EQU	INPUT4-$4	; pointer to parameter 3 for GPU
INPUT2		EQU	INPUT3-$4	; pointer to parameter 2 for GPU
INPUT1		EQU	INPUT2-$4	; pointer to parameter 1 for GPU

DEG0		EQU	$0		;*   0 degrees
DEG90		EQU	$5A		;*  90 degrees
DEG180		EQU	$B4		;* 180 degrees
DEG270		EQU	$10E		;* 270 degrees
DEG360		EQU	$168		;* 360 degrees
DEGN360		EQU	-DEG360		;* -360 degrees

SEC		EQU	$60		;* 60Hz clock
ATESEC		EQU	(SEC>>$3)	;* 7
QTRSEC		EQU	(SEC>>$2)	;* 15
ATE3SEC		EQU	(QTRSEC+ATESEC)	;* 22
HALFSEC		EQU	(SEC>>$1)	;* 30
ATE5SEC		EQU	(HALFSEC+ATESEC);* 37
QTR3SEC		EQU	(HALFSEC+QTRSEC);* 45
ATE7SEC		EQU	(QTR3SEC+ATESEC);* 52

XMIN		EQU	-$180
XMAX		EQU	$180

YMIN		EQU	-$18B
YMAX		EQU	$18B

ZMIN		EQU	0
ZMAX		EQU	$400

;*======================================================================*
;*	EXTERNAL ROUTINES
;*======================================================================*

	.extern	gpuload
	.extern	gpurun

;*======================================================================*
;*	EXTERNAL VARAIBLES
;*======================================================================*

	.extern	param_ptr
	.extern	m3x3mult
	.extern	matbuffer	;* buffer area for matrix multiplies

	.extern	joy_level
	.extern	joy_edge
	.extern	fire_level
	.extern	fire_edge
	.extern	key_level
	.extern	key_edge

;*======================================================================*
;*	GLOBAL VARAIBLES
;*======================================================================*

	.globl	vMatrix		;* Viewer transform matrix
	.globl	iMatrix		;* Model transform matrix

;*======================================================================*
;*	MACROS
;*======================================================================*

.macro	LONGALIGN	addr
	addq.l	#$3,\addr	;* make sure the address will remain
				;* within the buffer
	andi.l	#$FFFFFFFC,\addr
.endm

;*======================================================================*
;* ClrMatrices() - clear and initialize the rotate matrices
;*
;*	preserved:
;*		d0
;*		a0-a4
;*======================================================================*

	.globl	ClrMatrices

ClrMatrices:
	movem.l	d0/a0-a4,-(sp)		; save registers

	;* clear the Instance roll, pitch, and yaw variables
	clr.l	alphaI
	clr.l	betaI
	clr.l	gammaI

	;* set the Instance position
	clr.l	xI
	clr.l	yI
	move.l	#$200,zI

	;* clear the Viewer roll, pitch, and yaw variables
	clr.l	alphaV
	clr.l	betaV
	clr.l	gammaV

	;* set the Viewer position
	clr.l	xV
	clr.l	yV
	clr.l	zV

	;* copy the entity matrix
	move.l	#LeftMatrix,a1
	move.l	#RiteMatrix,a2
	move.l	#iMatrix,a3
	move.l	#vMatrix,a4
	moveq	#11,d0

.clrlp:
	clr.l	(a1)+
	clr.l	(a2)+
	clr.l	(a3)+
	clr.l	(a4)+
	dbra	d0,.clrlp

	movem.l	(sp)+,a0-a4/d0		; restore resgisters
	rts

;*======================================================================*
;* updPosition() - update the X, Y, and Z values based on the control
;*		   inputs
;*
;*	input:
;*		d0 - keypad levels
;*		d1 - firebutton levels
;*		d2 - joypad levels
;*
;*	preserved:
;*		d0-d5
;*		a0-a4
;*======================================================================*

	.globl	updPosition

updPosition:
	movem.l	d0-d5/a0-a4,-(sp)		; save registers

;	TIMEBAR	RGB_AQUA

	;*==============================================================*
	;* update based on controller inputs.
	;*	Instance	- A button = 0
	;*	Viewer		- A button = 1
	;*
	;*	X pos		- left (JOY_LEFT) right (JOY_RIGHT)
	;*	Y pos		- up   (JOY_UP)   down  (JOY_DOWN)
	;*	Z pos		- in   (KEY_S)    out   (KEY_P)

	move.l	d2,d5		;* save joypad levels

	;* are we going to effect the viewer or instance
	btst	#FIRE_A,d1		;* are we effecting the viewer
	beq	.instance
	move.l	#1,viewer		;* effect viewer
	move.l	xV,d2
	move.l	yV,d3
	move.l	zV,d4
	bra	updX

.instance:
	clr.l	viewer			;* effect instance
	move.l	xI,d2
	move.l	yI,d3
	move.l	zI,d4

updX:					;* look for Xpos change
	btst	#JOY_RIGHT,d5
	beq	.ck_left
	addq.l	#1,d2			;* move 1 unit right
	bra	updY
.ck_left:
	btst	#JOY_LEFT,d5
	beq	updY
	subq.l	#1,d2			;* move 1 unit left

updY:					;* look for Ypos change
	btst	#JOY_DOWN,d5
	beq	.ck_up
	addq.l	#1,d3			;* move 1 unit down
	bra	updZ
.ck_up:
	btst	#JOY_UP,d5
	beq	updZ
	subq.l	#1,d3			;* move 1 unit up

updZ:					;* look for Zpos change
	btst	#KEY_S,d0
	beq	.ck_in
	addq.l	#1,d4			;* move 1 unit out
	bra	limits
.ck_in:
	btst	#KEY_P,d0
	beq	limits
	subq.l	#1,d4			;* move 1 unit in

limits:
	jsr	ckLimits		;* limit range
	tst.l	viewer
	beq	.instance
	move.l	d2,xV
	move.l	d3,yV
	move.l	d4,zV
	bra	doneUpd
.instance:
	move.l	d2,xI
	move.l	d3,yI
	move.l	d4,zI

doneUpd:

	;* determine the delta distance from Viewer to Instance
	jsr	setDelta

;	TIMEBAR	RGB_VIOLET

	movem.l	(sp)+,a0-a4/d0-d5		; restore resgisters
	rts

;*======================================================================*
;* updAngles() - update the roll, pitch, and yaw values based on the
;*		 control inputs
;*
;*	input:
;*		d0 - keypad levels
;*
;*	preserved:
;*		d0-d4
;*		a0-a4
;*======================================================================*

	.globl	updAngles

updAngles:
	movem.l	d0-d2/a0-a4,-(sp)		; save registers

;	TIMEBAR	RGB_LTGREEN

	;*==============================================================*
	;* update roll, pitch, and yaw based on controller inputs.
	;*	Instance	- A button = 0
	;*	Viewer		- A button = 1
	;*
	;*	roll		- up (KEY_1) down (KEY_3)
	;*	pitch		- up (KEY_4) down (KEY_6)
	;*	yaw		- up (KEY_7) down (KEY_9)
	;*
	;*	X pos		- left (JOY_LEFT) right (JOY_RIGHT)
	;*	Y pos		- up   (JOY_UP)   down  (JOY_DOWN)
	;*	Z pos		- in   (KEY_S)    out   (KEY_P)

	tst.l	viewer
	beq	.instance
	move.l	alphaV,d2
	move.l	betaV,d3
	move.l	gammaV,d4
	bra	rollup

.instance:
	move.l	alphaI,d2
	move.l	betaI,d3
	move.l	gammaI,d4

rollup:					;* look for roll
	btst	#KEY_1,d0
	beq	rolldn
	addq.l	#1,d2			;* roll +1 degree
	bra	pitchup
rolldn:
	btst	#KEY_3,d0
	beq	pitchup
	subq.l	#1,d2			;* roll -1 degree

pitchup:				;* look for pitch
	btst	#KEY_4,d0
	beq	pitchdn
	addq.l	#1,d3			;* pitch +1 degree
	bra	yawup
pitchdn:
	btst	#KEY_6,d0
	beq	yawup
	subq.l	#1,d3			;* pitch -1 degree

yawup:					;* look for yaw
	btst	#KEY_7,d0
	beq	yawdn
	addq.l	#1,d4			;* yaw +1 degree
	bra	wrap
yawdn:
	btst	#KEY_9,d0
	beq	wrap
	subq.l	#1,d4			;* yaw -1 degree

wrap:
	jsr	ckDegWrap		;* adjust deg for wrap
	tst.l	viewer
	beq	.instance
	move.l	d2,alphaV
	move.l	d3,betaV
	move.l	d4,gammaV
	bra	buildMatrix
.instance:
	move.l	d2,alphaI
	move.l	d3,betaI
	move.l	d4,gammaI


	;*==============================================================*

buildMatrix:

;	TIMEBAR	RGB_DKGREEN

	;* roll Instance
	move.l	alphaI,d0
	move.l	#LeftMatrix,a0
	jsr	arb_roll

	;* pitch Instance
	move.l	betaI,d0
	move.l	#RiteMatrix,a0
	jsr	arb_pitch

	;* do the matrix multiply
	move.l	#LeftMatrix,a1	
	move.l	#RiteMatrix,a2	
	move.l	#iMatrix,a3	

	jsr	matmult

	;* copy new matrix back into Left
	move.l	#iMatrix,a3
	move.l	#LeftMatrix,a1	
	moveq	#11,d0
.IMlp:
	move.l	(a3)+,(a1)+
	dbra	d0,.IMlp

	;* yaw Instance
	move.l	gammaI,d0
	move.l	#RiteMatrix,a0
	jsr	arb_yaw

	;* do the matrix multiply, storing answer in iMatrix
	move.l	#LeftMatrix,a1	
	move.l	#RiteMatrix,a2	
	move.l	#iMatrix,a3	
	jsr	matmult

	;* result in iMatrix

	;*==============================================================*
 	;* roll Viewer
	move.l	alphaV,d0
	move.l	#LeftMatrix,a0
	jsr	arb_roll

	;* pitch Viewer
	move.l	betaV,d0
	move.l	#RiteMatrix,a0
	jsr	arb_pitch

	;* do the matrix multiply
	move.l	#LeftMatrix,a1	
	move.l	#RiteMatrix,a2	
	move.l	#vMatrix,a3	
	jsr	matmult

	;* copy new matrix back into Left
	move.l	#vMatrix,a3
	move.l	#LeftMatrix,a1	
	moveq	#11,d0
.VMlp:
	move.l	(a3)+,(a1)+
	dbra	d0,.VMlp

	;* yaw Instance
	move.l	gammaV,d0
	move.l	#RiteMatrix,a0
	jsr	arb_yaw

	;* do the matrix multiply, storing answer in iMatrix
	move.l	#LeftMatrix,a1	
	move.l	#RiteMatrix,a2	
	move.l	#vMatrix,a3	
	jsr	matmult

	;* result in vMatrix

	;*==============================================================*
	;* now add the delta translation to the Viewer matrix
upddone:

	move.l	#vMatrix,a1
	move.l	xdelta,36(a1)		; put xD into V41
	move.l	ydelta,40(a1)		; put yD into V42
 	move.l	zdelta,44(a1)		; put zD into V43

	;*=====================

;	TIMEBAR	RGB_VIOLET

	movem.l	(sp)+,a0-a4/d0-d2		; restore resgisters
	rts

;*======================================================================*
;* arb_roll()	- rotate an entity (instance) about its Z-axis by an
;*		  arbitrary angle
;*
;*	input:
;*		d0	- angle to rotate by (determine unit system)
;*		a0	- address of load matrix
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	arb_roll

arb_roll:
	movem.l	d0-d2/a0-a1,-(sp)		; save registers

	;* find the sin() and cos() values for this angle
	move.l	d0,d2
	jsr	cos			;* returns answer in d0
	move.l	d0,d1			;* save cosine
	move.l	d2,d0
	jsr	sin			;* returns answer in d0
	move.l	d0,d2			;* save sine

	;* actually roll the entity
	jsr	roll

	movem.l	(sp)+,a0-a1/d0-d2		; restore resgisters
	rts

;*======================================================================*
;* arb_pitch()	- rotate an entity (instance) about its X-axis by an
;*		  arbitrary angle
;*
;*	input:
;*		d0	- angle to rotate by (determine unit system)
;*		a0	- address of load matrix
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	arb_pitch

arb_pitch:
	movem.l	d0-d2/a0-a1,-(sp)		; save registers

	;* find the sin() and cos() values for this angle
	move.l	d0,d2
	jsr	cos			;* returns answer in d0
	move.l	d0,d1			;* save cosine
	move.l	d2,d0
	jsr	sin			;* returns answer in d0
	move.l	d0,d2			;* save sine

	;* actually pitch the entity
	jsr	pitch

	movem.l	(sp)+,a0-a1/d0-d2		; restore resgisters
	rts

;*======================================================================*
;* arb_yaw()	- rotate an entity (instance) about its Y-axis by an
;*		  arbitrary angle
;*
;*	input:
;*		d0	- angle to rotate by (determine unit system)
;*		a0	- address of load matrix
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	arb_yaw

arb_yaw:
	movem.l	d0-d2/a0-a1,-(sp)		; save registers

	;* find the sin() and cos() values for this angle
	move.l	d0,d2
	jsr	cos			;* returns answer in d0
	move.l	d0,d1			;* save cosine
	move.l	d2,d0
	jsr	sin			;* returns answer in d0
	move.l	d0,d2			;* save sine

	;* actually yaw the entity
	jsr	yaw

	movem.l	(sp)+,a0-a1/d0-d2		; restore resgisters
	rts

;*======================================================================*
;* roll()	- rotate an entity (instance) about its Z-axis by an
;*		  specific angle.  It builds the [3x3] necessary to
;*		  roll the entity. The matrix is described by the
;*		  following diagram:
;*
;*		+-                      -+
;*		|  cos()    -sin()    0  |	
;*		|  sin()     cos()    0  |
;*		|  0         0     4000  |
;*		|  0         0        0  |
;*		+-                      -+
;*
;*
;*	input:
;*		d1	- cosine of angle
;*		d2	- sine   of angle
;*		a0	- address of load matrix
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	roll

roll:
	movem.l	d0-d2/a0-a1,-(sp)		;* save registers

	;* clear the roll matrix
	move.l	a0,a1
	moveq	#11,d0

.clrlp:
	clr.l	(a1)+
	dbra	d0,.clrlp

	;* build the roll portion of the matrix
 	move.l	d1,(a0)			;*  cos(angle)
	move.l	d2,12(a0)		;*  sin()
	move.l	d1,16(a0)		;*  cos()
	move.l	#$4000,32(a0)		;*  unity
	neg.l	d2
	move.l	d2,4(a0)		;* -sin(angle)

	movem.l	(sp)+,a0-a1/d0-d2		;* restore resgisters
	rts

;*======================================================================*
;* pitch()	- rotate an entity (instance) about its X-axis by an
;*		  specific angle.  It builds the [3x3] necessary to
;*		  pitch the entity. The matrix is described by the
;*		  following diagram:
;*
;*		+-                      -+
;*		|  4000      0        0  | 	
;*		|     0  cos()   -sin()  |
;*		|     0  sin()    cos()  |
;*		|     0      0        0  |
;*		+-                      -+
;*
;*	input:
;*		d1	- cosine of angle
;*		d2	- sine   of angle
;*		a0	- address of load matrix
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	pitch

pitch:
	movem.l	d0-d2/a0-a1,-(sp)		;* save registers

	;* clear the pitch matrix
	move.l	a0,a1
	moveq	#11,d0

.clrlp:
	clr.l	(a1)+
	dbra	d0,.clrlp

	;* build the pitch portion of the matrix
	move.l	#$4000,(a0)		;*  unity
	move.l	d1,16(a0)		;*  cos(angle)
	move.l	d2,28(a0)		;*  sin()
	move.l	d1,32(a0)		;*  cos()
	neg.l	d2
	move.l	d2,20(a0)		;* -sin(angle)

	movem.l	(sp)+,a0-a1/d0-d2		;* restore resgisters
	rts

;*======================================================================*
;* yaw()	- rotate an entity (instance) about its Y-axis by an
;*		  specific angle.  It builds the [3x3] necessary to
;*		  yaw the entity. The matrix is described by the
;*		  following diagram:
;*
;*		+-                      -+
;*		|   cos()    0    sin()  |
;*		|       0 4000        0  |
;*		|  -sin()    0    cos()  |
;*		|       0    0        0  |
;*		+-                      -+
;*
;*	input:
;*		d1	- cosine of angle
;*		d2	- sine   of angle
;*		a0	- address of load matrix
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	yaw

yaw:
	movem.l	d0-d2/a0-a1,-(sp)		;* save registers

	;* clear the yaw matrix
	move.l	a0,a1
	moveq	#11,d0

.clrlp:
	clr.l	(a1)+
	dbra	d0,.clrlp

	;* build the yaw portion of the matrix
	move.l	d1,(a0)			;*  cos(angle)
	move.l	d2,8(a0)		;*  sin()
	move.l	#$4000,16(a0)		;*  unity
	move.l	d1,32(a0)		;*  cos()
	neg.l	d2
	move.l	d2,24(a0)		;* -sin(angle)
  
	movem.l	(sp)+,a0-a1/d0-d2		;* restore resgisters
	rts

;*======================================================================*
;* matmult()	- preform a [3x3][3x3]  matrix multiply, utilizing the
;*		  fast GPU to actually do the calculations.
;*
;*	input:
;*		a1	- left-hand matrix
;*		a2	- right-hand matrix
;*		a3	- answer-hand matrix
;*
;*	preserved:
;*		d0-d1
;*		a0-a4
;*======================================================================*

	.globl	matmult

matmult:
	movem.l	d0-d1/a0-a4,-(sp)		;* save registers

	;* setup the parameters for the GPU program
	move.l	#matbuffer,param_ptr		;* get buffer area
	LONGALIGN	param_ptr		;* GPU requires a long aligned address

	move.l	param_ptr,a0			;* a0 = buffer area long-aligned

	;* fill the buffer area with 3 pointers and 3 matrices
	move.l	a0,a4			;* remember where pointers go
	add.l	#12,a0			;* skip pointers

	;* load the address of left-hand matrix and data
	move.l	a0,(a4)+		;* store address
	moveq	#11,d1
.lhmlp:
	move.l	(a1)+,(a0)+		;* store data
	dbra	d1,.lhmlp

	;* load the address of rite-hand matrix and data
	move.l	a0,(a4)+		;* store address
	moveq	#11,d1
.rhmlp:
	move.l	(a2)+,(a0)+		;* store data
	dbra	d1,.rhmlp

	;* load the address of the GPU result-matrix
	move.l	a0,(a4)

	;* prepare to loadup the GPU program
	move.l	param_ptr,d0
	swap	d0
	move.l	d0,INPUT1

	lea.l	m3x3mult,a0		;* get base address of GPU code
	lea.l	G_RAM,a1		;* get GPU program base address
	jsr	gpuload			;* load the GPU program
	jsr	gpurun			;* execute the program
 
.waitgpu:
	move.l	#SEMAPHORE,a0
	move.l	(a0),d0
	beq	.waitgpu

	LASTCOLR

	;* copy the GPU-result matrix into 68000-result matrix
	move.l	param_ptr,a0
	move.l	8(a0),a1
	moveq	#8,d1			;* was only a [3x3][3x3] multiply
.copylp:
	move.l	(a1)+,(a3)+		;* copy data
	dbra	d1,.copylp
	
	movem.l	(sp)+,a0-a4/d0-d1	;* restore resgisters
	rts

;*======================================================================*
;* setDelta()	- set up the dX, dY, and dZ values (TEST)
;*
;*	input:
;*		none
;*
;*	preserved:
;*		d1
;*======================================================================*

	.globl	setDelta

setDelta:
	move.l	d1,-(sp)		; save registers

	move.l	xI,d1
	sub.l	xV,d1
	move.l	d1,xdelta

	move.l	yI,d1
	sub.l	yV,d1
	move.l	d1,ydelta

	move.l	zI,d1
	sub.l	zV,d1
	move.l	d1,zdelta

	move.l	(sp)+,d1		; restore resgisters
	rts

;*======================================================================*
;* ckDegWrap() - make sure the degree value wrap in the range
;*			-360 <= 0 <= 360
;*
;*	input:
;*		d2 - alpha degrees
;*		d2 - beta  degrees
;*		d2 - gamma degrees
;*
;*	output:
;*		d2 - degrees in range -360 <= deg <= 360
;*		d3 - degrees in range -360 <= deg <= 360
;*		d4 - degrees in range -360 <= deg <= 360
;*	preserved:
;*		nothing
;*======================================================================*

	.globl	ckDegWrap

ckDegWrap:

	;* check for less than -360
N360alpha:
	cmpi.l	#DEGN360,d2
	bpl	ck360alpha
	clr.l	d2			;* wrap to 0 deg
	bra	N360beta

	;* check for greater than 360
ck360alpha:
	cmpi.l	#DEG360,d2
	bmi	N360beta
	clr.l	d2			;* wrap to 0 deg

N360beta:
	cmpi.l	#DEGN360,d3
	bpl	ck360beta
	clr.l	d3			;* wrap to 0 deg
	bra	N360gamma

	;* check for greater than 360
ck360beta:
	cmpi.l	#DEG360,d3
	bmi	N360gamma
	clr.l	d3			;* wrap to 0 deg

N360gamma:
	cmpi.l	#DEGN360,d4
	bpl	ck360gamma
	clr.l	d4			;* wrap to 0 deg
	bra	ck_done

	;* check for greater than 360
ck360gamma:
	cmpi.l	#DEG360,d4
	bmi	ck_done
	clr.l	d4			;* wrap to 0 deg

ck_done:
	rts

;*======================================================================*
;* ckLimits() - make sure the pos is on screen
;*
;*	input:
;*		d2 - X position
;*		d2 - Y position
;*		d2 - Z position
;*
;*	output:
;*		d2 - 0 <= X < XMAX
;*		d3 - 0 <= Y < YMAX
;*		d4 - 0 <= Z < ZMAX
;*	preserved:
;*		nothing
;*======================================================================*

	.globl	ckLimits

ckLimits:

	;* check for less than 0
Xmin:
	cmpi.l	#XMIN,d2
	bpl	ckXmax
	move.l	#XMIN,d2		;* set to X min
	bra	Ymin

	;* check for greater than XMAX
ckXmax:
	cmpi.l	#XMAX,d2
	bmi	Ymin
	move.l	#XMAX,d2		;* set to X max

	;* check for less than 0
Ymin:
	cmpi.l	#YMIN,d3
	bpl	ckYmax
	move.l	#YMIN,d3		;* set to Y min
	bra	Zmin

	;* check for greater than YMAX
ckYmax:
	cmpi.l	#YMAX,d3
	bmi	Zmin
	move.l	#YMAX,d3		;* set to Y max

	;* check for less than 0
Zmin:
	cmpi.l	#ZMIN,d4
	bpl	ckZmax
	move.l	#ZMIN,d4		;* set to Z min
	bra	doneLimits

	;* check for greater than ZMAX
ckZmax:
	cmpi.l	#ZMAX,d4
	bmi	doneLimits
	move.l	#ZMAX,d4		;* set to Z max

doneLimits:
	rts

;*======================================================================*
;* cos()	- determine the cosine of a degree normalized by 0x4000
;* sin()	- determine the sine   of a degree normalized by 0x4000
;*
;*	input:
;*		d0	- deg (radians -360 to 360)
;*
;*	output:
;*		d0	- cosine = sin(deg+90) * 0x4000
;*			or
;*			  sine   = sin(deg) * 0x4000
;*
;*	preserved:
;*		d1-d4
;*		a0
;*======================================================================*

	.globl	cos

cos:
	movem.l	d1-d4/a0,-(sp)		;* save resgisters

	clr.l	d1			;* clear negative flag
	add.l	#DEG90,d0		;* cos(deg) = sin(deg+90)
	cmpi.l	#DEG360,d0		;* if deg > 360
	ble	cossign
	sub.l	#DEG360,d0		;* deg = deg - 360
cossign:
	tst.l	d0			;* check for negative
	bpl	possin
	moveq.l	#1,d1			;* remember negative
	neg.l	d0			;* make abs
	bra	possin			;* calculate

sin:
	movem.l	d1-d4/a0,-(sp)		;* save resgisters

	clr.l	d1			;* clear negative flag
	tst.l	d0			;* check for negative
	bpl	possin
	moveq.l	#1,d1			;* remember negative
	neg.l	d0			;* make abs

	cmpi.l	#DEG360,d0		;* if deg > 360
	ble	possin
	move.l	0,d0			;* set to 0

possin:
	move.l	#sintbl,a0		;* get lookup table

	;* if 0 < deg <= 90, lookup (deg)
	cmpi.l	#DEG90,d0
	bgt	chk180

	;* perform the actual lookup of the sine/cosine value
lookup:
	asl.l	#2,d0			;* data in longs (4 bytes/degree)
	add.l	d0,a0			;* add offset into table
	move.l	(a0),d0			;* get value
;	tst.l	d1			;* see if negative deg
;	beq	lkdone
;	neg.l	d0			;* account for neg result
	bra	lkdone

chk180:
	;* if 91 < deg <= 180, lookup (90 - (deg-90))
	cmpi.l	#DEG180,d0
	bgt	chk270
	move.l	#DEG90,d2
	move.l	d0,d3
	sub.l	d2,d3
	sub.l	d3,d2
;
;	move.l	#DEG180,d2
;	sub.l	d0,d2
	move.l	d2,d0
	bra	lookup

chk270:
	;* if 181 < deg <= 270, lookup -(deg - 180)
	cmpi.l	#DEG270,d0
	bgt	chk360
	move.l	#DEG180,d2
	sub.l	d2,d0
	tst.l	d1			;* account for neg result
	beq	.accneg
	clr.l	d1
	bra	lookup
.accneg:
	moveq.l	#1,d1			;* account for neg result
	bra	lookup


chk360:
	;* if 271 < deg <= 360, lookup -(90 - (deg-270))

	move.l	#DEG270,d2
	move.l	d0,d3
	sub.l	d2,d3
	move.l	#DEG90,d2
	sub.l	d3,d2
	
;	move.l	#DEG360,d2
;	sub.l	d0,d2
;
	move.l	d2,d0
	tst.l	d1			;* account for neg result
	beq	.accneg
	clr.l	d1
	bra	lookup
.accneg:
	moveq.l	#1,d1			;* account for neg result
	bra	lookup

lkdone:
	tst.l	d1
	beq	am_done
	neg.l	d0
am_done:
	movem.l	(sp)+,a0/d1-d4		;* restore resgisters
	rts

;*======================================================================*

	.bss

	.even

LeftMatrix:
	ds.l	12		; enough for a [3x4]

RiteMatrix:
	ds.l	12		; enough for a [3x4]

iMatrix:
	ds.l	12		; enough for a [3x4]

vMatrix:
	ds.l	12		; enough for a [3x4]

	;*==============================================================*
	;*	INPUT Flags
	;*==============================================================*

viewer:
	ds.l	1		; viewer/instance flag

	;*==============================================================*
	;*	INSTANCE Variables
	;*==============================================================*

alphaI:	ds.l	1		; Instance roll angle
betaI:	ds.l	1		; Instance pitch angle
gammaI:	ds.l	1		; Instance yaw angle

xI:	ds.l	1		; Instance X position
yI:	ds.l	1		; Instance Y position
zI:	ds.l	1		; Instance Z position

	;*==============================================================*
	;*	VIEWER Variables
	;*==============================================================*

alphaV:	ds.l	1		; Viewer roll angle
betaV:	ds.l	1		; Viewer pitch angle
gammaV:	ds.l	1		; Viewer yaw angle

xV:	ds.l	1		; Viewer X position
yV:	ds.l	1		; Viewer Y position
zV:	ds.l	1		; Viewer Z position

	;*==============================================================*
	;*	TRANSFORM variables
	;*==============================================================*

xdelta:	ds.l	1		; dX variable
ydelta:	ds.l	1		; dY variable
zdelta:	ds.l	1		; dZ variable

;*======================================================================*

	.data

	.even

sintbl: ;* sin(0) - sin(90)
	DC.L	$00000000,$0000011D,$0000023B,$00000359
	DC.L	$00000476,$00000593,$000006B0,$000007CC
	DC.L	$000008E8,$00000A03,$00000B1D,$00000C36
	DC.L	$00000D4E,$00000E65,$00000F7B,$00001090
	DC.L	$000011A4,$000012B6,$000013C6,$000014D6
	DC.L	$000015E3,$000016EF,$000017F9,$00001901
	DC.L	$00001A07,$00001B0C,$00001C0E,$00001D0E
	DC.L	$00001E0B,$00001F07,$00001FFF,$000020F6
	DC.L	$000021EA,$000022DB,$000023C9,$000024B5
	DC.L	$0000259E,$00002684,$00002766,$00002846
	DC.L	$00002923,$000029FC,$00002AD3,$00002BA5
	DC.L	$00002C75,$00002D41,$00002E09,$00002ECE
	DC.L	$00002F8F,$0000304D,$00003106,$000031BC
	DC.L	$0000326E,$0000331C,$000033C6,$0000346C
	DC.L	$0000350E,$000035AC,$00003646,$000036DB
	DC.L	$0000376C,$000037F9,$00003882,$00003906
	DC.L	$00003985,$00003A00,$00003A77,$00003AE9
	DC.L	$00003B56,$00003BBF,$00003C23,$00003C83
	DC.L	$00003CDE,$00003D34,$00003D85,$00003DD1
	DC.L	$00003E19,$00003E5C,$00003E99,$00003ED2
	DC.L	$00003F07,$00003F36,$00003F60,$00003F85
	DC.L	$00003FA6,$00003FC1,$00003FD8,$00003FE9
	DC.L	$00003FF6,$00003FFD,$00004000

;*======================================================================*

	END

;*======================================================================*
;*                                 EOF                                  *
;*======================================================================*

 
