;bullet sturct

	.def	bulletSourceWidth	681

	;buState 

	.def	buStateInactive		0
	.def	buStateFlying		1
	.def	buStateExplosion	2
	
	;buExplosionAnimCount/buExplosionAnimSubCount global never changed
	
	.def	buExplosionAnimCountMax		9
	.def	buExplosionAnimSubCountMax	1
	
	;buLifeTime/buSpeed changed by player and enemys
	
	.def	buLifeTimeDefault	40
	.def	buSpeedDefault		4
	
	;bullet buWhichPerson (how can use this slot)
	
	.def	buPlayer		0
	.def	buEnemy			1
	
	;struct def
	
	.def	buPositionX		0
	.def	buPositionY		1
	.def	buDirection		2	
	.def	buSpeed			3	;xy speed
	.def	buLifeTime		4	;time to fly
	.def	buState			5	;0 = is inactive, 1 = flying, 2 = explosion
	.def	buExplosionAnimCount	6	;0..9
	.def	buExplosionAnimSubCount	7
	.def	buWhichPerson		8
	.def	buStructLength		9
	
	.def	bulletsMax		29	;30-1	
	
;******************************
;*
;* addBullet
;* 
;* r1 = who can use
;* r2 = direction 
;* r3 = x
;* r4 = y
;* r5 = lifetime
;* r6 = speed
;* 
;*

addBullet

	;prolog

	push	r0
	push	r1
	push	r5
	push	r6
	push	r7

	;check for free bullet
	
	dexti	>bulletsData
	movei	r7,bulletsData	
	movei	r0,bulletsMax	;cnt
	nop
	
addBulletTestLoop

	push	r0
	push	r7
	push	r2

	rqldi	r7,buState
	rqldi	r7,buWhichPerson
	movei	r2,0
	ld	r0	;state
	ld	r7	;type
		
	cmpeqi	r0,buStateInactive	;inactive
	addtqi	r2,r2,0
	cmpeq	r7,r1			;right type
	addtqi	r2,r2,0
	nop
	cmpeqi	r2,2			;both true 	T
	
	rqpop	
	rqpop	
	rqpop	
	pop	r2	
	pop     r7
	pop     r0
	
	brts	addBulletReal		;use		T
	nop				;delay slot
	nop				;delay slot
	nop				;delay slot
	subi	r0,1			;delay slot	
	
	brts	addBulletTestLoop
	addi	r7,buStructLength	;delay slot
	nop				;delay slot
	nop				;delay slot
	nop				;delay slot	
	
addBulletEpilog	
	
	;epliog
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6
	pop	r5
	pop	r1
	pop	r0
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot		

	;r2 = direction 
	;r3 = x
	;r4 = y
	;r5 = lifetime
	;r6 = speed
	
addBulletReal


	stinc	r7,r3	;x
	movei	r0,buStateFlying	;new state
	stinc	r7,r4	;y
	movei	r1,0
	stinc	r7,r2	;direction
	nop
	stinc	r7,r6	;speed
	nop
	stinc	r7,r5	;lifetime
	nop
	stinc	r7,r0	;state
	nop
	stinc	r7,r1	;anim cnt
	nop
	stinc	r7,r1	;anim sub cnt
	
	;now play shot sound
	
	dexti	>playSFX
	movei	r0,playSFX
	gpci	r7,2
	jmpi	r0,0
	dexti	>sfxShotData	;delay slot
	movei	r5,sfxShotData	;delay slot
	dexti	>channel0	;delay slot
	movei	r6,channel0	;delay slot
	
	;
	
	br	addBulletEpilog
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* drawAndCalcBullets
;* 
;* r0 = mapStruct
;*	
	
drawAndCalcBullets

	;prolog

	push	r1
	push	r2
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7	
	
	dexti	>bulletsData
	movei	r1,bulletsData
	
	movei	r3,bulletsMax

