	.include	'eq.s'
	.include	'externs.s'

	.text
fire_spec::
	cmp.w	#CUTTER,spec_type
	beq		f_cutr
	tst.b	specweap+O_TYPE
	bpl		.90					;if positive, special weapon is already active
	move.b	#SPEC_DELAY_TIME,spec_delay
	move.w	spec_type,d0
	cmp.w	specweap+O_DESC,d0
	beq.b	.10
	bsr		loadspec
.10:
	and.b	#$7F,specweap+O_TYPE			;turn on the special weapon object
	move.b	#4,spec_dir					;most weapons will move to the right
	move.w	specweap+O_DESC,d0
	lsl.w	#1,d0						;weapon type * 2
	lea		spec_ht,a0
	move.w	(a0,d0.w),specweap+O_HEIGHT
	lsl.w	#1,d0						;change weapon type * 2 to weapon type * 4
	lea		specinfb,a0					;bytes of information (flags, depth, index, pitch)
	move.b	(a0,d0.w),specweap+O_FLAGS
	move.b	1(a0,d0.w),specweap+O_DEPTH
	move.b	2(a0,d0.w),specweap+O_INDEX
	move.b	3(a0,d0.w),specweap+O_PITCH
	lsl.w	#1,d0						;change weapon type * 4 to weapon type * 8
	lea		specinfw,a0					;words of information (x, y, dwidth, iwidth)
	move.w	(a0,d0.w),d1
	move.w	player+O_XPOS,specweap+O_XPOS
	add.w	d1,specweap+O_XPOS				;add horizontal offset to player xpos
	move.w	2(a0,d0.w),d1					;get y offset
	move.w	player+O_YPOS,specweap+O_YPOS
	add.w	d1,specweap+O_YPOS				;add vertical offset to player ypos
	move.w	4(a0,d0.w),specweap+O_DWIDTH
	move.w	6(a0,d0.w),specweap+O_IWIDTH

	move.w	spec_type,d0
	lsl.w	#2,d0						;weapon type * 4
	lea		f_spec,a0						;addresses of firing subroutines
	move.l	(a0,d0.w),a0
	jsr		(a0)
	move.w	spec_type,d0
	lea		spec_snd,a0
	move.b	(a0,d0.w),d0
	cmp.w	#FLASH,spec_type
	bne.b	.80
	move.l	#$00003FFF,d1
	bra.b	.85
.80:	move.w	specweap+O_XPOS,d1		;xpos to determine pan value
.85:	move.w	#1,d2				;use voice #1
	bsr		playvoice				;d0 = sample number, d1 = sound xpos, d2 = voice number

.90:	rts

f_tracer::
	move.w	#0,tracstep			;reset anim step
	move.w	#$FFFF,spec_hit		;initialize number of last enemy that was hit by tracer
	move.w	#0,d0				;count enemies
	lea		en_tractg,a1
	lea		enemy0,a0
.25:	tst.b	O_TYPE(a0)
	bmi.b	.50					;skip if delete flag is on
	move.w	O_DESC(a0),d1			;enemy is an explosion if >= $80
	bmi.b	.50
	cmp.b	#1,(a1,d1.w)			;1 if enemy can be a target for the tracer
	bne.b	.50
	move.b	d0,spec_tgt			;use this enemy number as the first target	
	rts
.50:	adda.l	#OBJ_SIZE,a0			;next enemy object
	addq.w	#1,d0				;next enemy
	cmp.w	#TOTAL_ENEMIES,d0
	blt.b	.25
	move.b	#$FF,spec_tgt			;$FF as target means there were no enemies
	rts
f_beam::
	move.w	#0,beamtime			;reset beam timer
	rts
f_flash::
	move.w	#0,flshtime			;reset flash timer
	rts
f_missile::
	move.w	specweap+O_XPOS,ms_rlimit
	add.w	#MISSILE_DIST,ms_rlimit	;distance before it explodes
	rts
f_ring::
	move.w	#0,ringstep			;reset ringstep
	move.w	#0,ringcnt			;reset ringcnt
	rts
f_bolt::
	move.b	#3,spec_dir			;move diagonally
	rts
f_magnet::
	rts
f_shield::
	move.w	#0,shldtime			;reset shield timer
	move.w	#PLR_PLAY,player+O_DESC	;cancel player flashing if necessary
	and.b	#$7F,player+O_TYPE		;make sure player object is on if it was flashing
	bsr		setshld
	rts

