;==============================================================================
;
;	Flyer - This little game runs on a VT-180 with screen addressing.
;		The game consists of an object that flys across the
;		screen, while zig-zagging up and down. The player is
;		sitting in a gun bunker at the bottom of the screen and
;		can fire a bullet at the flyer. Only one bullet can be
;		fired at a time and it must be a direct hit in order to
;		count.
;
;
;	Version 1.2 : 8-Dec-82	Incorporated modifications and suggestions
;			by Bruce 'Fort Collins' Trent.
;
;		This version has extra beeps when the flyer hits a
;		boundry and when the bullet fires. The bullet also bounces
;		off the top and returns to the gun, leaving a trail behind
;		it on the up traverse and erasing when going back down. 
;
;	Version 1.3 : 11-Dec-82 Modified to remove beeps altogether, for
;		now. Restricted hit possibilities so that you can only
;		score on the downward traverse of the bullet.
;
;==============================================================================
;
;			    Copyright Notice
;
;		Reproduction and/or distribution of this software
;		is forbidden without express written consent.
;
;				Dave Cook
;			Ball Aerospace Systems Division
;				P.O. 1062
;			      Boulder, Colo.
;					80306
;			      (303) 441-4058
;
;				27-Nov-82
;
;==============================================================================

b$dos	equ	5
readf	equ	1
typef	equ	2
diof	equ	6			; Direct console I/O function
ymax	equ	2			; Flyer screen boundries
ymin	equ	19
xmin	equ	1
xmax	equ	80
ymaxb	equ	1			; Bullet range boundries
yminb	equ	22
home	equ	23
flyer	equ	'`'			; Special graphics characters
bull	equ	'f'
bell	equ	7

main:	org	100h

	lxi	h, 0			; Save CP/M stack
	dad	sp
	shld	stack
	lxi	sp, stack

	call	init			; Initialize

	call	looper			; Call main routine

	lhld	stack			; Restore CP/M context
	xthl	
	ret
	page
;
;	Initialization routine.
;
init:	mvi	a, xmax			; Initialize flyer positions
	sta	lastx
	mvi	a, xmin
	sta	currx
	mvi	a, ymin
	sta	lasty
	sta	curry

	xra	a			; Initialize direction flags
	sta	xdirf
	sta	ydirf
	sta	bdirf

	mvi	a, 40			; Initialize bullet positions
	sta	lasxs
	sta	curxs
	mvi	a, home
	sta	lasys
	sta	curys

	xra	a			; Initialize shot counter
	sta	shots

	lxi	h, clearm		; Set up the screen
	call	sendm
	lxi	h, infom
	call	sendm
	lxi	h, altchr
	call	sendm

	lxi	h, bunkm		; Set up gun bunker
	call	sendm

	ret
	page
;
;	Main loop.
;
looper:	
	call	updfly			; Update the flyer position

	call	updbul			; Update the bullet position
	ora	a			; Did we hit the flyer ?
	jz	exit

	mvi	c, diof			; Now get user info
	mvi	e, 0ffh
	call	b$dos
	ora	a			; No input ?
	jz	looper

	ani	0dfh			; Convert to upper case
	cpi	5			; Quit ?
	jz	quiter
	cpi	'R'			; Cheat ?
	jz	exit

	lda	curys			; Bullet avaliable ?
	cpi	home
	jnz	looper

	dcr	a			; Yes, launch it.
	sta	curys
	lda	shots			; Update shot counter
	inr	a
	sta	shots
	mvi	h, 23			; Print out no. of shots fired
	mvi	l, 22
	call	setpos
	lda	shots
	call	deco
	call	sendb
	jmp	looper

	page
;
;	You get here when you nail the bastard (or cheat).
;
exit:
	lxi	h, rstchr
	call	sendm
;	lxi	h, clearm
;	call	sendm
	lxi	h, winm
	call	sendm
	lda	shots
	call	deco
	lxi	h, enditm
	call	sendm

endw:	mvi	c, diof			; Wait for a character
	mvi	a, 0ffh
	call	b$dos
	ora	a
	jz	endw

	ani	0dfh			; Convert to upper case
	cpi	5			; Quit ?
	jz	bailer

	call	init			; No, re-initialize and continue
	jmp	looper

bailer:					; Bail out
	lxi	h, clearm
	call	sendm
	ret

quiter:					; You get here by bailing out
	lxi	h, rstchr
	call	sendm
	lxi	h, clearm
	call	sendm
	lxi	h, quitm
	call	sendm
	ret
	page
