User Tools

Site Tools


base:pallo
; Pallo
; -----
; 2006 Hannu Nuotio

; Pallo is a remake of the crap QBasic game of the same name (and author).

; Start of project: 26.8.2006
; v.1.1 - 20.10.2006 - added joyport constants
; v.1.0 - 16.9.2006 - seems to work

; Compiles with ACME 0.91
; # acme --cpu 6502 -f cbm -o pallo.prg pallo.a

; Type SYS 4096 to start or use crunched version.

; Known bugs:
;  - If warning collides with pallo and food, pallo does not get food.
;    This is done intentionally to avoid nasty coordinate check code :)

; TODO:
;  - music/sfx
;  - 2 player mode

; Memory map:
; $0000-$0fff : unused
; $1000-$xxxx : code
; $xxxx-$yyyy : variables (reused sprite data)
; $yyyy-$zzzz : sintable, strings, logo
; $5300-$5aff : character set
; $5b00-$5bff : sprites
; $5c00-$5ff7 : screen memory (color data)
; $6000-$7ff7 : font memory   (pixel data)
; $7ff8-$7fff : sprite pointers
; $8000-$ffff : unused

; Sprites:
; 0 = $5b00 = Pallo's eyes (white)
; 1 = $5b40 = Pallo's edges (brown)
; 2 = $5bc0 = Pallo's body (green)
; 3 = $5b80 = Food (light red)
; 4 = $5b80 = Warning (dark grey)
; 5 = $5b00 = Pallo2's eyes (white)
; 6 = $5b40 = Pallo2's edges (brown)
; 7 = $5bc0 = Pallo2's body (light blue)

; Interrupt states:
; $x0 - do nothing
; $01: - update "random" numbers
;	- check collisions:
;		- if none,   state = $02
;		- if food,   state = $40
;		- if killer, state = $80
;		- if both,   state = $C0
; $02 - update sprite positions, set state = $01

; Gameloop states:
;  a = if collision goto c. read joystick, explode bomb, update sprite pos.
;  b = decrease bomb & warning timeout, draw killer
;  c = check which collision(s), move food & warning, erase killer, update score or end game

; Pallo movement:
;  basic idea:
;    X += sin(dir), Y += cos(dir)
;
;  variables:
;    pallo1x(h)/y = sprite coordinates (= X/Y)
;    pallo1subx/y = subpixel coordinates (= x/y)
;    pallo1dir = direction of movement (= dir)
;
;  direction circle:
;         $80
;       /--|--\
;      / 3 | 2 \ <- segment
; $C0 |---------| $40
;      \ 4 | 1 /
;       \--|--/
;         $00 (dir)
;
; case dir =
;  $00: Y++
;  $40: X++
;  $80: Y--
;  $C0: X--
;
; (if dir & $3f != 0 ) case segment =
;  1: X.x += sin(dir), Y.y += cos(dir)
;  2: X.x += cos(dir), Y.y -= sin(dir)
;  3: X.x -= sin(dir), Y.y -= cos(dir)
;  4: X.x -= cos(dir), Y.y += sin(dir)
;
; sintable: 
;  sintable[i] = 256*sin(2*pi*i/256), i = [0,$3f]
;  sin(dir) -> sintable[dir]
;  cos(dir) -> sintable[$40-dir]


; --- Macros

; SpriteLine - for easy definition of sprites
; from "ddrv.a" by Marco Baye
!macro SpriteLine .v {
!by .v>>16, (.v>>8)&255, .v&255
}


; --- Constants

joyport = $dc00		; joystick port
joypddr = $dc02		; joystick port data direction register

bombpoints = 15		; points required to get a bomb
bombtimeout = 35	; min. time between explosions
warningtimeout = 50	; warning->killer interval


; --- Variables

highscoretext = startscrtext10+12

tmp = Sprites

; last joystick state
lastjoy = Sprites+1

; interrupt state (explained above)
intstate = Sprites+2

; sprite coordinates (0=1=2=Pallo, 5=6=7=Pallo2)
pallo1x   = Sprites+3
pallo1xh  = Sprites+4
pallo1y   = Sprites+5
foodx     = Sprites+6
foodxh    = Sprites+7
foody     = Sprites+8
warningx  = Sprites+9
warningxh = Sprites+10
warningy  = Sprites+11
pallo2x   = Sprites+12
pallo2xh  = Sprites+13
pallo2y   = Sprites+14

; pallo dir & subpixel coordinates
pallo1subx = Sprites + 15
pallo1suby = Sprites + 16
pallo1dir  = Sprites + 17
pallo2subx = Sprites + 18
pallo2suby = Sprites + 19
pallo2dir  = Sprites + 20

; "random" variables
rnd1 = Sprites + 21
rnd2 = Sprites + 22	; rnd[2:1] = 0..308
rnd3 = Sprites + 23
rnd4 = Sprites + 24	; rnd[4:3] = 0..308
rnd5 = Sprites + 25	; rnd5 = 0..182
rnd6 = Sprites + 26	; rnd6 = 0..182

; score & bombs
bombs  = Sprites + 27	; bomb amount
bombc  = Sprites + 28	; bomb counter (0..15)
hscore = Sprites + 29	; high score
score  = Sprites + 30	; score

; timeouts
btime = Sprites + 31	; bomb timeout
wtime = Sprites + 32	; warning timeout

; temp char for drawbomb
tmpchar = Sprites + 33
;next variable = Sprites + 41


; --- Main 

; start of program
*=$1000
mlcodeentry:

; - interrupt setup
; from "An Introduction to Programming C-64 Demos" by Puterman aka Linus Åkerlund
; http://user.tninet.se/~uxm165t/demo_programming/demo_prog/demo_prog.html
; ... + modifications
;
sei		; interrupts off
lda #$7f
ldx #$01
sta $dc0d	; Turn off CIA 1 interrupts
sta $dd0d	; Turn off CIA 2 interrupts
stx $d01a	; Turn on raster interrupts
lda #<int	; low part of address of interrupt handler code
ldx #>int	; high part of address of interrupt handler code
ldy #250	; line to trigger interrupt
sta $0314	; store in interrupt vector
stx $0315
sty $d012
lda #<nmi	; low part of address of NMI handler code
ldx #>nmi	; high part of address of NMI handler code
sta $0318	; store in NMI vector
stx $0319
lda #0
sta intstate	; set interrupt state to 0
lda $dc0d	; ACK CIA 1 interrupts
lda $dd0d	; ACK CIA 2 interrupts
asl $d019	; ACK VIC interrupts
cli		; interrupts on

; disable bcd-mode
cld

