*****************************************************************************
*						    			    *
*	Amiga system takeover framework			    		    *
*	1988 Dave Jones, DMA Design			    		    *
*						    			    *
* Allows killing of system, allowing changing of all display & blitter	    *
* hardware, restoring to normal after exiting.			    	    *
* Memory must still be properly allocated/deallocated upon entry/exit       *
* DOS routines for loading must be called BEFORE killing the system   	    *
*						    			    *
* Written using Devpac2					    		    *
*						    			    *
*****************************************************************************

	section	Framework,code_c	

	incdir		"fast:devpac/include/"
	include 	libraries/dos_lib.i
	include 	exec/exec_lib.i
	include 	hardware/custom.i

Hardware		equ	$dff000
SystemCopper1		equ	$26
SystemCopper2		equ	$32
PortA			equ	$bfe001
ICRA			equ	$bfed01
LeftMouse		equ	6

BackgroundWidth		equ	100	100 bytes wide
ForegroundWidth		equ	92	92  bytes wide
ScreenHeight		equ	192	playing area 192 lines high (12 blocks)
NumberPlanes		equ	3	3 planes in each playfield

BytesPerBackPlane	equ	BackgroundWidth*ScreenHeight
BytesPerForePlane	equ	ForegroundWidth*ScreenHeight
BackgroundMemory	equ	2*NumberPlanes*BytesPerBackPlane
ForegroundMemory	equ	NumberPlanes*BytesPerForePlane
MemNeeded		equ	BackgroundMemory+ForegroundMemory

FullFirepower		equ	0
aliensize		equ	24<<6!3
firedelay		equ	3

*******************************************************************************

start	lea	GraphicsName(pc),a1	open the graphics library purely
	move.l	_SysBase,a6		to find the system copper
	clr.l	d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,GraphicsBase
	lea	DOSName(pc),a1		open the DOS library to allow
	clr.l	d0			the loading of data before
	jsr	_LVOOpenLibrary(a6)	killing the system
	move.l	d0,DOSBase

	move.l	#MemNeeded,d0		properly allocate some chip
	moveq.l	#2,d1			memory for screens etc.
	jsr	_LVOAllocMem(a6)	d1 = 2, specifies chip memory
	tst.l	d0			where screens,samples etc
	beq	MemError		must be (bottom 512K)
	move.l	d0,MemBase

*******************************************************************************

	lea	variables(pc),a5	a5 is the variables pointer
	lea	rasters(a5),a0
	lea	displayraster(a5),a1
	move.l	d0,(a0)+		calculate the address of each plane
	move.l	d0,(a1)+		store them in the variables area,
	add.l	#BytesPerBackPlane,d0	twice for the background as it is
	move.l	d0,(a0)+		double buffered			
	move.l	d0,(a1)+
	add.l	#BytesPerBackPlane,d0
	move.l	d0,(a0)+			
	move.l	d0,(a1)+
	add.l	#BytesPerBackPlane,d0
	move.l	d0,(a0)+			
	add.l	#BytesPerForePlane,d0
	move.l	d0,(a0)+			
	add.l	#BytesPerForePlane,d0
	move.l	d0,(a0)+			
	add.l	#BytesPerForePlane,d0
	move.l	d0,(a0)+			
	move.l	d0,(a1)+
	add.l	#BytesPerBackPlane,d0
	move.l	d0,(a0)+			
	move.l	d0,(a1)+
	add.l	#BytesPerBackPlane,d0
	move.l	d0,(a0)+			
	move.l	d0,(a1)+

	move.l	#Hardware,a6
	jsr	TakeSystem

*******************************************************************************

	move.l	#$dff000,a6		a6 ALWAYS point to base of
	move.l	#-1,bltafwm(a6)		custom chips
	bsr	GameInit
	move.l	#clist,cop1lc(a6)
	move.w	#$87e0,dmacon(a6)	enable copper,sprite,blitter
	move.w	#$7fff,intreq(a6)	clear all int request flags
	move.w	#$0c30,clxcon(a6)

*******************************************************************************

* Main game loop with the routines we are yet to cover commented out

*******************************************************************************

vloop	bsr	waitline223		interrupt set at vertical 
	not.b	vcount(a5)		position 223 (panel start)
	beq	twoblanks		alternate every frame

	lea	copperlist(pc),a1	set up registers for routine
	move.w	pf2scroll(a5),d0	checkpf2
	move.w	pf1scroll(a5),d1
	bsr	checkpf2		and branch to it
	bsr	moveship	
	bsr	check.collision
	bsr	erase.missiles
	bsr	levels.code
	bsr	update.missiles
	bsr	drawfgnds
*	bsr	print.score
*	bsr	check.keys
	bsr	check.path
	bra	vloop
twoblanks	
	bsr	checkpf1		the following routines are only
	bsr	flipbgnd		executed every second frame
	bsr	moveship
	bsr	restorebgnds		restore backgrounds behind aliens
	bsr	process.aliens		
	bsr	save.aliens		save the backgrounds behind aliens
	bsr	draw.aliens		and then draw the aliens

	tst.b	kill.game(a5)	
	beq	vloop
	bra	alldone	

**************************************************************************

waitline223
	btst	#4,intreqr+1(a6)	wait for vertical line 223
	beq	waitline223		interrupt set by the
	move.w	#$10,intreq(a6)		copperlist
return	rts

**************************************************************************

checkpf1
	cmp.w	#3,level.end(a5)	level.end = 3 means 
	beq	return			guardian on, so no scroll
	lea	copperlist(pc),a1
	move.w	pf2scroll(a5),d0	d0 = pf2 scroll value (0-15)
	move.w	pf1scroll(a5),d1	d1 = pf1 scroll value (0-15)
	subq.w	#1,d1			scroll a pixel
	bcs	resetpf1		reset back to 15
checkpf2
	cmp.w	#3,level.end(a5)	as above
	beq	return
	subq.w	#1,d0			scroll a pixel
	bcs	resetpf2		reset to 15 and update pointers
storescroll					
	move.w	d1,pf1scroll(a5)	resave the values
	move.w	d0,pf2scroll(a5)
	move.w	pf1count(a5),d2
	subq.w	#1,d2			check if at the end of the two
	or.w	d1,d2			screens and flag for the sprite
	move.w	d2,screenend(a5)	routine if true	
	lsl.w	#4,d0
	or.w	d0,d1
	move.w	d1,54(a1)		put the new scroll value into 
	rts				the copper list

resetpf1
	moveq	#$f,d1			reset scroll to 15
	subq.w	#1,pf1count(a5)		decrement words scrolled
	bne	storepf1		carry on if not zero
	move.w	#23,pf1count(a5)	otherwise reset the number of
	lea	rasters(a5),a4		words to scroll and reset the 
	lea	displayraster(a5),a3	display planes back to the very
	move.l	(a4)+,(a3)+		start.
	move.l	(a4)+,(a3)+
	move.l	(a4)+,(a3)+		six planes in all
	add.w	#12,a4
	move.l	(a4)+,(a3)+
	move.l	(a4)+,(a3)+
	move.l	(a4)+,(a3)+
	bra	checkpf2		now check pf2
storepf1
	lea	displayraster(a5),a3	increment the plane pointers
	addq.l	#2,(a3)			by a word each
	addq.l	#2,4(a3)		these are background planes
	addq.l	#2,8(a3)		and are therefore double
	addq.l	#2,12(a3)		buffered
	addq.l	#2,16(a3)
	addq.l	#2,20(a3)
	bra	checkpf2

resetpf2
	lea	rasters(a5),a4
	moveq	#$f,d0			reset scroll back to 15
	subq.w	#1,pf2count(a5)		decrement the word scroll
	bne	respf2			value and reset if zero
	move.w	#23,pf2count(a5)
	clr.w	pf2offset(a5)		offset is reverse of pf2count
	cmp.w	#1,level.end(a5)	and is used for the copper
	bne	respf2			level.end = 1 when map finished
	addq.w	#1,level.end(a5)	so start to draw guardian
	bsr	change.colours		setup the guardian colours
	move.w	#6*72,guard.offset(a5)	changes the missiles
respf2 
	move.l	12(a4),d2		get the foreground plane 
	move.l	16(a4),d3		pointers and add the offset to
	move.l	20(a4),d4		them
	addq.w	#2,pf2offset(a5)
	add.w	pf2offset(a5),d2	store these in the copper list
	add.w	pf2offset(a5),d3
	add.w	pf2offset(a5),d4
storepf2
	move.w	d2,30(a1)
	move.w	d3,38(a1)
	move.w	d4,46(a1)
	bra	storescroll

**************************************************************************

flipbgnd	
	lea	copperlist(pc),a1	swap the background displays
	lea	displayraster(a5),a3	every second frame
	move.l	(a3),d4
	move.l	4(a3),d5
	move.l	8(a3),d6
	move.l	12(a3),(a3)
	move.l	16(a3),4(a3)
	move.l	20(a3),8(a3)
	move.l	d4,12(a3)
	move.l	d5,16(a3)
	move.l	d6,20(a3)
	addq	#4,d4			add 4 bytes (32 pixels) to the
	addq	#4,d5			pointers so that clipping can
	addq	#4,d6			be carried out on the left
	move.w	d4,6(a1)		hand side
	swap	d4
	move.w	d4,2(a1)		store the new ones in the copper
	move.w	d5,14(a1)		list
	swap	d5
	move.w	d5,10(a1)
	move.w	d6,22(a1)
	swap	d6
	move.w	d6,18(a1)
	not.b	screen.num(a5)
	rts

**************************************************************************

drawfgnds
	cmp.w	#3,level.end(a5)	3 for guardian fully on
	beq	return
	cmp.w	#2,level.end(a5)	2 for drawing guardian
	beq	draw.guardian
	tst.w	pf2scroll(a5)		every 16 pixels a new strip
	beq	drawbegin		of foreground graphics are
	cmp.w	#$e,pf2scroll(a5)	drawn into a hidden part
	beq	drawend			of the screen
	rts
drawbegin
	bsr	setupblit
	clr.l	d6			d6 = offset into the screen
	move.l	fgndpointer(a5),a0	for the start of the screen
	bsr	drawfgnd		this will be zero
	subq	#1,a0
	move.l	a0,fgndpointer(a5)
	rts

drawend
	bsr	setupblit
	moveq	#46,d6			as the screen is 46 bytes
	move.l	fgndpointer(a5),a0	wide, this is the offset
	cmp.b	#$ff,(a0)		at which to draw the strip
	bne	drawfgnd
	sub.w	#12,a0			the end of map is flagged
	move.l	a0,fgndpointer(a5)	by an FF block number
	move.w	#1,level.end(a5)	flag the end of the map

drawfgnd
	clr.l	d0
	move.b	(a0)+,d0		d0 = block number (0-254)
	lea	rasters(a5),a4		get the current foreground
	move.l	12(a4),d1		plane pointers in d1,d2,d3
	move.l	16(a4),d2
	move.l	20(a4),d3
	add.l	d6,d1			add the offset passed
	add.l	d6,d2
	add.l	d6,d3
	add.w	pf2offset(a5),d1	add the scrolled words
	add.w	pf2offset(a5),d2	offset to each plane
	add.w	pf2offset(a5),d3
	moveq	#11,d7			12 blocks in height
	move.l	#graphics,a4		a4 = base address of the graphics
fgndloop					
	move.l	a4,d4
	mulu	#96,d0			96 bytes per graphic blocks
	ext.l	d0			(2 bytes wide x 16 high
	add.l	d0,d4			 x 3 planes)
	bsr	blitfgnd
	add.l	#ForegroundWidth*16,d1	work out address of 16 scanlines
	add.l	#ForegroundWidth*16,d2	down 
	add.l	#ForegroundWidth*16,d3
	clr.l	d0
	move.b	(a0)+,d0		get next block number
	dbf	d7,fgndloop		and repeat for all 12
	rts

blitfgnd
	move.l	d1,bltdpt(a6)		blit a 16x16 pixel block
	move.l	d4,bltapt(a6)		into the foreground screen
	move.w	#$0401,bltsize(a6)	unmasked with no shift
	add.l	#32,d4
	move.l	d2,bltdpt(a6)
	move.l	d4,bltapt(a6)
	move.w	#$0401,bltsize(a6)
	add.l	#32,d4
	move.l	d3,bltdpt(a6)
	move.l	d4,bltapt(a6)
	move.w	#$0401,bltsize(a6)
	rts

setupblit
	move.w	#$09f0,bltcon0(a6)		minterm for D = A
	clr.w	bltcon1(a6)
	clr.w	bltamod(a6)			data is stored sequentially
	move.w	#ForegroundWidth-2,bltdmod(a6)
	rts

**************************************************************************

buildbackgnd
	lea	rasters(a5),a0
	move.l	(a0),a1			get the background plane pointers
	move.l	4(a0),a2		in a1-a4 (double buffered so 2 sets)
	move.l	24(a0),a3		background graphics are only 4 colour
	move.l	28(a0),a4		(2 planes) so third plane is ignored
	addq	#4,a1			skip the hidden words used for
	addq	#4,a2			clipping
	addq	#4,a3
	addq	#4,a4
	move.l	#backgroundtable,a0	a0 = the background map
	move.w	level.number(a5),d0
	mulu	#144,d0			144 bytes per background map
	add.w	d0,a0
	moveq	#11,d0			12 blocks high
