521 lines
8.2 KiB
NASM
521 lines
8.2 KiB
NASM
!cpu 6510
|
|
|
|
; PETSCII Aquarium
|
|
; F feeds the fish, 1-3 change speed, Q returns to BASIC.
|
|
; Self-starting BASIC line: 10 SYS2061
|
|
* = $0801
|
|
!word basic_end
|
|
!word 10
|
|
!byte $9e
|
|
!text "2061"
|
|
!byte 0
|
|
basic_end: !word 0
|
|
|
|
* = $080d
|
|
SCREEN = $0400
|
|
COLOR = $d800
|
|
GETIN = $ffe4
|
|
CHROUT = $ffd2
|
|
|
|
start:
|
|
lda $d020
|
|
sta old_border
|
|
lda $d021
|
|
sta old_background
|
|
lda #0
|
|
sta $d020
|
|
sta $d021
|
|
jsr show_splash
|
|
lda #14
|
|
sta $d020
|
|
lda #6
|
|
sta $d021
|
|
ldx #0
|
|
print_title:
|
|
lda runtime_title,x
|
|
beq initialize
|
|
jsr CHROUT
|
|
inx
|
|
bne print_title
|
|
|
|
show_splash:
|
|
ldx #0
|
|
print_splash:
|
|
lda splash_text,x
|
|
beq wait_for_space
|
|
jsr CHROUT
|
|
inx
|
|
bne print_splash
|
|
wait_for_space:
|
|
jsr GETIN
|
|
cmp #32
|
|
bne wait_for_space
|
|
lda #147
|
|
jsr CHROUT
|
|
rts
|
|
|
|
initialize:
|
|
lda #3
|
|
sta animation_speed
|
|
lda #0
|
|
sta tick
|
|
sta phase
|
|
sta food_active
|
|
lda $a2
|
|
sta last_jiffy
|
|
jsr draw_tank
|
|
jsr draw_all_fish
|
|
jsr draw_all_bubbles
|
|
|
|
main_loop:
|
|
jsr GETIN
|
|
beq check_clock
|
|
cmp #81
|
|
bne check_feed
|
|
jmp exit
|
|
check_feed:
|
|
cmp #70
|
|
bne check_speed_one
|
|
lda food_active
|
|
bne check_clock
|
|
lda #1
|
|
sta food_active
|
|
lda phase
|
|
asl
|
|
asl
|
|
clc
|
|
adc #7
|
|
cmp #36
|
|
bcc save_food_x
|
|
sbc #33
|
|
save_food_x:
|
|
sta food_x
|
|
lda #3
|
|
sta food_y
|
|
jmp check_clock
|
|
check_speed_one:
|
|
cmp #49
|
|
bne check_speed_two
|
|
lda #6
|
|
sta animation_speed
|
|
jmp check_clock
|
|
check_speed_two:
|
|
cmp #50
|
|
bne check_speed_three
|
|
lda #3
|
|
sta animation_speed
|
|
jmp check_clock
|
|
check_speed_three:
|
|
cmp #51
|
|
bne check_clock
|
|
lda #1
|
|
sta animation_speed
|
|
|
|
check_clock:
|
|
lda $a2
|
|
cmp last_jiffy
|
|
beq main_loop
|
|
sta last_jiffy
|
|
inc tick
|
|
lda tick
|
|
cmp animation_speed
|
|
bcc main_loop
|
|
lda #0
|
|
sta tick
|
|
jsr animate_frame
|
|
jmp main_loop
|
|
|
|
animate_frame:
|
|
jsr erase_all_fish
|
|
jsr erase_all_bubbles
|
|
jsr erase_food
|
|
inc phase
|
|
jsr move_fish
|
|
jsr move_bubbles
|
|
jsr move_food
|
|
jsr draw_all_fish
|
|
jsr draw_all_bubbles
|
|
jsr draw_food
|
|
rts
|
|
|
|
; Fish are two characters wide. Half move every frame and half every other
|
|
; frame, giving the tank a less mechanical look.
|
|
erase_all_fish:
|
|
ldx #0
|
|
erase_fish_loop:
|
|
stx object_index
|
|
jsr erase_one_fish
|
|
ldx object_index
|
|
inx
|
|
cpx #6
|
|
bne erase_fish_loop
|
|
rts
|
|
|
|
erase_one_fish:
|
|
lda fish_x,x
|
|
sta plot_x
|
|
lda fish_y,x
|
|
sta plot_y
|
|
lda #32
|
|
ldy #6
|
|
jsr plot_character
|
|
inc plot_x
|
|
lda #32
|
|
ldy #6
|
|
jsr plot_character
|
|
rts
|
|
|
|
move_fish:
|
|
ldx #0
|
|
move_fish_loop:
|
|
stx object_index
|
|
txa
|
|
eor phase
|
|
and #1
|
|
bne next_fish
|
|
lda fish_direction,x
|
|
bmi move_fish_left
|
|
move_fish_right:
|
|
inc fish_x,x
|
|
lda fish_x,x
|
|
cmp #37
|
|
bcc next_fish
|
|
lda #36
|
|
sta fish_x,x
|
|
lda #$ff
|
|
sta fish_direction,x
|
|
jmp next_fish
|
|
move_fish_left:
|
|
dec fish_x,x
|
|
lda fish_x,x
|
|
cmp #2
|
|
bcs next_fish
|
|
lda #2
|
|
sta fish_x,x
|
|
lda #1
|
|
sta fish_direction,x
|
|
next_fish:
|
|
ldx object_index
|
|
inx
|
|
cpx #6
|
|
bne move_fish_loop
|
|
rts
|
|
|
|
draw_all_fish:
|
|
ldx #0
|
|
draw_fish_loop:
|
|
stx object_index
|
|
lda fish_x,x
|
|
sta plot_x
|
|
lda fish_y,x
|
|
sta plot_y
|
|
ldy fish_color,x
|
|
lda fish_direction,x
|
|
bmi draw_left_fish
|
|
lda #62
|
|
jsr plot_character
|
|
inc plot_x
|
|
lda #41
|
|
ldy fish_color,x
|
|
jsr plot_character
|
|
jmp fish_drawn
|
|
draw_left_fish:
|
|
lda #40
|
|
jsr plot_character
|
|
inc plot_x
|
|
lda #60
|
|
ldy fish_color,x
|
|
jsr plot_character
|
|
fish_drawn:
|
|
ldx object_index
|
|
inx
|
|
cpx #6
|
|
bne draw_fish_loop
|
|
rts
|
|
|
|
erase_all_bubbles:
|
|
ldx #0
|
|
erase_bubble_loop:
|
|
stx object_index
|
|
lda bubble_x,x
|
|
sta plot_x
|
|
lda bubble_y,x
|
|
sta plot_y
|
|
lda #32
|
|
ldy #6
|
|
jsr plot_character
|
|
ldx object_index
|
|
inx
|
|
cpx #5
|
|
bne erase_bubble_loop
|
|
rts
|
|
|
|
move_bubbles:
|
|
lda phase
|
|
and #1
|
|
bne bubbles_done
|
|
ldx #0
|
|
move_bubble_loop:
|
|
dec bubble_y,x
|
|
lda bubble_y,x
|
|
cmp #3
|
|
bcs next_bubble
|
|
lda #21
|
|
sta bubble_y,x
|
|
lda bubble_x,x
|
|
clc
|
|
adc #11
|
|
cmp #37
|
|
bcc store_bubble_x
|
|
sbc #34
|
|
store_bubble_x:
|
|
sta bubble_x,x
|
|
next_bubble:
|
|
inx
|
|
cpx #5
|
|
bne move_bubble_loop
|
|
bubbles_done:
|
|
rts
|
|
|
|
draw_all_bubbles:
|
|
ldx #0
|
|
draw_bubble_loop:
|
|
stx object_index
|
|
lda bubble_x,x
|
|
sta plot_x
|
|
lda bubble_y,x
|
|
sta plot_y
|
|
lda phase
|
|
and #2
|
|
beq small_bubble
|
|
lda #81
|
|
bne paint_bubble
|
|
small_bubble:
|
|
lda #46
|
|
paint_bubble:
|
|
ldy #3
|
|
jsr plot_character
|
|
ldx object_index
|
|
inx
|
|
cpx #5
|
|
bne draw_bubble_loop
|
|
rts
|
|
|
|
erase_food:
|
|
lda food_active
|
|
beq erase_food_done
|
|
lda food_x
|
|
sta plot_x
|
|
lda food_y
|
|
sta plot_y
|
|
lda #32
|
|
ldy #6
|
|
jsr plot_character
|
|
erase_food_done:
|
|
rts
|
|
|
|
move_food:
|
|
lda food_active
|
|
beq move_food_done
|
|
inc food_y
|
|
lda food_y
|
|
cmp #22
|
|
bcc move_food_done
|
|
lda #0
|
|
sta food_active
|
|
move_food_done:
|
|
rts
|
|
|
|
draw_food:
|
|
lda food_active
|
|
beq draw_food_done
|
|
lda food_x
|
|
sta plot_x
|
|
lda food_y
|
|
sta plot_y
|
|
lda #46
|
|
ldy #8
|
|
jsr plot_character
|
|
draw_food_done:
|
|
rts
|
|
|
|
draw_tank:
|
|
; Top and bottom glass.
|
|
ldx #0
|
|
horizontal_glass:
|
|
stx plot_x
|
|
lda #2
|
|
sta plot_y
|
|
lda #160
|
|
ldy #3
|
|
jsr plot_character
|
|
lda #23
|
|
sta plot_y
|
|
lda #160
|
|
ldy #3
|
|
jsr plot_character
|
|
inx
|
|
cpx #40
|
|
bne horizontal_glass
|
|
|
|
; Side glass.
|
|
ldx #3
|
|
vertical_glass:
|
|
stx plot_y
|
|
lda #0
|
|
sta plot_x
|
|
lda #160
|
|
ldy #3
|
|
jsr plot_character
|
|
lda #39
|
|
sta plot_x
|
|
lda #160
|
|
ldy #3
|
|
jsr plot_character
|
|
inx
|
|
cpx #23
|
|
bne vertical_glass
|
|
|
|
; Sandy floor.
|
|
ldx #1
|
|
sand_loop:
|
|
stx plot_x
|
|
lda #22
|
|
sta plot_y
|
|
txa
|
|
and #1
|
|
beq sand_dot
|
|
lda #58
|
|
bne sand_plot
|
|
sand_dot:
|
|
lda #46
|
|
sand_plot:
|
|
ldy #7
|
|
jsr plot_character
|
|
inx
|
|
cpx #39
|
|
bne sand_loop
|
|
|
|
; Five clusters of seaweed.
|
|
ldx #0
|
|
plant_loop:
|
|
stx object_index
|
|
lda plant_x,x
|
|
sta plot_x
|
|
lda #21
|
|
sta plot_y
|
|
lda #93
|
|
ldy #5
|
|
jsr plot_character
|
|
dec plot_y
|
|
lda #94
|
|
ldy #5
|
|
jsr plot_character
|
|
dec plot_y
|
|
lda #93
|
|
ldy #5
|
|
jsr plot_character
|
|
ldx object_index
|
|
inx
|
|
cpx #5
|
|
bne plant_loop
|
|
rts
|
|
|
|
; A = screen code, X/Y are supplied through plot_x/plot_y, Y = color.
|
|
plot_character:
|
|
sta character
|
|
sty character_color
|
|
ldy plot_y
|
|
lda screen_row_lo,y
|
|
sta $fb
|
|
lda screen_row_hi,y
|
|
sta $fc
|
|
ldy plot_x
|
|
lda character
|
|
sta ($fb),y
|
|
; Color RAM uses the same row/column layout as screen RAM.
|
|
ldy plot_y
|
|
lda color_row_lo_table,y
|
|
sta $fd
|
|
lda color_row_hi_table,y
|
|
sta $fe
|
|
lda character_color
|
|
ldy plot_x
|
|
sta ($fd),y
|
|
rts
|
|
|
|
exit:
|
|
lda old_border
|
|
sta $d020
|
|
lda old_background
|
|
sta $d021
|
|
lda #147
|
|
jsr CHROUT
|
|
rts
|
|
|
|
splash_text:
|
|
!byte 147,13,13,13
|
|
!byte 154
|
|
!text " PETSCII AQUARIUM"
|
|
!byte 13,13
|
|
!byte 5
|
|
!text " A LIVELY WORLD OF FISH AND BUBBLES"
|
|
!byte 13,13,13
|
|
!byte 153
|
|
!text " CONTROLS"
|
|
!byte 13,13
|
|
!text " "
|
|
!byte 158
|
|
!text "F"
|
|
!byte 5
|
|
!text " FEEDS "
|
|
!byte 158
|
|
!text "1-3"
|
|
!byte 5
|
|
!text " SPEED "
|
|
!byte 158
|
|
!text "Q"
|
|
!byte 5
|
|
!text " QUITS"
|
|
!byte 13,13,13
|
|
!byte 5
|
|
!text " HTTPS://C64.P20.DEV"
|
|
!byte 13,13
|
|
!byte 152
|
|
!text " RELEASED 16 OCTOBER 2026"
|
|
!byte 13,13,13
|
|
!byte 158
|
|
!text " PRESS SPACE TO START"
|
|
!byte 0
|
|
|
|
runtime_title: !byte 147,154
|
|
!text " PETSCII AQUARIUM"
|
|
!byte 0
|
|
|
|
fish_x: !byte 4,28,12,33,7,23
|
|
fish_y: !byte 5,8,11,14,17,20
|
|
fish_direction: !byte 1,$ff,1,$ff,1,$ff
|
|
fish_color: !byte 7,10,8,13,2,15
|
|
bubble_x: !byte 6,14,21,29,35
|
|
bubble_y: !byte 18,12,20,8,16
|
|
plant_x: !byte 5,12,20,28,35
|
|
|
|
screen_row_lo: !for i,0,24 { !byte <(SCREEN+i*40) }
|
|
screen_row_hi: !for i,0,24 { !byte >(SCREEN+i*40) }
|
|
color_row_lo_table: !for i,0,24 { !byte <(COLOR+i*40) }
|
|
color_row_hi_table: !for i,0,24 { !byte >(COLOR+i*40) }
|
|
|
|
animation_speed: !byte 0
|
|
tick: !byte 0
|
|
phase: !byte 0
|
|
last_jiffy: !byte 0
|
|
food_active: !byte 0
|
|
food_x: !byte 0
|
|
food_y: !byte 0
|
|
plot_x: !byte 0
|
|
plot_y: !byte 0
|
|
character: !byte 0
|
|
character_color: !byte 0
|
|
object_index: !byte 0
|
|
old_border: !byte 0
|
|
old_background: !byte 0
|