; copy character rom to $5300-$5aff
; copy sprites to $5b40-$5bfe
ldx #0		; 255 loops
sei		; interrups off
lda $1
and #$fb
sta $1		; character rom on
-	lda $d000,x	; load from char-rom
	sta $5300,x	; store to ram
	lda $d100,x	; load from char-rom
	sta $5400,x	; store to ram
	lda $d200,x	; load from char-rom
	sta $5500,x	; store to ram
	lda $d300,x	; load from char-rom
	sta $5600,x	; store to ram
	lda $d400,x	; load from char-rom
	sta $5700,x	; store to ram
	lda $d500,x	; load from char-rom
	sta $5800,x	; store to ram
	lda $d500,x	; load from char-rom
	sta $5900,x	; store to ram
	lda $d600,x	; load from char-rom
	sta $5a00,x	; store to ram
	lda Sprites,x	; load from sprites (& sine table)
	sta $5b00,x	; save to ram
	inx
	bne -
lda $1
ora #$04
sta $1		; character rom off
asl $d019	; ACK VIC interrupts
cli		; interrupts on

; generate pallo's body sprite
ldx #64
-	lda $5b80,x	; a = food sprite
	eor $5b40,x	; a xor edges
	eor $5b00,x	; a xor eyes
	sta $5bc0,x	; save to body sprite
	dex
	bne -

; bank 1 ($4000)
lda #2
sta $dd00

; hires bitmap
; 25 rows
; file scroll = 2
; raster compare msb = 0
; blank
lda #$2b
sta $d011

; font = "screen" = $6000
; screen = "color" = $5c00
lda #$78
sta $d018

; sprite block pointers
ldx #108	; -> $5b00
stx $5ff8	; p1eyes
stx $5ffd	; p2eyes
inx		; -> $5b40
stx $5ff9	; p1edge
stx $5ffe	; p2edge
inx		; -> $5b80
stx $5ffb	; food
stx $5ffc	; warning
inx		; -> $5bc0
stx $5ffa	; p1body
stx $5fff	; p2body

; sprite colors
lda #1		; white
sta $d027	; p1eyes
sta $d02c	; p2eyes
lda #9		; brown
sta $d028	; p1edge
sta $d02d	; p2edge
lda #5		; green
sta $d029	; p1body
lda #10		; light red
sta $d02a	; food
lda #11		; dark gray
sta $d02b	; warning
lda #14		; light blue
sta $d02e	; p2body

; misc. vic settings
lda #0
sta $d020	; border color
sta $d021	; background color
sta $d01c	; sprites = hi-res
lda #$10	; sprite 4 < backgnd
sta $d01b	; sprite-backgnd priority

; init random variables
lda #0
sta rnd2
sta rnd4
sta rnd5
sta rnd6

; set joyport to input
lda #0
sta joypddr

; - Pre-start screen
lda #0
sta hscore	; high score = 0
lda #$f0	; fg = gray, bg = black
jsr setscreencolor

; - Start screen
; clear screen
; draw logo & text
; draw highscore
; position sprites
; draw killer
; wait for fire
;
startscreen:
jsr clearscreen

; draw logo
lda #<pallologo
sta logosl
lda #>pallologo
sta logosh	; point to logo (144x88)
lda #<$6000+8*2+320*1
sta logodl
lda #>$6000+8*2+320*1
sta logodh

ldy #11		; y = 88/8 = 11
-		; y loop
ldx #0		; x = 0
--		; x loop
	logosl = *+1
	logosh = *+2
	lda $0000,x	; load bitmap
	logodl = *+1
	logodh = *+2
	sta $0000,x	; store screen
	inx		; next x
	cpx #144	
	bne --		; loop until x=144
clc
lda #64
adc logodl 
sta logodl
lda #1
adc logodh
sta logodh		; destination += 320
clc
lda #144
adc logosl 
sta logosl
lda #0
adc logosh
sta logosh		; source += 144
dey
bne -			; next y

; draw text
lda #<startscrtext1
sta strptrl
lda #>startscrtext1
sta strptrh
ldx #28
ldy #3
jsr printstr	; = pallo
lda #<startscrtext2
sta strptrl
lda #>startscrtext2
sta strptrh
ldx #28
ldy #5
jsr printstr	; = food
lda #<startscrtext3
sta strptrl
lda #>startscrtext3
sta strptrh
ldx #28
ldy #7
jsr printstr	; = warning
lda #<startscrtext4
sta strptrl
lda #>startscrtext4
sta strptrh
ldx #28
ldy #9
jsr printstr	; = killer
lda #<startscrtext5
sta strptrl
lda #>startscrtext5
sta strptrh
ldx #7
ldy #13
jsr printstr	; use joystick...
lda #<startscrtext6
sta strptrl
lda #>startscrtext6
sta strptrh
ldx #7
ldy #14
jsr printstr	; < and > ...
lda #<startscrtext7
sta strptrl
lda #>startscrtext7
sta strptrh
ldx #7
ldy #15
jsr printstr	; fire ...
lda #<startscrtext8
sta strptrl
lda #>startscrtext8
sta strptrh
ldx #4
ldy #17
jsr printstr	; collect food...
lda #<startscrtext9
sta strptrl
lda #>startscrtext9
sta strptrh
ldx #4
ldy #18
jsr printstr	; a bomb ...
lda #<startscrtext10
sta strptrl
lda #>startscrtext10
sta strptrh
ldx #12
ldy #21
jsr printstr	; high score
lda #<startscrtext11
sta strptrl
lda #>startscrtext11
sta strptrh
ldx #4
ldy #24
jsr printstr

; activate sprites
lda #$1f
sta $d015

; position sprites
ldx #231
lda #73
ldy #0
stx pallo1x
sty pallo1xh
sta pallo1y
lda #89
stx foodx
sty foodxh
sta foody
lda #105
stx warningx
sty warningxh
sta warningy
sty pallo2x
sty pallo2y
sty pallo2xh

; calc & draw killer
clc
ldx #231-24
ldy #121-50
jsr calckiller
jsr drawkiller

; update sprites
lda #2
sta intstate	
-	cmp intstate
	beq -	; wait for state change
lda $d01f	; clear sprite-data collision
lda $d01e	; clear sprite-sprite collision

; unblank screen
lda #$3b
sta $d011

; wait for joystick fire 
jsr waitfirej

; - Entering game
; clear screen
; draw game screen & text
; position sprites
; init variables
; clear any collisions
; 
lda #0
sta intstate	; interrupt does nothing

; blank screen
lda #$2b
sta $d011

; draw game screen & text
jsr clearscreen
lda #<statustext
sta strptrl
lda #>statustext
sta strptrh
ldx #0
ldy #0
jsr printstr
jsr drawborders

; init variables & sprite positions
lda #$c0
sta pallo1dir
lda #0
sta warningy	; warning is offscreen
sta btime
sta wtime
sta score
sta bombs
sta bombc
lda #$30	; a = char "0"
sta bombstext+0
sta bombstext+1
sta scoretext+0
sta scoretext+1
sta scoretext+2

lda #2
sta intstate	; update sprites
-	cmp intstate
	beq -	; wait for state change
lda $d01f	; clear sprite-data collision
lda $d01e	; clear sprite-sprite collision

