[comp.sys.handhelds] Source for Joust v2.1, More Comments

catto@vivaldi.ecn.purdue.edu (Erin S Catto) (05/31/91)

Below is the new and improved source for Joust v2.1.  Changes are minor.
However the comments are improved (more).  This source may be compiled
on Chipper assembler.

							-Zoom
							catto@ecn.purdue.edu


========================================================================

;--------------
;Register Usage
;--------------
;
;V0	=	Sprite X coordinate (player, crows and eggs)
;V1	=	Sprite Y coordinate
;V2	=	Sprite X delta
;V3	=	Sprite Y delta
;V4	=	Current right/left flag (moves pointer)
;V5	=	Old right/left flag
;V6	=	Player's X coordinate, for collision checking, player dead flag
;V7	=	Player's Y coordinate, for collision checking
;V8	=	Mode of play flag
;V9	=	# players left
;VA	=	Sprite scope flag
;VB	=	# crows, by level
;VC	=	level
;VD	=	scratch
;VE	=	scratch
;VF	=	collision, greater/less than flag
;
;Many items are stored, see bottom of source code

;Constants
;---------

SCOREDELTA	=	1

SPRTHEIGHT     	=    	8		;height of sprite (player/crow)
SPRTWIDTH      	=    	8		;width of sprite

NONE        	=    	0		;Sprite scoping values (VA)
ONECROW        	=    	1
TWOCROWS       	=    	2
ONECROW1EGG	=	3
TWOEGGS		=	4
ONEEGG		=	5

GUYDEAD		=	#DD		;flag, V6

MODE1		=	0		;levels 1-3 (slow)
MODE2		=	1		;levels 4-7 (faster with lava)
MODE3		=	2		;levels 8-99 (fastest with lava)

KEYUP		=	#A
KEYRGT		=	#C
KEYLFT		=	3

PAD1TOP		=	28		;geometry of islands
PAD1BOT		=	32
PAD1RGT		=	16	;----------------------------	
PAD1LFT		=	112	;                           |
				;         ----2----         |
PAD2TOP		=	16	;                           |
PAD2BOT		=	20	;                           |
PAD2RGT		=	80	;--1--                 --1--|
PAD2LFT		=	48	;                           |
				;                           |
PAD3TOP		=	40	;	  ----3----         |
PAD3BOT		=	44	;                           |
PAD3RGT		=	80	;----------------------------
PAD3LFT		=	48

ROOF		=	0
FLOOR		=	60

BONUSLIMIT	=	106		;bonus round time limit

JP	BRAG

DA 'Joust2 by Zoom'

BRAG:		DW	#00FF		;turn on extended
		CALL	NAME		;title screen


;This routine initializes registers and the score
;------------------------------------------------

REPLAY:		LD	V0, 0		;zero score storage
		LD	I, SCORE
		LD	[I], V0
		LD	V8, MODE1
		LD	V9, 3		;three players
		LD	VC, 0


;This routine sets # of buzzards (crows), conducts level intro
--------------------------------------------------------------

NEWLEVEL:	LD	VD, 15
		CALL	DELAY
		CLS
		LD	VA, TWOCROWS
		ADD	VC, 1
		LD	VD, 7		
		SUB	VD, VC
		SNE	VF, 0		;7 - n < 0   ->    vf=0
		JP	STALL		;past level 8 freeze #crows
		SNE	VC, 4
		LD	V8, MODE2
		LD	VB, VC		;levels 1-6, #crows=level + 1
		ADD	VB, 1
RSTALL:		CALL	RAY1		;draw rays
		LD	VE, 27		;y coordinate of level number
		LD	VD, 9
		SUB	VD, VC
		SNE	VF, 0		;check if level > 9
		JP	TWODIGIT	;draw two digit level
		DW	#FC30		;10 byte font for VD
		LD	VD, 60
		DRW	VD, VE, 10
		CALL	RAY2		;erase rays
		JP	RESUME

STALL:		LD	VB, 8		;past level 7, #crows=8
		LD	V8, MODE3	;fast mode
		JP	RSTALL

TWODIGIT:	LD	I, LEVEL	;two digit level number
		LD	B, VC		;load bcd of vc into LEVEL data space
		LD	V2, [I]		;read back bcd
		LD	VD, 55
		DW	#F130
		DRW	VD, VE, 10
		LD	VD, 65
		DW	#F230
		DRW	VD, VE, 10
		CALL	RAY2
		JP	RESUME


;RESUME initializes sprites and screen or goes to bonus round
;------------------------------------------------------------

RESUME:		LD	VD, 7
		AND	VD, VC
		SNE	VD, 7		;every 7 levels is the bonus round
		JP	BONUS
		CALL	SCREEN
		CALL	INITGUY
		CALL	INITCROW1
		SE	VB, 0		;sometimes only one crow left
		CALL	INITCROW2
		LD	VD, 15		;delay argument
		CALL	DELAY


;MAIN is the game loop
----------------------

MAIN:		CALL	MOVEGUY
		SNE	V6, GUYDEAD
		JP	DIE
		SNE	VA, NONE
		JP	NEWLEVEL
		CALL	MOVEOTHERS	;handles all non-player sprites
		SE	V8, MODE1
		CALL	WAVE
		LD	VD, 5
		SNE	V8, MODE1
		CALL	DELAY
		LD	VD, 3
		SNE	V8, MODE2
		CALL	DELAY
		JP	MAIN


;DELAY is a subroutine which takes VD (scratch) as an argument
;-------------------------------------------------------------

DELAY:		LD	DT, VD
DLP:		LD	VD, DT
		SE	VD, 0
		JP	DLP
		RET