setshld::
;change the data address for shield to match the player ship
	lea		shlddata,a0
	move.w	curship,d0			;current type of player ship
	lsl.w	#2,d0
	move.l	(a0,d0.w),specweap+O_DATA	;address of shield data
	rts

loadspec::
;d0 is new special weapon type
	move.w	d0,specweap+O_DESC
	cmp.w	#SHIELD,d0
	beq.b	.90
	lsl.w	#4,d0				;get weapon type * 16
	lea		specblit,a0
	move.l	(a0,d0.w),A2_BASE		;source address
	beq		draw_flsh				;if 0, blit $FF's for flash, it has no data in rom
	move.l	4(a0,d0.w),B_COUNT		;height, width
	move.l	8(a0,d0.w),A1_STEP		;Y step = 1, X step = negative width
	move.l	12(a0,d0.w),d5			;A1_FLAGS, A2_FLAGS value
	move.l	d5,A1_FLAGS			;destination
	move.l	d5,A2_FLAGS			;source
	move.l	#specdata,A1_BASE		;destination address
	move.l	#0,A2_PIXEL			;start at 0,0 of source image
	move.l	#0,A1_PIXEL			;Y,X position to write data in destination area
	move.l	#UPDA1|SRCEN|LFU_A|LFU_AN,B_CMD	;turn on blitter
.90:	rts

draw_flsh::
	move.l	#PITCH1|PIXEL32|WID2|XADDPHR,A1_FLAGS
	move.l	#specdata,A1_BASE			;destination address
	move.l	#0,A1_PIXEL				;get rectangle Y,X
	move.l	#$0001FFFE,A1_STEP			;high = Y step, low = negative width
	move.l	#$01200002,B_COUNT			;high = height, low = width
	move.l	#$FFFFFFFF,B_PATD			;write FF's for 1 bit per pixel object
	move.l	#$FFFFFFFF,B_PATD+4
	move.l	#PATDSEL|UPDA1,B_CMD
	rts

move_spec::
	tst.b	specweap+O_TYPE
	bmi.b	.90					;if negative, weapon is not active
	move.w	specweap+O_DESC,d0
	bmi		m_msexp				;if negative, missile explosion is active

	lsl.w	#2,d0				;weapon type * 4
	lea		m_spec,a0				;addresses of moving subroutines
	move.l	(a0,d0.w),a0
	jmp		(a0)
.90:	rts

mv_spec::
;d0 is set to the speed for the object
	move.w	#$FFF0,d2				;left limit
	move.w	#SCRN_RIGHT,d3			;right limit
	move.w	#SCRN_TOP-128,d4		;top limit
	move.w	#SCRN_BOTTOM,d5		;bottom limit
	lsl.w	#5,d0				;multiply speed * 16 directions for each speed * 2 bytes for each direction
	move.l	#0,d1
	move.b	spec_dir,d1			;get powerup direction
	add.w	d1,d0				;add direction to speed * 32
	add.w	d1,d0				;add direction again because each direction uses 2 bytes
	lea		specweap,a1			;special weapon object
	bsr		move_obj
	tst.b	limitflag
	beq.b	endmvspec
spec_off::
	or.b		#DELETE_OBJ,specweap+O_TYPE	;turn off special weapon
	or.b		#DELETE_OBJ,specflsh+O_TYPE	;make sure flash is off
	move.l	#specdata,specweap+O_DATA
endmvspec::
	rts

m_msexp::
	move.w	specweap+O_XPOS,d1
	sub.w	scrlspd,d1
	move.w	d1,specweap+O_XPOS
	addq.b	#1,ms_excnt
	move.b	ms_excnt,d1
	move.w	specweap+O_DESC,d0
	and.w	#$FF,d0					;clear negative bit
	lea		exp_chg,a0
	move.b	(a0,d0.w),d2				;when to change anim step for this type of explosion
	cmp.b	d2,d1
	bne.b	.90
	move.b	#0,ms_excnt
	addq.b	#1,ms_exstp
	move.b	ms_exstp,d1
	lea		exp_stp,a0
	move.b	(a0,d0.w),d2				;get max anim steps for this type of explosion
	cmp.b	d2,d1
	bne		ld_msexp					;load new frame of explosion
	move.b	#0,ms_exstp				;reset animation step
	or.b		#DELETE_OBJ,specweap+O_TYPE	;turn off explosion
	move.w	#$7FFF,specweap+O_DESC		;clear negative bit, make sure weapon gets blitted next time it is used
	move.b	#0,specweap+O_INDEX			;reset the first color used to 0
	move.l	#specdata,specweap+O_DATA	;change data pointer from explosion data back to specdata
