pretty6502/aard1.asm

2041 lines
53 KiB
NASM
Executable File

;
; Aardvark
;
; by Oscar Toledo G. (nanochess)
;
; Creation date: Sep/02/2016.
; Revision date: Dec/02/2016. Added holes and playfield mouth/eggs.
; Revision date: Dec/03/2016. Added enemy bitmaps and color.
; Revision date: Dec/04/2016. Tongue can be started/reverted with joystick.
; Added eggs in board.
; Revision date: Dec/06/2016. Tongue rules more close to arcade. Queen ants
; are now fixed and flashing. Counts eaten eggs
; and score. Displays score.
; Revision date: Dec/07/2016. Enemies are filled randomly, also two speeds.
; Aardvark centered. Dots are thicker now (uses
; 2 rows). Aardvark walks slower.
; Revision date: Dec/11/2016. Now is main bank of 8K ROM. Worm appears at
; tongue tip level. Player can eat ants and
; worms.
; Revision date: Dec/12/2016. Enemy collisions now are checked here to avoid
; too many cycles used in display.
; Revision date: Jan/18/2016. Added Ranz des Vaches and Mountain King music.
; Revision date: Jan/19/2016. Corrected lack of feet in aardvark. Added
; tongue touched music. Added sound effects.
; Aardvark exits level when all eggs eaten.
; Remade code for collision of tongue. Corrected
; bug where eating right queen would delete left
; queen.
; Revision date: May/27/2017. Moved all display code to bank 0, this makes it
; to work with Atari Flashback Portable.
; Revision date: Oct/02/2017. Sun moves to left. Counts level.
; Revision date: Oct/08/2017. Added tongue retrain sound effect. Changes hole
; position randomly.
; Revision date: Oct/09/2017. Lives counting. Avoids worm appearing over ant.
; Going down has priority over going left/right
; but tries also left/right. New enemies: red
; ant and caterpillar. Only one worm can appear
; at any moment. Added more difficulty per level.
; Calculates bonus. New enemy: spider.
; Revision date: Oct/10/2017. Solved bug where worm would overwrite spider.
; Solved bug where tongue removed eggs without
; adjusting egg count. Solved bug where 150 points
; sprites wouldn't disappear. Added click sound
; effect for sunset. Added title screen.
; Revision date: Nov/01/2017. Changed holes1-6 to bitmap interpretation.
; Revision date: Nov/02/2017. Moved eggs and tongue to extra RAM (Sara chip).
; Revision date: Nov/03/2017. Renamed level as antHill. Now tongue and eggs
; bitmaps are intermixed (new display kernel).
; Sprites now appear at right places. Now hole
; map is aligned with kernelLst. Updated egg
; count. Configurable X-limit.
; Revision date: Nov/04/2017. Relocated direction bit. Collisions working
; again.
; Revision date: Nov/05/2017. Corrected worm catch. Score resets REFP0/1.
; Collision working again. Supports player
; reflection in display kernel.
;
; Next available label: aa128
; Free label: aa84, aa85
; TODO:
; * Bug: live counting isn't working right.
; * Bug: egg counting isn't working right.
; * Tune collisions.
; * Check if spider is working.
; * Bug: slight bam tone after winning music.
; * Bug: spider is slow to appear or doesn't appear.
; * Handle holes like a bitset instead of coordinate.
; * Allow backtracking (using up)
; * Test in MAME for movement details
; * Clouds (using PF)
; * Maybe new aardvark sprite, maybe multicolor, maybe 48px:
; * Aardvark moving ears.
; * Aardvark sprite sitting when tongue is touched.
; * Aardvark walking.
; * Options in title screen.
; * Starting level.
; * Message "Press start" in title screen.
; * Intermediate screen (losing live and completing level):
; ants
; x worms
; * 10 = bonus
; * Game over (shown below intermediate screen)
; * Give an extra live each 20000 points.
; Differences versus arcade:
; * Arcade has 8 tunnels, we have 7.
; * Red ant appears at tunnel 4, in arcade is 5.
; * Centipede appears at tunnel 5, in arcade is 6.
; * Worm can appear at tunnel 7 in arcade (we have no space in screen)
; Things in unreleased ROM:
; * Sun timer using a digit counter.
; * White line after first bottom section
; * Level and time in second bottom section (separated)
; Game in brief:
; * Move tongue in joystick direction.
; * Press button to retrain tongue.
; * Bugs appear randomly on both sides.
; * Bug touching tongue -> lost life.
; * Tongue touching bug from behind -> score.
; * Spider descends from top to bottom, if touch tip -> lost life.
; * If tongue eats queen -> all enemies in board disappear.
; * Eating all dots -> level change.
; * Each level has different configuration of holes in floors.
; * Ant: 100 points, appears starting in level 1, tunnels 1-4
; * Red ant: 150 points, appears starting in level 2, tunnel 5
; * Centipede: 150 points, appears starting in level 3, tunnel 6
; * Worm: 200 points, appears always at level of tongue.
; * Only enemy that can appear at tunnel 7.
; * Tongue cannot move in tunnel 8, nor there are points, only can eat queen.
; * On restarting level the holes configuration changes.
; * On restarting level preserves darkness even if the initial animation is
; done again.
; * Sun starts more at left per level. Since level 22 always starts barely
; some pixels from left.
; * Extra lives each 20000 points
processor 6502
include aardm.asm
;
; Set object in X
; A = X position
; First argument = Object to position (0=P0, 1=P1, 2=M0, 3=M1, 4=BALL)
;
MAC set_x_position
sta WSYNC ; 0- Start line synchro
sec ; 2- Set carry flag (avoids it in loop)
.AE2: sbc #15 ; 4- Uses required time dividing A by 15
bcs .AE2 ; 6/7 - 11/16/21/26/31/36/41/46/51/56/61/66
tay ; 8
lda fine_adjustment-$f1,y; 13 - Eats 5 cycles crossing page
sta HMP0+{1}
nop
sta RESP0+{1} ; 21/26/31/36/41/46/51/56/61/66/71 - "big" positioning
ENDM
org $f000 ; ROM start address (4K)
REPEAT 256
.byte $4f
REPEND
START:
sta bank1 ; Ghost
sei ; Disable interruptions
cld ; Disable decimal mode
jmp START2
ba0: sta bank0
jmp 0 ; Ghost
sta bank1 ; Ghost
jmp ba1
ba2: sta bank0
jmp 0 ; Ghost
sta bank1
jmp ba3
START2:
ldy rand
; Clean up the memory
ldx #$ff ; Load X with $FF...
txs ; ...copy to stack pointer
lda #0 ; Load zero in accumulator
AE1: sta 0,X ; Save in address 0 plus X
dex ; Decrement X
bne AE1 ; Repeat until X is zero.
sta SWACNT ; Allow to read joysticks
sta SWBCNT ; Allow to read buttons
tsx ; ldx #$ff
stx prev_button
sty rand
lda rand
sta level_seed
title_screen:
lda #20
sta temp1
jmp ba2
ba3:
lda #0
sta antHill
lda #4
sta lives
lda #0
sta score
sta score+1
sta score+2
ldx #tongue_size*2-12
aa124: lda #0
sta tongue1+W,x
sta tongue1+W+1,x
sta tongue1+W+2,x
sta tongue1+W+3,x
sta tongue1+W+4,x
sta tongue1+W+5,x
txa
sec
sbc #12
tax
bpl aa124
;
; Goes to next level
;
next_level:
inc antHill
inc level_seed
;
; Setup starting sun position
;
lda antHill
asl
bmi aa82
asl
bpl aa83
aa82: lda #$80
aa83: eor #$ff
adc #$98
sta sun_pos
lda #$00
sta COLUBK ; Background color
; VERTICAL_SYNC
lda #2
sta VSYNC ; Start vertical synchro
sta WSYNC ; Wait for 3 lines
sta WSYNC
sta WSYNC
;
lda #43
sta TIM64T
lda #0
sta VSYNC ; Stop vertical synchro
ldx #tongue_size*2-12
aa29: lda #0
sta tongue1+W,x
sta tongue1+W+1,x
sta tongue1+W+2,x
sta tongue1+W+3,x
sta tongue1+W+4,x
sta tongue1+W+5,x
cpx #0
beq .+4
lda #$aa
sta eggs1+W,x
sta eggs1+W+2,x
sta eggs1+W+3,x
sta eggs1+W+5,x
lsr
sta eggs1+W+1,x
sta eggs1+W+4,x
txa
sec
sbc #12
tax
bpl aa29
lda #7*20
sta eggs
;
; Setup queen ants
;
lda #sprite_queen_ant+ENEMY_DIR_MASK
sta enemy0_t
sta enemy8_t
lda #$2e
sta enemy0_x
lda #$66
sta enemy8_x
jmp aa73
restart_level:
inc level_seed
lda #$00
sta effect0
sta effect1
sta ants_eaten
sta worms_eaten
sta COLUBK ; Background color
; VERTICAL_SYNC
lda #2
sta VSYNC ; Start vertical synchro
sta WSYNC ; Wait for 3 lines
sta WSYNC
sta WSYNC
;
lda #43
sta TIM64T
lda #0
sta VSYNC ; Stop vertical synchro
aa73:
lda #1 ; Ranz des Vaches (Rossini)
sta tracker
lda #1 ; Start immediately
sta tracker_c
lda #6
sta aa_x_pos
lda #1
sta timer
lda #0
sta filling
sta flags
;
; Delete tongue and delete also any eggs under
;
ldx #tongue_size*2-12
aa69:
ldy #5
aa80: lda tongue1+R,x
eor #$ff
and eggs1+R,x
sta eggs1+W,x
lda #0
sta tongue1+W,x
inx
dey
bpl aa80
txa
sec
sbc #18
tax
bpl aa69
lda #0
sta enemy1_t
sta enemy2_t
sta enemy3_t
sta enemy4_t
sta enemy5_t
sta enemy6_t
sta enemy7_t
sta enemy9_t
sta enemy10_t
sta enemy11_t
sta enemy12_t
sta enemy13_t
sta enemy14_t
sta enemy15_t
sta holeCols
sta holeCols+1
sta holeCols+2
sta holeCols+3
sta holeCols+4
sta holeCols+5
sta holeCols+6
sta holeCols+7
lda #$ff
sta tip_y
jmp aa75
main_loop:
lda #$00
sta COLUBK ; Background color
; VERTICAL_SYNC
lda #2
sta VSYNC ; Start vertical synchro
sta WSYNC ; Wait for 3 lines
sta WSYNC
sta WSYNC
;
lda #43
sta TIM64T
lda #0
sta VSYNC ; Stop vertical synchro
aa75:
; Nanochess' mini sound effects player
ldx tracker
bne ef4
lda effect0
beq ef0
tax
lda sound_effect,x
bne ef1
sta effect0
beq ef0
ef1: sta AUDF0
lda sound_effect+1,x
sta AUDC0
lsr
lsr
lsr
lsr
inx
inx
stx effect0
ef0: sta AUDV0
lda effect1
beq ef2
tax
lda sound_effect,x
bne ef3
sta effect1
beq ef2
ef3: sta AUDF1
lda sound_effect+1,x
sta AUDC1
lsr
lsr
lsr
lsr
inx
inx
stx effect1
ef2: sta AUDV1
bpl tr0
; Nanochess' mini tracker
ef4:
ldx tracker
beq tr1
dec tracker_c
bne tr3
lda music-1,x
bne tr2
sta tracker
beq tr1
tr2: and #$1f
asl
tay
lda music_notes-2,y
sta AUDC0
lda music_notes-1,y
sta AUDF0
lda music-1,x
lsr
lsr
and #$38
sta tracker_c
lda music,x
asl
tay
lda music_notes-2,y
sta AUDC1
lda music_notes-1,y
sta AUDF1
inx
inx
stx tracker
lda #$3f
sta tracker_v
tr3: dec tracker_v
lda tracker_v
lsr
lsr
cpx #43
bcs tr1
lda tracker_v
and #$03
bne tr4
lda #$02
tr4: ora #$0c
tr1: sta AUDV0
sta AUDV1
tr0:
lda aa_x_pos
cmp #$0f ; Corrects left side X-pos, for some reason it breaks.
bcs *+4
sbc #2
set_x_position 0 ; Player 0
; ldx #1 ; Player 1
lda sun_pos
set_x_position 1 ; Player 1
lda #84
set_x_position 2 ; Missile 0
lda #$20
sta NUSIZ0
sta NUSIZ1
jsr build_hole_map
lda #$00
sta GRP0
sta GRP1
sta COLUPF
lda #$20
sta CTRLPF
jmp ba0
ba1:
;
; Score zone
;
sta WSYNC ; 0
ldx #$00 ; 3
stx COLUBK ; 5 Background color
stx GRP0 ; 8
stx GRP1 ; 11
stx REFP0 ; 14
stx REFP1 ; 17
sta en5 ; 20
lda score ; 23
and #$0f ; 26
asl ; 28
asl ; 30
asl ; 32
sta en4 ; 34
lda score ; 37
lsr ; 40
and #$78 ; 42
sta en3 ; 44
lda #$21 ; 47
sta CTRLPF ; 49
lda #lives_color ; 52
sta COLUPF ; 54
ldx lives ; 57
cpx #7 ; 60
bcc aa88 ; 62
ldx #7 ; 64
aa88:
lda lives_pf,x ; 66
sta WSYNC ; 71
sta PF0
lda lives_pf+8,x
sta PF1
lda lives_pf+16,x
sta PF2
lda score+1 ; 35
and #$0f ; 38
asl ; 40
asl ; 42
asl ; 44
sta en2 ; 46
lda score+1 ; 49
lsr ; 52
and #$78 ; 54
sta en1 ; 56
lda score+2 ; 59
and #$0f ; 62
asl ; 64
asl ; 66
asl ; 68
sta en0 ; 70
ldx #0
lda #score_color ; 73
jmp $f400 ; 75
org $F400
mp0:
sta WSYNC
stx GRP0
stx GRP1
ldy #numbers>>8 ; 8
sty en0+1 ; 11
sty en1+1 ; 14
sty en2+1 ; 17
sty en3+1 ; 20
sty en4+1 ; 23
sty en5+1 ; 26
sta COLUP0 ; 29
sta COLUP1 ; 32
lda #$03 ; 35 3 copies together
ldx #$f0 ; 37
stx RESP0 ; 39
stx RESP1 ; 42
stx HMP0 ; 45
sta NUSIZ0 ; 48
sta NUSIZ1 ; 51
lsr ; 53
sta VDELP0 ; 56
sta VDELP1 ; 59
lsr
sta HMP1
sta WSYNC ; 62
sta HMOVE ; 3
lda #4
sta temp2
mp1: ldy temp2 ; 2
lda (en0),y ; 7
sta GRP0 ; 10
sta WSYNC ; 13 + 61 = 76
lda (en1),y ; 5
sta GRP1 ; 8
lda (en2),y ; 13
sta GRP0 ; 16
lda (en3),y ; 21
sta temp1 ; 24 Write (this depends on being at "root" stack pos)
lda (en4),y ; 29 (and of course not being called)
tax ; 31
lda (en5),y ; 36
tay ; 38
lda temp1 ; 41 Read
sta GRP1 ; 44
stx GRP0 ; 47
sty GRP1 ; 50
sta GRP0 ; 53
dec temp2 ; 58
bpl mp1 ; 60/61
mp3:
; Looks for code spanning page
if (mp1&$ff00)!=(mp3&$ff00)
lda megabug3 ; :P
endif
echo "mp0 ",mp0," mp1 ",mp1," mp3 ",mp3
;
; End of graphics (204 lines)
;
ldx #$00
lda #2
sta WSYNC
sta VBLANK
stx VDELP0
stx VDELP1
stx GRP0
stx GRP1
stx PF0
stx PF1
stx PF2
;
; Start overscan timer
;
lda #43 ; 37 lines * 76 = 2812 cycles / 64 = 43.9375
sta TIM64T
lda flags
and #$03
cmp #$02 ; Tongue touched?
bne aa67
jmp wait_overscan
aa67: lda eggs
bne aa70
ldx aa_x_pos
cpx #52
bne aa71
inc aa_x_pos
lda #43 ; Mountain King (Grieg)
sta tracker
lda #1
sta tracker_c
lda #0
sta filling
sta flags
ldx #tongue_size*2-1
lda #0
aa72: sta tongue1+W,x
dex
bpl aa72
sta enemy0_t
sta enemy1_t
sta enemy2_t
sta enemy3_t
sta enemy4_t
sta enemy5_t
sta enemy6_t
sta enemy7_t
sta enemy8_t
sta enemy9_t
sta enemy10_t
sta enemy11_t
sta enemy12_t
sta enemy13_t
sta enemy14_t
sta enemy15_t
sta holeCols
sta holeCols+1
sta holeCols+2
sta holeCols+3
sta holeCols+4
sta holeCols+5
sta holeCols+6
sta holeCols+7
lda #$ff
sta tip_y
aa71: jmp aa34
aa70: lda flags
and #$fc
sta flags
;
; Check for collisions of enemies versus tongue (playfield pixels)
;
ldx #15
aa53: lda enemy0_t,x
tay
cmp #non_interactive_sprites
bcc aa86
cpx #8
bcs aa45
lda cxLst,x
and #$20
beq aa86 ; No, jump
bne aa127
aa45: lda cxLst-8,x
asl
bpl aa86
aa127: tya
and #$f0
cmp #sprite_spider
beq aa106
cmp #sprite_worm ; Is it a worm?
beq aa55
bne aa87
aa86:
dex
bpl aa53
jmp aa78
;
; Spider
; * Kills if touches tongue tip
;
aa106:
txa
and #$07
cmp tip_y ; Is it at same level than tongue?
bne aa86 ; No, jumps
lda enemy0_x,x
tay
sbc #3
lsr
lsr
cmp tip_x
beq aa56sc
tya
clc
adc #10
lsr
lsr
cmp tip_x
beq aa56sc
bne aa86
aa87:
;
; Ant:
; * Eaten if tongue tip.
; * Kills if it touch any other part of tongue.
;
txa
and #$07
cmp tip_y ; Is it at same level than tongue?
bne aa56sc ; No, kills
lda enemy0_x,x
sbc #3
tay
lsr
lsr
cmp tip_x
beq aa57
bcs aa56
tya
clc
adc #10
lsr
lsr
cmp tip_x
beq aa57
bcc aa56
aa57: lda enemy0_t,x
cmp #sprite_queen_ant+$20
bcs aa125
cmp #sprite_queen_ant
bcs aa59
aa125: cmp #pricey_sprites ; Red ant and caterpillar
bcs aa97
sed
lda ants_eaten
adc #1
sta ants_eaten
cld
lda #sprite_explosion; Goodbye ant
.byte $2c ; BIT opcode to jump
aa97: lda #sprite_150
ldy #11
bne aa79
aa56sc: jmp aa56
aa59: jsr clear_enemies
ldy #33
aa79: sty effect1
bne aa60
;
; Worm:
; * Eaten if tongue tip from behind.
; * Kills only if tongue tip in front.
;
aa55: txa
and #$07
cmp tip_y
bne aa54
lda enemy0_x,x
tay
sbc #3
lsr
lsr
cmp tip_x
beq aa58
bcs aa54
tya
clc
adc #10
lsr
lsr
cmp tip_x
beq aa58
bcc aa54
aa58: lda tip_dir
beq aa56
lsr ; $ff left $00 right
eor enemy0_t,x
and #ENEMY_SPEED_MASK
bne aa56
lda flags
and #~FLAGS_WORM
sta flags
inc worms_eaten
lda #20
sta effect1
lda #sprite_200 ; 200 points
aa60: sta enemy0_t,x
bne aa54
; Kill
aa56: lda flags
and #$fc
ora #$01
sta flags
aa54:
dex
bmi aa78
jmp aa53
aa78:
lda flags
and #$03
beq aa52
jmp wait_overscan
;
; Invoke an enemy
;
aa52:
dec timer
beq aa95
jmp aa14
aa95:
jsr random_proc ; Get a random number (just because :P)
tay ; Save it
and #$0e ; Restart timer
ora #$01
sta timer
lda antHill ; Starts at 1
clc
adc #$03 ; Level 1 - fills 4 tunnels, 2 - 5 t., 4 and so- 6 t.
cmp #$06 ; No more than 6 tunnels
bcc aa92
lda #$06
aa92: asl
sta temp1
lda filling
cmp temp1
bcc aa102
aa103: jmp aa8
aa102:
and #$0e
lsr
eor #$07
tax
cmp #$07
bne aa111
lda enemy8_t,x
bne aa111
lda #FLAGS_SPIDER
bit flags
bne aa111
lda sun_pos
cmp #8 ; Now it's night?
beq aa110 ; No, jump
aa111: lda enemy0_t,x ; There is space for a common enemy?
beq aa12 ; Yep, jump.
aa110: lda enemy8_t,x ; There is space for a worm/spider?
bne aa103 ; No, jump
cpx #0 ; Top tunnel?
bne aa101 ; No, jump
lda sun_pos
cmp #8 ; Now it's night?
bne aa101 ; No, jump
lda #FLAGS_SPIDER
bit flags ; We have already the spider?
bne aa101 ; Yes, jump
ora flags
sta flags
lda #ENEMY_MAX_X
sta enemy8_x,x
tya
and #ENEMY_SPEED_MASK
ora #sprite_spider
sta enemy8_t,x
bne aa8
aa101:
txa
and #$07
cmp tip_y
bne aa103
lda #FLAGS_WORM
bit flags ; Already a worm in screen?
bne aa8 ; Yes, jump
ora flags
sta flags
tya
and #$40
beq aa37
lda enemy0_x,x
cmp #40
bcc aa90
aa91: lda #ENEMY_MIN_X
sta enemy8_x,x
tya
and #ENEMY_SPEED_MASK
ora #sprite_worm+ENEMY_DIR_MASK
sta enemy8_t,x
bne aa8
aa37: lda enemy0_x,x
cmp #129
bcs aa91
aa90: lda #ENEMY_MAX_X
sta enemy8_x,x
tya
and #ENEMY_SPEED_MASK
ora #sprite_worm
sta enemy8_t,x
bne aa8
aa12: tya
and #$40
beq aa15
lda #ENEMY_MIN_X
sta enemy0_x,x
tya
and #ENEMY_SPEED_MASK
ora enemies_going_right,x
sta enemy0_t,x
bne aa8
aa15: lda #ENEMY_MAX_X
sta enemy0_x,x
tya
and #ENEMY_SPEED_MASK
ora enemies_going_left,x
sta enemy0_t,x
; bne aa8
aa8: ldx antHill
cpx #32
bcc aa93
ldx #31
aa93: lda filling
clc
adc #2
cmp refilling,x
bne aa94
lda #0
aa94: sta filling
aa14:
;
; Sun animation
;
lda frame
and #$1f ; Each 32 frames
bne aa81
lda sun_pos
cmp #8
beq aa81
dec sun_pos ; Move sun left by one pixel
cmp #9
bne aa81
lda #129 ; Click effect
sta effect0
aa81:
;
; Enemy animation and movement
;
ldy #0
lda frame
and #$07 ; Enemies change animation frame each 8 frames
bne aa11
ldy #8
aa11: and #$03 ; Enemies move each 4 frame
beq aa117
jmp aa43
aa117:
ldx #$0f
aa10:
lda enemy0_t,x ; Active enemy?
bne aa118 ; Yes, jump
aa120: dex
bpl aa10
jmp aa43
;
; Check first for brief sprites (explosion, 150 and 200 points)
;
aa118: cmp #non_interactive_sprites
bcs aa39
aa49: inc enemy0_t,x
cmp #sprite_150+$03
beq aa96
cmp #sprite_200+$03
beq aa46
cmp #sprite_200_spider+$03
beq aa46
cmp #sprite_explosion+$03
bne aa38sd
lda #$10 ; 100 points
.byte $2c ; BIT opcode to jump
aa46: lda #$20 ; 200 points
.byte $2c ; BIT opcode to jump
aa96: lda #$15 ; 150 points
jsr score_points
lda #$00
sta enemy0_t,x
aa38sd: jmp aa38
;
; All other sprites
;
aa39: and #$f0
cmp #sprite_spider
bne aa108
;
; Spider handling
;
lda tip_y ; Tongue tip active?
bmi aa120 ; No, jump (spider stays quiet)
txa ; Get vertical position of spider
and #$07
cmp tip_y ; Comparison with tongue tip vertical position.
beq aa109 ; Same vertical position? yes, jump
bcs aa120 ; Jump if spider deeper than tongue tip. It shouldn't happen
stx temp1
tax
lda holeCols,x ; Check if tongue goes thru a hole !!!
lsr
bcs aa112
lsr
bcs aa113
lsr
bcs aa114
lda #0
.byte $2c ; BIT opcode to jump
aa114: lda #8
.byte $2c ; BIT opcode to jump
aa113: lda #16
.byte $2c ; BIT opcode to jump
aa112: lda #24
clc
adc kernelLst,x
tax
lda hole_pos,x ; Now get the X-coordinate for hole
ldx temp1
sec ; There's an X-coordinate, center spider over it
sbc #2
jmp aa116
;
; Spider at same level than tongue tip
;
aa109: lda tip_x
asl
asl
beq aa116
sbc #1
aa116: sbc enemy0_x,x ; Take a decision of direction to move
beq aa119 ; At target position? yes, jump
bcc aa44
bcs aa40
;
; Try to lower spider by one level
;
aa119: cpx #1 ; Is spider at bottom-most position?
beq aa41 ; Yes, jump, stay quiet
cpx #9
beq aa41
lda enemy0_t-1,x ; Is it busy the next enemy slot?
bne aa41 ; Yes, jump, stay quiet
lda enemy0_x,x ; Copy X position
sta enemy0_x-1,x
lda enemy0_t,x ; Copy type
sta enemy0_t-1,x
lda #0 ; Erase spider from old slot
sta enemy0_t,x
beq aa41
;
; Ant, red ant, worm or centipede
;
aa108:
cmp #sprite_queen_ant
beq aa38
cmp #sprite_queen_ant+$10
beq aa38
lda enemy0_t,x
and #ENEMY_SPEED_MASK ; Fast?
beq aa44
lda frame
and #$04
aa38sc: bne aa38
aa44:
lda enemy0_t,x
and #ENEMY_DIR_MASK ; Goes to left?
bne aa40 ; No, jump
dec enemy0_x,x
lda enemy0_x,x
cmp #ENEMY_MIN_X ; Reached left limit?
bne aa41 ; No, jump
aa42:
lda enemy0_t,x
and #$f0
cmp #sprite_worm
bne aa98
lda flags
and #~FLAGS_WORM
sta flags
aa98: cmp #sprite_spider ; It could happen *sigh*
bne aa107
lda flags
and #~FLAGS_SPIDER
sta flags
aa107: lda #0
sta enemy0_t,x
beq aa38
aa40:
inc enemy0_x,x
lda enemy0_x,x
cmp #ENEMY_MAX_X ; Reached right limit?
beq aa42 ; Yes, jump
aa41:
tya
eor enemy0_t,x ; Changed animation frame if required
sta enemy0_t,x
aa38: dex
bmi aa43
jmp aa10
aa43:
;
; Queen ant flashing
;
lda frame
and #$01
bne aa34
lda enemy0_t
beq aa32
cmp #non_interactive_sprites
bcs aa51
adc #1
cmp #sprite_1000+8
bne aa32
jsr score_points_2 ; 1000 points
lda #0
beq aa32
aa51: adc #$07
cmp #sprite_queen_ant+$20
bcc aa32
sbc #$20
aa32: sta enemy0_t
lda enemy8_t
beq aa33
cmp #non_interactive_sprites
bcs aa50
adc #1
cmp #sprite_1000+8
bne aa33
jsr score_points_2 ; 1000 points
lda #0
beq aa33
aa50: adc #$07
cmp #sprite_queen_ant+$20
bcc aa33
sbc #$20
aa33: sta enemy8_t
aa34:
;
; Count frame, step on random generator
;
inc frame
jsr random_proc
;
; Aardvark enters game
;
ldx aa_x_pos
cpx #52
beq aa7
lda frame
and #$07
bne aa31
inc aa_x_pos
cpx #51
bne aa31
; Start tongue
lda #$02
sta holeCols+7
ldx #19
stx tip_x
lda #7
sta tip_y
lda #0
sta tip_dir
jsr point_egg
ldx tip_x
lda tip_y
jsr draw_block
aa31:
lda frame
and #$07
bne aa4
lda aa_offset
eor #$28
sta aa_offset
aa4:
jmp aa20
aa7:
lda #0
jsr fire_button ; Fire button pressed?
bpl aa22 ; No, jump
ldx tip_x ; Get tongue coordinates
lda tip_y
cpx #19
bne aa19
cmp #7
beq aa123 ; Is it at base? yes, jump without doing anything
aa19:
jsr clear_block
lda effect0
cmp #128
bcs aa122
cmp #66
bcs aa121
aa122:
lda #66
sta effect0
aa121: ldx tip_x
beq aa23
dex
lda tip_y
jsr check_block
bne aa24
inx
aa23: cpx #39
beq aa25
inx
lda tip_y
jsr check_block
bne aa24
aa25: ldx tip_y
lda #$00
sta holeCols,x
inc tip_y
jmp aa20
aa24: stx tip_x
jmp aa20
aa123: jmp aa28
aa22:
jsr build_hole_map
lda SWCHA
; Note #$10 isn't used (going up)
and #$20 ; Going down?
beq aa17 ; Yes, jump
aa18: lda SWCHA
bmi aa16 ; Going right? No, jump
lda tip_y
bmi aa28
beq aa28 ; Last tunnel? Yes, cannot move
lda frame
lsr
bcc aa28
ldx tip_x
cpx #39
beq aa28
inx
aa26: lda tip_y
jsr check_block
bne aa30
txa
sec
sbc tip_x
sta tip_dir
stx tip_x
lda tip_y
jsr point_egg
ldx tip_x
lda tip_y
jsr draw_block
jmp aa20
aa30: txa
pha
ldx tip_x
lda tip_y
jsr clear_block
pla
sta tip_x
aa28: jmp aa20
aa16: rol ; Going left?
bmi aa20
lda tip_y
bmi aa20
beq aa20 ; Last tunnel? Yes, cannot move
lda frame
lsr
bcc aa20
ldx tip_x
beq aa20
dex
bpl aa26
;
; Going down
;
aa17: ldx tip_y ; Get row of tongue tip
bmi aa18 ; Invalid? Yes, jump to check for right/left
beq aa18 ; Vertical limit? Yes, jump to check for right/left
lda kernelLst-1,x
tax
lda tip_x ; Tongue tip at 0?
beq aa18 ; Jump to check for right/left
cmp hole_pos,x
beq aa126
cmp hole_pos+8,x
beq aa27
cmp hole_pos+16,x
beq aa115
cmp hole_pos+24,x
bne aa18 ; No hole, so jump to check for right/left
ldy #$01
.byte $2c ; BIT opcode to jump
aa115: ldy #$02
.byte $2c ; BIT opcode to jump
aa126: ldy #$08
.byte $2c ; BIT opcode to jump
aa27: ldy #$04
tya
ldx tip_y
dex
ora holeCols,x
sta holeCols,x
stx tip_y
txa
ldx tip_x
jsr point_egg
ldx tip_x
lda tip_y
jsr draw_block
lda #0
sta tip_dir
aa20:
wait_overscan:
lda INTIM
bne wait_overscan
sta WSYNC
sta WSYNC
lda aa_x_pos
cpx #135
bne aa74
jsr bonus_screen
jmp next_level
aa74:
lda flags
and #$03
cmp #$02 ; Has finished tongue color changing animation?
beq aa68 ; Yes, jump
jmp main_loop ; Continue with main loop
aa68: dec lives
jsr bonus_screen
lda lives
bmi aa89
jmp restart_level ; Restart level
aa89: jmp title_screen
;
; Bonus screen
;
bonus_screen:
ldx worms_eaten
beq aa99
aa100:
lda ants_eaten
jsr score_points
dex
bne aa100
aa99:
rts
;
; Run random number generator
;
random_proc:
;
; Random number generator
;
lda rand
sec
ror
eor frame
ror
eor rand
ror
eor #9
sta rand
rts
;
; Check for fire button
;
fire_button_single:
lda INPT4
eor #$ff
tax
eor prev_button
stx prev_button
bpl fire_button1
txa
fire_button1:
rts
fire_button:
lda INPT4
eor #$ff
sta prev_button
rts
;
; Calculate memory zone for tongue block
; a = zone (0-7)
;
calc_zone:
asl ; x2
asl ; x4
sta en0
asl ; x8
adc en0 ; x12
adc #tongue1
sta en0
adc #<R
sta en1
lda #>W
sta en0+1
sta en1+1
rts
;
; Check for tongue block
;
; a = zone (0-5)
; x = x pixel (0-39)
;
check_block:
jsr calc_zone
lda pixel_to_byte,x
tay
lda (en1),y
and pixel_to_bit,x
rts
;
; Clear enemies (used when eating queen ant)
;
clear_enemies:
txa
pha
ldx #9
aa61: lda enemy0_t,x
cmp #non_interactive_sprites
bcc aa62
and #$f0
cmp #sprite_worm
beq aa63
cmp #sprite_spider
beq aa104
cmp #pricey_sprites
bcs aa64
lda #sprite_explosion
.byte $2c ; BIT opcode to jump
aa63: lda #sprite_200
.byte $2c ; BIT opcode to jump
aa64: lda #sprite_150
.byte $2c ; BIT opcode to jump
aa104: lda #sprite_200_spider
sta enemy0_t,x
cmp #sprite_200_spider
bne aa105
lda flags
and #~FLAGS_SPIDER
sta flags
aa105:
cmp #sprite_200 ; Only a worm gives a 200 points bonus
bne aa62
lda flags
and #~FLAGS_WORM
sta flags
aa62: dex
bpl aa61
pla
tax
lda #sprite_1000
rts
;
; Give points per egg eaten
;
; a = zone (0-7)
; x = x pixel (0-39)
;
point_egg:
cmp #0
beq aa35
jsr calc_zone
lda en1
clc
adc #tongue_to_eggs
sta en1
lda pixel_to_byte,x
tay
lda (en1),y
and pixel_to_bit,x
beq aa35
lda eggs
ror
lda #1
bcc aa77
lda #6
aa77: sta effect0
dec eggs
lda #1
; Score 1 point for egg eaten
score_points:
clc
sed
adc score
sta score
aa48: lda score+1
adc #0
sta score+1
lda score+2
adc #0
sta score+2
cld
aa35:
rts
score_points_2:
sec
sed
bcs aa48
;
; Draw a tongue block
;
; a = zone (0-7)
; x = x pixel (0-39)
;
draw_block:
jsr calc_zone
lda pixel_to_byte,x
tay
lda (en1),y
ora pixel_to_bit,x
sta (en0),y
lda en0
clc
adc #tongue_to_eggs
sta en0
lda en1
adc #tongue_to_eggs
sta en1
lda (en1),y
ora pixel_to_bit,x
sta (en0),y
rts
;
; Clear a tongue block
;
; a = zone (0-7)
; x = x pixel (0-39)
;
clear_block:
jsr calc_zone
lda pixel_to_byte,x
tay
lda (en1),y
and pixel_to_bit2,x
sta (en0),y
lda en0
clc
adc #tongue_to_eggs
sta en0
lda en1
adc #tongue_to_eggs
sta en1
lda (en1),y
and pixel_to_bit2,x
sta (en0),y
rts
;
; Build random hole map for the current level seed
; See also random.c
;
build_hole_map: SUBROUTINE
.lastPat = tmpVars
lda #255
sta .lastPat
ldy #NUM_FLOORS-1
ldx level_seed
.0:
lda random_level,x
tax
and #$07
cmp .lastPat
bne .1
txa
lsr
lsr
tax
and #$07
.1:
sta kernelLst,y
sta .lastPat
dey
bne .0
sty kernelLst ; Fixed tunnel for queen ants
rts
;
; With the help of:
;
; http://alienbill.com/2600/basic/music/tune2600.html
; http://piano-player.info/
;
;
; Songs refer to these notes.
; These notes contain frequency and "instrument" and are
; choosen per usage in song instead of full "continuous" octaves
;
music_notes:
.byte 12,12 ; 1
.byte 4,28
.byte 4,25 ; 3
.byte 4,22
.byte 4,18 ; 5
.byte 4,16
.byte 12,20 ; 7
.byte 12,19
.byte 12,18 ; 9
.byte 12,17
.byte 12,15 ; 11
.byte 12,14
.byte 12,13 ; 13
.byte 12,11
.byte 4,31 ; 15
.byte 6,7 ; 16
.byte 6,6 ; 17
.byte 12,27 ; 18
.byte 12,23 ; 19
.byte 0,0 ; 20 Unused
.byte 6,7 ; 21
.byte 12,30
.byte 12,27 ; 23
.byte 12,24
.byte 12,20 ; 25
.byte 12,18
.byte 0,0 ; 27 Unused
.byte 1,12 ; 29
.byte 1,6 ; 31
.byte 1,13 ; 33
.byte 1,9 ; 35
.byte 0,0
;
; Global label to access music
;
music:
;
; Ranz des vaches
;
music_ranz_des_vaches:
.byte 6*32+2,22 ; 1 -> tracker
.byte 1*32+3,23
.byte 1*32+1,21
.byte 1*32+2,22
.byte 1*32+4,24
.byte 1*32+1,21
.byte 6*32+2,22
.byte 1*32+3,23
.byte 1*32+1,21
.byte 1*32+2,22
.byte 1*32+4,24
.byte 1*32+1,21
.byte 6*32+2,22
.byte 1*32+4,24
.byte 1*32+6,26
.byte 1*32+5,25
.byte 1*32+1,21
.byte 1*32+4,24
.byte 5*32+3,23
.byte 1*32+5,25
.byte 0,0
;
; Mountain king
;
music_mountain_king:
.byte 2*32+7,16 ; 43 -> tracker
.byte 2*32+9,16
.byte 2*32+10,18
.byte 2*32+11,18
.byte 2*32+13,16
.byte 2*32+10,16
.byte 4*32+13,18
.byte 2*32+12,16
.byte 2*32+9,16
.byte 4*32+12,18
.byte 2*32+11,16
.byte 2*32+8,16
.byte 4*32+11,18
.byte 2*32+7,16
.byte 2*32+9,16
.byte 2*32+10,18
.byte 2*32+11,18
.byte 2*32+13,16
.byte 2*32+10,16
.byte 2*32+13,18
.byte 2*32+15,18
.byte 2*32+14,17
.byte 2*32+13,17
.byte 2*32+10,19
.byte 2*32+13,19
.byte 7*32+14,17
.byte 0,0
;
; Death music
;
music_touch:
.byte 4*32+28,28 ; 97 -> tracker
.byte 4*32+29,29
.byte 4*32+30,30
.byte 7*32+31,31
.byte 0,0
;
; Global label to access sound effects
;
sound_effect:
.byte 0
.byte $04,$81 ; 1 Eating egg (1)
.byte $03,$71 ; 3
.byte 0 ; 5
.byte $08,$81 ; 6 Eating egg (2)
.byte $07,$71 ; 8
.byte 0 ; 10
.byte $07,$88 ; 11 Eating bug
.byte $06,$88 ; 13
.byte $07,$88 ; 15
.byte $06,$88 ; 17
.byte 0 ; 19
.byte $1c,$fc ; 20 Eating worm
.byte $1c,$cc ; 22
.byte $1c,$ac ; 24
.byte $1c,$8c ; 26
.byte $1c,$6c ; 28
.byte $1c,$4c ; 30
.byte 0 ; 32
.byte $1c,$fc ; 33 Eating queen
.byte $1c,$cc ; 35
.byte $1c,$ac ; 37
.byte $1c,$8c ; 39
.byte $1c,$6c ; 41
.byte $1c,$4c ; 43
.byte $10,$ec ; 45
.byte $10,$cc ; 47
.byte $10,$ac ; 49
.byte $10,$6c ; 51
.byte $10,$4c ; 53
.byte $10,$3c ; 55
.byte $10,$4c ; 57
.byte $10,$3c ; 59
.byte $10,$4c ; 61
.byte $10,$3c ; 63
.byte 0 ; 65
.byte $1f,$c4 ; 66 Retrain tongue
.byte $1e,$b4 ; 68
.byte $1d,$c4 ; 70
.byte $1c,$b4 ; 72
.byte $1b,$c4 ; 74
.byte $1a,$b4 ; 76
.byte $19,$c4 ; 78
.byte $18,$b4 ; 80
.byte $17,$c4 ; 82
.byte $16,$b4 ; 84
.byte $15,$c4 ; 86
.byte $14,$b4 ; 88
.byte $13,$c4 ; 90
.byte $12,$b4 ; 92
.byte $11,$c4 ; 94
.byte $10,$b4 ; 96
.byte $0f,$c4 ; 98
.byte $0e,$b4 ; 100
.byte $0d,$c4 ; 102
.byte $0c,$b4 ; 104
.byte $0b,$c4 ; 106
.byte $0a,$b4 ; 108
.byte $09,$c4 ; 110
.byte $08,$b4 ; 112
.byte $07,$c4 ; 114
.byte $06,$b4 ; 116
.byte $05,$c4 ; 118
.byte $04,$b4 ; 120
.byte $03,$c4 ; 122
.byte $02,$b4 ; 124
.byte $01,$c4 ; 126
.byte 0
.byte $18,$c1 ; 129 Click effect for sunset
.byte $0c,$61 ; 131
.byte $06,$a1 ; 133
.byte $03,$41 ; 135
.byte $02,$81 ; 137
.byte $01,$21 ; 139
.byte 0
echo "Before random_level at $fd00: ",*
org $fd00
.include "aardlev.asm"
org $fe00
fine_adjustment:
.byte $70 ; -7
.byte $60 ; -6
.byte $50 ; -5
.byte $40 ; -4
.byte $30 ; -3
.byte $20 ; -2
.byte $10 ; -1
.byte $00 ; 0
.byte $f0 ; +1
.byte $e0 ; +2
.byte $d0 ; +3
.byte $c0 ; +4
.byte $b0 ; +5
.byte $a0 ; +6
.byte $90 ; +7
pixel_to_byte:
.byte 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2
.byte 3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5
pixel_to_bit:
.byte $10,$20,$40,$80
.byte $80,$40,$20,$10,$08,$04,$02,$01
.byte $01,$02,$04,$08,$10,$20,$40,$80
.byte $10,$20,$40,$80
.byte $80,$40,$20,$10,$08,$04,$02,$01
.byte $01,$02,$04,$08,$10,$20,$40,$80
pixel_to_bit2:
.byte $ef,$df,$bf,$7f
.byte $7f,$bf,$df,$ef,$f7,$fb,$fd,$fe
.byte $fe,$fd,$fb,$f7,$ef,$df,$bf,$7f
.byte $ef,$df,$bf,$7f
.byte $7f,$bf,$df,$ef,$f7,$fb,$fd,$fe
.byte $fe,$fd,$fb,$f7,$ef,$df,$bf,$7f
;
; Position for holes (in "fat" pixels)
; Note vertical sorting, one line of holes is made from one column of data.
; A B C D E F G H
;
hole_pos:
.byte 0, 6, 3, 0, 0, 0, 0, 0
.byte 12,12, 9, 6, 9, 3, 0,15
.byte 26,18,20,26,23,15,18,23
.byte 0,32,35,32, 0,29,29,35
;
; Lives representation as playfield graphics
;
lives_pf:
.byte $00,$40,$40,$40,$40,$40,$40,$40
.byte $00,$00,$80,$a0,$a8,$aa,$aa,$aa
.byte $00,$00,$00,$00,$00,$00,$01,$05
;
; Refilling constant per level
;
refilling:
.byte 128,126,124,122,120,118,116,114
.byte 112,110,108,106,104,102,100,98
.byte 96,94,92,90,88,86,84,82
.byte 80,78,76,74,72,70,68,66
;
; Enemies per tunnel
;
enemies_going_right:
.byte 0
.byte 0
.byte sprite_caterpillar+ENEMY_DIR_MASK
.byte sprite_red_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte 0
.byte 0
.byte sprite_caterpillar+ENEMY_DIR_MASK
.byte sprite_red_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
.byte sprite_ant+ENEMY_DIR_MASK
enemies_going_left:
.byte 0
.byte 0
.byte sprite_caterpillar
.byte sprite_red_ant
.byte sprite_ant
.byte sprite_ant
.byte sprite_ant
.byte sprite_ant
.byte 0
.byte 0
.byte sprite_caterpillar
.byte sprite_red_ant
.byte sprite_ant
.byte sprite_ant
.byte sprite_ant
.byte sprite_ant
org $ff00
numbers:
.byte $fe,$c6,$c6,$c6,$fe,$00,$00,$00
.byte $78,$30,$30,$70,$30,$00,$00,$00
.byte $fe,$c0,$fe,$06,$fe,$00,$00,$00
.byte $fe,$06,$fe,$06,$fe,$00,$00,$00
.byte $06,$06,$fe,$c6,$c6,$00,$00,$00
.byte $fe,$06,$fe,$c0,$fe,$00,$00,$00
.byte $fe,$c6,$fe,$c0,$fe,$00,$00,$00
.byte $18,$18,$0c,$06,$fe,$00,$00,$00
.byte $fe,$c6,$fe,$c6,$fe,$00,$00,$00
.byte $fe,$06,$fe,$c6,$fe,$00,$00,$00
org $fffc
.word START ; RESET
.word START ; BRK