;MOVEGUY polls keyboard and sets up player motion
;-------------------------------------------------

MOVEGUY:	LD	I, GUYSAVE	;retrieve player registers
		LD	V5, [I]
		CALL	GODOWN
		LD	V2, 0		;start with delta x = 0
		LD	VD, KEYUP
		SKNP	VD
		CALL	GOUP
		LD	VD, KEYLFT
		SKNP	VD
		CALL	GOLEFT
		LD	VD, KEYRGT
		SKNP	VD
		CALL	GORIGHT
		CALL	DRAWGUY
		SNE	V6, GUYDEAD	;lava death
		RET
		SE	VF, 0
		CALL	COLLISION	;global collision routine
		RET


;DRAWGUY calls platform constraint routines (CHECKVERT & CHECKHORZ), does
;housekeeping and erases and redraws player sprite.  TITLEGUY, for the 
;the title and score screen, does not have platform constraints.
;------------------------------------------------------------------------

DRAWGUY:	CALL	CHECKVERT
		CALL	CHECKHORZ
TITLEGUY:	LD	VD, V0
		LD	VE, V1
		ADD	V0, V2
		ADD	V1, V3
		LD	I, GUY
		ADD	I, V5
		LD	V5, 127
		AND	V0, V5
		LD	V5, V4
		LD	V6, V0
		LD	V7, V1
		DRW	VD, VE, 8
		LD	I, GUY
		ADD	I, V4
		DRW	V0, V1, 8
		SNE	V1, 56
		LD	V6, GUYDEAD
		LD	I, GUYSAVE
		LD	[I], V5
		RET


;MOVEOTHERS supervises sprite motion
;-----------------------------------

MOVEOTHERS:	SNE	VA, ONECROW
		JP	MOVECROW1
		SNE	VA, TWOCROWS
		JP	MOVECROWS
		SNE	VA, ONECROW1EGG
		JP	MOVECROW1EGG1
		SNE	VA, TWOEGGS
		JP	MOVEEGGS
		SNE	VA, ONEEGG
		JP	MOVEEGG1

;MOVECROWS is used when two crows are present (VA=TWOCROWS)
;----------------------------------------------------------

MOVECROWS:	CALL	MOVECROW1
		SNE	VA, TWOCROWS	;if crow1 dies then crow2 becomes crow1
		CALL	MOVECROW2
		RET

;MOVECROW1 - although somewhat subtle when playing the game, only one crow
;attacks the player the other crow is just random.  CROW1 is the attacking
;crow.

MOVECROW1:	LD	I, CROW1SAVE
		LD	V5, [I]
		RND	VD, 3
		SNE	VD, 0
		CALL	GORANDOM	;random motion
		CALL	ATTACK		;within range, crow will attack
		CALL	DRAWCROW1
		SE	VF, 0		;collision?
		JP	CROW1COLL
		RET


;ATTACK finds the absolute distance between player and crow and compares
;this with a minimum attacking distance.  If the crow is close to the
;player ATTACK will instruct the crow to move towards the player and
;above it.
------------------------------------------------------------------------

ATTACK:		LD	VD, V6		;V6 = current player x coord.
		SUB	VD, V0		;V0 = crow x coord
		SNE	VF, 0		;V6 < V0 ?
		SUBN	VD, VF		;then VD = V0 - V6
		LD	VE, 16		;x distance attack criteria
		SUB	VE, VD
		SNE	VF, 0
		RET
		LD	VD, V7		;check y distance
		SUB	VD,V1
		SNE	VF, 0
		SUBN	VD, VF
		LD	VE, 12
		SUB	VE, VD
		SNE	VF, 0
		RET
		LD	VD, V6		;this part steers the crow towards
		SUB	VD, V0		;the player
		SNE	VF, 0
		CALL	GOLEFT
		SE	VF, 0
		CALL	GORIGHT
		LD	VD, V7
		SUB	VD, V1
		SE	VF, 0
		CALL	GODOWN
		SNE	VF, 0
		CALL	GOUP
		SNE	V1, V7
		CALL	GOUP
		RET


;MOVECROW2 does not instruct crow2 to attack the player (otherwise the crows
;would stick together).  Notice that crow2 is more random.  Also note that
;crow2 is only present if crow1 is present.
;---------------------------------------------------------------------------

MOVECROW2:	LD	I, CROW2SAVE
		LD	V5, [I]
		RND	VD, 1
		SNE	VD, 0
		CALL	GORANDOM
		CALL	DRAWCROW2
		SE	VF, 0
		JP	CROW2COLL	;collision routine for crows only
		RET

DRAWCROW1:	CALL	DRAWCROW
		LD	I, CROW1SAVE
		LD	[I], V5
		RET

DRAWCROW2:	CALL	DRAWCROW
		LD	I, CROW2SAVE
		LD	[I], V5
		RET


;DRAWCROW is similar to DRAWGUY
;------------------------------

DRAWCROW:	CALL	CHECKVERT
		CALL	CHECKHORZ
		SNE	V1, 52
		CALL	GOUP
TITLECROW:	LD	VD, V0
		LD	VE, V1
		ADD	V0, V2
		ADD	V1, V3 
		LD	I, CROW
		ADD	I, V5
		LD	V5, 127
		AND	V0, V5
		LD	V5, V4
		DRW	VD, VE, 8
		LD	I, CROW
		ADD	I, V4
		DRW	V0, V1, 8
		RET

MOVECROW1EGG1:	CALL	MOVECROW1
		CALL	MOVEEGG1
		RET

MOVEEGGS:	CALL	MOVEEGG2
		CALL	MOVEEGG1
		RET


;MOVEEGG1 coordinates the egg motion and determines if the egg
;should fade away.
--------------------------------------------------------------