.90:	rts
ms_exp::
;start an explosion when the missile has travelled a certain distance away from the ship
;a1 points to enemy object
;d6 is the enemy number that was hit
	move.b	#0,ms_excnt					;reset missile explosion count
	move.b	#0,ms_exstp					;reset missile explosion step
	move.w	#(EXP_E+$FF00),specweap+O_DESC	;missile explosion with negative bit set
	move.b	#4,specweap+O_DEPTH				;set pixel depth for explosion
	sub.w	#10,specweap+O_XPOS
	sub.w	#56,specweap+O_YPOS
	move.w	#45,specweap+O_HEIGHT			;set explosion height
	move.w	#20,specweap+O_DWIDTH			;set explosion dwidth
	move.w	#20,specweap+O_IWIDTH			;set explosion iwidth
	move.b	#TRANS_ON,specweap+O_FLAGS
	move.b	#0,specweap+O_INDEX
;fall through to ld_msexp
ld_msexp::						;blit the missile explosion
	move.w	#0,d1
	move.b	ms_exstp,d1			;get animation step for current explosion
	lsl.w	#2,d1				;4 bytes for each data address in table
	lea		expe_dta,a0
	move.l	(a0,d1.w),specweap+O_DATA
	lea		exp_ht+(EXP_E*16),a0
	lsr.w	#1,d1				;anim step * 2
	move.w	(a0,d1.w),specweap+O_HEIGHT
	rts

m_bolt::
	addq.b	#1,boltflip
	and.b	#7,boltflip
	cmp.b	#4,boltflip
	blt		.20
;blit the beam part of the bolt weapon, not horizontally flipped
	move.l	#PITCH1|PIXEL16|WID16|XADDPHR,A1_FLAGS	;description of destination area
	move.l	#PITCH1|PIXEL16|WID16|XADDPHR,A2_FLAGS	;description of source area
	move.l	#$00090000,A1_PIXEL		;Y,X position to write data in destination area
	move.l	#$0001FFF0,A1_STEP		;1 in Y step size, negative width in X step size
	bra.b	.50
.20:
;blit the beam part of the bolt weapon, horizontally flipped
	move.l	#PITCH1|PIXEL16|WID16|XADDPIX|XSIGNSUB,A1_FLAGS	;description of destination area
	move.l	#PITCH1|PIXEL16|WID16|XADDPIX|XSIGNADD,A2_FLAGS	;description of source area
	move.l	#$0009000F,A1_PIXEL		;Y,X position to write data in destination area
	move.l	#$00010010,A1_STEP		;1 in Y step size, width in X step size
.50:
;the rest of the code to blit the beam part of the bolt weapon
	move.l	#specdata,A1_BASE		;destination address
	move.l	#boltmid,A2_BASE		;source address
	move.l	#0,A2_PIXEL			;start at 0,0 of source image
	move.l	#$00780010,B_COUNT		;inner loop = 120, outer loop = 16
	move.l	#UPDA1|SRCEN|LFU_A|LFU_AN,B_CMD	;turn on blitter
;blit bottom piece of bolt weapon
	move.l	#PITCH1|PIXEL32|WID8|XADDPHR,A1_FLAGS	;description of destination area
	move.l	#PITCH1|PIXEL32|WID8|XADDPHR,A2_FLAGS	;description of source area
	move.l	#boltbot,A2_BASE		;source address
	move.l	#0,d0				;initialize Y,X position
	move.w	specweap+O_HEIGHT,d0
	sub.w	#9,d0				;subtract height of bottom piece
	swap		d0					;move Y position to high word
	move.l	d0,A1_PIXEL			;Y,X in destination
	move.l	#0,A2_PIXEL			;start at 0,0 of source image
	move.l	#$000B0008,B_COUNT		;inner loop = 11, outer loop = 8
	move.l	#$0001FFF8,A1_STEP		;1 in Y step size, negative width in X step size
	move.l	#UPDA1|SRCEN|LFU_A|LFU_AN,B_CMD	;turn on blitter

	cmp.w	#BOLT_HEIGHT,specweap+O_HEIGHT
	bge.b	.60					;keep it at maximum size
	addq.w	#2,specweap+O_HEIGHT
	cmp.w	#BOLT_HEIGHT,specweap+O_HEIGHT
	blt.b	.60
	move.b	#4,spec_dir			;move to the right when at maximum size
