; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί Object Handler/Scheduler						   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: None.							   Ί
; Ί  Exit: Nothing is protected.					   Ί
; Ί  Used: d0-d7/a0-a6							   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Everything to do with OBJECTS happens here!				   Ί
; Ί 									   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ


; MASTER OBJECT HANDLER !!


BuildActiveObjectMap	lea	OBJECT_RAM,a0
			lea	ActiveObjectRam,a1
;			lea	ActiveObjectNumber,a2

			move.w	#MaxObs-1,d1
			move.w	#-1,d2
.l1			btst.b	#ob_active,OB_Flag1(a0)
			beq.s	.nxt
;			move.w	d1,(a2)+
			move.l	a0,(a1)+
			addq.w	#1,d2
.nxt			lea	OB_DATA_SIZE(a0),a0
			dbra	d1,.l1
			move.w	d2,ActiveObjectCnt
			rts


HandleObjects		bsr	BuildActiveObjectMap
			tst.w	ActiveObjectCnt
			bmi.s	.x
			
			tst.b	first_pass
			bne.s	.ok
   			bsr	GetScreenCenterClips		;check if x is out of bounds
			bra	.frm0a
.x			rts

.ok			btst.b	#0,second
			beq.s	.frm0

; - Frame #1 ---------------------------------------------------------------

.frm1			bsr	Enemy2PlayerATTACK

			move.b	#1,linker
			move.l	#SprtAttr_RAM,_SprtAttr_RAM	;a2=sprt attribute table	

			lea	ActiveObjectRam,a5

			move.w	ActiveObjectCnt,d0
.l1			movem.l	d0/a5,-(sp)
			move.l	(a5),a0
			bsr	LogicOb				;do the logic/control for this object
			bsr	MoveOb				;move this object
			bsr	AnimOb				;animate this object
			bsr	BuildOb				;physically build this object
			btst.b	#ob_kill,OB_Flag2(a0)		;is object active
			beq.s	.1				;no: skip it
			bsr	TidyKilledObject
.1			movem.l	(sp)+,d0/a5
			addq.l	#4,a5
			dbra	d0,.l1
			clr.b	-8+link(a2)			;zero last link
			bra	ClrSprend			;wipe unused sprites off screen


; - Frame #0 ---------------------------------------------------------------

.frm0			bsr	GetScreenCenterClips		;check if x is out of bounds
			bsr	HandlePlayerCollision		;Handle collision detection
			
.frm0a			move.b	#1,linker
			move.l	#SprtAttr_RAM,_SprtAttr_RAM	;a2=sprt attribute table	

			lea	ActiveObjectRam,a5

			move.w	ActiveObjectCnt,d0
.l1a			movem.l	d0/a5,-(sp)
			move.l	(a5),a0
			bsr	LogicOb				;do the logic/control for this object
			bsr	MoveOb				;move this object
			bsr	KillOb				;handle objects going off screen
			bsr	AnimOb				;animate this object
			bsr	BuildOb				;physically build this object
			btst.b	#ob_kill,OB_Flag2(a0)		;is object active
			beq.s	.1a				;no: skip it
			bsr	TidyKilledObject
.1a			movem.l	(sp)+,d0/a5
			addq.l	#4,a5
			dbra	d0,.l1a
			clr.b	-8+link(a2)			;zero last link
			bra	ClrSprend			;wipe unused sprites off screen


HandleObjectsSORTED	move.b	#1,linker
			move.l	#SprtAttr_RAM,_SprtAttr_RAM	;a2=sprt attribute table	
			
			lea	Sort_D,a3
			
			moveq	#MaxObs-1,d1
.l1			move.l	d1,-(sp)

			lea	OBJECT_RAM,a0			;point to objects RAM
			move.w	(a3)+,d0
			bmi.s	.nxtob
			move.w	d0,d2
			asl.w	#6,d2
			add.w	d2,a0
			lsr.w	#1,d0

			btst.b	#ob_active,OB_Flag1(a0)		;is object active
			beq.s	.nxtob				;no: skip it
			
			move.l	a3,-(sp)
			bsr	LogicOb				;do the logic/control for this object
			bsr	MoveOb				;move this object
			bsr	KillOb				;handle objects going off screen
			btst.b	#ob_null,OB_Flag2(a0)		;no need to animate/dma invisible objects
			bne.s	.nxtob
			btst.b	#ob_composite,OB_Flag5(a0)
			bne	.skp1
			bsr	AnimOb				;animate this object
.skp1			bsr	BuildOb				;physically build this object
			move.l	(sp)+,a3

.nxtob			move.l	(sp)+,d1
			dbra	d1,.l1

			clr.b	-8+link(a2)			;zero last link
			
			bra	ClrSprend			;wipe unused sprites off screen


; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί Universal, SINGLE OBJECT Animation Routine				   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: D0 = Object number.						   Ί
; Ί  Exit: N/A								   Ί
; Ί  Used: D0-D7/A0-A6 (protected)					   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Author: Chris Shrigley						   Ί
; Ί   Date: 2/15/94							   Ί
; Ί    Rev: 6/94							   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ
;
; Data structure :
; 
; Seq#	anm	Label.l,Duration.b,Flags.b	;straight animantion data (flags,frame #,animation duration)
; 	anm	AJmp.w,Seq#.l 			;Jump directive (reloads anim pointer with Seq#)						
; 	anm	ARep.w				;Repeat animation (loop)								
; 	anm	AEnd.w				;End animation (stop)									
; 	anm	APat.w,Rout.l			;Patch to any subroutine								
; 	anm	AMov.w,Flags.b,pad.b,Xspd.w,Yspd.w,Xacc.w,Yacc.w	;Physical movement of animated object (up x pixels) 					
; 	anm	AJsr.w,Seq#.l 			;JSR directive (reloads anim pointer with Seq#) returns to original Seq#
;	anm	ARts.w				;Used with AJsr (returns to old Seq# and position)						
; 						;NB. JSR's are not stacked so recursive JSR cannot be done.
;	anm	ANew.w,Data.l			;init a new animation sequence
;
;
; Sample animation : (not a good example)
;
; Seq1	anm	jmpfrm1,4,%00000000
;	anm	jmpfrm2,4,%00000000
;	anm	AJsr,Seq2
;	anm	jmpfrm3,4,%00000000
;	anm	AEnd
;
; Seq2	anm	jmpkickfrm1,4,%00000000
;	anm	ARts
;



AJmp			equ	-1
ARep			equ	-2
AEnd			equ	-3
APat			equ	-4
AMov			equ	-5
AJsr			equ	-6
ARts			equ	-7
ANew			equ	-8
AMov2			equ	-9	;move player/scroll
APau			equ	-10
AVar1			equ	-11
AVar2			equ	-12
AVar3			equ	-13
AVar4			equ	-14
ALoop			equ	-15
AInit			equ	-16
AMovDF			equ	-17	;move player/scroll in flip direction

M2lft			equ	0
M2rte			equ	1
M2up			equ	2
M2dn			equ	3

MDFlftrte		equ	0
MDFupdn		 	equ	1



AnimOb			tst.l	OB_AnSequence(a0)		;do we have a sequence?
			beq	.exit

			move.b	OB_AnCmp(a0),d1
			beq.s	.no_patch			;1st time around
			cmp.b	OB_AnCnt(a0),d1
			ble.s	.next
			addq.b	#1,OB_AnCnt(a0)
			rts
											
.next			clr.b	OB_AnCnt(a0)
			;tst.l	OB_AnPatch(a0)			;have we got a patch to execute?
			;beq.s	.no_patch			;no: exit
			;move.l	OB_AnPatch(a0),a5		;rack it up
			;clr.l	OB_AnPatch(a0)			;clr the entry
			;jmp	(a5)				;do the patch

.no_patch		move.w	OB_AnDex(a0),d1			;index
			move.l	OB_AnSequence(a0),a6		;sequence vec
			add.w	d1,a6
			move.w	0(a6),d2			;data
			beq.s	.doANM
			move.w	d2,d3
			neg.w	d3
			asl.w	#2,d3
			jmp	.AnimRoutine(pc,d3.w)
			
.AnimRoutine		bra	.doNULL
			bra	.doJMP			
			bra	.doREP
			bra	.doEND
			bra	.doPAT
			bra	.doMOV
			bra	.doJSR
			bra	.doRTS
			bra	.doNEW
			bra	.doMOV2
			bra	.doPAU
			bra	.doVAR1
			bra	.doVAR2
			bra	.doVAR3
			bra	.doVAR4
			bra	.doLOOP
			bra	.doINIT
			bra	.doMOVDF
		
.doANM			bclr.b	#ob_tidy,OB_Flag5(a0)		;clr tidy bit
			move.l	2(a6),OB_AnSeqLab(a0)		;a1=frame (anm >>Label.l<<)
			move.b	6(a6),OB_AnCmp(a0)		;duration
			move.b	7(a6),OB_AnFlags(a0)		;flags
			bset.b	#ob_newdma,OB_Flag5(a0)
			btst.b	#ob_anxflptog,OB_AnFlags(a0)
			beq.s	.n1
			eor.b	#_ob_xflp,OB_Flag1(a0)
.n1			btst.b	#ob_anyflptog,OB_AnFlags(a0)
			beq.s	.n2
			eor.b	#_ob_yflp,OB_Flag1(a0)
.n2			bra	bump8				

.doNULL			bra	bump2

.doJMP			move.l	2(a6),OB_AnSequence(a0)		;set new sequence pointer
			;drop thru to index clr

.doREP			clr.w	OB_AnDex(a0)			;clr index
			bra	.no_patch

.doEND			clr.l	OB_AnSequence(a0)   		;clr sequence pointer
			clr.w	OB_AnDex(a0)			;clr index
			bra	.exit

.doPAT			move.l	2(a6),OB_AnPatch(a0)		;set patch routine
			bra	bump6

.doMOV			move.b 2(a6),OB_MoveFlags(a0)		;store Flags
			move.w 4(a6),OB_Xspd(a0)		;store X speed
			move.w 6(a6),OB_Yspd(a0)		;store Y speed
			move.w 8(a6),OB_Xacc(a0)		;store X acc
			move.w 10(a6),OB_Yacc(a0)		;store Y acc
			bra	bump12

.doJSR			move.l	OB_AnSequence(a0),OB_AnSeqTemp(a0)	;save sequence
			move.w	OB_AnDex(a0),OB_AnDexTemp(a0)		;and index
			bra	.doJMP
		
.doRTS			move.l	OB_AnSeqTemp(a0),OB_AnSequence(a0)	;restore sequence
			move.w	OB_AnDexTemp(a0),OB_AnDex(a0)		;and index
			bra	bump6
		
.doNEW			move.l	2(a6),a1				;setup a new animation
			bsr	SetNewAnim_Q
			bra	.no_patch

.doMOV2			move.b	3(a6),d2
			ext.w	d2
			cmp.b	#M2lft,2(a6)				;move the sprite object NOW
			beq.s	.m2l
			cmp.b	#M2rte,2(a6)
			beq.s	.m2r
			cmp.b	#M2up,2(a6)
			beq.s	.m2u
.m2d			add.w	d2,OB_Ypos(a0)
			bclr.b	#ob_movupdn,OB_Flag5(a0)
			bsr	bump4
			bra	.no_patch
.m2l			sub.w	d2,OB_Xpos(a0)
			bset.b	#ob_movlftrte,OB_Flag5(a0)
			bsr	bump4
			bra	.no_patch
.m2r			add.w	d2,OB_Xpos(a0)
			bclr.b	#ob_movlftrte,OB_Flag5(a0)
			bsr	bump4
			bra	.no_patch
.m2u			sub.w	d2,OB_Ypos(a0)
			bset.b	#ob_movupdn,OB_Flag5(a0)
			bsr	bump4
			bra	.no_patch
			
.doPAU			move.b	2(a6),OB_AnCmp(a0)		;force pause
			bra	bump4

.doVAR1			move.b	2(a6),OB_EventVar1(a0)
			bsr	bump4					
			bra	.no_patch
.doVAR2			move.b	2(a6),OB_EventVar2(a0)
			bsr	bump4					
			bra	.no_patch
.doVAR3			move.b	2(a6),OB_EventVar3(a0)
			bsr	bump4					
			bra	.no_patch
.doVAR4			move.b	2(a6),OB_EventVar4(a0)
			bsr	bump4
			bra	.no_patch
					
.doLOOP			tst.b	OB_AnLoop(a0)
			bne.s	.dl1
    			move.b	6(a6),OB_AnLoop(a0)
.dl1			subq.b	#1,OB_AnLoop(a0)
			beq.s	.dl2
			move.l	2(a6),OB_AnSequence(a0)		;set new sequence pointer
			clr.w	OB_AnDex(a0)			;clr index
			bsr	bump8
			bra	.no_patch
.dl2			bra	bump8
	
.doINIT			clr.w	OB_AnDex(a0)			;clr index
			clr.b	OB_AnLoop(a0)
			clr.l	OB_AnPatch(a0)	
			clr.w	OB_AnDex(a0)	
			clr.b	OB_AnFlags(a0)	
			clr.b	OB_AnCnt(a0)	
			clr.b	OB_EventVar1(a0)
			clr.b	OB_EventVar2(a0)
			clr.b	OB_EventVar3(a0)
			clr.b	OB_EventVar4(a0)
			bra	bump2

.doMOVDF		move.b	3(a6),d2				;move in direction faced
			ext.w	d2
			cmp.b	#MDFupdn,2(a6)
			beq.s	.mdfud
.mdflr			btst.b	#ob_xflp,OB_Flag1(a0)
			beq.s	.mdflr1
			sub.w	d2,OB_Xpos(a0)
			bset.b	#ob_movlftrte,OB_Flag5(a0)
			bra	.mdfx
.mdflr1			add.w	d2,OB_Xpos(a0)
			bclr.b	#ob_movlftrte,OB_Flag5(a0)
			bra	.mdfx
.mdfud			btst.b	#ob_yflp,OB_Flag1(a0)
			beq.s	.mdfud1
			add.w	d2,OB_Ypos(a0)
			bclr.b	#ob_movupdn,OB_Flag5(a0)
			bra	.mdfx
.mdfud1			sub.w	d2,OB_Ypos(a0)
			bset.b	#ob_movupdn,OB_Flag5(a0)
.mdfx			bsr	bump4
			bra	.no_patch

.exit			rts

bump12			moveq	#12,d1				;bump index by 12Bytes
			bra	bump_x
bump8			moveq	#8,d1				;bump index by 8Bytes
			bra	bump_x
bump6			moveq	#6,d1				;bump index by 6Bytes
			bra	bump_x
bump4			moveq	#4,d1 				;bump index by 4Bytes
			bra	bump_x
bump2			moveq	#2,d1 				;bump index by 2Bytes
bump_x			add.w	d1,OB_AnDex(a0)
			rts



; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί Universal, COMPOSITE OBJECT Animation Routine			   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: D0 = Object number.						   Ί
; Ί  Exit: N/A								   Ί
; Ί  Used: D0-D7/A0-A6 (protected)					   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Author: Chris Shrigley						   Ί
; Ί   Date: 12/29/94							   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ


AnimCompOb		rts



; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί OBJECT Builder							   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: a0=frame label.l						   Ί
; Ί  Exit: n/a								   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Author: Chris Shrigley						   Ί
; Ί   Date: 2/1/94							   Ί
; Ί    Rev: 6/94 .. 1/95 (to use Cary Hara' CHOP data format)		   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Build objects using all the data tables.				   Ί
; Ί   Create Sprite ATTR table (to be DMA'd by Vblank)			   Ί
; Ί   Create DMA script for DMAing all the data during the Vblank          Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

			rsreset
_NumSprts		rs.b	1
_NumBoxes		rs.b	1
_MinX			rs.w	1
_MinY			rs.w	1
_MaxX			rs.w	1
_MaxY			rs.w	1
_Sub_bump		rs.w	1
			rsreset
_SizeRaw		rs.b	1
_SizeMod		rs.b	1
_Wide			rs.w	1
_High			rs.w	1
_Pal			rs.w	1
_Xoff			rs.w	1
_Yoff			rs.w	1
_Coff			rs.l	1
_es			rs.w	0
_Sub_bump2		equ	_es-_Sub_bump


			;build h/w sprite attr tables
			;  x,y position, h/v flips, palette, pattern etc.
			;create DMA script to DMA char data to VRAM
			;  
BuildOb			btst.b	#ob_tidy,OB_Flag5(a0)
			bne	.exit

			move.w	OB_Xpos(a0),d1			;get and store x,y origin
			move.w	OB_Ypos(a0),d2

			btst.b	#ob_noclip,OB_Flag1(a0)
			bne.s	.noclip

			cmp.w	ClipLeft,d1
			blt	.exit
			cmp.w	ClipRight,d1
			bgt	.exit

.noclip			move.l	OB_AnSeqLab(a0),a1		;a1=frame (anm >>Label.l<<)
			move.l	_SprtAttr_RAM,a2
			move.l	OB_RefAnRam(a0),a3		;a3=RAM reference table
			
			move.l	OB_AnChrData(a0),d3		;source chr set
			add.l	_Coff+_Sub_bump(a1),d3		;get base of ROM char data (for this frame)
			move.l	d3,_ROM_A_T
			
			clr.w	OB_Priority
			btst.b	#ob_hiprior,OB_Flag2(a0)	;do priority stuff
			beq.s	.a
			move.w	#$8000,OB_Priority		;set this sprite hi priority

.a			clr.w	sdef_cnt			;clr running add
			
			moveq	#0,d7
			moveq	#0,d5
			move.b	_NumSprts(a1),d7		;get # of subsprites (loop)
			move.b	_NumBoxes(a1),OB_CBCount	;get # of collision boxes

.ploop			lea	_Sub_bump(a1),a1		;next sub sprite
			
			move.w	_VRAM_Adiv32(a3),d6		;VRAM addrs/32 = char #
			add.w	sdef_cnt,d6			;+running sprt count
			add.w	_Pal(a1),d6			;+palette
			or.w	OB_Priority,d6			;set this sprites priority
			
			move.b	_SizeRaw(a1),size(a2)		;store raw size in sprt attr
			move.b	_SizeMod(a1),d5			;+size to running sprt #
			add.w	d5,sdef_cnt
	
			move.w	d1,d4				;copy xy origin
			move.w	_Xoff(a1),d3			;mod from x,y offsets
			btst.b	#ob_xflp,OB_Flag1(a0)		;check xflip
			beq.s	.x1
			or.w	#$0800,d6			;set this sprite x flipped
			neg.w	d3				;adjust x for flip
			sub.w	_Wide(a1),d3
.x1			add.w	d3,d4
			btst.b	#ob_noscroll,OB_Flag5(a0)	;does scroll effect object
			bne.s	.nxs
			sub.w	map_x_p,d4			;yes: add in scrolls x
.nxs			add.w	#$80-$10,d4			;make 0,0 = top left of screen
			and.w	#$1ff,d4			
			bne.s	.2
			moveq	#1,d4				;none of that funky sega sprite masking
.2			move.w	d4,x_pos(a2)			;set x position

			move.w	d2,d4
			move.w	_Yoff(a1),d3			;mod from x,y offsets
			btst.b	#ob_yflp,OB_Flag1(a0)		;check yflip
			beq.s	.y1
			or.w	#$1000,d6			;set this sprite y flipped
			neg.w	d3				;adjust y for flip
			sub.w	_High(a1),d3
.y1			add.w	d3,d4
			btst.b	#ob_noscroll,OB_Flag5(a0)	;does scroll effect object
			bne.s	.nys
			sub.w	map_y_p,d4			;yes: add in scrolls x
.nys			add.w	#$80-$10,d4			;make 0,0 = top left of screen
			and.w	#$1ff,d4			
			move.w	d4,y_pos(a2)			;set y position

			move.w	d6,attr(a2)			;set pattern/attributes
			move.b	linker,link(a2)			;link

			lea	_Sub_bump2(a1),a1		;next sub sprite
			
			cmp.l	#SprtAttr_RAM_End-8,a2		;trap: out of h/w sprites
			bge.s	.overflow

			addq.l	#8,a2				;bump to next h/w sprite
			addq.b	#1,linker			;next link
			dbra	d7,.ploop			;loop for each sub sprite
			
			move.l	a2,_SprtAttr_RAM		;save a2 for next object 
			btst.b	#ob_flown,OB_Flag3(a0)
			beq	PullCollisionBoxes
			btst.b	#ob_newdma,OB_Flag5(a0)		;still set dma even if runout of sprites
			beq	PullCollisionBoxes
			bsr	QueueNewDMA
			bra	PullCollisionBoxes

.overflow		move.l	a2,_SprtAttr_RAM		;save a2 for next object 
			btst.b	#ob_flown,OB_Flag3(a0)
			beq	PullCollisionBoxes_O
			btst.b	#ob_newdma,OB_Flag5(a0)		;still set dma even if runout of sprites
			beq	PullCollisionBoxes_O
			bsr	QueueNewDMA
			bra	PullCollisionBoxes_O
.exit			rts


QueueNewDMA		bclr.b	#ob_newdma,OB_Flag5(a0)
			move.l	DMA_Stack,a6			;place entry in DMA Stack
			move.w	_VRAM_A(a3),-(a6)		;_VRAM_A(a3)=destination of DMA data	
			move.l	_ROM_A_T,d1			;_ROM_A(a3)=source of data to DMA / 2
			lsr.l	#1,d1
			move.l	d1,-(a6)
			move.w	sdef_cnt,d1			;sdef_cnt*16=length of data to DMA (.w)
			asl.w	#4,d1
			move.w	d1,-(a6)
			move.w	#_DMATransfer,-(a6)		;flag this data package is a dma transfer
			move.l	a6,DMA_Stack
			rts


PullCollisionBoxes_O	move.l	OB_CollisionRAM(a0),a4		;Overflow collsion boxes
			move.l	#$88888888,OB_CBox1X1(a4)	
			move.l	#$88888888,OB_CBox1X2(a4)
			move.l	#$88888888,OB_CBox2X1(a4)		
			move.l	#$88888888,OB_CBox2X2(a4)
			move.l	#$88888888,OB_CBox3X1(a4)		
			move.l	#$88888888,OB_CBox3X2(a4)
			tst.b	OB_CBCount
			bne.s	.ok
.x			rts
.ok			bmi.s	.x
			addq.l	#2,a1				;search
			cmp.l	#"CBOX",(a1)
			bne.s	.ok
   			addq.l	#4,a1
  			bra	PCB_Bit

PullCollisionBoxes	move.l	OB_CollisionRAM(a0),a4
			move.l	#$88888888,OB_CBox1X1(a4)		;clr collision boxes
			move.l	#$88888888,OB_CBox1X2(a4)
			move.l	#$88888888,OB_CBox2X1(a4)		
			move.l	#$88888888,OB_CBox2X2(a4)
			move.l	#$88888888,OB_CBox3X1(a4)		
			move.l	#$88888888,OB_CBox3X2(a4)
			tst.b	OB_CBCount
			bne.s	.ok
			rts
.ok			lea	14(a1),a1
  			
PCB_Bit			move.b	OB_CBCount,d1
			bsr	pb1
			subq.b	#1,d1
			beq.s	.x
			lea	14(a1),a1
			bsr	pb1
			subq.b	#1,d1
			beq.s	.x
			lea	14(a1),a1
			bsr	pb1
			subq.b	#1,d1
			beq.s	.x
			lea	14(a1),a1
			bsr	pb1
.x			rts

pb1			move.w	0(a1),d3
			move.w	2(a1),d4
			move.w	4(a1),d5
			move.w	6(a1),d6
			move.w	8(a1),d7
			asl.w	#3,d7

Cb2			btst.b	#ob_xflp,OB_Flag1(a0)
			beq	.1
			neg.w	d3
			neg.w	d5
			move.w	OB_Xpos(a0),d2
			tst.w	d3
			bpl.s	.aa
			neg.w	d3
			sub.w	d3,d2
			bra	.ab
.aa			add.w	d3,d2			
.ab			move.w	d2,OB_CBox1X2(a4,d7.w)
			move.w	OB_Xpos(a0),d2
			tst.w	d5
			bpl.s	.aa2
			neg.w	d5
			sub.w	d5,d2
     			bra	.ab2
.aa2			add.w	d5,d2			
.ab2			move.w	d2,OB_CBox1X1(a4,d7.w)
			bra	.2
.1			move.w	OB_Xpos(a0),d2
			tst.w	d3
			bpl.s	.a
			neg.w	d3
			sub.w	d3,d2
			bra	.b
.a			add.w	d3,d2			
.b			move.w	d2,OB_CBox1X1(a4,d7.w)
			move.w	OB_Xpos(a0),d2
			tst.w	d5
			bpl.s	.a2
			neg.w	d5
			sub.w	d5,d2
     			bra	.b2
.a2			add.w	d5,d2			
.b2			move.w	d2,OB_CBox1X2(a4,d7.w)
			
.2			btst.b	#ob_yflp,OB_Flag1(a0)
			beq.s	.3
			neg.w	d4
			neg.w	d6
			move.w	OB_Ypos(a0),d2
			tst.w	d4
			bpl.s	.aa1
			neg.w	d4
			sub.w	d4,d2
			bra	.ab1
.aa1			add.w	d4,d2			
.ab1			move.w	d2,OB_CBox1Y2(a4,d7.w)
			move.w	OB_Ypos(a0),d2
			tst.w	d6
			bpl.s	.aa3
			neg.w	d6
			sub.w	d6,d2
			bra	.ab3
.aa3			add.w	d6,d2			
.ab3			move.w	d2,OB_CBox1Y1(a4,d7.w)
			rts
.3			move.w	OB_Ypos(a0),d2
			tst.w	d4
			bpl.s	.a1
			neg.w	d4
			sub.w	d4,d2
			bra	.b1
.a1			add.w	d4,d2			
.b1			move.w	d2,OB_CBox1Y1(a4,d7.w)
			move.w	OB_Ypos(a0),d2
			tst.w	d6
			bpl.s	.a3
			neg.w	d6
			sub.w	d6,d2
			bra	.b3
.a3			add.w	d6,d2			
.b3			move.w	d2,OB_CBox1Y2(a4,d7.w)
			rts


; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί Universal OBJECT Mover						   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: n/a								   Ί
; Ί  Exit: n/a								   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Moves objects based on ;						   Ί
; Ί OB_MoveFlags, OB_Xspd, OB_Yspd, OB_Xacc, OB_Yacc			   Ί
; Ί NOTE : OB_Xspd&OB_Yspd are WORD.  The HiByte=Actual speed		   Ί
; Ί        the LoByte=Fractional speed.					   Ί
; Ί 	   the speed must be devided by 256 to get actual speed		   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ


MoveOb			btst.b	#ob_noxmove,OB_MoveFlags(a0)	;dont store
			bne.s	.ov1
			move.w	OB_Xspd(a0),d1			;speed
			beq.s	.ov1				;=0 the do nothing
			lsr.w	#8,d1				;/256
			btst.b	#ob_movxdir,OB_MoveFlags(a0)	;move in which dir?
			beq.s	.rt
.lt			sub.w	d1,OB_Xpos(a0)			;left <
			bset.b	#ob_movlftrte,OB_Flag5(a0)
			bra	.ov1
.rt			add.w	d1,OB_Xpos(a0)			;right >
			bclr.b	#ob_movlftrte,OB_Flag5(a0)
			
.ov1			btst.b	#ob_noymove,OB_MoveFlags(a0)	;dont store
			bne.s	.ov2
			move.w	OB_Yspd(a0),d1			;speed
			beq.s	.nxtob				;=0 the do nothing
			lsr.w	#8,d1				;/256
			btst.b	#ob_movydir,OB_MoveFlags(a0)	;move in which dir?
			beq.s	.dn
.up			sub.w	d1,OB_Ypos(a0)			;up /\
			bset.b	#ob_movupdn,OB_Flag5(a0)
			bra	.ov2
.dn			add.w	d1,OB_Ypos(a0)			;down \/
			bclr.b	#ob_movupdn,OB_Flag5(a0)
			
.ov2			move.w	OB_Xacc(a0),d1			;any X speed mods?
			beq.s	.ov3			    	;no: skip
			btst.b	#ob_movxacc,OB_MoveFlags(a0)	;acc/decceleration?
			beq.s	.xacc
.xdecc			sub.w	d1,OB_Xspd(a0)			;deccelerate			
			bpl	.ov3
			clr.w	OB_Xspd(a0)
			bra	.ov3
.xacc			add.w	d1,OB_Xspd(a0)			;accelerate			
								
.ov3			move.w	OB_Yacc(a0),d1			;any Y speed mods?
			beq.s	.nxtob				;no: skip
			btst.b	#ob_movyacc,OB_MoveFlags(a0)	;acc/decceleration?
			beq.s	.yacc
.ydecc			sub.w	d1,OB_Yspd(a0)			;deccelerate		
			bpl	.nxtob
			clr.w	OB_Yspd(a0)
			bra	.nxtob
.yacc			add.w	d1,OB_Yspd(a0)			;accelerate		
			
.nxtob			rts


; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί OBJECT COLLISION ROUTINES						   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: d0=Object #							   Ί
; Ί  Exit: Collision flags set accordingly.				   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Universal object collision handler. These routines, compare collision  Ί
; Ί boxes and set flags and/or execute routines based on the outcome.	   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ


HandlePlayerCollision	move.l	Plr_Database,a1
			btst.b	#attkmode,OB_MasterMode(a1)
			bne.s	Player2EnemyATTACK
			btst.b	#grabmode,OB_MasterMode(a1)
			bne.s	Player2EnemyATTACK
			rts

Player2EnemyATTACK	move.l	OB_CollisionRAM(a1),a2
			bsr	GetAttackBox
			cmp.w	#$8888,d1
			beq.s	.x

			lea	ActiveObjectRam,a5

			move.w	ActiveObjectCnt,d0
.l1			movem.l	d0/a5,-(sp)
			move.l	(a5),a0
			
			cmp.l	Plr_Database,a0
			beq.s	.nxt
			btst.b	#ob_notect1,OB_Flag3(a0)	;disable sprt 2 sprt detection (0=no:1=yes)
			bne.s	.nxt
			btst.b	#ob_beinghit,OB_Flag1(a0)	;nme already being hit
			bne.s	.nxt
			
			move.l	OB_CollisionRAM(a0),a1		;enemies Collision RAM
			
			move.w	OB_CBox1X2(a1),d5		;test Plr CBox against NME CBox
			cmp.w	#$8888,d5
			beq.s	.nxt
			cmp.w	d5,d1
			bgt.s	.nxt
			move.w	OB_CBox1Y2(a1),d6		;test Plr CBox against NME CBox
			cmp.w	d6,d2
			bgt.s	.nxt
			move.w	OB_CBox1X1(a1),d5		;test Plr CBox against NME CBox
			cmp.w	d5,d3
			blt.s	.nxt
			move.w	OB_CBox1Y1(a1),d6		;test Plr CBox against NME CBox
			cmp.w	d6,d4
			blt.s	.nxt
		
			bsr	SetNmeHitSide
			
.nxt			movem.l	(sp)+,d0/a5
			addq.l	#4,a5
			dbra	d0,.l1
.x			rts


Enemy2PlayerATTACK	move.l	Plr_Database,a3
			move.l	OB_CollisionRAM(a3),a1
			move.w	OB_CBox1X1(a1),d1		;get plr Collision box
			cmp.w	#$8888,d1			;there isn't one
			beq	.x				;so exit
			move.w	OB_CBox1X2(a1),d2		
			move.w	OB_CBox1Y1(a1),d3		
			move.w	OB_CBox1Y2(a1),d4		
			
			lea	ActiveObjectRam,a5

			move.w	ActiveObjectCnt,d0
.l1			movem.l	d0/a5,-(sp)
			move.l	(a5),a0
			
			cmp.l	Plr_Database,a0
			beq.s	.nxt
			btst.b	#ob_notect1,OB_Flag3(a0)	;disable sprt 2 sprt detection (0=no:1=yes)
			bne.s	.nxt
			btst.b	#ob_beinghit,OB_Flag1(a3)	;plr being hit?
			bne.s	.nxt
			
			move.l	OB_CollisionRAM(a0),a2		;enemies Collision RAM
			move.w	OB_CBox3X1(a2),d5		;get nme attack box	
			cmp.w	#$8888,d5			;there isn't one
			beq.s	.nxt				;so next enemy
			cmp.w	d5,d2				;cmp nme x1 with plr x2
			blt.s	.nxt				;plr x2<nme x1 so no collision
			move.w	OB_CBox3X2(a2),d5		;get nme attack box	
			cmp.w	d5,d1
			bgt.s	.nxt
			move.w	OB_CBox3Y1(a2),d5		;get nme attack box	
			cmp.w	d5,d4
			blt.s	.nxt
			move.w	OB_CBox3Y2(a2),d5		;get nme attack box	
			cmp.w	d5,d3
			bgt.s	.nxt
			
			bset.b	#ob_hitting,OB_Flag1(a0)	;flag this object is hitting (player)
			movem.l	(sp)+,d0/a5
			bra	SetPlrHitSide
			
.nxt			movem.l	(sp)+,d0/a5
			addq.l	#4,a5
			addq.l	#2,a6
			dbra	d0,.l1
.x			rts


HandleBeingHit		move.b	OB_Flag6(a0),d1
			and.b	#obhit_mask,d1
			beq.s	.x
			move.l	OB_HitRoutine(a0),a1
			cmp.l	#-1,a1
			beq.s	.x
			jmp	0(a1)
.x			rts
			

			;optimize this
Get1stHitBox		move.w	OB_CBox1X1(a2),d1
			move.w	OB_CBox1Y1(a2),d2
			move.w	OB_CBox1X2(a2),d3
			move.w	OB_CBox1Y2(a2),d4
	       		rts
Get2ndHitBox		move.w	OB_CBox2X1(a2),d1
			move.w	OB_CBox2Y1(a2),d2
			move.w	OB_CBox2X2(a2),d3
			move.w	OB_CBox2Y2(a2),d4
	       		rts
GetAttackBox		move.w	OB_CBox3X1(a2),d1
			move.w	OB_CBox3Y1(a2),d2
			move.w	OB_CBox3X2(a2),d3
			move.w	OB_CBox3Y2(a2),d4
			rts
CmpHitBox		move.w	OB_CBox1X2(a1),d5		;test Plr CBox against NME CBox
			cmp.w	d5,d1
			bgt	FlagNO
			move.w	OB_CBox1Y2(a1),d6		;test Plr CBox against NME CBox
			cmp.w	d6,d2
			bgt	FlagNO
			move.w	OB_CBox1X1(a1),d5		;test Plr CBox against NME CBox
			cmp.w	d5,d3
			blt	FlagNO
			move.w	OB_CBox1Y1(a1),d6		;test Plr CBox against NME CBox
			cmp.w	d6,d4
			blt	FlagNO
			bra	FlagYES


; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί OBJECT TRIGGER/INITIALISE ROUTINES					   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: n/a								   Ί
; Ί  Exit: n/a								   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί All OBJECT triggering and setup routines are here.			   Ί
; Ί Object Triggering (switching on) is linked to the scroll routine.	   Ί
; Ί When a new edge is decompressed and dma'd, this routine will scan	   Ί
; Ί a column and/or row in the map and pull out an OBJECT entry from	   Ί
; Ί the 4th layer of the TUME map.  See File: "OBDATA.INC" for more info.  Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

; **** TO DO : Handle X going > Right map limit
; **** TO DO : Handle Y going > Bottom map limit


ScreenWide		equ	40
ScreenHigh		equ	28

LRClipMargin		equ	$60
TBClipMargin		equ	0

OnZoneSize		equ	6*16		;# gtile * 16pix

Adjust_T_XXX		equ	((ScreenWide*8)/2)+OnZoneSize
Adjust_T_YYY		equ	((ScreenHigh*8)/2)+OnZoneSize

VertScanCMP		equ	Adjust_T_YYY/8	
HorzScanCMP		equ	Adjust_T_XXX/8	


HandleTriggers		;rts
			
			tst.b	Trigger_LEFT
			beq.s	.1
			clr.b	Trigger_LEFT
			bsr	CheckLeft_T
			bra	.2
.1			tst.b	Trigger_RIGHT
			beq.s	.2
			clr.b	Trigger_RIGHT
			bsr	CheckRight_T

.2			tst.b	Trigger_TOP
			beq.s	.3
			clr.b	Trigger_TOP
			bra	CheckTop_T
.3			tst.b	Trigger_BOTTOM
			beq	clrtxx
			clr.b	Trigger_BOTTOM
			bra	CheckBottom_T


CheckRight_T		move.w	SCenterX,d1			;get center of screen
			move.w	SCenterY,d2			;get center of screen
			sub.w	x_speed,d1
			moveq	#VertScanCMP-1,d7		;height of vertical column
			add.w	#Adjust_T_XXX,d1		;adjust to get start pos (in pixels)
			;handle x going > right map limit
			bra	CGLR_T

CheckLeft_T		move.w	SCenterX,d1			;get center of screen
			move.w	SCenterY,d2			;get center of screen
			add.w	x_speed,d1
CL_T			moveq	#VertScanCMP-1,d7		;height of vertical column
			sub.w	#Adjust_T_XXX,d1		;adjust to get start pos (in pixels)
			bmi.s	clrtxx
CGLR_T			sub.w	#Adjust_T_YYY,d2		
			bpl.s	.ok
			neg.w	d2   				;handle y going negative
			lsr.w	#4,d2
			sub.w	d2,d7
			moveq	#0,d2

.ok			move.w	d1,OBPOS_X
			move.w	d2,OBPOS_Y
			jsr	GetUnderAddrs			;get the map address		
			move.w	map_wide,d5			;get map width for add
			ext.l	d5

.loop			moveq	#0,d3
			jsr	GetObject			;pull the object block from 4th layer
			tst.b	d3				;test entry
			beq.s	.nxt				;0 = null
;			bmi.s	.nxt				;- = action trigger
;			ext.w	d3				
			subq.w	#1,d3				;-1=adjusted index

			movem.l	d7/d5/a5,-(sp)
			bsr	SetupThisObject			;we have a valid object, so lets set it up ...
			movem.l	(sp)+,d7/d5/a5
			
.nxt			add.w	#$10,OBPOS_Y
			add.l	d5,a5				;move down the column
			dbra	d7,.loop
clrtxx			rts


CheckBottom_T		move.w	SCenterX,d1			;get center of screen
			move.w	SCenterY,d2			;get center of screen
			sub.w	y_speed,d2
			moveq	#HorzScanCMP-1,d7		;height of vertical column
			add.w	#Adjust_T_YYY,d2		
			;handle y going > bottom map limit
			bra	CGTB_T

CheckTop_T		move.w	SCenterX,d1			;get center of screen
			move.w	SCenterY,d2			;get center of screen
			add.w	y_speed,d2
			moveq	#HorzScanCMP-1,d7		;height of vertical column
			sub.w	#Adjust_T_YYY,d2		
			bmi.s	ctbtxx

CGTB_T			sub.w	#Adjust_T_XXX,d1		;adjust to get start pos (in pixels)
			bpl.s	.ok
			neg.w	d1				;handle x going negative
			lsr.w	#4,d1
			sub.w	d1,d7
			moveq	#0,d1

.ok			move.w	d1,OBPOS_X
			move.w	d2,OBPOS_Y
			jsr	GetUnderAddrs			;get the map address		

.loop			jsr	GetObject			;pull the object block from 4th layer
			tst.b	d3				;test entry
			beq.s	.nxt				;0 = null
			subq.w	#1,d3				;-1=adjusted index
			
			movem.l	d7/a5,-(sp)
			bsr	SetupThisObject			;we have a valid object, so lets set it up ...
			movem.l	(sp)+,d7/a5
			
.nxt			add.w	#$10,OBPOS_X
			addq.l	#2,a5				;move down the column
			dbra	d7,.loop
ctbtxx			rts


TriggerALL		;rts
			
			move.w	map_x_p,d6			;trigger all objects that should be triggered
			move.w	map_y_p,d7			;by performing a column sweep across the map
			moveq	#HorzScanCMP-1,d3
.loop			movem.l	d3/d6/d7,-(sp)
			move.w	map_x_p,d1			;get top left	
			move.w	map_y_p,d2		
			add.w	#(ScreenWide*8)/2,d1		;add to get center of screen
			add.w	#(ScreenHigh*8)/2,d2
			bsr	CL_T
			add.w	#$10,map_x_p
			movem.l	(sp)+,d3/d6/d7
			dbra	d3,.loop
			move.w	d6,map_x_p
			move.w	d7,map_y_p
			clr.l	Trigger_LEFT
			rts

							

; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί GetOBLayer - Get OBJECT entry from OBJECT LAYER @ X,Y		   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: d1/d2 = X/Y							   Ί
; Ί  Exit: a1/d3 = pointer to entry in layer/entry			   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Sets up layer address and pulls initial entry.			   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

GetOBLayer		jsr	GetUnderAddrs
			move.w	(a5),d1			;get block
			lsr.w	#1,d1			;/2 for .FLR index
			move.l	LevelFlr,a1		;get .FLR table
			move.b	3(a1,d1.w),d3		;Object from 4th layer
			move.l	LevelCon,a1
			add.l	d1,a1			;a1=addrs of contour data
			rts



; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί KILL OBJECTS ...							   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: d0=Object #							   Ί
; Ί  Exit: n/a								   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Switches objects off if they go out of screen bounds.		   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

OffZoneSize		equ	OnZoneSize+(4*16)

OffLeftRight		equ	((ScreenWide*8)/2)+OffZoneSize
OffTopBot		equ	((ScreenHigh*8)/2)+OffZoneSize

GetScreenCenterClips	move.w	map_x_p,d1			;get top left	
			move.w	map_y_p,d2		
			add.w	#(ScreenWide*8)/2,d1		;add to get center of screen
			add.w	#(ScreenHigh*8)/2,d2
			move.w	d1,SCenterX
			move.w	d2,SCenterY
			sub.w	#((ScreenWide*8)/2)+LRClipMargin,d1
			move.w	d1,ClipLeft
			add.w	#(ScreenWide*8)+(LRClipMargin*2),d1
			move.w	d1,ClipRight
			sub.w	#((ScreenHigh*8)/2)+TBClipMargin,d2
			move.w	d2,ClipTop
			add.w	#(ScreenHigh*8)+(TBClipMargin*2),d2
			move.w	d2,ClipBottom
.x			rts


KillOb			btst.b	#ob_nooff,OB_Flag2(a0)
			bne.s	.no
			
			move.w	SCenterX,d1
			move.w	SCenterY,d2
			move.w	d1,d3
			sub.w	#OffLeftRight,d1
			add.w	#OffLeftRight,d3
			cmp.w	OB_Xpos(a0),d1
			bgt.s	SwitchObjectOff
			cmp.w	OB_Xpos(a0),d3
			blt.s	SwitchObjectOff

			move.w	d2,d3				;check if y is out of bounds
			sub.w	#OffTopBot,d2
			add.w	#OffTopBot,d3
			cmp.w	OB_Ypos(a0),d2
			bgt.s	SwitchObjectOff
			cmp.w	OB_Ypos(a0),d3
			blt.s	SwitchObjectOff
.no			rts

SwitchObjectOff_A1	movem.l	a0/a1/d1,-(sp)
			move.l	a1,a0
			bsr	SwitchObjectOff
			movem.l	(sp)+,a0/a1/d1
			rts

SwitchObjectOff		bset.b	#ob_kill,OB_Flag2(a0)		;turn object off
			rts


TidyKilledObject	lea	OBOnOffFlags,a1			;flag this object is off
			move.w	OB_ObNum(a0),d3
			beq.s	.not_triggered			;trap a non triggered object
			subq.w	#1,d3				;-1 of index to make valid
			clr.b	0(a1,d3.w)			;flag this (triggered) object as OFF

.not_triggered		move.l	OB_OffRoutine(a0),a1		;get objects off routine
			cmp.l	#-1,a1				;null? (default)
			beq.s	.1 				
			move.l	a0,-(sp)
			jsr	(a1)				;execute off routine
			move.l	(sp)+,a0
			
.1			bclr.b	#ob_kill,OB_Flag2(a0)		
			bclr.b	#ob_active,OB_Flag1(a0)
			move.l	OB_CollisionRAM(a0),a1
			move.l	#$88888888,OB_CBox1X1(a1)	;clr collision boxes
			move.l	#$88888888,OB_CBox1X2(a1)
			move.l	#$88888888,OB_CBox2X1(a1)		
			move.l	#$88888888,OB_CBox2X2(a1)
			move.l	#$88888888,OB_CBox3X1(a1)		
			move.l	#$88888888,OB_CBox3X2(a1)
			move.l	OB_RefAnRam(a0),a1		;get ram reference table
			move.w	_VRAM_L(a1),d0			;length
			move.w	_VRAM_A(a1),d1			;address
			jmp	VRamFree			;free it up

			
; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί Misc. OBJECT routines						   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: n/a								   Ί
; Ί  Exit: n/a								   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Lots of useful routines for manipulating objects			   Ί
; Ί in various ways (ooeerr!)						   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ


SnapX			and.w	#$fff0,OB_Xpos(a0)
			rts
SnapY			and.w	#$fff0,OB_Ypos(a0)
			rts
SnapXY			and.w	#$fff0,OB_Xpos(a0)
			and.w	#$fff0,OB_Ypos(a0)
			rts

SetFlipFromMother	move.b	OB_Flag1(a0),d1
			and.b	#_ob_xflp!_ob_yflp,d1
			or.b	d1,OB_Flag1(a1)
			rts

TestProxX		bsr	TestProxX_Left
			bpl.s	.n
			bra	TestProxX_Right
.n			rts

TestProxX_Left		move.w	OB_Xpos(a0),d2
			sub.w	d1,d2
			cmp.w	Plr_XPos,d2
			bgt	FlagNO
			bra	FlagYES
			
TestProxX_Right		move.w	OB_Xpos(a0),d2
			add.w	d1,d2
			cmp.w	Plr_XPos,d2
			blt	FlagNO
			bra	FlagYES

TestProxY_Above		move.w	OB_Ypos(a0),d2
			sub.w	d1,d2
			cmp.w	Plr_YPos,d2
			bgt	FlagNO
			bra	FlagYES
			
TestProxY_Below		move.w	OB_Ypos(a0),d2
			add.w	d1,d2
			cmp.w	Plr_YPos,d2
			blt	FlagNO
			bra	FlagYES
			

SaveLastThrowXY		move.w	GolThrowXPos,GolThrowXPosL
			move.w	GolThrowYPos,GolThrowYPosL
			rts

EnemyWallInterupt	move.l	Plr_Database,a1
			cmp.w	#GolGroundGrabSTATE,OB_State(a1)
			beq	FlagNO

.yup			btst.b	#ob_xflp,Plr_Flag1
			beq.s	.wr
			bsr	GetUnderFEET
			bsr	TestLevelWalls
			bmi.s	.y
			bsr	GetUnderRIGHTFEET
			bsr	TestLevelWalls
			bmi.s	.y1
.no			bra	FlagNO
.wr			bsr	GetUnderFEET
			bsr	TestLevelWalls
			bmi.s	.y
			bsr	GetUnderLEFTFEET
			bsr	TestLevelWalls
			bpl	FlagNO
.y1			move.w	GolThrowXPosL,OB_Xpos(a0)
			move.w	GolThrowYPosL,OB_Ypos(a0)
			bra	.1
.y			move.w	GolThrowXPos,OB_Xpos(a0)
			move.w	GolThrowYPos,OB_Ypos(a0)
.1			st.b	GolSlamOutFLG
			bra	FlagYES


ObjectOffBottom		move.w	bot_lim,d1
			add.w	#(32*8)+$40,d1
			cmp.w	OB_Ypos(a0),d1
			rts

		
DecayXSpd		tst.w	OB_Xspd(a0)
			beq.s	.x
			sub.w	#$0030,OB_Xspd(a0)
			bpl.s	.x
			clr.w	OB_Xspd(a0)
.x			rts

UpParabola		addq.b	#1,OB_Var1a(a0)				;do variable height jumping
			and.b	#3,OB_Var1a(a0)				;depending on length of jump button
			bne.s	.2					;depression
			subq.w	#1,OB_Var2(a0)				;decrease upward velocity				
			beq	FlagYES
.2			move.w	OB_Var2(a0),d1				;get speed
			bsr	MoveGolUp_Smooth			;move up
			bra	FlagNO
DownParabola		addq.b	#1,OB_Var1a(a0)				;do variable height jumping
			and.b	#3,OB_Var1a(a0)				;depending on length of jump button
			bne.s	.2					;depression
			addq.w	#1,OB_Var2(a0)				;decrease upward velocity				
			beq	FlagYES
.2			move.w	OB_Var2(a0),d1				;get speed
			bsr	MoveGolDown;_Smooth			;move up
			bra	FlagNO

ClrHitStuff		move.b	OB_Flag1(a0),d1
			and.b	#((_ob_hitting!_ob_beinghit)^$ff),d1
			move.b	d1,OB_Flag1(a0)
			move.b	OB_Flag6(a0),d1
			and.b	#((_ob_hit_small!_ob_hit_med!_ob_hit_big)^$ff),d1
			move.b	d1,OB_Flag6(a0)
			clr.b	OB_HitPower(a0)
			rts

			
CheckIfHitSomething	btst.b	#ob_hitting,OB_Flag1(a0)
			beq	FlagNO
			bra	FlagYES

SetPlrHitSide		move.b	OB_Flag6(a0),d7			;get nmes attack
			and.b	#obattk_mask,d7
			asl.b	#3,d7				;mod it
			or.b	d7,OB_Flag6(a3)			;set plrs hit

			bset.b	#ob_beinghit,OB_Flag1(a3)	;flag ob being hit	

			btst	#blokmode,OB_MasterMode(a3)	;get plrs master mode 
			bne.s	.a1
			bsr	HitPlayer
			bmi	SetPlayerDead

.a1			SFX	15

			move.l	a0,OB_Interact(a3)		;save offending objects # for plr useage
			move.w	Plr_XPos,d7
			cmp.w	OB_Xpos(a0),d7
			bgt.s	.l
			bset.b	#ob_hitside,OB_Flag1(a3)
			rts
.l			bclr.b	#ob_hitside,OB_Flag1(a3)
			rts

HitPlayer		moveq	#0,d5
			move.b	OB_HitPower(a0),d5
			sub.w	d5,PlrEnergy
			beq.s	.y
			bpl	FlagNO
.y			clr.w	PlrEnergy
			clr.w	OB_Nrg(a3)
			bra	FlagYES

SetNmeHitSide		move.l	Plr_Database,a1				;flag player has hit summat
			bset.b	#ob_hitting,OB_Flag1(a1)			
			
			move.b	OB_Flag6(a1),d7				;get plr attack
			and.b	#obattk_mask,d7				
			asl.b	#3,d7					;roll it
			or.b	d7,OB_Flag6(a0)				;becomes nmes hit

			bset.b	#ob_beinghit,OB_Flag1(a0)		;flag nme being hit	

			bsr	HitEnemy
			bmi	SetEnemyDead
			
			SFX 	11

			move.w	Plr_XPos,d7				;flag side nme was hit on
			cmp.w	OB_Xpos(a0),d7
			blt.s	.l
			bset.b	#ob_hitside,OB_Flag1(a0)
.x			rts
.l			bclr.b	#ob_hitside,OB_Flag1(a0)
			rts

HitEnemy		moveq	#0,d5
			move.b	OB_HitPower(a1),d5			;plr hit power
			sub.w	d5,OB_Nrg(a0)				;subtract from enemy health
			beq.s	.y
			bpl	FlagNO
.y			clr.w	OB_Nrg(a0)
			bra	FlagYES

SetEnemyDead		bset.b	#ob_dead,OB_Flag2(a0)
			move.w	OB_State(a1),OB_Var5(a0)
			move.b	OB_MasterMode(a0),OB_Var6(a0)
			rts


HandleEnemyKilled	btst.b	#ob_drop,OB_Flag2(a0)			;does nme have an item to drop?
			beq.s	.no
			bclr.b	#ob_drop,OB_Flag2(a0)
			moveq	#0,d1
			move.b	OB_Var7(a0),d1
			asl.b	#2,d1
			jsr	DropItemJumpTab(pc,d1.w)
.no			move.l	OB_KillRoutine(a0),a1
			cmp.l	#-1,a1
			beq	SwitchObjectOff
			jmp	(a1)

DropItemJumpTab		bra	DropSTRENGTH
			bra	DropINVICIBILITY
			bra	DropCONTINUE
			bra	DropHEALTH
			bra	DropLIFE

DropSTRENGTH		move.b	#0,d1
			bra	SetupDroppedIcon

DropINVICIBILITY	move.b	#1,d1
			bra	SetupDroppedIcon

DropCONTINUE		move.b	#2,d1
			bra	SetupDroppedIcon

DropHEALTH		move.b	#3,d1
			bra	SetupDroppedIcon

DropLIFE		move.b	#4,d1
			bra	SetupDroppedIcon


HitSlideObject		tst.w	OB_Var1(a0)
			beq.s	.1
			btst.b	#ob_hitside,OB_Flag1(a0)
			beq.s	.2
			bsr	GetUnderLEFTLEFT
			bsr	TestLevelWalls
			bmi.s	.3
			bsr	GetUnderLEFT
			bsr	TestLevelWalls
			bmi.s	.3
			move.w	OB_Var1(a0),d1
			bsr	MoveGolLeft_NF_Smooth
			bra	.3
.2			bsr	GetUnderRIGHTRIGHT
			bsr	TestLevelWalls
			bmi.s	.3
			bsr	GetUnderRIGHT
			bsr	TestLevelWalls
			bmi.s	.3
			move.w	OB_Var1(a0),d1
			bsr	MoveGolRight_NF_Smooth
.3			addq.b	#1,OB_Var2(a0)
			and.b	#3,OB_Var2(a0)
			bne.s	.1
  			subq.w	#1,OB_Var1(a0)
.1			rts

SetSmallAttack		move.b	#_ob_attk_small,d2
			bra	SetAttack
SetMediumAttack		move.b	#_ob_attk_med,d2
			bra	SetAttack
SetBigAttack		move.b	#_ob_attk_big,d2
SetAttack		move.b	OB_Flag6(a0),d1
			and.b	#%11111000,d1
			or.b	d2,d1
			move.b	d1,OB_Flag6(a0)
			rts

SetSmallAttackA1	move.b	#_ob_attk_small,d2
			bra	SetAttackA1
SetMediumAttackA1	move.b	#_ob_attk_med,d2
			bra	SetAttackA1
SetBigAttackA1		move.b	#_ob_attk_big,d2
SetAttackA1		move.b	OB_Flag6(a1),d1
			and.b	#%11111000,d1
			or.b	d2,d1
			move.b	d1,OB_Flag6(a1)
			rts

BeenHit			move.b	OB_Flag6(a0),d1
			and.b	#obhit_mask,d1
			rts
			
CheckScreenBoundsX	move.w	SCenterX,d1			;get center of screen
			move.w	d1,d3				;check if x is out of bounds
			sub.w	#(OffLeftRight-$20),d1
			add.w	#(OffLeftRight-$20),d3
			cmp.w	OB_Xpos(a0),d1
			bgt	FlagYES
			cmp.w	OB_Xpos(a0),d3
			blt	FlagYES
			bra	FlagNO


TestLand		bsr	GetUnderFEET				;land proper
			bra	SetHeight


HandleContours		bsr	GetUnderFEET
			bsr	SetHeight
			bpl.s	.1
			rts
			
.1			moveq	#0,d3
			move.w	#-$10,d4
			bsr	GetUnderGENERIC
			moveq	#8,d1
			bsr	MoveGolUp_Smooth
			bsr	GetXInBlock
			move.b	0(a1,d7.w),d1	
			ext.w	d1
			beq.s	.2
			subq.w	#1,d1
			and.w	#$fff0,OB_Ypos(a0)
			or.w	d1,OB_Ypos(a0)
			bra	FlagYES

.2			addq.w	#8,OB_Ypos(a0)	
			moveq	#0,d3
			moveq	#$10,d4
			bsr	GetUnderGENERIC
			moveq	#8,d1
			bsr	MoveGolDown_Smooth
			bsr	GetXInBlock
			move.b	0(a1,d7.w),d1	
			ext.w	d1
			beq	FlagNO
			subq.w	#1,d1
			and.w	#$fff0,OB_Ypos(a0)
			or.w	d1,OB_Ypos(a0)
			bra	FlagYES


			;IN  : n/a
			;OUT : d0=object #  
			;    : a0=Object RAM pointer
			;
GetFreeOBJECT_HI	moveq	#0,d0
			lea	OBJECT_RAM,a0
.loop			btst.b	#ob_active,OB_Flag1(a0)
			beq	FlagYES
.nxt			lea	OB_DATA_SIZE(a0),a0
			addq.w	#1,d0
			cmp.w	#GoliathObjectNumber,d0
			bne.s	.loop
			bra	FlagNO


			;IN  : n/a
			;OUT : d0=object #  
			;    : a0=Object RAM pointer
			;
GetFreeOBJECT_LO	moveq	#GoliathObjectNumber+1,d0
			lea	OBJECT_RAM+((GoliathObjectNumber+1)*128),a0
.loop			btst.b	#ob_active,OB_Flag1(a0)
			beq	FlagYES
.nxt			lea	OB_DATA_SIZE(a0),a0
			addq.w	#1,d0
			cmp.w	#MaxObs,d0
			bne.s	.loop
			bra	FlagNO


			;IN  : n/a
			;OUT : d0=Composite object #  
			;    : a0=Composite Object RAM pointer
GetFreeCOBJECT		moveq	#0,d6
			lea	COBJECT_RAM,a6
.loop			btst.b	#cob_active,COB_Flag1(a6)
			beq	FlagYES
.nxt			lea	COB_DATA_SIZE(a6),a6
			addq.w	#1,d6
			cmp.w	#MaxCobs,d6
			bne.s	.loop
			bra	FlagNO

			;setup some vector for the composite object
GetCobjectVECS		move.w	d6,d1
			move.w	#MaxObsInCobs,d2			;max # of objects in composite object
			mulu	d2,d1					;* Composite object #
			lea	COB_LINKS,a2				;get
			add.w	d1,a2
			move.l	a2,COB_LinksVEC(a6)			;links list vec
			lea	COB_UNIQUE,a2
			add.w	d1,a2
			move.l	a2,COB_UniqueVEC(a6)			;unique flags vec
			lea	COB_AGE,a2
			add.w	d1,a2
			move.l	a2,COB_AgeVEC(a6)			;unique obs address vec
			
			move.w	d6,d1
			move.w	#MaxObsInCobs*4,d2			;max # of objects in composite object
			mulu	d2,d1					;* Composite object #
			lea	COB_ADDRS,a2
			add.w	d1,a2
			move.l	a2,COB_AddrsVEC(a6)			;unique obs address vec
			lea	COB_ADDRS2,a2
			add.w	d1,a2
			move.l	a2,COB_Addrs2VEC(a6)			;unique obs address vec
			rts


; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί SetupObjectFLY_ROM - Setup a RAW object thats FLOWN from ROM	   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: d3 = Max Size (in bytes) of object (XChar*YChar*32)		   Ί
; Ί  Exit: _WRAM_A(RamTab) = ROM address of Source data			   Ί
; Ί  	   _VRAM_A(RamTab) = VRAM address of Destination		   Ί
; Ί  	   _VRAM_Adiv32(RamTab) = VRAM address of Destination / 32	   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

SetupObjectFLY_ROM	bsr	VRamAlloc_BF			;allocate the VRAM
			bpl	FlagNO
			bsr	GetObRAMTab			;get table for objects RAM info (a2)
			move.w	d3,_VRAM_L(a2)			;save length of block
			move.w	d1,_VRAM_A(a2)			;save address of block
			lsr.w	#5,d1				;/32
			move.w	d1,_VRAM_Adiv32(a2)		;save address/32 of block
	   		bsr	SetupObject
			bset.b	#ob_flown,OB_Flag3(a0)		;set this object flown
			bra	FlagYES				;object setup okay


SetupObjectRES		bsr	GetObjectRAM			;set Database Ram Addrs
			bsr	GetObRAMTab
			bclr.b	#ob_flown,OB_Flag3(a0)		;set this object resident

SetupObject		move.l	#-1,OB_OffRoutine(a0)		;null object off routine (default)
			move.l	#-1,OB_KillRoutine(a0)		;null object kill routine (default)
			move.l	#-1,OB_HitRoutine(a0)		;null object hit routine (default)
			clr.b	OB_MoveFlags(a0)
			clr.w	OB_Xspd(a0)
			clr.w	OB_Yspd(a0)
			clr.w	OB_Xacc(a0)
			clr.w	OB_Yacc(a0)
			clr.b	OB_State(a0)
			move.b	#_ob_active,OB_Flag1(a0)
			clr.b	OB_Flag2(a0)
			clr.b	OB_Flag3(a0)	
			clr.b	OB_Flag4(a0)	
			clr.b	OB_Flag5(a0)	
			clr.b	OB_Flag6(a0)
			clr.l	OB_Task(a0)	
			clr.l	OB_Var1(a0)
			clr.l	OB_Var3(a0)
			clr.l	OB_Var5(a0)
			clr.w	OB_Var7(a0)
			clr.w	OB_ObNum(a0)
			rts


SpawnBasicOBJECT_LO	bsr	GetFreeOBJECT_LO 			;get a free object
			bpl	FlagNO					;no free objects
			bsr	SetupObjectFLY_ROM			;setup object as a raw ROM flown object
			bpl	FlagNO					;no free VRAM
			bra	FlagYES

SpawnBasicOBJECT_HI	bsr	GetFreeOBJECT_HI 			;get a free object
			bpl	FlagNO					;no free objects
			bsr	SetupObjectFLY_ROM			;setup object as a raw ROM flown object
			bpl	FlagNO					;no free VRAM
			bra	FlagYES

PosOnContour		bsr	GetXInBlock
			moveq	#0,d1
			move.b	0(a1,d7.w),d1	
			beq	FlagNO
			subq.b	#1,d1
			ext.w	d1
			and.w	#$fff0,OB_Ypos(a0)
			add.w	d1,OB_Ypos(a0)
			bra	FlagYES

WipeObjects		lea	OBJECT_RAM,a0
			move.w	#((object_ram_end-OBJECT_RAM)/4)-1,d0
.l1			clr.l	(a0)+
			dbra	d0,.l1
			rts


			;Wipe unused sprs off scrn
ClrSprend		lea	SprtAttr_RAM,a0		;sprt attribute RAM
			moveq	#0,d0			;get number of sprites used this frame
			move.b	linker,d0
			subq.b	#1,d0	 		;- 1
			move.w	#80,d1			;max # of h/w sprts
			sub.w	d0,d1			;- number used = number of sprts to clear
			asl.w	#3,d0			;* 8 to get offset into sprt attribute RAM
			add.w	d0,a0			;add to pointer
.loop			clr.b	attr(a0)		;clr attribute byte
			addq.w	#8,a0			;bump pointer
			dbra	d1,.loop		;loop 
			rts


GetObRAMTab		lea	ObjectCollisionRAM,a2
			move.w	d0,d2
			asl.w	#5,d2
			add.w	d2,a2
			move.l	a2,OB_CollisionRAM(a0)
			move.l	#$88888888,OB_CBox1X1(a2)		;clr collision boxes
			move.l	#$88888888,OB_CBox1X2(a2)
			move.l	#$88888888,OB_CBox2X1(a2)		
			move.l	#$88888888,OB_CBox2X2(a2)
			move.l	#$88888888,OB_CBox3X1(a2)		
			move.l	#$88888888,OB_CBox3X2(a2)
			lea	ObjectRAMTab,a2
			move.w	d0,d2
			asl.w	#3,d2
			add.w	d2,a2
			move.l	a2,OB_RefAnRam(a0)
			rts			
			
NullAnim		ds.b	16

SetNewAnim_Q		move.l	0(a1),OB_AnSequence(a0)
			move.l	4(a1),OB_AnChrData(a0)
			move.l	8(a1),OB_AnPatch(a0)				
			move.w	12(a1),OB_AnDex(a0)	
			move.b	15(a1),OB_AnFlags(a0)	
			rts

SetNewAnimFREE		tst.l	OB_AnSequence(a0)		;set new anim ONLY if old one has finished
			beq.s	SetNewAnim
			rts
SetNewAnim		move.l	0(a1),OB_AnSequence(a0)
			move.l	4(a1),OB_AnChrData(a0)
			move.l	8(a1),OB_AnPatch(a0)				
			move.w	12(a1),OB_AnDex(a0)	
			move.b	NewAnCnt,OB_AnCnt(a0)	
			move.b	#4,OB_AnCmp(a0)
			move.b	15(a1),OB_AnFlags(a0)	
			clr.l	OB_AnSeqTemp(a0)	
			clr.w	OB_AnDexTemp(a0)
			addq.b	#1,NewAnCnt
			and.b	#3,NewAnCnt
			rts

ForceNewAnim		clr.b	OB_AnCmp(a0)
			rts

SetNewAnimA1		move.l	0(a2),OB_AnSequence(a1)
			move.l	4(a2),OB_AnChrData(a1)
			move.l	8(a2),OB_AnPatch(a1)				
			move.w	12(a2),OB_AnDex(a1)	
			move.b	NewAnCnt,OB_AnCnt(a1)	
			move.b	#4,OB_AnCmp(a1)
			move.b	15(a2),OB_AnFlags(a1)	
			clr.l	OB_AnSeqTemp(a1)	
			clr.w	OB_AnDexTemp(a1)
			addq.b	#1,NewAnCnt
			and.b	#3,NewAnCnt
			rts

ForceNewAnimA1		clr.b	OB_AnCmp(a1)
			rts


ForceNextAnimFrame	clr.b	OB_AnCnt(a0)
			clr.b	OB_AnCmp(a0)
			rts


			;NOTE: This routine uses a arithmetic shift operation to multiply
			;the object # by 128.  If the OB_DATA_SIZE is changed, then this
			;asl.w	#7,d2 must be changed to mulu	#OB_DATA_LEN,d2
			;
GetObjectRAM		lea	OBJECT_RAM,a0		;point to objects RAM
			move.w	d0,d2
			asl.w	#7,d2			;<<<<< HERE
			add.w	d2,a0
			rts

FindObject		lea	OBJECT_RAM,a1
			moveq	#MaxObs-1,d1
.l1			btst.b	#ob_active,OB_Flag1(a1)
			beq.s	.n
			cmp.w	OB_Type(a1),d2
			beq	FlagYES
.n			lea	$80(a1),a1
			dbra	d1,.l1
			bra	FlagNO
			

; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί SETUP THIS OBJECT							   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: d3 = OBJECT Entry from 4th Layer of TUME map.		   Ί
; Ί  Exit: mi = Object setup OK.					   Ί
; Ί        pl = Object NOT setup OK.					   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Sets up an OBJECT using the Entry from 4th layer of TUME map.	   Ί
; Ί T`his value (-1) is used as an index to access the objects,		   Ί
; Ί unique setup, config data.						   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

SetupThisObject		lea	OBOnOffFlags,a1			;check if this object is flagged on 
			tst.b	0(a1,d3.w)			
			bne	FlagNO
			lea	OBIsKilled,a1			;check if this object is dead already
			tst.b	0(a1,d3.w)			
			bmi	FlagNO				;dead for ever!
			
			move.l	OBJECTDataLVec,a1		;vec to object data tab vecs
			asl.w	#2,d3				;*4 = index .l
			move.l	0(a1,d3.w),a2			;pull pointer to data tab
			cmp.l	#-1,a2				;null entry
			beq	FlagNO
			
			cmp.b	#LO,$1b(a2)			;spawn hi or lo?
			bne.s	.hi
.lo			bsr	GetFreeOBJECT_LO		;get a free object
			bpl	FlagNO				;didn't find one so exit
			bra	.ok	
.hi			bsr	GetFreeOBJECT_HI		;get a free object
			bpl	FlagNO				;didn't find one so exit
			
.ok			lsr.w	#2,d3
			move.w	d3,OB_ObNum(a0)
			lea	OBObNumbers,a1			;save this objects number
			move.b	d0,0(a1,d3.w)
			
			move.w	4(a2),d3			;max size of VRAM needed for this OBJECT
			tst.w	d3  				;- size means that this objects doesn't need
			bmi.s	.skp				;VRAM so skip the allocation
			bsr	VRamAlloc_BF			;allocate the VRAM
			bpl	FlagNO				;didn't find enough VRAM so exit
			move.l	a2,-(sp)
			bsr	GetObRAMTab			;get table for objects RAM info (a2)
			move.w	d3,_VRAM_L(a2)			;save length of block
			move.w	d1,_VRAM_A(a2)			;save address of block
			lsr.w	#5,d1				;/32
			move.w	d1,_VRAM_Adiv32(a2)		;save address/32 of block
			move.l	(sp)+,a2

.skp			move.w	0(a2),OB_Type(a0)		;set type	
			move.w	2(a2),OB_Nrg(a0)		;set energy
			move.b	6(a2),OB_Flag1(a0)		;set flags
			move.b	7(a2),OB_Flag2(a0)		
			move.b	8(a2),OB_Flag3(a0)		
			move.b	9(a2),OB_Flag4(a0)		
			move.b	$0a(a2),OB_Flag5(a0)		
			move.b	$0b(a2),OB_Flag6(a0)		
			move.w	$0c(a2),OB_Var1(a0)		;set variables
			move.w	$0e(a2),OB_Var2(a0)
			move.w	$10(a2),OB_Var3(a0)
			move.w	$12(a2),OB_Var4(a0)
			move.w	$14(a2),OB_Var5(a0)
			move.w	$16(a2),OB_Var6(a0)
			move.w	$18(a2),OB_Var7(a0)
			moveq	#0,d1
			move.b	$1a(a2),d1
			move.w	d1,OB_State(a0)			;set starting state
			cmp.l	#-1,$1c(a2)			;does this object need a new palette
			beq.s	.1
			move.l	$1c(a2),a1			;drop in the new palette
			bsr	SetSinglePalette

.1			move.l	#-1,OB_OffRoutine(a0)		;null object off routine (default)
			move.l	#-1,OB_KillRoutine(a0)		;null object kill routine (default)
			bset.b	#ob_tidy,OB_Flag5(a0)
			clr.b	OB_MoveFlags(a0)		;wipe movement vars
			clr.w	OB_Xspd(a0)
			clr.w	OB_Yspd(a0)
			clr.w	OB_Xacc(a0)
			clr.w	OB_Yacc(a0)
			clr.l	OB_Task(a0)	
			lea	NullAnim,a1
			bsr	SetNewAnim
			move.w	OBPOS_X,OB_Xpos(a0)
			and.w	#$fff0,OB_Xpos(a0)
			move.w	OBPOS_Y,OB_Ypos(a0)
			add.w	#$10,OB_Ypos(a0)
			and.w	#$fff0,OB_Ypos(a0)
			add.w	#$8,OB_Ypos(a0)
	
			move.w	OB_ObNum(a0),d3			;flag this object on
			addq.w	#1,OB_ObNum(a0)			;+1=trappable value
			lea	OBOnOffFlags,a1
			st.b	0(a1,d3.w)			;flag on
			bra	FlagYES


CheckIfOnAlready	lea	OBOnOffFlags,a1			;check if this object is flagged on 
			tst.b	0(a1,d3.w)			
			bne	FlagYES				;mi if on
			bra	FlagNO				;pl if off


InitOBJECTS		lea	OBIsKilled,a1			;clear onject on flags
			moveq	#(256/4)-1,d1
.l1			clr.l	(a1)+
			dbra	d1,.l1
InitOBJECTS2		bsr	WipeObjects
			lea	OBOnOffFlags,a1			;clear onject on flags
			moveq	#(256/4)-1,d1
.l1			clr.l	(a1)+
			dbra	d1,.l1
			rts


; - OBJECT LOGIC ROUTINES --------------------------------------------------


; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί OBJECT Routines							   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί Entry: n/a								   Ί
; Ί  Exit: n/a								   Ί
; Ί  Used: n/a								   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί These are all the individual "enemy" routines			   Ί
; Ί including the PLAYER (Goliath)					   Ί
; Ί Logic, logic, logic and more logic ...				   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

; - Hit Point Equates ------------------------------------------------------

RapBotSnakeAttackPOWER	equ	8
RapBotRendPOWER		equ	2
RapBotDefencePOWER	equ	4
TriloBodyHitPOWER	equ	16
LaserHitPOWER		equ	8
HomerHitPOWER		equ	8


; - Object Maximum sizes ---------------------------------------------------

Goliath_MAX_Size	equ	10*10*32
Burn_MAX_Size		equ	32*32
RaptorBot_MAX_Size	equ	48*32		
SniperBot_MAX_Size	equ	33*32
PiecePaper_MAX_Size	equ	5*32	
BreakWall_MAX_Size	equ	16*32	
SkyLight_MAX_Size	equ	27*32		
BreakLight_MAX_Size	equ	18*32		
BreakPipe_MAX_Size	equ	4*32		
ThrowCrate_MAX_Size	equ	21*32	
PigeonCoop_MAX_Size	equ	44*32	
Pigeon_MAX_Size		equ	4*32	
BreakEdgeL_MAX_Size	equ	14*32	
BreakEdgeR_MAX_Size	equ	5*32	
BigFlrExplode_MAX_Size	equ	42*32	
BigAirExplode_MAX_Size	equ	42*32	
SmallAirExplode_MAX_Size	equ	3*3*32
Fireball_MAX_Size	equ	2*2*32
Spark_MAX_Size		equ	1*32	
Sparks_MAX_Size		equ	4*4*32
Sparks2_MAX_Size	equ	4*4*32
Debris_MAX_Size		equ	3*3*32
WoodDebris_MAX_Size	equ	4*32
TriloBotBody_MAX_Size	equ	99*32
TriloBotLegs_MAX_Size	equ	103*32
TriloBotJet_MAX_Size	equ	4*4*32
TriloBotShield_MAX_Size	equ	26*32
HomingProj1_MAX_Size	equ	1*32
HorzProj1_MAX_Size	equ	4*32
VertProj1_MAX_Size	equ	4*32
DirProj1_MAX_Size	equ	8*32
DirProj2_MAX_Size	equ	4*32
WallDebris_MAX_Size	equ	3*3*32
Scratch1_MAX_Size	equ	19*32
Scratch2_MAX_Size	equ	43*32
Scratch3_MAX_Size	equ	36*32
Scratch4_MAX_Size	equ	35*32
Icon_MAX_Size		equ	4*32
SpiderBot_MAX_Size	equ	31*32
WaspBot_MAX_Size	equ	48*32
SteelClan_MAX_Size	equ	4*32

			ObRESET			
			ObDEF	Goliath_OB				;GOLIATH (player)
			ObDEF	Test_OB					;testbed
			ObDEF	Health1_OB				;health meter
			ObDEF	Health2_OB				;health meter slider
			ObDEF	Numeral_OB		
			ObDEF	Burn_OB			
			ObDEF	Strawman_OB		
			ObDEF	RaptorBot_OB		
			if	show_tect
			ObDEF	Corner_OB		
			endif
			ObDEF	BigExplode_OB		
			ObDEF	SmallExplode_OB		
			ObDEF	GlassDebris_OB		
			ObDEF	MetalDebris_OB		
			ObDEF	WoodDebris_OB		
			ObDEF	WallDebris_OB		
			ObDEF	SunSet_OB		
			ObDEF	SniperBot_OB		
			ObDEF	PiecePaper_OB		
			ObDEF	BreakWall_OB		
			ObDEF	SkyLight_OB		
			ObDEF	BreakLight_OB		
			ObDEF	BreakPipe_OB		
			ObDEF	ThrowCrate_OB		
			ObDEF	PigeonCoop_OB		
			ObDEF	Pigeon_OB		
			ObDEF	BreakEdgeLeft_OB		
			ObDEF	BreakEdgeRight_OB		
			ObDEF	TriloBotBody_OB		
			ObDEF	TriloBotLegs_OB		
			ObDEF	TriloBotJet_OB		
			ObDEF	TriloBotShield_OB		
			ObDEF	Spark_OB		
			ObDEF	Sparks_OB		
			ObDEF	Sparks2_OB		
			ObDEF	Fireball_OB
			ObDEF	HomingProj1_OB
			ObDEF	HorzProj1_OB
			ObDEF	VertProj1_OB
			ObDEF	DirProj1_OB
			ObDEF	DirProj2_OB
			ObDEF	Scratch_OB
			ObDEF	Icon_OB
			ObDEF	SpiderBot_OB
			ObDEF	WaspBot_OB
			ObDEF	SteelClan_OB

Child_OB		equ	-1			

lobx			rts
LogicOb			move.w	OB_Type(a0),d1		;use type to jump to handler
			tst.w	d1
			bmi.s	lobx
			jmp	OB_JUMP_TAB(pc,d1.w)


; NEVER! EVER!! use A0 & D0 in the logic routines (unless you stack them)

OB_JUMP_TAB		bra	Goliath_Logic			;Goliath (player) control
			bra	Test2				;Test bed	
			bra	Health1_Logic			;Static health meter
			bra	Health2_Logic			;Dynamic health meter
			bra	Numeral_Logic			;Numeral Life counter
			bra	Burn_Logic			;burn
			bra	Strawman_Logic			;The Composite Strawman
			bra	RaptorBot_Logic			;RaptorBot 
			if	show_tect
			bra	Corner_Logic			;debug corners
			endif
			bra	BigExplode_Logic		;Big Explosion
			bra	SmallExplode_Logic		;Big Explosion
			bra	GlassDebris_Logic		;Misc Debris
			bra	MetalDebris_Logic		;Misc Debris
			bra	WoodDebris_Logic		;Misc Debris
			bra	WallDebris_Logic		;Misc Debris
			bra	SunSet_Logic			;level1.1 setting sun
			bra	SniperBot_Logic			;SniperBot
			bra	PiecePaper_Logic		;piece o paper
			bra	BreakWall_Logic			;breakable wall
			bra	SkyLight_Logic			;skylight
			bra	BreakLignt_Logic		;breakable light
			bra	BreakPipe_Logic			;breakable pipe
			bra	ThrowCrate_Logic		;throwable crate
			bra	PigeonCoop_Logic		;pigeon coop
			bra	Pigeon_Logic			;a pigeon
			bra	BreakEdgeLeft_Logic		;breakable edge
			bra	BreakEdgeRight_Logic		;breakable edge
			bra	TriloBotBody_Logic		;TriloBot body
			bra	TriloBotLegs_Logic		;TriloBot legs
			bra	TriloBotJet_Logic		;TriloBot legs
			bra	TriloBotShield_Logic		;TriloBot shield
			bra	Spark_Logic			;single spark
			bra	Sparks_Logic			;sparks anim
			bra	Sparks2_Logic			;sparks anim
 			bra	Fireball_Logic
 			bra	HomingProj1_Logic		;homing, non-directional projectile
 			bra	HorzProj1_Logic			;horizontal directional projectile
 			bra	VertProj1_Logic			;vertical directional projectile
 			bra	DirProj1_Logic			;directional projectile
 			bra	DirProj2_Logic			;directional projectile
 			bra	Scratch_Logic			;Titlepage scratch
			bra	Icon_Logic			;pickup powerup icons
			bra	SpiderBot_Logic			;spider robot
			bra	WaspBot_Logic			;wasp robot
			bra	SteelClan_Logic			;steelclan robot

	

; ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
; Ί ENEMY/OBJECT AI Routine						   Ί
; ΜΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΉ
; Ί This Routine will scan through an AI Table that's made up of a number  Ί
; Ί of entries.  Each entry will be scanned and ALL flagged conditions 	   Ί
; Ί will be tested.  If all flagged conditions are satisfied, the AI	   Ί
; Ί routine will return the new AI Logic setup routine address in A1 and   Ί
; Ί the passable data in d1 (3 bytes).  The Enemy control routine can then Ί
; Ί process this however it needs to.					   Ί
; ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ


AI_Tables		include	aidata.inc
			even

; 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
; T  ?  ?  ?  ?  ?  ?  ?  ?  ?  b  g  a  f  J  D  H  I  W  C  A  G  B  F  R  L  Y  Y  ~Y X  X  ~X

; ~X -	1=Negate X proximity test.  (player must be outside of X proximity area)
; XX -	00=Ignore X Proximity test : 01=Check Right : 10=Check Left : 11=Check Right AND Left.		
; ~Y -	1=Negate Y proximity test.  (player must be outside of Y proximity area)
; YY -	00=Ignore Y Proximity test : 01=Check Below : 10=Check Above : 11=Check Below AND Above.
; L  -	1=Player must be to LEFT of Enemy : 0=n/a.
; R  -	1=Player must be to RIGHT of Enemy : 0=n/a.
; F  -	1=Player must be FACING the Enemy : 0=n/a.
; B  -	1=Player must NOT be facing Enemy (Player must have back to Enemy) : 0=n/a.
; G  -	1=Player must be on the GROUND : 0=n/a.
; A  -	1=Player must be in the AIR : 0=n/a.
; C  -	1=Player must be on a CEILING : 0=n/a.
; W  -	1=Player must be on a WALL : 0=n/a.
; I  -	1=Player must be IDLING : 0=n/a.
; H  -	1=Player must be BEING HIT : 0=n/a.
; D  -	1=Player must be DIEING : 0=n/a.
; J  -	1=Player must be JUMPING : 0=n/a.
; f  -	1=Player must be FALLING : 0=n/a.
; a  -	1=Player must be ATTACKING : 0=n/a.
; g  -	1=Player must be GRABBING : 0=n/a.
; b  -	1=Player must be BLOCKING : 0=n/a.
; ?  -  Not Used
; T  -  1=Table Terminator : 0=New Entry

; EXAPLE AI TABLE ENTRY :

; RAPTOR_AI	AI_CB &		;Condition bits macro.
; 	  	NO,&		;Player must NOT be within X Proximity distance.
; 	  	YES,&		;Proximity test check RIGHT/LEFT.
; 	  	NO,&		;Player must NOT be within Y Proximity distance.
;		YES,&		;Proximity test check ABOVE/BELOW.
;		NO,&		;Player must be to the LEFT of the enemy.
;		NO,&		;Player must be to the RIGHT of the enemy.
;		YES,&		;Player must be FACING the enemy.
;		NO,&		;Player must have BACK towards enemy.
;		YES,&		;Player must be on the GROUND.
;		NO,&		;Player must be in the AIR.
;		NO,&		;Player must be on the CEILING.
;		NO,&		;Player must be on the WALL.
;		NO,&		;Player must be IDLING.
;		NO,&		;Player must be BEING HIT.
;		NO,&		;Player must be DIEING.
;		NO,&		;Player must be JUMPING.
;		NO,&		;Player must be FALLING.
;		NO,&		;Player must be ATTACKING.
;		NO,&		;Player must be GRABBING.
;		NO,&		;Player must be BLOCKING.
;		NO,&		;Player must be ABOVE enemy.
;		NO,&		;Player must be BELOW enemy.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO,&		;Unused.
;		NO		;Unused.	
;		AI_DATA	&	;AI Data macro.
;		$40,&		;Proximity to Player in X.
;		$20,&		;Proximity to Player in Y.
;		HALF_CHANCE,&	;Chance that called routine will NOT be called.
;		1,&		;Enemy data #1.
;		2,&		;Enemy data #1.
;		3,&		;Enemy data #1.
;		0,&		;Future expansion.
;		RaptorBot_INIT	;This routine is called if all conditions are met.	
;		AI_END_LIST	;End of AI list.		


			RSRESET
AI_Bits			rs.l	1
AI_XProx		rs.w	1
AI_YProx		rs.w	1
AI_Rand			rs.b	1
AI_Data1		rs.b	1
AI_Data2		rs.b	1
AI_Data3		rs.b	1
AI_Exp			rs.l	1
AI_Rout			rs.l	1
AI_EntryLen		rs.b	0

AI_Routine		move.l	Plr_Database,a6			;a6 points to plr database
			
.AILoop			move.l	0(a1),a2
			cmp.l	#-1,a2
			beq.s	.NotSatisfied			;end of AI List

			move.l	AI_Bits(a2),d1			;get Condition BIT DATA
  			bmi.s	.NotSatisfied			;end of table
			
			moveq	#0,d3				;index for condition jump table
			moveq	#31-1,d2			;got to test 31 condition codes
.l1			lsr.l	#1,d1				;roll next bit into carry flag
			bcc.s	.NextBIT			;bit=0 so ignore
			jsr	AIConditionTests(pc,d3.w)	;do condition test
			bpl.s	.NextENTRY			;condition wasn't met so exit

.NextBIT		addq.w	#4,d3				;bump index
			dbra	d2,.l1				;next bit
			bra	.Satisfied

.NextENTRY		addq.l	#4,a1				;next entry
			bra	.AILoop				;loop

.Satisfied		move.l	AI_Exclude,d2			;Routine address
			cmp.l	AI_Rout(a2),d2
			beq.s	.NextENTRY
			bsr	Randy 				;do the random test
			and.b	AI_Rand(a2),d6
			bne.s	.NextENTRY			;ohoh didn't make it after all that
			move.b	AI_Data1(a2),d1			;data #1	
			asl.w	#8,d1
			move.b	AI_Data2(a2),d1			;data #2	
			swap	d1			
			move.b	AI_Data3(a2),d1			;data #3
			move.l	AI_Rout(a2),a1
			bra	FlagYES

.NotSatisfied		bra	FlagNO

AIConditionTests	bra	AITestNotProxRightLeft
			bra	AITestProxRightLeft
			bra	AITestNotProxAboveBelow
			bra	AITestProxAboveBelow
			bra	AITestPlrOnLeft
			bra	AITestPlrOnRight
			bra	AITestPlrIsFacing
			bra	AITestPlrIsNotFacing
			bra	AITestPlrOnGround
			bra	AITestPlrInAir
			bra	AITestPlrOnCeiling
			bra	AITestPlrOnWall
			bra	AITestPlrIsIdling
			bra	AITestPlrBeingHit
			bra	AITestPlrIsDieing
			bra	AITestPlrIsJumping
			bra	AITestPlrIsFalling
			bra	AITestPlrIsAttacking								
			bra	AITestPlrIsGrabbing
			bra	AITestPlrIsBlocking
			bra	AITestPlrIsAbove
			bra	AITestPlrIsBelow
			

AITestNotProxRightLeft	bsr	AITNPR
     			bmi	FlagYES
			bra	AITNPL

AITNPR			move.w	OB_Xpos(a0),d6				;nme x pos
			add.w	AI_XProx(a2),d6
			cmp.w	Plr_XPos,d6
			blt	FlagYES
			rts

AITNPL			move.w	OB_Xpos(a0),d6				;nme x pos
			sub.w	AI_XProx(a2),d6
			cmp.w	Plr_XPos,d6
			bgt	FlagYES
			bra	FlagNO

AITestProxRightLeft	bsr	AITPR
     			bpl	FlagNO
			bra	AITPL

AITPR			move.w	OB_Xpos(a0),d6				;nme x pos
			add.w	AI_XProx(a2),d6
			cmp.w	Plr_XPos,d6
			blt	FlagNO
			bra	FlagYES

AITPL			move.w	OB_Xpos(a0),d6				;nme x pos
			sub.w	AI_XProx(a2),d6
			cmp.w	Plr_XPos,d6
			bgt	FlagNO
			bra	FlagYES

AITestNotProxAboveBelow	bsr	AITNPA
			bmi	FlagYES
			bra	AITNPB

AITNPA			move.w	OB_Ypos(a0),d6				;nme x pos
			sub.w	AI_YProx(a2),d6
			cmp.w	Plr_YPos,d6
			bgt	FlagYES
			bra	FlagNO

AITNPB			move.w	OB_Ypos(a0),d6				;nme x pos
			add.w	AI_YProx(a2),d6
			cmp.w	Plr_YPos,d6
			blt	FlagYES
			bra	FlagNO

AITestProxAboveBelow	bsr	AITPA
			bpl	FlagNO
			bra	AITPB

AITPA			move.w	OB_Ypos(a0),d6				;nme x pos
			sub.w	AI_YProx(a2),d6
			cmp.w	Plr_YPos,d6
			bgt	FlagNO
			bra	FlagYES

AITPB			move.w	OB_Ypos(a0),d6				;nme x pos
			add.w	AI_YProx(a2),d6
			cmp.w	Plr_YPos,d6
			blt	FlagNO
			bra	FlagYES

AITestPlrOnLeft		move.w	OB_Xpos(a0),d6
			cmp.w	Plr_XPos,d6
			bgt	FlagYES
			bra	FlagNO

AITestPlrOnRight	move.w	OB_Xpos(a0),d6
			cmp.w	Plr_XPos,d6
			blt	FlagYES
			bra	FlagNO

AITestPlrIsFacing	bsr	AITestPlrOnLeft			;is plr on left of nme?
			bpl.s	.r
			btst.b	#ob_xflp,Plr_Flag1		;yes: so plr must be facing right >
			beq	FlagYES
			bra	FlagNO
.r			btst.b	#ob_xflp,Plr_Flag1		;no: so plr must be facing left <
			bne	FlagYES
			bra	FlagNO

AITestPlrIsNotFacing	bsr	AITestPlrOnLeft			;is plr on left of nme?
			bpl.s	.r
			btst.b	#ob_xflp,Plr_Flag1		;yes: so plr must be facing left <
			bne	FlagYES
			bra	FlagNO
.r			btst.b	#ob_xflp,Plr_Flag1		;no: so plr must be facing right >
			beq	FlagYES
			bra	FlagNO

AITestPlrOnGround	btst.b	#grndmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrInAir		btst.b	#airmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrOnCeiling	btst.b	#ceilmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrOnWall		btst.b	#wallmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrIsIdling	rts

AITestPlrBeingHit	btst.b	#hitmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrIsDieing	rts

AITestPlrIsJumping	tst.b	GolJumpFLG
			bne	FlagYES
			bra	FlagNO

AITestPlrIsFalling	tst.b	GolFallFLG
			bne	FlagYES
			bra	FlagNO

AITestPlrIsAttacking	btst.b	#attkmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrIsGrabbing	btst.b	#grabmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrIsBlocking	btst.b	#blokmode,OB_MasterMode(a6)
			bne	FlagYES
			bra	FlagNO

AITestPlrIsAbove	move.w	OB_Ypos(a0),d6
			cmp.w	Plr_YPos,d6
			bge	FlagYES
			bra	FlagNO

AITestPlrIsBelow	move.w	OB_Ypos(a0),d6
			cmp.w	Plr_YPos,d6
			ble	FlagYES
			bra	FlagNO