MOVEEGG1:	LD	I, EGG1SAVE
		LD	V4, [I]
		SNE	V4, 2		;v4 flags if egg is on the floor
		JP	FADE1		;count down for egg removal
		LD	V2, 0
		CALL	HOPCHECK	;egg will hop on pads
		CALL	DRAWEGG
		LD	I, EGG1SAVE
		LD	[I], V4
		RET

FADE1:		ADD	V2, 1		;V2 becomes the count down to remove
		SNE	V2, 8		;the egg
		JP	BYEEGG1
		LD	I, EGG1SAVE
		LD	[I], V4
		RET

BYEEGG1:	LD	I, EGG
		DRW	V0, V1, 4
		SNE	VA, TWOEGGS	;take care of sprite scope
		JP	SHIFTEGG
		SNE	VA, ONECROW1EGG
		JP	MAKECROW2
		LD	VA, NONE
		RET


;SHIFTEGG (used by BYEEEGG1) moves egg2 data to egg1 when egg1 is 
;eaten.  Egg2 is never present without egg1.
;--------------------------------------------------------------------

SHIFTEGG:	LD	I, EGG2SAVE
		LD	V4, [I]
		LD	I, EGG1SAVE
		LD	[I], V4
		SNE	VB, 0
		LD	VA, ONEEGG
		SNE	VB, 0
		RET
		CALL	INITCROW1
		LD	VA, ONECROW1EGG
		RET


;MAKECROW2 is used by BYEEGG1 when crow1 is present
;--------------------------------------------------

MAKECROW2:	SNE	VB, 0
		LD	VA, ONECROW
		SNE	VB, 0
		RET
		CALL	INITCROW2
		LD	VA, TWOCROWS
		RET


;MOVEEGG2 is similar to MOVEEGG1
;-------------------------------

MOVEEGG2:	LD	I, EGG2SAVE
		LD	V4, [I]
		SNE	V4, 2
		JP	FADE2
		LD	V2, 0
		CALL	HOPCHECK
		CALL	DRAWEGG
		LD	I, EGG2SAVE
		LD	[I], V4
		RET

FADE2:		ADD	V2, 1
		SNE	V2, 8
		JP	BYEEGG2
		LD	I, EGG2SAVE
		LD	[I], V4
		RET

BYEEGG2:	LD	I, EGG
		DRW	V0, V1, 4
		SNE	VB, 0
		JP 	BB2
		CALL	INITCROW1
		LD	VA, ONECROW1EGG
		RET
BB2:            LD	VA, ONEEGG
                RET


;HOPCHECK determines if an egg is at the elevation of a platform
;---------------------------------------------------------------

HOPCHECK:	SNE	V1, PAD1TOP - 4
		JP	HOP1
		SNE	V1, PAD2TOP - 4
		JP	HOP23
		SNE	V1, PAD3TOP - 4
		JP	HOP23
		LD	V3, 1
		RET


;HOP routines first check the x coordinate of the egg, then moves the 
;egg up if the x coordinate is within the limits of a platform.
;--------------------------------------------------------------------

HOP1:		CALL	PAD1H
		SE	V3, 0
		RET
		LD	VD, 1
		LD	ST, VD
		LD	V3, #FD
		SNE	V4, 0
		LD	V2, #FE
		SNE	V4, 1
		LD	V2, #2
		RET

HOP23:		CALL	PAD23H		;platforms 2 & 3 have equal x limits
		SE	V3, 0
		RET
		LD	VD, 1
		LD	ST, VD
		LD	V3, #FD
		SNE	V4, 0
		LD	V2, #FE
		SNE	V4, 1
		LD	V2, #2
		RET


;DRAWEGG updates x and y coordinates and checks if the egg is on the floor
;-------------------------------------------------------------------------

DRAWEGG:	LD	VD, V0
		LD	VE, V1
		ADD	V0, V2
		ADD	V1, V3
		LD	I, EGG
		DRW	VD, VE, 4
		DRW	V0, V1, 4
		SNE	V1, 56
		LD	V4, 2
		RET


;The GO routines are generic motion functions that enhance interpretation
;------------------------------------------------------------------------

GOLEFT:		LD	V4, 8		;version 1 resorted to increasing
		LD	V2, #FC		;delta x and delta y to 
		RET			;increase speed.
					;Super Chip's speed makes this
GORIGHT:	LD	V4, 0		;unneccessary.
		LD	V2, 4		;Delays are used instead.
		RET

GOUP:		LD	V3, #FE
		RET

GODOWN:		LD	V3, 2
		RET

GORANDOM:	RND	VD, 1
		LD	ST, VD		;that awful clicking sound
		SNE	VD, 0
		CALL	GOLEFT
		SNE	VD, 1
		CALL	GORIGHT
		RND	VD, 1
		SNE	VD, 0
		CALL	GODOWN
		SNE	VD, 1
		CALL	GOUP
		RET


;WAVE uses a single draw with an a special sprite to switch the splashes
;from right to left.  Data storage (SPLASHSAVE) contains the current
;direction and coordinate.
;-----------------------------------------------------------------------

WAVE:		RND	VD, 3		;save time by skipping this routine
		SE	VD, 0		;75% of the time
		RET
		LD	I, SPLASHSAVE
		LD	V1, [I]
		LD	VD, 59
		LD	I, SPLASHXOR
		DRW	V0, VD, 5
		ADD	V0, V1
		SNE	V0, 8
		CALL	SPLASHRGT
		SNE	V0, 112
		CALL	SPLASHLFT
		LD	I, SPLASHSAVE
		LD	[I], V1
		RET

SPLASHRGT:	LD	V0, 16
		LD	V1,  8
		RET