build1	moveq	#11,d1			24 blocks across
	movem.l	a1-a4,-(sp)
build2	move.b	(a0),d2			this loop draws 2 across
	lsr.b	#4,d2			block number stored in 4 bits
	bsr	drawback
	move.b	(a0)+,d2
	and.b	#$f,d2
	tst.w	d1
	beq	skipit
	bsr	drawback
skipit	dbf	d1,build2		do all 24 across
	movem.l	(sp)+,a1-a4
	add.l	#BackgroundWidth*16,a1	next block down the way
	add.l	#BackgroundWidth*16,a2
	add.l	#BackgroundWidth*16,a3
	add.l	#BackgroundWidth*16,a4
	dbf	d0,build1		do all 12 high
	move.l	#$dff000,a6
	rts

drawback
	lea	backgrounds,a6		a6 = the background graphics
	move.w	level.number(a5),d3
	mulu	#1024,d3		1024 bytes per level of background
	add.w	d3,a6			graphics (16 blocks)
	and.w	#$f,d2
	mulu	#64,d2			64 bytes per block
	add.l	d2,a6			(2 bytes x 16 high x 2 planes)
	movem.l	a1-a4,-(sp)
	moveq	#15,d3
drawb1	move.w	(a6),(a1)		draw into both the screens
	move.w	(a6),(a3)
	move.w	(a6),46(a1)		
	move.w	(a6),46(a3)
	move.w	32(a6),(a2)
	move.w	32(a6),(a4)
	move.w	32(a6),46(a4)
	move.w	32(a6),46(a2)
	add.w	#BackgroundWidth,a1
	add.w	#BackgroundWidth,a2
	add.w	#BackgroundWidth,a3
	add.w	#BackgroundWidth,a4
	addq	#2,a6
	dbf	d3,drawb1
	movem.l	(sp)+,a1-a4
	addq	#2,a1			next block along
	addq	#2,a2
	addq	#2,a3
	addq	#2,a4
	rts

**************************************************************************

GameInit
	lea	map,a0
	move.l	a0,fgndpointer(a5)	set up the map index
	move.w	#23,pf1count(a5)	width of the foreground in words
	move.w	#24,pf2count(a5)	width of the background in words
	move.w	#15,pf1scroll(a5)	initial scroll value
	move.w	#15,pf2scroll(a5)
	move.w	#100,xpos(A5)		ships initial x,y & speed
	move.w	#80,ypos(a5)
	move.w	#2,ship.speed(a5)
	move.w	#1,mult.number(a5)
	move.l	#ship1.2,shipaddress(a5) setup address of initial ship
	move.w	#10,path.delay(a5)
	move.w	#5,bonus.count(a5)

	move.w	#128,ship.energy(a5)
	move.w	#$ffff,ship.count(a5)
	move.w	#324-12,d0
	bsr	max.energy
	move.l	#explosion.sequence,explosion.ptr(a5)
	move.l	#guardian+384,guardian.data(a5)
	move.w	#999,guardian.count(a5)
	
	lea	copperlist(pc),a1
	lea	rasters(a5),a0
	move.w	(a0),2(a1)		copy the plane adresses into the
	move.w	2(a0),6(a1)		copperlist
	move.w	4(a0),10(a1)
	move.w	6(a0),14(a1)
	move.w	8(a0),18(a1)
	move.w	10(a0),22(a1)
	move.w	12(a0),26(a1)
	move.w	14(a0),30(a1)
	move.w	16(a0),34(a1)
	move.w	18(a0),38(a1)
	move.w	20(a0),42(a1)
	move.w	22(a0),46(a1)
	addq.w	#4,6(a1)		skip the hidden words in the
	addq.w	#4,14(a1)		background
	addq.w	#4,22(a1)
	lea	scroll.value(pc),a0
	move.w	#$ff,2(a0)

	move.l	#panel+32,d0		put the address of the panel
	lea	rastersplit2(pc),a1	graphics into the copper
	moveq	#3,d1			the panel is 4 planes
setup1	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0
	add.l	#1408,d0		panel size is 352x32 (1408 bytes
	addq	#8,a1			per plane)
	dbf	d1,setup1

	lea	level.colours(pc),a0	copy the level colours into the
	lea	colours(pc),a1		copperlist
	moveq	#31,d0
.copy	move.w	(a0)+,2(a1)
	addq	#4,a1
	dbf	d0,.copy

	lea	panel.colours(pc),a0	copy the panel colours into the
	lea	colours2(pc),a1		copperlist
	moveq	#15,d0
.copy2	move.w	(a0)+,2(a1)
	addq	#4,a1
	dbf	d0,.copy2

	bsr	ship.to.copper		setup the hardware sprite pointers

	bsr	clear.screen
	bsr	buildbackgnd		and draw the background
	bsr	setup.mouse

	IFNE	FullFirepower
	st.b	mult1.on(a5)
	st.b	mult2.on(a5)
	st.b	canons.on(a5)
	st.b	lasers.on(A5)
	move.w	#2,ship.speed(A5)
	move.b	#3,ship.status(a5)	
	bsr	change.ship
	ENDC
	rts


clear.screen
	move.l	rasters(a5),a0		clear all the screen memory
	move.w	#MemNeeded/4-1,d0
clear.scr1
	clr.l	(a0)+
	dbf	d0,clear.scr1
	rts

**************************************************************************

check.collision
	tst.b	ship.dead(a5)			no action taken if he's dead
	bne	return
	move.w	clxdat(a6),d0			get collison value in d0
	bsr	collect.bonus			check if bonus mode
	and.w	#$46,d0
	beq	return				no collision, so return
	tst.w	field.count(a5)			is force field on
	bne	return
	cmp.b	#3,last.path(a5)		is guardian dead
	beq	return
	move.w	ship.count(a5),d2
	and.w	#$6,d0				bits 1 & 2 of clxdat for background
	beq	check3
	tst.b	last.path(a5)
	beq	normal.value			decrease by 8 if guardian path
normal.value
	lsr.w	#5,d2				
	bcc	shield.decrease			
no.decrease
	move.w	d2,ship.count(a5)
	rts
check3
	cmp.w	#2,level.end(a5)
	bge	foreground.hit			guardian always deadly
	tst.w	difficulty(a5)
	beq	return				no effect on easy level
foreground.hit
	lsr.w	#3,d2				on level. This is less than for
	bcs	no.decrease			alien collisons
shield.decrease
	subq.w	#2,ship.energy(a5)		bit 5 of clxdat for foreground
	move.w	ship.energy(a5),d1
	bmi	explode				if shield <0 start the explosion
	move.w	#$ffff,ship.count(a5)		reset secondary count
	move.w	#324-12,d0
	bra	decrease.energy

explode
	st	ship.dead(a5)			flag ship dead
	move.w	xpos(a5),d4
	move.w	ypos(a5),d5
	clr.l	d0				return longword in do
	add.w	#44,d5				hardware offset vertical
	lsl.w	#8,d5				into bits 8-15
	add.w	#128,d4				horizontal offset
	lsr.w	#1,d4				/2 low bit into extend
	or.w	d5,d4				X intact
	move.w	d4,d0				X still intact
	swap	d0				ditto
	roxl.w	#1,d0				get low bit of hstart into bit 0
	add.w	#$1800,d5			calcualate vstop (+24 lines)
	or.w	d5,d0				low word set up
	move.l	d0,d1
	move.l	d0,d2
	add.l	#$00080000,d1			3 sprites for the explosion
	add.l	#$00100000,d2			so each is 16 pixels apart

	lea	ship.explosion,a1
	moveq	#9,d7
setup.sprite
	move.l	d0,(a1)				store the new coords in the ten
	move.l	d1,104(a1)			explosion animations
	move.l	d2,208(a1)
	add.l	#312,a1
	dbf	d7,setup.sprite
	lea	colours(pc),a0
	move.w	#$fd0,70(a0)			copy the explosion colours into
	move.w	#$fd0,86(a0)			the copper
	move.w	#$f80,74(a0)
	move.w	#$f80,90(a0)
	move.w	#$c21,78(a0)
	move.w	#$c21,94(a0)
	
explode.ship
	addq.w	#1,explosion.delay(a5)
	and.w	#%11,explosion.delay(a5)
	bne	return
	move.l	explosion.ptr(a5),a0		points to an animation sequence
	clr.w	d0				ended by 255
	move.b	(a0)+,d0
	bmi	game.over
	move.l	a0,explosion.ptr(a5)
	move.l	#ship.explosion,d1
	mulu	#312,d0				work out the next sprite address
	add.l	d0,d1
	lea	sprite(pc),a0
	moveq	#2,d0
explode1
	move.w	d1,6(a0)			and put it in the copper
	swap	d1
	move.w	d1,2(a0)
	swap	d1
	add.w	#104,d1
	addq.l	#8,a0
	dbf	d0,explode1
	clr.w	2(a0)				make sure outriders are not
	clr.w	6(a0)				displayed
	rts

game.over
	st.b	kill.game(a5)
	rts

collect.bonus
	move.w	d0,d1
	and.w	#$6,d1				was it a foreground hit
	beq	return				if so no bonus
	tst.b	bonus.mode(a5)
	beq	return
	move.w	bonus.num(a5),d1
	beq	bonus.score
	cmp.w	#1,d1
	beq	max.canons
	cmp.w	#2,d1
	beq	max.lasers
	cmp.w	#3,d1
	beq	increase.speed
	cmp.w	#4,d1
	beq	attach.mult
	cmp.w	#5,d1
	beq	force.field

	addq.b	#1,num.shields(a5)
	move.w	#324-12,d0			final one is full shields
	move.w	#128,ship.energy(a5)
	bsr	max.energy
	bra	collect.end	

bonus.score
	move.l	#$1000,score.add(a5)
	bra	collect.end

max.canons
	addq.b	#1,num.canons(a5)
	tst.b	canons.on(a5)			attach canons or power them up
	beq	attach1
	move.w	#676-12,d0
	move.w	#128,canon.energy(a5)
	bsr	max.energy
	bra	collect.end
attach1
	st	canons.on(a5)			activate canons
	addq.b	#1,ship.status(a5)
	bsr	change.ship
	bra	collect.end

max.lasers
	addq.b	#1,num.lasers(a5)
	tst.b	lasers.on(a5)
	beq	attach2
	move.w	#1028-12,d0
	move.w	#128,laser.energy(a5)
	bsr	max.energy
	bra	collect.end
attach2
	st	lasers.on(a5)
	addq.b	#2,ship.status(a5)
	bsr	change.ship
	bra	collect.end

increase.speed
	cmp.w	#8,ship.speed(a5)		
	beq	collect.end
	addq.b	#1,num.speedups(a5)
	addq.w	#1,ship.speed(a5)		pixel speed between		
	bra	collect.end			1 & 7 only

force.field
	addq.b	#1,num.fields(a5)
	move.w	#768,field.count(a5)		set up the force field count
	move.w	#$f,colours+74			make ship outline blue
	bra	collect.end

attach.mult
	tst.b	mult1.on(a5)			attach outriders
	bne	attach.mult2
	st	mult1.on(a5)
	addq.b	#1,num.outriders(a5)
	bra	collect.end
attach.mult2
	addq.b	#1,num.outriders(a5)
	st	mult2.on(a5)

collect.end
	clr.w	d0				no collison
	move.l	#path.buffer,a0
	clr.w	x.pos(a0)			reset the bonus path
	clr.b	bonus.mode(a5)
	move.w	#$ffff,ship.count(a5)
	rts


max.energy
	move.l	#panel,a0			d0 = offset
	add.w	d0,a0
	moveq	#7,d1
max.loop
	or.w	#$5555,(a0)			set all energy bits
	or.w	#$5555,44(a0)
	or.w	#$5555,88(a0)
	addq	#2,a0
	dbf	d1,max.loop
	rts
	
moveship
	tst.b	ship.dead(a5)
	bne	explode.ship
	tst.w	field.count(a5)
	beq	no.field
	move.w	#$f,colours+74
	subq.w	#1,field.count(a5)		decrement the force field
	bne	no.field
	clr.w	colours+74			outline back to black
no.field
	btst	#1,field.count+1(a5)		check lsb
	beq	no.field2
	move.w	#$00c,colours+74
no.field2
	bsr	joy			read joystick & mouse
	tst.w	ypos(a5)		upper y limit of 0
	bge	up.ok
	clr.w	d0			reset up flag if not allowed
	clr.w	yvector(a5)		and no y movement
up.ok	cmp.w	#150,ypos(a5)		maximum y value is 150
	ble	down.ok
	clr.w	d1			if at max signal down no more
	clr.w	yvector(a5)
down.ok	tst.w	xpos(a5)		minimum x position is 0
	bge	left.ok
	clr.w	d3
	clr.w	xvector(a5)