.60:	move.l	#BOLT_SPEED,d0			;set speed for mv_spec	
	bra		mv_spec

m_missile::
	move.l	#MISSILE_SPEED,d0
	move.w	#$FFF0,d2				;left limit
	move.w	ms_rlimit,d3			;right limit
	move.w	#SCRN_TOP-28,d4		;top limit
	move.w	#SCRN_BOTTOM,d5		;bottom limit
	lsl.w	#5,d0				;multiply speed * 16 directions for each speed * 2 bytes for each direction
	move.l	#0,d1
	move.b	spec_dir,d1			;get special weapon direction
	add.w	d1,d0				;add direction to speed * 32
	add.w	d1,d0				;add direction again because each direction uses 2 bytes
	lea		specweap,a1			;special weapon object
	bsr		move_obj
	tst.b	limitflag
	beq.b	.90
	bsr		ms_exp				;start missile explosion
.90:	rts

m_magnet::
	move.l	#MAGNET_SPEED,d0
	bra		mv_spec
m_tracer::
	add.w	#1,tracstep
	cmp.w	#12,tracstep			;3 steps, changes every 4 steps
	blt.b	.10
	move.w	#0,tracstep
.10:
	move.w	tracstep,d0
	lsr.w	#2,d0				;counter goes to 12, there are 3 frames
	lsl.w	#2,d0
	lea		tracdata,a0
	move.l	(a0,d0.w),A2_BASE		;address of explosion data in rom
	move.l	#PITCH1|PIXEL32|WID12|XADDPHR,A1_FLAGS	;description of destination area
	move.l	#PITCH1|PIXEL32|WID12|XADDPHR,A2_FLAGS	;description of destination area
	move.l	#specdata,A1_BASE		;destination address
	move.l	#0,A2_PIXEL			;start at 0,0 of source image
	move.l	#0,A1_PIXEL			;Y,X position to write data in destination area
	move.l	#$0014000C,B_COUNT		;object size is 24 x 20, data is 16 bits per pixel, so data size is 12 x 20
	move.l	#$0001FFF4,A1_STEP		;1 in Y step size, negative width in X step size
	move.l	#UPDA1|SRCEN|LFU_A|LFU_AN,B_CMD	;turn on blitter

	cmp.b	#$FF,spec_tgt
	beq.b	.30						;don't change direction
	bsr		get_tr_dir
.30:	move.l	#TRACER_SPEED,d0
	bra		mv_spec
m_beam::
	move.l	#BEAM_SPEED,d0				;set this for mv_spec
	cmp.w	#BEAM_TIME,beamtime
	bge		mv_spec					;if beam timer has expires, move the beam to the right
	addq.w	#1,beamtime
	cmp.w	#BEAM_IWIDTH,specweap+O_IWIDTH
	bge.b	.20						;if beam is at maximum width, keep it at that size
	addq.w	#2,specweap+O_IWIDTH		;keep making beam wider
.20:	move.w	player+O_YPOS,specweap+O_YPOS
	add.w	#BEAM_Y,specweap+O_YPOS		;keep beam attached to player until it is full width
	move.w	player+O_XPOS,specweap+O_XPOS
	add.w	#BEAM_X,specweap+O_XPOS		;keep beam attached to player until it is full width
	rts
m_ring::
	addq.w	#1,ringstep
	cmp.w	#RING_STEPS,ringstep
	blt.b	.10
	move.w	#0,ringstep
	addq.w	#1,ringcnt
	cmp.w	#RING_CNT,ringcnt
	bge		spec_off
.10:
	move.w	ringstep,d0
	lsl.w	#2,d0					;2 bytes for xpos, 2 bytes for ypos for each ringstep
	lea		ringoffs,a0
	move.w	player+O_XPOS,d1
	add.w	(a0,d0.w),d1				;horizontal distance from player ship
	move.w	d1,specweap+O_XPOS
	move.w	player+O_YPOS,d2
	add.w	2(a0,d0.w),d2				;vertical distance from player ship in half lines
	move.w	d2,specweap+O_YPOS
	rts