SPLASHLFT:	LD	V0, 104
		LD	V1, #F8
		RET


;The collision routines.  Numerous routines are necessary to accomodate
;the different combination of sprites and to redefine the sprite scope when
;a sprite vanishes.  The routines are only called as a result of VF<>0
;after a draw command.  You could continuously check coordinates for
;collisions but that reduces speed.
;==========================================================================

;The next three routines handle crow collisions only, collisions resulting
;from drawing a crow on previously drawn pixels..

CROW1COLL:	CALL	CROWCOLL
		SNE	VF, 0
		JP	KILLCROW1
		RET

CROW2COLL:	CALL	CROWCOLL
		SNE	VF, 0
		JP	KILLCROW2
		RET


;CROWCOLL is used to determine which crow was hit.
;-------------------------------------------------

CROWCOLL:	LD	VD, V6			;V6 = player x
		SUB	VD, V0			;V0 = crow x
		SNE	VF, 0
		SUBN	VD, VF
		LD	VE, SPRTWIDTH
		SUB	VD, VE
		SE	VF, 0
		RET
		LD	VD, V7			;V7 = player y
		SUB	VD, V1			;V1 = crow y
		SNE	VF, 0
		SUBN	VD, VF
		LD	VE, SPRTHEIGHT
		SUB	VD, VE
		RET


;COLLISION is called buy MOVEGUY when the player collides with something
;This routine delegates collision checking based on the current sprite
;scope (VA).

COLLISION:	SNE	VA, TWOCROWS
		JP	COLLCC
		SNE	VA, ONECROW
		JP	KILLCROW1
		SNE	VA, TWOEGGS
		JP	EATEGGS
		SNE	VA, ONEEGG
		JP	EATEGG1
		JP	COLLCB


;If EATEGGS is called then it is only necessary to determine which egg
;collided with the player by comparing coordinates.

EATEGGS:	LD	I, EGG1SAVE
		LD	V4, [I]
		CALL	COLX
		SNE	VF, 0
		JP	EATEGG2
		CALL	COLY
		SNE	VF, 0
		JP	EATEGG2
		JP	EATEGG1

EATEGG1:	CALL	SCOREINC
		CALL	SHORT
		CALL	QUICK
		LD	I, EGG1SAVE
		LD	V4, [I]
		JP	BYEEGG1

EATEGG2:	CALL	SCOREINC
		CALL	SHORT
		CALL	QUICK
		LD	I, EGG2SAVE
		LD	V4, [I]
		JP	BYEEGG2


;COLLCB is called when VA = ONECROW1EGG

COLLCB:		LD	I, CROW1SAVE
		LD	V5, [I]
		CALL	COLX
		SNE	VF, 0
		JP	EATEGG1
		CALL	COLY
		SNE	VF, 0
		JP	EATEGG1
		JP	KILLCROW1


;COLLCC is called when two crows are present
;-------------------------------------------

COLLCC:		LD	I, CROW1SAVE
		LD	V5, [I]
		CALL	COLX
		SNE	VF, 0
		JP	KILLCROW2
		CALL	COLY
		SNE	VF, 0
		JP	KILLCROW2
		JP	KILLCROW1

COLX:		LD	VD, V6
		SUB	VD, V0
		SNE	VF, 0
		SUBN	VD, VF
		LD	VE, SPRTWIDTH
		SUB	VE, VD
		RET

COLY:		LD	VD, V7
		SUB	VD, V1
		SNE	VF, 0
		SUBN	VD, VF
		LD	VE, SPRTHEIGHT
		SUB	VE, VD
		RET


;KILLCROW1 is called once it has been determined that the player has collided
;with crow1.  So either the player dies or the crow dies and becomes an egg
;or there is a draw and BUMP1 is called.
;----------------------------------------------------------------------------

KILLCROW1:	LD	I, CROW1SAVE
		LD	V5, [I]
		SNE	V7, V1
		JP	BUMP1
		LD	VD, V7
		SUB	VD, V1
		SE	VF, 0
		JP	DIEGUY
		CALL	QUICK			;sound for dead crow
		CALL	SHORT
		LD	I, CROW
		ADD	I, V5
		DRW	V0, V1, 8		;erase crow
		SNE	VA, ONECROW1EGG		;new sprite scope
		JP	MAKEEGG2
		SNE	VA, TWOCROWS
		JP	SHIFTCROW
		SNE	VA, ONECROW
		LD	VA, ONEEGG               
		CALL	INITEGG1		;an egg!              
		RET

MAKEEGG2:	LD	VA, TWOEGGS
		CALL	INITEGG2
		RET


;SHIFTCROW is called if crow1 dies and crow2 is present.  I found it easier
;to move crow2 to crow1 instead of having crow2 alone.  We also need crow1
;because it attacks and crow2 doesn't
;--------------------------------------------------------------------------

SHIFTCROW:	CALL	INITEGG1
		LD	I, CROW2SAVE
		LD	V5, [I]
		LD	I, CROW1SAVE
		LD	[I], V5
		LD	VA, ONECROW1EGG
		RET


;KILLCROW2 is similar to KILLCROW1 except there is no data swapping
;between crows
;------------------------------------------------------------------

KILLCROW2:	LD	I, CROW2SAVE
		LD	V5, [I]
		SNE	V7, V1
		JP	BUMP2
		LD	VD, V7
		SUB	VD, V1
		SE	VF, 0
		JP	DIEGUY
		CALL	QUICK
		CALL	SHORT
		LD	I, CROW
		ADD	I, V5
		DRW	V0, V1, 8
		LD	VA, ONECROW1EGG
		CALL	INITEGG1
		RET

