
; part 3

; 'pacman2.s' source , see accompaning text in the July 1994 issue
; of Amiga computing . Written by Mark Jackson using Devpac 3.02

; this month I've added the background graphics , and (after hours of
; trying!) I finally got the movement routines to work the way I
; wanted them to . So now pacman moves in the paths , and for example
; when you're moving right along a path and press up , at then next
; opportunity pacman will go up a path! .



	section	pacman,code_c		; put in CHIP memory
	opt	c-,o+			; not case-sensitive
					; optimisation on


	move.l	4.w,a6			; execbase
	jsr	forbid(a6)		; turn off multitasking!

	lea	$dff000,a5		; a5 always points to
					; register's base address

	lea	gfx_lib,a1		; name of library to open
	moveq	#0,d0			; version number unimportant
	move.l	4.w,a6			; execbase
	jsr	openlib(a6)		; open graphics-library
	move.l	d0,gfx_base		; save base address


	move.l	#screen,d0		; address of first bitplane
	move.w	d0,pl1l			; set pointer low word
	swap	d0
	move.w	d0,pl1h			; and high word

	move.l	#screen+40*256,d0
	move.w	d0,pl2l
	swap	d0
	move.w	d0,pl2h

	move.l	#screen+40*256*2,d0
	move.w	d0,pl3l
	swap	d0
	move.w	d0,pl3h


	move.l	#sprite1,d0		; address of sprite
	move.w	d0,sp0l			; set pointer low word
	swap	d0
	move.w	d0,sp0h			; and high word

	move.l	#sprite2,d0
	move.w	d0,sp1l
	swap	d0
	move.w	d0,sp1h


	move.l	gfx_base,a6		; graphics-library base address
	move.w	#$80,dmacon(a5)		; turn copper dma off
	move.l	$32(a6),old_copper	; save address of old copper-list
	move.l	#new_copper,$32(a6)	; insert our new copper-list
	move.w	#$8080,dmacon(a5)	; and turn copper dma back on!


start_game:				; reset all variables ->
	move.w	#151,x			; pacman x-coordinate
	move.w	#156,y			; pacman y-coordinate
	move.w	#1,dir			; pacman direction
	move.w	#1,dir2			; set other to same (see later)
	move.w	#0,score		; player's score
	move.w	#5,lives		; player's number of lives

	bsr	draw_lives		; draw the number of lives
	bsr	print_score
	bsr	draw_pacman		; put pacman on screen

	bsr	ready			; print 'are you ready?' and wait

main_loop:
	move.b	vhposr(a5),d0		; get scanline
	cmp.b	#$ff,d0			; reached line $ff?
	bne.s	main_loop		; not yet


	bsr	read_joystick		; read joystick and adjust coords
	bsr	draw_pacman		; put sprite in correct position
	bsr	animate_pacman		; animate sprite

	bsr	print_score
	bsr	draw_lives		; draw number of lives on screen


	move.b	$bfec01,d0		; read keyboard (raw keycode)
	eor.b	#$ff,d0			; decode byte
	ror.b	#1,d0

	cmp.b	#$45,d0			; escape key pressed?
	beq.s	quit_game		; if so then quit game!

	cmp.b	#$10,d0			; 'q' key pressed?
	beq.s	start_game		; if so then restart game

	cmp.b	#$19,d0			; 'p' key pressed?
	bne.s	no_pause		; no - carry on
	bsr	pause_game		; else pause game
no_pause:

	tst.w	lives			; have player's lives reached zero?
	bne.s	main_loop		; nope - do loop again!

	bsr	game_over		; else print 'game over' , etc.
	bra	start_game		; and start again


quit_game:
	move.l	gfx_base,a6		; graphics-library base address
	move.w	#$80,dmacon(a5)		; copper dma off
	move.l	old_copper,$32(a6)	; restore system copper-list
	move.w	#$8080,dmacon(a5)	; copper dma on

	move.l	gfx_base,a1		; graphics-library base address
	move.l	4.w,a6			; execbase
	jsr	closelib(a6)		; close library
error:
	move.l	4.w,a6			; execbase
	jsr	permit(a6)		; multitasking on

	moveq	#0,d0			; no errors , please!
	rts				; and return to CLI