left.ok	cmp.w	#266,xpos(a5)		maximum x position is 266
	ble	right.ok
	clr.w	d2
	clr.w	xvector(a5)
right.ok

	move.w	ship.speed(a5),d4	d4 = ship speed
	move.w	d4,d5			d5 = -ve ship speed
	neg.w	d5				
	clr.w	up.down(a5)		make ship untilt
	move.w	yvector(a5),d7		change the y vector first
up	tst.w	d0			are we going up?
	beq	down			no, so check down	
	move.w	#-560,up.down(a5)	yes, so tilt ship up (anims 560 bytes apart)
	cmp.w	d7,d5			are we at max y speed
	beq	right			yes, so go and check x movement
	subq.w	#1,d7			no, so decrease the vector
	bra	right
down	tst.w	d1			are we going down?
	beq	right			no, so check right
	move.w	#560,up.down(a5)	yes, so tilt the ship down
	cmp.w	d7,d4			are we at max y speed
	beq	right			yes, so check x movement
	addq.w	#1,d7			no, so increase the y vector
right	move.w	d7,yvector(a5)		store the new y vector
	move.w	xvector(a5),d7
	clr.w	d6			now do the x vector which is
	tst.w	d2			virtually identical to the y above
	beq	left
	moveq	#1,d6
	cmp.w	d7,d4
	beq	add.vectors
	addq	#1,d7
	bra	add.vectors
left	tst.w	d3
	beq	add.vectors
	moveq	#-1,d6
	cmp.w	d7,d5
	beq	add.vectors
	subq	#1,d7
add.vectors
	move.w	d7,xvector(a5)

	or.w	d2,d3			if we have moved left or right we
	bne	checky			may have to alter the animation
	move.w	#4,mult.delay(a5)	of the multiples

	moveq	#1,d7			if the ship is not being moved but
	tst.w	xvector(a5)		still has some inertia then decrease
	beq	checky			the x & y vectors until they hit 0
	bmi	xto0
	neg.w	d7
xto0	add.w	d7,xvector(a5)
checky	or.w	d0,d1
	bne	add.vectors2
	moveq	#1,d7
	tst.w	yvector(a5)
	beq	add.vectors2
	bmi	yto0
	neg.w	d7
yto0	add.w	d7,yvector(a5)

add.vectors2
	move.w	xpos(a5),d4		finally add the new vectors to
	move.w	ypos(a5),d5		the x & y coordinates
	add.w	xvector(a5),d4
	add.w	yvector(a5),d5
	move.w	d4,xpos(a5)
	move.w	d5,ypos(a5)
	bsr	xytosprite		convert the xy coords into
	move.l	shipaddress(a5),a0	hardware sprite format
	add.w	up.down(a5),a0		add the up/down offset


	* now set up the four hardware sprite control words

	move.l	d0,(a0)			ship 1.1 (rear end)
	bset	#7,d0
	move.l	d0,184(a0)		ship 1.2 with attach bit set
	add.l	#$0b080000,d0		add 11 to vstart & 16 to hstart
	bclr	#7,d0			reset attach bit
	sub.w	#$0b00,d0		vstop is 11 less
	move.l	d0,2*184(a0)		ship 1.3 (front)
	bset	#7,d0			set attach
	move.l	d0,2*184+96(a0)		ship 1.4
	bsr	ship.to.copper		put the address of the current
	subq.w	#1,mult.delay(a5)	ship in the copper
	bne	same.outrider		and finally work out which multiple 
	move.w	#4,mult.delay(a5)	to display
	add.w	d6,mult.number(a5)	outriders must be between
	bne	max.mult		1 & 5
	move.w	#1,mult.number(a5)
max.mult
	cmp.w	#6,mult.number(a5)
	bne	same.outrider
	move.w	#5,mult.number(a5)
same.outrider
	bsr	draw.outrider		draw the multiple into the sprite
	bra	check.firekey

**************************************************************************

xytosprite
*	d4 = x coordinate
*	d5 = y coordinate
*	returns d0.l as the control words

	clr.l	d0			return longword in do
	add.w	#44-11,d5		hardware offset vertical
	lsl.w	#8,d5			into bits 8-15
	add.w	#128,d4			horizontal offset
	lsr.w	#1,d4			/2 low bit into extend
	or.w	d5,d4			X intact
	move.w	d4,d0			X still intact
	swap	d0			ditto
	roxl.w	#1,d0			get low bit of hstart into bit 0
	add.w	#$2c00,d5		calcualate vstop (+44 lines)
	or.w	d5,d0			low word set up
	rts

**************************************************************************

draw.outrider
	move.w	mult.number(a5),d0	get the animation number
	tst.b	mult1.on(a5)		for the multiple
	bne	mult1ok
	clr.w	d0
mult1ok
	lea	outriders,a0		base address of outriders
	mulu	#44,d0			44 bytes per plane for pair
	add.w	d0,a0
	move.l	a0,a1			a0 = plane 1
	add.w	#264,a1			a1 = plane 2
	move.l	shipaddress(a5),a2	current ship address
	add.w	up.down(a5),a2
	addq	#4,a2			get past sprite header
	movem.l	a0-a2,-(sp)
	moveq	#10,d7			11 lines high
out1	move.w	(a0)+,(a2)+
	move.w	(a1)+,(a2)+
	dbf	d7,out1
	tst.b	mult2.on(a5)
	bne	mult2ok
	lea	outriders,a0		if mult 2 not on then
	move.l	a0,a1			point the data to zeroes
mult2ok
	add.w	#22*2*2,a2		pass the ship graphics
	moveq	#10,d7			and draw the bottom one
out2	move.w	(a0)+,(a2)+
	move.w	(a1)+,(a2)+
	dbf	d7,out2			planes 1 & 2 done

	movem.l	(sp)+,a0-a2		get back pointers
	add.w	#528,a0			a0 = plane 3
	add.w	#528,a1			a1 = plane 4
	add.w	#44*4+8,a2		next sprite
	moveq	#10,d7			11 lines high
out3	move.w	(a0)+,(a2)+
	move.w	(a1)+,(a2)+
	dbf	d7,out3
	tst.b	mult2.on(a5)
	bne	mult3ok
	lea	outriders,a0		if mult 2 not on then
	move.l	a0,a1			point the data to zeroes
mult3ok
	add.w	#22*2*2,a2		pass the ship graphics
	moveq	#10,d7			and draw the bottom one
out4	move.w	(a0)+,(a2)+
	move.w	(a1)+,(a2)+
	dbf	d7,out4			planes 3 & 4 done
	rts


**************************************************************************

check.firekey
	bsr	get.firekey
	bne	fire
	clr.b	firekey(a5)
	rts
fire	tst.w	fire.delay(a5)
	bne	fire.end
	move.w	#firedelay,fire.delay(a5)
	tst.b	firekey(a5)
	beq	test.missiles
	rts
fire.end
	move.w	#firedelay,fire.delay(a5)
	rts
	
get.firekey
	move.b	PortA,d0
	not.b	d0
	and.b	#$c0,d0
	rts

shift.coords
	lea	xpos(a5),a2
	move.w	16(a2),20(a2)
	move.w	18(a2),22(a2)
	move.w	12(a2),16(a2)
	move.w	14(a2),18(a2)
	move.w	8(a2),12(a2)
	move.w	10(a2),14(a2)
	move.w	4(a2),8(a2)
	move.w	6(a2),10(a2)
	move.w	(a2),4(a2)
	move.w	2(a2),6(a2)
	rts

test.missiles
	st	firekey(a5)
	clr.w	d0				0 for missile sound only
	tst.w	canon.energy(a5)
	sne	d1
	and.w	#1,d1				1 for canons only
	tst.w	laser.energy(a5)
	sne	d2
	and.w	#2,d2				2 for lasers only
	add.w	d1,d0
	add.w	d2,d0				3 for all
;	lea	effects(pc),a0
;	move.b	0(a0,d0.w),d0
;	jsr	initfx

	moveq	#3,d7
fire3	btst	d7,activemissiles(a5)
	beq	initmissile
	dbf	d7,fire3

test.canon
	tst.b	canons.on(a5)
	beq	test.lasers
	tst.w	canon.energy(a5)
	beq	test.lasers
	moveq	#2,d7
fire1	btst	d7,activecanons(a5)
	beq	initcanon
	dbf	d7,fire1

test.lasers
	tst.b	lasers.on(a5)
	beq	test.mult1
	tst.w	laser.energy(a5)
	beq	test.mult1
	moveq	#2,d7
fire4	btst	d7,activelasers(a5)
	beq	initlaser
	dbf	d7,fire4

test.mult1
	tst.b	mult1.on(a5)
	beq	test.mult2
	moveq	#1,d7
fire5	btst	d7,activemult1(a5)
	beq	init.mult1
	dbf	d7,fire5

test.mult2	
	tst.b	mult2.on(a5)
	beq	fire7
	moveq	#1,d7
fire6	btst	d7,activemult2(a5)
	beq	init.mult2
	dbf	d7,fire6
fire7
	rts

init.mult1
	bset	d7,activemult1(a5)
	lea	mult1data(a5),a0
	lsl.w	#3,d7
	add.w	d7,a0
	move.w	xpos(a5),d0
	add.w	#38,d0
	move.w	d0,(a0)+
	move.w	ypos(a5),d0
	addq	#6,d0
	move.w	d0,(a0)+
	move.w	mult.number(a5),d0
	subq.w	#1,d0
	lsl.w	#1,d0
	lea	mult1offsets(pc),a1
	move.b	0(a1,d0.w),(a0)+	
	move.b	1(a1,d0.w),(a0)+
	move.w	#16,(a0)+
	bra	test.mult2	

init.mult2
	bset	d7,activemult2(a5)
	lea	mult2data(a5),a0
	lsl.w	#3,d7
	add.w	d7,a0
	move.w	xpos(a5),d0
	add.w	#38,d0
	move.w	d0,(a0)+
	move.w	ypos(a5),d0
	add.w	#40,d0
	move.w	d0,(a0)+
	move.w	mult.number(a5),d0
	subq.w	#1,d0
	lsl.w	#1,d0
	lea	mult2offsets(pc),a1
	move.b	0(a1,d0.w),(a0)+	
	move.b	1(a1,d0.w),(a0)+
	move.w	#16,(a0)+
	rts	

initmissile
	bset	d7,activemissiles(a5)
	lea	missiledata(a5),a0
	lsl.w	#3,d7
	add.w	d7,a0
	move.w	xpos(a5),d0
	add.w	#58,d0
	move.w	d0,(a0)+
	move.w	ypos(a5),d0
	add.w	#24,d0
	move.w	d0,(a0)+
	move.w	#16,(a0)+
	bra	test.canon

initcanon
	bset	d7,activecanons(a5)
	lea	canondata(a5),a0
	lsl.w	#3,d7
	add.w	d7,a0
	move.w	xpos(a5),d0
	add.w	#53,d0
	move.w	d0,(a0)+
	move.w	ypos(a5),d0
	add.w	#30,d0
	move.w	d0,(a0)+
	move.w	#12,(a0)+
	move.w	#676,d0
	subq.w	#2,canon.energy(a5)
	move.w	canon.energy(a5),d1
	bsr	decrease.energy

	bra	test.lasers

initlaser
	bset	d7,activelasers(a5)
	lea	laserdata(a5),a0
	lsl.w	#3,d7
	add.w	d7,a0
	move.w	xpos(a5),d0
	add.w	#42,d0
	move.w	d0,(a0)+
	move.w	ypos(a5),d0
	add.w	#14,d0
	move.w	d0,(a0)+
	move.w	#32,(a0)+
	move.w	#1028,d0
	subq.w	#2,laser.energy(a5)
	move.w	laser.energy(a5),d1
	bsr	decrease.energy
	bra	test.mult1

decrease.energy
	move.l	#panel,a1			d0 = offset
	add.w	d0,a1				d1 = energy value (0-128)
;						324 for ship energy
;						676 for canons
	lsr.w	#4,d1				1028 for lasers
	lsl.w	#1,d1				a1 = plane1
	add.w	d1,a1				
	move.w	(a1),d1
	move.w	d1,d2
	and.w	#$5555,d1			get energy bits only
	and.w	#$aaaa,d2			preserve panel bits
	lsl.w	#2,d1				shift into next space
	or.w	d1,d2
	move.w	d2,(a1)				
	add.w	#44,a1
	move.w	(a1),d2
	and.w	#$aaaa,d2
	or.w	d1,d2				new energy into panel
	move.w	d2,(a1)				
	add.w	#44,a1
	move.w	(a1),d2
	and.w	#$aaaa,d2
	or.w	d1,d2
	move.w	d2,(a1)				
	rts

**************************************************************************

setup.mouse
	move.w	joy0dat(a6),d4		read the mouse x,y position so
	move.w	d4,-(sp)
	and.w	#$ff,d4			the ship doesnt jump when we
	move.w	d4,oldmousex(a5)	start
	move.w	(sp)+,d4
	lsr.w	#8,d4
	move.w	d4,oldmousey(a5)
	rts