; unblank screen
lda #$3b
sta $d011

; - Game loop
; states:
;  a = if collision goto c. read joystick, update sprite pos.
;  b = decrease bomb & warning timeout, draw killer (entry point)
;  c = check which collision(s), move food & warning, erase killer, update score or end game

; state b
gstateb:
; decrease bomb timeout
lda btime	; a = btime (Z if 0)
beq +		; skip if 0
dec btime	; btime--
; decrease warning timeout & draw killer if timeout -> 0
+ lda wtime	; a = wtime (Z if 0)
beq +		; skip if 0
dec wtime	; wtime--
bne +		; skip if > 0
jsr drawkiller	; draw killer
lda #0
sta warningy	; move warning offscreen
+ lda #1	; next state
-	cmp intstate
	beq -	; wait for state change

; state a
gstatea:
; check for collisions
lda #3
bit intstate	; intstate & 3, N & V=intstate 7 & 6
bne +		; if !Z, proceed
jmp gstatec	; if Z, jump to state c
; read joystick
; test fire button (falling edge)
+ ldy lastjoy	; y = lastjoy (for later use) 
lda joyport	; a = joy
tax		; save to x
eor lastjoy	; joy xor lastjoy
stx lastjoy	; update lastjoy
and #$10	; test fire
beq gstatea_p2	; jump if no change
txa		; a = joy
and #$10	; test fire
bne gstatea_p2	; jump if rising edge
; fire pressed
; check timeout and available bombs
lda bombs	; a = bombs (Z if 0)
beq gstatea_p2	; jump if no bombs
lda btime	; a = btime (Z if 0)
bne gstatea_p2	; jump if bomb timeout
; bomb explosion
lda #1
sta $d020	; set border white
lda #0
sta intstate	; next state = 0
; decrease bomb amount
dec bombs
ldy #$39	; y = char "9"
lda #$2f	; a = char "0"-1
dec bombstext+1	; bombstext--
cmp bombstext+1	; test BCD underflow
bne +
sty bombstext+1	; save "0" to bombstext
dec bombstext	; bombstext--
; print bombs
+ jsr printbombs
; explode bomb
lda pallo1y	; a = pallo1y
sec
sbc #50		; remove sprite offset
tay		; y = bomb y
lda pallo1x	; a = pallo1x
sec
sbc #24		; remove sprite offset
tax		; x = bomb x
lda pallo1xh	; a = pallo1xh
sbc #0
clc
beq +
sec		; c = pallo1xh
+ jsr drawbomb	; drawbomb at x(c=msb),y
lda #1
sta intstate	; next state = 1
; set timeout
lda #bombtimeout
sta btime
lda #0
sta $d020	; set border black

; test left & right (use lastjoy for inertia)
gstatea_p2:
txa		; a = joy
and #$04	; test left
bne +		; jump if not active
inc pallo1dir	; pallo1dir++
inc pallo1dir	; pallo1dir++
+ tya		; a = lastjoy
and #$04	; test left
bne +		; jump if not active
inc pallo1dir	; pallo1dir++
+ txa		; a = joy
and #$08	; test right
bne +		; jump if not active
dec pallo1dir	; pallo1dir--
dec pallo1dir	; pallo1dir--
+ tya		; a = lastjoy
and #$08	; test right
bne gstatea_c	; jump if not active
dec pallo1dir	; pallo1dir--

; calculate movement & update sprite position
; check if movement is straight or from sintable
gstatea_c:
lda #$3f	; a = $3f
bit pallo1dir	; Z = p1dir && $3f, NV = bit7&6
php		; put flags to stack
lda #$3f	; a = $3f
and pallo1dir	; a = p1dir & $3f
bne + 		; skip if !Z (sintable movement)
jmp gstatea_s	; jump if Z (straight movement)
; sintable movement (flags in stack tell the segment)
+ tax		; x = p1dir & $3f = dir
eor #$ff	; a = !a
clc		; c = 0
adc #1		; a++
and #$3f	; a = a & $3f
tay		; y = $40-dir
lda sintable,x	; a = sin(dir)
tax		; x = sin(dir)
lda sintable,y	; a = sin($40-dir)
tay		; y = sin($40-dir)
plp		; pull flags from stack
bmi gstatea_34	; jump if N (segment 3 or 4)
bvs gstatea_2	; jump if V (segment 2)
clc		; (segment 1:x+,y+) c = 0
adc pallo1suby	; pallo1suby += sin($40-dir)
sta pallo1suby	; save pallo1suby
bcc +		; skip if no carry
inc pallo1y	; pallo1y++
+ clc		; c = 0
txa		; a = sin(dir)
adc pallo1subx	; pallo1subx += sin(dir)
sta pallo1subx	; save pallo1subx
bcs gstatea_r	; inc x if carry
jmp gstatea_f	; jump to state a finish
gstatea_2:	; 2:x+,y-
stx tmp		; tmp = sin(dir)
lda pallo1suby	; a = pallo1suby
sec		; c = 1
sbc tmp		; a = pallo1suby - sin(dir)
sta pallo1suby	; save pallo1suby
bcs +		; skip if carry (no borrow)
dec pallo1y	; pallo1y--
+ clc		; c = 0
tya		; a = sin($40-dir)
adc pallo1subx	; pallo1subx += sin($40-dir)
sta pallo1subx	; save pallo1subx
bcs gstatea_r	; inc x if carry
jmp gstatea_f	; jump to state a finish
gstatea_34:	; 3 or 4
bvs gstatea_4	; jump if V (4)
sty tmp		; (3:x-,y-) tmp = sin($40-dir)
lda pallo1suby	; a = pallo1suby
sec		; c = 1
sbc tmp		; a = pallo1suby - sin($40-dir)
sta pallo1suby	; save pallo1suby
bcs +		; skip if carry (no borrow)
dec pallo1y	; pallo1y--
+ lda pallo1subx	; a = pallo1subx
stx tmp		; tmp = sin(dir)
sec		; c = 1
sbc tmp		; a = pallo1subx - sin(dir)
sta pallo1subx	; save pallo1subx
bcc gstatea_l	; dec x if no carry (borrow)
jmp gstatea_f	; jump to state a finish
gstatea_4:	; 4:x-,y+
clc		; c = 0
txa		; a = sin(dir)
adc pallo1suby	; pallo1suby += sin(dir)
sta pallo1suby	; save pallo1suby
bcc +		; skip if no carry
inc pallo1y	; pallo1y++
+ lda pallo1subx	; a = pallo1subx
sty tmp		; tmp = sin($40-dir)
sec		; c = 1
sbc tmp		; a = pallo1subx - sin($40-dir)
sta pallo1subx	; save pallo1subx
bcc gstatea_l	; dec x if no carry (borrow)
jmp gstatea_f	; jump to state a finish
; straight movement (pallo1)
gstatea_s:	
plp		; pull flags from stack
bmi gstatea_ul	; jump if N (up or left)
bvs gstatea_r	; jump if V (right)
gstatea_d:	; straight movement to down
inc pallo1y	; y++
jmp gstatea_f	; jump to state a finish
gstatea_r:	; straight movement to right
inc pallo1x	; x++
bne gstatea_f	; jump if x!=0 ("carry"=0)
inc pallo1xh	; x++ (msb)
jmp gstatea_f	; jump to state a finish
gstatea_ul:	; straight, up or left
bvs gstatea_l	; jump if V (left)
gstatea_u:	; straight movement to up
dec pallo1y	; y--
jmp gstatea_f	; jump to state a finish
gstatea_l:	; straight movement to left
dec pallo1x	; x--
lda #$ff	; a = $ff (for "carry" test)
cmp pallo1x	; test "carry"
bne gstatea_f	; jump if x!=$ff ("carry"=0)
dec pallo1xh	; x-- (msb)
jmp gstatea_f	; jump to state a finish
gstatea_f:
lda #2		; next state
-	cmp intstate
	beq -	; wait for state change