drawAndCalcBulletsLoop	
	
	;calc bullet

	gpci	r7,2
	br	calcBullet
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot	

	;draw	
		
	gpci	r7,2
	br	drawBullet			;return r2 if 1 hit detected with someone
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot	
	
	cmpeqi	r2,1	;code 1 -> collision to enemy
	gpci	r7,2
	brts	hitBulletCode1
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot	
	
	cmpeqi	r2,2	;code 3 -> collision to player
	gpci	r7,2
	brts	hitBulletCode2
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	cmpeqi	r2,3	;code 3 -> collision to bullet
	gpci	r7,2
	brts	hitBulletCode3
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;if collision then play explosion siund
	
	dexti	>playSFX
	movei	r4,playSFX
	cmpeqi	r2,0	;code not zero -> collision
	gpci	r7,2
	jmptc	r4
	dexti	>sfxExplosionData	;delay slot
	movei	r5,sfxExplosionData	;delay slot
	dexti	>channel5		;delay slot
	movei	r6,channel5		;delay slot

	subi	r3,1
	brts	drawAndCalcBulletsLoop
	addi	r1,buStructLength		;next struct 	delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;epilog
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6
	poparqp	r5
	poparqp	r4
	pop	r3
	pop	r2
	pop	r1
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot	

;******************************
;*
;* hitBulletCode2 (player hit)
;* 
;* r0 = mapStruct
;* r1 = bulletStruct
;*	
	
hitBulletCode2

	push	r2
	push	r3
	push	r4
	push	r7
	
	rqldi	r1,buState
	nop
	nop
	ld	r3	;state
	
	movei	r2,buStateExplosion
	cmpeqi	r3,buStateFlying	;flying state
	dexti	>playerHit
	movei	r4,playerHit
	gpci	r7,2
	jmpts	r4			;notify player (if hit on flying state)
	movets	r3,r2,r3		;delay slot	yes then set explosion else don't change
	ssto	buState			;delay slot
	stwo	r1,r2			;delay slot
	nop				;delay slot

	rqpop
	rqpop
	rqpop
	pop	r7
	pop	r4
	pop	r3
	
	rqpop
	jmpi	r7,0
	nop		;delay slot
	pop	r2	;delay slot
	nop		;delay slot
	nop		;delay slot
	


	
;******************************
;*
;* hitBulletCode3 (bullet hit)
;* 
;* r0 = mapStruct
;* r1 = bulletStruct
;*
	
hitBulletCode3	

	push	r2
	push	r3
	
	rqldi	r1,buState
	nop
	nop
	ld	r3	;state	
	
	movei	r2,buStateExplosion
	cmpeqi	r3,buStateFlying	;flying state
	movets	r3,r2,r3		;yes then set explosion else don't change
	
	ssto	buState
	stwo	r1,r2
	
	rqpop
	rqpop
	jmpi	r7,0
	pop	r3	;delay slot
	pop	r2	;delay slot
	nop		;delay slot
	nop		;delay slot
	
	
;******************************
;*
;* hitBulletCode1 (enemy hit)
;* 
;* r0 = mapStruct
;* r1 = bulletStruct
;*
	
hitBulletCode1

	;prolog

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7
		
	;get x,y of bullet
	
	rqldi	r1,buState
	rqldi	r1,buPositionX
	rqldi	r1,buPositionY
	ld	r4		;state
	ld	r2		;x
	ld	r3		;y
	
	
	;get/set bullet to explode state
	
	cmpeqi	r4,buStateFlying	;only flying bullets will hit
	brtc	hitBulletCode1End
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	;
	
	push	r0	;store map struct
	push	r1	;store bullet struct
	
	dexti	>getNearestEnemy
	movei	r6,getNearestEnemy
	gpci	r7,2
	jmpi	r6,0
	or	r1,r0,r0	;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	;return	r4 = nearest enemy, r5 = distance 
	
	rqpop
	rqpop
	nop
	pop	r1	;restore bullet struct
	pop	r0	;restore map struct
	
	cmploi	r5,64	;distane < 64 (then its in the bastard)
	brtc	hitBulletCode1End
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	;flying bullet hit enemy (code1) so bullet will explode

	movei	r5,buStateExplosion
	ssto	buState
	stwo	r1,r5		;store to bullet struct
	
	;now hited enemy should die
				
	dexti	>killEnemy
	movei	r6,killEnemy
	gpci	r7,2
	jmpi	r6,0
	or	r1,r0,r0	;r1 = map struct	delay slot
	or	r0,r4,r4	;r0 = enemy to kill	delay slot
	nop			;delay slot
	nop			;delay slot
	