old_copper:				; space to store address of
	dc.l	0			; system copper-list

new_copper:				; our new copper-list
	dc.w	bplcon0,$3200		; 5 bitplane (32 colour) screen
	dc.w	bplcon1,0		; hardware-scroll value
	dc.w	bplcon2,$20		; video priority
	dc.w	bpl1mod,0		; bitplane modulo (odd bitplanes)
	dc.w	bpl2mod,0		; bitplane modulo (even bitplanes)
	dc.w	ddfstrt,$38		; left edge of screen
	dc.w	ddfstop,$d0		; right edge of screen
	dc.w	diwstrt,$2c81		; top left corner of screen
	dc.w	diwstop,$2cc1		; bottom right corner of screen


	dc.w	bpl1pth				; bitplane pointers
pl1h:	dc.w	0,bpl1ptl
pl1l:	dc.w	0,bpl2pth
pl2h:	dc.w	0,bpl2ptl
pl2l:	dc.w	0,bpl3pth
pl3h:	dc.w	0,bpl3ptl
pl3l:	dc.w	0

	dc.w	spr0pth				; sprite pointers
sp0h:	dc.w	0,spr0ptl
sp0l:	dc.w	0,spr1pth
sp1h:	dc.w	0,spr1ptl
sp1l:	dc.w	0,spr2pth
sp2h:	dc.w	0,spr2ptl
sp2l:	dc.w	0,spr3pth
sp3h:	dc.w	0,spr3ptl
sp3l:	dc.w	0,spr4pth
sp4h:	dc.w	0,spr4ptl
sp4l:	dc.w	0,spr5pth
sp5h:	dc.w	0,spr5ptl
sp5l:	dc.w	0,spr6pth
sp6h:	dc.w	0,spr6ptl
sp6l:	dc.w	0,spr7pth
sp7h:	dc.w	0,spr7ptl
sp7l:	dc.w	0


	dc.w	colour0,$000			; colours at top of screen
	dc.w	colour1,$fff
	dc.w	colour2,$ff0
	dc.w	colour3,$660

	dc.w	$3801,$ff00,colour0,$fff	; draw a little copper bar
	dc.w	$3901,$ff00,colour0,$666
	dc.w	$3a01,$ff00,colour0,$000

	dc.w	colour1,$000			; main screen's colours
	dc.w	colour2,$fff
	dc.w	colour3,$f00
	dc.w	colour4,$332
	dc.w	colour5,$fff
	dc.w	colour6,$fff
	dc.w	colour7,$fff

	dc.w	colour18,$04e			; pacman's colours
	dc.w	colour19,$ff4
	dc.w	colour20,$ff0
	dc.w	colour21,$ee0
	dc.w	colour22,$dd0
	dc.w	colour23,$cc0
	dc.w	colour24,$bb0
	dc.w	colour25,$aa0
	dc.w	colour26,$05f
	dc.w	colour27,$03d
	dc.w	colour28,$02c
	dc.w	colour29,$eee
	dc.w	colour30,$ddd
	dc.w	colour31,$ccc

	dc.w	$ffff,$fffe			; end of copper-list
	dc.w	$ffff,$fffe			; (should be done twice!)



************  read joystick  ************


read_joystick:
	move.w	$c(a5),d0			; read joy0dat

	btst	#9,d0
	beq.s	l
	move.w	#0,dir2				; set direction
l:
	btst	#1,d0
	beq.s	r
	move.w	#1,dir2				; set direction
r:
	move.w	d0,d1				; make copy of joy0dat
	and.w	#$3,d1				; and out unwanted bits
	cmp.w	#$2,d1
	beq.s	down
	cmp.w	#$1,d1
	bne.s	d
down:
	move.w	#2,dir2				; set direction
d:
	and.w	#$300,d0
	cmp.w	#$200,d0
	beq.s	up
	cmp.w	#$100,d0
	bne.s	u
up:
	move.w	#3,dir2				; set direction
u:
	rts



************  draw pacman  ************


