1024 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1024 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
_runtimePath_ "../../runtime"
 | 
						|
_runtimeStart_ &h7FFF
 | 
						|
_arraysStart_ &h7FFF
 | 
						|
_codeRomType_ ROMv3
 | 
						|
 | 
						|
'size of your most complex expression, (temporary variables required)*2, defaults to 8
 | 
						|
_tempVarSize_ 6
 | 
						|
 | 
						|
'free string work area, (better not use any of the string runtime!)
 | 
						|
free STRINGWORKAREA
 | 
						|
 | 
						|
'free scanline 0, 1, 118 and 119 for code and data
 | 
						|
free &h0800, 160
 | 
						|
free &h0900, 160
 | 
						|
free &h7E00, 160
 | 
						|
free &h7F00, 160
 | 
						|
 | 
						|
'use this after _runtimeStart_ to specify maximum number of sprites if you have more than 48
 | 
						|
_maxNumSprites_ 76
 | 
						|
 | 
						|
'defines the amount of contiguous RAM needed for sprite stripes, (in this case 15*6 + 1), also min address and search direction
 | 
						|
_spriteStripeChunks_ 15, &h3BA0, descending
 | 
						|
 | 
						|
'normally sprites must be horizontally divisible by 6, but by specifying an overlap value the last column
 | 
						|
'of a sprite can be pushed closer to the rest of the sprite, (works with flipped sprites as well)
 | 
						|
const SPRITE_OVERLAP = 3 '12x9 sprites displayed as 9x9
 | 
						|
 | 
						|
const BlinkyUp = 0
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_u0.tga, BlinkyUp + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_u1.tga, BlinkyUp + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const BlinkyDn = 2
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_d0.tga, BlinkyDn + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_d1.tga, BlinkyDn + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const BlinkyLt = 4
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_l0.tga, BlinkyLt + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_l1.tga, BlinkyLt + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const BlinkyRt = 6 'instance and hardware flip, (native code), in the X direction to save memory
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_l0.tga, BlinkyRt + 0, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Blinky_l1.tga, BlinkyRt + 1, FlipX, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PinkyUp = 8
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_u0.tga, PinkyUp + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_u1.tga, PinkyUp + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PinkyDn = 10
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_d0.tga, PinkyDn + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_d1.tga, PinkyDn + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PinkyLt = 12
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_l0.tga, PinkyLt + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_l1.tga, PinkyLt + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PinkyRt = 14 'instance and hardware flip, (native code), in the X direction to save memory
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_l0.tga, PinkyRt + 0, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Pinky_l1.tga, PinkyRt + 1, FlipX, SPRITE_OVERLAP
 | 
						|
 | 
						|
const InkyUp = 16
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_u0.tga, InkyUp + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_u1.tga, InkyUp + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const InkyDn = 18
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_d0.tga, InkyDn + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_d1.tga, InkyDn + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const InkyLt = 20
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_l0.tga, InkyLt + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_l1.tga, InkyLt + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const InkyRt = 22 'instance and hardware flip, (native code), in the X direction to save memory
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_l0.tga, InkyRt + 0, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Inky_l1.tga, InkyRt + 1, FlipX, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ClydeUp = 24
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_u0.tga, ClydeUp + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_u1.tga, ClydeUp + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ClydeDn = 26
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_d0.tga, ClydeDn + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_d1.tga, ClydeDn + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ClydeLt = 28
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_l0.tga, ClydeLt + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_l1.tga, ClydeLt + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ClydeRt = 30 'instance and hardware flip, (native code), in the X direction to save memory
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_l0.tga, ClydeRt + 0, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Clyde_l1.tga, ClydeRt + 1, FlipX, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PucUp = 32
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u0.tga, PucUp + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u1.tga, PucUp + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u2.tga, PucUp + 2, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u3.tga, PucUp + 3, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PucDn = 36 'instance and hardware flip, (native code), in the Y direction to save memory
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u0.tga, PucDn + 0, FlipY, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u1.tga, PucDn + 1, FlipY, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u2.tga, PucDn + 2, FlipY, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_u3.tga, PucDn + 3, FlipY, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PucLt = 40
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l0.tga, PucLt + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l1.tga, PucLt + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l2.tga, PucLt + 2, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l3.tga, PucLt + 3, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const PucRt = 44 'instance and hardware flip, (native code), in the X direction to save memory
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l0.tga, PucRt + 0, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l1.tga, PucRt + 1, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l2.tga, PucRt + 2, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Puc_l3.tga, PucRt + 3, FlipX, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ScaredUp = 48
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_u0.tga, ScaredUp + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_u1.tga, ScaredUp + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ScaredDn = 50
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_d0.tga, ScaredDn + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_d1.tga, ScaredDn + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ScaredLt = 52
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_u0.tga, ScaredLt + 0, NoFlip, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_u1.tga, ScaredLt + 1, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const ScaredRt = 54
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_u0.tga, ScaredRt + 0, FlipX, SPRITE_OVERLAP
 | 
						|
load sprite, ../../../res/image/PucMon/Scared_u1.tga, ScaredRt + 1, FlipX, SPRITE_OVERLAP
 | 
						|
 | 
						|
const EyesUp = 56
 | 
						|
load sprite, ../../../res/image/PucMon/Eyes_d.tga, EyesUp, FlipY, 0
 | 
						|
 | 
						|
const EyesDn = 57
 | 
						|
load sprite, ../../../res/image/PucMon/Eyes_d.tga, EyesDn, NoFlip, 0
 | 
						|
 | 
						|
const EyesLt = 58
 | 
						|
load sprite, ../../../res/image/PucMon/Eyes_l.tga, EyesLt, NoFlip, 0
 | 
						|
 | 
						|
const EyesRt = 59
 | 
						|
load sprite, ../../../res/image/PucMon/Eyes_l.tga, EyesRt, FlipX, 0
 | 
						|
 | 
						|
const Tunnel = 60
 | 
						|
load sprite, ../../../res/image/PucMon/Black12x9.tga, Tunnel, NoFlip, 0
 | 
						|
 | 
						|
const Pill = 61
 | 
						|
const Erase6x6 = Pill + 1
 | 
						|
load sprite, ../../../res/image/PucMon/Pill.tga,     Pill + 0, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Black6x6.tga, Pill + 1, NoFlip, 0
 | 
						|
 | 
						|
const Erase12x9 = 63
 | 
						|
load sprite, ../../../res/image/PucMon/Black12x9.tga, Erase12x9, NoFlip, SPRITE_OVERLAP
 | 
						|
 | 
						|
const Life = 64
 | 
						|
load sprite, ../../../res/image/PucMon/Life.tga, Life, NoFlip, 0
 | 
						|
 | 
						|
const Level = 65
 | 
						|
load sprite, ../../../res/image/PucMon/Level.tga, Level, NoFlip, 0
 | 
						|
 | 
						|
const Digit = 66
 | 
						|
load sprite, ../../../res/image/PucMon/Zero.tga,  Digit + 0, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/One.tga,   Digit + 1, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Two.tga,   Digit + 2, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Three.tga, Digit + 3, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Four.tga,  Digit + 4, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Five.tga,  Digit + 5, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Six.tga,   Digit + 6, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Seven.tga, Digit + 7, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Eight.tga, Digit + 8, NoFlip, 0
 | 
						|