DIEGUY:		LD	V6, GUYDEAD	;flag is captured in mainloop
		RET			;this avoids jumping out of subroutines
					;I think CHIP dies if you do that

INITCROW2:	CALL	ADDCROW
		LD	I, CROW2SAVE
		LD	[I], V5
		RET

INITCROW1:	CALL	ADDCROW
		LD	I, CROW1SAVE
		LD	[I], V5
		RET

ADDCROW:	CALL	RANDINIT	;random crow placement
		ADD	VB, #FF		;decrement # of crows
		CALL	GOUP		;crow starts going up
		RND	VD, 1		;random right or left
		SE	VD, 1
		CALL	GOLEFT
		SE	VD, 0
		CALL	GORIGHT
		LD	I, CROW		;crow sprite
		ADD	I, V4
		DRW	V0, V1, 8
		LD	V5, V4
		RET


;RANDINIT places the new crows in four different locations randomly
;------------------------------------------------------------------

RANDINIT:	RND	VD, 3		;4 possibilities: 00 01 10 11
		SNE	VD, 0
		JP	STARTPAD1
		SNE	VD, 1
		JP	STARTPAD2
		SNE	VD, 2
		JP	STARTPAD3
STARTPAD4:	LD	V0, 120
		LD	V1, FLOOR - SPRTHEIGHT
		RET
STARTPAD3:	LD	V0, 64
		LD	V1, PAD3TOP - SPRTHEIGHT
		RET
STARTPAD2:	LD	V0, 64
		LD	V1, PAD2TOP - SPRTHEIGHT
		RET
STARTPAD1:	LD	V0, 8
		LD	V1, PAD1TOP - SPRTHEIGHT
		RET

INITEGG1:	CALL	INITEGG
		LD	I, EGG1SAVE
		LD	[I], V4
		RET

INITEGG2:	CALL	INITEGG
		LD	I, EGG2SAVE
		LD	[I], V4
		RET

;INITEGG places the egg 8 pixels below the dead crow
;---------------------------------------------------

INITEGG:	ADD	V1, 8		;v1 is dead crow y coordinate
		LD	VD, 55		;check the floor
		SUB	VD, V1		;so the egg won't fall thru
		SNE	VF, 0
		LD	V1, 55
		RND	V4, 1
		LD	I, EGG
		DRW	V0, V1, 4
		RET

;The BUMP routines handle equal height collisions between the player and crow
;----------------------------------------------------------------------------

BUMP1:		CALL	BUMPTEST
		SE	VF, 0
		JP	BUMP1RIGHT
		CALL	GORIGHT		;set delta x
		CALL	DRAWCROW1	;adds delta x, draws
		CALL	DRAWCROW1	;adds delta x again and draws
		JP	BUMPGUYLEFT
BUMP1RIGHT:	CALL	GOLEFT
		CALL	DRAWCROW1
		CALL	DRAWCROW1
		JP	BUMPGUYRIGHT

BUMP2:		CALL	BUMPTEST
		SE	VF, 0
		JP	BUMP2RIGHT
		CALL	GORIGHT
		CALL	DRAWCROW2
		CALL	DRAWCROW2
		JP	BUMPGUYLEFT
BUMP2RIGHT:	CALL	GOLEFT
		CALL	DRAWCROW2
		CALL	DRAWCROW2
		JP	BUMPGUYRIGHT


;BUMPTEST determines which side the player is on so that s/he is bumped in
;that direction.
;-------------------------------------------------------------------------

BUMPTEST:	LD	VD, 3
		LD	ST, VD
		LD	VD, V6
		SUB	VD, V0
		RET

BUMPGUYRIGHT:	LD	I, GUYSAVE
		LD	V5, [I]
		CALL	GORIGHT
		CALL	DRAWGUY
		CALL	DRAWGUY
		RET

BUMPGUYLEFT:	LD	I, GUYSAVE
		LD	V5 , [I]
		CALL	GOLEFT
		CALL	DRAWGUY
		CALL	DRAWGUY
		RET


;DIE is jumped to from the main loop.  It updates the player count, determines
;if the game is over and if not sets up the crows to resume.  Eggs are lost.

DIE:		CALL	SHORT
		CALL	QUICK
		CALL	LONG
		LD	VD, 10
		CALL	DELAY
		ADD	V9, #FF
		SNE	V9, #0
		JP	FINI
		SNE	VA, ONECROW
		ADD	VB, 1
		SNE	VA, ONECROW1EGG
		ADD	VB, 1
		SNE	VA, TWOCROWS
		ADD	VB, 2
		LD	VA, TWOCROWS
		SNE	VB, 0
		JP	NEWLEVEL
		LD	VA, TWOCROWS
		SNE	VB, 1
		LD	VA, ONECROW
		JP	RESUME

FINI:		CALL	BYE		;little tune
		CLS
		CALL	SCOREDRW
		CALL	FINITE		;flying birds
		JP	REPLAY

BYE:		LD	VD, 12		;plays ending tune
		LD	ST, VD
		LD	VD, #18
		CALL	DELAY
		CALL	SHORT
		CALL	SHORT
		CALL	LONG
		CALL	LONG
		LD	VD, 32
		CALL	DELAY
		CALL	LONG
		CALL	LONG
		LD	VD, 32
		CALL	DELAY
		RET

QUICK:		LD	VD, 2
		LD	ST, VD
		LD	VD, 5
		CALL	DELAY
		RET

SHORT:		LD	VD, 4
		LD	ST, VD
		LD	VD, 10
		CALL	DELAY
		RET

LONG:		LD	VD, 8
		LD	ST, VD
		LD	VD, 20
		CALL	DELAY
		RET