m_flash::								;animate the flash
	addq.w	#1,flshtime
	cmp.w	#FLASH_TIME,flshtime
	bge		spec_off					;turn off flash when time runs out
	move.w	flshtime,d0
	and.w	#1,d0
	bne.b	.50
	and.b	#$7F,specflsh+O_TYPE
	rts
.50:	or.b		#DELETE_OBJ,specflsh+O_TYPE
	rts

m_shield::
	addq.w	#1,shldtime
	cmp.w	#SHIELD_TIME,shldtime		;compare timer to time limit
	bge		spec_off					;turn off special weapon
	move.w	player+O_YPOS,specweap+O_YPOS
	add.w	#SHLD_Y,specweap+O_YPOS		;keep shield with player if player moves
	move.w	player+O_XPOS,specweap+O_XPOS
	add.w	#SHLD_X,specweap+O_XPOS		;keep shield with player if player moves
	bsr		setshld					;match the player ship if it turns
	rts


get_tr_dir::						;get tracer direction
	move.l	#0,d0
	move.b	spec_tgt,d0
	mulu		#OBJ_SIZE,d0
	lea		enemy0,a0
	adda.l	d0,a0				;add target * OBJ_SIZE to first object address
	tst.b	O_TYPE(a0)
	bpl.b	.10					;use this enemy as the target
	move.b	#$FF,spec_tgt
	rts
.10:
	move.w	#0,d3				;init quadrant number
	move.w	O_XPOS(a0),d1			;get enemy xpos
	add.w	O_DWIDTH(a0),d1		;add dwidth (width / 4) so tracer goes toward middle of enemy
	sub.w	specweap+O_XPOS,d1		;enemy xpos - tracer xpos
	bpl.b	.20
	neg.w	d1					;get absolute value of horiz distance
	addq.w	#2,d3				;horiz dir is right, use right quadrants
.20:
	move.w	O_YPOS(a0),d2
	add.w	O_HEIGHT(a0),d2		;add height (height in pixels is height / 2 in halflines)
	sub.w	specweap+O_YPOS,d2		;enemy ypos - tracer ypos
	bpl.b	.30
	neg.w	d2					;get absolute value of vert distance
	addq.w	#4,d3				;horiz dir is down, use lower quadrants
.30:
	bsr		got_quad				;sets d0 to offset for track_dirs
	lea		track_dirs,a5
	move.b	(a5,d0.w),spec_dir		;get enemy direction to tracer
	addq.b	#8,spec_dir
	and.b	#$F,spec_dir			;make sure direction is 0 - 15
.90:	rts

spec_collisions::
	tst.b	specweap+O_TYPE
	bmi.b	.90					;if negative, weapon is not active

	move.w	#0,d6				;enemy counter
	lea		enemy0,a1				;first enemy object
	lea		en_collwh,a2
	move.w	specweap+O_XPOS,d0		;initialize right edge to special weapon xpos
	move.w	d0,d1				;initialize left edge to special weapon xpos
	move.w	specweap+O_YPOS,d2		;initialize bottom edge to special weapon ypos
	move.w	d2,d3				;initialize top edge to special weapon ypos
	move.w	specweap+O_DESC,d4
	bmi		msexp_coll
	cmp.w	#FLASH,d4
	bne.b	.50
	cmp.w	#1,flshtime
	bne.b	.90
.50:	lsl.w	#2,d4				;special weapon type * 4
	lea		s_coll_addr,a4			;addresses of collision routines
	move.l	(a4,d4.w),a4			;get address of collision routine
	jmp		(a4)
.90:	rts

beamcoll::
	move.w	specweap+O_IWIDTH,d4
	lsl.w	#3,d4				;8 pixels per iwidth
	add.w	d4,d0				;add width to xpos to get right edge (left edge is already xpos)
	add.w	#BEAM_COLL_B,d2		;add to ypos to get bottom edge (top edge is already ypos)
	move.w	#BEAM_DAMAGE,d7		;amount of damage to enemy
	bra		s_coll
boltcoll::
	add.w	#BOLT_COLL_R,d0		;add to xpos to get right edge
	add.w	#BOLT_COLL_L,d1		;add to xpos to get left edge
	move.w	specweap+O_HEIGHT,d4
	add.w	d4,d2				;add current height to ypos
	add.w	d4,d2				;add current height to ypos again because its halflines to get bottom edge
	move.w	#BOLT_DAMAGE,d7		;amount of damage to enemy
	bra		s_coll