draw_pacman:
	move.w	dir2,d2				; direction pac wants to go
	bsr	test_dir			; test if it's possible
	tst.b	d4				; test flag
	bne.s	dir2_blocked			; it's not possible!
	move.w	dir2,dir			; if it is then set real dir
	bra.s	draw_pacman2			; and draw pacman

dir2_blocked:
	move.w	dir,d2				; pac's direction
	bsr	test_dir			; test if path is blocked
	tst.b	d4				; test flag
	beq.s	draw_pacman2			; if zero then ok to draw
	rts					; else if set then skip


draw_pacman2:
	move.w	dir,d0				; get direction (0-3)
	lea	dir_tab,a0			; and direction table
	lsl	#2,d0				; times 4
	lea	(a0,d0),a0			; get start word
	move.w	(a0)+,dx			; set x speed
	move.w	(a0),dy				; and y speed

	move.w	dx,d0				; get x-speed
	move.w	dy,d1				; and y-speed
	add.w	d0,x				; add x-speed to x-coordinate
	add.w	d1,y				; add y-speed to y-coordinate

	move.l	#0,sprite1			; clear control words
	move.l	#0,sprite2			; and on second sprite

	move.w	x,d0				; our x-coordinate (word)
	move.w	y,d1				; and y-coordinate (word)

	add.w	#$80,d0				; $80 = left edge of screen
	add.w	#$2c,d1				; $2c = top edge of screen

	move.w	d1,d2				; don't touch original value
	move.b	d2,sprite1			; set y low 8 bits
	add.w	#$10,d2				; add height of sprite
	move.b	d2,sprite1+$2			; set 'last line' low 8 bits

	move.w	d0,d2				; work on copy of x-coord
	lsr	#1,d2				; shift right 1 bit
	move.b	d2,sprite1+$1			; set x high 8 bits

	move.w	d1,d2				; copy y-coord to 'd2'
	and.w	#$100,d2			; and out unwanted bits
	lsr	#6,d2				; shift right by 6 bits
	or.b	d2,sprite1+$3			; set y high bit

	add.w	#$10,d1				; add height of sprite
	and.w	#$100,d1			; and out unwanted bits
	lsr	#7,d1				; shift right by 7 bits
	or.b	d1,sprite1+$3			; set 'last line' high bit

	and.b	#$1,d0				; and out unwanted bits
	or.b	d0,sprite1+$3			; set x low bit

	move.l	sprite1,sprite2			; copy control words over
	or.b	#$80,sprite2+$3			; and set 'attach' bit
	rts



************  test direction  ************


test_dir:
	lea	screen,a0			; start of screen
	move.w	x,d0				; pacman's x-coordinate
	move.w	y,d1				; pacman's y-coordinate
	moveq.b	#0,d4				; collision flag

test_left:
	tst.w	d2				; is 'dir' zero?
	bne	test_right			; no - not going left

	subq.w	#1,d0				; test pixels to pac's left
	mulu	#40,d1				; y * 40 bytes per line
	lea	(a0,d1),a0			; start line
	move.w	d0,d1				; make copy of x-coord
	lsr	#3,d0				; divided by 8 = no. bytes
	lea	(a0,d0),a0			; point to start byte
	lsl	#3,d0				; times 8 again
	sub.w	d0,d1				; get number of pixel
	moveq.w	#7,d0				; take this from 7
	sub.w	d1,d0				; gives us bit number!

	btst	d0,(a0)				; test that bit
	bne.s	path_in_way_l			; if set then path in way
	btst	d0,40(a0)			; do this for all 16 lines
	bne.s	path_in_way_l
	btst	d0,40*2(a0)
	bne.s	path_in_way_l
	btst	d0,40*3(a0)
	bne.s	path_in_way_l
	btst	d0,40*4(a0)
	bne.s	path_in_way_l
	btst	d0,40*5(a0)
	bne.s	path_in_way_l
	btst	d0,40*6(a0)
	bne.s	path_in_way_l
	btst	d0,40*7(a0)
	bne.s	path_in_way_l
	btst	d0,40*8(a0)
	bne.s	path_in_way_l
	btst	d0,40*9(a0)
	bne.s	path_in_way_l
	btst	d0,40*10(a0)
	bne.s	path_in_way_l
	btst	d0,40*11(a0)
	bne.s	path_in_way_l
	btst	d0,40*12(a0)
	bne.s	path_in_way_l
	btst	d0,40*13(a0)
	bne.s	path_in_way_l
	btst	d0,40*14(a0)
	bne.s	path_in_way_l
	btst	d0,40*15(a0)
	bne.s	path_in_way_l
	rts					; all clear!