hitBulletCode1End	
	
	;epilog
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6
	poparqp	r5
	poparqp	r4
	poparqp	r3
	pop	r2
	pop	r1
	pop	r0
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot		
	
	
;******************************
;*
;* calcBullet
;* 
;* r0 = mapStruct
;* r1 = bulletStruct
;*	
;* 
;*
	
calcBullet

	;prolog

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7	
	
	;get state
	
	rqldi	r1,buState
	nop
	nop
	ld	r2
	nop
	
	cmpeqi	r2,buStateInactive
	brts	calcBulletEnd		;nothing to do at inactive state
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	cmpeqi	r2,buStateExplosion
	brts	calcBulletExplosion		;explosion
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;else its 
	;buStateFlying
	
	;
	
	rqldi	r1,buPositionX
	rqldi	r1,buPositionY
	rqldi	r1,buDirection
	ld	r2		;position x
	ld	r3		;position y
	ld	r4		;direction
	
	rqldi	r1,buLifeTime
	rqldi	r1,buSpeed
	nop
	ld	r5		;life time
	ld	r6		;speed
	
	;test life time
		
	cmpeqi	r5,0
	brts	bulletIsDead
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	subi	r5,1
	ssto	buLifeTime
	stwo	r1,r5		;life time --
	
	;calc new position
	
	;N	0	y-
	;NO	1	y-	x+
	;O	2		x+
	
	;SO	3	y+	x+
	;S	4	y+
	;SW	5	y+	x-
	;W	6		x-
	;NW	7	y-	x-
	
	push	r0		;store r0
	
	sub	r0,r3,r6	;r0 = y-
	add	r7,r2,r6	;r7 = x+
	
	cmpeqi	r4,0	;N
	movets	r3,r0,r3	;y-
	
	cmpeqi	r4,1	;NO
	movets	r3,r0,r3	;y-
	movets	r2,r7,r2	;x+
	
	cmpeqi	r4,2	;O
	movets	r2,r7,r2	;x+
	
	add	r0,r3,r6	;r0 = y+
	
	cmpeqi	r4,3	;SO
	movets	r3,r0,r3	;y+
	movets	r2,r7,r2	;x+
	
	cmpeqi	r4,4	;S
	movets	r3,r0,r3	;y+
	
	sub	r7,r2,r6	;r7 = x-
	
	cmpeqi	r4,5	;SW
	movets	r3,r0,r3	;y+
	movets	r2,r7,r2	;x-
	
	cmpeqi	r4,6	;W
	movets	r2,r7,r2	;x-
	
	sub	r0,r3,r6	;r0 = y-
	
	cmpeqi	r4,7	;NW
	movets	r3,r0,r3	;y-
	movets	r2,r7,r2	;x-
	
	ssto	buPositionX
	stwo	r1,r2		;position x
	ssto	buPositionY
	stwo	r1,r3		;position y
	
	rqpop
	nop
	nop
	pop	r0
	nop
	
	;test against background collision
	
	rqldi	r0,mapWidth
	addi	r2,8		;center of bullet
	addi	r3,8		;center of bullet
	ld	r4		;map width
	
	lsri	r2,4		;16 width of tiles
	lsri	r3,4
	
	nop
	mul	r3,r3,r4	;y + map width
	nop
	add	r3,r3,r2	;+x
	nop
	
	rqldi	r0,mapAdrCtrlLow
	rqldi	r0,mapAdrCtrlHigh
	nop
	ld	r5
	ld	r6

	add	r5,r5,r3
	addtqi	r6,r6,0
	nop
	
	edrqldi	r6,r5,0		;request collion data	
	eld	r4
	
	nop
	cmpeqi	r4,1		;1 is collision
	brts	bulletIsDead
	nop			;delay slot
	nop			;delay slot	
	nop			;delay slot
	nop			;delay slot
	
	
	
