	.title		"CROSSBOW for Atari 7800"

;	10/2/87		Started by Scott Marshall
;	12/17/87	Milestone #1 delivered
;	2/1/88		Milestone #2 delivered
;	2/16/88		Milestone #3 delivered
;	2/24/88		Milestone #4 delivered
;	3/14/88		Milestone #5 delivered
;	4/6/88		Milestone #6 delivered
;	4/18/88		Milestone #7 delivered
;
;
	.include	"\\INCLUDE\\MARIA.S"	;maria equates and some macros
	.include	"BM\\ADDR.S"		;bitmap addresses
	.include	"MACROS.S"		;special-purpose macros
	.include	"EQUATES.S"
	.include	"AUDEQU.S"		;audio equates
	.include	"VARS.S"		;all variables
;
;	set the bank

setbank	7
;
;	choose if debug examine is enabled for compiling. If true,
;	the finish quest sequence after killing the face is disabled
;
EXAMINE	equ	FALSE
;
	.org	CODE	;fixed ROM $C000 .. $FFFF
;
;	load in the ROM data tables
;
	.include	"TABLES.S"
;
;	the executable code
;
; place for IRQ to attach
;
dummy:
	rti

main:		
;
;	initialize hardware
;
	lda	#$7	;lock in 7800 mode
	sta	PTCTRL

	sei		;block interrupts
	cld		;clear decimal mode

	lda	#0
	sta	OFFSET	;future expansion
	sta	PTCTRL	;avoid joystick freeze

	ldx	#$FF	;init stack
 	txs
;
;	init high score
;
	jsr	initscore	;clear score to zero
	jsr	newhiscore	;clear hi score
;
restart0:		;from hitting SELECT during a game

	lda	#$7f	;turn MARIA off
	sta	CTRL
;
;	init audio
;
	lda	#$FF
	sta	soundon
	lda	#0
	tax
	sta	spriority,x
	sta	shistory,x
	jsr	setav
	inx
	sta	spriority,x
	sta	shistory,x
	jsr	setav