path_in_way_l:
	moveq.b	#1,d4				; set collision flag
	rts					; and return

test_right:
	cmp.w	#1,d2				; do same for right
	bne	test_down

	add.w	#16,d0
	mulu	#40,d1
	lea	(a0,d1),a0
	move.w	d0,d1
	lsr	#3,d0
	lea	(a0,d0),a0
	lsl	#3,d0
	sub.w	d0,d1
	moveq.w	#7,d0
	sub.w	d1,d0

	btst	d0,(a0)
	bne.s	path_in_way_r
	btst	d0,40(a0)
	bne.s	path_in_way_r
	btst	d0,40*2(a0)
	bne.s	path_in_way_r
	btst	d0,40*3(a0)
	bne.s	path_in_way_r
	btst	d0,40*4(a0)
	bne.s	path_in_way_r
	btst	d0,40*5(a0)
	bne.s	path_in_way_r
	btst	d0,40*6(a0)
	bne.s	path_in_way_r
	btst	d0,40*7(a0)
	bne.s	path_in_way_r
	btst	d0,40*8(a0)
	bne.s	path_in_way_r
	btst	d0,40*9(a0)
	bne.s	path_in_way_r
	btst	d0,40*10(a0)
	bne.s	path_in_way_r
	btst	d0,40*11(a0)
	bne.s	path_in_way_r
	btst	d0,40*12(a0)
	bne.s	path_in_way_r
	btst	d0,40*13(a0)
	bne.s	path_in_way_r
	btst	d0,40*14(a0)
	bne.s	path_in_way_r
	btst	d0,40*15(a0)
	bne.s	path_in_way_r
	rts
path_in_way_r:
	moveq.b	#1,d4
	rts

test_down:
	cmp.w	#2,d2
	bne.s	test_up

	add.w	#16,d1
	mulu	#40,d1
	lea	(a0,d1),a0
	move.w	d0,d1
	lsr	#3,d0
	lea	(a0,d0),a0
	lsl	#3,d0
	sub.w	d0,d1
	moveq.w	#7,d0
	sub.w	d1,d0

	move.w	#16-1,d3			; test 16 pixels below...
t_down_loop:
	btst	d0,(a0)				; test bit
	bne.s	path_in_way_d			; if set then that's it!
	tst.w	d0				; is bit no. zero?
	beq.s	overflow_d			; yes - need next byte
	subq.w	#1,d0				; else next bit in byte
	dbra	d3,t_down_loop			; and loop back
	rts
overflow_d:
	moveq.w	#7,d0				; start bit = 7
	lea	1(a0),a0			; point to next byte
	dbra	d3,t_down_loop			; and loop back
	rts

path_in_way_d:
	moveq.b	#1,d4
	rts

test_up:
	subq.w	#1,d1				; do same for up direction
	mulu	#40,d1
	lea	(a0,d1),a0
	move.w	d0,d1
	lsr	#3,d0
	lea	(a0,d0),a0
	lsl	#3,d0
	sub.w	d0,d1
	moveq.w	#7,d0
	sub.w	d1,d0

	move.w	#16-1,d3
t_up_loop:
	btst	d0,(a0)
	bne.s	path_in_way_u
	tst.w	d0
	beq.s	overflow_u
	subq.w	#1,d0
	dbra	d3,t_up_loop
	rts
overflow_u:
	moveq.w	#7,d0
	lea	1(a0),a0
	dbra	d3,t_up_loop
	rts

path_in_way_u:
	moveq.b	#1,d4
	rts



************  animate pacman  ************


animate_pacman:
	lea	pacman_gfx,a0			; start of pacman graphics
	lea	sprite1+$4,a1			; the gfx part of sprite1
	lea	sprite2+$4,a2			; the gfx part of sprite2

	move.w	dir,d0				; direction of pacman (0-3)


	mulu	#16*4*2*10,d0			; times length of gfx blocks
	lea	(a0,d0),a0			; start of gfx data

	addq.w	#1,pacman_anim			; pacman animation number
	cmp.w	#10,pacman_anim			; have we reached end?
	bne.s	pacman_anim_ok			; nope - we're ok!
	move.w	#0,pacman_anim			; else reset anim number