calcBulletEnd	
	
	;epilog
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6
	poparqp	r5
	poparqp	r4
	poparqp	r3
	pop	r2
	pop	r1
	pop	r0
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot	
		
;lifetime over so explode		

bulletIsDead

	;play explosion sound

	dexti	>playSFX
	movei	r4,playSFX
	gpci	r7,2
	jmpi	r4,0
	dexti	>sfxExplosionData	;delay slot
	movei	r5,sfxExplosionData	;delay slot
	dexti	>channel5		;delay slot
	movei	r6,channel5		;delay slot
	
	;

	br	calcBulletEnd
	movei	r2,buStateExplosion	;delay slot
	ssto	buState			;delay slot	
	stwo	r1,r2			;delay slot
	nop				;delay slot	

	
;explosion	
	
calcBulletExplosion	


	rqldi	r1,buExplosionAnimSubCount
	rqldi	r1,buExplosionAnimCount
	rqldi	r1,buState
	ld	r2		;sub counter
	ld	r3		;anim counter
	ld	r6		;state
	
	cmpeqi	r2,buExplosionAnimSubCountMax		;counter hit
	brtc	calcBulletEnd	; no so anim change
	addi	r2,1					;delay slot
	ssto	buExplosionAnimSubCount			;delay slot
	stwo	r1,r2					;delay slot
	nop						;delay slot
	
	movei	r5,0		;r5 = 0    
	addqi	r4,r3,1		;r4 = anim counter + 1	
	ssto	buExplosionAnimSubCount	
	stwo	r1,r5		;clear anim sub count			             
	
	cmpeqi	r3,buExplosionAnimCountMax	;anim finshed
	movets	r3,r5,r3			;		anim count = 0
	movets	r6,r5,r6			;		state = 0 (inActive now)
	movets	r3,r3,r4			;else		anim count ++
	
	br	calcBulletEnd
	ssto	buExplosionAnimCount	;delay slot
	stwo	r1,r3			;delay slot	store anim count
	ssto	buState			;delay slot
	stwo	r1,r6			;delay slot	store state
	
;******************************
;*
;* drawBullet
;* 
;* r0 = mapStruct
;* r1 = bulletStruct
;*	
;* return
;*
;* r2 = 1 if collision is detected
;*
	
drawBullet

	;prolog

	push	r0
	push	r1
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7	
	
	;get state
	
	rqldi	r1,buState
	nop
	nop
	ld	r7		;get state
	nop
	
	cmpeqi	r7,buStateInactive
	brts	drawBulletEnd		;inactive nothing to do
	movei	r2,0	;set return code to 0 (nothing happend here) delay slot	
	nop		;delay slot	
	nop		;delay slot	
	nop		;delay slot	
	
	
	;
	
	rqldi	r1,buPositionX
	rqldi	r1,buPositionY
	rqldi	r1,buDirection
	ld	r2		;position x
	ld	r3		;position y
	ld	r4		;direction
	
	rqldi	r0,mapPositionX
	rqldi	r0,mapPositionY
	nop
	ld	r5		;map pos x
	ld	r6		;map pos y
	
	add	r2,r2,r5
	add	r3,r3,r6	
	
	dexti	>bulletBobData
	movei	r6,bulletBobData
	
	ssto	csDestX
	stwo	r6,r2		;store destination x
	ssto	csDestY
	stwo	r6,r3		;store destination y
	
	cmpeqi	r7,buStateExplosion	;explosion state so use other animation
	brtc	drawBulletMove
	nop		;delay slot	
	nop		;delay slot	
	nop		;delay slot	
	nop		;delay slot
	
	rqldi	r1,buExplosionAnimCount
	dexti	>bulletExplosionGFXPosition
	movei	r5,bulletExplosionGFXPosition
	ld	r2		;explosion anim
	
	nop
	add	r2,r2,r2	;*2
	nop
	add	r5,r5,r2
	nop
	
	rqldi	r5,0		;get inner source x
	rqldi	r5,1		;get inner source y
	nop
	ld	r2
	ld	r3
	
	ssto	csSourceX
	stwo	r6,r2		;inner source destination x
	ssto	csSourceY
	stwo	r6,r3		;inner source destination y
	
	;dump
	
	br	drawBulletContinue
	nop		;delay slot	
	nop		;delay slot	
	nop		;delay slot	
	nop		;delay slot
	
	