joy	move.w	#$0100,d0		setup the mask for each bit in
	move.w	#$0001,d1		the joystick register
	move.w	#$0002,d2		the routine returns left/right
	move.w	#$0200,d3		/up/down in d0..d3
	move.w	joy1dat(a6),d4		if the corresponding data register
	and.w	d4,d0			is not = 0 then the joystick
	and.w	d4,d1			had been pressed in that direction
	and.w	d4,d2
	and.w	d4,d3
	lsl.w	#1,d0
	lsl.w	#1,d1
	eor.w	d2,d1
	eor.w	d3,d0

	move.w	joy0dat(a6),d4		read the mouse counters, if a move
	move.w	d4,-(sp)		has been detected then set the
	and.w	#$ff,d4			appropiate joystick registers
	sub.w	oldmousex(a5),d4	to mimick a joystick move
	beq	noxmove
	bmi	leftmove		this is not a proper proportional
	moveq	#1,d2			read but a simple up/dowm/left/right
	bra	noxmove			check
leftmove
	moveq	#1,d3
noxmove	move.w	(sp),d4
	lsr.w	#8,d4
	sub.w	oldmousey(a5),d4
	beq	joyend
	bmi	upmove
	moveq	#1,d1
	bra	joyend
upmove	moveq	#1,d0
joyend	move.w	(sp),d4
	and.w	#$ff,d4
	move.w	d4,oldmousex(a5)	save the mouse values for comparison
	move.w	(sp)+,d4		next time around
	lsr.w	#8,d4
	move.w	d4,oldmousey(a5)
	rts

**************************************************************************

ship.to.copper
	move.l	shipaddress(a5),a1	get the current ship address
	add.w	up.down(a5),a1		and update the four sprite
	move.l	a1,d0			pointers in the copperlist
	move.l	a1,d1			
	move.l	a1,d2
	move.l	a1,d3	
	add.w	#184,d1			work out the address of each		
	add.w	#184*2,d2		hardware sprite
	add.w	#184*2+96,d3
	lea	sprite(pc),a0
	move.w	d0,6(a0)
	swap	d0
	move.w	d0,2(a0)
	move.w	d1,14(a0)
	swap	d1
	move.w	d1,10(a0)
	move.w	d2,22(a0)
	swap	d2
	move.w	d2,18(a0)
	move.w	d3,30(a0)
	swap	d3
	move.w	d3,26(a0)
	rts

**************************************************************************

change.ship
	clr.w	d0
	move.b	ship.status(a5),d0	1 = canons, 2 = lasers, 3 = both
	lea	ship1.2(pc),a0
	mulu	#1680,d0		968 bytes for the four sprites
	add.l	d0,a0			per ship
	move.l	a0,shipaddress(a5)	store the ship address
	rts

**************************************************************************

restorebgnds
	bsr	getscreeninfo
	clr.w	bltamod(a6)
	move.l	d0,bltapt(a6)		set blitter A channel to the saved
	clr.w	bltcon1(a6)		background data
restoreloop
	move.w	(a0)+,d1		fetch the blit size
	beq	return			once zero all have been replaced
	move.w	d1,d3
	addq	#2,a0
	and.w	#$3f,d1			work out the length in bytes
	lsl.w	#1,d1
	move.w	#100,d2			subtract from the screen width
	sub.w	d1,d2			to give the destination modulo
	move.w	d2,bltdmod(a6)
	move.w	#$09f0,bltcon0(a6)	use D = A for the blit
	move.l	(a0)+,bltdpt(a6)	and do all three planes.
	move.w	d3,bltsize(a6)
	move.l	(a0)+,bltdpt(a6)
	move.w	d3,bltsize(a6)
	move.l	(a0)+,bltdpt(a6)
	move.w	d3,bltsize(a6)
	bra	restoreloop

savebgnds
	bsr	check.end.screen	watch out for screen wraparound
	bsr	coords.to.pf1offsets	convert pixel coords to byte offsets
	move.w	#aliensize,d3
	move.w	#94,bltamod(a6)
	clr.w	bltdmod(a6)
	clr.w	bltcon1(a6)
	move.w	#$09f0,bltcon0(a6)	use D = A for the blit
	bsr	setup.addresses		save the blitsize and addresses
	bsr	blit.to.buffer		and save the background data
	rts

**************************************************************************

drawbobs
	move.w	#94,bltdmod(a6)		set up the destination modulos
	move.w	#94,bltcmod(a6)
	clr.l	d6			d6 will hold an offset if the
	tst.b	upsidedown(a5)		bob is drawn upside down
	beq	normal
	move.w	#-106,bltdmod(a6)	draw from the bottom up by using
	move.w	#-106,bltcmod(a6)	a negative modulo
	move.l	#23*100,d6
normal	move.w	(a0),d3			get the blitsize in d3
	move.w	2(a0),d1		the scroll value in d1 (0-15)
	ror.w	#4,d1
	move.w	d1,bltcon1(a6)		set up the B scroll value
	or.w	#$0fca,d1		set up the A scroll value and the
	move.w	d1,bltcon0(a6)		minterm for D = notA.C + B
	move.w	#-2,bltbmod(a6)
	move.w	#-2,bltamod(a6)
	move.l	a1,bltbpt(a6)
	bsr	blit.to.backgnd		draw to the screen
	rts

**************************************************************************

getscreeninfo
*	returns the address in a0 of the data listing the screeen locations
*	where the backgrounds have to be replaced
*	d0 points to the buffer containing the saved backgrounds

	tst.b	screen.num(a5)		double buffering means we have 
	bne	getscreen1		to have two lists running
	move.l	#buffer0,d0
	move.l	#screen0bgnds,a0
	rts
getscreen1
	move.l	#buffer1,d0
	move.l	#screen1bgnds,a0
	rts

**************************************************************************

process.aliens
	clr.w	all.coords(a5)
	move.l	#path.buffer,a0
	lea	alien.buffer(a5),a1		where to store the info
	moveq	#11,d7				12 aliens max
process.loop
	move.w	table.offset(a0),d0		get offset in d0
	move.b	mode(a0),d6			d6 contains the mode byte
	move.w	x.pos(a0),d1
	beq	finished			alien dead
	clr.w	last.x(a5)
	clr.w	last.y(a5)
	move.w	y.pos(a0),d2
	subq.b	#1,anim.delay(a0)
	bne	same.anim

	move.b	num.anims(a0),d3
	beq	same.anim
	btst	#3,d6
	beq	up.only
	btst	#4,d6
	bne	down.anim
	addq.b	#1,anim.num(a0)			increase anim num
	cmp.b	anim.num(a0),d3
	bne	process1
	bchg	#4,d6
	bra	process1
down.anim
	subq.b	#1,anim.num(a0)
	bpl	process1
	move.b	#1,anim.num(a0)
	bchg	#4,d6
	bra	process1
up.only
	addq.b	#1,anim.num(a0)			next animation
	addq.b	#1,d3
	cmp.b	anim.num(a0),d3			wrap around anims
	bne	process1
	clr.b	anim.num(a0)
	tst.b	sprite.num(a0)			was it an explosion
	bne	process1
	clr.w	x.pos(a0)			yes so
	move.w	d1,last.x(a5)			store its coords
	move.w	d2,last.y(a5)
	clr.w	d1				kill this alien
	bra	finished
process1
	move.b	anim.delay2(a0),anim.delay(a0)	restore the delay
same.anim
	tst.b	sprite.num(a0)		
	beq	finished			dont move explosions
	tst.b	pause.count(a0)
	beq	no.pause			no pause 
	cmp.b	#$ff,pause.count(a0)
	beq	finished			ff means pause forever...
	subq.b	#1,pause.count(a0)
	beq	update				if zero update the offset
	bra	finished			not zero so do nufink
no.pause
	clr.w	d3
	clr.w	d4
	clr.w	d5
	move.b	speed(a0),d5			speed in d5
	move.b	0(a0,d0.w),d3			d3 is the x coord to go to
	move.b	1(a0,d0.w),d4			d4 is the y coord to go to
	bsr	check.seek			check all seek bits
	tst.b	sprite.num(a0)
	beq	store.coords			a heat seeker may have exploded
	btst	#0,d6				test for offset mode
	bne	add.offsets
	tst.w	d3				if x goto is minus then
	bmi	check.y				leave x coord alone
	lsl.w	#1,d3				even coord only
	cmp.w	d3,d1				check difference between the 
	sne	x.equal(a5)			two x coords
	beq	check.y
	blt	increase.x			if d1<d3 then increase x
	sub.w	d5,d1				else decrease it
	cmp.w	d3,d1				has it now passed
	bgt	check.y				the x coord
	move.w	d3,d1				if so, make it equal to the x
	sf	x.equal(a5)
	bra	check.y
increase.x
	add.w	d5,d1
	cmp.w	d3,d1
	blt	check.y				is it still less than x
	move.w	d3,d1
	sf	x.equal(a5)
check.y	tst.w	d4
	bmi	store.coords			check wether to leave y alone
	lsl.w	#1,d4				
	cmp.w	d4,d2				compares d2 to d4
	sne	y.equal(a5)
	beq	store.coords
	blt	increase.y			if d2<d4 then increase y
	sub.w	d5,d2
	cmp.w	d4,d2
	bgt	store.coords
	move.w	d4,d2
	sf	y.equal(a5)
	bra	store.coords
increase.y
	add.w	d5,d2
	cmp.w	d4,d2
	blt	store.coords
	move.w	d4,d2
	sf	y.equal(a5)
	bra	store.coords

add.offsets
	ext.w	d3
	ext.w	d4
	add.w	d3,d1				add the offsets
	add.w	d4,d2
	clr.b	x.equal(a5)			signal to update table
	clr.b	y.equal(a5)

store.coords
	move.w	d1,x.pos(a0)			restore the new coords
	move.w	d2,y.pos(a0)
	move.b	x.equal(a5),d3
	or.b	d3,y.equal(a5)			is the alien there
	bne	finished			no, so dont update the table
	btst	#5,d6				heat seeker ?
	beq	update
	bsr	explode.alien			heat seekers explode when they
	bra	finished			hit their target
update
	btst	#1,d6				check for seek mode
	beq	new.offset
	bsr	copy.coords
	subq.b	#1,seek.count(a0)
	bne	finished
	bclr	#1,d6				reset seek mode
new.offset
	addq.w	#2,d0
	move.w	d0,table.offset(a0)		new offset
	tst.w	0(a0,d0.w)
	beq	path.finished			path finished, so branch
	move.b	0(a0,d0.w),d4			get code in d4 & d3
	move.w	d4,d3
	and.w	#$f0,d4				get upper 4 bits
	cmp.w	#$e0,d4				hex E for a code
	bne	finished			no code so carry on
	and.w	#$f,d3				otherwise get code number in d3
	lsl.w	#2,d3				x4
	lea	vector.table(pc),a2		get table base
	move.l	0(a2,d3.w),a2			get routine address in a2
	jmp	(a2)				and jump to it

vector.table
	dc.l	init.pause
	dc.l	loop.back
	dc.l	toggle.offset
	dc.l	change.speed
	dc.l	change.sprite
	dc.l	seek.mode
	dc.l	reload.coords
	dc.l	new.table
	dc.l	restore.offset
	dc.l	fire.heatseeker
	dc.l	change.anim
	dc.l	restart.table
	dc.l	start.xy
	dc.l	start.seekx
	dc.l	start.seeky
	dc.l	return				16 codes maximum

finished					
	or.w	d1,all.coords(a5)
	move.w	d1,(a1)+			
	move.w	d2,(a1)+			store it all in the 
	move.b	sprite.num(a0),(a1)+		buffer
	move.b	anim.num(a0),(a1)+
	move.b	d6,mode(a0)			save the mode byte
	add.w	next.path(a0),a0
	dbf	d7,process.loop
	rts

path.finished
	clr.w	d1				make x = 0
	clr.w	x.pos(a0)
	btst	#2,d6
	seq 	no.bonus(a5)
	bra	finished

check.seek
	btst	#6,d6				bit 6 for seek on ship x
	beq	check.seeky
	st	y.equal(a5)			make sure it never updates table
	move.w	xpos(a5),d3			get new x coord to goto
	moveq	#-1,d4				signal to leave y alone
	add.w	#54,d3				hardware sprite offset
	lsr.w	#1,d3				even coords only
	subq.b	#1,seek.count(a0)		check count
	bne	check.seeky
	bclr	#6,d6				reset if count zero
check.seeky
	btst	#7,d6				bit 7 for seek on ship y
	beq	check.heat
	st	x.equal(a5)			make sure it never updates table
	move.w	ypos(a5),d4			get new y coord to goto
	moveq	#-1,d3				signal to leave x alone
	add.w	#14,d4				hardware sprite offset
	lsr.w	#1,d4				even coords only
	subq.b	#1,seek.count(a0)		check count
	bne	check.heat
	bclr	#7,d6				reset if count zero
check.heat
	btst	#5,d6				bit 5 for a heat seeking mine
	beq	return				all finished
	move.w	xpos(a5),d3			get new x coord to goto
	move.w	ypos(a5),d4			get new y coord to goto
	add.w	#56,d3				hardware sprite offset
	add.w	#16,d4				hardware sprite offset
	lsr.w	#1,d3				even coords only
	lsr.w	#1,d4				even coords only
	subq.b	#1,seek.count(a0)		check count
	bne	return
	bsr	explode.alien			kill mine if count zero
	rts