load sprite, ../../../res/image/PucMon/Nine.tga,  Digit + 9, NoFlip, 0
 | 
						|
 | 
						|
dim maze%(23, 27) = {&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&h01,&h01,&h01,&h01,&h01,&hD1,&h01,&h01,&h01,&h01,&h01,&h01,&hF0,&hF0,&h01,&h01,&h01,&h01,&h01,&h01,&hD1,&h01,&h01,&h01,&h01,&h01,&hF0,
 | 
						|
                     &hF0,&h02,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h02,&hF0,
 | 
						|
                     &hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,
 | 
						|
                     &hF0,&hD1,&h01,&h01,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&h01,&h01,&hD1,&hF0,
 | 
						|
                     &hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,
 | 
						|
                     &hF0,&h01,&h01,&h01,&h01,&h01,&hD1,&hF0,&hF0,&h01,&h01,&h01,&h01,&hF0,&hF0,&h01,&h01,&h01,&h01,&hF0,&hF0,&hD1,&h01,&h01,&h01,&h01,&h01,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h00,&hF0,&hF0,&h00,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h00,&h00,&h00,&hD0,&hB0,&h00,&hD0,&h00,&h00,&h00,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h00,&hF0,&hF0,&hF0,&hE0,&hE0,&hF0,&hF0,&hF0,&h00,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h00,&hF0,&h00,&h00,&hC0,&h00,&h00,&h00,&hF0,&h00,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hA0,&h90,&h90,&h90,&h90,&h00,&hD1,&h00,&h00,&hD0,&hF0,&h00,&h00,&h00,&h00,&h00,&h00,&hF0,&hD0,&h00,&h00,&hD1,&h00,&h90,&h90,&h90,&h90,&hA0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h00,&hF0,&h00,&h00,&h00,&h00,&h00,&h00,&hF0,&h00,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h00,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h00,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hD0,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&hD0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h00,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h00,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&h01,&h01,&h01,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&h01,&hF0,&hF0,&h01,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&h01,&h01,&h01,&hF0,
 | 
						|
                     &hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,
 | 
						|
                     &hF0,&h02,&h01,&h01,&hF0,&hF0,&hD1,&h01,&h01,&hD1,&h01,&h01,&hD1,&h00,&h00,&hD1,&h01,&h01,&hD1,&h01,&h01,&hD1,&hF0,&hF0,&h01,&h01,&h02,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,
 | 
						|
                     &hF0,&h01,&h01,&hD1,&h01,&h01,&h01,&hF0,&hF0,&h01,&h01,&h01,&h01,&hF0,&hF0,&h01,&h01,&h01,&h01,&hF0,&hF0,&h01,&h01,&h01,&hD1,&h01,&h01,&hF0,
 | 
						|
                     &hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,&hF0,&h01,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&h01,&hF0,
 | 
						|
                     &hF0,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&hD1,&h01,&h01,&hD1,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&h01,&hF0,
 | 
						|
                     &hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0,&hF0}
 | 
						|
 | 
						|
const MUSIC_INTRO = &h31A0
 | 
						|
def byte(&h31a0) =  &h90, &h47, &h91, &h23, &h04, &h80, &h04, &h90, &h53, &h81, &h05, &h80, &h04, &h90, &h4e, &h04,
 | 
						|
def byte         =  &h80, &h04, &h90, &h4b, &h91, &h2f, &h05, &h80, &h04, &h90, &h53, &h91, &h23, &h04, &h90, &h4e,
 | 
						|
def byte         =  &h04, &h80, &h81, &h09, &h90, &h4b, &h08, &h91, &h2f, &h05, &h80, &h04, &h90, &h48, &h91, &h24,
 | 
						|
def byte         =  &h04, &h80, &h04, &h90, &h54, &h81, &h05, &h80, &h04, &h90, &h4f, &h04, &h80, &h04, &h90, &h4c,
 | 
						|
def byte         =  &h91, &h30, &h05, &h80, &h04, &h90, &h54, &h91, &h24, &h04, &h90, &h4f, &h04, &h80, &h81, &h09,
 | 
						|
def byte         =  &h90, &h4c, &h08, &h91, &h30, &h05, &h80, &h04, &h90, &h47, &h91, &h23, &h04, &hd0, &ha0, &h32,
 | 
						|
 | 
						|
def byte(&h32a0) =  &h80, &h04, &h90, &h53, &h81, &h05, &h80, &h04, &h90, &h4e, &h04, &h80, &h04, &h90, &h4b, &h91,
 | 
						|
def byte         =  &h2f, &h05, &h80, &h04, &h90, &h53, &h91, &h23, &h04, &h90, &h4e, &h04, &h80, &h81, &h09, &h90,
 | 
						|
def byte         =  &h4b, &h08, &h91, &h2f, &h04, &h80, &h05, &h90, &h4b, &h91, &h2a, &h04, &h90, &h4c, &h04, &h90,
 | 
						|
def byte         =  &h4d, &h81, &h04, &h80, &h05, &h90, &h4d, &h91, &h2c, &h04, &h90, &h4e, &h04, &h90, &h4f, &h81,
 | 
						|
def byte         =  &h04, &h80, &h05, &h90, &h4f, &h91, &h2e, &h04, &h90, &h50, &h04, &h90, &h51, &h81, &h04, &h80,
 | 
						|
def byte         =  &h05, &h90, &h53, &h91, &h2f, &h08, &h80, &h81, &hd0, &h00, &h00,
 | 
						|
 | 
						|
const ORIGIN_X = 2
 | 
						|
const ORIGIN_Y = 2
 | 
						|
const SCORE_X = 112
 | 
						|
const SCORE_Y = 65
 | 
						|
const LEVEL_X = 137
 | 
						|
const LEVEL_Y = 53
 | 
						|
const HIGH_X = 112
 | 
						|
const HIGH_Y = 40
 | 
						|
const LIFE_X = 137
 | 
						|
const LIFE_Y = 109
 | 
						|
 | 
						|
const PILL_LT = @maze( 2,  1)
 | 
						|
const PILL_RT = @maze( 2, 26)
 | 
						|
const PILL_LB = @maze(18,  1)
 | 
						|
const PILL_RB = @maze(18, 26)
 | 
						|
 | 
						|
const WALL   = &hF0
 | 
						|
const DOOR   = &hE0
 | 
						|
const JUNC   = &hD0
 | 
						|
const EXIT   = &hC0
 | 
						|
const ENTER  = &hB0
 | 
						|
const TUNNEL = &hA0
 | 
						|
const SLOW   = &h90
 | 
						|
const RPILL  = &h04
 | 
						|
const RDOT   = &h03
 | 
						|
const PILL   = &h02
 | 
						|
const DOT    = &h01
 | 
						|
 | 
						|
 | 
						|
dim MAZE_BORDER(6)   = 0, 115, 255
 | 
						|
dim MAZE_OUTER_T(14) = 25, 0, 0, -15, -25, 0, 0, -35, 65, 0, 0, 15, 2, 0, 255
 | 
						|