jmp gstateb	; back to state b

; state c - a collision happened
gstatec:	; N->killer, V->food, NV->both
php		; save flags
bvs +		; skip if food collision
jmp gstatec_k	; jump if not food collision
; food collision
; increase score
+ inc score	; score++
lda #$3a	; a = char "9"+1
ldy #$30	; y = char "0"
inc scoretext+2	; scoretext++
cmp scoretext+2	; test BCD overflow
bne +
sty scoretext+2	; save "0" to scoretext
inc scoretext+1	; scoretext++
cmp scoretext+1	; test BCD overflow
bne +
sty scoretext+1	; save "0" to scoretext
inc scoretext	; scoretext++
; print score
+ jsr printscore
; increase bomb couter
inc bombc	; bomb counter ++
lda #bombpoints	; a = bombpoints
cmp bombc	; if bomb counter != bombpoints,
bne ++		; jump
; give a bomb to player
lda #0
sta bombc	; reset bomb counter
inc bombs	; bombs++
lda #$3a	; a = char "9"+1
ldy #$30	; y = char "0"
inc bombstext+1	; bombstext++
cmp bombstext+1	; test BCD overflow
bne +
sty bombstext+1	; save "0" to bombstext
inc bombstext	; bombstext++
; print bombs
+ jsr printbombs
; if warning timeout>0 draw killer
++ lda wtime	; a = wtime (Z if 0)
beq +		; skip if Z
jsr drawkiller
; move food & warning
+ clc
lda rnd1	; a = rnd1
adc #25		; add sprite x offset + 1
sta foodx	; save to food x
lda #0		; a = 0
adc rnd2	; add msb + c
sta foodxh	; save to food x msb
clc		; c = 0
lda rnd5	; a = rnd5
adc #59		; add sprite y offset + 9
sta foody	; save to food y
clc
lda rnd3	; a = rnd3
adc #25		; add sprite x offset + 1
sta warningx	; save to warning x
lda #0		; a = 0
adc rnd4	; add msb + c
sta warningxh	; save to warning x msb
clc		; c = 0
lda rnd6	; a = rnd6
adc #59		; add sprite y offset + 9
sta warningy	; save to warning y
; calc & erase killer below food
lda rnd5	; a = rnd5
clc
adc #9		; a += 9
tay		; y = rnd5 + 9
ldx rnd1	; x = rnd1
inx		; x++ (Z if 255->0)
beq +
lda rnd2	; a = rnd2
clc
beq ++
+ sec		; c = rnd[1:2] msb
++ jsr calckiller	; calc killer at x(c=msb),y
jsr erasekiller	; erase killer under food
; calc killer
lda rnd6	; a = rnd6
clc
adc #9		; a += 9
tay		; y = rnd6 + 9
ldx rnd3	; x = rnd3
inx		; x++ (Z if 255->0)
beq +
lda rnd4	; a = rnd4
clc
beq ++
+ sec		; c = rnd[3:4] msb
++ jsr calckiller	; calc killer at x(c=msb),y
; set warning timeout
+ lda #warningtimeout	; a = warningtimeout
sta wtime	; set timeout
gstatec_k:	; test killer
plp		; restore flags
bpl gstatec_f	; jump if not killer collision
; killer collision
; set state to 0
lda #0
sta intstate	; interrupt does nothing
lda #2
sta $d020	; set border red
; check score and highscore
lda hscore	; a = high score
cmp score	; check if score>highscore
bcs ++		; jump if not
; print high score
lda #<gothighscoretext
sta strptrl
lda #>gothighscoretext
sta strptrh
ldx #16
ldy #0
jsr printstr
; update highscore
lda score
sta hscore
lda scoretext+0
sta highscoretext+0
lda scoretext+1
sta highscoretext+1
lda scoretext+2
sta highscoretext+2
jmp +++		; jump
; print game over
++ lda #<gameovertext
sta strptrl
lda #>gameovertext
sta strptrh
ldx #16
ldy #0
jsr printstr
; wait for fire (falling edge)
+++ jsr waitfirej
lda #0
sta $d020	; set border black
; blank screen
lda #$2b
sta $d011
; goto start screen
jmp startscreen
gstatec_f:
lda #2
sta intstate	; next state = 2
-	cmp intstate
	beq -	; wait for state change
lda $d01f	; clear sprite-data collision
lda $d01e	; clear sprite-sprite collision
lda #2
sta intstate	; next state = 2
jmp gstatea	; back to state a, read joystick


; --- Interrupt routines