pacman_anim_ok:
	move.w	pacman_anim,d0			; get animation number
	mulu	#16*4*2,d0			; times length of gfx block
	lea	(a0,d0),a0			; this is the one!!!

	move.w	#16-1,d0			; pacman = 16 lines high
pac_loop1:
	move.l	(a0)+,(a1)+			; move in longword
	dbra	d0,pac_loop1			; Decrement and BRAnch

	move.w	#16-1,d0			; pacman = 16 lines high
pac_loop2:
	move.l	(a0)+,(a2)+			; move in longword
	dbra	d0,pac_loop2			; Decrement and BRAnch
	rts



************  draw lives  ************


draw_lives:
	lea	screen,a1			; where to draw lives
	move.w	lives,d0			; number of lives
	subq.w	#1,d0				; take one , for dbra
lives_loop:
	move.b	#$44,(a1)			; draw little pacman!
	move.b	#$80,40(a1)			; first bitplane
	move.b	#$00,40*2(a1)
	move.b	#$00,40*3(a1)
	move.b	#$00,40*4(a1)
	move.b	#$80,40*5(a1)
	move.b	#$44,40*6(a1)

	move.b	#$7c,40*256(a1)			; and second bitplane
	move.b	#$ec,40*256+40(a1)		; (to give 4 colours)
	move.b	#$f8,40*256+40*2(a1)
	move.b	#$f0,40*256+40*3(a1)
	move.b	#$f8,40*256+40*4(a1)
	move.b	#$fc,40*256+40*5(a1)
	move.b	#$7c,40*256+40*6(a1)

	lea	1(a1),a1			; next byte on screen
	dbra	d0,lives_loop			; and repeat...

	moveq.b	#0,d0				; put a zero in D0
	move.b	d0,(a1)				; and copy to screen
	move.b	d0,40(a1)			; this is quicker than
	move.b	d0,40*2(a1)			; 'move.b #0,(a1)' , etc.
	move.b	d0,40*3(a1)
	move.b	d0,40*4(a1)
	move.b	d0,40*5(a1)
	move.b	d0,40*6(a1)
	move.b	d0,40*7(a1)

	move.b	d0,40*256(a1)			; clear second bitplane too
	move.b	d0,40*256+40(a1)
	move.b	d0,40*256+40*2(a1)
	move.b	d0,40*256+40*3(a1)
	move.b	d0,40*256+40*4(a1)
	move.b	d0,40*256+40*5(a1)
	move.b	d0,40*256+40*6(a1)
	move.b	d0,40*256+40*7(a1)
	rts



************  print score  ************


print_score:
	move.w	score,d2			; get score (stored in word)

digit4:
	lea	numbers,a0			; start of numbers gfx data
	cmp.w	#1000,d2			; compare 1000 to score
	bge.s	do_1000				; score = 1000 or above
	lea	screen+18,a6			; else print '0'
	bsr	print				; print it
	bra.s	digit3				; and go onto next digit
do_1000:
	divu.w	#1000,d2			; divide score by 1000
	move.w	d2,d3				; save value
	clr	d2				; clear
	swap	d2				; swap words
	lea	(a0,d3),a0			; get number
	lea	screen+18,a6			; where to print
	bsr.s	print				; and print it

digit3:
	lea	numbers,a0
	cmp.w	#100,d2
	bge.s	do_100
	lea	screen+19,a6
	bsr.s	print
	bra.s	digit2
do_100:
	divu.w	#100,d2
	move.w	d2,d3
	clr	d2
	swap	d2
	lea	(a0,d3),a0
	lea	screen+19,a6
	bsr.s	print

digit2:
	lea	numbers,a0
	cmp.w	#10,d2
	bge.s	do_10
	lea	screen+20,a6
	bsr.s	print
	bra.s	digit1