dim MAZE_OUTER_B(16) = -68, 0, 0, -20, 9, 0, -9, 0, 0, -20, 25, 0, 0, -15, -25, 0, 255
 | 
						|
dim MAZE_TJUNC_0(10) = 25, 0, 0, -10, 5, 0, 0, 10, 15, 0, 255
 | 
						|
dim MAZE_TJUNC_1(6)  = -2, 0, 0, -10, -15, 0, 255
 | 
						|
dim MAZE_CAGE(6)     = -10, 0, 0, 20, 17, 0, 255
 | 
						|
dim MAZE_VERT_0(8)   = 0, 15, -5, 0, 0, -15, 5, 0, 255
 | 
						|
dim MAZE_VERT_1(8)   = 5, 0, 0, 25, -5, 0, 0, -25, 255
 | 
						|
dim MAZE_CORNER(8)   = 10, 0, 0, 10, 5, 0, 0, -10, 255
 | 
						|
dim MAZE_HORIZ_0(8)  = 15, 0, 0, 5, -15, 0, 0, -5, 255
 | 
						|
dim MAZE_HORIZ_1(8)  = 20, 0, 0, 5, -20, 0, 0, -5, 255
 | 
						|
dim MAZE_LINE_0(2)   = 15, 0, 255
 | 
						|
dim MAZE_LINE_1(2)   = 20, 0, 255
 | 
						|
 | 
						|
'LUT containing maze piece locations
 | 
						|
const NUM_MAZE_PIECES = 36
 | 
						|
dim MAZE_PIECES(NUM_MAZE_PIECES - 1) = 0+2*256, 1+2*256, 2+2*256, 157+2*256, 158+2*256, 159+2*256, ORIGIN_X+((50+ORIGIN_Y)*256), (135+ORIGIN_X)+((50+ORIGIN_Y)*256), (68+ORIGIN_X)+((115+ORIGIN_Y)*256), (67+ORIGIN_X)+((115+ORIGIN_Y)*256), (10+ORIGIN_X)+((105+ORIGIN_Y)*256), (125+ORIGIN_X)+((105+ORIGIN_Y)*256), (67+ORIGIN_X)+((105+ORIGIN_Y)*256), (68+ORIGIN_X)+((105+ORIGIN_Y)*256), (67+ORIGIN_X)+((85+ORIGIN_Y)*256), (68+ORIGIN_X)+((85+ORIGIN_Y)*256), (67+ORIGIN_X)+((35+ORIGIN_Y)*256), (68+ORIGIN_X)+((35+ORIGIN_Y)*256), (60+ORIGIN_X)+((45+ORIGIN_Y)*256), (75+ORIGIN_X)+((45+ORIGIN_Y)*256), (40+ORIGIN_X)+((60+ORIGIN_Y)*256), (95+ORIGIN_X)+((60+ORIGIN_Y)*256), (35+ORIGIN_X)+((25+ORIGIN_Y)*256), (100+ORIGIN_X)+((25+ORIGIN_Y)*256), (10+ORIGIN_X)+((85+ORIGIN_Y)*256), (125+ORIGIN_X)+((85+ORIGIN_Y)*256), (10+ORIGIN_X)+((10+ORIGIN_Y)*256), (125+ORIGIN_X)+((10+ORIGIN_Y)*256), (35+ORIGIN_X)+((10+ORIGIN_Y)*256), (100+ORIGIN_X)+((10+ORIGIN_Y)*256), (40+ORIGIN_X)+((35+ORIGIN_Y)*256), (95+ORIGIN_X)+((35+ORIGIN_Y)*256), (35+ORIGIN_X)+((85+ORIGIN_Y)*256), (100+ORIGIN_X)+((85+ORIGIN_Y)*256), (10+ORIGIN_X)+((25+ORIGIN_Y)*256), (125+ORIGIN_X)+((25+ORIGIN_Y)*256), 
 | 
						|
 | 
						|
'LUT containing maze piece addresses
 | 
						|
dim MAZE_ADDRS(NUM_MAZE_PIECES - 1) = @MAZE_BORDER, @MAZE_BORDER, @MAZE_BORDER, @MAZE_BORDER, @MAZE_BORDER, @MAZE_BORDER, @MAZE_OUTER_T, @MAZE_OUTER_T, @MAZE_OUTER_B, @MAZE_OUTER_B, @MAZE_TJUNC_0, @MAZE_TJUNC_0, @MAZE_TJUNC_1, @MAZE_TJUNC_1, @MAZE_TJUNC_1, @MAZE_TJUNC_1, @MAZE_TJUNC_1, @MAZE_TJUNC_1, @MAZE_CAGE, @MAZE_CAGE, @MAZE_VERT_0, @MAZE_VERT_0, @MAZE_VERT_1, @MAZE_VERT_1, @MAZE_CORNER, @MAZE_CORNER, @MAZE_HORIZ_0, @MAZE_HORIZ_0, @MAZE_HORIZ_1, @MAZE_HORIZ_1, @MAZE_LINE_0, @MAZE_LINE_0, @MAZE_LINE_1, @MAZE_LINE_1, @MAZE_LINE_0, @MAZE_LINE_0,
 | 
						|
 | 
						|
'LUT containing ghost directions
 | 
						|
dim GHOST_DIRS(7) = 1, 0, 0, 1, -1, 0, 0, -1
 | 
						|
 | 
						|
const NUM_GHOSTS   = 4
 | 
						|
const CHASE_MODE   = 0
 | 
						|
const SCARED_MODE  = 1
 | 
						|
const SCATTER_MODE = 2
 | 
						|
 | 
						|
'LUT containing ghost sprite frames
 | 
						|
dim gframes%(NUM_GHOSTS*4 - 1) = BlinkyRt, BlinkyLt, BlinkyDn, BlinkyUp, PinkyRt, PinkyLt, PinkyDn, PinkyUp, InkyRt, InkyLt, InkyDn, InkyUp, ClydeRt, ClydeLt, ClydeDn, ClydeUp
 | 
						|
 | 
						|
dim ghostsXr(NUM_GHOSTS)    = (64+ORIGIN_X), (52+ORIGIN_X), (52+ORIGIN_X), (76+ORIGIN_X), (76+ORIGIN_X)
 | 
						|
dim ghostsYr(NUM_GHOSTS)    = (36+ORIGIN_Y), (46+ORIGIN_Y), (56+ORIGIN_Y), (46+ORIGIN_Y), (56+ORIGIN_Y)
 | 
						|
dim ghostsX(NUM_GHOSTS - 1) = (64+ORIGIN_X), (52+ORIGIN_X), (52+ORIGIN_X), (76+ORIGIN_X)
 | 
						|
dim ghostsY(NUM_GHOSTS - 1) = (36+ORIGIN_Y), (46+ORIGIN_Y), (56+ORIGIN_Y), (46+ORIGIN_Y)
 | 
						|
dim ghostsXd(NUM_GHOSTS - 1) = -1, -1, -1, -1
 | 
						|
dim ghostsYd(NUM_GHOSTS - 1) = 0, 0, 0, 0
 | 
						|