SCOREINC:	LD	I, SCORE
		LD	V0, [I]
		ADD	V0, SCOREDELTA
		LD	[I], V0
		RET

SCOREDRW:	LD	I, SCORE
		LD	V0, [I]
		LD	B, V0
		LD	V2, [I]
		LD	VE, 27
		LD	VD, 49
		DW	#F030               ;10 BYTE FONT FOR V0
		DRW	VD, VE, 10
		ADD	VD, 10
		DW	#F130               ;10 BYTE FONT FOR V1
		DRW	VD, VE, 10
		ADD	VD, 10
		DW	#F230               ;10 BYTE FONT FOR V2
		DRW	VD, VE, 10
		RET


RAY1:		LD	V3, 0
		LD	V4, 0
		LD	V5, 124
		LD	V6, 62

RAY2:		LD	I, DOT
CONV:		DRW	V3, V4, 3
		DRW	V3, V6, 3
		DRW	V5, V4, 3
		DRW	V5, V6, 3
		ADD	V3, 4
		ADD	V4, 2
		ADD	V5, #FC
		ADD	V6, #FE
		LD	VD, 4
		CALL	DELAY
		SNE	V3, 64
		RET
		SNE	V3, 128
		RET
		JP	CONV

INITGUY:	LD	V4, 0
		LD	V5, 0
		LD	V0, PAD1LFT
		LD	V1, PAD1TOP - 8
		LD	I, GUY
		DRW	V0, V1, 8
		LD	I, GUYSAVE
		LD	[I], V5
		RET


;CHECKVERT and CHECKHORZ keep the crows and players from running through the
;platforms.  Very important routines.  Note that since Chipper allows
;constants to be named that you change the platform postions somewhat without
;glitching the code.  Awesome!

CHECKVERT:	SNE	V1, ROOF
		JP	CHECKROOF
		SNE	V1, FLOOR - SPRTHEIGHT
		JP	CHECKFLOOR

		LD	VD, 2
		SE	V3, VD
		JP	STOPUP

		SNE	V1, PAD1TOP - SPRTHEIGHT
		JP	PAD1H
		SNE	V1, PAD2TOP - SPRTHEIGHT
		JP	PAD23H
		SNE	V1, PAD3TOP - SPRTHEIGHT
		JP	PAD23H
		RET

STOPUP:		SNE	V1, PAD1BOT
		JP	PAD1H
		SNE	V1, PAD2BOT
		JP	PAD23H
		SNE	V1, PAD3BOT
		JP	PAD23H
		RET

PAD1H:		LD	VD, PAD1RGT
		SUBN	VD, V0
		SNE	VF, 0
		JP	YHOLD
		LD	VD, PAD1LFT - SPRTWIDTH
		SUB	VD, V0
		SNE	VF, 0
		JP	YHOLD
		RET

PAD23H:		LD	VD, PAD2LFT - SPRTWIDTH+1
		SUBN	VD, V0
		SNE	VF, 0
		RET
		LD	VD, PAD2RGT
		SUBN	VD, V0
		SNE	VF, 0
		JP	YHOLD
		RET

CHECKROOF:	LD	VD, #FE
		SNE	V3, VD
		CALL	GODOWN
		RET

CHECKFLOOR:	LD	VD, 2
		SE	V3, VD
		RET
		SNE	V8, MODE1
		JP	YHOLD
		SE	V8, MODE1
		JP	PAD1H
		RET

YHOLD:		LD	V3, 0
		RET 

CHECKHORZ:	SNE	V2, 0
		RET
		LD	VD, 4
		SE	V2, VD
		JP	STAYLEFT

		SNE	V0, PAD1LFT - SPRTWIDTH
		JP	PAD1V
		SNE	V0, PAD2LFT - SPRTWIDTH
		JP	PAD23V
		RET

STAYLEFT:	SNE	V0, PAD1RGT
		JP	PAD1V
		SNE	V0, PAD2RGT
		JP	PAD23V
		RET

PAD1V:		LD	VD, PAD1TOP - SPRTHEIGHT - 3
		SUBN	VD, V1
		SNE	VF, 0
		RET
		LD	VD, PAD1BOT + 1
		SUBN	VD, V1
		SNE	VF, 0
		JP	XHOLD
		RET

PAD23V:		LD	VD, 28
		SUB	VD, V1
		SNE	VF, 0
		JP	PAD3V

PAD2V:		LD	VD, PAD2TOP - SPRTHEIGHT - 3
		SUBN	VD, V1
		SNE	VF, 0
		RET
		LD	VD, PAD2BOT + 1
		SUBN	VD, V1
		SNE	VF, 0
		JP	XHOLD
		RET

PAD3V:		LD	VD, PAD3TOP - SPRTHEIGHT - 3
		SUBN	VD, V1
		SNE	VF, 0
		RET
		LD	VD, PAD3BOT + 1
		SUBN	VD, V1
		SNE	VF, 0
		JP	XHOLD
		RET

XHOLD:		LD	V2, 0
		RET