magcoll::
	add.w	#MAGNET_COLL_R,d0		;add to xpos to get right edge
	add.w	#MAGNET_COLL_L,d1		;add to xpos to get left edge
	add.w	#MAGNET_COLL_B,d2		;add to ypos to get bottom edge
	add.w	#MAGNET_COLL_T,d3		;add to ypos to get top edge
	move.w	#MAGNET_DAMAGE,d7		;amount of damage to enemy
	bra		s_coll
ringcoll::
	add.w	#RING_COLL_R,d0		;add to xpos to get right edge
	add.w	#RING_COLL_L,d1		;add to xpos to get left edge
	add.w	#RING_COLL_B,d2		;add to ypos to get bottom edge
	add.w	#RING_COLL_T,d3		;add to ypos to get top edge
	move.w	#RING_DAMAGE,d7		;amount of damage to enemy
	bsr		s_coll

;D0, D1, D2, D3 set to ring left, right, top, bottom
	move.w	#(MAX_ENEMY_SHOTS-1),d6	;count enemy shots
	lea		en_shot0,a1			;first enemy shot object
	lea		en_sh_width,a2			;table of shot widths
	lea		en_sh_ht,a3			;table of shot heights
.30:
	tst.b	O_TYPE(a1)			;see if enemy shot is active
	bmi.b	.70					;check next enemy shot if not active

	move.w	O_XPOS(a1),d4			;get enemy shot xpos
	cmp.w	d0,d4				;compare ring xpos + width to enemy shot xpos (d4)
	bge.b	.70					;if enemy shot xpos > ring xpos + width, exit

	move.w	O_DESC(a1),d5			;get enemy shot type
	lsl.w	#1,d5				;2 bytes for each width in the table
	add.w	(a2,d5.w),d4			;add width of enemy shot to its xpos
	cmp.w	d1,d4				;compare ring right to enemy shot right (d4)
	blt.b	.70					;if enemy shot right < ring right, exit

	move.w	O_YPOS(a1),d4			;get enemy shot ypos
	cmp.w	d2,d4				;compare ring bottom to enemy shot ypos
	bge.b	.70					;if enemy shot ypos >= ring bottom, exit

	add.w	(a3,d5.w),d4			;add height of enemy shot to its ypos (d5 is already shot type * 2)
	add.w	(a3,d5.w),d4			;add height again to make it halflines
	cmp.w	d3,d4				;compare ring bottom (d3) to enemy shot bottom (d4)
	blt.b	.70					;if enemy shot bottom < ring bottom, exit

	or.b		#DELETE_OBJ,O_TYPE(a1)	;turn off enemy shot
.70:
	adda.l	#OBJ_SIZE,a1			;next object header
	dbra		d6,.30				;enemy shot counter
	rts

misscoll::
	add.w	#MISS_COLL_R,d0		;add to xpos to get right edge
	add.w	#MISS_COLL_L,d1		;add to xpos to get left edge
	add.w	#MISS_COLL_B,d2		;add to ypos to get bottom edge
	add.w	#MISS_COLL_T,d3		;add to ypos to get top edge
	move.w	#MISSILE_DAMAGE,d7		;amount of damage to enemy
	bra		s_coll
msexp_coll::
	add.w	#MISS_EXP_COLL_WD,d0	;add collision width to xpos to get right edge
	add.w	#MISS_EXP_COLL_HT,d2	;add collision height in half lines to get bottom edge
	move.w	#MISSEXP_DAMAGE,d7		;amount of damage to enemy
	bra		s_coll
shldcoll::
	add.w	#SHIELD_COLL_R,d0		;add to xpos to get right edge
	add.w	#SHIELD_COLL_L,d1		;add to xpos to get left edge
	add.w	#SHIELD_COLL_B,d2		;add to ypos to get bottom edge
	add.w	#SHIELD_COLL_T,d3		;add to ypos to get top edge
	move.w	#SHIELD_DAMAGE,d7		;amount of damage to inflict
	bra		s_coll