dim ghostsFlags%(NUM_GHOSTS - 1) = 0, 0, 0, 0
 | 
						|
 | 
						|
const SCORE_LEN = 7
 | 
						|
dim highBCD%(SCORE_LEN - 1) = 0
 | 
						|
dim scoreBCD%(SCORE_LEN - 1) = 0
 | 
						|
dim pointsBCD%(SCORE_LEN - 1) = 0
 | 
						|
 | 
						|
const LEVEL_LEN = 2
 | 
						|
dim levelBCD%(LEVEL_LEN - 1) = 0
 | 
						|
 | 
						|
'livesDots <8:lives><8:dots>
 | 
						|
'levelPain <8:level><8:pain>
 | 
						|
'timeTicks <8:time><8:ticks>
 | 
						|
'flags <8:puc flags><8:ghost flags>, puc flags XXXXXXXD, ghost flags XXXXXXSD : where S = slowed, D = dead
 | 
						|
 | 
						|
'define vars without intitialisation, (initialised in initVars)
 | 
						|
def livesDots, levelPain, timeTicks, flags, gmode, gx, gy, gxd, gyd, mz, pyd, oxd, oyd, puci, pucj, ti, tj, px, py, pxd, bonus
 | 
						|
 | 
						|
gosub initSystem
 | 
						|
'gosub drawGrid
 | 
						|
'gosub drawCells
 | 
						|
gosub drawMaze
 | 
						|
    
 | 
						|
reset:
 | 
						|
    gosub resetLevel
 | 
						|
    
 | 
						|
start:
 | 
						|
    gosub startLevel
 | 
						|
    
 | 
						|
init:
 | 
						|
    call initVars
 | 
						|
 | 
						|
repeat
 | 
						|
    wait
 | 
						|
 | 
						|
    'change sprite priority based on who is agressor
 | 
						|
    if gmode &&= SCARED_MODE
 | 
						|
        gosub drawGhosts
 | 
						|
        gosub drawPucMon
 | 
						|
    else
 | 
						|
        gosub drawPucMon
 | 
						|
        gosub drawGhosts
 | 
						|
    endif
 | 
						|
 | 
						|
    'level complete
 | 
						|
    if livesDots.lo &&= 0
 | 
						|
        if levelPain.lo &&= 99 then poke &h0101, &h40  'level100 easter egg, good luck once you get to level 100!
 | 
						|
        inc levelPain.lo
 | 
						|
        inc levelPain.hi
 | 
						|
        goto start
 | 
						|
    endif
 | 
						|
 | 
						|
    'puc died
 | 
						|
    if flags.hi &&= 1
 | 
						|
        flags.hi = 0
 | 
						|
        livesDots.hi = livesDots.hi - 1
 | 
						|
        call drawDots, 0 'refresh
 | 
						|
        gosub drawDeath
 | 
						|
        if livesDots.hi &&= 0
 | 
						|
            goto reset
 | 
						|
        endif
 | 
						|
        goto init
 | 
						|
    endif
 | 
						|
 | 
						|
    'tunnels
 | 
						|
    sprite NoFlip, Tunnel, (1+ORIGIN_X),   (51+ORIGIN_Y)
 | 
						|
    sprite NoFlip, Tunnel, (123+ORIGIN_X), (51+ORIGIN_Y)
 | 
						|
    
 | 
						|
    gosub drawPills
 | 
						|
    
 | 
						|
    gosub setGhostsMode
 | 
						|
    gosub moveGhosts
 | 
						|
 | 
						|
    gosub handleInput
 | 
						|
    gosub movePucMon
 | 
						|
    
 | 
						|
    inc timeTicks.lo
 | 
						|
forever
 | 
						|
 | 
						|
'fast modulus by 5 for mx and my, only works for the domain 0<->20734
 | 
						|
'this sub need to be fast, so place it early in the source file so that it will most likely
 | 
						|
'be placed in a large RAM page and thus not require page jumps and allow us to use full BRA optimisations
 | 
						|
'there is no contiguous memory left on a 32K system for 160byte and 120byte LUTs
 | 
						|
mod5:
 | 
						|
    mx = mx.hi + mx.lo : mx = (mx LSR 4) + (mx AND &h000F)
 | 
						|
    if mx &&> 14
 | 
						|
        mx = mx - 15
 | 
						|
    elseif mx &&> 9
 | 
						|
        mx = mx - 10
 | 
						|
    elseif mx &&> 4
 | 
						|
        mx = mx - 5
 | 
						|
    endif
 | 
						|
    
 | 
						|
    my = my.hi + my.lo : my = (my LSR 4) + (my AND &h000F)
 | 
						|
    if my &&> 14
 | 
						|
        my = my - 15
 | 
						|
    elseif my &&> 9
 | 
						|
        my = my - 10
 | 
						|
    elseif my &&> 4
 | 
						|
        my = my - 5 
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
'fast divide by 5 for ci and cj, only works for the domain 0<->319
 | 
						|
'this sub need to be fast, so place it early in the source file so that it will most likely
 | 
						|
'be placed in a large RAM page and thus not require page jumps
 | 
						|
'there is no contiguous memory left on a 32K system for 160byte and 120byte LUTs
 | 
						|
proc div5
 | 
						|
    local i, j
 | 
						|
    
 | 
						|
    ci = ci - (ci LSR 6)                             'error term
 | 
						|
    i  = ci LSL 4 : ci = (i LSL 1) + i + (ci LSL 2)  'multiply by 52
 | 
						|
    ci = ci.hi                                       'divide by 256
 | 
						|
 | 
						|
    cj = cj - (cj LSR 6)                             'error term
 | 
						|
    j  = cj LSL 4 : cj = (j LSL 1) + j + (cj LSL 2)  'multiply by 52
 | 
						|
    cj = cj.hi                                       'divide by 256
 | 
						|
endproc
 | 
						|
 | 
						|
drawPucMon:
 | 
						|
    if mz &= WALL
 | 
						|
        sprite NoFlip, PucLt + 2, px, py
 | 
						|
        return
 | 
						|
    endif
 | 
						|
    
 | 
						|
    xf = (px LSR 1) AND 3
 | 
						|
    yf = (py LSR 1) AND 3
 | 
						|
    if pxd &&= 1
 | 
						|
        sprite FlipX, PucRt + xf, px, py
 | 
						|
    elseif pxd &&= -1
 | 
						|
        sprite NoFlip, PucLt + xf, px, py
 | 
						|
    elseif pyd &&= 1
 | 
						|
        sprite FlipY, PucDn + yf, px, py
 | 
						|
    else
 | 
						|
        sprite NoFlip, PucUp + yf, px, py
 | 
						|
    endif
 | 
						|
    px = px + pxd
 | 
						|
    py = py + pyd
 | 
						|
return
 | 
						|
 | 
						|