;
;	Subroutine to update flyer position
;
updfly:
	lda	currx
	mov	h, a
	lda	curry
	mov	l, a
	call	setpos
	mvi	a, flyer
	call	sendc

	lda	lastx			; Erase last position
	mov	h, a
	lda	lasty
	mov	l, a
	call	setpos
	mvi	a, ' '
	call	sendc

	lda	currx			; Update last position
	sta	lastx
	lda	curry
	sta	lasty
;
;	Calculate next X-Y position
;
	lda	xdirf			; X right or left
	ora	a
	jnz	xp1

	lda	currx			; Hard right rudder
	inr	a
	sta	currx
	cpi	40
;	cz	sendb
;	cz	sendb
	cpi	xmax			; Right side of screen ?
;3	cz	sendb
	jnz	xp2
	mvi	a, 0ffh			; Yes, change directions
	sta	xdirf
	jmp	xp2

xp1:	lda	currx			; Hard left rudder
	dcr	a
	sta	currx
	cpi	40
;	cz	sendb
;	cz	sendb
	cpi	xmin			; Left side of screen ?
;3	cz	sendb
	jnz	xp2
	xra	a			; Yes, change directions
	sta	xdirf

xp2:
	lda	ydirf			; Y up or down ?
	ora	a
	jnz	yp1

	lda	curry			; Going up
	dcr	a
	sta	curry
	cpi	ymax			; Top of screen ?
;	cz	sendb
	jnz	yp2
	mvi	a, 0ffh			; Yes change directions
	sta	ydirf
	jmp	yp2

yp1:	lda	curry			; Going down
	inr	a
	sta	curry
	cpi	ymin			; Lower limit ?
;	cz	sendb
	jnz	yp2
	xra	a			; Yes, change directions
	sta	ydirf

yp2:	ret
	page
;
;	Subroutine to update the bullet position
;
updbul:
	lda	curys			; Now update bullet
	cpi	home
	jz	nohit			; It's in the barn, forget it.

	lda	bdirf			; Bullet going up or down ?
	ora	a
	jnz	godn

goup:	lda	curys			; Bump bullet pos up
	dcr	a
	sta	curys
	cpi	ymaxb
	jnz	lp2			; Off top screen ?

	inr	a
	sta	curys
	mvi	a, 0ffh			; Yes, set flag for down
	sta	bdirf
	jmp	lp2			; And continue...

godn:	lda	curys			; Bump bullet pos down
	inr	a
	sta	curys
	cpi	yminb
	jnz	lp2			; Off bottom screen ?

	xra	a
	sta	bdirf			; Yes, set flag for up
	mvi	a, home			; Reset bullet to home
	sta	curys
	lda	lasys			; And erase last bullet position
	mov	l, a
	lda	lasxs
	mov	h, a
	call	setpos
	mvi	a, ' '
	call	sendc
	jmp	nohit

lp2:	lda	curys
	mov	l, a			; Draw the bullet
	lda	curxs
	mov	h, a
	call	setpos
	mvi	a, bull
	call	sendc

	lda	lasys			; Erase last bullet
	mov	l, a
	lda	lasxs
	mov	h, a
	call	setpos

	lda	bdirf
	ora	a
	jnz	blnk1
	mvi	a, 'x'			; Draw trail if going up
	jmp	blnk2
blnk1:	mvi	a, ' '			; Erase if going down
blnk2:	call	sendc

	lda	curxs			; Update bullet pos
	sta	lasxs
	lda	curys
	sta	lasys
;
;	Now see if we have hit the flyer
;
	lda	ydirf			; Going down ?
	ora	a
	jz	nohit			; No, return

	mov	b, a			; Check Y coordinates
	lda	curry
	cmp	b
	jnz	lp3			; No, keep going

	lda	curxs			; Now check the X coordinates
	mov	b, a
	lda	currx
	cmp	b
	jz	gotit

nohit:	mvi	a, 0ffh			; No, didn't get him
	jmp	lp3

gotit:	xra	a			; We got him !
	ret

lp3:	ret
	page
;
;	Set cursor position.
;	H holds column, L holds line.
;
setpos:	mvi	a, 1bh
	call	sendc
	mvi	a, '['
	call	sendc
	mov	a, l
	call	deco
	mvi	a, ';'
	call	sendc
	mov	a, h
	call	deco
	mvi	a, 'H'
	call	sendc
	ret
	page