init.pause
	move.b	1(a0,d0.w),pause.count(a0)	setup the pause
	bra	finished

loop.back
	clr.w	d3
	move.b	loop.offset(a0),d3		get the loop offset in words
	lsl.w	#1,d3				convert to bytes
	subq.b	#1,loop.count(a0)		reduce the loop counter
	beq	update
	sub.w	d3,table.offset(a0)		and work out the new path PC
	bra	finished

toggle.offset
	bchg	#0,d6				start or end offset mode
	bra	update				get the next path value
				
seek.mode
	bset	#1,d6				set the seek mode bit
	move.b	1(a0,d0.w),seek.count(a0)	copy the count
	addq.w	#2,d0
	move.w	d0,table.offset(a0)
	bsr	copy.coords
	bra	finished

start.seekx
	bset	#6,d6				set the seek on X bit
	move.b	1(a0,d0.w),seek.count(a0)	copy the count
	addq.w	#2,d0
	move.w	d0,table.offset(a0)
	bra	finished

start.seeky
	bset	#7,d6				set the seek on Y bit
	move.b	1(a0,d0.w),seek.count(a0)	copy the count
	addq.w	#2,d0
	move.w	d0,table.offset(a0)
	bra	finished

copy.coords
	move.w	xpos(a5),d3			copy the ship coords
	move.w	ypos(a5),d4			for the seek functions
	add.w	#54,d3				into the path table
	add.w	#14,d4
	lsr.w	#1,d3
	lsr.w	#1,d4
	move.b	d3,0(a0,d0.w)
	move.b	d4,1(a0,d0.w)
	rts

change.speed
	move.b	1(a0,d0.w),speed(a0)		copy the new speed byte
	bra	update

change.sprite
	addq.w	#2,d0
	move.b	0(a0,d0.w),sprite.num(a0)	new sprite number
	move.b	1(a0,d0.w),num.anims(a0)	new max anims
	clr.b	anim.num(a0)			
	move.b	anim.delay2(a0),anim.delay(a0)	new anim delay
	bra	update

reload.coords
	addq	#2,d0
	clr.w	d1				copy a new x,y position
	clr.w	d2				into the sprite structure
	move.b	0(a0,d0.w),d1	
	move.b	1(a0,d0.w),d2
	lsl.w	#1,d1
	lsl.w	#1,d2
	move.w	d1,x.pos(a0)
	move.w	d2,y.pos(a0)
	bra	update	

new.table
	addq.w	#2,d0				setup a new path PC
	move.w	d0,d4				saving the old one in the
	move.b	d4,loop.offset+1(a0)		loop.offset word
	lsr.w	#8,d4
	move.b	d4,loop.offset(a0)
	move.w	0(a0,d0.w),d0
	subq.w	#2,d0
	bra	new.offset

restore.offset
	move.b	loop.offset(a0),d0		restore the old path PC
	lsl.w	#8,d0
	move.b	loop.offset+1(a0),d0
	bra	new.offset

fire.heatseeker
	move.l	#path.buffer,a2			start a new path at the
	moveq	#11,d5				present paths x,y coord
	addq	#2,d0
heat1	btst	#5,mode(a2)			only if a free path entry
	beq	heat2				can be found
	tst.w	x.pos(a2)
	bne	heat2
	move.w	d1,x.pos(a2)
	move.w	d2,y.pos(a2)
	move.b	0(a0,d0.w),seek.count(a2)
	move.b	1(a0,d0.w),hits.num(a2)
	move.b	#2,sprite.num(a2)
	move.b	#2,anim.delay(a2)
	clr.b	anim.num(a2)
	move.b	#3,num.anims(a2)
	bra	new.offset
heat2	add.w	(a2),a2
	dbf	d5,heat1
	bra	new.offset

change.anim
	move.b	1(a0,d0.w),anim.num(a0)		new animation number
	bra	new.offset

restart.table
	move.w	#table.size-2,d0		restart the path from the
	bra	update				beginning

start.xy
	move.b	1(a0,d0.w),d4			get path number to start
	subq.b	#2,d4				cant use path 0
	move.l	a0,-(sp)			save path pointer
	move.l	#path.buffer,a0
find.num
	add.w	next.path(a0),a0
	dbf	d4,find.num			get the path
	move.w	d1,x.pos(a0)			new one starts at present x & y
	move.w	d2,y.pos(a0)
	move.w	d1,d4
	lsr.w	#1,d4
	move.b	d4,table.size(a0)		set up the first xy coord to
	move.w	d2,d4				goto. Must be the same as
	lsr.w	#1,d4				the present xy
	move.b	d4,table.size+1(a0)
	move.w	#table.size,table.offset(a0)	start of path
	move.b	#128,hits.num(a0)		indistrutable
	move.b	#2,anim.delay(a0)
	clr.b	pause.count(a0)
	clr.b	anim.num(a0)			reset anim info
	move.l	(sp)+,a0
	bra	new.offset

**************************************************************************

save.aliens
	lea	alien.buffer+66(a5),a4		the buffer contains
	moveq	#11,d7				word x-cord
	bsr	getscreeninfo			word y-cord
save.alien1					
	move.w	(a4),d1				byte sprite number
	beq	save.next			byte animation number
	move.w	2(a4),d2
	bsr	savebgnds
save.next
	subq	#6,a4
	dbf	d7,save.alien1
	rts

**************************************************************************

draw.aliens
	clr.w	bltalwm(a6)
	moveq	#11,d7
	bsr	getscreeninfo
	lea	alien.buffer+66(a5),a4		work DOWN through
draw.alien2
	tst.w	(a4)				the buffer so that the first
	beq	draw.next2			sprite is drawn first and
	clr.w	d1				therefore hit first.
	clr.w	d2
	move.b	4(a4),d1			d1 = sprite number
	bclr	#7,d1
	sne	upsidedown(a5)
	move.b	5(a4),d2			d2 = animation number
	move.l	#alien.pointers,a1
	move.w	level.number(a5),d3
	mulu	#24*4,d3
	ext.l	d3
	add.l	d3,a1
	lsl.w	#2,d1
	add.w	d1,a1
	move.l	(a1),a1				get the sprite pointer in a1
	mulu	#384,d2				from the lookup table
	ext.l	d2				and then work out the animation
	add.l	d2,a1				number address
	move.l	a1,a2
	add.w	#288,a2				a2 = mask address
	bsr	drawbobs
draw.next2
	subq	#6,a4
	dbf	d7,draw.alien2
	move.w	#$ffff,bltalwm(a6)
	rts	
	
**************************************************************************

blit.to.backgnd
	addq	#4,a0			skip the hidden words
	move.l	(a0)+,d5		get the screen offset
	add.l	d6,d5
	move.l	d5,bltcpt(a6)		setup the screen pointers
	move.l	d5,bltdpt(a6)
	move.l	a2,bltapt(a6)		setup the bob mask
	move.w	d3,bltsize(a6)		and blit the bob to the screen
	move.l	(a0)+,d5
	add.l	d6,d5
	move.l	d5,bltcpt(a6)
	move.l	d5,bltdpt(a6)
	move.l	a2,bltapt(a6)
	move.w	d3,bltsize(a6)		plane 2
	move.l	(a0)+,d5
	add.l	d6,d5
	move.l	d5,bltcpt(a6)
	move.l	d5,bltdpt(a6)
	move.l	a2,bltapt(a6)
	move.w	d3,bltsize(a6)		plane 3
	rts

**************************************************************************

blit.to.buffer
	tst.l	d6			copy the background where a 
	beq	no.blit			bob  is to be drawn into
	move.l	d0,bltdpt(a6)		the buffer
	addq	#4,a0
	move.l	(a0)+,bltapt(a6)
	move.w	d3,bltsize(a6)
	move.l	(a0)+,bltapt(a6)
	move.w	d3,bltsize(a6)
	addq	#4,a0
no.blit	clr.w	(a0)
	add.l	#3*6*24,d0
	rts

**************************************************************************

coords.to.pf1offsets	
*	convert the x,y coordinate in d1,d2 into a byte offset
*	in d1 and a scroll offset (0-15) in d2
			
	add.w	#16,d1
	sub.w	pf1scroll2(a5),d1		d2 = y coord
	mulu	#100,d2				d1 = x coord
	swap	d2
	move.w	d1,d2
	and.w	#$f,d2
	swap	d2
	lsr.w	#3,d1
	add.w	d2,d1
	swap	d2				d2 = scroll value
	ext.l	d1				d1 = offset
	rts

**************************************************************************

coords.to.pf2offsets
*	As the above routine but for the front playfield which is only
*	92 bytes wide

	sub.w	pf2scroll(a5),d1
	mulu	#92,d2
	swap	d2
	move.w	d1,d2
	and.w	#$f,d2
	swap	d2
	lsr.w	#3,d1
	add.w	d2,d1
	swap	d2
	ror.w	#4,d2
	add.w	pf2offset(a5),d1
	ext.l	d1
	rts

**************************************************************************

setup.addresses
*	setup the list of addresses to which bobs are to be blitted

	move.w	d3,(a0)				d3 = blitsize
	move.w	d2,2(a0)			d2 = scroll value
	move.l	(a2),d6				d1 = offset
	add.l	d1,d6				stores the addresses
	cmp.l	4(a0),d6
	beq	dont.save
	move.l	d6,4(a0)			without updating the
	move.l	4(a2),d6			pointer
	add.l	d1,d6
	move.l	d6,8(a0)
	move.l	8(a2),d6
	add.l	d1,d6
	move.l	d6,12(a0)
	rts
dont.save
	clr.l	d6
	add.w	#16,a0
	rts

**************************************************************************

check.end.screen
	tst.w	screenend(a5)
	bne	notend
	lea	rasters(a5),a2
	move.w	#16,pf1scroll2(a5)
	rts
notend	lea	displayraster(a5),a2
	move.w	pf1scroll(a5),pf1scroll2(a5)
	rts

**************************************************************************

check.path
	cmp.b	#1,last.path(a5)
	beq	decrement.counter
	tst.w	all.coords(a5)		wait until all the x coords are 0 
	bne	check.end		before a new path can start
	not.b	bonus.delay(a5)
	bne	check.end		a small delay before the bonus
	tst.b	last.path(a5)		path can start
	bne	start.path
	clr.b	bonus.mode(a5)
	move.w	last.x(a5),d1
	beq	start.path		if all the aliens had been killed
	tst.b	no.bonus(a5)		then we will start the bonus path
	bne	start.path
	move.w	#10,path.delay(a5)
	move.w	last.y(a5),d2
	move.l	paths,a0
	st	bonus.mode(a5)
	clr.w	bonus.num(a5)
	move.w	#5,bonus.count(a5)	setup the bonus path coordinates
	move.w	d1,x.pos+2(a0)
	move.w	d2,y.pos+2(a0)
	clr.b	anim.num+2(a0)
	lsr.w	#1,d2
	move.w	#$0200,d1
	or.w	d2,d1
	move.w	d1,table.size+2(a0)
	bra	copy.path	
check.end
	rts

start.path
	cmp.w	#1,level.end(a5)	start a new path, providing
	beq	return			the guardian is not scrolling on
	cmp.w	#2,level.end(a5)
	beq	return
	cmp.w	#3,level.end(a5)
	beq	check.all
	subq.w	#1,path.delay(a5)
	beq	start.path1
	rts
start.path1
	move.w	#10,path.delay(a5)	start a normal path
	move.w	path.number(a5),d0
	lea	paths,a0
	add.w	d0,a0
	move.l	(a0),d1
	bne	start1
	moveq	#4,d0
	lea	paths,a0
	move.l	4(a0),d1
start1
	addq	#4,d0
	move.w	d0,path.number(a5)
	move.l	d1,a0
copy.path
	clr.w	d0			copy the new path data
	lea	colours(pc),a2		and set up the new alien colours
	move.b	sprite.num+2(a0),d0		get sprite num
	and.b	#$7f,d0
	subq.w	#1,d0
	lea	alien.colours(pc),a1		get colour table
	move.w	level.number(a5),d3
	mulu	#384,d3	
	add.w	d3,a1
	lsl.w	#4,d0				16 bytes per alien
	add.w	d0,a1
	move.w	(a1)+,2(a2)			copy 8 colours
	move.w	(a1)+,6(a2)			
	move.w	(a1)+,10(a2)			
	move.w	(a1)+,14(a2)			
	move.w	(a1)+,18(a2)			
	move.w	(a1)+,22(a2)
	move.w	(a1)+,26(a2)
	move.w	(a1)+,30(a2)
	move.w	(a0)+,d0
	move.l	#path.buffer,a1
	lsr.w	#2,d0
copyloop
	move.l	(a0)+,(a1)+
	dbf	d0,copyloop
	clr.b	no.bonus(a5)
	rts

**************************************************************************

update.missiles
	tst.w	fire.delay(a5)
	beq	.skip
	subq.w	#1,fire.delay(a5)