drawGhosts:
 | 
						|
    for gidx=0 to NUM_GHOSTS-1
 | 
						|
        gosub getGhostVars
 | 
						|
 | 
						|
        'if puc died or level is complete, then erase ghost
 | 
						|
        if &((flags.hi) OR (livesDots.lo = 0))
 | 
						|
            sprite NoFlip, Erase12x9, gx, gy
 | 
						|
            goto drawNextGhost
 | 
						|
        endif
 | 
						|
 | 
						|
        xf = (gx LSR 2) AND 1
 | 
						|
        yf = (gy LSR 2) AND 1
 | 
						|
        
 | 
						|
        'ghost dead, scared or normal
 | 
						|
        if &(flags.lo AND 1)
 | 
						|
            gosub drawDeadGhost
 | 
						|
        elseif gmode &&= SCARED_MODE
 | 
						|
            if timeTicks.hi &&< (8-levelPain.hi)
 | 
						|
                gosub drawScaredGhost
 | 
						|
            else
 | 
						|
                if &((timeTicks.lo LSR 3) AND 1)
 | 
						|
                    gosub drawNormalGhost
 | 
						|
                else
 | 
						|
                    gosub drawScaredGhost
 | 
						|
                endif
 | 
						|
            endif
 | 
						|
        else
 | 
						|
            gosub drawNormalGhost
 | 
						|
        endif
 | 
						|
        
 | 
						|
drawNextGhost:        
 | 
						|
    next gidx
 | 
						|
return
 | 
						|
 | 
						|
drawNormalGhost:
 | 
						|
    i = gidx LSL 2
 | 
						|
    if gxd &= 1
 | 
						|
        sprite FlipX,  peek(@gframes + 0 + i) + xf, gx, gy
 | 
						|
    elseif gxd &= -1
 | 
						|
        sprite NoFlip, peek(@gframes + 1 + i) + xf, gx, gy
 | 
						|
    elseif gyd &= 1
 | 
						|
        sprite NoFlip, peek(@gframes + 2 + i) + yf, gx, gy
 | 
						|
    else
 | 
						|
        sprite NoFlip, peek(@gframes + 3 + i) + yf, gx, gy
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
drawScaredGhost:
 | 
						|
    if gxd &= 1
 | 
						|
        sprite FlipX,  ScaredRt + xf, gx, gy
 | 
						|
    elseif gxd &= -1
 | 
						|
        sprite NoFlip, ScaredLt + xf, gx, gy
 | 
						|
    elseif gyd &&= 1
 | 
						|
        sprite NoFlip, ScaredDn + yf, gx, gy
 | 
						|
    else
 | 
						|
        sprite NoFlip, ScaredUp + yf, gx, gy
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
drawDeadGhost:
 | 
						|
    if gxd &&= 1
 | 
						|
        sprite FlipX,  EyesRt, gx+2, gy+3
 | 
						|
    elseif gxd &&= -1
 | 
						|
        sprite NoFlip, EyesLt, gx+2, gy+3
 | 
						|
    elseif gyd &&= 1
 | 
						|
        sprite NoFlip, EyesDn, gx+2, gy+3
 | 
						|
    else
 | 
						|
        sprite FlipY,  EyesUp, gx+2, gy+3
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
drawPills:
 | 
						|
    i = timeTicks.lo AND 7
 | 
						|
    if i &= 0
 | 
						|
        i = (timeTicks.lo LSR 3) AND 1
 | 
						|
        if peek(PILL_LT) &= PILL then sprite NoFlip, Pill + i, (1*5)  + (ORIGIN_X-2), (2*5)  + (ORIGIN_Y - 3)
 | 
						|
        if peek(PILL_RT) &= PILL then sprite NoFlip, Pill + i, (26*5) + (ORIGIN_X-2), (2*5)  + (ORIGIN_Y - 3)
 | 
						|
        if peek(PILL_LB) &= PILL then sprite NoFlip, Pill + i, (1*5)  + (ORIGIN_X-2), (18*5) + (ORIGIN_Y - 3)
 | 
						|
        if peek(PILL_RB) &= PILL then sprite NoFlip, Pill + i, (26*5) + (ORIGIN_X-2), (18*5) + (ORIGIN_Y - 3)
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
movePucMon:
 | 
						|
    gosub coordsPucMon
 | 
						|
    puci = ci - pxd
 | 
						|
    pucj = cj - pyd
 | 
						|
        
 | 
						|
    'dots, pills, doors and tunnels
 | 
						|
    mz = maze(cj, ci)
 | 
						|
    if (mz AND &h0F) &= DOT
 | 
						|
        maze(cj, ci) = (mz AND &hF0) OR RDOT
 | 
						|
        bcdint @pointsBCD, 10
 | 
						|
        call drawScore
 | 
						|
        livesDots.lo = livesDots.lo - 1
 | 
						|
    elseif mz &= PILL
 | 
						|
        maze(cj, ci) = (mz AND &hF0) OR RPILL
 | 
						|
        gmode = SCARED_MODE
 | 
						|
        timeTicks = 0
 | 
						|
        bcdint @pointsBCD, 50
 | 
						|
        call drawScore
 | 
						|
        livesDots.lo = livesDots.lo - 1
 | 
						|
    elseif mz &>= DOOR
 | 
						|
        pxd = oxd : pyd = oyd
 | 
						|
        gosub coordsPucMon
 | 
						|
        mz = maze(cj, ci) 
 | 
						|
    elseif mz &= TUNNEL
 | 
						|
        px = (129+ORIGIN_X) - px
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
moveGhosts:
 | 
						|
    for gidx=0 to NUM_GHOSTS-1
 | 
						|
        gosub getGhostVars
 | 
						|
 | 
						|
        'ghost slowed
 | 
						|
        slowed = 0
 | 
						|
        if (gmode = SCARED_MODE) OR (flags.lo AND 2)
 | 
						|
            if timeTicks.lo XOR 255 AND 1  'if timeTicks.lo AND 1 = 0
 | 
						|
                if flags.lo XOR 255 AND 1  'if flags.lo     AND 1 = 0
 | 
						|
                    slowed = 1
 | 
						|
                    gxd = 0 : gyd = gxd
 | 
						|
                endif
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
        
 | 
						|
        'ghost position
 | 
						|
        gx = gx + gxd
 | 
						|
        gy = gy + gyd
 | 
						|
        
 | 
						|
        'ghost colliding with puc
 | 
						|
        if flags.lo XOR 255 AND 1  'if flags.lo AND 1 = 0
 | 
						|
            if abs(gx - px) &<= 3
 | 
						|
                if abs(gy - py) &<= 3
 | 
						|
                    sprite NoFlip, Erase12x9, gx, gy
 | 
						|
                    if gmode &= SCARED_MODE
 | 
						|
                        flags.lo = flags.lo OR 1 : ghostsFlags(gidx) = flags.lo
 | 
						|
                        bcdint @pointsBCD, bonus : bonus = bonus + bonus
 | 
						|
                        call drawScore
 | 
						|
                    else
 | 
						|
                        flags.hi = 1
 | 
						|
                    endif
 | 
						|
                endif
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
 | 
						|
        'ghost reverses direction
 | 
						|
        if gmode &= SCARED_MODE
 | 
						|
            if timeTicks.hi &= 0
 | 
						|
                if timeTicks.lo &= 1
 | 
						|
                    gxd = -gxd : gyd = -gyd
 | 
						|
                endif
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
 | 
						|
        'skip ghost AI if not centered on a tile
 | 
						|
        mx = gx : my = gy : gosub mod5
 | 
						|
        if mx &<> 3 then goto moveNextGhost
 | 
						|
        if my &<> 3 then goto moveNextGhost
 | 
						|
 | 
						|
        'ghost look ahead indices
 | 
						|
        ci = gx + gxd + gxd + gxd + -(ORIGIN_X-6)
 | 
						|
        cj = gy + gyd + gyd + gyd +  (ORIGIN_Y+2)
 | 
						|
        call div5
 | 
						|
 | 
						|
        'ghost dot indices
 | 
						|
        di = ci - gxd - gxd
 | 
						|
        dj = cj - gyd - gyd
 | 
						|
 | 
						|
        'ghost indices
 | 
						|
        gi = ci - gxd
 | 
						|
        gj = cj - gyd
 | 
						|
 | 
						|
        'ghost replaces dot
 | 
						|
        mz = maze(dj, di)
 | 
						|
        if slowed &= 0 then gosub replaceDot
 | 
						|
 | 
						|
        'ghost leaves home
 | 
						|
        if maze(gj, gi) &= EXIT
 | 
						|
            if &(flags.lo XOR 255 AND 1)  'if flags.lo AND 1 = 0
 | 
						|
                if gmode &<> SCARED_MODE
 | 
						|
                    gxd = 0 : gyd = -1
 | 
						|
                endif
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
 | 
						|
        'ghost's next target
 | 
						|
        on gidx gosub getBlinkyTarget, getPinkyTarget, getInkyTarget, getClydeTarget
 | 
						|
 | 
						|
        'ghost home
 | 
						|
        if gi &= 13
 | 
						|
            if gj &= 10
 | 
						|
                flags.lo = flags.lo AND &hFE : ghostsFlags(gidx) = flags.lo
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
 | 
						|
        'ghost died, so head home
 | 
						|
        if &(flags.lo AND 1)
 | 
						|
            ti = 12 : tj = 11
 | 
						|
        endif
 | 
						|
 | 
						|
        'ghost walls, tunnel and junctions
 | 
						|
        mz = maze(cj, ci)
 | 
						|
        if mz &= WALL
 | 
						|
            gosub getWallDir
 | 
						|
            gosub getGhostDir
 | 
						|
        elseif mz &= TUNNEL
 | 
						|
            gx = (129+ORIGIN_X) - gx
 | 
						|
        elseif mz &= SLOW
 | 
						|
            flags.lo = flags.lo OR 2 : ghostsFlags(gidx) = flags.lo
 | 
						|
        else
 | 
						|
            'reset slow flag
 | 
						|
            if flags.lo AND 2
 | 
						|
                flags.lo = flags.lo AND &hFD : ghostsFlags(gidx) = flags.lo
 | 
						|
            endif
 | 
						|
 | 
						|
            'junctions and entering cage whilst dead
 | 
						|
            mz = maze(gj, gi) AND &hF0
 | 
						|
            if &((mz = JUNC) OR (((mz = DOOR) OR (mz = ENTER)) AND (flags.lo AND 1)))
 | 
						|
                gosub getJuncDir
 | 
						|
                gosub getGhostDir
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
 | 
						|