; - IRQ
; Interrupt states:
; $x0 - do nothing
; $01 - update random numbers
;     - check collisions:
;	- if none,   state = $02
;	- if food,   state = $40
;	- if killer, state = $80
;	- if both,   state = $c0
; $02 - update sprite positions, set state = $01
;
int:
lda #$0f	; a = $f
and intstate	; a = intstate & $f
bne + 
jmp int_return	; if state = $x0, return
+ cmp #2
bne + 
jmp int_sprites	; if state = 2, update sprites
; state $01: update "random" numbers
+ clc
lda #13
adc rnd1
sta rnd1
bcc +
inc rnd2	; rnd[1:2] += 13
+ clc
lda #23
adc rnd3
sta rnd3
bcc +
inc rnd4	; rnd[3:4] += 23
+ inc rnd5	; rnd5 ++
clc
lda #29
adc rnd6	; rnd6 += 29
sta rnd6
; set numbers within limits
; rnd[1:2] = 0..306
lda rnd2
beq +		; jump if msb = 0
lda rnd1
sec
sbc #<306	; a = rnd1-306 (lsb)
bcc +		; jump if rnd[1:2]<306
sta rnd1	; rnd1 -= 306 (lsb)
lda #0
sta rnd2	; rnd[1:2] = rnd[1:2] mod 306
; rnd[3:4] = 0..306
+ lda rnd4
beq +		; jump if msb = 0
lda rnd3
sec
sbc #<306	; a = rnd3-306 (lsb)
bcc +		; jump if rnd[3:4]<306
sta rnd3	; rnd3 -= 306 (lsb)
lda #0
sta rnd4	; rnd[3:4] = rnd[3:4] mod 306
; rnd5 = 0..180
+ lda rnd5
sec
sbc #180	; a = rnd5-180
bcc +		; jump if rnd5<180
sta rnd5	; rnd5 = rnd5 mod 180
; rnd6 = 0..180
+ lda rnd6
sec		
sbc #180	; a = rnd6-180
bcc +		; jump if rnd6<180
sta rnd6	; rnd6 = rnd6 mod 180
; state $01: check collisions
+ ldy #$00	; next state = $00
lda $d01e	; sprite-sprite collision
tax		; save to x
and #$08	; test food
beq ++		; skip if no collision
; test pallo
txa		; a = sprite-sprite collision
and #$07	; test pallo collision
beq ++		; skip if no collision
; test warning (ignore if food+pallo+warning)
txa		; a = sprite-sprite collision
and #$10	; test warning collision
bne ++		; skip if collision
ldy #$40	; next state = $40
++ lda $d01f	; sprite-data collision
and #$07	; test pallo
beq +		; skip if no collision
tya		; a = next state
ora #$80	; next state |= $80
tay		; y = next state
+ cpy #$00	; if next state = 0
bne +		; jump if collisions
ldy #$02	; next state = $02
+ sty intstate	; set next state
jmp int_return	; return
; state $02: update sprites
int_sprites:
; pallo
ldx pallo1x
lda pallo1y
stx $d000
sta $d001
stx $d002
sta $d003
stx $d004
sta $d005
; food
ldx foodx
lda foody
stx $d006
sta $d007
; warning
ldx warningx
lda warningy
stx $d008
sta $d009
; pallo2
;ldx pallo2x
;lda pallo2y
;stx $d00a
;sta $d00b
;stx $d00c
;sta $d00d
;stx $d00e
;sta $d00f
; sprite pos msbs
lda #0
;ora pallo2xh
;asl
;ora pallo2xh
;asl
;ora pallo2xh
;asl
ora warningxh
asl
ora foodxh
asl
ora pallo1xh
asl
ora pallo1xh
asl
ora pallo1xh
sta $d010	; sprite pos msbs
dec intstate	; next state = $01
int_return:
asl $d019	; ACK interrupt (to re-enable it)
pla
tay
pla
tax
pla		; pop y,x and a from stack
rti		; return

; - NMI
;
nmi:
rti		; return


; --- Subroutines

; - clearscreen
;
clearscreen:
ldx #0		; 256 loops
lda #0		; clear
-	sta $6000,x
	sta $6100,x
	sta $6200,x
	sta $6300,x
	sta $6400,x
	sta $6500,x
	sta $6600,x
	sta $6700,x
	sta $6800,x
	sta $6900,x
	sta $6a00,x
	sta $6b00,x
	sta $6c00,x
	sta $6d00,x
	sta $6e00,x
	sta $6f00,x
	sta $7000,x
	sta $7100,x
	sta $7200,x
	sta $7300,x
	sta $7400,x
	sta $7500,x
	sta $7600,x
	sta $7700,x
	sta $7800,x
	sta $7900,x
	sta $7a00,x
	sta $7b00,x
	sta $7c00,x
	sta $7d00,x
	sta $7e00,x
	sta $7ee8,x
	inx
	bne -
rts		; return

; - setscreencolor
; parameters:
; a = screen color (0xfb, f/b=fore/background)
;
setscreencolor:
ldx #0		; 256 loops
-	sta $5c00,x
	sta $5d00,x
	sta $5e00,x
	sta $5ee8,x
	inx
	bne -
rts		; return

; - drawbowders
;
drawborders:
; left & right edge
ldx #0		; 8 loops
--	lda #$61
	sta drawbordersl+1
	lda #$62
	sta drawbordersr+1
	lda #$40
	sta drawbordersl
	lda #$78		; left dest. = (0,1)
	sta drawbordersr	; right dest.= (39,1)
	ldy #24	; 24 loops
- 		lda #$80	; left edge
drawbordersl=*+1
		sta $0000,x	; save to dest.
	 	lda #$01	; right edge
drawbordersr=*+1
		sta $0000,x	; save to dest.
		clc
		lda #$40
		adc drawbordersl 
		sta drawbordersl
		lda #1
		adc drawbordersl+1
		sta drawbordersl+1	; left dest. += 320
		clc
		lda #$40
		adc drawbordersr 
		sta drawbordersr
		lda #1
		adc drawbordersr+1
		sta drawbordersr+1	; right dest. += 320
		dey
		bne -
	inx
	cpx #8
	bne --
; top & bottom edge
lda #$61
sta drawborderst+1
lda #$7e
sta drawbordersb+1
lda #$40
sta drawborderst
lda #$07		; top dest. = (0,1)
sta drawbordersb	; bottom dest.= (0,23)
ldx #40		; 40 loops
- 	lda #$ff	; line
drawborderst=*+1
	sta $0000	; save to dest.
drawbordersb=*+1
	sta $0000	; save to dest.
	clc
	lda #8
	adc drawborderst 
	sta drawborderst
	lda #0
	adc drawborderst+1
	sta drawborderst+1	; left dest. += 8
	clc
	lda #$8
	adc drawbordersb 
	sta drawbordersb
	lda #0
	adc drawbordersb+1
	sta drawbordersb+1	; bottom dest. += 8
	dex
	bne -
rts		; return

; - waitfirej
; returns: 
;  lastjoy
;
waitfirej:
lda joyport	; a = joy
sta lastjoy	; update lastjoy
- 
lda joyport	; a = joy
tax		; save to x
eor lastjoy	; joy xor lastjoy
stx lastjoy	; update lastjoy
and #$10	; test fire
beq -		; jump if no change
txa		; a = joy
and #$10	; test fire
bne -		; jump if rising edge
rts