do_10:
	divu.w	#10,d2
	move.w	d2,d3
	clr	d2
	swap	d2
	lea	(a0,d3),a0
	lea	screen+20,a6
	bsr.s	print

digit1:
	lea	numbers,a0
	cmp.w	#1,d2
	bge.s	do_1
	lea	screen+21,a6
	bsr.s	print
	bra.s	numbers_done
do_1:
	lea	(a0,d2),a0
	lea	screen+21,a6
	bsr.s	print
numbers_done:
	rts


print:
	move.b	(a0),(a6)
	move.b	10(a0),40(a6)
	move.b	10*2(a0),40*2(a6)
	move.b	10*3(a0),40*3(a6)
	move.b	10*4(a0),40*4(a6)
	move.b	10*5(a0),40*5(a6)
	move.b	10*6(a0),40*6(a6)
	move.b	10*7(a0),40*7(a6)
	rts



************  are you ready?  ************


ready:
	lea	screen+(40*110)+12,a0
	lea	gfx_buffer,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#24,$64(a5)			; A channel modulo
	move.w	#0,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	40*256(a0),a0			; next bitplane on screen
	lea	16*26(a1),a1			; next bitplane in buffer

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#24,$64(a5)			; A channel modulo
	move.w	#0,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!


	lea	ready_gfx,a0
	lea	screen+(40*110)+12,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	40*256(a1),a1			; draw on next bitplane too!

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!


ready_wait:
	move.b	vhposr(a5),d0			; get scanline
	cmp.b	#$ff,d0				; reached line $ff?
	bne.s	ready_wait			; not yet

	bsr	animate_pacman			; animate pacman sprite

	move.b	$bfe001,d0			; read hardware register
	btst	#7,d0				; fire-button = bit 7
	bne.s	ready_wait			; not pressed - wait again!

	lea	gfx_buffer,a0
	lea	screen+(40*110)+12,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	16*26(a0),a0
	lea	40*256(a1),a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!
	rts



************  pause game  ************


pause_game:
	lea	screen+(40*110)+12,a0
	lea	gfx_buffer,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#24,$64(a5)			; A channel modulo
	move.w	#0,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	40*256(a0),a0
	lea	16*26(a1),a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#24,$64(a5)			; A channel modulo
	move.w	#0,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!


	lea	pause_gfx,a0
	lea	screen+(40*110)+12,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	40*256(a1),a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!


ps_wait:
	move.b	$bfec01,d0			; read keyboard
	eor.b	#$ff,d0
	ror.b	#1,d0

	cmp.b	#$19,d0				; is 'p' still pressed?
	beq.s	ps_wait				; wait till it's released

ps_wait2:
	move.b	$bfec01,d0
	eor.b	#$ff,d0
	ror.b	#1,d0

	cmp.b	#$19,d0				; is 'p' pressed?
	bne.s	ps_wait2			; wait till it is again

ps_wait3:
	move.b	$bfec01,d0
	eor.b	#$ff,d0
	ror.b	#1,d0

	cmp.b	#$19,d0				; is 'p' still pressed?
	beq.s	ps_wait3			; wait till it's not!!!


	lea	gfx_buffer,a0
	lea	screen+(40*110)+12,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	16*26(a0),a0
	lea	40*256(a1),a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!
	rts



************  game over  ************


game_over:
	lea	screen+(40*110)+12,a0
	lea	gfx_buffer,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#24,$64(a5)			; A channel modulo
	move.w	#0,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	40*256(a0),a0
	lea	16*26(a1),a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#24,$64(a5)			; A channel modulo
	move.w	#0,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!


	lea	game_over_gfx,a0
	lea	screen+(40*110)+12,a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	40*256(a1),a1

	bsr	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!