moveNextGhost:
 | 
						|
        'ghost vars update when not slowed
 | 
						|
        if slowed &= 0
 | 
						|
            gosub setGhostVars
 | 
						|
        endif
 | 
						|
    next gidx
 | 
						|
return
 | 
						|
 | 
						|
getGhostVars:
 | 
						|
    gx = ghostsX(gidx).lo : gy = ghostsY(gidx).lo
 | 
						|
    gxd = ghostsXd(gidx)  : gyd = ghostsYd(gidx)
 | 
						|
    flags.lo = ghostsFlags(gidx)
 | 
						|
return
 | 
						|
 | 
						|
setGhostVars:
 | 
						|
    ghostsX(gidx) = gx : ghostsY(gidx) = gy
 | 
						|
    ghostsXd(gidx) = gxd : ghostsYd(gidx) = gyd
 | 
						|
return
 | 
						|
 | 
						|
getGhostDir:
 | 
						|
    i = i LSL 2
 | 
						|
    gxd = deek(@GHOST_DIRS + i + 0)
 | 
						|
    gyd = deek(@GHOST_DIRS + i + 2)
 | 
						|
return
 | 
						|
 | 
						|
setGhostsMode:
 | 
						|
    if (timeTicks.lo AND &h1F) then return
 | 
						|
 | 
						|
    'roughly every second when running at ~30fps, (mode 2)
 | 
						|
    inc timeTicks.hi
 | 
						|
    
 | 
						|
    'ghost scared mode lasts approx 10 seconds
 | 
						|
    if gmode &= SCARED_MODE
 | 
						|
        if timeTicks.hi &> (10 - levelPain.hi)
 | 
						|
            timeTicks.hi = 0
 | 
						|
            bonus = 200
 | 
						|
            gmode = CHASE_MODE
 | 
						|
        endif
 | 
						|
        return
 | 
						|
    endif
 | 
						|
    
 | 
						|
    'ghosts return to chase mode
 | 
						|
    if timeTicks.hi &> 30
 | 
						|
        timeTicks.hi = 0
 | 
						|
        gmode = CHASE_MODE
 | 
						|
        return
 | 
						|
    endif
 | 
						|
    
 | 
						|
    'ghosts scatter for 10 seconds out of every 30 seconds    
 | 
						|
    if timeTicks.hi &> (20 + levelPain.hi)
 | 
						|
        gmode = SCATTER_MODE
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
'Blinkys target is Puc
 | 
						|
getBlinkyTarget:
 | 
						|
    'save Blinkys indices for inky's targeting
 | 
						|
    bi = gi : bj = gj
 | 
						|
 | 
						|
    if gmode &= CHASE_MODE    
 | 
						|
        ti = puci : tj = pucj
 | 
						|
        return
 | 
						|
    endif
 | 
						|
    
 | 
						|
    'scatter target
 | 
						|
    ti = 27 : tj = 0
 | 
						|
return
 | 
						|
 | 
						|
'Pinkys target is 4 tiles ahead of Pucs current direction
 | 
						|
getPinkyTarget:
 | 
						|
    if gmode &= CHASE_MODE
 | 
						|
        ti = puci + pxd + pxd + pxd + pxd
 | 
						|
        tj = pucj + pyd + pyd + pyd + pyd
 | 
						|
        return
 | 
						|
    endif
 | 
						|
    
 | 
						|
    'scatter target
 | 
						|
    ti = 0 : tj = 0
 | 
						|
return
 | 
						|
 | 
						|
'Inkys target is (vector from Blinky to (Puc + 2)) * 2
 | 
						|
getInkyTarget:
 | 
						|
    if gmode &= CHASE_MODE
 | 
						|
        ti = puci + pxd + pxd
 | 
						|
        tj = pucj + pyd + pyd
 | 
						|
        bi = ti - bi : bj = tj - bj 'vector from Blinky to (Puc + 2)
 | 
						|
        ti = ti + bi
 | 
						|
        tj = tj + bj
 | 
						|
        return
 | 
						|
    endif
 | 
						|
    
 | 
						|
    'scatter target
 | 
						|
    ti = 27 : tj = 23
 | 
						|