;
;	Initialize software
;
;	Maria zones and headers
;
;	Copy zone list from ROM to RAM (MARIA can't read it from ROM)
;
	ldx	#0
.loop1:	dex
	lda	romzon,x
	sta	ramzon,x
	txa
	bne	.loop1
;
;	make the vblank header
;
	lda	#%01000000	;5 byte to set write mode
	sta	vblhdr+1
	lda	#SCWP		;offscreen to the right
	sta	vblhdr+4
	lda	#0		;2nd header null
	sta	vblhdr+6
;
;	initialize application
;
;
;	set switch states
;
	lda	SWCHB	;console
	sta	oldsw
	lda	SWCHA	;joystick
	sta	oldjs
*
***** added by Dave S. 5-Jul-88
*
*   init default state of gun mode based on "UP" bit of left joystick
*
	ldx	#$ff	;assume gun
	and	#$10	;see if lite gun likely to be installed
	beq	.gunok	;power-up UP means probable gun
	ldx	#0	;else, do 'stick
.gunok:
	stx	gun	;init this guy
*
***** end Dave's addition
*
	lda	#0	;turn off
	sta	selecton ;select
	sta	pauseon	;pause,
	sta	left	;and js
	sta	right
	sta	up
	sta	down

	sta	faddir	;fader init
	sta	fadtim
;
;	gun/stick option init
;
	lda	gun		;if 0 or FF, this is a warm start
	beq	.warmstart	;so don't clear this flag
	eor	#$FF
	beq	.warmstart
	lda	#0
	sta	gun
.warmstart:
;
;	init rand
;
	jsr	initrand
;
;	Set up Maria zone and header lists
;
;	clear screen
;
	jsr	clearsc
;
;	init fader
;
	jsr	cutout
;
;	setup interrupts
;
	jsr	clrijt1
;
;	init MARIA to 160 x 2 mode
;
	lda	#(ramzon & $ff)	;zone addr low
	sta	DPPL

	lda	#(ramzon >> 8)	;zone addr high
	sta	DPPH

	jsr	waitvbl		;wait for vert blank
;
;	TURN MARIA ON
	lda	#%01000000	;color,DMA on,CW 2,border on,transp,160x2
	sta	CTRL

	jsr	waitvbl		;wait while MARIA reads 5-byte header
	lda	#0		;null vbl header to buy future time
	sta	vblhdr+1
;
;	main program loop (forever)
;
mainloop:

	jsr	doattr	;attract mode
restart:		;from hitting RESET
	lda	#FALSE
	sta	idlemode
	sta	pauseon
	jsr	cutout
	ldx	#$FF
	txs

	jsr	doplay	;play game
	jsr	doend	;say "the end"
	jmp	mainloop
;
;	do attract mode
;
doattr:
	lda	#TRUE
	sta	idlemode	;turns true if fire button down

.loop:	jsr	dotitle
	beq	.exit
	lda	#DESERT
	jsr	doselfplay
	beq	.exit
	jsr	dotitle
	beq	.exit
	lda	#TOWN
	jsr	doselfplay
	bne	.loop
.exit:
	makesound	UWILLDA
	makesound	UWILLDB
	jsr	fadeoutwait
	rts
;
;	title screen
;
dotitle:
	lda	#TITLE
	sta	cursc

	jsr	setupsc

	makeheaders	crsbwhdr
	maketall	logotall
	jsr	titlerags

	jsr	fadeinwait
	jsr	showselect
	ldx	#4
	jsr	doidlewait
	jsr	fadeout
	jsr	doidlefade
	lda	idlemode	;set return flag
	rts
;
;	idle fade .. wait for fade done or idlemode going low
;
doidlefade:
	jsr	waitbot
	jsr	dofades
	lda	idlemode
	beq	.exit
	lda	faddir
	bne	doidlefade
.exit:	rts
;
;	do self-play
;
doselfplay:
	sta	cursc
	jsr	clrbh
	jsr	initrand
	jsr	setroster
	jsr	nextsc
	jsr	fadeout
	jsr	doidlefade

	lda	idlemode	;set return flag
	rts
;
;	do idle wait .. call with 4 second units in x reg, returns when
;	time elapsed or idlemode false
doidlewait:

	lda	#$FF
	sta	clock
.loop:	pushx
	jsr	waitbot
	jsr	dofades
	popx
	lda	clock
	bne	.nodec
	dex
	beq	.exit
.nodec:
	lda	idlemode
	bne	.loop
.exit:
	rts
;
;	init score (clear to zero)
;
initscore:
	lda	#0		;init score
	sta	score

	lda	#LDZERO		;blank leading zeroes
_curdig	set	1

.rept	SCRDGTS-1		;assembly loop
	sta	score+_curdig
_curdig	set	_curdig+1
.endr
rts
;
;	set roster (friends joined and potential)
;
setroster:
	lda	#JOINED
	sta	frstat+HERO
	sta	frstat+WOMAN
	sta	frstat+DWARF
	lda	#POTENTIAL
	sta	frstat+NEGRO
	sta	frstat+MONK
	sta	frstat+GIRL
	sta	frstat+WIMP
	sta	frstat+MERLIN
	rts
;
;	do play mode
;
doplay:
;
;	clear been-here record
;
	jsr	clrbh
;
;	set these things false
;
	lda	#FALSE
	sta	gavewarning
	sta	gameover
;
;	set current screen
;
	lda	#MAP ;should be MAP	;set current and previous screen
	sta	cursc
	sta	prevsc
;
;	clear the list of map paths
;
	ldx	#NUMBPATHS-1
	lda	#FALSE
.loop:	sta	pathmem,x
	dex
	bpl	.loop
;
;	init score
;
	jsr	initscore
;
;	set roster of friends
;
	jsr	setroster
;
;	play until gameover
;
.nextscloop:
	jsr	waitbot
	jsr	clearsc
	jsr	nextsc
	jsr	fadeoutwait
	lda	gameover	;exit if game over
	beq	.nextscloop
	rts
;
;	next screen jump table
;	reads cursc (current screen), jumps to right subroutine
nextsc:
	lda	cursc
	asl
	tay
	lda	jmptab,y
	sta	jaddr
	lda	jmptab+1,y
	sta	jaddr+1
	jmp	(jaddr)
;
;	clear been here table
;
clrbh:
	ldx	#NUMBSCRS-1
	lda	#0
.loop:	sta	beenhere,x
	dex
	bpl	.loop
	rts	
;
;	each screen has its own function
;	the game screens are called using the jump table
;	do the map screen
;
domap:
	jsr	waitbot
	jsr	clearsc

	jsr	setupsc
	setpal	0,1,BLACK	;loadpals doesn't set these, so we set them here
	setpal	0,2,BLUE
	setpal	0,3,GRAY
	setpal	1,1,RED+1

	makeheaders	iconhdrs
;
;	left and right ragged edges
;
	maketall	raglr2
;
;	draw in black all connecting paths that player has already taken
;
	ldy	#NUMBPATHS-1	;set loop counter
.loop:	lda	pathmem,y	;if not walked on, don't draw
	beq	.skip
	tya			;convert pointer from byte to word
	asl
	tax
	lda	pathlist,x	;get data
	sta	addrl
	lda	pathlist+1,x
	sta	addrh

	pushy
	jsr	readhdrs	;draw the lines
	popy

.skip:	dey
	bpl	.loop
;
;
;	path buttons
;
;	read path table to decide 2 or 3 paths
;
	lda	prevsc
	asl
	asl
	tay
	lda	pathtab+2,y
	sta	path3
;
;
;	switch to two-path or three-path according to sign of path3
;
	bmi	twopaths

	lda	#p3hdrs & $FF	;3 paths
	sta	addrl
	lda	#p3hdrs >> 8
	sta	addrh
	lda	#SCWP/3		;set dividing lines for buttons
	sta	redline
	lda	#(SCWP/3)*2
	sta	greenline
	jmp	end3p
twopaths:
	lda	#p2hdrs & $FF	;2 paths
	sta	addrl
	lda	#p2hdrs >> 8
	sta	addrh
	lda	#SCHWP		;set dividing lines for buttons
	sta	redline
	lda	#SCWP
	sta	greenline
end3p:
;
	jsr	readhdrs
;
	jsr	doscore

	jsr	lockbkg		;lock background
;
;	setup interrupts
;
	jsr	waitbot

	setijt	INTZ2,intgrnd1
	setijt	INTZ0,intgrnd2	;blink button backgrounds

	jsr	fadeinwait

	lda	#0	;set clock for blink
	sta	clock

	lda	#20
	sta	timeout	;start timeout

.maploop:
	jsr	waitclear
	jsr	docursor
	jsr	doblink
	jsr	setcursor
	lda	movsta+N_CURSOR
	and	#S_NOTHREAT	;test for cursor firing
	bne	.maploop
	makesound	FIRE
	lda	movy+N_CURSOR	;fire button, check for cursor not over buttons
	cmp	#ZONEHL-5	;below buttons?
	bmi	.maploop		;yes, loop
	cmp	#(ZONEHL*3)-5	;above buttons?
	bpl	.maploop		;yes, loop

	lda	movx+N_CURSOR	;on a button, read x
	clc
	adc	#5		;fudge, compensate in doblink
	cmp	redline		;red?
	bmi	.choosered
	cmp	greenline	;green?
	bmi	.choosegreen
	lda	#CHOOSEBLUE	;blue.
	jmp	.break
.choosered:
	lda	#CHOOSERED
	jmp	.break
.choosegreen:
	lda	#CHOOSEGREEN
.break:
	sta	choice		;store player's choice

	clc			;set pal so line is drawn in button color
	adc	#1
	asl
	asl
	asl
	asl
	asl
	sta	subpal

	jsr	clrmov		;erase cursor to make room in header list

	lda	prevsc		;calc choice in 2d matrix of paths
	asl
	asl
	clc
	adc	choice
	tay

	lda	pathtab,y	;now we know the next screen
	sta	cursc

	ldx	pathmatrix,y	;find out which path to draw on screen
	lda	#TRUE
	sta	pathmem,x	;register that we're drawing this path
	txa			;convert byte to word
	asl
	tax
	lda	pathlist,x	;get header data for this path
	sta	addrl
	lda	pathlist+1,x
	sta	addrh
	jsr	readhdrs2	;draw the new lines
;
	lda	#BLACK		;kill blink
	sta	ground1
	sta	fadgrnd1
	makesound	CUCKOO
;
;	timeout
;
	lda	#ONESEC
	jsr	waitalarm

	rts
;
;	do blink, also the 20 sec map limit
;
doblink:
	lda	clock	;timeout 20 seconds
	and	#%00111111
	bne	.notyet
	dec	timeout
	bne	.notyet

	lda	#ZONEHL		;time is up .. set cursor on path buttons
	sta	movy+N_CURSOR
	jsr	rand160		;random x pos
	sec
	sbc	#5		;compensate for fudge in maploop
	sta	movx+N_CURSOR
	lda	#0		;activate
	sta	movsta+N_CURSOR
.notyet:
	lda	clock
	ror
	ror
	ror
	ror
	and	#1
	tay
	lda	.blinkcolors,y
	sta	ground1
	sta	fadgrnd1
	rts
.blinkcolors:	.dc.b	BLACK,YELLOW+2
;
;	do the cave screen
;
docave:
	jsr	dogtrdy
	maketall	cavtall
	jsr	lockbkg
	jsr	initfrs
	jsr	initcavet
	jsr	initeye
	jsr	initsnowman
	jsr	initices
	jsr	initbat
	jsr	initfsts	;path enable falling stal.

	jsr	waitbot

	jsr	domites		;ready on fadein
	jsr	dofsts
	ldx	#N_CAVET
	jsr	dotreasure

	makesound	BATCRY
	jsr	fadeinwait
	makesound	BATCRY
;
;	cave loop
;
.caveloop:
	jsr	waitclear
	jsr	doeye
	jsr	dosnowman
	jsr	dofsts		;falling stalactites that enable path
	jsr	dobat
	jsr	dofrs		;do friend
	ldx	#N_CAVET
	jsr	dotreasure
	jsr	doices		;do enemy
	jsr	domites		;onlayed stalagmites

	jsr	cpst		;cursor, points, score, threats, exit flag
	ldx	#N_CAVET
	jsr	checktreasure

	lda	activefrs
	bne	.caveloop

	jsr	checkend	;gameover?
	bne	.exit

	jsr	waitclear
	jsr	domites		;put onlays into background

	jsr	levelcomp	;level completed

	lda	cursc		;set previous screen
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
.exit:	rts
;
;	do stalagmites
;
domites:
	setbaddr	(MITE1+3)	;top half of mite 1
	ldpw	BKGPAL,3
	sta	palwid
	lda	#3
	sta	curzon
	lda	#10
	sta	hpos
	jsr	mkhdr

	lda	#2			;bottom half
	sta	curzon
	lda	#(MITE1 & $FF)
	sta	baddrl
	jsr	mkhdr

	lda	#(MITE2 & $FF)		;mite 2
	sta	baddrl
	lda	#37
	sta	hpos
	jsr	mkhdr

	lda	#(MITE3 & $FF)		;mite 3
	sta	baddrl
	lda	#90
	sta	hpos
	jsr	mkhdr

	lda	#(MITE4 & $FF)		;mite 4
	sta	baddrl
	lda	#118
	sta	hpos
	jsr	mkhdr
	rts	
;
;	do the town screen
;
dotown:
	jsr	dogtrdy
;
;	make background
;
	maketall	towtall

	setbaddr	CHIMN1	;chimney that sticks up over bitmap
	lda	#1
	sta	srcht
	lda	#141
	sta	vpos
	lda	#132
	sta	hpos
	ldpw	3,3	;pal, width
	sta	palwid
	jsr	xvermov

	setbaddr	CHIMN1	;chimney over center house
	lda	#1
	sta	srcht
	lda	#113
	sta	vpos
	lda	#94
	sta	hpos
	ldpw	3,3	;pal, width
	sta	palwid
	jsr	xvermov
	setbaddr	STAR	;stars in the sky
	ldpw	7,1
	sta	palwid

	lda	#1
	sta	srcht
	lda	#170
	sta	vpos
	lda	#40
	sta	hpos
	jsr	xvermov

	setbaddr	STAR	;stars in the sky
	lda	#1
	sta	srcht
	lda	#160
	sta	vpos
	lda	#47
	sta	hpos
	jsr	xvermov

	setbaddr	STAR	;stars in the sky
	lda	#1
	sta	srcht
	lda	#183
	sta	vpos
	lda	#77
	sta	hpos
	jsr	xvermov

	setbaddr	STAR	;stars in the sky
	lda	#1
	sta	srcht
	lda	#189
	sta	vpos
	lda	#152
	sta	hpos
	jsr	xvermov

	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
;
;
	jsr	inittownt	;town treasure
;
;	enemys
;
	jsr	initeye
	jsr	initwolf
	jsr	initlamps
	jsr	initghost
	jsr	initwinds
	jsr	initbolt
	jsr	initwiz
;
;	setup interrupts
;
	jsr	waitbot

	setijt	INTZ2,intgrnd1
	setijt	INTZ0,intgrnd2

	ldx	#N_TOWNT	;ready on fadein
	jsr	dotreasure
	jsr	fadeinwait
;
;	town loop
;
.townloop:
	jsr	waitclear
	jsr	doeye
	jsr	dowinds
	jsr	dolamps
	jsr	dofrs
	ldx	#N_TOWNT
	jsr	dotreasure
	jsr	dobolt
	jsr	doghost
	jsr	dowolf
	jsr	dowiz

	jsr	cpst		;cursor, points, score, threats, exit flag
	ldx	#N_TOWNT
	jsr	checktreasure

	lda	activefrs
	bne	.townloop

	jsr	checkend	;gameover?
	bne	.exit

	jsr	waitclear
	jsr	levelcomp

	lda	cursc		;set previous screen
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
.exit:	rts
;
;	do the desert screen
;
dodesert:
	jsr	dogtrdy
;
;	make background
;
	makeheaders	desclouds
	maketall	destall
	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
	jsr	initdest
;
;	enemys
;
	jsr	initscorp
	jsr	initants
	jsr	initeye
	jsr	initbird
	jsr	initsnake
	jsr	initrabbit
;
;	setup interrupts
;
	jsr	waitbot

	setijt	INTZ6,intgrnd1

	ldx	#N_DEST		;ready on fadein
	jsr	dotreasure
	jsr	docactuses

	makesound	BIRDCRY
	jsr	fadeinwait
	makesound	BIRDCRY
;
;	desert loop
;
.desertloop:
;
;	high priority tasks
;
	jsr	waitclear
	jsr	dosnake
	jsr	dorabbit
	jsr	doscorp
	jsr	doants
	jsr	dofrs		;do friends
	ldx	#N_DEST
	jsr	dotreasure
	jsr	dobird
	jsr	docactuses	;onlays
	jsr	doeye

	jsr	cpst		;cursor, points, score, threats, exit flag

	ldx	#N_DEST
	jsr	checktreasure

	lda	activefrs
	bne	.desertloop
;
	jsr	checkend	;gameover?
	bne	.exit

	jsr	waitclear
	jsr	docactuses

	jsr	levelcomp	;level completed

	lda	cursc		;set previous screen
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
.exit:
	rts
;
;	do cactuses, onlayed over desert scene
;
docactuses:

	setbaddr	CACTUS	;left
	lda	#0
	sta	curzon
	lda	#11
	sta	hpos
	ldpw	4,10
	sta	palwid
	lda	#5
	sta	destht
	lda	#1
	sta	srcht
	lda	#10
	sta	srcw
	jsr	tallobj

	lda	#(CACTUS + 10) & $FF	;right one shifted down 1 zone
	sta	baddrl
	lda	#4
	sta	destht
	lda	#110
	sta	hpos
	jsr	tallobj

	rts
;
;	do the jungle screen
;
dojungle:
	jsr	dogtrdy
;
;	make background
;
	maketall	juntall
	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
;
	jsr	initbag		;jungle treasure
;
;	enemys
;
	jsr	initchimps
	jsr	inittoc
	jsr	initplant
	jsr	initeye
;
;	setup interrupts
;
	jsr	waitbot
	setijt	INTZ9,intgrnd1
	setijt	INTZ3,intgrnd2

	jsr	dojunonlays	;ready on fadein
	ldx	#N_BAG
	jsr	dotreasure

	makesound	TOCANCRY
	jsr	fadeinwait
	makesound	TOCANCRY
;
;	jungle loop
;
.jungleloop:
;
;	high priority tasks
;
	jsr	waitclear
	ldx	#N_BAG
	jsr	dotreasure
	jsr	dofrs
	jsr	doplant
	jsr	dochimps
	jsr	dotoc
	jsr	dojunonlays	;jungle onlays
	jsr	doeye

	jsr	cpst		;cursor, points, score, threats

	ldx	#N_BAG
	jsr	checktreasure
;
	lda	activefrs
	bne	.jungleloop
;
;	exit seq
;
	jsr	checkend
	bne	.exit

	jsr	waitclear
	jsr	dojunonlays

	jsr	levelcomp

	lda	cursc		;set previous screen
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
.exit:	rts
;
;	do jungle onlays, treetops and ground veg
;
dojunonlays:
	setbaddr	JUN3	;rough tops of trees
	lda	#0
	sta	hpos
	lda	#9
	sta	curzon
	ldpw	BKGPAL,SCHWB
	sta	palwid
	jsr	mkhdr

	lda	#SCHWP
	sta	hpos
	jsr	mkhdr

	setbaddr	JUN4	;darkening leaves above
	inc	curzon
	ldpw	4,SCHWB
	sta	palwid
	jsr	mkhdr

	lda	#0
	sta	hpos
	jsr	mkhdr

	setbaddr	JUN2	;undergrowth onlay, top left half
	lda	#1
	sta	curzon
	ldpw	BKGPAL,SCHWB
	sta	palwid
	jsr	mkhdr

	lda	#(SCWP/4)*3	;top fourth quarter
	sta	hpos
	ldpw	BKGPAL,SCWB/4
	sta	palwid
	jsr	mkhdr

	lda	#(JUN2 + 10) & $FF	;top third quarter
	sta	baddrl
	lda	#SCHWP
	sta	hpos
	jsr	mkhdr

	setbaddr	C23	;bottom left half
	lda	#0
	sta	hpos
	dec	curzon
	ldpw	BKGPAL,SCHWB
	sta	palwid
	jsr	mkhdr

	lda	#SCHWP		;bottom right half
	sta	hpos
	jsr	mkhdr

	rts
;
;	do the castle screen
;
docastle:
	jsr	dogtrdy
;
;	make background
;
	maketall	castall
	makeheaders	casclouds
	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
;
;	enemys
;
	jsr	initarchers
	jsr	initptera
	jsr	initali2
	jsr	initeye
;
;	castle door
;
	jsr	initdoor
;
;	set interrupts
;
	setijt	INTZ6,intgrnd1

	jsr	dodoor	;ready on fadein
	jsr	fadeinwait
;
;	castle loop
;
.castleloop:
;
;	high priority tasks
;
	jsr	waitclear
	jsr	doeye
	jsr	dodoor		;drawbridge door
	jsr	dofrs		;do friends
	jsr	dowall		;the wall the frs walk behind
	jsr	doarchers
	jsr	doptera
	jsr	doali2

	jsr	cpst		;cursor, points, score, threats, exit flag
	bne	.castleloop
;
;	exit seq
;
	jsr	checkend
	bne	.exit

	jsr	waitclear
	jsr	dodoor
	jsr	levelcomp

	lda	cursc		;set previous screen
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
.exit:
	rts
;
;	do castle wall that friends walk behind
;
dowall:
	setbaddr	(CAS1 + 18 + 8)
	ldpw	BKGPAL,4
	sta	palwid
	lda	#18
	sta	srcw
	lda	#2
	sta	srcht
	lda	#3
	sta	destht
	lda	#2
	sta	curzon
	lda	#120
	sta	hpos
	jsr	tallobj
	rts
;
;	do the volcano screen
;
dovolcano:
	jsr	dogtrdy
;
;	background
;
	setbaddr	BM_VOLCANO
	jsr	mkbkg
	jsr	lockbkg
;
;	init movers
;
	jsr	initfrs
	jsr	initrocks
	jsr	initflrocks
	jsr	initvolups
	jsr	initltng
	jsr	initskyflash
	jsr	initdiamnd
	jsr	initbldr
	jsr	initeye
	jsr	initlriver

	setijt	INTZ5,intgrnd1

	ldx	#N_DIAMOND	;ready on fadein
	jsr	dotreasure
	jsr	dobldr

	makesound	BOOM
	jsr	fadeinwait
	makesound	BOOM

.volcanoloop:
;
;	high priority
;
	jsr	waitclear

	jsr	doeye
	jsr	doskyflash
	jsr	doltng
	jsr	dovolups
	jsr	dolriver
	jsr	dobldr
	ldx	#N_DIAMOND
	jsr	dotreasure
	jsr	dofrs
	jsr	doflrocks
	jsr	dorocks

	jsr	cpst		;cursor, points, score, threats

	ldx	#N_DIAMOND
	jsr	checktreasure

	lda	activefrs
	bne	.volcanoloop
;
;	terminate volcano screen
;
	lda	#GRAY		;clear skyflash
	sta	sky
	sta	fadsky
	lda	#RED-1		;clear mountain flash
	sta	P6C2

	jsr	checkend
	bne	.exit

	jsr	waitclear
	jsr	levelcomp

.exit:	lda	cursc		;set previous screen
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
	rts
;
;	sky flash
;
initskyflash:
	ldx	#N_SKYFLASH
	jsr	randt1
	lda	#FALSE
	sta	movid+N_SKYFLASH
	rts
doskyflash:
	lda	movid+N_SKYFLASH
	beq	.noton
	lda	#GRAY		;this should match volpal table sky color
	sta	fadsky
	bne	initskyflash	;always branch, target does rts
.noton:	dec	movt1+N_SKYFLASH
	bne	.exit
	lda	#WHITE		;time up .. flash the sky
	sta	fadsky
	lda	#TRUE
	sta	movid+N_SKYFLASH
	makesound	BOOM
.exit:	rts
;
;	do the bridge screen
;
dobridge:
	jsr	dogtrdy
;
;	make background
;
	setbaddr	BM_BRIDGE
	jsr	mkbkg
;
	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
;
;	enemys
;
	jsr	initfrog
	jsr	initfish
	jsr	initali
	jsr	initbeaver
	jsr	initowl
	jsr	initrockbri
	jsr	initbuzz
	jsr	initeye

	jsr	waitbot
	setijt	INTZ8,intgrnd1

	jsr	fadeinwait
;
;	bridge loop
;
.bridgeloop:
	jsr	waitclear
	jsr	doeye
	jsr	doali
	jsr	dofish
	jsr	dobeaver
	jsr	doowl
	jsr	dofrs		;do friend
	jsr	dorockbri
	jsr	dobuzz
	jsr	dobronlay	;bridge onlay
	jsr	dofrog

	jsr	cpst		;cursor, points, score, threats, exit flag
	bne	.bridgeloop

	jsr	checkend	;gameover?
	bne	.exit

	jsr	waitclear
	jsr	levelcomp

	lda	cursc
	sta	prevsc
	lda	#MAP		;update current screen
	sta	cursc
.exit:	rts
;
;	do bridge onlayed
;
dobronlay:

	setbaddr	BRONLAY	;left
	lda	#5
	sta	curzon
	lda	#0
	sta	hpos
	ldpw	6,SCHWB
	sta	palwid
	lda	#2
	sta	destht
	lda	#2
	sta	srcht
	lda	#SCHWB
	sta	srcw
	jsr	tallobj

	lda	#(BRONLAY + 20) & $FF	;right
	sta	baddrl
	lda	#SCHWP
	sta	hpos
	jsr	tallobj

	rts
;
;	do the room screen
;
doroom:
	jsr	dogtrdy
;
;	make background
;
	makeheaders	roohdrs

	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
;
;	enemys
;
	jsr	initeye
	jsr	initdaggers
	jsr	initdrag
	jsr	inittrap
	jsr	inittorches
	jsr	initchest
	jsr	initrdface
	jsr	initspear1
	jsr	initspear2
	jsr	initflsh
	jsr	initface1
	jsr	initface2

	ldx	#N_CHEST
	jsr	dotreasure		;ready on fade in
	jsr	dotorches
	makesound	CREAKY
	jsr	fadeinwait
;
;	room loop
;
.roomloop:
	jsr	waitclear
	jsr	doeye
	jsr	dotrap		;trap door
	jsr	doflsh
	ldx	#N_CHEST
	jsr	dotreasure
	jsr	doface1
	jsr	doface2
	jsr	dordface
	jsr	dotorches
	jsr	dofrs		;friends
	jsr	dodaggers	;enemies
	jsr	dospears
	jsr	dodrag

	jsr	cpst		;cursor, points, score, threats

	ldx	#N_CHEST
	jsr	checktreasure
;
	lda	activefrs
	bne	.roomloop

	jsr	checkend
	bne	.exit

	jsr	waitclear
	jsr	levelcomp

	lda	cursc		;set previous screen
	sta	prevsc
	lda	#FACE		;update current screen
	sta	cursc
.exit:
	rts
;
;	do the face screen
;
doface:
	jsr	dobeware
	jsr	setupsc
;
;	make background
;
	jsr	drawface
	jsr	drawfloor

	jsr	lockbkg
;
;	init friends
;
	jsr	initfrs
;
;	enemys
;
	jsr	initeyes

	jsr	doeyes	;ready on fadein
	makesound	HAHAHA
	jsr	fadeinwait
;
;	face loop
;
.faceloop:
	jsr	waitclear
	jsr	doeyes
	jsr	dofrs		;do friend
	jsr	dofds		;face daggers

	jsr	cpst		;cursor, points, score, threats
;
	lda	movsta+N_EYEL
	and	movsta+N_EYER
	bmi	finishquest	;target does rts

	lda	activefrs
	bne	.faceloop

	jsr	checkend
	bne	.exit

	jsr	waitclear
	jsr	doeyes

	jsr	levelcomp

	lda	#MAP		;update current screen
	sta	prevsc		;setting previous screen to map
	sta	cursc		;allows us to start from beginning again
.exit:
	rts
;
;	finish quest
;
finishquest:
.if	(EXAMINE = FALSE)
;
;	mark any joined friends survived
;
	ldy	#NUMBFRS-1
.loop1:	lda	frstat,y
	cmp	#JOINED
	bne	.skip
	lda	#SURVIVED
	sta	frstat,y
.skip:	dey
	bpl	.loop1
;
;	do skull animation
;
	jsr	waitbot
	jsr	clearsc		;erase face
	jsr	drawfloor	;redraw floor
	jsr	lockbkg

	lda	#$FF		;set clock to sync dissolve
	sta	clock
	lda	#$D8
	sta	mesclock	;message clock

	lda	#2		;set current message
	sta	curmes

	makesound	BOOM

	lda	#1		;dissolve direction
	sta	disdir
	lda	#0		;dissolve state
	sta	facefade
	jsr	setdissolve

.loop2:	jsr	drawdissolve

	lda	facefade
	cmp	#MAXFADE
	bne	.loop2

	lda	#ONESEC*2
	sta	clock

	makesound	BOOM
.loop3:	jsr	waitclear	;show only skull
	jsr	drawskull
	jsr	domessage
	jsr	dofrs
	jsr	doscore

	lda	clock
	bne	.loop3
	lda	#$FF		;dissolve direction
	sta	disdir
	sta	clock

.loop4:	jsr	drawdissolve

	lda	facefade
	bne	.loop4
;
;	play out fr walk until no friends
;
	jsr	waitclear
	jsr	drawface
	makeheaders	eyehdrs
	jsr	lockbkg
	jsr	domessage
	jsr	dofrs
	jsr	doscore

.loop5:	jsr	waitclear
	jsr	domessage
	jsr	dofrs
	jsr	doscore
	lda	activefrs
	bne	.loop5
;
;	screen end seq
;
	lda	#$25
	jsr	incsc
	lda	#$54
	jsr	incsc

	jsr	waitclear
	jsr	doscore
	makeheaders	hdrbns
	makesound	CLANKA
	makesound	CLANKB

	lda	#ONESEC*2
	jsr	waitalarm

	jsr	checkend
	bne	.exit

	jsr	waitclear

	jsr	levelcomp

	lda	#MAP		;update current screen
	sta	prevsc		;setting previous screen to map
	sta	cursc		;allows us to start from beginning again
.exit:
.endif
	rts
;
;	draw dissolve
;
drawdissolve:
	jsr	waitclear	;dissolve from face to skull
	jsr	dodissolve
	jsr	dostagger
	jsr	domessage
	jsr	dofrs
	jsr	doscore
	rts
;
;	do staggered draw of face and skull
;
dostagger:
	lda	clock
	and	#1
	beq	.face
;skull:
	jsr	drawskull
	rts
.face:
	jsr	drawface
	rts
;
;	do messages (you have .. try again..)
;
domessage:
	dec	mesclock
	bne	.draw
	dec	curmes	;twice for words
	dec	curmes
	bmi	.exit
	makesound	BOOM
.draw:
	ldx	curmes
	bmi	.exit
	lda	mestab,x
	sta	addrl
	lda	mestab+1,x
	sta	addrh
	jsr	readhdrs
.exit:
	rts
;
;	draw face floor
;
drawfloor:
	setbaddr	FFLOOR	;tiled floor
	ldpw	5,12
	sta	palwid
	lda	#12
	sta	srcw
	lda	#1
	sta	srcht
	lda	#3
	sta	destht
	lda	#0
	sta	curzon
	lda	#-3 & $FF
	sta	hpos
	jsr	tallobj

	lda	#-3 + (48*1)	;five repititions
	sta	hpos
	jsr	tallobj

	lda	#-3 + (48*2)
	sta	hpos
	jsr	tallobj

	lda	#-3 + (48*3)
	sta	hpos
	jsr	tallobj

	lda	#-3 + (48*4)
	sta	hpos
	jsr	tallobj
	rts
;
;	draw face
;
drawface:
	maketall	facetall
.if 0
	setbaddr	BM_FACE
	lda	#(SCWP - (22*4))/2	;center hpos
	sta	hpos
	ldpw	6,22
	sta	palwid
	lda	#22
	sta	srcw
	lda	#4
	sta	srcht
	lda	#8
	sta	destht
	lda	#4
	sta	curzon
	jsr	tallobj
.endif
	rts
;
;	draw skull
;
drawskull:
	maketall	skulltall
.if 0
	setbaddr	BM_SKULL
	lda	#((SCWP - (17*4))/2) + 3	;center hpos
	sta	hpos
	ldpw	2,17
	sta	palwid
	lda	#17
	sta	srcw
	lda	#4
	sta	srcht
	lda	#8
	sta	destht
	lda	#4
	sta	curzon
	jsr	tallobj
.endif
	rts
;
;	do dissolve from face to skull
;
dodissolve:
	lda	clock
	and	#%00001111
	beq	.changeit
	rts
.changeit:
	lda	facefade
	clc
	adc	disdir
	sta	facefade

setdissolve:
	lda	facefade
	sta	fadsta	;fade the face
	ldx	#(6*4)	;pal 6
	jsr	fadepal

	lda	#MAXFADE	;fade the skull
	sec
	sbc	facefade
	sta	fadsta
	ldx	#(2*4)	;pal 2
	jsr	fadepal

	lda	#0		;clear fadsta so subsequent fade will be right
	sta	fadsta
	rts
;
;	do "get ready" screen
;
dogtrdy:
	lda	idlemode	;if idle mode, skip "get ready"
	bne	.skipthis

	jsr	clearsc
	lda	#BLACK
	sta	sky
	setpal	0,1,YELLOW
	jsr	clrijt
	makeheaders	gtrdyhdr
	jsr	cutin
	lda	#ONESEC*3
	jsr	waitalarm
	jsr	cutout
.skipthis:
	jsr	setupsc		;altruistic act of this function to caller
	rts
;
;	do "beware" screen
;
dobeware:
	makesound	DRUM

	lda	#TITLE	;temp setting to title screen sets pals
	sta	cursc

	jsr	setupsc

	lda	#BLACK
	sta	sky

	lda	#FACE
	sta	cursc

	jsr	cutin
	makeheaders	bewarehdrs

	lda	#255
	jsr	waitalarm

	lda	#102
	jsr	waitalarm

	jsr	cutout
	rts
;
;	do end.. say "the end" or "gameover"
;
doend:
	jsr	comparesc	;compare hi score and current score
	bcs	.nonew		;if higher
	jsr	newhiscore	;make new high score
.nonew:
	lda	#TITLE
	sta	cursc

	jsr	setupsc

	makesound	CREAKY
	makeheaders	gmovrhdr
	jsr	titlerags

	setpal	6,1,YELLOW

	lda	#5	;display final score
	sta	curzon
	lda	#80
	sta	hpos
	ldpw	6,2
	sta	palwid
	jsr	drawscore
;
;	display high score
;
	ldy	#SCRDGTS-1	;copy current score to save buffer
.loop1:	lda	score,y
	sta	savescore,y
	dey
	bpl	.loop1

	ldy	#SCRDGTS-1	;copy hi score to score buffer
.loop2:	lda	hiscore,y
	sta	score,y
	dey
	bpl	.loop2

	lda	#3	;display hi score
	sta	curzon
	lda	#80
	sta	hpos
	ldpw	6,2
	sta	palwid
	jsr	drawscore

	ldy	#SCRDGTS-1	;copy saved current score back to score buffer
.loop3:	lda	savescore,y
	sta	score,y
	dey
	bpl	.loop3

	jsr	fadeinwait
	lda	#128
	jsr	waitalarm
	makesound	BOOM
	lda	#255
	jsr	waitalarm
	lda	#255
	jsr	waitalarm

	jsr	fadeoutwait
	rts
;
;	title screen style ragged edges
;
titlerags:
	maketall	raglr1
	makeheaders	ragudhdr
	rts
;
;	setupscreen
;	standard setup for interactive screens
;
setupsc:
	jsr	clrijt
	jsr	clearsc
	jsr	clrmsta		;clear moving object status to idle
	jsr	loadpals
	jsr	screenbank
	jsr	initcursor

	ldy	cursc
	lda	frypostab,y
	sta	frypos
	lda	fallevels,y	;enemy fall level where they die
	sta	fallevel
	lda	frlimits,y	;set walk limit before friend survives
	sta	frlimit
	lda	#FRNOSTOP	;for waiting for path enables like drawbridge
	sta	frstop
	lda	#0		;points display time
	sta	ptime
	sta	gottreasure
	sta	dropflag
	rts
;
;	do threats .. find collisions between dangerous enemies and friends.
;
dothreats:
;
;	check the cursor against the enemies
;
	lda	movsta+N_CURSOR	;if cursor not hot, skip
	and	#S_NOTHREAT
	bne	.donecursor

	ldy	#N_CURSOR	;y is cursor
	ldx	#N_CURSOR	;right before first enemy
.loop:
	inx			;first enemy
	txa
	cmp	#MAXMOV		;done?
	beq	.donecursor
	lda	movsta,x	;chk status bits
	and	#S_IDLE | S_INVULNERABLE
	bne	.loop

	jsr	coldet		;collision detect
	bcc	.loop

	jsr	dodeath		;yes! cursor hit something
.donecursor:	
;
;	check friends against threats (including cursor)
;
	ldy	#FRIEND1	;fr 1
.outerloop:
	lda	movsta,y	;check status
	and	#S_IDLE | S_INVULNERABLE
	bne	.donefr		;if idle or invulnerable, skip

	ldx	#1		;just before first enemy
.innerloop:
	inx			;next enemy
	txa			;
	cmp	#MAXMOV		;done?
	beq	.donefr
	lda	movsta,x	;active?
	and	#S_IDLE | S_NOTHREAT
	bne	.innerloop	;if idle or no threat, loop
	jsr	coldet		;collision detect
	bcc	.innerloop	;check for injured friend
	jsr	hurtfr

	jmp	.exit		;only one fr injury allowed
.donefr:
	dey			;point next fr
	bpl	.outerloop	;loop if no overflow
.exit:
.if 0
	lda	movsta+N_CURSOR	;if cursor still firing, means it hit nothing
	and	#S_NOTHREAT	;so make fire sound
	bne	.nosound
	makesound	FIRE
.nosound:
.endif
	rts
;
;	hurt friend
;	This func called when something dangerous hits a friend
;	FR in y reg, enemy (or cursor) in x reg
hurtfr:
	pushy
	pushx			;leaves x in acc

	cmp	#N_CURSOR	;injured by player?
	bne	.notcursor

	lda	movsta,x	;null cursor threat for subsequent target
	ora	#S_NOTHREAT
	sta	movsta,x

	lda	gavewarning	;already warned player?
	bne	.alreadywr
	makeheaders	hdrdntsht	;give first warning
	makesound	FIRE	;crossbow fire sound
	lda	#ONESEC*2
	sta	timer
	jsr	waitalarm
	lda	#TRUE
	sta	gavewarning
	jmp	.exit
.alreadywr:
;
;	friend has been shot by player and warning has already been issued
;
	lda	limptab,y	;already limping?
	bne	.alreadylp
	ldx	movid,y		;fr says "ouch"
	lda	frouchtab,x
	jsr	playsound
	lda	#TRUE		;mark fr limping
	sta	limptab,y
	bne	.exit		;always branch
.alreadylp:
;
;	enemy kills a friend
;
.notcursor:
	lda	#S_SETINIT		;flag to reinit killer
	sta	movsta,x
	lda	#1
	sta	movt1,x

	jsr	killfr
.exit:
	popx
	popy
	rts
;
;	kill friend, mov in y reg
;
killfr:
	ldx	movid,y		;friend cries out
	lda	frahtab,x
	jsr	playsound

	lda	#DIEING		;status
	sta	movsta,y
	lda	#1		;immediate update
	sta	movt1,y
	lda	#4		;above first frame of fire
	sta	movframe,y
	lda	#2
	sta	movht,y

	tya			;put mov in x reg
	tax
	ldy	#DEATHID	;special id for death flames
	jsr	setfrpal
	rts
;
;	do death of enemy
;	killer in y, victim in x
;
dodeath:
	lda	movsta,y	;null threat of killer
	ora	#S_NOTHREAT
	sta	movsta,y
	jsr	startdeath
	rts
;
;	start death seq, mov in x
;
startdeath:
	lda	#S_NOTHREAT | S_INVULNERABLE	;strip victim
	sta	movsta,x
	lda	movdseql,x	;start death sequence
	sta	movaniml,x
	lda	movdseqh,x
	sta	movanimh,x
	lda	#1		;flag for immediate update
	sta	movt1,x
	lda	#JUMPALWAYS
	sta	movloop,x
	rts	
;
;
;
.include	"coldet.s"
;coldet: goes here
;
;
;	clear moving object status .. set them all to inactive
;
clrmsta:
	ldy	#MAXMOV-1
	lda	#S_HANG
.loop:	sta	movsta,y
	dey
	bpl	.loop
	rts
;
;	screenbank
;	use cursc to lookup ROM bank, and switch
;
screenbank:
	ldy	cursc
	lda	banktab,y
	sta	BANKSW
	rts
;
;	transfer pal, source in y reg, dest in x reg
;	increments regs
;
transpal:
	inx			;skip control reg shadow

	lda	(haddrl),y	;c1
	sta	palshad,x
	inx
	iny

	lda	(haddrl),y	;c2
	sta	palshad,x
	inx
	iny

	lda	(haddrl),y	;c3
	sta	palshad,x
	inx
	iny

	rts
;
;	load pals .. reads global cursc, looks up addr of pal data, loads
;	pal data into shadow pals
;
loadpals:
	lda	cursc		;get par
	asl			;point to words
	tax			;index
	lda	SCPALTAB,x	;low byte
	sta	haddrl
	lda	SCPALTAB+1,x	;high byte
	sta	haddrh

	ldy	#0		;source index first table byte
	ldx	#8		;dest index first palshad byte of pal 2

	jsr	transpal	;transfer pals 2 .. 7
	jsr	transpal	;(pals 0 .. 1 for frs)
	jsr	transpal
	jsr	transpal
	jsr	transpal
	jsr	transpal

	lda	(haddrl),y	;backgrounds
	sta	sky
	iny
	lda	(haddrl),y
	sta	ground1
	iny
	lda	(haddrl),y
	sta	ground2
	rts
;
;	start of game logic subroutines
;
;	level completed routine
;	who survived, new friends, etc
levelcomp:

	ldx	cursc		;register that we were here
	inc	beenhere,x

	cpx	#FACE			;if not face screen
	beq	.skipmessage
	makeheaders	hdrlvlcmp	;say "level completed"
.skipmessage:

	jsr	lockbkg

	jsr	doscore			;show score

	lda	#ONESEC
	jsr	waitalarm

	jsr	clrmov

	makeheaders	hdrsrvbns	;survival bonus window

	jsr	lockbkg

;	go through roster of friends to see who survived

	lda	#NUMBFRS	;show survivals to player
	sta	curfr
.loop1:	dec	curfr
	bmi	break20		;done?
	ldy	curfr
	lda	frstat,y
	cmp	#SURVIVED
	bne	.loop1		;not survived?

				;survived
	lda	#JOINED		;update his stat for next sc
	sta	frstat,y

	ldx	#0
	ldy	curfr
	jsr	setfrpal

	jsr	clrmov

	lda	#35		;draw new icon
	sta	hpos
	lda	#32
	sta	vpos
	ldpw	0,FRWB
	sta	palwid
	jsr	xdrawfr
	lda	#$14	;add 10000 to score
	jsr	incsc
	jsr	doscore
	makesound	CLANKA
	makesound	CLANKB

	lda	#50
	jsr	waitalarm
	jmp	.loop1

break20:		;done with survival bonuses

;
;	find and echo the new friend
;
;	lookup new friend for this screen
	ldx	cursc
	ldy	newfrtab,x
;
;	leave if no new friend for this screen
	bmi	skipnewfr

;	leave if this friend not potential anymore
	lda	frstat,y
	cmp	#POTENTIAL
	bne	skipnewfr

;	set this friend's status
	lda	#JOINED
	sta	frstat,y
	sty	curfr

	makeheaders	hdrnewfr	;new friend window

;	draw new friend
	ldx	#1
	ldy	curfr
	jsr	setfrpal

	lda	#115		;draw icon
	sta	hpos
	lda	#32
	sta	vpos
	ldpw	1,FRWB
	sta	palwid
	jsr	xdrawfr
	makesound	CLANK2A
	makesound	CLANK2B

skipnewfr:
	lda	#50
	jsr	waitalarm
	rts
;
;	check end of screen to see if game over
;	exit with gameover var in acc
checkend:
;
;	see if any friends survived
;
	lda	idlemode	;if idlemode, set gameover
	bne	.nosurvivors
	ldy	#NUMBFRS
.loop:	dey
	bmi	.nosurvivors		;done?
	lda	frstat,y
	cmp	#SURVIVED
	bne	.loop		;not survived?
	rts			;zero flag set, tested as return value
.nosurvivors:
	lda	#TRUE
	sta	gameover
	rts
;
;	draw friend
;	give it curfr, hpos, curzon
xdrawfr:
	lda	curfr	;fr id
	tax		;get height
	lda	frhts,x
	sta	srcht

	lda	curfr	;get bitmap addr
	asl		;times 8
	asl
	asl
	clc
	adc	#6	;get standing frame
	tax
	lda	fftab,x
	sta	baddrl
	lda	#HER >> 8
	sta	baddrh

	jsr	xvermov
	rts
;
;	do switches
;
dosw:
	lda	idlemode
	beq	.nofire
*
*** added by dave 5-Jul-88 ***
*
*  New stuff added by Dave S. to start-up a game via gun
*
	lda	gun		;are we in gun mode?
	beq	.notgun		;br if not--just do previous stuff
	lda	SWCHA		;else, check gun trigger
	and	#$10		;it's like a joystick "UP" switch
	beq	.nofire		;br if not actuated
	bne	.gunfire	;else, always br to start-up game
.notgun:
*
****  end of Dave S. additions *****
*
*
	lda	INPT4	;if not play mode and fire button down, start play
	bmi	.nofire
.gunfire:
	lda	#FALSE
	sta	activefrs
	sta	idlemode
.nofire:
	lda	SWCHA	;check joystick
	cmp	oldjs
	bne	newjs
	lda	SWCHB	;check console
	cmp	oldsw
	bne	newcon
	rts		;return if no switches changed
newjs:
	sta	oldjs		;save
	eor	#$FF
	tax
	and	#%10000000
	sta	right
	txa
	and	#%01000000
	sta	left
	txa
	and	#%00010000
	sta	up
	txa
	and	#%00100000
	sta	down
	rts
newcon:
	sta	oldsw

	lda	#RESET
	bit	oldsw
	bne	noreset
	jmp	restart
noreset:
	lda	#PAUSE
	bit	oldsw
	bne	nopause

	lda	pauseon		;handle descent of PAUSE button
	eor	#$FF
	sta	pauseon
	bne	enterpause
	lda	#$FF	;exit pause
	sta	soundon
	ldx	#0
	lda	audvshadow,x
	jsr	setav
	ldx	#1
	lda	audvshadow,x
	jsr	setav
	rts
enterpause:
	lda	#0	;enter pause
	sta	soundon
	sta	AUDV0
	sta	AUDV1
	rts
nopause:
	lda	#SELECT		;select button down?
	bit	oldsw
	bne	.noselect

.if EXAMINE
	jmp	doex
.endif
	lda	cursc
	cmp	#TITLE		;if not title screen, ignore select
	beq	.selectgun
	jmp	restart0
.selectgun:
	lda	gun		;toggle gun flag
	eor	#$FF
	sta	gun
	jmp	showselect	;target does rts
.noselect:
	rts
;
;	show select .. gun or stick?
;
showselect:
	lda	gun
	beq	.stick
;gun:
	resetpal	5,2,WHITE
	resetpal	5,3,BLACK
	rts	
.stick:
	resetpal	5,3,WHITE
	resetpal	5,2,BLACK
	rts
;
;	do examine (look at a video bank)
;
.if EXAMINE
doex:
;	lda	#7		;set the bank
;	sta	BANKSW

	lda	#0
	sta	xpos
	sta	ypos

	jsr	fadeoutwait

	jsr	clrijt

	lda	#BLACK
	sta	sky

	setpal	7,1,BLUE
	setpal	7,2,GRAY
	setpal	7,3,WHITE

	jsr	clearsc
	jsr	fadein

.loop:	jsr	waitclear
	jsr	setex
	jsr	dofades
	lda	right
	beq	.notright
	inc	xpos
.notright:
	lda	left
	beq	.notleft
	dec	xpos
.notleft:
	lda	up
	beq	.notup
	inc	ypos
.notup:
	lda	down
	beq	.notdown
	dec	ypos
.notdown:
	jmp	.loop
;
;	set examine
;
setex:	lda	#$80
	sta	baddrh
	lda	xpos
	sta	baddrl
	ldpw	7,31
	sta	palwid
	lda	#((160-(31*4))/2)
	sta	hpos
	lda	#4
	sta	curzon
	lda	#4
	sta	destht
	lda	#4
	sta	srcht
	lda	#31
	sta	srcw
	jsr	tallobj
	rts
.endif
;
;	inc score, only by integer times power of 10
;	input data in A reg, format: low nib: exponent, hi nib: mantissa
;	uses x and y regs
incsc:
	ldy	idlemode	;if idle, no score
	bne	.exit

	pha			;save input
	and	#%00001111	;mask exp
	tay			;set indexes
	tax
;
;	clear leading zeroes from here to ones place
;
.loop1:
	lda	score,y
	cmp	#LDZERO
	bne	.break
	lda	#0
	sta	score,y
	dey
	beq	.break
	bne	.loop1
.break:
;
;	add and carry
;
	pla			;get mantissa
	lsr
	lsr
	lsr
	lsr

.loop2:	clc			;carry amount is now in acc
	adc	score,x
	sta	score,x
	cmp	#10
	bmi	.nocarry
	lda	#0
	sta	score,x
	inx			;next higher digit
	txa			;avoid overflow
	cmp	#SCRDGTS
	bpl	.nocarry
	lda	score,x		;if target is ldzero, make it #1 and rts
	cmp	#LDZERO
	bne	.notldzero
	lda	#1
	sta	score,x
.exit:	rts
.notldzero:
	lda	#1		;carry a 1
	bne	.loop2	
.nocarry:
	rts
;
;	cursor, points, score, threats
;
cpst:
	jsr	docursor
	jsr	drawpoints
	jsr	doscore
	jsr	setcursor
	jsr	dothreats
	lda	activefrs	;also set exit flag
	rts
;
;	score value table. Input: score index, Output, score value
;	this makes a blank leading zero ($F) = 0
scorevals:
	.dc.b	0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0
;
;	compare score
;	return carry clear if current score greater than hi score
comparesc:
	ldy	#SCRDGTS-1	;index high digit
.loop:	ldx	hiscore,y	;read score digit
	lda	scorevals,x	;load absolute digit value
	ldx	score,y		;read hiscore digit
	cmp	scorevals,x	;compare values
	bne	.exit		;if new score different from old hi, return
.nexty:
	dey			;else loop
	bpl	.loop		;and return carry set (by above) if done
	sec	
.exit:
	rts
;
;	new high score .. copy current score to high score
;
newhiscore:
	ldy	#SCRDGTS-1	;index top digit
.loop:	lda	score,y
	sta	hiscore,y
	dey
	bpl	.loop
	rts
;
;	do score: draw it once at bottom center of screen
;
doscore:
	lda	#((SCWP-(DGTWP*SCRDGTS))/2)	;init hdr pars
	sta	hpos
	ldpw	7,2
	sta	palwid
	lda	#0
	sta	curzon
	jsr	drawscore
	rts
;
;	draw score: put it where needed, in specified pal
;	give it hpos,palwid,curzon
;
drawscore:
	ldy	#SCRDGTS-1	;loop counter
.loop:	lda	score,y		;lookup baddr in table
	tax
	lda	numadt,x
	sta	baddrl
	lda	#ZERO >> 8
	sta	baddrh
	pushy
	jsr	mkhdr		;make header
	popy
	lda	hpos		;inc hpos
	clc
	adc	#DGTWP
	sta	hpos
	dey			;dec loop count
	bpl	.loop
	rts
;
;	draw points .. where an enemy has been killed
;
drawpoints:
	lda	ptime
	beq	.exit

	dec	ptime
	lda	paddrl		;baddrl
	sta	baddrl
	lda	#POINTS >> 8	;baddrh
	sta	baddrh
	lda	ppalwid		;palwid
	sta	palwid
	lda	phpos		;hpos
	sta	hpos
	lda	pvpos		;vpos
	sta	vpos
	lda	#1		;srcht
	sta	srcht
	jsr	xvermov
.exit:
	rts
;
;	init friends
;
initfrs:
	lda	#0		;init active frs count
	sta	activefrs
;
;	friend0
;
	ldy	#NUMBFRS	;search for friend
.fr0loop:
	dey

	lda	frstat,y
	cmp	#JOINED
	bne	.fr0loop

	pushy			;fr found! init
	ldx	#FRIEND0
	jsr	initfr
	popy

	lda	cursc		;if face screen, only 1 fr
	cmp	#FACE
	beq	.onefr
;
;	friend1
;
.fr1loop:
	dey			;continue search for friend
	bmi	.onefr
	lda	frstat,y
	cmp	#JOINED
	bne	.fr1loop		;not joined

	ldx	#FRIEND1	;create fr 1
	jsr	initfr

	jsr	rand		;rand idle status 0 .. 8 sec
	ora	#%11111000
	sta	movsta,x
	jsr	randt1		;rand start time 0 .. 4 sec
	rts
;
;	here if only fr0 active
;
.onefr:
	ldx	#FRIEND1
	lda	#S_HANG
	sta	movsta,x
	rts
;
;	init friend
;	mov in X, id in Y
initfr:
	lda	#FALSE			;clear limp
	sta	limptab,x

	inc	activefrs

	lda	#WALKING		;assume stat walking
	sta	movsta,x
	tya				;id
	sta	movid,x
	lda	#0			;frame
	sta	movframe,x
	lda	#HER >> 8		;baddrh
	sta	movfrh,x

	pushy
	jsr	randt1			;randomized start time
	popy

	lda	#((-FRWP) & $FF)	;initial position
	sta	movx,x
	lda	frypos			;set his vertical pos
	sta	movy,x
	lda	#FRWB			;width
	sta	movw,x
	lda	frhts,y		;table lookup height
	sta	movht,x

	lda	#CROSSING	;use id in y
	sta	frstat,y
;
;	if face screen, start fr falling
;
	lda	cursc		;is this screen
	cmp	#FACE		;face?
	bne	.notface	;no, skip
	lda	#SCHL		;set y above screen
	sta	movy,x
	lda	#FALLHPOS	;set x onscreen
	sta	movx,x
	lda	#FALLING	;set status to falling
	sta	movsta,x
	lda	#FALLTIME	;frame time
	sta	movt1,x
.notface:

	jsr	setfrpal
	rts
;
;	set friend pal, id in y reg, mov in x reg
;
setfrpal:
	pushx

	tya		;calc source pal from id
	asl		;4 bytes per pal
	asl
	tay

	txa		;calc dest pal from mov
	asl		;4 bytes per pal
	asl
	tax

	inx			;color 1
	iny
	lda	frpaltab,y
	sta	palshad,x
	sta	PALS,x

	inx			;color 2
	iny
	lda	frpaltab,y
	sta	palshad,x
	sta	PALS,x

	inx			;color 3
	iny
	lda	frpaltab,y
	sta	palshad,x
	sta	PALS,x

	popx
	rts	
;
;	do friends
;
dofrs:
	ldpw	0,FRWB
	sta	palwid
	ldx	#FRIEND0	;first friend
	jsr	dofr

	ldpw	1,FRWB
	sta	palwid
	ldx	#FRIEND1	;second friend
	jsr	dofr
;
;	see if any fr is waiting
;
	lda	#FALSE		;assume false
	sta	frwait

	lda	movx+FRIEND0
	cmp	frstop
	bne	.try1
	lda	movsta+FRIEND0
	bpl	.rettrue
.try1:
	lda	movx+FRIEND1
	cmp	frstop
	bne	.exit
	lda	movsta+FRIEND1
	bmi	.exit
.rettrue:
	lda	#TRUE
	sta	frwait
.exit:	rts
;
;	do one friend
;	ord of friend in x reg
;	uses y reg
;	clobbers all regs
;
dofr:	dec	movt1,x		;update?
	bne	.frnoup
	lda	movsta,x	;active?
	bmi	.fridle
	bne	.notwalking	;walking?
;
;	fr walking
;
.walking:
	lda	movx,x	;see if stopped by obstacle
	cmp	frstop
	bne	.notstopped
;
;	fr stopped
;
	lda	#6		;stopped, set standing frame
	sta	movframe,x
	lda	#13		;reset time
	sta	movt1,x
	lda	dropflag	;drop thru trap door?
	bne	.startdrop	;if not dropping, draw
	jmp	.drawfr
.startdrop:
	lda	#DROPPING	;set status to ..
	sta	movsta,x
	jmp	.dropping
.notstopped:
	lda	movx,x	;inc, check for this friend done
	clc
	adc	#2
	sta	movx,x
	cmp	frlimit
	bne	.frnocomp
	lda	#SURVIVED	;YES! friend completed
	jsr	nextfr
	rts
.frnocomp:
	ldy	movframe,x	;limp or don't limp depends on timing table
	lda	limptab,x	;selected
	beq	.nolimp
;limp:
	lda	limpwalk,y
	bne	.donelimp	;branch always
.nolimp:
	lda	okwalk,y
.donelimp:
	sta	movt1,x
	dec	movframe,x
	bpl	.nowrap
	lda	#5		;wrap walk cycle
	sta	movframe,x
.nowrap:
	jmp	.drawfr
;
;	fr idle
;
.fridle:
	cmp	#S_HANG
	beq	.hung		;if not hung,
	inc	movsta,x	;inc inactive status
.hung:
	lda	#ONESEC
	sta	movt1,x
	rts
;
;	fr no update (just draw)
;
.frnoup:
	lda	movsta,x	;abort if idle
	bmi	.nodraw
	jmp	.drawfr2
.nodraw:
	rts
;
;	not walkng .. switch on status
;
.notwalking:
	cmp	#DIEING
	beq	.dieing
	cmp	#DROPPING	;in room screen, dropping thru trap door
	beq	.dropping
;
;	only alternative is:
;	fr falling in face screen
;
.falling:
	lda	movy,x		;move friend down one zone
	sec
	sbc	#ZONEHL
	sta	movy,x
	cmp	frypos
	beq	.donefalling	;done falling?
	lda	#FALLTIME	;set time
	sta	movt1,x
	jmp	.drawfr
.donefalling:
	lda	#WALKING	;reset to walking stat
	sta	movsta,x
	lda	#0
	sta	movframe,x
	lda	#14
	sta	movt1,x
	jmp	.walking
;
;	fr dieing in flames
;
.dieing:
	lda	movframe,x	;if done dieing, nextfr
	bne	.contdie
	lda	#DEAD
	jsr	nextfr
	rts
.contdie:
	lda	#14		;reset time
	sta	movt1,x
	dec	movframe,x	;next frame
	lda	movframe,x	;lookup bitmap address
	asl
	tay
	lda	frdietab,y
	sta	movfrl,x
	jmp	.drawfr2	;draw it
;
;	fr dropping down trap door
;
.dropping:
	dec	movht,x		;show only upper portion of fr
	beq	.donedrop	;done if no fr left
	lda	movfrh,x	;inc baddrh to show upper part
	clc
	adc	#$10
	sta	movfrh,x
	lda	#6
	sta	movt1,x
	inc	movx,x
	inc	movx,x
	jmp	.drawfr2
.donedrop:			;fr has finished dropping thru trap door
	lda	#SURVIVED
	jsr	nextfr
	rts
.drawfr:
;
;	calc bitmap addr from id and frame number
;
	lda	movid,x		;get guy's identity
	asl
	asl
	asl			;shift left by number of frames per guy
	clc
	adc	movframe,x	;add for which frame
	tay

	lda	fftab,y		;read table
	sta	movfrl,x
	lda	#HER >> 8	;constant page address
	sta	movfrh,x
;
;	xvermov call
;
.drawfr2:
	lda	movfrl,x
	sta	baddrl
	lda	movfrh,x
	sta	baddrh
	lda	movy,x
	sta	vpos
	lda	movx,x
	sta	hpos
	lda	movht,x
	sta	srcht
	jsr	xvermov

	rts	
;
;	next friend .. a friend has completed, so who's next?
;	call with mov in x reg, new status in acc
;
nextfr:
	dec	activefrs	;one less friend active

	ldy	movid,x		;put friend identity in y reg
	sta	frstat,y	;store new status
;
;	look for next party member
;
	ldy	#NUMBFRS-1
.loop:	lda	frstat,y
	cmp	#JOINED
	beq	.newfr
	dey
	bpl	.loop
				;no more friends for this screen
				;null this mover
	lda	#S_HANG		;set status to inactive
	sta	movsta,x
	lda	#ONESEC
	sta	movt1,x
	rts

.newfr:
	jsr	initfr
	rts
;
;	init scorpion
;
initscorp:
	ldx	#N_SCORP
	makeaniminit	scorpinit
	jsr	harder
	rts
;
;	do scorpion
;
doscorp:
	ldx	#N_SCORP
	jsr	checkreinit
	beq	initscorp	;target does rts
	jsr	doanim
	rts
;
;	init ghost
;
initghost:
	ldx	#N_GHOST
	makeaniminit	ghostinit
	jsr	rand63
	adc	movy+N_GHOST
	sta	movy+N_GHOST
	lda	#$FF			;id controls up or down movement
	sta	movid+N_GHOST
	jsr	harder
	rts
;
;	do ghost
;
doghost:
	ldx	#N_GHOST
	jsr	falldeath
	bcs	initghost	;target does rts

	lda	movsta+N_GHOST	;see if dead
	and	#S_NOTHREAT
	bne	.ghostok
;ghostalive
	lda	movy+N_GHOST
	cmp	#ZONEHL*3	;see if too low
	bcs	.notlow
;low
	lda	#1		;too low, start rising
	sta	movid+N_GHOST
.notlow:
	lda	clock		;change height every other field
	and	#1
	beq	.nomove
	lda	movid+N_GHOST
	clc
	adc	movy+N_GHOST
	sta	movy+N_GHOST
.nomove:
	lda	movx+N_GHOST	;reinit if finished crossing
	tay
	cmp	#-(5*4) & $FF	;offscreen to left?
	bcs	.ghostok
	tya
	cmp	#SCWP+1		;offscreen to right?
	bcs	initghost	;target does rts
	bcc	.ghostok
.ghostok:
	jsr	doanim		;checked ok
	rts
;
;	init bolt
;
initbolt:
	ldx	#N_BOLT
	makeaniminit	boltinit
	jsr	rand63		;random x pos
	adc	#(-8) & $FF
	sta	movx+N_BOLT
	rts
dobolt:
	ldx	#N_BOLT		;check for reset
	jsr	falldeath
	bcs	initbolt

	jsr	doanim
	rts
;
;	init wolf
;
initwolf:
	ldx	#N_WOLF
	makeaniminit	wolfinit
	jsr	rand140x		;set random h pos
	rts
;	
;	do wolf
;
dowolf:
	ldx	#N_WOLF
	jsr	checkreinit
	beq	initwolf	;initwolf performs rts
	jsr	doanim
	rts
;
;	init eye
;
initeye:
	ldx	#N_EYE
	makeaniminit	eyeseqinit
	rts
;	
;	do eye
;
doeye:
	ldx	#N_EYE
	jsr	doanim
	rts
;
;	town wiz and fireball
;
initwiz:
	ldx	#N_WIZ
	makeaniminit	wizinit
	jsr	harder
initfrball:
	ldx	#N_FRBALL
	makeaniminit	frballinit
	rts
dowiz:
	ldx	#N_FRBALL
	jsr	falldeath
	bcc	.noreinit
	jsr	initfrball
.noreinit:
	ldx	#N_WIZ		;launch frball
	ldy	#N_FRBALL
	jsr	dolaunch

	jsr	doanim		;wiz anim

	ldx	#N_FRBALL	;frball anim
	jsr	doanim
	rts
;
;	bridge fish
;
initfish:
	ldx	#N_FISH
	makeaniminit	fishinit
	jsr	rand		;put fish randomly at various pos
	and	#%00000011
	tay
	lda	fishx,y
	sta	movx,x
	lda	fishy,y
	sta	movy,x
	rts
dofish:
	ldx	#N_FISH
	jsr	checkreinit
	beq	initfish	;target does rts	
	jsr	doanim
	rts
;
;	init frog
;
initfrog:
	ldx	#N_FROG
	makeaniminit	froginit
	rts
;	
;	do frog
;
dofrog:
	ldx	#N_FROG
	jsr	checkreinit
	beq	initfrog	;target does rts
	jsr	doanim
	rts
;
;	init rock (bridge)
;
initrockbri:
	ldx	#N_ROCKBRI
	makeaniminit	rockbriinit
	jsr	harder
	rts
dorockbri:
	ldx	#N_ROCKBRI
	jsr	checkreinit
	beq	initrockbri	;target does rts
	jsr	doanim
	rts
;
;	init buzzard
;
initbuzz:
	ldx	#N_BUZZ
	makeaniminit	buzzinit
	jsr	harder
	rts
;
;	do buzzard
;
dobuzz:
	ldx	#N_BUZZ
	jsr	falldeath
	bcs	initbuzz	;target does rts
	jsr	doanim
	rts
;
;	init aligator
;
initali:
	ldx	#N_ALI
	makeaniminit	aliinit
	rts
;
;	do alligator
;
doali:
	ldx	#N_ALI
	jsr	checkreinit
	beq	initali		;target does rts
	jsr	doanim
	rts
;
;	init aligator 2 (castle)
;
initali2:
	ldx	#N_ALI2
	makeaniminit	ali2init
	rts
;
;	do alligator 2 (castle)
;
doali2:
	ldx	#N_ALI2
	jsr	checkreinit
	beq	initali2	;target does rts
	jsr	doanim
	rts
;
;	init beaver
;
initbeaver:
	ldx	#N_BEAVER
	makeaniminit	beaverinit
	rts
;
;	do beaver
;
dobeaver:
	ldx	#N_BEAVER
	jsr	checkreinit
	beq	initbeaver		;target does rts
	jsr	doanim
	rts
;
;	init owl
;
initowl:
	ldx	#N_OWL
	makeaniminit	owlinit
	rts
;
;	do owl
;
doowl:
	ldx	#N_OWL
	jsr	checkreinit
	beq	initowl		;target does rts
	jsr	doanim
	rts
;
;	volcano animations
;
;
;	init rocks
;
initrocks:
	ldx	#N_ROCK1
	jsr	initrock
	ldx	#N_ROCK2
	jsr	initrock
	rts
;
;	init rock
;
initrock:
	makeaniminit	rockinit
	jsr	randxth		;set random xpos, time, harder
	rts
;
;	do rocks
;
dorocks:
	ldx	#N_ROCK1
	jsr	dorock
	ldx	#N_ROCK2
	jsr	dorock
	rts
;	
;	do rock
;
dorock:
	jsr	checkreinit
	beq	initrock	;target does rts
	jsr	doanim
	rts
;
;	init flaming rocks
;
initflrocks:
	ldx	#N_FLROCK1
	jsr	initflrock
	ldx	#N_FLROCK2
	jsr	initflrock
	rts
;
;	init flaming rock
;
initflrock:
	makeaniminit	flrockinit
	jsr	randxth		;rand x, t1, harder
	rts
;
;	do flaming rocks
;
doflrocks:
	ldx	#N_FLROCK1
	jsr	doflrock
	ldx	#N_FLROCK2
	jsr	doflrock
	rts
;
;	do flaming rock
;
doflrock:
	jsr	checkreinit
	beq	initflrock	;target does rts
	jsr	doanim
	rts
;
;	treasure code
;
;	cave treasure
;
initcavet:
	ldx	#N_CAVET
	makeaniminit	ctinit
	rts
;
;	bag treasure (jungle)
;
initbag:
	ldx	#N_BAG
	makeaniminit	baginit
	rts
;
;	desert treasure
;
initdest:
	ldx	#N_DEST
	makeaniminit	destinit
	rts
;
;	town treasure
;
inittownt:
	ldx	#N_TOWNT
	makeaniminit	ttinit
	rts
;
;	init chest treasure
;
initchest:
	ldx	#N_CHEST
	makeaniminit	chestinit
	rts
;
;	init diamond treasure
;
initdiamnd:
	ldx	#N_DIAMOND
	makeaniminit	diamndinit
	rts
;
;	generic do treasures
;
dotreasure:
	lda	movsta,x	;if treasure status idle, quit
	bmi	.exit
	lda	gottreasure	;if treasure not gotten, just draw
	beq	.notgot
	jsr	startdeath
.notgot:
	jsr	doanim
.exit:	rts
;
;	check treasure .. returns TRUE if friend touches treasure
;	call with mov in X reg
;
checktreasure:
	lda	gottreasure
	bne	.exitfalse
	lda	movsta+FRIEND0
	bmi	.fr0idle
	ldy	#FRIEND0
	jsr	coldet
	bcs	.exittrue
.fr0idle:
	lda	movsta+FRIEND1
	bmi	.exitfalse
	ldy	#FRIEND1
	jsr	coldet
	bcc	.exitfalse
.exittrue:
	lda	#TRUE
	sta	gottreasure
.exitfalse:
	rts
;
;	init boulder that allows friends to walk
;
initbldr:
	ldx	#N_BLDR
	makeaniminit	bldrinit
	lda	#30
	sta	frstop
	rts
;
;	do boulder
;
dobldr:
	ldx	#N_BLDR
	jsr	dostoptime	;if frs stopped too long, drop boulder
	bcc	.cont
	makeanim	bldrdseq2
.cont:
	lda	movsta + N_BLDR	;has it fallen yet?
	and	#S_INVULNERABLE
	beq	.stillup
	lda	#FRNOSTOP	;YES! clear friend stop
	sta	frstop
.stillup:
	jsr	doanim
	rts
;
;	init volcano up flares
;
initvolups:
	ldx	N_VOLUP1
	jsr	initvolup
	ldx	N_VOLUP2
	jsr	initvolup
	rts
initvolup:
	makeaniminit	volupinit
	jsr	rand63			;random wait time
	sta	movt1,x
	and	#%00000111		;rand x pos
	pha
	clc
	adc	movx,x
	sta	movx,x
	pla
	tay		;random left, right angle
	lda	flangles,y
	sta	movid,x
	rts
flangles:	.dc.b	$FF,$FF,$FF,0,0,1,1,1
;
;	do flares
;
dovolups:
	ldx	#N_VOLUP1
	jsr	dovolup
	ldx	#N_VOLUP2
	jsr	dovolup
	rts
dovolup:
	lda	movsta,x
	bmi	.inactive	;if active, shift in x every 4 fields
	lda	clock
	and	#%00000011
	bne	.noshift
	lda	movx,x
	clc
	adc	movid,x
	sta	movx,x
.inactive:
	jsr	checkreinit
	beq	initvolup	;target does rts
.noshift:
	jsr	doanim
	rts
;
;	lightning
;
initltng:
	ldx	#N_LTNG
	makeaniminit	ltnginit
	jsr	randt1
	rts
;
;	do lightning
;
doltng:
	ldx	#N_LTNG
	jsr	checkreinit
	beq	initltng	;target does rts
	jsr	doanim
	lda	#RED-1		;set the mountain color (match to volpal table)
	sta	P6C2		;pal 6 color 2
	lda	movsta+N_LTNG	;read lightning status
	bmi	.exit
	lda	#WHITE		;if active turn mountains white
	sta	P6C2
.exit:	rts
;
;	lava river
;
initlriver:
	ldx	#N_LRIVER
	makeaniminit	lriverinit
	rts
dolriver:
	ldx	#N_LRIVER
	jsr	doanim
	rts
;
;	room daggers
;
initdaggers:
	ldx	#N_DAGGER1
	jsr	initdagger
	ldx	#N_DAGGER2
	jsr	initdagger
	ldx	#N_DAGGER3
	jsr	initdagger
	rts
initdagger:
	makeaniminit	daggerinit

	jsr	rand		;random x pos
	and	#%00011111
	adc	#10
	sta	movx,x
	jsr	randt1		;random start time
	jsr	harder
	rts
dodaggers:
	ldx	#N_DAGGER1
	jsr	dodagger
	ldx	#N_DAGGER2
	jsr	dodagger
	ldx	#N_DAGGER3
	jsr	dodagger
	rts
dodagger:
	jsr	falldeath
	bcs	initdagger	;target does rts
	jsr	doanim
	rts
;
;	face daggers
;
initfd:
	txa		;read lookup table to select seq
	sec
	sbc	#N_FD1
	asl
	tay
	lda	fdtab,y
	sta	animl
	lda	fdtab+1,y
	sta	animh
	jsr	doaniminit
	rts
;
;
;
dofds:
	jsr	rand		;randomly launch left or right
	bcs	.rightfirst
;leftfirst:
	ldy	#N_EYEL		;to check for launch
	jsr	fdlaunch
	ldy	#N_EYER
	bne	.leftdone	;branch always
.rightfirst:
	ldy	#N_EYER
	jsr	fdlaunch
	ldy	#N_EYEL
.leftdone:
	jsr	fdlaunch

	ldx	#N_FD1		;animate all the face daggers
.loop:	pushx
	jsr	doanim
	popx
	inx
	cpx	#N_FD16 + 1
	bmi	.loop

	rts
;
;	face dagger launch .. eye in y
;
fdlaunch:
	lda	movsta,y
	cmp	#N_FD1		;if eye has valid fd mov
	bmi	.exit
	cmp	#N_FD16 + 1
	bpl	.exit
	tax
	lda	movsta,x	;and target dag idle
	bpl	.exit

	pushy
	jsr	initfd		;init it!
	popy
	lda	#0		;turn it on
	sta	movsta,x
	lda	#1
	sta	movt1,x
	lda	movx,y		;copy x and y
	sta	movx,x
	lda	movy,y
	sta	movy,x
.exit:	rts
;
;	init trap
;
inittrap:
	ldx	#N_TRAP
	makeaniminit	trapinit
	lda	#SCHWP-4		;friends will stop over trap door
	sta	frstop
	rts
;
;	do trap
;
dotrap:
	ldx	#N_TRAP		;check for flash triggers trap
	ldy	#N_FLASH
	jsr	dotrigger

	jsr	doanim

	lda	movsta+N_TRAP	;check for trap triggers drop
	bmi	.trigoff
	and	#S_TRIGGER
	beq	.notrig
	sta	dropflag	;set flag
	lda	#S_INVULNERABLE | S_NOTHREAT	;clear trigger status
	sta	movsta+N_TRAP
.notrig:
	rts
.trigoff:
	lda	#FALSE
	sta	dropflag
	rts
;
;	torches
;
inittorches:
	ldx	#N_TORCH1
	makeaniminit	torchinit
	lda	#8*ZONEHL
	sta	movy,x
	lda	#13
	sta	movx,x
	lda	#14
	sta	movt1,x
	ldx	#N_TORCH2
	makeaniminit	torchinit
	ldx	#N_TORCH3
	makeaniminit	torchinit
	lda	#114
	sta	movx,x
	lda	#42
	sta	movt1,x
	ldx	#N_TORCH4
	makeaniminit	torchinit
	lda	#142
	sta	movx,x
	lda	#7
	sta	movt1,x
	lda	#8*ZONEHL
	sta	movy,x
	rts
;
;	do torches
;
dotorches:
	ldx	#N_TORCH1
	jsr	doanim
	ldx	#N_TORCH2
	jsr	doanim
	ldx	#N_TORCH3
	jsr	doanim
	ldx	#N_TORCH4
	jsr	doanim

	lda	movsta+N_TORCH1		;if all torches idle, darken room
	and	movsta+N_TORCH2
	and	movsta+N_TORCH3
	and	movsta+N_TORCH4
	bpl	.exit
	resetpal	6,3,CYAN-5
	sta	sky
	sta	fadsky
	resetpal	6,2,RED-2
.exit:	rts
;
;	init rdface
;
initrdface:
	ldx	#N_RDFACE
	makeaniminit	rdfaceinit
	rts
;
;	do rdface
;
dordface:
	lda	movsta+N_CHEST	;if chest status
	bpl	.notrig		;minus and not
	cmp	#S_HANG	;hang, trigger red face
	beq	.notrig

	lda	#S_HANG	;turn off chest
	sta	movsta+N_CHEST
	lda	#S_NOTHREAT | S_INVULNERABLE	;activate face
	sta	movsta+N_RDFACE
	lda	#1
	sta	movt1+N_RDFACE
.notrig:
	ldx	#N_RDFACE
	jsr	doanim
	rts
;
;	room spears
;
initspear1:
	ldx	#N_SPEAR1
	makeaniminit	spearinit
	rts
initspear2:
	ldx	#N_SPEAR2
	makeaniminit	spearinit
	lda	#ZONEHL*5
	sta	movy+N_SPEAR2
	rts
dospears:
	lda	movsta+N_FLASH	;launch if flash and not launched
	bmi	.nolaunch
	lda	movsta+N_SPEAR1
	bpl	.nolaunch
	lda	movsta+N_SPEAR2
	bpl	.nolaunch
	lda	#0
	sta	movsta+N_SPEAR1
	sta	movsta+N_SPEAR2
	lda	#1
	sta	movt1+N_SPEAR1	
	lda	#12
	sta	movt1+N_SPEAR2
.nolaunch:
	ldx	#N_SPEAR1
	jsr	doanim
	ldx	#N_SPEAR2
	jsr	doanim

	ldx	#N_SPEAR1
	jsr	checkreinit
	beq	initspear1

	ldx	#N_SPEAR2
	jsr	checkreinit
	beq	initspear2
.exit:	rts
;
;	flash on statue's staff
;
initflsh:
	ldx	#N_FLASH
	makeaniminit	flashinit
	rts
doflsh:
	ldx	#N_FLASH
	lda	movsta+N_FLASH
	bpl	.flshactive	;if not active

	lda	frwait	;and frs stopped
	beq	.drawflsh

	lda	#1		;activate
	sta	movt1+N_FLASH
	lda	#S_NOTHREAT
	sta	movsta+N_FLASH
	makeanim	flashseq
	makesound	FANFAREA
	makesound	FANFAREB
	jmp	.drawflsh
.flshactive:
	lda	frwait	;if active and frs not stopped
	beq	initflsh	;reinit flash (does rts)

.drawflsh:
	jsr	doanim
	rts
;
;	init face1
;
initface1:
	ldx	#N_FACE1
	makeaniminit	face1init
	rts
;
;	do face1
;
doface1:
	ldx	#N_FACE1
	jsr	doanim
	rts
;
;	init face2
;
initface2:
	ldx	#N_FACE2
	makeaniminit	face2init
	rts
;
;	do face2
;
doface2:
	ldx	#N_FACE2
	jsr	doanim
	rts
;
;	init dragon (room)
;
initdrag:
	ldx	#N_DRAG
	makeaniminit	draginit
	jsr	harder
	jsr	initroofrbl
	rts
;
;	init room fireball
;
initroofrbl:
	ldx	#N_ROOFRBL
	makeaniminit	roofrblinit
	rts
;	
;	do dragon
;
dodrag:
	ldx	#N_ROOFRBL
	jsr	falldeath
	bcc	.noreinit
	jsr	initroofrbl	;target does rts
.noreinit:
	jsr	doanim

	ldx	#N_DRAG
	jsr	doanim

	ldx	#N_ROOFRBL
	ldy	#N_DRAG
	jsr	dotrigger
	rts
;
;	init windows
;
initwinds:
	ldx	#N_WIN1
	makeaniminit	win1init
	inx
	makeaniminit	win2init
	inx
	makeaniminit	win3init
	inx
	makeaniminit	win4init
	inx
	makeaniminit	win5init
	inx
	makeaniminit	win6init
	rts
;	
;	do window enemies
;
dowinds:
	ldx	#N_WIN1
	jsr	doanim
	ldx	#N_WIN2
	jsr	doanim
	ldx	#N_WIN3
	jsr	doanim
	ldx	#N_WIN4
	jsr	doanim
	ldx	#N_WIN5
	jsr	doanim
	ldx	#N_WIN6
	jsr	doanim
	rts
;
;	init street lamps
;
initlamps:
	ldx	#N_LAMP1
	makeaniminit	lampinit
	jsr	rand
	and	#%00011111
	sta	movt1+N_LAMP1
	inx
	makeaniminit	lampinit
	lda	#86
	sta	movx+N_LAMP2
	jsr	rand
	and	#%00011111
	sta	movt1+N_LAMP2
	inx
	makeaniminit	lampinit
	lda	#116
	sta	movx+N_LAMP3
	rts
;	
;	do street lamps
;
dolamps:
	ldx	#N_LAMP1
	jsr	doanim
	ldx	#N_LAMP2
	jsr	doanim
	ldx	#N_LAMP3
	jsr	doanim

	lda	movsta+N_LAMP1	;darken scene if all lamps idle
	and	movsta+N_LAMP2
	and	movsta+N_LAMP3
	bpl	.exit
	resetpal	6,1,BLUE-3
	sta	ground1
	sta	fadgrnd1
	resetpal	6,2,WHITE-6
	sta	ground2
	sta	fadgrnd2
	resetpal	6,3,GREEN-3
.exit:	rts
;
;	init plant
;
initplant:
	ldx	#N_PLANT
	makeaniminit	plantinit
	jsr	rand			;randomly choose x pos
	and	#%00000001
	tay
	lda	plantxtab,y
	sta	movx+N_PLANT
	jsr	harder
	rts
;	
;	do plant
;
doplant:
	ldx	#N_PLANT
	jsr	checkreinit
	beq	initplant	;target does rts
	jsr	doanim
	rts
;
;	init chains holding up drawbridge
;
initchains:
	ldx	#N_CHAIN1
	makeaniminit	chain1init
	ldx	#N_CHAIN2
	makeaniminit	chain2init
	rts
;
;	do chains holding up drawbridge
;
dochains:
	jsr	dostoptime	;if frs stopped too long, force chains
	bcc	.cont
	ldx	#N_CHAIN1
	makeanim	chaindseq
	ldx	#N_CHAIN2
	makeanim	chaindseq
.cont:
	ldx	#N_CHAIN1
	jsr	doanim
	ldx	#N_CHAIN2
	jsr	doanim
	rts	
;
;	init door
;
initdoor:
	lda	#FALSE
	sta	doordown
	jsr	initchains
	lda	#1
	sta	movt1+N_DOOR
	lda	#4
	sta	movframe+N_DOOR
	lda	#S_HANG
	sta	movsta+N_DOOR	;inactivate
	lda	#60
	sta	frstop		;stop friends
	rts
;
;	do drawbridge door
;
dodoor:
	jsr	dochains
	lda	movsta+N_CHAIN1		;if chains exist, just draw
	and	movsta+N_CHAIN2
	bpl	.drawdoor

	lda	movframe+N_DOOR		;if on frame 0, just draw
	beq	.drawdoor
	dec	movt1+N_DOOR		;if time not up, just draw
	bne	.drawdoor

	lda	#12			;reset time, inc frame
	sta	movt1+N_DOOR
	dec	movframe+N_DOOR
	bne	.drawdoor		;if frame zero, let friends walk
	lda	#FRNOSTOP
	sta	frstop

.drawdoor:
	lda	#1
	sta	curzon
	sta	srcht
	lda	movframe+N_DOOR
	asl
	tay
	lda	.doorjtab,y
	sta	jaddr
	lda	.doorjtab+1,y
	sta	jaddr+1
	jmp	(jaddr)
.doorjtab:	.dc.w	.jdoor9,.jdoor7,.jdoor4,.jdoor2,.jdoor1

.jdoor1:
	setbaddr	DOOR1	;closed
	ldpw	4,7
	sta	palwid
	lda	#7
	sta	srcw
	lda	#5
	sta	destht
	lda	#91
	sta	hpos
	bne	.readydoor
.jdoor2:
	setbaddr	DOOR2
	ldpw	4,10
	sta	palwid
	lda	#10
	sta	srcw
	lda	#4
	sta	destht
	lda	#83
	sta	hpos
	bne	.readydoor
.jdoor4:
	setbaddr	DOOR4
	ldpw	4,10
	sta	palwid
	lda	#10
	sta	srcw
	lda	#3
	sta	destht
	lda	#81
	sta	hpos
	bne	.readydoor
.jdoor7:
	setbaddr	DOOR7
	ldpw	4,12
	sta	palwid
	lda	#12
	sta	srcw
	lda	#2
	sta	destht
	lda	#73
	sta	hpos
	bne	.readydoor
.jdoor9:
	lda	doordown
	bne	.notdown
	makesound	BOOM
	lda	#TRUE
	sta	doordown
.notdown:
	setbaddr	DOOR9	;open
	ldpw	4,12
	sta	palwid
	lda	#12
	sta	srcw
	lda	#2
	sta	destht
	lda	#73
	sta	hpos

.readydoor:
	jsr	tallobj
	rts
;
;	archers amd arrows
;
initarchers:
	lda	#N_ARCHERS
	sta	curarcher
	lda	#N_ARROWS
	sta	curarrow
.loop:	jsr	initarcher
	jsr	initarrow
	inc	curarcher
	inc	curarrow
	lda	curarcher
	cmp	#N_ARCHERS + MAXARCHERS
	bne	.loop
	rts
;
;
;
initarcher:
	ldx	curarcher
	makeaniminit	archerinit

	txa			;table lookup vhpos
	sec
	sbc	#N_ARCHERS
	tay
	lda	archersy,y	;vpos
	sta	movy,x
	lda	archersx,y	;hpos
	sta	movx,x

	jsr	randt1		;random start time
	ora	#%11110000
	sta	movsta,x
	jsr	harder
	rts
;
;
;
initarrow:
	ldx	curarrow
	makeaniminit	arrowinit

	jsr	rand		;randomly choose arrow angle
	and	#%00000010
	tay
	lda	arrowseqtab,y
	sta	movaniml,x
	lda	arrowseqtab+1,y
	sta	movanimh,x
	rts
;
;	do archers and arrows
;
doarchers:
	lda	#N_ARCHERS
	sta	curarcher
	lda	#N_ARROWS
	sta	curarrow
.loop:	jsr	doarcher
	jsr	doarrow
	inc	curarcher
	inc	curarrow
	lda	curarcher
	cmp	#N_ARCHERS + MAXARCHERS
	bne	.loop
	rts
;	
;
;
doarcher:
	tax
	jsr	checkreinit
	beq	initarcher	;target does rts
	jsr	doanim
	rts
;
;
;
doarrow:
	ldx	curarrow	;if special reinit code (-1)
	lda	movsta,x
	cmp	#$FF
	beq	initarrow	;target does rts

	ldx	curarcher	;check for launching
	ldy	curarrow
	jsr	dolaunch

	ldx	curarrow	;animate
	jsr	doanim

	ldx	curarrow	;if active and
	lda	movsta,x
	bmi	.exit

	lda	movy,x		;below ground, reinit
	cmp	#32
	bcc	initarrow	;target does rts

.exit:	rts
;
;	falldeath
;	mov in x, carry set if enemy fallen below fall level, or
;	if hung
;
falldeath:
	lda	movsta,x	;hung?
	cmp	#S_READINIT
	beq	.rettrue

	lda	movsta,x	;idle?
	bmi	.retfalse
	
	lda	fallevel		;below fall level?
	cmp	movy,x
	rts
.retfalse:
	clc
	rts
.rettrue:
	sec
	rts
;
;	check reinit rts false (equal) if status = readinit
;
checkreinit:
	lda	movsta,x
	cmp	#S_READINIT
	rts
;
;	do launch..launcher in x, launchee in y
;	if stat of x is launch, sets x and y of launchee and launches
dolaunch:
	lda	movsta,x	;time to launch?
	cmp	#S_LAUNCH
	bne	.exit

	lda	#0		;YES, clear launch status
	sta	movsta,x
	lda	movx,x		;copy coords
	sta	movx,y
	lda	movy,x
	sta	movy,y
	lda	#1		;time to activate
	sta	movt1,y
	lda	#0		;activated launchee
	sta	movsta,y
.exit:	rts
;
;	init ptera
;
initptera:
	ldx	#N_PTERA
	makeaniminit	pterainit
	jsr	harder
	rts
;
;	do ptera
;
doptera:
	ldx	#N_PTERA
	jsr	falldeath
	bcs	initptera	;target does rts

	jsr	doanim
	rts
;
;	init tocan
;
inittoc:
	ldx	#N_TOC1
	makeaniminit	toc1init
	rts
;
;	do tocan (the one standing alone)
;
dotoc:
	ldx	#N_TOC1
	jsr	doanim
	rts
;
;	init dependent animations
;
initcoco:
	ldx	#N_COCO
	makeaniminit	cocoinit
	rts
inittoc2:
	ldx	#N_TOC2
	makeaniminit	toc2init
	rts
;
;	init chimps
;
initchimps:
	ldx	#N_CHIMP1
	jsr	initchimp1

	ldx	#N_CHIMP2		;coconut chimp
	jsr	initchimp2

	ldx	#N_CHIMP3		;tocan chimp
	jsr	initchimp3

	jsr	inittoc2		;dependent animations
	jsr	initcoco

	rts
;
;	reinit chimp 1
;
initchimp1:
	jsr	stdchimp
	makeanim	chimp1seq
	rts
;
;	reinit chimp 2 (coconut thrower)
;
initchimp2:
	jsr	stdchimp
	makeanim	chimp2seq
	rts
;
;	reinit chimp 3	(tocan thrower)
;
initchimp3:
	jsr	stdchimp
	makeanim	chimp3seq
	rts
;
;	do chimps
;
dochimps:
	ldx	#N_CHIMP1
	jsr	junreinit
	bcc	.skipinit1
	jsr	initchimp1
.skipinit1:
	jsr	doanim

	ldx	#N_CHIMP2	;do coconut throwing chimp 2
	jsr	junreinit
	bcc	.skipinit2
	jsr	initchimp2
.skipinit2:
	jsr	doanim

	ldx	#N_CHIMP2
	ldy	#N_COCO
	jsr	dolaunch

	ldx	#N_COCO
	jsr	junreinit
	bcc	.skipinit3
	jsr	initcoco
.skipinit3:
	jsr	doanim

	ldx	#N_CHIMP3	;chimp 3, who throws the tocan
	jsr	junreinit
	bcc	.skipinit4
	jsr	initchimp3
.skipinit4:
	jsr	doanim

	ldx	#N_CHIMP3	;launch and do victum tocan
	ldy	#N_TOC2
	jsr	dolaunch

	ldx	#N_TOC2
	jsr	junreinit
	bcc	.skipinit5
	jsr	inittoc2
.skipinit5:
	jsr	doanim
;
;	if toc2 shot while chimp3 dependent, redirect chimp3
;
	lda	movsta+N_CHIMP3
	cmp	#S_DEPENDENT
	bne	.norechimp
	lda	movsta+N_TOC2
	cmp	#S_NOTHREAT | S_INVULNERABLE	;dieing status
	bne	.norechimp
	ldx	#N_CHIMP3
	makeanim	chimp3climb
	lda	#S_NOTHREAT
	sta	movsta+N_CHIMP3
.norechimp:
;
;	if chimp3 shot while toc2 dependent, redirect toc2
;
	lda	movsta+N_TOC2
	cmp	#S_DEPENDENT
	bne	.noretoc
	lda	movsta+N_CHIMP3
	cmp	#S_NOTHREAT | S_INVULNERABLE	;dieing status
	bne	.noretoc
	ldx	#N_TOC2
	makeanim	tocescapeseq
	lda	#S_NOTHREAT
	sta	movsta+N_TOC2
.noretoc:
	rts
;
;	jungle reinit, give mov in x reg
;	returns carry set if status=reinit or fallen below screen
;
junreinit:
	lda	movsta,x
	cmp	#S_READINIT
	beq	.rettrue
	lda	movy,x
	clc
	adc	#ZONEHL
	rts
.rettrue:
	sec
	rts
;
;	standard chimp init
;	call with mov in x reg, sets movx, and movid to vine ord,
;	y, randomized idle sta
;
stdchimp:
	makeaniminit	chimpinit
	lda	#$FF		;invalidate this guy's id
	sta	movid,x

.loop:
	jsr	rand		;select a random vine
	and	#%00000111
	cmp	movid+N_CHIMP1	;repeat until unreserved vine found
	beq	.loop
	cmp	movid+N_CHIMP2
	beq	.loop
	cmp	movid+N_CHIMP3
	beq	.loop

	sta	movid,x		;set id to ord of vine
	tay
	lda	chimpvines,y	;table lookup x value
	sta	movx,x

	jsr	randt1		;random wait time
	jsr	harder
	rts
;
;	init snowman
;
initsnowman:
	ldx	#N_SNOWMAN
	makeaniminit	snoinit
	jsr	rand
	and	#%1
	tay
	lda	snoxtab,y
	sta	movx+N_SNOWMAN
	rts
;
;	do snowman
;
dosnowman:
	ldx	#N_SNOWMAN
	jsr	checkreinit
	beq	initsnowman	;target does rts

	jsr	doanim
	rts
;
;	init bat
;
initbat:
	ldx	#N_BAT
	makeaniminit	BATINIT
	jsr	rand63		;random x pos
	adc	#20
	sta	movx,x
	jsr	harder
	rts
dobat:
	ldx	#N_BAT		;check reinit
	jsr	falldeath
	bcs	initbat		;target does rts

	lda	movx+N_BAT	;reinit if offscreen to right
	cmp	#SCWP
	bcs	initbat		;target does rts

	jsr	doanim

	rts
;
;	init ices
;
initices:
	ldx	#ICE + MAXICE
.loop:	dex
	jsr	initice
	txa
	cmp	#ICE
	bne	.loop
	rts
;
;	init ice
;
initice:
	makeaniminit	iceinit
	jsr	rand		;random idle status
	ora	#%11111100
	sta	movsta,x
	jsr	randxth		;rand x, t1, harder
	rts
;
;	doices
;
doices:	ldx	#ICE		;first ice

.loop:	pushx
	jsr	doice
	popx
	inx
	txa
	cmp	#(ICE+MAXICE)	;done with all ices?
	bne	.loop
	rts
;
;	do ice
;
doice:
	jsr	checkreinit
	beq	initice		;initice performs rts

	jsr	doanim
	rts
;
;	init falling stalactites that enable path
;
initfsts:
	ldx	#N_FST1		;init them
	makeaniminit	fstinit
	ldx	#N_FST2
	makeaniminit	fstinit
	lda	#144		;move 2nd one to proper x
	sta	movx+N_FST2

	lda	#35		;scramble time
	sta	movt1+N_FST2

	lda	#%00000001	;set bit pattern of ids to mark fall sta
	sta	movid+N_FST1
	lda	#%00000010
	sta	movid+N_FST2

	lda	#0		;clear fall status bits
	sta	fallsta

	lda	#CAVESTOP1	;set fr stop
	sta	frstop
	rts
;
;	do falling stalactites
;
dofsts:
	ldx	#N_FST1
	jsr	dofst
	ldx	#N_FST2
	jsr	dofst
	rts
;
;
;
dofst:
	lda	movsta,x	;if status
	and	#S_INVULNERABLE	;invulnerable bit
	bne	.nodrop		;high, don't try to auto-drop it
	jsr	dostoptime	;is fr idly waiting for stag to fall?
	bcc	.nodrop		;no, skip
	makeanim	fstdseq	;yes, start death seq
	jmp	.readydraw	;and draw
.nodrop:
	lda	movsta,x	;quiescent?
	and	#S_QUIET
	bne	.readydraw

	lda	movy,x		;see if hit ground
	cmp	#8
	bcs	.readydraw

	makeanim	fstqseq	;YES! just hit ground
	makesound	BOOM
	lda	#S_NOTHREAT | S_INVULNERABLE | S_QUIET
	sta	movsta,x
	lda	#8		;lock y level
	sta	movy,x

	lda	movid,x		;register fall status
	ora	fallsta
	sta	fallsta
	tay			;lookup new stop point
	lda	cavestoptab,y
	sta	frstop

.readydraw:
	jsr	doanim
	rts
;
;	do stop time .. return carry set if frs are waiting too long
;
dostoptime:
	lda	frwait
	beq	.nostop
	lda	clock
	bne	.retfalse

	dec	clock		;move clock past trigger point
	dec	stoptime	;1 stop time click
	bne	.retfalse
;rettrue:
	lda	#4	;reset stop time to avoid redundant signals
	sta	stoptime
	sec
	rts
.nostop:		;if no frs stopped, keep time at 4*4 (12 .. 16 secs)
	lda	#4
	sta	stoptime
.retfalse:
	clc
	rts
;
;	init ants
;
initants: ldx	#ANTS + MAXANTS
.loop1:	dex
	jsr	initant
	txa
	cmp	#ANTS
	bne	.loop1
	rts
;
;	Input: ant number in x reg
;
antytab:	.dc.b	5,59

initant:
	jsr	rand	;randomly decide if right or left ant
	bcs	.doleft
	makeaniminit	antrinit
	jmp	.finishant
.doleft:
	makeaniminit	antlinit
.finishant:
	lda	#0		;make ant go neither up nor down
	sta	movid,x

	jsr	rand		;randomly choose y pos
	and	#%1
	tay
	lda	antytab,y
	sta	movy,x

	jsr	rand		;randomize idle time
	ora	#%11100000	;make from -1 .. -31
	sta	movsta,x
	jsr	harder
	rts
;
;	do ants
;
doants:
	ldx	#ANTS		;first ice
.loop:
	jsr	doant
	inx
	txa
	cmp	#(ANTS+MAXANTS)	;done with all ices?
	bne	.loop
	rts
;
;	do one ant
;	ord of ant in X reg
doant:
	pushx
	jsr	doanim
	popx

	jsr	checkreinit
	beq	initant		;target does rts

	lda	movsta,x	;if idle, forget the rest
	bpl	.notidle
	rts
.notidle:
	lda	movx,x		;reinit if crawled offscreen
	clc
	adc	#8		;check partly off on left
	bcs	.notoff
	adc	#(256-SCWP-8)
	bcs	initant		;target does rts
	
.notoff:
	lda	movy,x		;a threat only if near friend's height
	cmp	#28
	bcc	.nothreat
	cmp	#36
	bcs	.nothreat
	lda	#0		;set status threatening
	beq	.yesthreat	;cheat .. branch always
.nothreat:
	lda	#S_NOTHREAT
.yesthreat:
	sta	movsta,x

	lda	clock		;every so often, change the rise and fall
	and	#%01111111
	bne	.nochange
	jsr	rand
	bcs	.nochange
	and	#%00000111
	tay
	lda	antupdown,y
	sta	movid,x
.nochange:
	lda	clock		;move it up or down
	and	#%00000111
	bne	.skip
	lda	movid,x
	clc
	adc	movy,x
	sta	movy,x
.skip:
	lda	movy,x		;see if its too high
	cmp	#64
	bmi	.nottoohigh
	lda	#64
	sta	movy,x
.nottoohigh:	
	lda	movy,x		;see if its too low
	bpl	.nottoolow
	lda	#0
	sta	movy,x
.nottoolow:
	lda	movy,x		;if at friend's level, stop rise or fall
	cmp	#32
	bne	.nolevel
	lda	#0
	sta	movid,x
.nolevel:
	rts
;
;	init bird (desert)
;
initbird:
	ldx	#N_BIRD
	makeaniminit	birdinit
	lda	#0		;y delta
	sta	movid+N_BIRD
	lda	#$FF		;time till descent 
	sta	timer
	jsr	rand		;random x pos
	and	#%00001111
	adc	#20
	sta	movx,x
	jsr	harder
	rts
dobird:
	ldx	#N_BIRD		;check reinit
	jsr	falldeath
	bcs	initbird	;target does rts

	lda	movsta+N_BIRD	;control descent
	bmi	.nodrop
	lda	timer
	bne	.nodrop
	jsr	rand
	bcs	.nodrop
	lda	#-1 & $FF
	sta	movid+N_BIRD
.nodrop:
	lda	movy+N_BIRD	;stop descent if too low
	cmp	#4*ZONEHL
	bcs	.nostopdrop
	lda	#0
	sta	movid+N_BIRD
.nostopdrop:
	lda	movx+N_BIRD	;reinit if offscreen to right
	clc
	adc	#(256 - SCWP)
	bcs	initbird	;target does rts

	jsr	doanim

	lda	movy+N_BIRD	;add delta to y
	clc
	adc	movid+N_BIRD
	sta	movy+N_BIRD
	rts
;
;	init snake
;
initsnake:
	ldx	#N_SNAKE
	makeaniminit	snakeinit

	jsr	rand63			;rand x and y pos
	adc	#(160 - 64 - 8)/2
	sta	movx,x

	jsr	rand			;rand y pos (only on zone)
	and	#%00010000
	clc
	adc	#3*ZONEHL
	sta	movy,x

	rts
;
;	do snake (desert)
;
dosnake:
	ldx	#N_SNAKE
	jsr	checkreinit
	beq	initsnake	;target does rts

	jsr	doanim
	rts
;
;	init rabbit
;
initrabbit:
	ldx	#N_RABBIT
	makeaniminit	rabbitinit
	rts
;
;	do rabbit (desert)
;
dorabbit:
	ldx	#N_RABBIT
	jsr	checkreinit
	beq	initrabbit	;target does rts

	lda	movx+N_RABBIT
	clc			;reinit of offscreen to right
	adc	#20		;slightly left of screen is ok
	bcs	.notoff
	lda	movx+N_RABBIT
	adc	#(256 - SCWP)
	bcs	initrabbit	;target does rts
.notoff:
	jsr	doanim
	rts
;
;	face screen animations
;
initeyes:
	lda	#FALSE
	sta	eyesred
	sta	frtarget
	ldx	#N_EYEL
	makeaniminit	wteyelinit
	ldx	#N_EYER
	makeaniminit	wteyerinit
	rts
;
initrdeyes:
	lda	#%10000000 | S_NOTHREAT	;if idle or no threat
	bit	movsta+N_EYEL
	bne	.next			;don't reint
	ldx	#N_EYEL
	makeaniminit	rdeyelinit	;init
.next:	lda	#%10000000 | S_NOTHREAT	;ditto
	bit	movsta+N_EYER
	bne	.exit
	ldx	#N_EYER
	makeaniminit	rdeyerinit	;init
.exit:	
	lda	#TRUE
	sta	eyesred
	makesound	DIEA
	makesound	DIEB
	rts
;
initwteyes:
	lda	#%10000000 | S_NOTHREAT	;if idle or no threat
	bit	movsta+N_EYEL
	bne	.next
	ldx	#N_EYEL
	makeaniminit	wteyelinit	;init
.next:	lda	#%10000000 | S_NOTHREAT	;ditto
	bit	movsta+N_EYER
	bne	.exit
	ldx	#N_EYER
	makeaniminit	wteyerinit	;init
.exit:	lda	#FALSE
	sta	eyesred
	rts
;
doeyes:
	ldx	#N_EYEL			;do anims
	jsr	doanim

	ldx	#N_EYER
	jsr	doanim

	lda	movsta+FRIEND0		;if friend not dieing
	cmp	#DIEING
	beq	.notarg			;and within range
	lda	movx+FRIEND0
	cmp	#45
	bcc	.notarg
	lda	#TRUE			;set target flag
	bne	.skip	;cheat always branch
.notarg:
	lda	#FALSE
.skip:
	sta	frtarget		;store as frtarget

	lda	eyesred			;if eyes not red
	bne	.doeyesred
;doeyeswt:				;do eyes white
	lda	movsta+N_EYEL		;if neither idle nor no threat
	ora	movsta+N_EYER
	and	#%10000000
	bne	.insync

	lda	movsta+N_EYEL		;and sync bits different,
	eor	movsta+N_EYER
	and	#S_SYNC
	beq	.insync

	jsr	initwteyes		;resync
.insync:
	lda	frtarget		;if fr target
	beq	.exit
	jsr	initrdeyes		;make red
	jmp	.exit
.doeyesred:
	lda	frtarget		;if not frtarget
	bne	.exit
	jsr	initwteyes		;make white
.exit:
	rts
;
;	harder	.. reduce idle time to make screens harder when revisited
;
harder:
	txa			;put x (mov) in y
	ldy	cursc
	ldx	beenhere,y	;put times been here in x
	tay

.loop:	dex
	bmi	.exit
	lda	movsta,y
	lsr
	ora	#%10000000	;keep negative
	sta	movsta,y
	lda	movt1,y
	lsr
	ora	#1		;make sure this isn't zero
	sta	movt1,y
	bne	.loop		;cheat always
	
.exit:	tya
	tax
	rts
;
;	do trigger .. a mover in y may trigger the mover in x
;
dotrigger:
	lda	movsta,x	;if triggeree active, abort
	bpl	.exit

	lda	movsta,y
	bmi	.exit		;triggerer must be active
	and	#S_TRIGGER	;and trigger bit set
	beq	.exit

	lda	movsta,y	;shut off trigger
	and	#(~S_TRIGGER) & $FF
	sta	movsta,y

	lda	#0		;activate triggered
	sta	movsta,x
	lda	#1
	sta	movt1,x
.exit:
	rts
;
;	do animation init
;	pass it address of initialization data, and mov in x reg.
;	completely sets up the sequence
;
doaniminit:
	ldy	#0
	lda	(animl),y	;height
	sta	movht,x
	iny	
	lda	(animl),y	;width
	sta	movw,x
	iny
	lda	(animl),y	;palwid
	sta	movpw,x
	iny
	lda	(animl),y	;xpos
	sta	movx,x
	iny
	lda	(animl),y	;ypos
	sta	movy,x
	iny
	lda	(animl),y	;status
	sta	movsta,x
	iny
	lda	(animl),y	;time
	sta	movt1,x
	iny
	lda	(animl),y	;frame addr
	sta	movfrl,x
	iny
	lda	(animl),y
	sta	movfrh,x
	iny
	lda	(animl),y	;seq addr
	sta	movaniml,x
	iny
	lda	(animl),y
	sta	movanimh,x
	iny
	lda	(animl),y	;death seq
	sta	movdseql,x
	iny
	lda	(animl),y
	sta	movdseqh,x
	iny
	lda	(animl),y	;type (stationary or moving xy)
	sta	movtype,x

	lda	#JUMPALWAYS		;null loop counter
	sta	movloop,x
	rts
;
;	super animation machine .. moving, multi-header objects
;	start by setting movaniml/h to address of first instruction
;	instruction format is time .. frame .. delta .. etc.
;	delta is x,y in high, low nibble, plus 8 to avoid sign extension
;	a null time ends sequence
;	end seq format: (null time), status, restart addrl/h
;	THIS VERSION ALSO HAS AUDIO,JUMP, STATUS, POINTS, LOOP FUNCTIONS
doanim:
	dec	movt1,x
	beq	.animup		;update?

	lda	movsta,x	;no update .. check status
	bpl	.drawanim	;not idle?
	rts			;idle .. return

.animup:
	lda	movsta,x	;check status
	bpl	.active		;active?
	cmp	#S_HANG		;if hang, return
	bne	.nothang
	rts
.nothang:
	inc	movsta,x	;idle .. inc status
	bpl	.active		;newly active?
	lda	#ONESEC		;inactive .. reset time for one sec
	sta	movt1,x
	rts			;bye!
		
.active:
	ldy	#0		;clear indirect index register
	lda	movaniml,x	;fetch address of animation instruction
	sta	animl		;and put it in zero page for indirection
	lda	movanimh,x
	sta	animh

.nextinst:
	lda	(animl),y	;get time value
	beq	.animnonframe	;zero time = non-frame instruction
	sta	movt1,x		;set time
	iny

	lda	(animl),y	;get frame address
	sta	movfrl,x
	iny

	lda	movtype,x	;if type minus, skip dx,dy
	bmi	.skipdxdy

	lda	(animl),y	;delta x
	clc
	adc	movx,x
	sta	movx,x
	iny

	lda	(animl),y	;delta y
	clc
	adc	movy,x
	sta	movy,x
	iny

.skipdxdy:
	tya		;update and save animation pointer
	clc
	adc	animl
	sta	movaniml,x
	lda	#0		;carry into high byte
	adc	animh
	sta	movanimh,x

.drawanim:
	lda	movfrl,x		;format vermov call
	sta	baddrl
	lda	movfrh,x
	sta	baddrh
	lda	movy,x
	sta	vpos
	lda	movx,x
	sta	hpos
	lda	movht,x
	sta	srcht
	lda	movpw,x
	sta	palwid
	jsr	xvermov
	rts	

.animnonframe:			;non-frame instruction
	iny
	pushx
	lda	(animl),y	;lookup the instruction token in jumptable
	tax
	lda	.jmptab,x
	sta	jaddr
	lda	.jmptab+1,x
	sta	jaddr+1
	popx
	iny
	jmp	(jaddr)

.jmptab:
	.dc.w	.doaudio,.dojump,.dostatus,.dopoints,.doloop,.dodelta

.doaudio:
	lda	(animl),y
	jsr	playsound
	iny
	jmp	.nextinst
.dojump:
	lda	movloop,x
	cmp	#JUMPALWAYS	;if invalid loop time, jump always
	beq	.readyjump
	sec			;decrement
	sbc	#1
	sta	movloop,x
	bcs	.readyjump	;if repeated required times, don't jump
	iny
	iny
	jmp	.nextinst
.readyjump:
	lda	(animl),y	;replace old address with new
	sta	movaniml,x
	iny
	lda	(animl),y
	sta	movanimh,x
	jmp	.animup		;back to top
.dostatus:
	lda	(animl),y		;new status, next action
	sta	movsta,x		;depends on status, so
	iny				;re-evaluate
	tya		;update and save animation pointer
	clc
	adc	animl
	sta	movaniml,x
	lda	#0		;carry animl to animh
	adc	animh
	sta	movanimh,x
	jmp	.animup
.dopoints:
	pushx
	pushy
	lda	(animl),y
	tay
	jsr	addpoints
	popy
	popx
	iny
	jmp	.nextinst
.doloop:
	lda	(animl),y	;set the loop counter
	sta	movloop,x
	iny
	jmp	.nextinst
.dodelta:
	lda	(animl),y	;add delta x and y
	clc
	adc	movx,x
	sta	movx,x
	iny
	lda	(animl),y
	clc
	adc	movy,x
	sta	movy,x
	iny
	jmp	.nextinst
;
;	add points.. given ord of point value, sets up screen display
;	and increments player's score
;	call with mov in x, score code in y
addpoints:
	lda	ptsbmtab,y	;baddrl
	sta	paddrl
	lda	ptspwtab,y	;palwid
	sta	ppalwid
	lda	movx,x		;hpos
	sta	phpos
	lda	movy,x		;vpos
	sta	pvpos
	lda	#ONESEC		;time
	sta	ptime

	tya			;inc score (two data bytes)
	asl
	tay
	pushx
	pushy
	lda	ptsinctab,y
	jsr	incsc
	popy
	pushy
	lda	ptsinctab+1,y
	jsr	incsc
	popy
	popx
	rts
;
;	fade machine: the following subroutines manage fades and cuts.
;	cut in and cut out cause immediate actions to the screen.
;	fade in and fade out set the flag faddir (fade direction), and
;	the fade occurs when the routine "dofades" is called every field.
;	waitfade is called when there is no action by the caller until
;	any pending fade is completed.
;	fadepals and fadecolor are utilities internal to the fade machine.
;	Any setting of colors intended to be faded correctly must be done
;	in the pal shadows (use the macro setpal).
;
;	fade in and wait
;
fadeinwait:
	jsr	fadein
	jsr	waitfade
	rts
;
;	fade out and wait
;
fadeoutwait:
	jsr	fadeout
	jsr	waitfade
	rts
;
;	wait for fade to finish
;
waitfade:
	jsr	waitbot
	jsr	dofades
	lda	faddir
	bne	waitfade
	rts
;
;	cut to black
;
cutout:
	lda	#MAXFADE
	sta	fadsta
	jsr	fadepals
	rts
;
;	cut from black
;
cutin:
	lda	#0
	sta	fadsta
	jsr	fadepals
	rts
;
;	fade in
;
fadein:
	lda	#FADEIN
	sta	faddir
	rts
;
;	fade out
;
fadeout:
	lda	#FADEOUT
	sta	faddir
	rts
;
;	do fades
;	task for fade in/out
;	reads global: faddir
;	uses locals: fadsta, fadtim, fadlum
dofades:
	lda	faddir
	bne	.fadewaits	;return if no fade waiting
	rts
.fadewaits:
	dec	fadtim	;time between changes
	bmi	.update
	rts
.update:
	lda	#FADSP	;reset timer
	sta	fadtim

	lda	faddir	;test direction
	bmi	.fadingout
;fadingin:	
	lda	fadsta
	beq	.faddone
	dec	fadsta		;fade in
	jsr	fadepals
	rts
.fadingout:
	lda	fadsta
	cmp	#MAXFADE
	beq	.faddone
	inc	fadsta		;fade out
	jsr	fadepals
	rts
.faddone:
	lda	#0	;fade done, switch to idle mode
	sta	fadtim
	sta	faddir
	rts
;
;	fade pals
;
fadepals:
	lda	#NUMBPAL
	sta	i
	ldx	#0

.loop:	jsr	fadepal
	dec	i
	bne	.loop

	ldy	sky		;fade ground and sky
	jsr	fadecolor
	sta	fadsky

	ldy	ground1
	jsr	fadecolor
	sta	fadgrnd1

	ldy	ground2
	jsr	fadecolor
	sta	fadgrnd2
	rts	
;
;	fade pal .. put pal color zero offset in x reg
;
fadepal:
	inx			;skip MARIA register
	ldy	palshad,x	;color 1
	jsr	fadecolor
	sta	PALS,x
	inx
	ldy	palshad,x	;color 2
	jsr	fadecolor
	sta	PALS,x
	inx
	ldy	palshad,x	;color 3
	jsr	fadecolor
	sta	PALS,x
	inx
	rts
;
;	fadecolor
;	call with intended color in Y reg
;	returns faded color in A reg
;	uses global fadsta (fade state)
;	uses temp fadlum (faded luminance)
fadecolor:
	tya			;get input
	and	#$0F		;mask in luminance
	sec
	sbc	fadsta		;subtract fade state
	bpl	fall30
	lda	#BLACK		;if negative return (black)
	rts			;done for negative
fall30:
	sta	fadlum		;get input
	tya			;get intended color
	and	#$F0		;keep chroma
	ora	fadlum		;add lum
	rts			;done
;
;	wait for alarm
;	call with field count in a reg
;	returns when time is up
;
waitalarm:
	sta	timer
.loop:	jsr	waitbot
	jsr	dofades
	lda	timer
	bne	.loop
	rts
;
;	wait for vblank
;
waitvbl:

.loop1:
	bit	MSTAT	;wait until vblank is off
	bmi	.loop1

.loop2:
	bit	MSTAT	;wait until vblank is on
	bpl	.loop2

	lda	#0	;clear bottom-of-screen flag
	sta	botflag
	sta	intcnt	;set interrupt count flag
	rts		;return
;
;	wait for bottom of screen (set by last-zone interrupt)
;	also, sound and pause functions occur in this routine
;
waitbot:
	jsr	dosound
.loop:
	lda	botflag	;check flag
	beq	.loop	;loop

	lda	#0	;clear flag
	sta	botflag

	jsr	dosw	;read console sw
	lda	pauseon	;check pause mode
	bne	.loop	;wait more if paused
	rts
;
;	make background, plain-jane format
;
mkbkg:				;left half
	maketall	plaintall
	rts
;
;	init cursor to center screen
;
initcursor:
	ldx	#N_CURSOR
	makeaniminit	cursorinit
	rts
;
;	do cursor: show it on screen
;
docursor:
	lda	idlemode		;if idle, exit
	bne	.exit

	lda	gun		;if light gun selected
	beq	.stick
	jsr	DOGUN		;call routine in lower fixed bank
	bne	.fire		;returns TRUE if fired
	beq	.nofire
.stick:
	lda	movsta+N_CURSOR		;see if firing allowed
	and	#S_STOPPED
	bne	.nofire

	lda	INPT4			;check fire button
	bmi	.nofire
.fire:
	lda	movx+N_CURSOR		;if cursor pos
	cmp	#SCWP			;offscreen
	bne	.onscreen
	makesound	CUCKOO2		;make cuckoo sound
.onscreen:
	lda	#S_STOPPED		;fire crossbow, forbid new fire
	sta	movsta+N_CURSOR
	ldx	#N_CURSOR
	makeanim	curseq2
.nofire:
	ldx	#N_CURSOR
	jsr	doanim
.exit:
	rts
;
;	setcursor
;
setcursor:
	lda	idlemode	;if idle mode
	bne	.exit		;exit
	lda	gun		;if light gun selected,
	bne	.exit		;exit
;
;	process joystick positioning of cursor (site)
;
;tryright
	lda	right		;if right
	beq	.tryleft	;false, try left
	lda	movx+N_CURSOR	;load curpos x
	cmp	#SCWP-4-2	;going offscreen?
	bcs	.trydown	;if at edge, abort
	inc	movx+N_CURSOR	;else inc
	inc	movx+N_CURSOR	;else inc
	jmp	.trydown
.tryleft:
	lda	left		;if left
	beq	.trydown	;false, try down
	lda	movx+N_CURSOR	;load curpos x
	cmp	#2		;going offscreen?
	bcc	.trydown	;if at left edge, abort
	dec	movx+N_CURSOR	;else dec
	dec	movx+N_CURSOR	;else dec
.trydown:
	lda	down		;if right
	beq	.tryup		;false, try up
	lda	movy+N_CURSOR	;load curpos y
	cmp	#2		;check for limit
	bcc	.exit		;if at bottom, abort
	lda	movy+N_CURSOR	;else dec
	sec
	sbc	#2
	sta	movy+N_CURSOR	;twice
	jmp	.exit
.tryup:
	lda	up		;if right
	beq	.exit		;false, try up
	lda	movy+N_CURSOR	;load curpos 
	cmp	#SCHL-4-2	;compare with top
	bcs	.exit		;if at bottom, abort
	lda	movy+N_CURSOR	;else inc
	clc
	adc	#2
	sta	movy+N_CURSOR	;twice
.exit:
	rts
;
;	header management machine: call the following functions to create
;	headers in MARIA's display lists. The list may be cleared (clearsc),
;	background headers can be locked (lockbkg), foreground headers can
;	be cleared (clrmov), collections of headers can be made (tallobj),
;	vertical positions can be managed (vermov). The basic header-maker
;	is mkhdr.
;
;	read headers
;	given addr of header list in addrl/h, calls mkhdr until all in place
;	data format: baddrh (hi nibble) zone (lo nibble), baddrl, palwid, hpos
;	end list = $FF in first byte
;	It is important to maintain this and readheaders2 together.
;
readhdrs:
	ldy	#0

	lda	(addrl),y	;baddrh and curzon
	cmp	#$FF
	beq	.exit

	tax
	and	#$0F
	sta	curzon

	txa
	and	#$F0
	sta	baddrh
	incw	addrl

	lda	(addrl),y	;baddrl
	sta	baddrl
	incw	addrl

	lda	(addrl),y	;palwid
	sta	palwid
	incw	addrl

	lda	(addrl),y	;hpos
	sta	hpos
	incw	addrl

	jsr	mkhdr
	jmp	readhdrs	;loop

.exit:	rts
;
;	This special read header 2 is for use of the map screen to draw
;	connecting paths with different palettes, overriding the palette
;	in the header data
;	It is important to maintain this and readheaders together.
;
readhdrs2:
	ldy	#0

	lda	(addrl),y	;baddrh and curzon
	cmp	#$FF
	beq	.exit

	tax
	and	#$0F
	sta	curzon

	txa
	and	#$F0
	sta	baddrh
	incw	addrl

	lda	(addrl),y	;baddrl
	sta	baddrl
	incw	addrl

	lda	(addrl),y	;palwid
	and	#%00011111	;substitute palette
	ora	subpal
	sta	palwid
	incw	addrl

	lda	(addrl),y	;hpos
	sta	hpos
	incw	addrl

	jsr	mkhdr
	jmp	readhdrs2	;loop

.exit:	rts
;
;	read tall .. reads data for a tall object or series of tall objects
;	calls tallobj. Clobbers x,y,a
;
readtall:
	ldy	#0

	lda	(addrl),y	;baddrh and curzon
	cmp	#$FF
	beq	.exit

	tax			;curzon
	and	#$0F
	sta	curzon

	txa			;baddrh
	and	#$F0
	sta	baddrh
	incw	addrl

	lda	(addrl),y	;baddrl
	sta	baddrl
	incw	addrl

	lda	(addrl),y	;srcht
	sta	srcht
	incw	addrl

	lda	(addrl),y	;srcwid
	sta	srcw
	incw	addrl

	lda	(addrl),y	;hpos
	sta	hpos
	incw	addrl

	lda	(addrl),y	;destht
	sta	destht
	incw	addrl

	lda	(addrl),y	;palwid
	sta	palwid
	incw	addrl

	jsr	tallobj
	jmp	readtall	;loop

.exit:	rts
;
;	tall object
;	passes on mkhdr vars
;	also: dest height (destht) source height (srcht) source width (srcw)
tallobj:
	save	curzon	;save destructable vars
	save	destht
	save	baddrl
	save	baddrh
	sta	baddrhs
	save	srcht
	sta	srchts

.loop:	jsr	mkhdr
	dec	destht
	bne	.cont	;done?

	restore	srcht	;return
	restore	baddrh
	restore	baddrl
	restore	destht
	restore	curzon
	rts
.cont:
			;setup next zone
	inc	curzon	;dest
	dec	srcht	;src height
	bne	.else	;wrap src?
	lda	srchts	;yes, wrap zone counter
	sta	srcht
	lda	baddrhs	;wrap baddrh
	sta	baddrh
	lda	baddrl	;advance baddrl
	clc	
	adc	srcw
	sta	baddrl
	bne	.loop	;branch always .. acc will never be zero
.else:
	lda	baddrh	;source
	clc
	adc	#ZONEHL
	sta	baddrh
	bne	.loop	;branch always .. acc will never be zero
;
;	fill region with same bitmap
;	passes on mkhdr vars
;	also: dest height (destht)
fillreg:
	save	curzon	;save destructable vars
	save	destht

.loop:	jsr	mkhdr	;make headers until done
	inc	curzon
	dec	destht
	bne	.loop

	restore	destht	;return
	restore	curzon
	rts
;
;	vertical moving object
;	extended
;	Some peculiar code follows. I need to know if the object is above
;	or below screen, or on screen. A vpos from 192 to 255 is NEGATIVE
;	(below the screen) in this context, but the 6502 sees numbers going
;	negative at 128. Therefore, a double test is needed to determine if
;	it is negative in THIS context, and the shift-lefts (divide by 16) must
;	be SIGN EXTENDED to work in this context.
;	Parameters: vpos, srcht, all mkhdr pars except curzon
xvermov:
	lda	vpos
	lsr	;calc zone
	lsr
	lsr
	lsr
	tax
	lda	convzsign,x	;lookup proper zone sign
	sta	curzon

	lda	vpos	;calc address offset
	and	#$0f
	beq	.loop	;fraction of a zone?
	sta	vpos	;yes, store fractional vpos,
	inc	srcht	;increase vertical size,
	lda	baddrh	;adjust source addr
	sec
	sbc	vpos
	sta	baddrh

.loop:
	jsr	mkhdr	;make
	dec	srcht
	beq	.break	;more height?
	inc	curzon	;...yes
	lda	#ZONEHL
	clc
	adc	baddrh
	sta	baddrh
	jmp	.loop
.break:
	rts
;
;	clear screen
;
clearsc:
	jsr	clrhdr
	jsr	lockbkg
	jsr	nullhdrs
	rts
;
;	lock background .. this function protects stationary background
;	headers by setting the header base addresses to right after them
;	Should be called after backgrounds are set up
;
lockbkg:
	ldx	#(ZONECNT*2)-1	;copy from hdrplst to hdrmlst
.loop:	lda	hdrplst,x
	sta	hdrmlst,x
	dex
	bpl	.loop
	rts
;
;	clear moving objects from header lst
;	Copy locked header info to list
;	Should be called before moving objects are re-written
;
waitclear:
	jsr	waitbot
clrmov:
	ldx	#(ZONECNT*2)-1	;copy from hdrmlst to hdrplst
.loop:	lda	hdrmlst,x
	sta	hdrplst,x
	dex
	bpl	.loop
	jsr	nullhdrs
	rts
;
;	clear headers completely for re-forming
;	copy rom-based header addresses to ram
;
clrhdr:
	ldx	#(ZONECNT*2)-1	;copy from rom to ram
.loop:	lda	hdradl,x
	sta	hdrplst,x
	dex
	bpl	.loop
	rts
nullhdrs:
	ldx	#(ZONECNT-1)<<1
	ldy	#1		;point to second, palwid byte

.loop:	lda	hdrplst,x	;low byte
	sta	haddrl
	lda	hdrplst+1,x	;high byte
	sta	haddrh

	lda	#0		;null the header
	sta	(haddrl),y

	dex
	dex
	bpl	.loop
	rts
;
;	make header
;
;	parameters:	baddrl/h, palwid, curzon, hpos
;	locals:		haddrl/h
;	uses: a,x,y regs
mkhdr:
	lda	curzon		;return if off screen
	bmi	abort1
	cmp	#ZONECNT
	bpl	abort1

	asl	;lookup header list address, store in haddrl/h
	tax
	lda	hdrplst,x	;low byte, indirect addr
	sta	haddrl
	clc			;point to next header
	adc	#4		;notice only low address is incremented
	sta	hdrplst,x	;without carry, so a row of headers must be
				;spaced within one page

	lda	hdrplst+1,x	;high byte, indirect addr
	sta	haddrh

	ldy	#0
	lda	baddrl		;bitmap address low
	sta	(haddrl),y

	iny		;pal width
	lda	palwid
	sta	(haddrl),y

	iny		;bitmap address high
	lda	baddrh
	sta	(haddrl),y

	iny		;hpos
	lda	hpos
	sta	(haddrl),y

	ldy	#5		;null next header
	lda	#0
	sta	(haddrl),y

abort1:
	rts
;
;	init rand .. seed random number generator
;
initrand:
	lda	#189	;183: one survivor in town
	sta	seedtab
	lda	#202
	sta	seedtab+1
	lda	#215
	sta	seedtab+2
	lda	#2
	sta	rindex
	rts
;
;	init x to rand140, t1 to 0..256, jsr harder
;
randxth:
	jsr	rand140x
	jsr	randt1
	jsr	harder
	rts
;
;	place a random number in movt1,x
;
randt1:
	jsr	rand
	sta	movt1,x
	rts
;
;	return a random number from 13 .. 140, put it in movx,x
;
rand140x:
	jsr	rand
	and	#%01111111
	adc	#(SCWP-128-6)/2		;center range
	sta	movx,x
	rts
;
;	return a random number from 0 .. 63
;
rand63:
	jsr	rand
	and	#%00111111
	rts
;
;	return random number from 0 .. 159
;
rand160:
	jsr	rand
	and	#128-1
	sta	r160tmp
	jsr	rand
	and	#32-1
	clc
	adc	r160tmp
	rts

;
;	random number generator (mod 256)
;	three values in a table are added together, the sum replaces each of
;	the values in successive calls
;	uses A, Y regs
;
rand:	ldy	rindex		;load sum pointer
	adc	seedtab		;first value
	adc	seedtab+1	;second value
	adc	seedtab+2	;third value
	sta	seedtab,y	;store
	dey			;dec sum pointer
	bpl	.fall		;no wrap?
	ldy	#2		;wrap
.fall:
	sty	rindex		;store sum pointer
	rts	
;
;	play sound
;	give it id in A reg
;	this func called from macro "makesound"
;	clobbers temp
playsound:
	sta	temp		;save regs
	pushx
	pushy
	ldy	temp			;sound table index

	lda	AUDADDR,y	;read table for data address
	sta	addrl
	lda	AUDADDR+1,y
	sta	addrh

	ldy	#0
	lda	(addrl),y	;read priority nibble
	and	#%01110000
	sta	temp
;
;	if a channel is idle, choose it
;
	ldx	#0
	lda	shistory
	beq	.replacesound

	inx
	lda	shistory+1
	beq	.replacesound
;
;	set x to channel with lowest priority
;	or longest history if pri same
;
	sec
	lda	spriority
	sbc	spriority+1
	bne	.pridiff
	
	lda	shistory	;pri same, choose channel playing longest
	cmp	shistory+1
	rol			;carry bit becomes
	and	#1
	tax			;chosen channel
	jmp	.prready

.pridiff:
	rol			;carry
	and	#1		;bit
	tax			;becomes chosen channel
.prready:
;
;	if new sound has higher priority than lowest pri channel
;	replace channel with new sound, else return
;
	lda	temp		;if new sound has lower pri than
	cmp	spriority,x	;old sound,
	bmi	.exit		;exit
.replacesound:
	lda	addrl		;set saved address
	sta	saddrl,x
	lda	addrh
	sta	saddrh,x

	lda	temp		;set priority
	sta	spriority,x
;
;	set these things to zero
;
	lda	#0

	tay
	jsr	setav
	sta	sptr,x
	sta	audvshadow,x
;
;	set these things to 1
;
	lda	#1
	sta	sptr,x		;point to after control byte
	sta	stime,x		;1st count, immediate update

	lda	#$FF
	sta	shistory,x

	lda	(addrl),y	;set control byte
	sta	AUDC0,x

.exit:	popy
	popx
	rts
;
;	do sound
;	looks at saddrh, if non-zero, takes saddrh/l, and starts interpreting
;	audio data (format in macro "audi" and "audend")
dosound:
	ldx	#0
	jsr	dochannel
	ldx	#1
	jsr	dochannel
	rts
;
;	do one channel of audio
;	channel in x reg
;
dochannel:
	lda	shistory,x	;if no history, idle
	bne	.notidle
	rts
.notidle:
	cmp	#1		;if history > 1, dec
	beq	.nodec
	dec	shistory,x
.nodec:
	dec	stime,x		;if dec time not zero, exit
	beq	.update
	rts
.update:
	lda	saddrl,x	;set indirect address
	sta	addrl
	lda	saddrh,x
	sta	addrh

	ldy	sptr,x		;set index pointer
	lda	(addrl),y	;read first byte
	beq	.stopchan	;if zero, stop channel
	iny

	lsr			;set time till next update
	sta	stime,x		;low bit of vol now in carry

	lda	(addrl),y	;second byte (freq, vol)
	iny
	pha			;save it
	rol			;shift left, bringing back low bit from carry
	and	#%00001111
	jsr	setav

	pla			;get freq
	lsr			;shift in
	lsr
	lsr
	sta	AUDF0,x		;set freq

	tya			;save index pointer
	sta	sptr,x
	rts

.stopchan:
	lda	#0		;channel becomes idle
	sta	shistory,x
	jsr	setav
	rts
;
;	set audio volume
;	shadow to audvshadow
;	using these subs is necessary to allow PAUSE to fully stop audio
;	and resume it exactly where it left off.
;	Call with volume in a reg, channel in x reg
setav:	sta	audvshadow,x
	and	soundon
	sta	AUDV0,x
	rts
;
;	Interrupt machine: an interrupt jump table is maintained, and at any
;	time, the global word "intjmp" is set so that an indirect jump will be
;	made at the next MARIA zone interrupt, performing the correct function.
;
;	clear interrupt jump table
;	set them all to point to null function, except for the top and bottom of
;	screen, which sets background to sky color and black, respectively.
;
clrijt:
	jsr	waitbot
clrijt1:			;for "internal" use
	ldy	#0
.loop:	lda	#(intnull & $FF)
	sta	intjt,y
	iny
	lda	#(intnull >> 8)
	sta	intjt,y
	iny
	tya
	cmp	#(NUMBINT*2)
	bne	.loop


	lda	#(intsky & $FF)	;top of screen, PLUS first interrupt
	sta	intjt+INTZB
	sta	intjmp
	lda	#(intsky >> 8)
	sta	intjt+INTZB+1
	sta	intjmp+1

	setijt	INTBOT,intbot	;bottom of screen

	lda	#2		;set ptr to next jmp addr
	sta	intptr

	rts
;
;	non-maskable interrupt handler (maria zones)
;
inter:	sta	WSYNC
	pha		;save regs
	pushy
	jmp	(intjmp)

intsky:	lda	fadsky
	sta	WSYNC
	sta	BKGRND
	jmp	intret
intgrnd1:
	lda	fadgrnd1
	sta	WSYNC
	sta	BKGRND
	jmp	intret
intgrnd2:
	lda	fadgrnd2
	sta	WSYNC
	sta	BKGRND
	jmp	intret
intbot:
	lda	#BLACK
	sta	WSYNC
	sta	BKGRND
	lda	#1	;set bottom flag
	sta	botflag
	lda	#0	;clear interrupt count
	sta	intcnt
	lda	pauseon	;if not in pause, service clocks
	bne	intret
	dec	timer
	dec	clock
intnull:
intret:
	ldy	intptr		;setup next intjmp
	lda	intjt,y
	sta	intjmp
	iny
	lda	intjt,y
	sta	intjmp+1
	iny
	tya			;check for overflow
	cmp	#(NUMBINT*2)
	bne	.nowrap
	ldy	#0		;wrap
.nowrap:
	sty	intptr
	popy			;restore regs
	pla
	rti
endcode:
ENDCODE	equ	endcode
;
;	encryption area
;
;	if the following fails, code has invaded top-of-ROM

	.assert	(* <= $FF7A)	;check end (codeend)
;
;	encryption data
;
	.org	$FF80
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.dc.b	$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
;
;
;		
	.assert	(* <= $FFF8)	;check encryption end

	.org	$FFF8		;region verification
	.dc.b	$FF

	.org	$FFF9		;7800 cart identification
	.dc.b	((FIXROM >> 8) | $7)

	.org	$FFFA		;interrupt and reset vectors
	.dc.w	inter	;NMI
	.dc.w	main	;RESET
	.dc.w	dummy	;IRQ

.end