s_coll::
;a1 points to enemy object header
;a2 points to en_collwh table
;a3 points to en_coladd table
;d0 = right edge
;d1 = left edge
;d2 = bottom edge
;d3 = top edge
;d6 = enemy number
;d7 = amount of damage to inflict
.10:	tst.b	O_TYPE(a1)			;see if enemy is active
	bmi.b	.70					;check next enemy if not active
	move.w	O_DESC(a1),d5			;enemy is an explosion if >= $80
	bmi.b	.70
	lsl.w	#2,d5				;4 bytes for each width and height

	move.w	O_XPOS(a1),d4			;get enemy xpos
	add.w	(a3,d5.w),d4			;add amount to get left edge
	cmp.w	d0,d4				;compare special weapon right edge (d0) to to enemy xpos (d4)
	bge.b	.70					;if enemy xpos >= special weapon right edge, exit

	add.w	(a2,d5.w),d4			;add amount to get right edge
	cmp.w	d1,d4				;compare special weapon left edge (d1) to enemy xpos + width (d4)
	blt.b	.70					;if enemy xpos + width < special weapon left edge, exit

	move.w	O_YPOS(a1),d4			;get enemy ypos
	add.w	2(a3,d5.w),d4			;add amount to get top edge
	cmp.w	d2,d4				;compare special weapon bottom edge (d2) to enemy ypos (d4)
	bge.b	.70					;if enemy ypos >= special weapon bottom edge, exit

	add.w	2(a2,d5.w),d4			;add height of enemy to its ypos (d5 is already enemy type * 4)
	cmp.w	d3,d4				;compare special weapon top edge (d3) to enemy ypos + height
	blt.b	.70
	bsr		damage_enemy			;if enemy ypos + height < special weapon top edge, exit -- otherwise collision occurred
	move.w	#1,d7				;set flag for traccoll to show that enemy was hit
	bra.b	.90

.70:	adda.l	#OBJ_SIZE,a1			;next object header
	add.w	#1,d6
	cmp.w	#TOTAL_ENEMIES,d6
	blt.b	.10
	move.w	#0,d7				;clear damage amount if no enemy was hit (traccoll needs to know this)
.90:	rts

traccoll::
	add.w	#TRACER_COLL_R,d0		;add to xpos to get right edge
	add.w	#TRACER_COLL_L,d1		;add to xpos to get left edge
	add.w	#TRACER_COLL_B,d2		;add to ypos to get bottom edge
	add.w	#TRACER_COLL_T,d3		;add to ypos to get top edge
	move.w	#TRACER_DAMAGE,d7		;amount of damage to enemy

	bsr		s_coll
	tst.w	d7					;see if enemy was hit
	beq.b	.90
	move.w	d6,spec_hit			;the enemy number that was hit
	move.w	#TRACER_SND,d0
	move.w	specweap+O_XPOS,d1		;xpos to determine pan value
	bsr		playsnd				;d0 = sample number, d1 = sound xpos
;if tracer hit something, get a new target
	add.b	#8,spec_dir			;bounce in opposite direction in case there is no next target
	and.b	#$F,spec_dir			;direction must be 0 - 15
	move.w	#0,d5				;count enemies
	move.w	spec_hit,d0
	lea		enemy0,a5
	lea		en_tractg,a1
	lea		en_action,a6
.25:	tst.b	O_TYPE(a5)
	bmi.b	.30					;skip if delete flag is on
	move.w	O_DESC(a5),d1			;enemy is an explosion if >= $80
	bmi.b	.30
	cmp.b	#EN_DYING,(a6,d5.w)		;check en_action
	beq.b	.30					;don't target a dying enemy
	cmp.w	d0,d5				;see if this was the last enemy that was hit
	beq.b	.30					;don't target the enemy that was hit last
	cmp.b	#1,(a1,d1.w)			;1 if enemy can be a target for the tracer
	bne.b	.30
	move.b	d5,spec_tgt			;use this enemy number as the first target	
	rts
.30:	adda.l	#OBJ_SIZE,a5			;next enemy object
	addq.w	#1,d5				;next enemy
	cmp.w	#TOTAL_ENEMIES,d5
	blt.b	.25
	move.b	#$FF,spec_tgt			;$FF as target means there were no enemies
.90:	rts

flshcoll::
.10:	tst.b	O_TYPE(a1)			;see if enemy is active
	bmi.b	.50					;check next enemy if not active
	tst.w	O_DESC(a1)			;enemy is an explosion if >= $80
	bmi.b	.50

	move.w	#FLASH_DAMAGE,d7		;amount of damage to enemy
	bsr		damage_enemy
.50:
	adda.l	#OBJ_SIZE,a1			;next object header
	addq.w	#1,d6
	cmp.w	#TOTAL_ENEMIES,d6
	blt.b	.10
	rts