.skip	move.l	#missiletable,a0		used for erasing 
	move.w	level.number(a5),d0
	mulu	#72,d0				72 bytes per missile graphics
	lea	missiles1(pc),a1		base address
	add.w	d0,a1				level missiles
	add.w	#32,a1				cannon offset
	add.w	guard.offset(a5),a1		different for guardian
	lea	missilemask+32(pc),a3
	lea	rasters(a5),a2
	lea	canondata+24(a5),a4
	move.l	#fgnd.buffer,d6
	move.w	#%101000010,d3			size for canon
	moveq	#3,d7
update1	btst	d7,activecanons(a5)		check canons first
	beq	update2
	move.w	(a4),d1				x coordinate in d1
	move.w	2(a4),d2			y coordinate in d2
	subq.w	#1,4(a4)			check range
	beq	killcanon			it's dead
	addq.w	#8,d1				move 8 pixels
	cmp.w	#360,d1
	bcc	killcanon			is it offscreen
	move.w	d1,(a4)				restore it
	bsr	draw.missile			and draw it
	bne	update2				
	move.w	(a4),d1
	move.w	2(a4),d2
	add.w	#12,d1				canon tip
	addq.w	#4,d2				middle of canon
	bsr	kill.alien
	beq	update2				zero, so it was'nt an alien
	bclr	d7,activecanons(a5)		canon hit alien, so kill it
update2	subq	#8,a4				work down thru buffer
	dbf	d7,update1			check for 4

	move.w	level.number(a5),d0
	mulu	#72,d0				72 bytes per missile graphics
	lea	missiles1(pc),a1		base address
	add.w	d0,a1				level missiles
	add.w	#16,a1				missile offset
	add.w	guard.offset(a5),a1		different for guardian
	lea	missilemask+16(pc),a3
	lea	missiledata+24(a5),a4
	move.w	#%10000010,d3			size for missiles
	moveq	#3,d7
update3	btst	d7,activemissiles(a5)
	beq	update4
	move.w	(a4),d1				x coordinate in d1
	move.w	2(a4),d2			y coordinate in d2
	subq.w	#1,4(a4)			check range
	beq	killmissile			it's dead
	add.w	#10,d1				move 10 pixels
	cmp.w	#360,d1
	bcc	killmissile			is it offscreen
	move.w	d1,(a4)				restore it
	bsr	draw.missile			and draw it
	bne	update4				
	move.w	(a4),d1
	move.w	2(a4),d2
	addq.w	#8,d1				missile tip
	addq.w	#2,d2				middle of missile
	bsr	kill.alien
	beq	update4				zero, so it was'nt an alien
	bclr	d7,activemissiles(a5)		missile hit alien, so kill it
update4	subq	#8,a4				work down thru buffer
	dbf	d7,update3			check for 4

	move.w	level.number(a5),d0
	mulu	#72,d0				72 bytes per missile graphics
	lea	missiles1(pc),a1		base address
	add.w	d0,a1				level missiles
	add.w	guard.offset(a5),a1		different for guardian
	lea	missilemask(pc),a3
	lea	laserdata+24(a5),a4
	move.w	#%10000010,d3			size for lasers
	moveq	#3,d7
update5	btst	d7,activelasers(a5)
	beq	update6
	move.w	(a4),d1				x coordinate in d1
	move.w	2(a4),d2			y coordinate in d2
	subq.w	#1,4(a4)			check range
	beq	killlaser			it's dead
	add.w	#16,d1				move 16 pixels!
	cmp.w	#360,d1
	bcc	killlaser			is it offscreen
	move.w	d1,(a4)				restore it
	bsr	draw.missile			and draw it
	bne	update6				
	move.w	(a4),d1				dont kill lasers
	move.w	2(a4),d2
	add.w	#16,d1				laser tip
	bsr	kill.alien
	beq	update6
	move.b	bonus.mode(a5),d5
	or.b	last.path(a5),d5
	beq	update6				kill lasers when guardian on
	bclr	d7,activelasers(a5)
update6	subq	#8,a4				work down thru buffer
	dbf	d7,update5			check for 4

	lea	mult(pc),a1			finally check mults
	lea	multmask(pc),a3
	lea	mult1data+8(a5),a4
	move.w	#%11000010,d3			size for mults
	moveq	#1,d7
update7	btst	d7,activemult1(a5)
	beq	update8
	move.w	(a4),d1				x coordinate in d1
	move.w	2(a4),d2			y coordinate in d2
	subq.w	#1,6(a4)			check range
	beq	killmult1			it's dead
	move.b	4(a4),d4
	ext.w	d4
	add.w	d4,d1				
	cmp.w	#360,d1
	bge	killmult1			is it offscreen
	cmp.w	#16,d1
	blt	killmult1
	move.w	d1,(a4)				restore it
	move.b	5(a4),d4
	ext.w	d4
	add.w	d4,d2				
	cmp.w	#186,d2
	bge	killmult1			is it offscreen
	cmp.w	#9,d2
	blt	killmult1
	move.w	d2,2(a4)			restore it
	
	bsr	draw.missile			and draw it
	bne	update8				
	move.w	(a4),d1				
	move.w	2(a4),d2
	addq	#1,d1				mult middle
	addq	#1,d2
	bsr	kill.alien
	beq	update8
	bclr	d7,activemult1(a5)
update8	subq	#8,a4				work down thru buffer
	dbf	d7,update7			check for 4

	lea	mult2data+8(a5),a4
	moveq	#1,d7
update9	btst	d7,activemult2(a5)
	beq	update10
	move.w	(a4),d1				x coordinate in d1
	move.w	2(a4),d2			y coordinate in d2
	subq.w	#1,6(a4)			check range
	beq	killmult2			it's dead
	move.b	4(a4),d4
	ext.w	d4
	add.w	d4,d1				
	cmp.w	#360,d1
	bge	killmult2			is it offscreen
	cmp.w	#16,d1
	blt	killmult2
	move.w	d1,(a4)				restore it
	move.b	5(a4),d4
	ext.w	d4
	add.w	d4,d2				
	cmp.w	#184,d2
	bge	killmult2			is it offscreen
	cmp.w	#9,d2
	blt	killmult2
	move.w	d2,2(a4)			restore it
	
	bsr	draw.missile			and draw it
	bne	update10				
	move.w	(a4),d1				
	move.w	2(a4),d2
	addq	#1,d1				mult middle
	addq	#1,d2
	bsr	kill.alien
	beq	update10
	bclr	d7,activemult2(a5)
update10
	subq	#8,a4				work down thru buffer
	dbf	d7,update9			check for 4
	rts					all finished.

killcanon
	bclr	d7,activecanons(a5)		kill a canon etc.
	bra	update2
killmissile
	bclr	d7,activemissiles(a5)
	bra	update4
killlaser
	bclr	d7,activelasers(a5)
	bra	update6	
killmult1
	bclr	d7,activemult1(a5)
	bra	update8	
killmult2
	bclr	d7,activemult2(a5)
	bra	update10

kill.alien
	move.l	a0,-(sp)
	tst.b	bonus.mode(a5)
	bne	hit.bonus
	move.l	#path.buffer,a0
	moveq	#11,d5
kill.alien.loop
	tst.b	sprite.num(a0)
	beq	try.next			dont check explosions
	move.w	x.pos(a0),d4
	beq	try.next			alien's dead
	sub.w	#16,d4
	cmp.w	d4,d1				is d1 > xpos
	blt	try.next
	add.w	#32,d4
	cmp.w	d4,d1				is d1 < xpos+32
	bgt	try.next
	move.w	y.pos(a0),d4
	cmp.w	d4,d2				is d2 > ypos
	blt	try.next
	add.w	#24,d4
	cmp.w	d4,d2				is d2 < ypos+24
	bgt	try.next
	btst	#7,hits.num(a0)
	bne	no.more				indistructable ?
	cmp.b	#3,sprite.num(a0)
	seq	hit.guardian(a5)
	subq.b	#1,hits.num(a0)			found an alien
	beq	check.which			not dead yet though!
	move.w	#$0106,d0			not dead sound!
;	jsr	initfx
	bra	no.more
check.which
	cmp.b	#3,sprite.num(a0)
	bne	not.guardian
	move.b	#2,last.path(a5)
not.guardian
	bsr	explode.alien
	move.l	alien.score(a5),score.add(a5)	the score
	move.w	kills.what(a0),d0
	move.l	#path.buffer,a0
	moveq	#11,d5
kill.more
	lsr.w	#1,d0
	bcc	kill.next	
	bsr	explode.alien
	move.l	#$0750,score.add(a5)
kill.next
	tst.w	next.path(a0)
	beq	resetz
	add.w	next.path(a0),a0
	dbf	d5,kill.more
resetz
	and.b	#0,ccr				z reset = a hit				
	bra	no.more
try.next
	add.w	next.path(a0),a0
	dbf	d5,kill.alien.loop
	or.b	#4,ccr				z set = no hit
no.more
	move.l	(sp)+,a0
	rts

explode.alien
	clr.b	anim.num(a0)			start the explosion
	clr.b	sprite.num(a0)
	move.b	#7,num.anims(a0)
	move.b	#2,anim.delay(a0)
	move.b	#2,anim.delay2(a0)
	bclr	#3,mode(a0)			up animate only
	move.w	d0,-(sp)
	move.w	#$0101,d0
;	jsr	initfx
	move.w	(sp)+,d0
	rts

hit.bonus
	movem.l	a1-a2/d0,-(sp)
	move.w	#$0113,d0
;	jsr	initfx
	subq.w	#1,bonus.count(a5)
	bne	hit.end
	move.w	#5,bonus.count(a5)
	move.w	bonus.num(a5),d1
	cmp.w	#6,d1
	beq	hit1
	addq	#1,d1
hit1	move.w	d1,bonus.num(a5)
	move.l	#path.buffer,a0
	move.b	d1,anim.num(a0)
hit.end
	movem.l	(sp)+,a1-a2/d0
	move.l	(sp)+,a0
	rts	


draw.missile
	movem.w	d1-d2,-(sp)			save for later
	bsr	coords.to.pf2offsets		convert to ofsset
	bsr	or.foregnds			a1 = missile sprite
	move.l	d6,d5				a3 = mask
	move.w	d3,d0				d5 & d6 = foreground buffer
	lsr.w	#4,d0				height*4 = number of bytes in 
	add.w	d0,d6				a an or'd foreground
	clr.w	bltcmod(a6)
	clr.w	bltamod(a6)
	clr.w	bltdmod(a6)
	clr.w	bltbmod(a6)
	move.l	a1,bltapt(a6)			a = sprite
	move.l	a3,bltbpt(a6)			b = mask
	move.l	d6,bltdpt(a6)			dest = buffer+height*4
	move.w	d2,bltcon1(a6)			c = buffer
	or.w	#$0f40,d2			use D = A.B.notC
	move.w	d2,bltcon0(a6)			which shows only where missile
	move.l	d5,bltcpt(a6)			can be drawn
	move.w	d3,bltsize(a6)
	move.l	d5,bltcpt(a6)
	move.w	d3,bltsize(a6)

	move.w	#88,bltdmod(a6)
	move.w	#88,bltbmod(a6)
	clr.w	bltcon1(a6)
	move.w	#$0dfc,bltcon0(a6)		D = A or B
	move.l	d6,bltapt(a6)			the new buffer being the mask only
	move.l	(a0),bltbpt(a6)			drawing where there is no 
	move.l	(a0)+,bltdpt(a6)		foreground
	move.w	d3,bltsize(a6)
	move.l	(a0),bltbpt(a6)
	move.l	(a0)+,bltdpt(a6)
	move.w	d3,bltsize(a6)
	clr.w	(a0)

	movem.w	(sp)+,d1-d2
	add.w	#16,d1
	move.w	pf1scroll(a5),pf1scroll2(a5)	copy scroll
	bsr	coords.to.pf1offsets		get pf1 offset
	ror.w	#4,d2				shift the scroll value
	or.w	#$aa0,d2			use D = A.C
	move.w	d2,bltcon0(a6)			with D turned off
	move.l	a1,bltapt(a6)			a1 = sprite
	move.l	a0,-(sp)
	lea	displayraster(a5),a0
	move.l	20(a0),d0
	move.l	(sp)+,a0
	add.l	d1,d0
	move.l	d0,bltcpt(a6)			d0 = background
	move.w	#96,bltcmod(a6)
	move.w	d3,bltsize(a6)			d3 = blitsize
	btst	#5,dmaconr(a6)
	rts

or.foregnds
	move.w	#88,bltamod(a6)			or the two foregrounds together
	move.w	#88,bltbmod(a6)
	clr.w	bltdmod(a6)
	move.w	d3,(a0)+			store the blitsize in the buffer
	move.l	12(a2),d0
	add.l	d1,d0
	move.l	d0,(a0)				store the plane 2 address
	move.l	d0,bltapt(a6)
	move.l	16(a2),d0
	add.l	d1,d0
	move.l	d0,4(a0)			store the plane 4 address
	move.l	d0,bltbpt(a6)
	clr.w	bltcon1(a6)
	move.w	#$0ffc,bltcon0(a6)		use D = A or B
	move.l	d6,bltdpt(a6)			d6 = foreground buffer
	move.w	d3,bltsize(a6)
	rts