return
 | 
						|
 | 
						|
'Clyde acts like Blinky until he gets within 8 tiles, then he scatters
 | 
						|
getClydeTarget:
 | 
						|
    if gmode &= CHASE_MODE
 | 
						|
        if abs(puci - gi) + abs(pucj - gj) &> 8 'taxi-cab distance
 | 
						|
            ti = puci : tj = pucj
 | 
						|
            return
 | 
						|
        endif
 | 
						|
    endif
 | 
						|
    
 | 
						|
    'scatter target
 | 
						|
    ti = 0 : tj = 23
 | 
						|
return
 | 
						|
 | 
						|
getJuncDir:
 | 
						|
    if (gxd)
 | 
						|
        if (abs(tj - gj))
 | 
						|
            if maze(gj - 1, gi) &<> WALL
 | 
						|
                i = 3 : if tj &< gj then return
 | 
						|
            endif
 | 
						|
            if maze(gj + 1, gi) &<> WALL
 | 
						|
                i = 1 : if tj &> gj then return
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
    else
 | 
						|
        if (abs(ti - gi))
 | 
						|
            if maze(gj, gi - 1) &<> WALL
 | 
						|
                i = 2 : if ti &< gi then return
 | 
						|
            endif
 | 
						|
            if maze(gj, gi + 1) &<> WALL
 | 
						|
                i = 0 : if ti &> gi then return
 | 
						|
            endif
 | 
						|
        endif
 | 
						|
    endif
 | 
						|
 | 
						|
    if gxd &= 1
 | 
						|
        i = 0
 | 
						|
    elseif gxd &= -1
 | 
						|
        i = 2
 | 
						|
    elseif gyd &= 1
 | 
						|
        i = 1
 | 
						|
    else
 | 
						|
        i = 3
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
getWallDir:
 | 
						|
    if (gxd)
 | 
						|
        if maze(gj - 1, gi) &<> WALL
 | 
						|
            i = 3 : if tj &< gj then return
 | 
						|
        endif
 | 
						|
        if maze(gj + 1, gi) &<> WALL then i = 1
 | 
						|
    else
 | 
						|
        if maze(gj, gi - 1) &<> WALL
 | 
						|
            i = 2 : if ti &< gi then return
 | 
						|
        endif
 | 
						|
        if maze(gj, gi + 1) &<> WALL then i = 0
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
replaceDot:
 | 
						|
    if (mz AND &h0F) &= DOT
 | 
						|
        di = (di LSL 2) + di + ORIGIN_X   'di = di*5 + 12
 | 
						|
        dj = (dj LSL 2) + dj + ORIGIN_Y   'dj = dj*5 + 2
 | 
						|
        poke ((dj + 8) LSL 8) + di, &h2B  'convert dj, di to vram address
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
coordsPucMon:
 | 
						|
    ci = px + pxd + pxd + pxd + -(ORIGIN_X-6)
 | 
						|
    cj = py + pyd + pyd + pyd +  (ORIGIN_Y+2)
 | 
						|
    call div5
 | 
						|
return
 | 
						|
 | 
						|
handleInput:
 | 
						|
    oxd = pxd : oyd = pyd
 | 
						|
    mx = px : my = py : gosub mod5
 | 
						|
    gosub get("BUTTON_STATE")
 | 
						|
return
 | 
						|
 | 
						|
253: if my &= 3 then pyd = 0 : pxd = pyd-1
 | 
						|
     return
 | 
						|
 | 
						|
254: if my &= 3 then pyd = 0 : pxd = pyd+1
 | 
						|
     return
 | 
						|
 | 
						|
247: if mx &= 3 then pxd = 0 : pyd = pxd-1
 | 
						|
     return
 | 
						|
 | 
						|
251: if mx &= 3 then pxd = 0 : pyd = pxd+1
 | 
						|
     return
 | 
						|
 | 
						|
proc drawScore
 | 
						|
    local char
 | 
						|
    
 | 
						|
    bcdadd @pointsBCD, @scoreBCD, SCORE_LEN
 | 
						|
    char = SCORE_X+ORIGIN_X
 | 
						|
    for i=0 to SCORE_LEN-1
 | 
						|
        sprite NoFlip, Digit + peek(@scoreBCD + SCORE_LEN-1 - i), char, SCORE_Y+ORIGIN_Y
 | 
						|
        char = char + 6
 | 
						|
    next i
 | 
						|
    'bcdcmp requires bcd addrs to point to msd
 | 
						|
    if bcdcmp(@scoreBCD+(SCORE_LEN-1), @highBCD+(SCORE_LEN-1), SCORE_LEN) &= 1
 | 
						|
        bcdcpy @scoreBCD, @highBCD, SCORE_LEN
 | 
						|
        call drawHigh
 | 
						|
    endif
 | 
						|
endproc
 | 
						|
 | 
						|
proc drawHigh
 | 
						|
    local char
 | 
						|
    
 | 
						|
    char = HIGH_X+ORIGIN_X
 | 
						|
    for i=0 to SCORE_LEN-1
 | 
						|
        sprite NoFlip, Digit + peek(@highBCD + SCORE_LEN-1 - i), char, HIGH_Y+ORIGIN_Y
 | 
						|
        char = char + 6
 | 
						|
    next i
 | 
						|
endproc
 | 
						|
 | 
						|
proc drawLevel
 | 
						|
    local char
 | 
						|
    
 | 
						|
    sprite NoFlip, Level, LEVEL_X+ORIGIN_X, LEVEL_Y+ORIGIN_Y
 | 
						|
    char = LEVEL_X+ORIGIN_X + 6
 | 
						|
    for i=0 to LEVEL_LEN-1
 | 
						|
        sprite NoFlip, Digit + peek(@levelBCD + LEVEL_LEN-1 - i), char, LEVEL_Y+ORIGIN_Y
 | 
						|
        char = char + 6
 | 
						|
    next i
 | 
						|
endproc
 | 
						|
 | 
						|
proc drawLives
 | 
						|
    local puc
 | 
						|
    
 | 
						|
    puc = LIFE_X+ORIGIN_X
 | 
						|
    i = 1
 | 
						|
    while i &<= livesDots.hi
 | 
						|
        sprite NoFlip, Life, puc, LIFE_Y+ORIGIN_Y
 | 
						|
        puc = puc + 6
 | 
						|
        inc i
 | 
						|
    wend
 | 
						|
    while i &<= 3
 | 
						|
        sprite NoFlip, Erase6x6, puc, LIFE_Y+ORIGIN_Y
 | 
						|
        puc = puc + 6
 | 
						|
        inc i
 | 
						|
    wend
 | 
						|
endproc
 | 
						|
 | 
						|
drawDeath:
 | 
						|
    call drawLives
 | 
						|
    for i=1 to 6
 | 
						|
        sprite NoFlip, PucLt + 2, px, py
 | 
						|
        wait 10
 | 
						|
        sprite NoFlip, Erase12x9, px, py
 | 
						|
        wait 10
 | 
						|
    next i
 | 
						|