drawBulletMove	
	
	dexti	>bulletMoveGFXPosition
	movei	r5,bulletMoveGFXPosition
	
	add	r4,r4,r4	;direction * 2
	nop
	add	r5,r5,r4
	nop
	rqldi	r5,0		;get inner source x
	rqldi	r5,1		;get inner source y
	nop
	ld	r2
	ld	r3
	
	ssto	csSourceX
	stwo	r6,r2		;inner source destination x
	ssto	csSourceY
	stwo	r6,r3		;inner source destination y
	
drawBulletContinue
	
	;
	
	
	dexti	>drawFrame
	movei	r7,drawFrame
	nop
	rqldi	r7,0
	rqldi	r7,1
	nop
	ld	r1	;high
	ld	r0	;low
	nop
	;addi	r0,16
	;addtqi	r1,r1,0
	
	
	ssto	csDestAdrLow
	stwo	r6,r0
	ssto	csDestAdrHigh
	stwo	r6,r1
	
	gpci	r7,2		;next 4 + X
	br	drawBob		;br	drawBob
	or	r0,r6,r6	;delay slot
	nop	;delay slot
	nop			;delay slot
	nop			;delay slot	
	
	or	r2,r0,r0	;if r0 = 1 (returncode) then bullet hit someone -> store to r2

drawBulletEnd	
	
	;epilog
	
	rqpop
	rqpop
	rqpop
	pop	r7
	pop	r6
	pop	r5
	rqpop
	rqpop
	rqpop
	pop	r4
	pop	r3
	pop	r1
	
	rqpop
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot	
	
;*********************************************************************
;* data
;*********************************************************************			
	
	;global array of all bullets
	
bulletsData	
	.data	190,40,4,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;0 x,y,direction,speed,lifeTime,state,anim cnt,anim sub cnt, who can use this
	.data	180,40,5,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;1
	.data	170,40,6,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;2
	.data	160,40,7,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;3
	.data	150,40,0,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;4
	.data	140,40,1,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;5
	.data	130,40,2,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;6
	.data	120,40,3,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;7
	.data	110,40,4,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;8
	.data	100,40,5,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buPlayer	;9
	.data	190,40,4,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;10
	.data	180,40,5,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;11
	.data	170,40,6,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;12
	.data	160,40,7,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;13
	.data	150,40,0,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;14
	.data	140,40,1,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;15
	.data	130,40,2,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;16
	.data	120,40,3,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;17
	.data	110,40,4,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;18
	.data	100,40,5,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;19
	.data	190,40,4,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;20
	.data	180,40,5,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;21
	.data	170,40,6,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;22
	.data	160,40,7,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;23
	.data	150,40,0,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;24
	.data	140,40,1,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;25
	.data	130,40,2,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;26
	.data	120,40,3,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;27
	.data	110,40,4,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;28
	.data	100,40,5,buSpeedDefault,buLifeTimeDefault,buStateInactive,0,0,buEnemy	;29	
	
bulletMoveGFXPosition	
	
	.data	208,37		;N	0	O
	.data	225,37          ;NO	1	OR
	.data	242,37          ;O	2	R
	.data	259,37          ;SO	3	UR
	.data	276,37          ;S	4	U
	.data	293,37          ;SW	5	UL
	.data	310,37          ;W	6	L
	.data	327,37          ;NW	7	OL
	
bulletExplosionGFXPosition

	.data	4,3		;0
	.data	21,3		;1
	.data	38,3		;2
	.data	55,3		;3
	.data	72,3		;4
	.data	89,3		;5
	.data	106,3		;6
	.data	123,3		;7
	.data	140,3		;8
	.data	157,3		;9	
	