SCREEN:		CLS
		LD	VD, 0
		LD	VE, 60
		LD	I, SOLIDPAD
		DRW	VD, VE, 4
		LD	VD, 8
		DRW	VD, VE, 4
		LD	I, CENTERPAD
		LD	VD, 16
		SNE	V8, MODE1
		CALL	FLOOR1
		SE	V8, MODE1
		CALL	FLOOR2
		LD	I, CENTERPAD
		LD	VE, PAD1TOP
		LD	VD, PAD1LFT + 8
		DRW	VD, VE, 4
		LD	VD, PAD1RGT - 16
		DRW	VD, VE, 4
		LD	VD, PAD2LFT + 8
		LD	VE, PAD2TOP 
		DRW	VD, VE, 4
		LD	VD, PAD2LFT + 16
		DRW	VD, VE, 4
		LD	VE, PAD3TOP
		DRW	VD, VE, 4
		LD	VD, PAD3LFT + 8
		DRW	VD, VE, 4
		LD	I, RIGHTPAD
		LD	VD, PAD3RGT - 8
		DRW	VD, VE, 4
		LD	VE, PAD2TOP
		DRW	VD, VE, 4
		LD	VD, PAD1RGT - 8
		LD	VE, PAD1TOP
		DRW	VD, VE, 4
		LD	I, LEFTPAD
		LD	VD, PAD1LFT
		DRW	VD, VE, 4
		LD	VE, PAD3TOP
		LD	VD, PAD3LFT
		DRW	VD, VE, 4
		LD	VE, PAD2TOP
		DRW	VD, VE, 4
		CALL	PLAYSLEFT
		RET

FLOOR1:		DRW	VD, VE, 4
		ADD	VD, 8
		SE	VD, 128
		JP	FLOOR1
		RET


;FLOOR2 has lava

FLOOR2:		LD	VD, 112
		DRW	VD, VE, 4
		LD	VD, 120
		DRW	VD, VE, 4
		LD	VD, 16
		LD	I, SPLASH
		LD	VE, 59
IWLP:		DRW	VD, VE, 5
		ADD	VD, 8
		SE	VD, 112
		JP	IWLP
		LD	V0, 104
		LD	V1, #F8
		LD	I, SPLASHSAVE
		LD	[I], V1
		RET

PLAYSLEFT:	SNE	V9, 1
		RET
		LD	VD, 1
		LD	VE, 61
		LD	I, DOT
		DRW	VD, VE, 3
		ADD	VD, 4
		SE	V9, 2
		DRW	VD, VE, 3
		ADD	VD, 4
		LD	V6, 3
		SUB	V6, V9
		SNE	VF, 0
		DRW	VD, VE, 3
		RET

NAME:		LD	I, TITLE
		LD	VD, 36
		LD	VE, 24
		DRW	VD, VE, 0
		LD	V0, 32
		ADD	I, V0
		ADD	VD, 16
		DRW	VD, VE, 0
		ADD	I, V0
		ADD	VD, 16
		DRW	VD, VE, 0
		ADD	I, V0
		ADD	VD, 16
		DRW	VD, VE, 0

FINITE:		LD	V8, 0		;animation demo setup
		LD	VB, 1
		LD	VA, 0
		CALL	INITCROW1
		CALL	INITGUY
		CALL	GORIGHT
		LD	I, GUYSAVE
		LD	[I], V5

TLP:		LD	VD, 10
		CALL	DELAY
		LD	I, GUYSAVE
		LD	V5, [I]
		CALL	TSUB
		CALL	TITLEGUY
		LD	I, GUYSAVE
		LD	[I], V5
		LD	I, CROW1SAVE
		LD	V5, [I]
		CALL	TSUB
		CALL	TITLECROW
		LD	I, CROW1SAVE
		LD	[I], V5
		LD	VD, KEYUP
		SKP	VD
		JP	TLP
		RET

TSUB:		RND	VD, #F
		SNE	VD, 0
		CALL	GORANDOM
		SNE	V1, 2
		LD	V3, 2
		SNE	V1, 54
		LD	V3, #FE
		RET

BONUS:		CALL	SCREEN
		CALL	INITGUY
		LD	I, EGG
		LD	VE, PAD2TOP - 4
		LD	VD, PAD2LFT + 2
		DRW	VD, VE, 4
		ADD	VD, 12
		DRW	VD, VE, 4
		ADD	VD, 12
		DRW	VD, VE, 4
		LD	VE, PAD3TOP - 4
		LD	VD, PAD3LFT + 2
		DRW	VD, VE, 4
		ADD	VD, 12
		DRW	VD, VE, 4
		ADD	VD, 12
		DRW	VD, VE, 4
		LD	VE, PAD1TOP - 4
		LD	VD, PAD1RGT - 6
		DRW	VD, VE, 4
		LD	VE, FLOOR - 4
		DRW	VD, VE, 4
		LD	VD, PAD1LFT + 2
		DRW	VD, VE, 4
		LD	V6, 0
		LD	V7, 0

;--------------------------
;Bonus Round Register Usage
;--------------------------
;v0 = guy x
;v1 = guy y
;v2 = guy delta x
;v3 = guy delta y
;v4 = current right/left flag
;v5 = old right/left flag
;v6 = number of eggs eaten
;v7 = countdown timer

BONUSMAIN:	ADD	V7, 1
		SNE	V7, BONUSLIMIT
		JP	NEWLEVEL
		LD	VD, 1
		LD	ST, VD
		LD	VD, 3
		CALL	DELAY
		LD	I, GUYSAVE
		LD	V5, [I]
		CALL	GODOWN
		LD	V2, 0
		LD	VD, KEYUP
		SKNP	VD
		CALL	GOUP
		LD	VD, KEYLFT
		SKNP	VD
		CALL	GOLEFT
		LD	VD, KEYRGT
		SKNP	VD
		CALL	GORIGHT
		CALL	CHECKVERT
		CALL	CHECKHORZ
		LD	VD, V0
		LD	VE, V1
		ADD	V0, V2
		ADD	V1, V3
		LD	I, GUY
		ADD	I, V5
		LD	V5, 127
		AND	V0, V5
		LD	V5, V4
		DRW	VD, VE, 8
		LD	I, GUY
		ADD	I, V4
		DRW	V0, V1, 8
		SNE	V1, 56
		JP	BONUSDIE
		LD	I, GUYSAVE
		LD	[I], V5
		SE	VF, 0
		CALL	BONUSCHECK
		SNE	V6, 9
		JP	BIGBONUS
          	JP	BONUSMAIN