; - drawbomb
; parameters:
;  x = x-coordinate, c = msb
;  y = y-coordinate
;
drawbomb:
; get tx&ty text coords from x,y
; tx-=3, ty-=3
; ex=tx+6+1, ey=ty+6+1 (end coord+1)
; check limits: 
;  x: <0 -> 0, >39 -> 39
;  y: <1 -> 1, >24 -> 24
txa		; a = x-coord.
ror		; c->bit7
lsr
lsr		; a = x/8, c = "0.5"
adc #-3		; a = a-3 + c (round)
bpl +		; jump if a>0
clc		; c = 0
adc #7		; a+=7
sta drawbombex	; store x end coord
lda #0		; a = 0
sta drawbombtx	; store x start coord
jmp ++		; jump to y coord conversion
+ sta drawbombtx ; store x start coord
clc		; c = 0
adc #7		; a+=7
cmp #40		; check if a>40
bcc +		; jump if a<=40
lda #40		; a = 40
+ sta drawbombex ; store to x end address
++ tya		; a = y-coord.
lsr
lsr
lsr		; a = y/8, c = "0.5"
adc #-3		; a = a-3 + c (round)
bpl +		; jump if a>0
clc		; c = 0
adc #7		; a+=7
sta drawbombey	; store y end coord
lda #1		; a = 1
sta drawbombty	; store y start coord
jmp ++		; jump 
+ bne +		; jump if a!=0
lda #1		; a = 1
+ sta drawbombty ; store y start coord
clc		; c = 0
adc #7		; a+=7
cmp #25		; check if a>25
bcc +		; jump if a<=25
lda #25		; a = 25
+ sta drawbombey	; store to y end address
; bombdest = ty*320+tx*8
++ lda drawbombty	; a = ty
sta bombdesth	; bombdesth = "256*ty"
lda #0		; a=0
lsr bombdesth	; bombdesth = "128*ty", c=lsb
ror 		; c->a,msb
lsr bombdesth	; bombdesth = "64*ty", c=lsb
ror 		; bombdesth:a = 64*ty
sta bombdestl	; bombdest = 64*ty
lda drawbombty	; a = ty
adc bombdesth	; a = ty+bombdesth
sta bombdesth	; bombdest = 320*y
; tmp=8*tx
lda #0		; a=0
ldx drawbombtx	; x = tx
stx tmp		; tmp = tx
asl tmp		; tmp = 2*tx, c=msb
rol		; c->a,lsb
asl tmp		; tmp = 4*tx, c=msb
rol		
asl tmp		; tmp = 8*tx, c=msb
rol		; a:tmp = 8*tx
; bomdest = $6000+320*ty+8*tx
adc bombdesth	; a = bombdesth + "tmph"
sta bombdesth	; charyh = a
lda tmp		; a = tmp
clc		; c = 0
adc bombdestl	; a = bombdestl + tmp
sta bombdestl	; bombdestl = a
sta bombdest2l	; bombdest2l = a
lda #$60	; a = $60 (screenmem msb)
adc bombdesth	; a = $60+bombdesth+c
sta bombdesth	; bombdest  = $6000 + 320*ty + 8*tx
sta bombdest2h	; bombdest2 = $6000 + 320*ty + 8*tx

; for y=ty..ey
drawbombyloop:
ldx #0		; reset dest x offset
lda drawbombtx	; a = bomb x offset
sta drawbombx	; reset bomb x offset

; for x=tx..ex
drawbombxloop:
; make char to print:
;  char = $00
;  if x=0 , set $80 all
;  if x=39, set $01 all
;  if y=1 , or $ff first
;  if y=24, or $ff last
drawbombx=*+1
ldy #$00	; y = bomb x coord
lda #$00	; bomb char line = 0
cpy #0		; check if bomb is at left edge
bne +		; jump if not
ora #$80	; don't erase left edge
+ cpy #39	; check if bomb is at right edge
bne +		; jump if not
ora #$01	; don't erase right edge
+ sta tmpchar+0	; create char
sta tmpchar+1
sta tmpchar+2
sta tmpchar+3
sta tmpchar+4
sta tmpchar+5
sta tmpchar+6
sta tmpchar+7
drawbombty=*+1
ldy #$00	; y = bomb y coord
cpy #1		; check if bomb is at top edge
bne +		; jump if not
lda #$ff	; dont erase top edge
sta tmpchar+0
+ cpy #24	; check if bomb is at bottom edge
bne +		; jump if not
lda #$ff	; dont erase bottom edge
sta tmpchar+7
+ ldy #0	; reset char line counter

; printchar - and version
-	lda tmpchar,y	; a = char line y
bombdestl=*+1
bombdesth=*+2
	and $0000,x	; a &= screen mem
bombdest2l=*+1
bombdest2h=*+2
	sta $0000,x	; screen mem = a
	inx		; x++
	iny		; y++
	cpy #8		; check if y = 8
	bne -		; jump if not
; next x
inc drawbombx		; bomb x ++
lda drawbombx		; a = bomb x
drawbombex=*+1
cmp #$00		; check if bomb x = end bomb x
bne drawbombxloop	; if not, next x
; next y
inc drawbombty		; bomb y ++
lda drawbombty		; a = bomb y
drawbombey=*+1
cmp #$00		; check if bomb y = end bomb y
beq drawbomb_f		; if it is, jump to end
; dest+=320
clc
lda #64
adc bombdestl 
sta bombdestl
sta bombdest2l
lda #1
adc bombdesth
sta bombdesth		
sta bombdest2h	; ...destination += 320
jmp drawbombyloop
drawbomb_f:
rts		; return
drawbombtx !by 0	; start bomb x variable

; - calckiller
; parameters:
;  x = x-coordinate, c = msb
;  y = y-coordinate
; returns:
;  ktemp = killer data
;  kloc(l:h) = killer location
;  kloc2(l:h) = killer location
;
calckiller:
; x&7 -> shifts
txa		; a = x (c = msb)
and #7		; a = x&7
sta kxoff	; kxoff = x&7
; x&$f8 -> x-coordinate
txa		; a = x (c = msb)
ror		; c->a,msb; a = x/2
and #$fc	; a = (x/2)&$fc
tax		; x = (x/2)&$fc
; y&7 -> line offset
tya		; a = y
and #7		; a = y&7
sta kyoff	; kyoff = y&7
; (y/8)*320 -> y-coordinate
tya		; a = y
lsr
lsr
lsr		; a = y/8
tay		; y = y/8
sty kloch	; kloch = "256*y"
lda #0		; a=0
lsr kloch	; kloch = "128*y", c=lsb
ror 		; c->a,msb
lsr kloch	; kloch = "64*y", c=lsb
ror 		; kloch:a = 64*y/8
sta klocl	; kloc = 64*y/8
tya		; a = y/8
adc kloch	; a = y/8+kloch
sta kloch	; kloc = 320*y/8
; kloc = $6000+320*(y/8)+8*(x/8)
txa		; a = (x/2)&$fc
asl		; a = (x/8)*8, c = msb
tax		; x = (x/8)*8
lda #0		; a = 0
adc kloch	; a = kloch + c 
sta kloch	; kloc = 320*y/8 + msb((x/8)*8), c = 0
txa		; a = lsb((x/8)*8)
adc klocl	; a += klocl
sta klocl	; klocl = 320*y/8 + lsb((x/8)*8), c = msb
sta kloc2l	; kloc2l = 320*y/8 + lsb((x/8)*8), c = msb
lda #$60	; a = $60 (screenmem msb)
adc kloch	; a = $60+kloch+c
sta kloch	; kloc = $6000+320*(y/8)+8*(x/8)
sta kloc2h	; kloc2 = $6000+320*(y/8)+8*(x/8)
; clear ktemp
ldx #48		; 48 loops
lda #0		; clear
-	dex
	sta ktemp,x
	bne -