erase.missiles
	move.l	#missiletable,a0
	move.l	#fgnd.buffer,a1
	clr.w	bltcon1(a6)
	clr.w	bltamod(a6)			a = or'd fgnd
	move.w	#$0dc0,bltcon0(a6)		D=A.B
	move.w	#88,bltbmod(a6)			b = foreground
	move.w	#88,bltdmod(a6)			d = foreground
eraseloop
	move.w	(a0),d0				d0 = blitsize								
	beq	eraseend			zero if end
	clr.w	(a0)+
	move.w	d0,d1
	lsr.w	#4,d1
	move.l	(a0),bltbpt(a6)
	move.l	(a0)+,bltdpt(a6)
	move.l	a1,bltapt(a6)
	move.w	d0,bltsize(a6)
	move.l	(a0),bltbpt(a6)
	move.l	(a0)+,bltdpt(a6)
	move.l	a1,bltapt(a6)
	move.w	d0,bltsize(a6)
	add.w	d1,a1
	bra	eraseloop
eraseend
	rts

**************************************************************************

draw.guardian
	cmp.w	#$e,pf2scroll(a5)
	bne	no.draw
	move.w	guardian.frame(a5),d0
	cmp.w	#16,d0
	beq	no.draw
	mulu	#24,d0
	ext.l	d0
	move.l	#guardian,a0
	add.l	d0,a0
	move.l	guardian.data(a5),a1
	lea	rasters+12(a5),a4
	move.l	(a4)+,a2
	move.l	(a4)+,a3
	move.l	(a4),a4
	moveq	#46,d6
	add.l	d6,a2
	add.l	d6,a3
	add.l	d6,a4
	add.w	pf2offset(a5),a2
	add.w	pf2offset(a5),a3
	add.w	pf2offset(a5),a4
	moveq	#92,d5
	moveq	#23,d7
drawg1	moveq	#7,d6
	move.b	(a0)+,d0
drawg2	btst	d6,d0
	bne	draw.data
	clr.w	(a2)
	clr.w	(a3)
	clr.w	(a4)
	bra	donext
draw.data
	move.w	(a1)+,(a2)
	move.w	(a1)+,(a3)
	move.w	(a1)+,(a4)
donext	add.l	d5,a2
	add.l	d5,a3
	add.l	d5,a4
	dbf	d6,drawg2
	dbf	d7,drawg1
	move.l	a1,guardian.data(a5)	
	addq.w	#1,guardian.frame(a5)
no.draw	cmp.w	#6,pf2count(a5)
	bne	return
	cmp.w	#8,pf2scroll(a5)
	bne	return
	addq.w	#1,level.end(a5)
	rts

change.colours
	lea	colours+32(pc),a2
	moveq	#7,d7
	lea	guard.colours,a3
	move.w	level.number(a5),d2
	lsl.w	#4,d2
	add.w	d2,a3
change1	move.w	(a3)+,2(a2)
	addq	#4,a2
	dbf	d7,change1
	rts


levels.code
	tst.b	hit.guardian(a5)
	beq	return
	lea	colours+50(pc),a0
	tst.b	colour.updown(a5)
	bne	colour.down
	add.w	#$100,(a0)
	cmp.w	#$f00,(a0)
	seq	colour.updown(a5)
	rts
colour.down
	sub.w	#$100,(a0)
	cmp.w	#$700,(a0)
	bne	return
	not.b	colour.updown(a5)
	clr.b	hit.guardian(a5)
	rts


decrement.counter
	tst.w	guardian.count(a5)
	beq	death.path
	subq.w	#1,guardian.count(a5)
	rts
death.path
	move.l	#path.buffer,a0
	add.w	next.path(a0),a0
	tst.b	sprite.num(a0)
	beq	wait.explosion
	moveq	#10,d7
ex.loop	bsr	explode.alien
	move.w	next.path(a0),d0
	beq	return
	add.w	d0,a0
	dbf	d7,ex.loop
	rts
wait.explosion
	tst.w	x.pos(a0)
	bne	return
	move.l	#paths,a0
find.path3
	tst.l	(a0)+
	bne	find.path3
	addq	#8,a0
	move.l	(a0),a0
	move.b	#$ff,last.path(a5)
	bra	copy.path

check.all
	tst.b	last.path(a5)
	beq	start.guard.path
	cmp.b	#2,last.path(a5)
	beq	explosion.path
	cmp.b	#3,last.path(a5)
	seq.b	kill.game(a5)
	rts

start.guard.path
	move.l	#paths,a0
;	moveq	#0,d0
;	jsr	Initune
find.path
	tst.l	(a0)+
	bne	find.path
	move.l	(a0),a0
	move.b	#1,last.path(a5)
	bra	copy.path

explosion.path
	move.l	#paths,a0
find.path2
	tst.l	(a0)+
	bne	find.path2
	addq	#4,a0
	move.l	(a0),a0
	move.b	#3,last.path(a5)
;	jsr	Turnoff
	bra	copy.path

**************************************************************************


clist		DC.W	$0A01,$FF00
copperlist	DC.W	bplpt+0,$0000,bplpt+2,$0000
		DC.W	bplpt+8,$0000,bplpt+10,$0000
		DC.W	bplpt+16,$0000,bplpt+18,$0000
		DC.W	bplpt+4,$0000,bplpt+6,$0000
		DC.W	bplpt+12,$0000,bplpt+14,$0000
		DC.W	bplpt+20,$0000,bplpt+22,$0000
		DC.W	bplcon0,$6600
scroll.value	DC.W	bplcon1,$00FF,bpl1mod,$0036
		DC.W	bpl2mod,$002E,bplcon2,$0044
		DC.W	ddfstrt,$0028,ddfstop,$00D8
		DC.W	diwstrt,$1F78,diwstop,$FFC6

colours		DC.W	color+0,$0000,color+2,$0000
		DC.W	color+4,$0000,color+6,$0000
		DC.W	color+8,$0000,color+10,$0000
		DC.W	color+12,$0000,color+14,$0000
		DC.W	color+16,$0000,color+18,$0000
		DC.W	color+20,$0000,color+22,$0000
		DC.W	color+24,$0000,color+26,$0000
		DC.W	color+28,$0000,color+30,$0000
		DC.W	color+32,$0000,color+34,$0000
		DC.W	color+36,$0000,color+38,$0000
		DC.W	color+40,$0000,color+42,$0000
		DC.W	color+44,$0000,color+46,$0000
		DC.W	color+48,$0000,color+50,$0000
		DC.W	color+52,$0000,color+54,$0000
		DC.W	color+56,$0000,color+58,$0000
		DC.W	color+60,$0000,color+62,$0000

sprite		DC.W	sprpt+0,$0000,sprpt+2,$0000
		DC.W	sprpt+4,$0000,sprpt+6,$0000
		DC.W	sprpt+8,$0000,sprpt+10,$0000
		DC.W	sprpt+12,$0000,sprpt+14,$0000
		DC.W	sprpt+16,$0000,sprpt+18,$0000
		DC.W	sprpt+20,$0000,sprpt+22,$0000
		DC.W	sprpt+24,$0000,sprpt+26,$0000
		DC.W	sprpt+28,$0000,sprpt+30,$0000

		DC.W	$DF01,$FF00
		DC.W	bplcon1,$0000,bplcon0,$4200,ddfstrt,$0030
rastersplit2	DC.W	bplpt+0,$0000,bplpt+2,$0000
		DC.W	bplpt+4,$0000,bplpt+6,$0000
		DC.W	bplpt+8,$0000,bplpt+10,$0000
		DC.W	bplpt+12,$0000,bplpt+14,$0000
colours2	DC.W	color+20,$0000,color+30,$0000
		DC.W	color+2,$0000,color+4,$0000
		DC.W	color+6,$0000,color+8,$0000
		DC.W	color+10,$0000,color+12,$0000
		DC.W	color+14,$0000,color+16,$0000
		DC.W	color+18,$0000,color+22,$0000
		DC.W	color+24,$0000,color+26,$0000
		DC.W	color+28,$0000,color+0,$0000
		DC.W	bpl1mod,$0000,bpl2mod,$0000
		DC.W	$DF01,$FF00,intreq,$8010
		DC.W	$FFFF,$FFFE


panel.colours	DC.W	$0600,$0333,$0fb3,$0d00,$0b00,$0720,$0fc2,$0c90
		DC.W	$0a40,$0eb0,$0eca,$0456,$0577,$0252,$0444,$0000


mult1offsets
	DC.B	5,0,5,-5,0,-5,-5,-5,-5,0
mult2offsets
	DC.B	5,0,5,5,0,5,-5,5,-5,0

explosion.sequence
	dc.b	0,1,2,3,4,5,6,7,8,9,10,-1

	rsreset
screen.num	RS.B	1	
vcount		RS.B	1	vertical blank counter
mult1.on	RS.B	1	byte set if a multiple is attached to ship
mult2.on	RS.B	1	same for another multiple (2 max)
canons.on	RS.B	1	bytes are set to signify what weapons
lasers.on	RS.B	1	are attached
ship.status	RS.B	1	values to indicate which ship to draw
activecanons	RS.B	1
activemissiles	RS.B	1
activelasers	RS.B	1
activemult1	RS.B	1
activemult2	RS.B	1
firekey		RS.B	1
ship.dead	RS.B	1
num.speedups	RS.B	1
num.outriders	RS.B	1
num.fields	RS.B	1
num.canons	RS.B	1
num.lasers	RS.B	1
num.shields	RS.B	1
kill.game	RS.B	1
hit.guardian	RS.B	1
colour.updown	RS.B	1

ship.speed	RS.W	1	speed in pixels
xpos		RS.W	1	ship x position
ypos		RS.W	1	ship y position
mult.number	RS.W	1	multiple animation number
mult.delay	RS.W	1	multiple animation delay
xvector		RS.W	1	inertia vectors for the ship
yvector		RS.W	1
oldmousex	RS.W	1	store the old mouse values to reference
oldmousey	RS.W	1	the new ones to
up.down		RS.W	1	this holds the graphic offset for a ship tilt

pf1count	RS.W	1	number of background words to scroll
pf2count	RS.W	1	number of foreground words to scroll
pf1scroll	RS.W	1	pixel scroll value (0-15) background
pf2scroll	RS.W	1	pixel scroll value (0-15) foreground
pf1scroll2	RS.W	1
pf2offset	RS.W	1
screenend	RS.W	1
level.end	RS.W	1
level.number	RS.W	1
canon.energy	RS.W	1	
laser.energy	RS.W	1
fire.delay	RS.W	1
ship.energy	RS.W	1
ship.count	RS.W	1
field.count	RS.W	1
difficulty	RS.W	1
guard.offset	RS.W	1

path.delay	RS.W	1
last.x		RS.W	1	x coord of last killed alien
last.y		RS.W	1	y coord of last killed alien
path.number	RS.W	1
all.coords	RS.W	1	zero if all aliens are dead
x.equal		RS.B	1
y.equal		RS.B	1
upsidedown	RS.B	1	draw alien upside down
no.bonus	RS.B	1	alien finished path so no bonus
last.path	RS.B	1
bonus.mode	RS.B	1	bonus icon on screen
bonus.num	RS.W	1	current bonus
bonus.count	RS.W	1	number of hits to change bonus
bonus.delay	RS.B	1
explosion.delay RS.W	1
guardian.frame	RS.W	1
guardian.count	RS.W	1

missiledata	RS.L	8
canondata	RS.L	8
laserdata	RS.L	8
mult1data	RS.L	4
mult2data	RS.L	4
score		RS.L	1
score.add	RS.L	1
alien.score	RS.L	1
fgndpointer	RS.L	1	foreground map pointer
displayraster	RS.L	6	holds the addresses of the planes
rasters 	RS.L	9	updated plane addresses
shipaddress	RS.L	1	ship animation address
alien.buffer	RS.L	18
explosion.ptr	RS.L	1
guardian.data	RS.L	1

vars.length	RS.B	0
variables	DS.B	vars.length

*		*********************************
*		*	Data structures		*
*		*********************************

	rsreset
next.path	RS.W	1			offset to the next path
x.pos		RS.W	1			current x position
y.pos		RS.W	1			current y position
kills.what	RS.W	1			kills others if dead (0-11)
table.offset	RS.W	1			the current table offset
sprite.num	RS.B	1			sprite number
anim.num	RS.B	1			animation number
anim.delay	RS.B	1			delay in 1/25 secs
anim.delay2	RS.B	1			static delay
speed		RS.B	1			speed in pixels
pause.count	RS.B	1			dynamic pause counter
mode		RS.B	1			flags, see bleow
loop.offset	RS.B	1			loop offset (-ve)
loop.count	RS.B	1			dynamic loop count
hits.num	RS.B	1			number of hits to kill
num.anims	RS.B	1			no of animations
seek.count	RS.B	1			dynamic seek count
table.size	RS.B	0

