From bca0ea2a9ccb37204cb6969b33ae2c497965a0d8 Mon Sep 17 00:00:00 2001 From: Christian Johannesen Date: Fri, 16 Oct 2026 02:33:51 +0200 Subject: [PATCH] Rebuild PETSCII Aquarium --- petscii-aquarium/petscii-aquarium.asm | 489 +++++++++++++++++++++----- petscii-aquarium/petscii-aquarium.prg | Bin 415 -> 1026 bytes 2 files changed, 398 insertions(+), 91 deletions(-) diff --git a/petscii-aquarium/petscii-aquarium.asm b/petscii-aquarium/petscii-aquarium.asm index 71faa4d..8e92920 100644 --- a/petscii-aquarium/petscii-aquarium.asm +++ b/petscii-aquarium/petscii-aquarium.asm @@ -1,4 +1,8 @@ !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 @@ -8,154 +12,457 @@ 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 #6 - sta $d020 lda #14 + sta $d020 + lda #6 sta $d021 lda #147 - jsr $ffd2 + jsr CHROUT ldx #0 -title_loop: +print_title: lda title,x - beq setup - jsr $ffd2 + beq initialize + jsr CHROUT inx - bne title_loop -setup: - lda #4 - sta speed + bne print_title + +initialize: + lda #3 + sta animation_speed lda #0 sta tick - sta food_y -main: - jsr wait_frame - jsr $ffe4 + 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 not_quit + bne check_feed jmp exit -not_quit: +check_feed: cmp #70 - bne speed_keys - lda #3 + 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 #2 + lda #3 sta food_y -speed_keys: + jmp check_clock +check_speed_one: cmp #49 - bne speed_two - lda #7 - sta speed -speed_two: + bne check_speed_two + lda #6 + sta animation_speed + jmp check_clock +check_speed_two: cmp #50 - bne speed_three - lda #4 - sta speed -speed_three: + bne check_speed_three + lda #3 + sta animation_speed + jmp check_clock +check_speed_three: cmp #51 - bne animate - lda #2 - sta speed -animate: + 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 speed - bcc main + 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 -fish_loop: - stx fish_index +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 old_x - ldy fish_y,x - ldx old_x + sta plot_x + lda fish_y,x + sta plot_y lda #32 - jsr plot - ldx fish_index + 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 #39 - bcc draw_fish - lda #0 + cmp #37 + bcc next_fish + lda #36 sta fish_x,x -draw_fish: - sta old_x - ldy fish_y,x - ldx old_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 - ldx fish_index + 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 fish_loop + 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 - bne move_food - jmp main -move_food: - ldx food_x - ldy food_y + sta plot_y lda #32 - jsr plot + 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 draw_food + bcc move_food_done lda #0 - sta food_y - jmp main + sta food_active +move_food_done: + rts + draw_food: - tay - ldx food_x + lda food_active + beq draw_food_done + lda food_x + sta plot_x + lda food_y + sta plot_y lda #46 - jsr plot - jmp main -plot: - sta char_value - lda row_lo,y - sta $fb - lda row_hi,y - sta $fc + 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 - tay - lda char_value + 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 -wait_frame: - lda #250 -wait_raster: - cmp $d012 - bne wait_raster -wait_leave: - cmp $d012 - beq wait_leave - rts + exit: lda old_border sta $d020 lda old_background sta $d021 lda #147 - jsr $ffd2 + jsr CHROUT rts title: !byte 147 !text "PETSCII AQUARIUM F FEED 1-3 SPEED Q QUIT" -!byte 13,0 -fish_x: !byte 2,9,16,23,30 -fish_y: !byte 5,9,13,17,20 -row_lo: !for i,0,24 { !byte <($0400+i*40) } -row_hi: !for i,0,24 { !byte >($0400+i*40) } -speed: !byte 0 +!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 -fish_index: !byte 0 -old_x: !byte 0 -char_value: !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 diff --git a/petscii-aquarium/petscii-aquarium.prg b/petscii-aquarium/petscii-aquarium.prg index c50d9cc1fb6361fc2b2c1dc11aa006c641f89d0d..4b4cb66c2d06e9c6afa0547449f31db733483ae9 100644 GIT binary patch literal 1026 zcmZ`&QAkr!7{0snZg=-zTDdt1gR@k056M*Mp`wyf987Yl5Ja)w=1cV8L-e$ly-3$4 zKG@4*3?vVD!^eac`BZzb4!u-HGAd%ejM1E%PPhJZ@0Nq=KQABO`Ty_x&N&>D46-6T z9q^v(7X(2gOs#_EW~yMP%_?EkqPiJfARnp;A$b9E7DO3Vpk_4>R8V(7Er42trG&Z* z3>p8#$$93qYJUvTh@T z^*EzSFd@uUfE4BD709G5>{l=u0(Bpf_dqQJC2(uXf-wi{u{O}gBDj6DstL{bj>4as5BbAd=|AhB;jyi-isoe;Jnkc>deyy~FN7~(LrPxHj$_L*21k1esUf2;9n zG1o)`Or(8rGlr-Me+=TYeAob`>C>>g)RZBYqdp$Pxz?u*MP$1U+AkRSSiEWV~CX3mLYPmf(Jc-`7$ThA#%9336YA1P5Ur^ z7}TnOA3_uC^&b&j7$2UTxa#wfp}^G84d2ulAtPjDc=#G2{bvWs#JCOvBrxTh6q-8h zZmUa@q4|WvROQR6$j8JMOSAKI=SjOmJ}%iE9i2k&_=EV{T>F(!^hH|s-V86Z5*fY! eY5Qf(~FYX%?Q4z&PHicLSVsdC{VPR!snMMNs4Iv<;5mrt@lFOGusw}wI z2MjhgTLcz=frUk?kVXVgjFY5si{W9OeP>{9_@i4~;LAM89&(4rS;m+aR<@usR<@xM zQdqSjGgg(w+oZ$#`xqyPhW1k}$_f;dRmcz`1@SR47uG%BhB>oI<;ohAL&{{WrW$6h%X-1@tdEv&0gRs*8cBL=6?9@ z*;gHc_Mh^ohNo~I9fhE-*$g<%4?(g^Rvl1^ST@nS!fq+