; copy from kdata to ktemp with y offset
kyoff=*+1	; y offset
ldy #0		; y = destination
ldx #0		; x = source
-	lda kdata,x	; a = row 1, line x
	sta ktemp,y	; ktemp line y = a
	lda kdata+16,x	; a = row 2, line x
	sta ktemp+8,y	; ktemp line y = a
	inx		; x++
	iny		; y++
	cpy #8	; if y = 8 then y = 24
	bne +
	ldy #24	; (see ktemp comments)
+	cpx #9	; loop until source line = 9
	bne -
; shift ktemp by x offset
lda kxoff	; load x offset
beq ++		; if x offset = 0, skip shifting
ldx kyoff 	; line counter = y offset
ldy #9		; 9 loops
--	tya	; a = loop counter
kxoff = *+1
	ldy #0	; y = x offset
-			clc		; c = 0
			ror ktemp,x	; 0->ktemp(left) >>1->c
			ror ktemp+8,x	; c->ktemp(mid)  >>1->c
			ror ktemp+16,x  ; c->ktemp(right)>>1->c
			dey		; loop for offset times
			bne -
	inx		; x++
	cpx #8	; if x = 8 then x = 24
	bne +
	ldx #24	; (see ktemp comments)
+	tay	; y = loop counter
	dey	; y--
	bne --
++
rts		; return

; - drawkiller
; parameters:
;  kloc = kloc2 = location to print killer
;  kdata = killer data to print
; notes:
;  if x > 308, this "leaks" into the next line 
;  (or sprite pointers), but they are just OR'd with 0
;
drawkiller:
ldx #0			; 48 loops
-	lda ktemp,x	; a = killer temp data
	klocl=*+1
	kloch=*+2
	ora $0000,x	; a |= screen data
	kloc2l=*+1
	kloc2h=*+2
	sta $0000,x	; screen data = a
	inx		; x++
	cpx #24		; if x=24 (4. char)...
	bne +
	clc
	lda #40
	adc klocl 
	sta klocl
	sta kloc2l
	lda #1
	adc kloch
	sta kloch		
	sta kloc2h	; ...destination += 320-24
+	cpx #48		; loop while x < 48
	bne -
rts			; return

; - erasekiller
; parameters:
;  kloc = kloc2 = location to print killer
;  kdata = killer data to print
; notes:
;  if x > 308, this "leaks" into the next line 
;  (or sprite pointers), but they are just AND'd with 1
;
erasekiller:
; copy locations from drawkiller
lda klocl
sta flocl
lda kloch
sta floch
lda kloc2l
sta floc2l
lda kloc2h
sta floc2h
ldx #0			; 48 loops
-	lda ktemp,x	; a = killer temp data
	eor #$ff	; invert a
	flocl=*+1
	floch=*+2
	and $0000,x	; a &= screen data
	floc2l=*+1
	floc2h=*+2
	sta $0000,x	; screen data = a
	inx		; x++
	cpx #24		; if x=24 (4. char)...
	bne +
	clc
	lda #40
	adc flocl 
	sta flocl
	sta floc2l
	lda #1
	adc floch
	sta floch		
	sta floc2h	; ...destination += 320-24
+	cpx #48		; loop while x < 48
	bne -
rts			; return

; - printscore
; uses: printstrnocalc
;
printscore:
lda #>$6000+8*7
sta charyh
lda #<$6000+8*7
sta charyl
lda #>scoretext
sta strptrh
lda #<scoretext
sta strptrl
jmp printstrnocalc

; - printbombs
; uses: printstrnocalc
;
printbombs:
lda #>$6000+8*38
sta charyh
lda #<$6000+8*38
sta charyl
lda #>bombstext
sta strptrh
lda #<bombstext
sta strptrl
jmp printstrnocalc

; - printstr
; parameters:
;  x = x-coordinate
;  y = y-coordinate
;  strptr(l:h) -> string to print
; assumptions:
;  x = 0..39, y = 0..24
; uses:
;  printchar (chary(l:h),charxl)
;
; - printstrnocalc
; parameters:
;  chary -> where to print (320*y+8*x)
;  strptr(l:h) -> string to print
; assumptions:
;  x = 0..39, y = 0..24
; uses:
;  printchar (chary(l:h),charxl)
;
printstr:
;chary=320*y=256*y+64*y
sty charyh	; charyh = "256*y"
lda #0		; a=0
lsr charyh	; charyh = "128*y", c=lsb
ror 		; c->a,msb
lsr charyh	; charyh = "64*y", c=lsb
ror 		; charyh:a = 64*y
sta charyl	; chary = 64*y
tya		; a = y
adc charyh	; a = y+charyh
sta charyh	; chary = 320*y
;charx=8*x
lda #0		; a=0
stx charxl	; charxl = x
asl charxl	; charxl = 2*x, c=msb
rol		; c->a,lsb
asl charxl	; charxl = 4*x, c=msb
rol		
asl charxl	; charxl = 8*x, c=msb
rol		; a:charxl = 8*x
; chary=$6000+320*y+8*x
adc charyh	; a = charyh + "charxh"
sta charyh	; charyh = a
lda charxl	; a = charxl
clc		; c = 0
adc charyl	; a = charyl + charxl
sta charyl	; charyl = a
lda #$60	; a = $60 (screenmem msb)
adc charyh	; a = $60+charyh+c
sta charyh	; chary = $6000 + 320*y + 8*x
printstrnocalc:	; chary is set
ldy #0		; y = 0
-	; char loop
	strptrl=*+1
	strptrh=*+2
	lda $0000,y	; a = char at strptr+y
	beq +		; if char = 0, leave
	jsr printchar	; print a to chary
	iny		; y++, -> next char
	lda #8
clc
adc charyl	; a = charyl+8, c=msb
sta charyl
lda #0
adc charyh	; a = 0 +charyh+c
sta charyh	; chary->next x-pos.
jmp -
+		
rts		; return

; - printchar
; parameters:
;  chary = where to print (320*y+8*x)
;  a = char (-> charxl=$5300+char*8)
;
printchar:
sta charxl	; charxl = char
lda #0
asl charxl	; charxl = 2*x, c=msb
rol		; c->a,lsb
asl charxl	; charxl = 4*x, c=msb
rol		
asl charxl	; charxl = 8*x, c=msb
rol		; a:charxl = 8*x, tmp = 0
adc #$53	; a:charxl = $5300+char*8
sta charxh
ldx #7		; 8 lines
-		; line loop
	charxl=*+1
	charxh=*+2
	lda $0000,x	; load from char-rom
	charyl=*+1
	charyh=*+2
	sta $0000,x	; store to screen
	dex		; next line
bpl -
rts		; return


; --- Sprites

; ...reused as variables