;
;	Output decimal value of binary in A reg.
;
deco:	push b ! push d

	mov	b, a		; Save A
	mvi	a, '0'		; Clear the buffer
	sta	dbuff
	sta	dbuff+1
	sta	dbuff+2
	mov	a, b		; Restore A

	cpi	200		; .gt. 200 ?
	jc	ck10
	sui	200		; Yes, adjust accum and store in buff
	mov	b, a
	mvi	a, '2'
	sta	dbuff
	jmp	dadj

ck10:	cpi	100		; .gt. 100 ?
	jc	dadj
	sui	100		; Yes, adjust accum and store in buff
	mov	b, a
	mvi	a, '1'
	sta	dbuff

dadj:				; Dec adjust accum
	mvi	c, 9		; Index counter
	mvi	a, 90

dad1:	cmp	b		; Check 10's digit
	jc	dout
	jz	dout
	sui	10		; No, try next lower
	dcr	c
	jnz	dad1
	jmp	dad2		; No 10's value

dout:	mov	d, a		; We have a 10's digit
	mov	a, b
	sub	d		; Subtract off the order of mag
	mov	b, a		; Save remainder
	mov	a, c		; Set up character
	adi	'0'
	sta	dbuff+1

dad2:	mov	a, b		; Set up last digit.
	adi	'0'
	sta	dbuff+2

	lda	dbuff		; Print out
	cpi	'0'
	cnz	sendc		; Blank out leading zeros
	lda	dbuff+1
	cpi	'0'
	jnz	do2
	lda	dbuff
	cpi	'0'
	jz	do3
do2:	call	sendc
do3:	lda	dbuff+2
	call	sendc

	pop d ! pop b
	ret
	page

sendc:	push b ! push d ! push h
	mvi	c, typef
	mov	e, a
	call	b$dos
	pop h ! pop d ! pop b
	ret

sendm:	mov	a, m
	ora	a
	rz
	call	sendc
	inx	h
	jmp	sendm

crlf:	push	d
	mvi	a, 0dh
	call	sendc
	mvi	a, 0ah
	call	sendc
	pop	d
	ret

sendb:	push	psw
	mvi	a, 7
	call	sendc
	pop	psw
	ret

	page
currx:	ds	1			; Current flyer X position
curry:	ds	1			; Current flyer Y position
lastx:	ds	1			; Last flyer X position
lasty:	ds	1			; Last flyer Y position
curxs:	ds	1			; Current bullet X position
curys:	ds	1			; Current bullet Y position
lasxs:	ds	1			; Last bullet X position
lasys:	ds	1			; Last bullet Y position
xdirf:	ds	1			; Flyer X direction flag
ydirf:	ds	1			; Flyer Y direction flag
bdirf	ds	1			; Bullet direction flag
shots:	ds	1			; Shot counter
dbuff:	ds	3			; Binary to decimal conv. buffer
;
;	Messages
;
infom:	db	1bh,'(0',1bh,'[1;1H'
	db	'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'
	db	'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'
	db	1bh,'[20;1H'
	db	'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'
	db	'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'
	db	1bh,'(B',1bh,'[7m'
	db	1bh,'[1;32HCookie`s Flyer'
	db	1bh,'[20;1HPress any key to fire'
	db	1bh,'[20;66HPress ^E to quit'
	db	1bh,'[22;1HNumber of shots fired'
	db	1bh,'[0m',0

clearm:	db	1bh,'[2J',0

altchr:	db	1bh,'(0',0

rstchr:	db	1bh,'(B',0

bunkm:	db	1bh,'[24;39flvk',0

winm:	db	1bh,'[5;7m',7,7,7
	db	1bh,'[10;10f',1bh,'#3'
	db	'Eat Shit `n Die !'
	db	1bh,'[11;10f',1bh,'#4'
	db	'Eat Shit `n Die !'
	db	1bh,'[0m',7,7,7,0dh,0ah,0ah,0ah
	db	9,9,'    It only took you ',0

enditm:	db	' shots !',0dh,0ah,0ah,0ah
	db	1bh,'[7m'
	db	1bh,'[20;1fPress any key to continue'
	db	1bh,'[0m',0

quitm:	db	1bh,'[5;7m',7,7,7
	db	1bh,'[12;10f',1bh,'#3'
	db	'What a Wimp !'
	db	1bh,'[13;10f',1bh,'#4'
	db	'What a Wimp !'
	db	1bh,'[0m',7,7,7,0dh,0ah,0ah,0ah,0ah,0ah,0
;
;	Local stack
;
	ds	100h
stack:	ds	2

	end	main