BONUSCHECK:	LD	VE, FLOOR - 8
		SNE	V1, VE
		JP	FLOORBONUS
		LD	VE, PAD1TOP - 8
		SNE	V1, VE
		JP	PAD1BONUS
		LD	VE, PAD2TOP - 8
		SNE	V1, VE
		JP	PAD23BONUS
		LD	VE, PAD3TOP - 8
		SNE	V1, VE
		JP	PAD23BONUS
		RET

FLOORBONUS:	LD	VD, PAD1LFT + 4
		SNE	V0, VD
		JP	BONUSEGG
		LD	VD, PAD1RGT - 4
		SNE	V0, VD
		JP	BONUSEGG
		RET

PAD1BONUS:	LD	VD, PAD1RGT - 4
		SNE	V0, VD
		JP	BONUSEGG
		RET

PAD23BONUS:	LD	VD, PAD2LFT + 4
		SNE	V0, VD
		JP 	BONUSEGG
		ADD	VD, 12
		SNE	V0, VD
		JP	BONUSEGG
		ADD	VD, 12
		SNE	V0, VD
		JP	BONUSEGG
		RET

BONUSEGG:	ADD	VD, #FE
		ADD	VE, 4
		LD	I, EGG
		DRW	VD, VE, 4
		CALL	SHORT
		CALL	QUICK
		ADD	V6, 1
		LD	I, SCORE
		LD	V0, [I]
		ADD	V0, SCOREDELTA
		LD	[I], V0
		RET

BONUSDIE:	LD	VD, 8
		LD	ST, VD
		LD	VD, 20
		CALL	DELAY
		ADD	V9, #FF
		SNE	V9, #0
		JP	FINI
		JP	NEWLEVEL

BIGBONUS:	LD	I, SCORE
		LD	V0, [I]
		ADD	V0, 8
		LD	[I], V0
		ADD	V9, 1
		CALL	LONG
		CALL	SHORT
		CALL	LONG
		JP	NEWLEVEL

SCORE:		DB	0, 0, 0

DOT:		DB	$01000000, $11100000, $01000000

GUY:		DB	$00000110, $00001111, $00001100, $00001100
		DB	$00000110, $11111111, $01111111, $00011110

		DB	$01100000, $11110000, $00110000, $00110000
		DB	$01100000, $11111111, $11111110, $01111000

CROW:		DB	$00001110, $00001111, $00001100, $00001100
		DB	$11111110, $01111111, $00011111, $00001110

		DB	$01110000, $11110000, $00110000, $00110000
		DB	$01111111, $11111110, $11111000, $01110000      

GUYSAVE:	DB	0, 0, 0, 0, 0, 0
CROW1SAVE:	DB	0, 0, 0, 0, 0, 0
CROW2SAVE:	DB	0, 0, 0, 0, 0, 0

EGG1SAVE:	DB	0, 0, 0, 0, 0
EGG2SAVE:	DB	0, 0, 0, 0, 0

RIGHTPAD:	DB	$11111111, $10111010, $11101000, $10000000
LEFTPAD:	DB	$11111111, $01101101, $00011011, $00000010
CENTERPAD:	DB	$11111111, $11101110, $10111011, $10110110
SOLIDPAD:	DB	$11111111, $11111111, $11111111, $11111111

LEVEL:		DB	0, 0, 0	;used for twodigit level

SPLASH:		DB	$00000110, $00011100, $00101000, $01011100, $11111110
SPLASHXOR:	DB	$01100110, $00100100, $00111100, $01100110, $00000000
SPLASHSAVE:	DB	0, 0	;right/left flag and x position

EGG:		DB	$01100000, $11110000, $11110000, $01100000

TITLE:    DB   $00000000, $11000000
          DB   $00000000, $11000000
          DB   $00000000, $11000000
          DB   $00000000, $11000000
          DB   $00000000, $11000000
          DB   $00000000, $11000000
          DB   $00000000, $11000011
          DB   $00000000, $11000111
          DB   $00000000, $11001100
          DB   $00000000, $11001100
          DB   $11000000, $11001100
          DB   $11000000, $11001100
          DB   $11000000, $11001100
          DB   $11000000, $11001100
          DB   $01111111, $10000111
          DB   $00111111, $00000011     

          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000    
          DB   $00000000, $00000000
          DB   $11110000, $11000000
          DB   $11111000, $11000000
          DB   $00001100, $11000000
          DB   $00001100, $11000000
          DB   $00001100, $11000000
          DB   $00001100, $11000000
          DB   $00001100, $11000000
          DB   $00001100, $11000000
          DB   $11111000, $01111111
          DB   $11110000, $00111111
     
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $00000000, $00000000
          DB   $11000011, $11111100
          DB   $11000111, $11111100
          DB   $11001100, $00000000
          DB   $11001100, $00000000
          DB   $11000111, $11110000
          DB   $11000011, $11111000
          DB   $11000000, $00001100
          DB   $11000000, $00001100
          DB   $11001111, $11111000
          DB   $11001111, $11110000


          DB   $00000000, $0
          DB   $00000000, $0
          DB   $00110000, $0
          DB   $00110000, $0
          DB   $00110000, $0
          DB   $00110000, $0
          DB   $11111100, $0
          DB   $11111100, $0
          DB   $00110000, $0
          DB   $00110000, $0
          DB   $00110000, $0
          DB   $00110000, $0
          DB   $00110011, $0
          DB   $00110011, $0
          DB   $00011110, $0
          DB   $00001100, $0