game_over_wait:
	move.b	vhposr(a5),d0			; get scanline
	cmp.b	#$ff,d0				; reached line $ff?
	bne.s	game_over_wait			; not yet

	bsr	animate_pacman			; animate pacman sprite

	move.b	$bfe001,d0			; read hardware register
	btst	#7,d0				; fire-button = bit 7
	bne.s	game_over_wait			; not pressed - wait again!


	lea	gfx_buffer,a0
	lea	screen+(40*110)+12,a1

	bsr.s	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!

	lea	16*26(a0),a0
	lea	40*256(a1),a1

	bsr.s	blitter_wait			; wait for blitter

	move.l	a0,$50(a5)			; A channel = source
	move.l	a1,$54(a5)			; D channel = destination
	move.w	#0,$64(a5)			; A channel modulo
	move.w	#24,$66(a5)			; D channel modulo
	move.w	#$09f0,$40(a5)			; function = straight copy
	move.w	#0,$42(a5)			; second control word
	move.l	#$ffffffff,$44(a5)		; first & last word masks
	move.w	#8+64*26,$58(a5)		; size of blit & start!
	rts



************  wait for blitter  ************


blitter_wait:
	btst	#14,$2(a5)			; is blitter ready?
	bne.s	blitter_wait			; not yet!
	rts



************  data  ************


gfx_lib:	dc.b	'graphics.library',0
		even
gfx_base:	dc.l	0


x:	dc.w	0			; x-coordinate of pacman
y:	dc.w	0			; y-coordinate of pacman
dx:	dc.w	0			; x-speed of pacman
dy:	dc.w	0			; y-speed of pacman
dir:	dc.w	0			; direction of pacman
dir2:	dc.w	0			; direction pacman wants to go in

pacman_anim:	dc.w	0		; pacman animation number

lives:	dc.w	0			; player's number of lives
score:	dc.w	0			; player's score


dir_tab:
	dc.w	-2,0,2,0,0,2,0,-2	; pac's direction table

ready_gfx:	incbin	text1.raw
game_over_gfx:	incbin	text2.raw
pause_gfx:	incbin	text3.raw
gfx_buffer:	ds.b	16*26*2		; buffer so we can save what's
					; under where we're drawing

numbers:	incbin	numbers.raw	; numbers graphics (for score)

sprite1:	ds.l	18		; control longword + 16 lines
					; + zero longword
sprite2:	ds.l	18

	include	pacman.spr_gfx.s	; pacman graphics (source)

screen:	incbin	pac_screen.raw



************  equates  ************


** exec library offsets

forbid		equ	-132
permit		equ	-138
openlib		equ	-552
closelib	equ	-414
allocmem	equ	-198
freemem		equ	-210


** register offsets

bplcon0		equ	$100
bplcon1		equ	$102
bplcon2		equ	$104
bpl1mod		equ	$108
bpl2mod		equ	$10a
bpl1pth		equ	$e0
bpl1ptl		equ	$e2
bpl2pth		equ	$e4
bpl2ptl		equ	$e6
bpl3pth		equ	$e8
bpl3ptl		equ	$ea

diwstrt		equ	$8e
diwstop		equ	$90
ddfstrt		equ	$92
ddfstop		equ	$94

dmacon		equ	$96
vhposr		equ	$6
spr0pth		equ	$120
spr0ptl		equ	$122
spr1pth		equ	$124
spr1ptl		equ	$126
spr2pth		equ	$128
spr2ptl		equ	$12a
spr3pth		equ	$12c
spr3ptl		equ	$12e
spr4pth		equ	$130
spr4ptl		equ	$132
spr5pth		equ	$134
spr5ptl		equ	$136
spr6pth		equ	$138
spr6ptl		equ	$13a
spr7pth		equ	$13c
spr7ptl		equ	$13e

colour0		equ	$180
colour1		equ	$182
colour2		equ	$184
colour3		equ	$186
colour4		equ	$188
colour5		equ	$18a
colour6		equ	$18c
colour7		equ	$18e
colour8		equ	$190
colour9		equ	$192
colour10	equ	$194
colour11	equ	$196
colour12	equ	$198
colour13	equ	$19a
colour14	equ	$19c
colour15	equ	$19e
colour16	equ	$1a0
colour17	equ	$1a2
colour18	equ	$1a4
colour19	equ	$1a6
colour20	equ	$1a8
colour21	equ	$1aa
colour22	equ	$1ac
colour23	equ	$1ae
colour24	equ	$1b0
colour25	equ	$1b2
colour26	equ	$1b4
colour27	equ	$1b6
colour28	equ	$1b8
colour29	equ	$1ba
colour30	equ	$1bc
colour31	equ	$1be

	end