Sprites	
	; eyes (white)
	; 	     765432107654321076543210
	+SpriteLine %........................ ;1
	+SpriteLine %........................ ;2
	+SpriteLine %........................ ;3
	+SpriteLine %........................ ;4
	+SpriteLine %..#.#.#.#............... ;5
	+SpriteLine %........................ ;6
	+SpriteLine %........................ ;7
	+SpriteLine %........................ ;8
	+SpriteLine %........................ ;9
	+SpriteLine %........................ ;10
	+SpriteLine %........................ ;11
	+SpriteLine %........................ ;12
	+SpriteLine %........................ ;13
	+SpriteLine %........................ ;14
	+SpriteLine %........................ ;15
	+SpriteLine %........................ ;16
	+SpriteLine %........................ ;17
	+SpriteLine %........................ ;18
	+SpriteLine %........................ ;19
	+SpriteLine %........................ ;20
	+SpriteLine %........................ ;21
	!byte 0
	; edges, mouth, eyes (brown)
	; 	     765432107654321076543210
	+SpriteLine %...#####................ ;1
	+SpriteLine %..#.....#............... ;2
	+SpriteLine %##.#...#.##............. ;3
	+SpriteLine %#...#.#...#............. ;4
	+SpriteLine %#..#...#..#............. ;5
	+SpriteLine %#.........#............. ;6
	+SpriteLine %##.#####.##............. ;7
	+SpriteLine %..#.....#............... ;8
	+SpriteLine %...#####................ ;9
	+SpriteLine %........................ ;10
	+SpriteLine %........................ ;11
	+SpriteLine %........................ ;12
	+SpriteLine %........................ ;13
	+SpriteLine %........................ ;14
	+SpriteLine %........................ ;15
	+SpriteLine %........................ ;16
	+SpriteLine %........................ ;17
	+SpriteLine %........................ ;18
	+SpriteLine %........................ ;19
	+SpriteLine %........................ ;20
	+SpriteLine %........................ ;21
	!byte 0
	; ball (food, warning)
	;            765432107654321076543210
	+SpriteLine %...#####................ ;1
	+SpriteLine %..#######............... ;2
	+SpriteLine %###########............. ;3
	+SpriteLine %###########............. ;4
	+SpriteLine %###########............. ;5
	+SpriteLine %###########............. ;6
	+SpriteLine %###########............. ;7
	+SpriteLine %..#######............... ;8
	+SpriteLine %...#####................ ;9
	+SpriteLine %........................ ;10
	+SpriteLine %........................ ;11
	+SpriteLine %........................ ;12
	+SpriteLine %........................ ;13
	+SpriteLine %........................ ;14
	+SpriteLine %........................ ;15
	+SpriteLine %........................ ;16
	+SpriteLine %........................ ;17
	+SpriteLine %........................ ;18
	+SpriteLine %........................ ;19
	+SpriteLine %........................ ;20
	+SpriteLine %........................ ;21
	!byte 0
	
; pallo's body = ball xor eyes xor edges


; --- Sintable

; 256*sin(2*pi*i/256), i = [0,63]

sintable
!byte $00,$06,$0c,$12,$19,$1f,$25,$2b,$31,$38,$3e,$44,$4a,$50,$56,$5c
!byte $61,$67,$6d,$73,$78,$7e,$83,$88,$8e,$93,$98,$9d,$a2,$a7,$ab,$b0
!byte $b5,$b9,$bd,$c1,$c5,$c9,$cd,$d1,$d4,$d8,$db,$de,$e1,$e4,$e7,$ea
!byte $ec,$ee,$f1,$f3,$f4,$f6,$f8,$f9,$fb,$fc,$fd,$fe,$fe,$ff,$ff,$ff


; --- Strings

!ct scr		; C64 screencode
;    |---------0---------0---------0--------|
statustext
!tx "score: 000        pallo        bombs: 00",0
scoretext
!tx "000",0	; x offset 7
bombstext
!tx "00",0	; x offset 38
gameovertext
!tx                 "game over.",0
gothighscoretext
!tx                 "highscore!",0
startscrtext1
!tx "= pallo",0
startscrtext2
!tx "= food",0
startscrtext3
!tx "= warning",0
startscrtext4
!tx "= killer",0
startscrtext5
!tx "use joystick in port 2",0
startscrtext6
!tx "< and > .... rotate pallo",0
startscrtext7
!tx "fire ....... explode bomb",0
startscrtext8
!tx "collect food, avoid collisions.",0
startscrtext9
!tx "a bomb is given every 15 points.",0
startscrtext10
!tx "high score: 000",0
startscrtext11
!tx "by hannu nuotio for c64cgc 2006",0


; --- Bitmaps

pallologo	; 144x88, 1bpp logo
!bin "logo.b"


; --- Killer data

; A killer occupies 2x2 chars.
; Initial data organisation: (read by drawkiller)
; l     r      left    right
;              7654321076543210
; 0     16     ...#####........
; 1     17     ..#######.......
; 2     18     ###########.....
; 3     19     ###########.....
; 4     20     ###########.....
; 5     21     ###########.....
; 6     22     ###########.....
; 7     23  -> ..#######....... top 
; 8     24     ...#####........ bottom
; 9     25     ................
; 10    26     ................
; 11    27     ................
; 12    28     ................
; 13    29     ................
; 14    30     ................
; 15    31     ................

kdata ;76543210
!by   %...#####	; left
!by   %..###### ; 1
!by   %######## ; 2
!by   %######## ; 3
!by   %######## ; 4
!by   %######## ; 5
!by   %######## ; 6
!by   %..###### ; 7
!by   %...##### ; 8
!by   %........ ; 9
!by   %........ ; 10
!by   %........ ; 11
!by   %........ ; 12
!by   %........ ; 13
!by   %........ ; 14
!by   %........ ; 15
!by   %........ ; right
!by   %#.......
!by   %###.....
!by   %###.....
!by   %###.....
!by   %###.....
!by   %###.....
!by   %#.......
!by   %........
!by   %........
!by   %........
!by   %........
!by   %........
!by   %........
!by   %........
!by   %........

; A shifted killer occupies at most 3x2 chars.
; Final data organisation: (by drawkiller)
; l  m  r      left    middle  right
;              765432107654321076543210
; 0  8  16     ...#####................
; 1  9  17     ..#######...............
; 2  10 18     ###########.............
; 3  11 19     ###########.............
; 4  12 20     ###########.............
; 5  13 21     ###########.............
; 6  14 22     ###########.............
; 7  15 23  -> ..#######............... top 
; 24 32 40     ...#####................ bottom
; 25 33 41     ........................
; 26 34 42     ........................
; 27 35 43     ........................
; 28 36 44     ........................
; 29 37 45     ........................
; 30 38 46     ........................
; 31 39 47     ........................
;
; shift down by  (y mod 8) steps (apply offset)
; shift right by (x mod 8) steps (ror loop)
; draw with drawkiller (or-version of printchar)

ktemp = *	; shifted version (48 bytes)
base/pallo.txt · Last modified: 2015-04-17 04:33 (external edit)