* This is followed by x,y bytes to move to (always even) with the following
* special codes

*	x = 0, path finished, terminate alien
*	x = $e0, perform a pause (up to 10 secs), followed by the pause value, $ff forever
*	x = $e1, perform the loop
*	x = $e2, toggle the offset mode
*	x = $e3, speed change, followed by new speed byte
*	x = $e4, sprite change, followed by sprite num, max anims
*	x = $e5, start seek mode, followed by count & two 0 bytes
*	x = $e6, reload the aliens x,y coords, followed by two xy bytes
*	x = $e7, reload the table offset, old one stored in loop.offset
*	x = $e8, restore the old table offset
*	x = $e9, fire a heat seeker, followed by count
*	x = $ea, new animation number, followed by animation number
*	x = $eb, repeat table indefinitely

*	mode bit 0 = offset mode
*	     bit 1 = seek mode
*	     bit 2 = 
*	     bit 3 = up/down animation type
*	     bit 4 = 0-animate up/1-animate down
*	     bit 5 = heat seeker path


backgroundtable	DC.W	$0123,$0123,$0123,$0123,$0123,$0123 background
		DC.W	$4567,$4567,$4567,$4567,$4567,$4567 map
		DC.W	$89AB,$89AB,$89AB,$89AB,$89AB,$89AB
		DC.W	$0123,$0123,$0123,$0123,$0123,$0123
		DC.W	$4567,$4567,$4567,$4567,$4567,$4567
		DC.W	$89AB,$89AB,$89AB,$89AB,$89AB,$89AB
		DC.W	$0123,$0123,$0123,$0123,$0123,$0123
		DC.W	$4567,$4567,$4567,$4567,$4567,$4567
		DC.W	$89AB,$89AB,$89AB,$89AB,$89AB,$89AB
		DC.W	$0123,$0123,$0123,$0123,$0123,$0123
		DC.W	$4567,$4567,$4567,$4567,$4567,$4567
		DC.W	$89AB,$89AB,$89AB,$89AB,$89AB,$89AB

backgrounds	DC.W  $1430,$0C30,$0C10,$0413,$8403,$4442,$2142,$3120
		DC.W  $3110,$2810,$141C,$1417,$140B,$0C71,$0A00,$DC08
		DC.W  $8A08,$9208,$0229,$8208,$4244,$2221,$12A1,$0891
		DC.W  $0888,$148A,$0A03,$2A48,$8A44,$9208,$8524,$2204

		DC.W  $0210,$0230,$1118,$0118,$8128,$414C,$314C,$10CA
		DC.W  $1005,$1013,$5103,$31C3,$5023,$D011,$3018,$6304
		DC.W  $0129,$0908,$0884,$0884,$4294,$22A2,$08A2,$0825
		DC.W  $0842,$0908,$2880,$C824,$2890,$2808,$0904,$1092

		DC.W  $0300,$4220,$0461,$0451,$0850,$08C8,$38C8,$1848
		DC.W  $0848,$0848,$0848,$08C8,$0148,$1050,$E060,$4041
		DC.W  $2084,$2110,$2210,$0228,$0429,$1424,$0424,$0424
		DC.W  $8424,$8424,$8424,$8424,$80A4,$8828,$1011,$2420

		DC.W  $1430,$0C08,$0800,$0413,$8083,$4442,$2242,$2120
		DC.W  $2110,$2810,$040C,$1487,$104B,$0C71,$0A10,$D908
		DC.W  $8A08,$9000,$042D,$8008,$4244,$2221,$1121,$0091
		DC.W  $0888,$048A,$0A03,$2240,$8220,$9208,$8124,$2004

		DC.W  $7028,$6218,$8218,$C208,$C210,$C210,$6420,$2420
		DC.W  $4820,$4820,$8843,$0882,$108C,$2118,$2220,$4421
		DC.W  $0914,$1104,$4104,$2504,$2508,$2508,$9250,$1250
		DC.W  $2450,$2410,$4420,$8441,$0840,$1080,$1110,$A210

		DC.W  $C60C,$C60A,$4609,$2209,$A201,$A223,$9011,$901F
		DC.W  $900C,$8C18,$0620,$060F,$0213,$0404,$1405,$1419
		DC.W  $2102,$2105,$2104,$5104,$5124,$5110,$4908,$4900
		DC.W  $4902,$4204,$8912,$0900,$2508,$0212,$4A02,$EA04

		DC.W  $0080,$0100,$0110,$0918,$0A14,$0A33,$8A31,$0621
		DC.W  $0220,$8204,$8204,$860D,$860A,$8A0C,$0108,$0101
		DC.W  $4940,$0888,$8888,$8484,$852A,$8508,$4508,$8110
		DC.W  $4911,$4902,$490A,$4102,$4905,$4502,$8084,$9088

		DC.W  $7028,$4318,$8298,$C248,$8250,$C210,$6120,$20A0
		DC.W  $5820,$4820,$8813,$188A,$108C,$2100,$2220,$4421
		DC.W  $0914,$1004,$4144,$2504,$4528,$2528,$9290,$1010
		DC.W  $2010,$2410,$4428,$8405,$0842,$1080,$1100,$A210

		DC.W  $8820,$0440,$0204,$1202,$8221,$8220,$8300,$8410
		DC.W  $C080,$0180,$20C0,$6040,$7060,$31A1,$2820,$2820
		DC.W  $4410,$8A24,$0122,$8921,$4910,$4110,$4090,$4208
		DC.W  $2448,$8048,$1020,$1220,$0910,$0850,$9492,$1412

		DC.W  $CE02,$4A02,$5402,$0442,$0844,$9048,$E148,$4150
		DC.W  $23A0,$31C4,$3185,$3842,$2820,$11A0,$23A0,$6322
		DC.W  $0101,$2501,$2A01,$9221,$9422,$68A4,$10A4,$A0A8
		DC.W  $1050,$0822,$0842,$04A1,$1412,$8850,$5051,$1091

		DC.W  $3100,$11C0,$10C1,$10E1,$4862,$8850,$9850,$88F0
		DC.W  $E830,$7031,$0028,$8248,$4088,$4018,$2018,$3018
		DC.W  $0881,$0821,$0820,$0810,$2411,$5429,$44A9,$4408
		DC.W  $0408,$0808,$8114,$4124,$2144,$2104,$1224,$0844

		DC.W  $C820,$4440,$2204,$1002,$8225,$8224,$8308,$8418
		DC.W  $C980,$1188,$20C4,$6040,$6260,$2121,$2820,$2820
		DC.W  $0410,$AA24,$1122,$8921,$4912,$0110,$4094,$4380
		DC.W  $2448,$8844,$1020,$1220,$0110,$0850,$9492,$1412

level.colours
		DC.W	$0332,$0055,$0543,$0000,$0000,$0000,$0000,$0000
		DC.W	$0000,$0F55,$0B05,$0700,$08A7,$0182,$0065,$0055
		DC.W	$0000,$0FF6,$0000,$0FD0,$0A00,$0BDF,$06AF,$004F
		DC.W	$0FFF,$0CDD,$0ABB,$0798,$0587,$0465,$0243,$0E32


alien.colours	DC.W	$0332,$0055,$0543,$0000,$0DFF,$06AC,$036A,$0038 level1
		DC.W	$0332,$0055,$0543,$0000,$0FE0,$0DA0,$0B62,$0900
		DC.W	$0332,$0055,$0543,$0000,$0FE0,$0DA0,$0B62,$0900
		DC.W	$0332,$0055,$0543,$0000,$0DE9,$0FE0,$0F90,$0D32
		DC.W	$0332,$0055,$0543,$0000,$0FE0,$0DA0,$0B62,$0900
		DC.W	$0332,$0055,$0543,$0000,$09E7,$06A0,$0D00,$0460
		DC.W	$0332,$0055,$0543,$0DDF,$099E,$0569,$0348,$0235
		DC.W	$0332,$0055,$0543,$0FFC,$0FF2,$0DE9,$0BC6,$09A4
		DC.W	$0332,$0055,$0543,$09FF,$0AF5,$03DF,$01BF,$008F
		DC.W	$0332,$0055,$0543,$0F77,$08A7,$0385,$0265,$0722
		DC.W	$0332,$0055,$0543,$0F66,$08A7,$0283,$0065,$0700
		DC.W	$0332,$0055,$0543,$0F66,$08A7,$0283,$0065,$0700
		DC.W	$0332,$0055,$0543,$0F66,$08A7,$0283,$0065,$0700
		DC.W	$0332,$0055,$0543,$0B85,$0DDA,$0C00,$0952,$0700
		DC.W	$0332,$0055,$0543,$0D8C,$0B5A,$000E,$0937,$0705
		DC.W	$0332,$0055,$0543,$0E00,$0A98,$0B60,$0832,$0733
		DC.W	$0332,$0055,$0543,$0E00,$0A98,$0B60,$0832,$0733
		DC.W	$0332,$0055,$0543,$0E00,$0A98,$0B60,$0832,$0733
		DC.W	0,0,0,0,0,0,0,0
		DC.W	0,0,0,0,0,0,0,0
		DC.W	0,0,0,0,0,0,0,0
		DC.W	0,0,0,0,0,0,0,0
		DC.W	0,0,0,0,0,0,0,0
		DC.W	0,0,0,0,0,0,0,0

guard.colours
		DC.W	$0000,$0A00,$0D22,$0E77,$0700,$0FDD,$0A73,$0C90

*******************************************************************************
*******************************************************************************

alldone
	bsr	FreeSystem

MemError
	move.l	_SysBase,a6
	move.l	MemBase,a1
	move.l	#MemNeeded,d0		free the memory we took
	jsr	_LVOFreeMem(a6)
	move.l	GraphicsBase,a1	
	jsr	_LVOCloseLibrary(a6)
	move.l	DOSBase,a1		finally close the 
	jsr	_LVOCloseLibrary(a6)	libraries
	clr.l	d0
	rts

*******************************************************************************

TakeSystem
	move.w	intenar(a6),SystemInts		save system interupts
	move.w	dmaconr(a6),SystemDMA		and DMA settings
	move.w	#$7fff,intena(a6)		kill everything!
	move.w	#$7fff,dmacon(a6)
	move.b	#%01111111,ICRA			kill keyboard
	move.l	$68,Level2Vector		save these interrupt vectors
	move.l	$6c,Level3Vector		as we will use our own 
	rts					keyboard & vblank routines

FreeSystem
	move.l	Level2Vector,$68	restore the system vectors
	move.l	Level3Vector,$6c		and interrupts and DMA
	move.l	GraphicsBase,a1			and replace the system
	move.l	SystemCopper1(a1),Hardware+cop1lc	copper list
	move.l	SystemCopper2(a1),Hardware+cop2lc
	move.w	SystemInts,d0
	or.w	#$c000,d0
	move.w	d0,intena(a6)
	move.w	SystemDMA,d0
	or.w	#$8100,d0
	move.w	d0,dmacon(a6)
	move.b	#%10011011,ICRA	keyboard etc back on
	rts

*******************************************************************************

Level2Vector		dc.l	0
Level3Vector		dc.l	0
SystemInts		dc.w	0
SystemDMA		dc.w	0
MemBase			dc.l	0
DOSBase			dc.l	0
GraphicsBase		dc.l	0

	even
GraphicsName	dc.b	'graphics.library',0
	even
DOSName		dc.b	'dos.library',0

*******************************************************************************

graphics	incbin	:foregrounds
shipbase	include	:ships.s
paths		include	:paths.s
map		incbin	:map
panel		incbin	:panel
aliens		incbin	:aliens
bonus.sprite	include	:bonus.s
mine		include :mine.s
guardian	incbin	:guardian

missiletable	ds.b	512

alien.pointers
explosion1	equ	aliens
guardian.eye1	equ	explosion1+(9*384)
tadpole		equ	guardian.eye1+(4*384)
eye		equ	tadpole+(4*384)
bubble		equ	eye+(15*384)
jellyfish1	equ	bubble+(4*384)
jellyfish2	equ	jellyfish1+(4*384)
bordertl	equ	jellyfish2+(4*384)
borderbl	equ	bordertl+(6*384)
bordertr	equ	borderbl+(6*384)
borderbr	equ	bordertr+(6*384)
mouth		equ	borderbr+(6*384)
slime		equ	mouth+(8*384)
snakebody	equ	slime+(9*384)
snakehead	equ	snakebody+(1*384)

	dc.l	explosion1
	dc.l	bonus.sprite
	dc.l	mine
	dc.l	guardian.eye1
	dc.l	explosion1
	dc.l	tadpole
	dc.l	eye
	dc.l	bubble
	dc.l	jellyfish1
	dc.l	jellyfish2
	dc.l	bordertl
	dc.l	borderbl
	dc.l	bordertr
	dc.l	borderbr
	dc.l	mouth
	dc.l	slime
	dc.l	snakebody
	dc.l	snakehead
	ds.l	6

path.buffer	ds.b	2048
buffer0		ds.b	6144
buffer1		ds.b	6144
screen0bgnds	ds.b	256
screen1bgnds	ds.b	256
fgnd.buffer	ds.b	2048
	end

                          