return
 | 
						|
 | 
						|
drawMaze:
 | 
						|
    set FG_COLOUR, &h30
 | 
						|
    for i=0 to (NUM_MAZE_PIECES*2 - 2) step 4
 | 
						|
        set CURSOR_XY, deek(@MAZE_PIECES + i)     : polyR deek(@MAZE_ADDRS + i)
 | 
						|
        set CURSOR_XY, deek(@MAZE_PIECES + i + 2) : polyR deek(@MAZE_ADDRS + i + 2), FLIPX
 | 
						|
    next i
 | 
						|
    
 | 
						|
    set FG_COLOUR, 0 '&h2B
 | 
						|
return
 | 
						|
 | 
						|
'redraw=0 is refresh, redraw=1 is redraw
 | 
						|
proc drawDots, redraw
 | 
						|
    set FG_COLOUR, &h2B
 | 
						|
    for cj=0 to 23
 | 
						|
        for ci=0 to 27
 | 
						|
            mz = maze(cj, ci)
 | 
						|
            if redraw &= 1
 | 
						|
                if (mz AND &h0F) &= RDOT       'reset dots
 | 
						|
                    mz = (mz AND &hF0) OR DOT
 | 
						|
                elseif (mz AND &h0F) &= RPILL  'reset pills
 | 
						|
                    mz = (mz AND &hF0) OR PILL
 | 
						|
                endif
 | 
						|
                maze(cj, ci) = mz
 | 
						|
            endif
 | 
						|
            if (mz AND &h0F) &= DOT
 | 
						|
                pset (ci LSL 2) + ci + ORIGIN_X, (cj LSL 2) + cj + ORIGIN_Y
 | 
						|
            endif
 | 
						|
        next ci
 | 
						|
    next cj
 | 
						|
endproc
 | 
						|
 | 
						|
proc initVars
 | 
						|
    local corner
 | 
						|
    
 | 
						|
    'initialises all variables, (to zero), starting at @timeTicks
 | 
						|
    init vars @timeTicks
 | 
						|
    
 | 
						|
    px = (63+ORIGIN_X)
 | 
						|
    py = (86+ORIGIN_Y)
 | 
						|
    pxd = -1
 | 
						|
    bonus = 200
 | 
						|
    
 | 
						|
    'reset ghost vars
 | 
						|
    corner = (rnd(0) AND 3)
 | 
						|
    for gidx=0 to (NUM_GHOSTS - 1)
 | 
						|
        if gidx &= 0
 | 
						|
            i = gidx LSL 1                          'blinky is always reset to the same position
 | 
						|
        else
 | 
						|
            i = (((corner + gidx) AND 3) + 1) LSL 1 'pinky, inky and clyde are reset to 1 of 4 random cage corners
 | 
						|
        endif
 | 
						|
        gx = deek(@ghostsXr + i)
 | 
						|
        gy = deek(@ghostsYr + i)
 | 
						|
        gxd = -1                                    'ghosts initially move left
 | 
						|
        gosub setGhostVars
 | 
						|
    next gidx
 | 
						|
endproc
 | 
						|
 | 
						|
startLevel:
 | 
						|
    sprite NoFlip, Erase12x9, px, py
 | 
						|
    livesDots.lo = 212
 | 
						|
    bcdint @pointsBCD, 0
 | 
						|
    bcdint @levelBCD, levelPain.lo
 | 
						|
    if levelPain.hi &> 7 then levelPain.hi = 7
 | 
						|
    
 | 
						|
    call drawDots, 1 'redraw
 | 
						|
    call drawScore
 | 
						|
    call drawHigh
 | 
						|
    call drawLives
 | 
						|
    call drawLevel
 | 
						|
    
 | 
						|
    if levelPain.lo &= 0
 | 
						|
        play music, MUSIC_INTRO, 2
 | 
						|
    else
 | 
						|
        wait 120
 | 
						|
    endif
 | 
						|
return
 | 
						|
 | 
						|
resetLevel:
 | 
						|
    levelPain = 0+0*256
 | 
						|
    livesDots = 3*256
 | 
						|
    bcdint @scoreBCD, 0
 | 
						|
    poke &h0101, 0
 | 
						|
    
 | 
						|
    'audio fix for ROMv5a
 | 
						|
    poke &h21, peek(&h21) OR 3
 | 
						|
return
 | 
						|
 | 
						|
initSystem:
 | 
						|
    px = (63+ORIGIN_X) : py = (86+ORIGIN_Y)
 | 
						|
    
 | 
						|
    'scanline 0 and 1 are replaced with scanline 2, (hide scanlines 0 and 1)
 | 
						|
    poke &h0100, &h0A
 | 
						|
    poke &h0102, &h0A
 | 
						|
    
 | 
						|
    'scanline 118 and 119 are replaced with scanline 117, (hide scanlines 118 and 119)
 | 
						|
    poke &h01EC, &h7D
 | 
						|
    poke &h01EE, &h7D
 | 
						|
    
 | 
						|
    'don't use cls as we are using hidden parts of VRAM for code and data
 | 
						|
    mode 2
 | 
						|
    set FGBG_COLOUR, 0
 | 
						|
    cls &h0A00, 160, 116
 | 
						|
    'rectf 0, 2, 159, 117
 | 
						|
    'set FG_COLOUR, &h30
 | 
						|
    'rectf 135+ORIGIN_X, 2,            154+ORIGIN_X, HIGH_Y-3
 | 
						|
    'rectf 135+ORIGIN_X, 15+HIGH_Y-3,  154+ORIGIN_X, SCORE_Y-3
 | 
						|
    'rectf 135+ORIGIN_X, 15+SCORE_Y-3, 154+ORIGIN_X, 117
 | 
						|
    'set FG_COLOUR, 0
 | 
						|
    'rectf 136+ORIGIN_X, 3,            154+ORIGIN_X, HIGH_Y-4
 | 
						|
    'rectf 136+ORIGIN_X, 16+HIGH_Y-3,  154+ORIGIN_X, SCORE_Y-4
 | 
						|
    'rectf 136+ORIGIN_X, 16+SCORE_Y-3, 154+ORIGIN_X, 116
 | 
						|
return
 | 
						|
 | 
						|
'drawGrid:
 | 
						|
'    set FG_COLOUR, &h15
 | 
						|
'    for i=ORIGIN_X to 140+ORIGIN_X step 5
 | 
						|
'        line i, 0, i, 119
 | 
						|
'    next i
 | 
						|
'    for i=ORIGIN_Y to 115+ORIGIN_Y step 5
 | 
						|
'        line 0, i, 159, i
 | 
						|
'    next i
 | 
						|
'return
 | 
						|
 | 
						|
'drawCells:
 | 
						|
'    set FG_COLOUR, &h15
 | 
						|
'    for i=10 to 150 step 5
 | 
						|
'        line i, 0, i, 119
 | 
						|
'    next i
 | 
						|
'    for i=0 to 115 step 5
 | 
						|
'        line 0, i, 159, i
 | 
						|
'    next i
 | 
						|
'return |