f_cutr::
	tst.b	cutter+O_TYPE
	bpl.b	.90
	move.w	#0,cutrtime
	and.b	#$7F,cutter+O_TYPE
	move.w	#-60,cutter+O_XPOS
	move.w	#-60,cutrfrmx
	move.w	#SCRN_TOP+218,cutrfrmy
	move.w	#0,cutrfrmc
	move.w	#40,cutrrad
	move.w	#8,cutrthet
.90:	rts

mv_cutr::
	tst.b	cutter+O_TYPE
	bmi.b	.90					;if negative, cutter is not active
.10:
	cmp.w	#CUTR_TIME,cutrtime
	beq.b	.50
	tst.w	cutrfrmx
	bmi.b	.20
	cmp.w	#120,cutrfrmx
	bge.b	.30
.20:	add.w	#1,cutrfrmx
	add.w	#1,cutter+O_XPOS
	cmp.w	#166,cutrrad
	bge.b	.30
	add.w	#1,cutrrad
.30:	add.w	#1,cutrtime
	bra		cutr_pat
.50:	add.w	#3,cutter+O_XPOS
	cmp.w	#SCRN_RIGHT,cutter+O_XPOS
	blt.b	.90
	move.w	#0,cutrtime
	or.b		#DELETE_OBJ,cutter+O_TYPE
.90:	rts

cutr_pat::
;move cutter according to formula
	move.w	cutrfrmc,d3
	add.w	#1,d3
	cmp.w	#(2048/8),d3			;compare limit to counter
	blt.b	.20
	move.w	#0,d3				;reset pattern moves counter
.20:	move.w	d3,cutrfrmc			;save new en_formc value
	move.w	cutrrad,d4			;set radius in D4
	move.w	cutrthet,d5			;set theta in D5
	move.w	cutrfrmx,d1			;set xpos in D1
	move.w	cutrfrmy,d2			;set ypos in D2
	bsr		do_wave				;must have D1-D5 set
	move.w	d2,cutter+O_YPOS
	rts



fire_cut::
	tst.w	cutter+O_XPOS
	bmi.b	.90					;don't fire until all the way on screen
	cmp.w	#CUTR_TIME,cutrtime
	beq.b	.90
	moveq.l	#(CUTR_BULLETS-1),d6
	lea		cutshot0,a0			;first cutter bullet object
.10:
	tst.b	O_TYPE(a0)
	bpl.b	.20					;if 0, bullet is already active
	and.b	#$7F,O_TYPE(a0)		;turn on the bullet object
	move.w	cutter+O_XPOS,O_XPOS(a0)
	add.w	#CUTR_BULLET_XPOS,O_XPOS(a0)	;object xpos
	lea		bulfirst,a1
	move.b	(1,a1),O_FIRSTPIX(a0)	;get firstpix for bullet power 1
	move.w	cutter+O_YPOS,O_YPOS(a0)
	add.w	#CUTR_BULLET_YPOS,O_YPOS(a0)
	lea		bulheight+2,a1			;bullet power 1
	move.w	(a1),O_HEIGHT(a0)		;bullet height
	lea		buldwid+2,a1
	move.w	(a1),O_DWIDTH(a0)
	move.w	(a1),O_IWIDTH(a0)
	rts
.20:	adda.l	#OBJ_SIZE,a0
	dbra		d6,.10
.90:	rts

mv_cutsh::
	move.w	#(CUTR_BULLETS-1),d6
	lea		cutshot0,a1
	move.w	#$FFE8,d2				;left limit
	move.w	#SCRN_RIGHT,d3			;right limit
	move.w	#SCRN_TOP-10,d4		;top limit
	move.w	#SCRN_BOTTOM,d5		;bottom limit
.10:	tst.b	O_TYPE(a1)
	bmi.b	.80					;if negative, bullet is not active
	move.l	#(4*2)+(CUTR_BULLET_SPEED*32),d0	;direction 4 * 2 bytes for each direction in spds_h and spds_v tables + 1 extra speed * 32
	bsr		mv_obj2				;don't scroll with background
	tst.b	limitflag
	beq.b	.80
.70:	or.b		#DELETE_OBJ,O_TYPE(a1)	;turn off bullet

.80:	adda.l	#OBJ_SIZE,a1			;next bullet object
	dbra		d6,.10
	rts

